NFC: mei_phy: move all nfc logic from mei driver to nfc
authorTomas Winkler <tomas.winkler@intel.com>
Thu, 7 May 2015 12:54:04 +0000 (15:54 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 24 May 2015 18:15:54 +0000 (11:15 -0700)
move nfc logic to mei_phy module, we prefer as much as
possible not to deal with a particualr client protocol
in the mei generic infrasutcutre

Cc: Samuel Ortiz <sameo@linux.intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/misc/mei/bus.c
drivers/misc/mei/mei_dev.h
drivers/misc/mei/nfc.c
drivers/nfc/mei_phy.c
drivers/nfc/mei_phy.h

index e76d94aa6e12e00f794c1b993f7a9dce76365e48..de8fd089a8a41df3bc3163c81a5b40093e70e94b 100644 (file)
@@ -220,8 +220,7 @@ struct mei_cl *mei_cl_bus_find_cl_by_uuid(struct mei_device *dev,
 struct mei_cl_device *mei_cl_add_device(struct mei_device *dev,
                                        struct mei_me_client *me_cl,
                                        struct mei_cl *cl,
-                                       char *name,
-                                       struct mei_cl_ops *ops)
+                                       char *name)
 {
        struct mei_cl_device *device;
        int status;
@@ -235,9 +234,8 @@ struct mei_cl_device *mei_cl_add_device(struct mei_device *dev,
                kfree(device);
                return NULL;
        }
-       device->cl = cl;
-       device->ops = ops;
 
+       device->cl = cl;
        device->dev.parent = dev->dev;
        device->dev.bus = &mei_cl_bus_type;
        device->dev.type = &mei_cl_device_type;
@@ -294,7 +292,7 @@ void mei_cl_driver_unregister(struct mei_cl_driver *driver)
 }
 EXPORT_SYMBOL_GPL(mei_cl_driver_unregister);
 
-static ssize_t ___mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
+ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
                        bool blocking)
 {
        struct mei_device *dev;
@@ -408,16 +406,6 @@ out:
        return rets;
 }
 
-inline ssize_t __mei_cl_async_send(struct mei_cl *cl, u8 *buf, size_t length)
-{
-       return ___mei_cl_send(cl, buf, length, 0);
-}
-
-inline ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length)
-{
-       return ___mei_cl_send(cl, buf, length, 1);
-}
-
 ssize_t mei_cl_send(struct mei_cl_device *device, u8 *buf, size_t length)
 {
        struct mei_cl *cl = device->cl;
@@ -425,23 +413,17 @@ ssize_t mei_cl_send(struct mei_cl_device *device, u8 *buf, size_t length)
        if (cl == NULL)
                return -ENODEV;
 
-       if (device->ops && device->ops->send)
-               return device->ops->send(device, buf, length);
-
-       return __mei_cl_send(cl, buf, length);
+       return __mei_cl_send(cl, buf, length, 1);
 }
 EXPORT_SYMBOL_GPL(mei_cl_send);
 
 ssize_t mei_cl_recv(struct mei_cl_device *device, u8 *buf, size_t length)
 {
-       struct mei_cl *cl =  device->cl;
+       struct mei_cl *cl = device->cl;
 
        if (cl == NULL)
                return -ENODEV;
 
-       if (device->ops && device->ops->recv)
-               return device->ops->recv(device, buf, length);
-
        return __mei_cl_recv(cl, buf, length);
 }
 EXPORT_SYMBOL_GPL(mei_cl_recv);
@@ -522,10 +504,7 @@ int mei_cl_enable_device(struct mei_cl_device *device)
        if (device->event_cb)
                mei_cl_read_start(device->cl, 0, NULL);
 
-       if (!device->ops || !device->ops->enable)
-               return 0;
-
-       return device->ops->enable(device);
+       return 0;
 }
 EXPORT_SYMBOL_GPL(mei_cl_enable_device);
 
@@ -540,9 +519,6 @@ int mei_cl_disable_device(struct mei_cl_device *device)
 
        dev = cl->dev;
 
-       if (device->ops && device->ops->disable)
-               device->ops->disable(device);
-
        device->event_cb = NULL;
 
        mutex_lock(&dev->device_lock);
