]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
Merge tag 'net-next-qcom-soc-4.7-2-merge' of git://github.com/andersson/kernel
authorDavid S. Miller <davem@davemloft.net>
Tue, 17 May 2016 18:11:19 +0000 (14:11 -0400)
committerDavid S. Miller <davem@davemloft.net>
Tue, 17 May 2016 18:11:19 +0000 (14:11 -0400)
Merge tag 'qcom-soc-for-4.7-2' into net-next

This merges the Qualcomm SOC tree with the net-next, solving the
merge conflict in the SMD API between the two.

MAINTAINERS
drivers/soc/qcom/smd-rpm.c
drivers/soc/qcom/smd.c
drivers/soc/qcom/smem.c
drivers/soc/qcom/spm.c
drivers/soc/qcom/wcnss_ctrl.c
include/linux/soc/qcom/smd.h
include/linux/soc/qcom/smem_state.h
net/qrtr/smd.c

index 458304bfe2d5c91a1979720c8945d4f32e3d057e..452aa2b9c6e5ac3e388c6f55c98d3237e607d0c4 100644 (file)
@@ -1470,7 +1470,10 @@ F:       arch/arm/boot/dts/qcom-*.dts
 F:     arch/arm/boot/dts/qcom-*.dtsi
 F:     arch/arm/mach-qcom/
 F:     arch/arm64/boot/dts/qcom/*
+F:     drivers/i2c/busses/i2c-qup.c
+F:     drivers/clk/qcom/
 F:     drivers/soc/qcom/
+F:     drivers/spi/spi-qup.c
 F:     drivers/tty/serial/msm_serial.h
 F:     drivers/tty/serial/msm_serial.c
 F:     drivers/*/pm8???-*
index 731fa066f712ebdd9a66135c773e6e7ce619c75d..6609d7e0edb045c3f26e159ee8938037de397dd2 100644 (file)
@@ -33,6 +33,7 @@
  */
 struct qcom_smd_rpm {
        struct qcom_smd_channel *rpm_channel;
+       struct device *dev;
 
        struct completion ack;
        struct mutex lock;
@@ -149,14 +150,14 @@ out:
 }
 EXPORT_SYMBOL(qcom_rpm_smd_write);
 
-static int qcom_smd_rpm_callback(struct qcom_smd_device *qsdev,
+static int qcom_smd_rpm_callback(struct qcom_smd_channel *channel,
                                 const void *data,
                                 size_t count)
 {
        const struct qcom_rpm_header *hdr = data;
        size_t hdr_length = le32_to_cpu(hdr->length);
        const struct qcom_rpm_message *msg;
-       struct qcom_smd_rpm *rpm = dev_get_drvdata(&qsdev->dev);
+       struct qcom_smd_rpm *rpm = qcom_smd_get_drvdata(channel);
        const u8 *buf = data + sizeof(struct qcom_rpm_header);
        const u8 *end = buf + hdr_length;
        char msgbuf[32];
@@ -165,7 +166,7 @@ static int qcom_smd_rpm_callback(struct qcom_smd_device *qsdev,
 
        if (le32_to_cpu(hdr->service_type) != RPM_SERVICE_TYPE_REQUEST ||
            hdr_length < sizeof(struct qcom_rpm_message)) {
-               dev_err(&qsdev->dev, "invalid request\n");
+               dev_err(rpm->dev, "invalid request\n");
                return 0;
        }
 
@@ -206,7 +207,9 @@ static int qcom_smd_rpm_probe(struct qcom_smd_device *sdev)
        mutex_init(&rpm->lock);
        init_completion(&rpm->ack);
 
+       rpm->dev = &sdev->dev;
        rpm->rpm_channel = sdev->channel;
+       qcom_smd_set_drvdata(sdev->channel, rpm);
 
        dev_set_drvdata(&sdev->dev, rpm);
 
index 498fd0581a451999b89cbb43805b37f003fdb379..ac1957dfdf24f313c5daaee942d62374a63fb0cf 100644 (file)
@@ -106,9 +106,9 @@ static const struct {
  * @channels:          list of all channels detected on this edge
  * @channels_lock:     guard for modifications of @channels
  * @allocated:         array of bitmaps representing already allocated channels
- * @need_rescan:       flag that the @work needs to scan smem for new channels
  * @smem_available:    last available amount of smem triggering a channel scan
- * @work:              work item for edge house keeping
+ * @scan_work:         work item for discovering new channels
+ * @state_work:                work item for edge state changes
  */
 struct qcom_smd_edge {
        struct qcom_smd *smd;
@@ -127,10 +127,12 @@ struct qcom_smd_edge {
 
        DECLARE_BITMAP(allocated[SMD_ALLOC_TBL_COUNT], SMD_ALLOC_TBL_SIZE);
 
-       bool need_rescan;
        unsigned smem_available;
 
-       struct work_struct work;
+       wait_queue_head_t new_channel_event;
+
+       struct work_struct scan_work;
+       struct work_struct state_work;
 };
 
 /*
@@ -186,13 +188,16 @@ struct qcom_smd_channel {
        int fifo_size;
 
        void *bounce_buffer;
-       int (*cb)(struct qcom_smd_device *, const void *, size_t);
+       qcom_smd_cb_t cb;
 
        spinlock_t recv_lock;
 
        int pkt_size;
 
+       void *drvdata;
+
        struct list_head list;
+       struct list_head dev_list;
 };
 
 /**
@@ -377,6 +382,19 @@ static void qcom_smd_channel_reset(struct qcom_smd_channel *channel)
        channel->pkt_size = 0;
 }
 
+/*
+ * Set the callback for a channel, with appropriate locking
+ */
+static void qcom_smd_channel_set_callback(struct qcom_smd_channel *channel,
+                                         qcom_smd_cb_t cb)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&channel->recv_lock, flags);
+       channel->cb = cb;
+       spin_unlock_irqrestore(&channel->recv_lock, flags);
+};
+
 /*
  * Calculate the amount of data available in the rx fifo
  */
@@ -497,7 +515,6 @@ static void qcom_smd_channel_advance(struct qcom_smd_channel *channel,
  */
 static int qcom_smd_channel_recv_single(struct qcom_smd_channel *channel)
 {
-       struct qcom_smd_device *qsdev = channel->qsdev;
        unsigned tail;
        size_t len;
        void *ptr;
@@ -517,7 +534,7 @@ static int qcom_smd_channel_recv_single(struct qcom_smd_channel *channel)
                len = channel->pkt_size;
        }
 
-       ret = channel->cb(qsdev, ptr, len);
+       ret = channel->cb(channel, ptr, len);
        if (ret < 0)
                return ret;
 
@@ -601,7 +618,8 @@ static irqreturn_t qcom_smd_edge_intr(int irq, void *data)
        struct qcom_smd_edge *edge = data;
        struct qcom_smd_channel *channel;
        unsigned available;
-       bool kick_worker = false;
+       bool kick_scanner = false;
+       bool kick_state = false;
 
        /*
         * Handle state changes or data on each of the channels on this edge
@@ -609,7 +627,7 @@ static irqreturn_t qcom_smd_edge_intr(int irq, void *data)
        spin_lock(&edge->channels_lock);
        list_for_each_entry(channel, &edge->channels, list) {
                spin_lock(&channel->recv_lock);
-               kick_worker |= qcom_smd_channel_intr(channel);
+               kick_state |= qcom_smd_channel_intr(channel);
                spin_unlock(&channel->recv_lock);
        }
        spin_unlock(&edge->channels_lock);
@@ -622,12 +640,13 @@ static irqreturn_t qcom_smd_edge_intr(int irq, void *data)
        available = qcom_smem_get_free_space(edge->remote_pid);
        if (available != edge->smem_available) {
                edge->smem_available = available;
-               edge->need_rescan = true;
-               kick_worker = true;
+               kick_scanner = true;
        }
 
-       if (kick_worker)
-               schedule_work(&edge->work);
+       if (kick_scanner)
+               schedule_work(&edge->scan_work);
+       if (kick_state)
+               schedule_work(&edge->state_work);
 
        return IRQ_HANDLED;
 }
@@ -793,18 +812,12 @@ static int qcom_smd_dev_match(struct device *dev, struct device_driver *drv)
 }
 
 /*
- * Probe the smd client.
- *
- * The remote side have indicated that it want the channel to be opened, so
- * complete the state handshake and probe our client driver.
+ * Helper for opening a channel
  */
-static int qcom_smd_dev_probe(struct device *dev)
+static int qcom_smd_channel_open(struct qcom_smd_channel *channel,
+                                qcom_smd_cb_t cb)
 {
-       struct qcom_smd_device *qsdev = to_smd_device(dev);
-       struct qcom_smd_driver *qsdrv = to_smd_driver(dev);
-       struct qcom_smd_channel *channel = qsdev->channel;
        size_t bb_size;
-       int ret;
 
        /*
         * Packets are maximum 4k, but reduce if the fifo is smaller
@@ -814,12 +827,44 @@ static int qcom_smd_dev_probe(struct device *dev)
        if (!channel->bounce_buffer)
                return -ENOMEM;
 
-       channel->cb = qsdrv->callback;
-
+       qcom_smd_channel_set_callback(channel, cb);
        qcom_smd_channel_set_state(channel, SMD_CHANNEL_OPENING);
-
        qcom_smd_channel_set_state(channel, SMD_CHANNEL_OPENED);
 
+       return 0;
+}
+
+/*
+ * Helper for closing and resetting a channel
+ */
+static void qcom_smd_channel_close(struct qcom_smd_channel *channel)
+{
+       qcom_smd_channel_set_callback(channel, NULL);
+
+       kfree(channel->bounce_buffer);
+       channel->bounce_buffer = NULL;
+
+       qcom_smd_channel_set_state(channel, SMD_CHANNEL_CLOSED);
+       qcom_smd_channel_reset(channel);
+}
+
+/*
+ * Probe the smd client.
+ *
+ * The remote side have indicated that it want the channel to be opened, so
+ * complete the state handshake and probe our client driver.
+ */
+static int qcom_smd_dev_probe(struct device *dev)
+{
+       struct qcom_smd_device *qsdev = to_smd_device(dev);
+       struct qcom_smd_driver *qsdrv = to_smd_driver(dev);
+       struct qcom_smd_channel *channel = qsdev->channel;
+       int ret;
+
+       ret = qcom_smd_channel_open(channel, qsdrv->callback);
+       if (ret)
+               return ret;
+
        ret = qsdrv->probe(qsdev);
        if (ret)
                goto err;
@@ -831,11 +876,7 @@ static int qcom_smd_dev_probe(struct device *dev)
 err:
        dev_err(&qsdev->dev, "probe failed\n");
 
-       channel->cb = NULL;
-       kfree(channel->bounce_buffer);
-       channel->bounce_buffer = NULL;
-
-       qcom_smd_channel_set_state(channel, SMD_CHANNEL_CLOSED);
+       qcom_smd_channel_close(channel);
        return ret;
 }
 
@@ -850,16 +891,15 @@ static int qcom_smd_dev_remove(struct device *dev)
        struct qcom_smd_device *qsdev = to_smd_device(dev);
        struct qcom_smd_driver *qsdrv = to_smd_driver(dev);
        struct qcom_smd_channel *channel = qsdev->channel;
-       unsigned long flags;
+       struct qcom_smd_channel *tmp;
+       struct qcom_smd_channel *ch;
 
        qcom_smd_channel_set_state(channel, SMD_CHANNEL_CLOSING);
 
        /*
         * Make sure we don't race with the code receiving data.
         */
-       spin_lock_irqsave(&channel->recv_lock, flags);
-       channel->cb = NULL;
-       spin_unlock_irqrestore(&channel->recv_lock, flags);
+       qcom_smd_channel_set_callback(channel, NULL);
 
        /* Wake up any sleepers in qcom_smd_send() */
        wake_up_interruptible(&channel->fblockread_event);
@@ -872,15 +912,14 @@ static int qcom_smd_dev_remove(struct device *dev)
                qsdrv->remove(qsdev);
 
        /*
-        * The client is now gone, cleanup and reset the channel state.
+        * The client is now gone, close and release all channels associated
+        * with this sdev
         */
-       channel->qsdev = NULL;
-       kfree(channel->bounce_buffer);
-       channel->bounce_buffer = NULL;
-
-       qcom_smd_channel_set_state(channel, SMD_CHANNEL_CLOSED);
-
-       qcom_smd_channel_reset(channel);
+       list_for_each_entry_safe(ch, tmp, &channel->dev_list, dev_list) {
+               qcom_smd_channel_close(ch);
+               list_del(&ch->dev_list);
+               ch->qsdev = NULL;
+       }
 
        return 0;
 }
@@ -996,6 +1035,18 @@ int qcom_smd_driver_register(struct qcom_smd_driver *qsdrv)
 }
 EXPORT_SYMBOL(qcom_smd_driver_register);
 
+void *qcom_smd_get_drvdata(struct qcom_smd_channel *channel)
+{
+       return channel->drvdata;
+}
+EXPORT_SYMBOL(qcom_smd_get_drvdata);
+
+void qcom_smd_set_drvdata(struct qcom_smd_channel *channel, void *data)
+{
+       channel->drvdata = data;
+}
+EXPORT_SYMBOL(qcom_smd_set_drvdata);
+
 /**
  * qcom_smd_driver_unregister - unregister a smd driver
  * @qsdrv:     qcom_smd_driver struct
@@ -1006,6 +1057,78 @@ void qcom_smd_driver_unregister(struct qcom_smd_driver *qsdrv)
 }
 EXPORT_SYMBOL(qcom_smd_driver_unregister);
 
+static struct qcom_smd_channel *
+qcom_smd_find_channel(struct qcom_smd_edge *edge, const char *name)
+{
+       struct qcom_smd_channel *channel;
+       struct qcom_smd_channel *ret = NULL;
+       unsigned long flags;
+       unsigned state;
+
+       spin_lock_irqsave(&edge->channels_lock, flags);
+       list_for_each_entry(channel, &edge->channels, list) {
+               if (strcmp(channel->name, name))
+                       continue;
+
+               state = GET_RX_CHANNEL_INFO(channel, state);
+               if (state != SMD_CHANNEL_OPENING &&
+                   state != SMD_CHANNEL_OPENED)
+                       continue;
+
+               ret = channel;
+               break;
+       }
+       spin_unlock_irqrestore(&edge->channels_lock, flags);
+
+       return ret;
+}
+
+/**
+ * qcom_smd_open_channel() - claim additional channels on the same edge
+ * @sdev:      smd_device handle
+ * @name:      channel name
+ * @cb:                callback method to use for incoming data
+ *
+ * Returns a channel handle on success, or -EPROBE_DEFER if the channel isn't
+ * ready.
+ */
+struct qcom_smd_channel *qcom_smd_open_channel(struct qcom_smd_channel *parent,
+                                              const char *name,
+                                              qcom_smd_cb_t cb)
+{
+       struct qcom_smd_channel *channel;
+       struct qcom_smd_device *sdev = parent->qsdev;
+       struct qcom_smd_edge *edge = parent->edge;
+       int ret;
+
+       /* Wait up to HZ for the channel to appear */
+       ret = wait_event_interruptible_timeout(edge->new_channel_event,
+                       (channel = qcom_smd_find_channel(edge, name)) != NULL,
+                       HZ);
+       if (!ret)
+               return ERR_PTR(-ETIMEDOUT);
+
+       if (channel->state != SMD_CHANNEL_CLOSED) {
+               dev_err(&sdev->dev, "channel %s is busy\n", channel->name);
+               return ERR_PTR(-EBUSY);
+       }
+
+       channel->qsdev = sdev;
+       ret = qcom_smd_channel_open(channel, cb);
+       if (ret) {
+               channel->qsdev = NULL;
+               return ERR_PTR(ret);
+       }
+
+       /*
+        * Append the list of channel to the channels associated with the sdev
+        */
+       list_add_tail(&channel->dev_list, &sdev->channel->dev_list);
+
+       return channel;
+}
+EXPORT_SYMBOL(qcom_smd_open_channel);
+
 /*
  * Allocate the qcom_smd_channel object for a newly found smd channel,
  * retrieving and validating the smem items involved.
@@ -1027,6 +1150,7 @@ static struct qcom_smd_channel *qcom_smd_create_channel(struct qcom_smd_edge *ed
        if (!channel)
                return ERR_PTR(-ENOMEM);
 
+       INIT_LIST_HEAD(&channel->dev_list);
        channel->edge = edge;
        channel->name = devm_kstrdup(smd->dev, name, GFP_KERNEL);
        if (!channel->name)
@@ -1089,8 +1213,9 @@ free_name_and_channel:
  * qcom_smd_create_channel() to create representations of these and add
  * them to the edge's list of channels.
  */
-static void qcom_discover_channels(struct qcom_smd_edge *edge)
+static void qcom_channel_scan_worker(struct work_struct *work)
 {
+       struct qcom_smd_edge *edge = container_of(work, struct qcom_smd_edge, scan_work);
        struct qcom_smd_alloc_entry *alloc_tbl;
        struct qcom_smd_alloc_entry *entry;
        struct qcom_smd_channel *channel;
@@ -1140,10 +1265,12 @@ static void qcom_discover_channels(struct qcom_smd_edge *edge)
 
                        dev_dbg(smd->dev, "new channel found: '%s'\n", channel->name);
                        set_bit(i, edge->allocated[tbl]);
+
+                       wake_up_interruptible(&edge->new_channel_event);
                }
        }
 
-       schedule_work(&edge->work);
+       schedule_work(&edge->state_work);
 }
 
 /*
@@ -1151,29 +1278,23 @@ static void qcom_discover_channels(struct qcom_smd_edge *edge)
  * then scans all registered channels for state changes that should be handled
  * by creating or destroying smd client devices for the registered channels.
  *
- * LOCKING: edge->channels_lock is not needed to be held during the traversal
- * of the channels list as it's done synchronously with the only writer.
+ * LOCKING: edge->channels_lock only needs to cover the list operations, as the
+ * worker is killed before any channels are deallocated
  */
 static void qcom_channel_state_worker(struct work_struct *work)
 {
        struct qcom_smd_channel *channel;
        struct qcom_smd_edge *edge = container_of(work,
                                                  struct qcom_smd_edge,
-                                                 work);
+                                                 state_work);
        unsigned remote_state;
-
-       /*
-        * Rescan smem if we have reason to belive that there are new channels.
-        */
-       if (edge->need_rescan) {
-               edge->need_rescan = false;
-               qcom_discover_channels(edge);
-       }
+       unsigned long flags;
 
        /*
         * Register a device for any closed channel where the remote processor
         * is showing interest in opening the channel.
         */
+       spin_lock_irqsave(&edge->channels_lock, flags);
        list_for_each_entry(channel, &edge->channels, list) {
                if (channel->state != SMD_CHANNEL_CLOSED)
                        continue;
@@ -1183,7 +1304,9 @@ static void qcom_channel_state_worker(struct work_struct *work)
                    remote_state != SMD_CHANNEL_OPENED)
                        continue;
 
+               spin_unlock_irqrestore(&edge->channels_lock, flags);
                qcom_smd_create_device(channel);
+               spin_lock_irqsave(&edge->channels_lock, flags);
        }
 
        /*
@@ -1200,8 +1323,11 @@ static void qcom_channel_state_worker(struct work_struct *work)
                    remote_state == SMD_CHANNEL_OPENED)
                        continue;
 
+               spin_unlock_irqrestore(&edge->channels_lock, flags);
                qcom_smd_destroy_device(channel);
+               spin_lock_irqsave(&edge->channels_lock, flags);
        }
+       spin_unlock_irqrestore(&edge->channels_lock, flags);
 }
 
 /*
@@ -1219,7 +1345,8 @@ static int qcom_smd_parse_edge(struct device *dev,
        INIT_LIST_HEAD(&edge->channels);
        spin_lock_init(&edge->channels_lock);
 
-       INIT_WORK(&edge->work, qcom_channel_state_worker);
+       INIT_WORK(&edge->scan_work, qcom_channel_scan_worker);
+       INIT_WORK(&edge->state_work, qcom_channel_state_worker);
 
        edge->of_node = of_node_get(node);
 
@@ -1303,13 +1430,13 @@ static int qcom_smd_probe(struct platform_device *pdev)
        for_each_available_child_of_node(pdev->dev.of_node, node) {
                edge = &smd->edges[i++];
                edge->smd = smd;
+               init_waitqueue_head(&edge->new_channel_event);
 
                ret = qcom_smd_parse_edge(&pdev->dev, node, edge);
                if (ret)
                        continue;
 
-               edge->need_rescan = true;
-               schedule_work(&edge->work);
+               schedule_work(&edge->scan_work);
        }
 
        platform_set_drvdata(pdev, smd);
@@ -1332,8 +1459,10 @@ static int qcom_smd_remove(struct platform_device *pdev)
                edge = &smd->edges[i];
 
                disable_irq(edge->irq);
-               cancel_work_sync(&edge->work);
+               cancel_work_sync(&edge->scan_work);
+               cancel_work_sync(&edge->state_work);
 
+               /* No need to lock here, because the writer is gone */
                list_for_each_entry(channel, &edge->channels, list) {
                        if (!channel->qsdev)
                                continue;
index 19019aa092e86d76ad5a24b80f34616b9e38e320..2e1aa9f130f4d860ea7c57994ba3f1302c2e7072 100644 (file)
@@ -684,8 +684,7 @@ static int qcom_smem_map_memory(struct qcom_smem *smem, struct device *dev,
 
        smem->regions[i].aux_base = (u32)r.start;
        smem->regions[i].size = resource_size(&r);
-       smem->regions[i].virt_base = devm_ioremap_nocache(dev, r.start,
-                                                         resource_size(&r));
+       smem->regions[i].virt_base = devm_ioremap_wc(dev, r.start, resource_size(&r));
        if (!smem->regions[i].virt_base)
                return -ENOMEM;
 
index 5548a31e1a39a100142b45841cbe38e1aa007e38..f324451e0940eeadd10e3d76af56c727e30c6de6 100644 (file)
@@ -2,6 +2,8 @@
  * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
  * Copyright (c) 2014,2015, Linaro Ltd.
  *
+ * SAW power controller driver
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
  * only version 2 as published by the Free Software Foundation.
@@ -12,7 +14,6 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
@@ -378,8 +379,5 @@ static struct platform_driver spm_driver = {
                .of_match_table = spm_match_table,
        },
 };
-module_platform_driver(spm_driver);
 
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("SAW power controller driver");
-MODULE_ALIAS("platform:saw");
+builtin_platform_driver(spm_driver);
index 7a986f881d5c860df19614c4ca781bce69d2d296..c544f3d2c6eecc26f12658fedb00871adcdf0d15 100644 (file)
@@ -100,17 +100,17 @@ struct wcnss_download_nv_resp {
 
 /**
  * wcnss_ctrl_smd_callback() - handler from SMD responses
- * @qsdev:     smd device handle
+ * @channel:   smd channel handle
  * @data:      pointer to the incoming data packet
  * @count:     size of the incoming data packet
  *
  * Handles any incoming packets from the remote WCNSS_CTRL service.
  */
-static int wcnss_ctrl_smd_callback(struct qcom_smd_device *qsdev,
+static int wcnss_ctrl_smd_callback(struct qcom_smd_channel *channel,
                                   const void *data,
                                   size_t count)
 {
-       struct wcnss_ctrl *wcnss = dev_get_drvdata(&qsdev->dev);
+       struct wcnss_ctrl *wcnss = qcom_smd_get_drvdata(channel);
        const struct wcnss_download_nv_resp *nvresp;
        const struct wcnss_version_resp *version;
        const struct wcnss_msg_hdr *hdr = data;
@@ -246,7 +246,7 @@ static int wcnss_ctrl_probe(struct qcom_smd_device *sdev)
        init_completion(&wcnss->ack);
        INIT_WORK(&wcnss->download_nv_work, wcnss_download_nv);
 
-       dev_set_drvdata(&sdev->dev, wcnss);
+       qcom_smd_set_drvdata(sdev->channel, wcnss);
 
        return wcnss_request_version(wcnss);
 }
index 46a984f5e3a3ae9fd38cab4a7b5fc142420bc385..cbb0f06c41b21866385882d85e6954d70b77b1a4 100644 (file)
@@ -26,6 +26,8 @@ struct qcom_smd_device {
        struct qcom_smd_channel *channel;
 };
 
+typedef int (*qcom_smd_cb_t)(struct qcom_smd_channel *, const void *, size_t);
+
 /**
  * struct qcom_smd_driver - smd driver struct
  * @driver:    underlying device driver
@@ -42,7 +44,7 @@ struct qcom_smd_driver {
 
        int (*probe)(struct qcom_smd_device *dev);
        void (*remove)(struct qcom_smd_device *dev);
-       int (*callback)(struct qcom_smd_device *, const void *, size_t);
+       qcom_smd_cb_t callback;
 };
 
 #if IS_ENABLED(CONFIG_QCOM_SMD)
@@ -50,8 +52,14 @@ struct qcom_smd_driver {
 int qcom_smd_driver_register(struct qcom_smd_driver *drv);
 void qcom_smd_driver_unregister(struct qcom_smd_driver *drv);
 
+struct qcom_smd_channel *qcom_smd_open_channel(struct qcom_smd_channel *channel,
+                                              const char *name,
+                                              qcom_smd_cb_t cb);
+void *qcom_smd_get_drvdata(struct qcom_smd_channel *channel);
+void qcom_smd_set_drvdata(struct qcom_smd_channel *channel, void *data);
 int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len);
 
+
 #else
 
 static inline int qcom_smd_driver_register(struct qcom_smd_driver *drv)
@@ -65,6 +73,29 @@ static inline void qcom_smd_driver_unregister(struct qcom_smd_driver *drv)
        WARN_ON(1);
 }
 
+static inline struct qcom_smd_channel *
+qcom_smd_open_channel(struct qcom_smd_channel *channel,
+                     const char *name,
+                     qcom_smd_cb_t cb)
+{
+       /* This shouldn't be possible */
+       WARN_ON(1);
+       return NULL;
+}
+
+void *qcom_smd_get_drvdata(struct qcom_smd_channel *channel)
+{
+       /* This shouldn't be possible */
+       WARN_ON(1);
+       return NULL;
+}
+
+void qcom_smd_set_drvdata(struct qcom_smd_channel *channel, void *data)
+{
+       /* This shouldn't be possible */
+       WARN_ON(1);
+}
+
 static inline int qcom_smd_send(struct qcom_smd_channel *channel,
                                const void *data, int len)
 {
index f35e1512fcaa1bb723da9f5825a2bc8406071fca..7b88697929e9ef6f729ce9fd1d9e512d352f8b94 100644 (file)
@@ -1,12 +1,17 @@
 #ifndef __QCOM_SMEM_STATE__
 #define __QCOM_SMEM_STATE__
 
+#include <linux/errno.h>
+
+struct device_node;
 struct qcom_smem_state;
 
 struct qcom_smem_state_ops {
        int (*update_bits)(void *, u32, u32);
 };
 
+#ifdef CONFIG_QCOM_SMEM_STATE
+
 struct qcom_smem_state *qcom_smem_state_get(struct device *dev, const char *con_id, unsigned *bit);
 void qcom_smem_state_put(struct qcom_smem_state *);
 
@@ -15,4 +20,34 @@ int qcom_smem_state_update_bits(struct qcom_smem_state *state, u32 mask, u32 val
 struct qcom_smem_state *qcom_smem_state_register(struct device_node *of_node, const struct qcom_smem_state_ops *ops, void *data);
 void qcom_smem_state_unregister(struct qcom_smem_state *state);
 
+#else
+
+static inline struct qcom_smem_state *qcom_smem_state_get(struct device *dev,
+       const char *con_id, unsigned *bit)
+{
+       return ERR_PTR(-EINVAL);
+}
+
+static inline void qcom_smem_state_put(struct qcom_smem_state *state)
+{
+}
+
+static inline int qcom_smem_state_update_bits(struct qcom_smem_state *state,
+       u32 mask, u32 value)
+{
+       return -EINVAL;
+}
+
+static inline struct qcom_smem_state *qcom_smem_state_register(struct device_node *of_node,
+       const struct qcom_smem_state_ops *ops, void *data)
+{
+       return ERR_PTR(-EINVAL);
+}
+
+static inline void qcom_smem_state_unregister(struct qcom_smem_state *state)
+{
+}
+
+#endif
+
 #endif
index 84ebce73aa2323d7631cf1bfdd584ebd9e9a7b2c..0d11132b3370a4024be644dede74a77d188a4f64 100644 (file)
 struct qrtr_smd_dev {
        struct qrtr_endpoint ep;
        struct qcom_smd_channel *channel;
+       struct device *dev;
 };
 
 /* from smd to qrtr */
-static int qcom_smd_qrtr_callback(struct qcom_smd_device *sdev,
+static int qcom_smd_qrtr_callback(struct qcom_smd_channel *channel,
                                  const void *data, size_t len)
 {
-       struct qrtr_smd_dev *qdev = dev_get_drvdata(&sdev->dev);
+       struct qrtr_smd_dev *qdev = qcom_smd_get_drvdata(channel);
        int rc;
 
        if (!qdev)
@@ -35,7 +36,7 @@ static int qcom_smd_qrtr_callback(struct qcom_smd_device *sdev,
 
        rc = qrtr_endpoint_post(&qdev->ep, data, len);
        if (rc == -EINVAL) {
-               dev_err(&sdev->dev, "invalid ipcrouter packet\n");
+               dev_err(qdev->dev, "invalid ipcrouter packet\n");
                /* return 0 to let smd drop the packet */
                rc = 0;
        }
@@ -73,12 +74,14 @@ static int qcom_smd_qrtr_probe(struct qcom_smd_device *sdev)
                return -ENOMEM;
 
        qdev->channel = sdev->channel;
+       qdev->dev = &sdev->dev;
        qdev->ep.xmit = qcom_smd_qrtr_send;
 
        rc = qrtr_endpoint_register(&qdev->ep, QRTR_EP_NID_AUTO);
        if (rc)
                return rc;
 
+       qcom_smd_set_drvdata(sdev->channel, qdev);
        dev_set_drvdata(&sdev->dev, qdev);
 
        dev_dbg(&sdev->dev, "Qualcomm SMD QRTR driver probed\n");