index ab719e674edfc8f91e8e17d540d7bf5dccb03f08..2175bff2730f5ff870b8741d270f9fa32c4e309e 100644 (file)
@@ -352,12 +352,11 @@ struct mei_cl_ops {
 struct mei_cl_device *mei_cl_add_device(struct mei_device *dev,
                                        struct mei_me_client *me_cl,
                                        struct mei_cl *cl,
-                                       char *name,
-                                       struct mei_cl_ops *ops);
+                                       char *name);
 void mei_cl_remove_device(struct mei_cl_device *device);
 
-ssize_t __mei_cl_async_send(struct mei_cl *cl, u8 *buf, size_t length);
-ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length);
+ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
+                       bool blocking);
 ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length);
 void mei_cl_bus_rx_event(struct mei_cl *cl);
 void mei_cl_bus_remove_devices(struct mei_device *dev);
index e2a6ba0236c8591ee7280485986bf3125079787e..b983c4ecad3800d34e21a453e034ed15d84574f4 100644 (file)
@@ -95,28 +95,21 @@ struct mei_nfc_hci_hdr {
  * @cl: NFC host client
  * @cl_info: NFC info host client
  * @init_work: perform connection to the info client
- * @send_wq: send completion wait queue
  * @fw_ivn: NFC Interface Version Number
  * @vendor_id: NFC manufacturer ID
  * @radio_type: NFC radio type
  * @bus_name: bus name
  *
- * @req_id:  message counter
- * @recv_req_id: reception message counter
  */
 struct mei_nfc_dev {
        struct mei_me_client *me_cl;
        struct mei_cl *cl;
        struct mei_cl *cl_info;
        struct work_struct init_work;
-       wait_queue_head_t send_wq;
        u8 fw_ivn;
        u8 vendor_id;
        u8 radio_type;
        char *bus_name;
-
-       u16 req_id;
-       u16 recv_req_id;
 };
 
 /* UUIDs for NFC F/W clients */
@@ -202,73 +195,6 @@ static int mei_nfc_build_bus_name(struct mei_nfc_dev *ndev)
        return 0;
 }
 
-static int mei_nfc_connect(struct mei_nfc_dev *ndev)
-{
-       struct mei_device *dev;
-       struct mei_cl *cl;
-       struct mei_nfc_cmd *cmd, *reply;
-       struct mei_nfc_connect *connect;
-       struct mei_nfc_connect_resp *connect_resp;
-       size_t connect_length, connect_resp_length;
-       int bytes_recv, ret;
-
-       cl = ndev->cl;
-       dev = cl->dev;
-
-       connect_length = sizeof(struct mei_nfc_cmd) +
-                       sizeof(struct mei_nfc_connect);
-
-       connect_resp_length = sizeof(struct mei_nfc_cmd) +
-                       sizeof(struct mei_nfc_connect_resp);
-
-       cmd = kzalloc(connect_length, GFP_KERNEL);
-       if (!cmd)
-               return -ENOMEM;
-       connect = (struct mei_nfc_connect *)cmd->data;
-
-       reply = kzalloc(connect_resp_length, GFP_KERNEL);
-       if (!reply) {
-               kfree(cmd);
-               return -ENOMEM;
-       }
-
-       connect_resp = (struct mei_nfc_connect_resp *)reply->data;
-
-       cmd->command = MEI_NFC_CMD_MAINTENANCE;
-       cmd->data_size = 3;
-       cmd->sub_command = MEI_NFC_SUBCMD_CONNECT;
-       connect->fw_ivn = ndev->fw_ivn;
-       connect->vendor_id = ndev->vendor_id;
-
-       ret = __mei_cl_send(cl, (u8 *)cmd, connect_length);
-       if (ret < 0) {
-               dev_err(dev->dev, "Could not send connect cmd\n");
-               goto err;
-       }
-
-       bytes_recv = __mei_cl_recv(cl, (u8 *)reply, connect_resp_length);
-       if (bytes_recv < 0) {
-               dev_err(dev->dev, "Could not read connect response\n");
-               ret = bytes_recv;
-               goto err;
-       }
-
-       dev_info(dev->dev, "IVN 0x%x Vendor ID 0x%x\n",
-                connect_resp->fw_ivn, connect_resp->vendor_id);
-
-       dev_info(dev->dev, "ME FW %d.%d.%d.%d\n",
-               connect_resp->me_major, connect_resp->me_minor,
-               connect_resp->me_hotfix, connect_resp->me_build);
-
-       ret = 0;
-
-err:
-       kfree(reply);
-       kfree(cmd);
-
-       return ret;
-}
-
 static int mei_nfc_if_version(struct mei_nfc_dev *ndev)
 {
        struct mei_device *dev;
@@ -288,7 +214,7 @@ static int mei_nfc_if_version(struct mei_nfc_dev *ndev)
        cmd.data_size = 1;
        cmd.sub_command = MEI_NFC_SUBCMD_IF_VERSION;
 
-       ret = __mei_cl_send(cl, (u8 *)&cmd, sizeof(struct mei_nfc_cmd));
+       ret = __mei_cl_send(cl, (u8 *)&cmd, sizeof(struct mei_nfc_cmd), 1);
        if (ret < 0) {
                dev_err(dev->dev, "Could not send IF version cmd\n");
                return ret;
@@ -320,100 +246,6 @@ err:
        return ret;
 }
 
-static int mei_nfc_enable(struct mei_cl_device *cldev)
-{
-       struct mei_device *dev;
-       struct mei_nfc_dev *ndev;
-       int ret;
-
-       ndev = (struct mei_nfc_dev *)cldev->priv_data;
-       dev = ndev->cl->dev;
-
-       ret = mei_nfc_connect(ndev);
-       if (ret < 0) {
-               dev_err(dev->dev, "Could not connect to NFC");
-               return ret;
-       }
-
-       return 0;
-}
-
-static int mei_nfc_disable(struct mei_cl_device *cldev)
-{
-       return 0;
-}
-
-static int mei_nfc_send(struct mei_cl_device *cldev, u8 *buf, size_t length)
-{
-       struct mei_device *dev;
-       struct mei_nfc_dev *ndev;
-       struct mei_nfc_hci_hdr *hdr;
-       u8 *mei_buf;
-       int err;
-
-       ndev = (struct mei_nfc_dev *) cldev->priv_data;
-       dev = ndev->cl->dev;
-
-       err = -ENOMEM;
-       mei_buf = kzalloc(length + MEI_NFC_HEADER_SIZE, GFP_KERNEL);
-       if (!mei_buf)
-               goto out;
-
-       hdr = (struct mei_nfc_hci_hdr *) mei_buf;
-       hdr->cmd = MEI_NFC_CMD_HCI_SEND;
-       hdr->status = 0;
-       hdr->req_id = ndev->req_id;
-       hdr->reserved = 0;
-       hdr->data_size = length;
-
-       memcpy(mei_buf + MEI_NFC_HEADER_SIZE, buf, length);
-       err = __mei_cl_send(ndev->cl, mei_buf, length + MEI_NFC_HEADER_SIZE);
-       if (err < 0)
-               goto out;
-
-       if (!wait_event_interruptible_timeout(ndev->send_wq,
-                               ndev->recv_req_id == ndev->req_id, HZ)) {
-               dev_err(dev->dev, "NFC MEI command timeout\n");
-               err = -ETIME;
-       } else {
-               ndev->req_id++;
-       }
-out:
-       kfree(mei_buf);
-       return err;
-}
-
-static int mei_nfc_recv(struct mei_cl_device *cldev, u8 *buf, size_t length)
-{
-       struct mei_nfc_dev *ndev;
-       struct mei_nfc_hci_hdr *hci_hdr;
-       int received_length;
-
-       ndev = (struct mei_nfc_dev *)cldev->priv_data;
-
-       received_length = __mei_cl_recv(ndev->cl, buf, length);
-       if (received_length < 0)
-               return received_length;
-
-       hci_hdr = (struct mei_nfc_hci_hdr *) buf;
-
-       if (hci_hdr->cmd == MEI_NFC_CMD_HCI_SEND) {
-               ndev->recv_req_id = hci_hdr->req_id;
-               wake_up(&ndev->send_wq);
-
-               return 0;
-       }
-
-       return received_length;
-}
-
-static struct mei_cl_ops nfc_ops = {
-       .enable = mei_nfc_enable,
-       .disable = mei_nfc_disable,
-       .send = mei_nfc_send,
-       .recv = mei_nfc_recv,
-};
-
 static void mei_nfc_init(struct work_struct *work)
 {
        struct mei_device *dev;
@@ -473,7 +305,7 @@ static void mei_nfc_init(struct work_struct *work)
        }
 
        cldev = mei_cl_add_device(dev, ndev->me_cl, ndev->cl,
-                                 ndev->bus_name, &nfc_ops);
+                                 ndev->bus_name);
        if (!cldev) {
                dev_err(dev->dev, "Could not add the NFC device to the MEI bus\n");
 
@@ -539,10 +371,7 @@ int mei_nfc_host_init(struct mei_device *dev, struct mei_me_client *me_cl)
 
        ndev->cl = cl;
 
-       ndev->req_id = 1;
-
        INIT_WORK(&ndev->init_work, mei_nfc_init);
-       init_waitqueue_head(&ndev->send_wq);
        schedule_work(&ndev->init_work);
 
        return 0;
index 11c7cbdade6663fe73e680a853df9908d1e18286..7f1495d649bb0da49c40a5d3b6015d934bece4ea 100644 (file)
 
 #include "mei_phy.h"
 
-struct mei_nfc_hdr {
+struct mei_nfc_cmd {
+       u8 command;
+       u8 status;
+       u16 req_id;
+       u32 reserved;
+       u16 data_size;
+       u8 sub_command;
+       u8 data[];
+} __packed;
+
+struct mei_nfc_reply {
+       u8 command;
+       u8 status;
+       u16 req_id;
+       u32 reserved;
+       u16 data_size;
+       u8 sub_command;
+       u8 reply_status;
+       u8 data[];
+} __packed;
+
+struct mei_nfc_if_version {
+       u8 radio_version_sw[3];
+       u8 reserved[3];
+       u8 radio_version_hw[3];
+       u8 i2c_addr;
+       u8 fw_ivn;
+       u8 vendor_id;
+       u8 radio_type;
+} __packed;
+
+struct mei_nfc_connect {
+       u8 fw_ivn;
+       u8 vendor_id;
+} __packed;
+
+struct mei_nfc_connect_resp {
+       u8 fw_ivn;
+       u8 vendor_id;
+       u16 me_major;
+       u16 me_minor;
+       u16 me_hotfix;
+       u16 me_build;
+} __packed;
+
+struct mei_nfc_hci_hdr {
        u8 cmd;
        u8 status;
        u16 req_id;
@@ -32,6 +77,16 @@ struct mei_nfc_hdr {
        u16 data_size;
 } __packed;
 
+#define MEI_NFC_CMD_MAINTENANCE 0x00
+#define MEI_NFC_CMD_HCI_SEND 0x01
+#define MEI_NFC_CMD_HCI_RECV 0x02
+
+#define MEI_NFC_SUBCMD_CONNECT    0x00
+#define MEI_NFC_SUBCMD_IF_VERSION 0x01
+
+#define MEI_NFC_HEADER_SIZE 10
+
+
 #define MEI_NFC_MAX_READ (MEI_NFC_HEADER_SIZE + MEI_NFC_MAX_HCI_PAYLOAD)
 
 #define MEI_DUMP_SKB_IN(info, skb)                             \
@@ -45,51 +100,156 @@ do {                                                              \
 do {                                                           \
        pr_debug("%s:\n", info);                                \
        print_hex_dump_debug("mei out: ", DUMP_PREFIX_OFFSET,   \
-                      16, 1, (skb)->data, (skb)->len, false);  \
+                       16, 1, (skb)->data, (skb)->len, false); \
 } while (0)
 
-int nfc_mei_phy_enable(void *phy_id)
+
+static int mei_nfc_if_version(struct nfc_mei_phy *phy)
 {
-       int r;
-       struct nfc_mei_phy *phy = phy_id;
+
+       struct mei_nfc_cmd cmd;
+       struct mei_nfc_reply *reply = NULL;
+       struct mei_nfc_if_version *version;
+       size_t if_version_length;
+       int bytes_recv, r;
 
        pr_info("%s\n", __func__);
 
-       if (phy->powered == 1)
-               return 0;
+       memset(&cmd, 0, sizeof(struct mei_nfc_cmd));
+       cmd.command = MEI_NFC_CMD_MAINTENANCE;
+       cmd.data_size = 1;
+       cmd.sub_command = MEI_NFC_SUBCMD_IF_VERSION;
 
-       r = mei_cl_enable_device(phy->device);
+       r = mei_cl_send(phy->device, (u8 *)&cmd, sizeof(struct mei_nfc_cmd));
        if (r < 0) {
-               pr_err("Could not enable device\n");
+               pr_err("Could not send IF version cmd\n");
                return r;
        }
 
-       r = mei_cl_register_event_cb(phy->device, nfc_mei_event_cb, phy);
-       if (r) {
-               pr_err("Event cb registration failed\n");
-               mei_cl_disable_device(phy->device);
-               phy->powered = 0;
+       /* to be sure on the stack we alloc memory */
+       if_version_length = sizeof(struct mei_nfc_reply) +
+               sizeof(struct mei_nfc_if_version);
 
-               return r;
+       reply = kzalloc(if_version_length, GFP_KERNEL);
+       if (!reply)
+               return -ENOMEM;
+
+       bytes_recv = mei_cl_recv(phy->device, (u8 *)reply, if_version_length);
+       if (bytes_recv < 0 || bytes_recv < sizeof(struct mei_nfc_reply)) {
+               pr_err("Could not read IF version\n");
+               r = -EIO;
+               goto err;
        }
 
-       phy->powered = 1;
+       version = (struct mei_nfc_if_version *)reply->data;
 
-       return 0;
+       phy->fw_ivn = version->fw_ivn;
+       phy->vendor_id = version->vendor_id;
+       phy->radio_type = version->radio_type;
+
+err:
+       kfree(reply);
+       return r;
 }
-EXPORT_SYMBOL_GPL(nfc_mei_phy_enable);
 
-void nfc_mei_phy_disable(void *phy_id)
+static int mei_nfc_connect(struct nfc_mei_phy *phy)
 {
-       struct nfc_mei_phy *phy = phy_id;
+       struct mei_nfc_cmd *cmd, *reply;
+       struct mei_nfc_connect *connect;
+       struct mei_nfc_connect_resp *connect_resp;
+       size_t connect_length, connect_resp_length;
+       int bytes_recv, r;
 
        pr_info("%s\n", __func__);
 
-       mei_cl_disable_device(phy->device);
+       connect_length = sizeof(struct mei_nfc_cmd) +
+                       sizeof(struct mei_nfc_connect);
 
-       phy->powered = 0;
+       connect_resp_length = sizeof(struct mei_nfc_cmd) +
+                       sizeof(struct mei_nfc_connect_resp);
+
+       cmd = kzalloc(connect_length, GFP_KERNEL);
+       if (!cmd)
+               return -ENOMEM;
+       connect = (struct mei_nfc_connect *)cmd->data;
+
+       reply = kzalloc(connect_resp_length, GFP_KERNEL);
+       if (!reply) {
+               kfree(cmd);
+               return -ENOMEM;
+       }
+
+       connect_resp = (struct mei_nfc_connect_resp *)reply->data;
+
+       cmd->command = MEI_NFC_CMD_MAINTENANCE;
+       cmd->data_size = 3;
+       cmd->sub_command = MEI_NFC_SUBCMD_CONNECT;
+       connect->fw_ivn = phy->fw_ivn;
+       connect->vendor_id = phy->vendor_id;
+
+       r = mei_cl_send(phy->device, (u8 *)cmd, connect_length);
+       if (r < 0) {
+               pr_err("Could not send connect cmd %d\n", r);
+               goto err;
+       }
+
+       bytes_recv = mei_cl_recv(phy->device, (u8 *)reply, connect_resp_length);
+       if (bytes_recv < 0) {
+               r = bytes_recv;
+               pr_err("Could not read connect response %d\n", r);
+               goto err;
+       }
+
+       pr_info("IVN 0x%x Vendor ID 0x%x\n",
+                connect_resp->fw_ivn, connect_resp->vendor_id);
+
+       pr_info("ME FW %d.%d.%d.%d\n",
+               connect_resp->me_major, connect_resp->me_minor,
+               connect_resp->me_hotfix, connect_resp->me_build);
+
+       r = 0;
+
+err:
+       kfree(reply);
+       kfree(cmd);
+
+       return r;
+}
+
+static int mei_nfc_send(struct nfc_mei_phy *phy, u8 *buf, size_t length)
+{
+       struct mei_nfc_hci_hdr *hdr;
+       u8 *mei_buf;
+       int err;
+
+       err = -ENOMEM;
+       mei_buf = kzalloc(length + MEI_NFC_HEADER_SIZE, GFP_KERNEL);
+       if (!mei_buf)
+               goto out;
+
+       hdr = (struct mei_nfc_hci_hdr *) mei_buf;
+       hdr->cmd = MEI_NFC_CMD_HCI_SEND;
+       hdr->status = 0;
+       hdr->req_id = phy->req_id;
+       hdr->reserved = 0;
+       hdr->data_size = length;
+
+       memcpy(mei_buf + MEI_NFC_HEADER_SIZE, buf, length);
+       err = mei_cl_send(phy->device, mei_buf, length + MEI_NFC_HEADER_SIZE);
+       if (err < 0)
+               goto out;
+
+       if (!wait_event_interruptible_timeout(phy->send_wq,
+                               phy->recv_req_id == phy->req_id, HZ)) {
+               pr_err("NFC MEI command timeout\n");
+               err = -ETIME;
+       } else {
+               phy->req_id++;
+       }
+out:
+       kfree(mei_buf);
+       return err;
 }
-EXPORT_SYMBOL_GPL(nfc_mei_phy_disable);
 
 /*
  * Writing a frame must not return the number of written bytes.
@@ -103,14 +263,37 @@ static int nfc_mei_phy_write(void *phy_id, struct sk_buff *skb)
 
        MEI_DUMP_SKB_OUT("mei frame sent", skb);
 
-       r = mei_cl_send(phy->device, skb->data, skb->len);
+       r = mei_nfc_send(phy, skb->data, skb->len);
        if (r > 0)
                r = 0;
 
        return r;
 }
 
-void nfc_mei_event_cb(struct mei_cl_device *device, u32 events, void *context)
+static int mei_nfc_recv(struct nfc_mei_phy *phy, u8 *buf, size_t length)
+{
+       struct mei_nfc_hci_hdr *hci_hdr;
+       int received_length;
+
+       received_length = mei_cl_recv(phy->device, buf, length);
+       if (received_length < 0)
+               return received_length;
+
+       hci_hdr = (struct mei_nfc_hci_hdr *) buf;
+
+       if (hci_hdr->cmd == MEI_NFC_CMD_HCI_SEND) {
+               phy->recv_req_id = hci_hdr->req_id;
+               wake_up(&phy->send_wq);
+
+               return 0;
+       }
+
+       return received_length;
+}
+
+
+static void nfc_mei_event_cb(struct mei_cl_device *device, u32 events,
+                            void *context)
 {
        struct nfc_mei_phy *phy = context;
 
@@ -125,7 +308,7 @@ void nfc_mei_event_cb(struct mei_cl_device *device, u32 events, void *context)
                if (!skb)
                        return;
 
-               reply_size = mei_cl_recv(device, skb->data, MEI_NFC_MAX_READ);
+               reply_size = mei_nfc_recv(phy, skb->data, MEI_NFC_MAX_READ);
                if (reply_size < MEI_NFC_HEADER_SIZE) {
                        kfree_skb(skb);
                        return;
@@ -139,7 +322,61 @@ void nfc_mei_event_cb(struct mei_cl_device *device, u32 events, void *context)
                nfc_hci_recv_frame(phy->hdev, skb);
        }
 }
-EXPORT_SYMBOL_GPL(nfc_mei_event_cb);
+
+static int nfc_mei_phy_enable(void *phy_id)
+{
+       int r;
+       struct nfc_mei_phy *phy = phy_id;
+
+       pr_info("%s\n", __func__);
+
+       if (phy->powered == 1)
+               return 0;
+
+       r = mei_cl_enable_device(phy->device);
+       if (r < 0) {
+               pr_err("Could not enable device %d\n", r);
+               return r;
+       }
+
+       r = mei_nfc_if_version(phy);
+       if (r < 0) {
+               pr_err("Could not enable device %d\n", r);
+               goto err;
+       }
+
+       r = mei_nfc_connect(phy);
+       if (r < 0) {
+               pr_err("Could not connect to device %d\n", r);
+               goto err;
+       }
+
+       r = mei_cl_register_event_cb(phy->device, nfc_mei_event_cb, phy);
+       if (r) {
+               pr_err("Event cb registration failed %d\n", r);
+               goto err;
+       }
+
+       phy->powered = 1;
+
+       return 0;
+
+err:
+       phy->powered = 0;
+       mei_cl_disable_device(phy->device);
+       return r;
+}
+
+static void nfc_mei_phy_disable(void *phy_id)
+{
+       struct nfc_mei_phy *phy = phy_id;
+
+       pr_info("%s\n", __func__);
+
+       mei_cl_disable_device(phy->device);
+
+       phy->powered = 0;
+}
 
 struct nfc_phy_ops mei_phy_ops = {
        .write = nfc_mei_phy_write,
@@ -157,6 +394,7 @@ struct nfc_mei_phy *nfc_mei_phy_alloc(struct mei_cl_device *device)
                return NULL;
 
        phy->device = device;
+       init_waitqueue_head(&phy->send_wq);
        mei_cl_set_drvdata(device, phy);
 
        return phy;
@@ -165,6 +403,7 @@ EXPORT_SYMBOL_GPL(nfc_mei_phy_alloc);
 
 void nfc_mei_phy_free(struct nfc_mei_phy *phy)
 {
+       mei_cl_disable_device(phy->device);
        kfree(phy);
 }
 EXPORT_SYMBOL_GPL(nfc_mei_phy_free);
index 06608c28ff14ba38ce292c8361fa0952e996a091..a51f8f2685cc9e385077fe6a73ef0b11f2a86e43 100644 (file)
 #define MEI_NFC_HEADER_SIZE 10
 #define MEI_NFC_MAX_HCI_PAYLOAD 300
 
+/**
+ * struct nfc_mei_phy
+ *
+ * @device: mei device
+ * @hdev:   nfc hci device
+
+ * @send_wq: send completion wait queue
+ * @fw_ivn: NFC Interface Version Number
+ * @vendor_id: NFC manufacturer ID
+ * @radio_type: NFC radio type
+ * @reserved: reserved for alignment
+ * @req_id:  message counter
+ * @recv_req_id: reception message counter
+ * @powered: the device is in powered state
+ * @hard_fault: < 0 if hardware error occurred
+ *    and prevents normal operation.
+ */
 struct nfc_mei_phy {
        struct mei_cl_device *device;
        struct nfc_hci_dev *hdev;
 
-       int powered;
+       wait_queue_head_t send_wq;
+       u8 fw_ivn;
+       u8 vendor_id;
+       u8 radio_type;
+       u8 reserved;
+
+       u16 req_id;
+       u16 recv_req_id;
 
-       int hard_fault;         /*
-                                * < 0 if hardware error occured
-                                * and prevents normal operation.
-                                */
+       int powered;
+       int hard_fault;
 };
 
 extern struct nfc_phy_ops mei_phy_ops;
 
-int nfc_mei_phy_enable(void *phy_id);
-void nfc_mei_phy_disable(void *phy_id);
-void nfc_mei_event_cb(struct mei_cl_device *device, u32 events, void *context);
 struct nfc_mei_phy *nfc_mei_phy_alloc(struct mei_cl_device *device);
 void nfc_mei_phy_free(struct nfc_mei_phy *phy);