mirror of https://gitee.com/openkylin/linux.git
Qualcomm ARM Based SoC Updates for v4.7 part 2
* Change SMD callback parameters * Use writecombine mapping for SMEM -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJXFvdZAAoJEFKiBbHx2RXVxPQQAJnEp1+5CDN7ziQ/zJ3juSxb b7rOr5Z0qMDhh0H9BFdmhGzFctbY0AOqerfh138pXa6KN7maXT/enUE4vvtWUp1B HCr9xt13waoa8e6umj/D1qU5mMLUX+JraVkIo6Dyd1g6pVmdrbwzP+Z0tW0x7CvW n5r9eDYts66vGbQ6xzK40rTi22sEN32AY4mezKj40L8o0NvfZCCwb3dfw2RQzLHK 0KnSQ0PKqU1ZWrDc2YuvRsyh5KGv+t8vvnpMVVUi4TRx3qzoGpHpH3fE3evvMGKY ya6nmFNFPZ+ZlzsGDx10RqLu58NmjS8LXY6O+yCGy9NPuonKpwHgYD2wxut2NR/W TTtMhvJWKNIwhXR8ZRDaVBWQJBwoLvpNQT1zOIUuUKf+SZ2DbfgVpte7NZvrgEka aY4nnZMbI0MvpaAHUtllWbC4xqMQJXY+4wrahKQgKF/l5H/0XQ99fHHz86DS9LCO y+dfmU98dv/1X8qmxNfsULtJwbxi2Xwzt3MMMZb5v138STyMWeqWOLm+KGzgs1hu Pc/RLQALdJpQEcg74s5xt2yxSqRuzDig7FtRT1a2SX33vi9YohQEgXCDe+IOJC5l sm1Ppi3oO/yUcocUDFTBz/g6zD4SWywu2gmBcZIh/JVy8Sd053WwlaKs1Nld6ta7 QPx6rga7lgrYW409RS2A =Jzqj -----END PGP SIGNATURE----- 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. Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
This commit is contained in:
commit
f79a917e69
|
@ -1470,7 +1470,10 @@ F: arch/arm/boot/dts/qcom-*.dts
|
||||||
F: arch/arm/boot/dts/qcom-*.dtsi
|
F: arch/arm/boot/dts/qcom-*.dtsi
|
||||||
F: arch/arm/mach-qcom/
|
F: arch/arm/mach-qcom/
|
||||||
F: arch/arm64/boot/dts/qcom/*
|
F: arch/arm64/boot/dts/qcom/*
|
||||||
|
F: drivers/i2c/busses/i2c-qup.c
|
||||||
|
F: drivers/clk/qcom/
|
||||||
F: drivers/soc/qcom/
|
F: drivers/soc/qcom/
|
||||||
|
F: drivers/spi/spi-qup.c
|
||||||
F: drivers/tty/serial/msm_serial.h
|
F: drivers/tty/serial/msm_serial.h
|
||||||
F: drivers/tty/serial/msm_serial.c
|
F: drivers/tty/serial/msm_serial.c
|
||||||
F: drivers/*/pm8???-*
|
F: drivers/*/pm8???-*
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
*/
|
*/
|
||||||
struct qcom_smd_rpm {
|
struct qcom_smd_rpm {
|
||||||
struct qcom_smd_channel *rpm_channel;
|
struct qcom_smd_channel *rpm_channel;
|
||||||
|
struct device *dev;
|
||||||
|
|
||||||
struct completion ack;
|
struct completion ack;
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
|
@ -149,14 +150,14 @@ int qcom_rpm_smd_write(struct qcom_smd_rpm *rpm,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(qcom_rpm_smd_write);
|
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,
|
const void *data,
|
||||||
size_t count)
|
size_t count)
|
||||||
{
|
{
|
||||||
const struct qcom_rpm_header *hdr = data;
|
const struct qcom_rpm_header *hdr = data;
|
||||||
size_t hdr_length = le32_to_cpu(hdr->length);
|
size_t hdr_length = le32_to_cpu(hdr->length);
|
||||||
const struct qcom_rpm_message *msg;
|
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 *buf = data + sizeof(struct qcom_rpm_header);
|
||||||
const u8 *end = buf + hdr_length;
|
const u8 *end = buf + hdr_length;
|
||||||
char msgbuf[32];
|
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 ||
|
if (le32_to_cpu(hdr->service_type) != RPM_SERVICE_TYPE_REQUEST ||
|
||||||
hdr_length < sizeof(struct qcom_rpm_message)) {
|
hdr_length < sizeof(struct qcom_rpm_message)) {
|
||||||
dev_err(&qsdev->dev, "invalid request\n");
|
dev_err(rpm->dev, "invalid request\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,7 +207,9 @@ static int qcom_smd_rpm_probe(struct qcom_smd_device *sdev)
|
||||||
mutex_init(&rpm->lock);
|
mutex_init(&rpm->lock);
|
||||||
init_completion(&rpm->ack);
|
init_completion(&rpm->ack);
|
||||||
|
|
||||||
|
rpm->dev = &sdev->dev;
|
||||||
rpm->rpm_channel = sdev->channel;
|
rpm->rpm_channel = sdev->channel;
|
||||||
|
qcom_smd_set_drvdata(sdev->channel, rpm);
|
||||||
|
|
||||||
dev_set_drvdata(&sdev->dev, rpm);
|
dev_set_drvdata(&sdev->dev, rpm);
|
||||||
|
|
||||||
|
|
|
@ -106,9 +106,9 @@ static const struct {
|
||||||
* @channels: list of all channels detected on this edge
|
* @channels: list of all channels detected on this edge
|
||||||
* @channels_lock: guard for modifications of @channels
|
* @channels_lock: guard for modifications of @channels
|
||||||
* @allocated: array of bitmaps representing already allocated 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
|
* @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_edge {
|
||||||
struct qcom_smd *smd;
|
struct qcom_smd *smd;
|
||||||
|
@ -127,10 +127,12 @@ struct qcom_smd_edge {
|
||||||
|
|
||||||
DECLARE_BITMAP(allocated[SMD_ALLOC_TBL_COUNT], SMD_ALLOC_TBL_SIZE);
|
DECLARE_BITMAP(allocated[SMD_ALLOC_TBL_COUNT], SMD_ALLOC_TBL_SIZE);
|
||||||
|
|
||||||
bool need_rescan;
|
|
||||||
unsigned smem_available;
|
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;
|
int fifo_size;
|
||||||
|
|
||||||
void *bounce_buffer;
|
void *bounce_buffer;
|
||||||
int (*cb)(struct qcom_smd_device *, const void *, size_t);
|
qcom_smd_cb_t cb;
|
||||||
|
|
||||||
spinlock_t recv_lock;
|
spinlock_t recv_lock;
|
||||||
|
|
||||||
int pkt_size;
|
int pkt_size;
|
||||||
|
|
||||||
|
void *drvdata;
|
||||||
|
|
||||||
struct list_head list;
|
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;
|
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
|
* 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)
|
static int qcom_smd_channel_recv_single(struct qcom_smd_channel *channel)
|
||||||
{
|
{
|
||||||
struct qcom_smd_device *qsdev = channel->qsdev;
|
|
||||||
unsigned tail;
|
unsigned tail;
|
||||||
size_t len;
|
size_t len;
|
||||||
void *ptr;
|
void *ptr;
|
||||||
|
@ -517,7 +534,7 @@ static int qcom_smd_channel_recv_single(struct qcom_smd_channel *channel)
|
||||||
len = channel->pkt_size;
|
len = channel->pkt_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = channel->cb(qsdev, ptr, len);
|
ret = channel->cb(channel, ptr, len);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
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_edge *edge = data;
|
||||||
struct qcom_smd_channel *channel;
|
struct qcom_smd_channel *channel;
|
||||||
unsigned available;
|
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
|
* 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);
|
spin_lock(&edge->channels_lock);
|
||||||
list_for_each_entry(channel, &edge->channels, list) {
|
list_for_each_entry(channel, &edge->channels, list) {
|
||||||
spin_lock(&channel->recv_lock);
|
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(&channel->recv_lock);
|
||||||
}
|
}
|
||||||
spin_unlock(&edge->channels_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);
|
available = qcom_smem_get_free_space(edge->remote_pid);
|
||||||
if (available != edge->smem_available) {
|
if (available != edge->smem_available) {
|
||||||
edge->smem_available = available;
|
edge->smem_available = available;
|
||||||
edge->need_rescan = true;
|
kick_scanner = true;
|
||||||
kick_worker = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kick_worker)
|
if (kick_scanner)
|
||||||
schedule_work(&edge->work);
|
schedule_work(&edge->scan_work);
|
||||||
|
if (kick_state)
|
||||||
|
schedule_work(&edge->state_work);
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
@ -792,6 +811,43 @@ static int qcom_smd_dev_match(struct device *dev, struct device_driver *drv)
|
||||||
return of_driver_match_device(dev, drv);
|
return of_driver_match_device(dev, drv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper for opening a channel
|
||||||
|
*/
|
||||||
|
static int qcom_smd_channel_open(struct qcom_smd_channel *channel,
|
||||||
|
qcom_smd_cb_t cb)
|
||||||
|
{
|
||||||
|
size_t bb_size;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Packets are maximum 4k, but reduce if the fifo is smaller
|
||||||
|
*/
|
||||||
|
bb_size = min(channel->fifo_size, SZ_4K);
|
||||||
|
channel->bounce_buffer = kmalloc(bb_size, GFP_KERNEL);
|
||||||
|
if (!channel->bounce_buffer)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
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.
|
* Probe the smd client.
|
||||||
*
|
*
|
||||||
|
@ -803,22 +859,11 @@ static int qcom_smd_dev_probe(struct device *dev)
|
||||||
struct qcom_smd_device *qsdev = to_smd_device(dev);
|
struct qcom_smd_device *qsdev = to_smd_device(dev);
|
||||||
struct qcom_smd_driver *qsdrv = to_smd_driver(dev);
|
struct qcom_smd_driver *qsdrv = to_smd_driver(dev);
|
||||||
struct qcom_smd_channel *channel = qsdev->channel;
|
struct qcom_smd_channel *channel = qsdev->channel;
|
||||||
size_t bb_size;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/*
|
ret = qcom_smd_channel_open(channel, qsdrv->callback);
|
||||||
* Packets are maximum 4k, but reduce if the fifo is smaller
|
if (ret)
|
||||||
*/
|
return ret;
|
||||||
bb_size = min(channel->fifo_size, SZ_4K);
|
|
||||||
channel->bounce_buffer = kmalloc(bb_size, GFP_KERNEL);
|
|
||||||
if (!channel->bounce_buffer)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
channel->cb = qsdrv->callback;
|
|
||||||
|
|
||||||
qcom_smd_channel_set_state(channel, SMD_CHANNEL_OPENING);
|
|
||||||
|
|
||||||
qcom_smd_channel_set_state(channel, SMD_CHANNEL_OPENED);
|
|
||||||
|
|
||||||
ret = qsdrv->probe(qsdev);
|
ret = qsdrv->probe(qsdev);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -831,11 +876,7 @@ static int qcom_smd_dev_probe(struct device *dev)
|
||||||
err:
|
err:
|
||||||
dev_err(&qsdev->dev, "probe failed\n");
|
dev_err(&qsdev->dev, "probe failed\n");
|
||||||
|
|
||||||
channel->cb = NULL;
|
qcom_smd_channel_close(channel);
|
||||||
kfree(channel->bounce_buffer);
|
|
||||||
channel->bounce_buffer = NULL;
|
|
||||||
|
|
||||||
qcom_smd_channel_set_state(channel, SMD_CHANNEL_CLOSED);
|
|
||||||
return ret;
|
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_device *qsdev = to_smd_device(dev);
|
||||||
struct qcom_smd_driver *qsdrv = to_smd_driver(dev);
|
struct qcom_smd_driver *qsdrv = to_smd_driver(dev);
|
||||||
struct qcom_smd_channel *channel = qsdev->channel;
|
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);
|
qcom_smd_channel_set_state(channel, SMD_CHANNEL_CLOSING);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make sure we don't race with the code receiving data.
|
* Make sure we don't race with the code receiving data.
|
||||||
*/
|
*/
|
||||||
spin_lock_irqsave(&channel->recv_lock, flags);
|
qcom_smd_channel_set_callback(channel, NULL);
|
||||||
channel->cb = NULL;
|
|
||||||
spin_unlock_irqrestore(&channel->recv_lock, flags);
|
|
||||||
|
|
||||||
/* Wake up any sleepers in qcom_smd_send() */
|
/* Wake up any sleepers in qcom_smd_send() */
|
||||||
wake_up_interruptible(&channel->fblockread_event);
|
wake_up_interruptible(&channel->fblockread_event);
|
||||||
|
@ -872,15 +912,14 @@ static int qcom_smd_dev_remove(struct device *dev)
|
||||||
qsdrv->remove(qsdev);
|
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;
|
list_for_each_entry_safe(ch, tmp, &channel->dev_list, dev_list) {
|
||||||
kfree(channel->bounce_buffer);
|
qcom_smd_channel_close(ch);
|
||||||
channel->bounce_buffer = NULL;
|
list_del(&ch->dev_list);
|
||||||
|
ch->qsdev = NULL;
|
||||||
qcom_smd_channel_set_state(channel, SMD_CHANNEL_CLOSED);
|
}
|
||||||
|
|
||||||
qcom_smd_channel_reset(channel);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -996,6 +1035,18 @@ int qcom_smd_driver_register(struct qcom_smd_driver *qsdrv)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(qcom_smd_driver_register);
|
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
|
* qcom_smd_driver_unregister - unregister a smd driver
|
||||||
* @qsdrv: qcom_smd_driver struct
|
* @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);
|
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,
|
* Allocate the qcom_smd_channel object for a newly found smd channel,
|
||||||
* retrieving and validating the smem items involved.
|
* 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)
|
if (!channel)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
INIT_LIST_HEAD(&channel->dev_list);
|
||||||
channel->edge = edge;
|
channel->edge = edge;
|
||||||
channel->name = devm_kstrdup(smd->dev, name, GFP_KERNEL);
|
channel->name = devm_kstrdup(smd->dev, name, GFP_KERNEL);
|
||||||
if (!channel->name)
|
if (!channel->name)
|
||||||
|
@ -1089,8 +1213,9 @@ static struct qcom_smd_channel *qcom_smd_create_channel(struct qcom_smd_edge *ed
|
||||||
* qcom_smd_create_channel() to create representations of these and add
|
* qcom_smd_create_channel() to create representations of these and add
|
||||||
* them to the edge's list of channels.
|
* 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 *alloc_tbl;
|
||||||
struct qcom_smd_alloc_entry *entry;
|
struct qcom_smd_alloc_entry *entry;
|
||||||
struct qcom_smd_channel *channel;
|
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);
|
dev_dbg(smd->dev, "new channel found: '%s'\n", channel->name);
|
||||||
set_bit(i, edge->allocated[tbl]);
|
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
|
* then scans all registered channels for state changes that should be handled
|
||||||
* by creating or destroying smd client devices for the registered channels.
|
* by creating or destroying smd client devices for the registered channels.
|
||||||
*
|
*
|
||||||
* LOCKING: edge->channels_lock is not needed to be held during the traversal
|
* LOCKING: edge->channels_lock only needs to cover the list operations, as the
|
||||||
* of the channels list as it's done synchronously with the only writer.
|
* worker is killed before any channels are deallocated
|
||||||
*/
|
*/
|
||||||
static void qcom_channel_state_worker(struct work_struct *work)
|
static void qcom_channel_state_worker(struct work_struct *work)
|
||||||
{
|
{
|
||||||
struct qcom_smd_channel *channel;
|
struct qcom_smd_channel *channel;
|
||||||
struct qcom_smd_edge *edge = container_of(work,
|
struct qcom_smd_edge *edge = container_of(work,
|
||||||
struct qcom_smd_edge,
|
struct qcom_smd_edge,
|
||||||
work);
|
state_work);
|
||||||
unsigned remote_state;
|
unsigned remote_state;
|
||||||
|
unsigned long flags;
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Register a device for any closed channel where the remote processor
|
* Register a device for any closed channel where the remote processor
|
||||||
* is showing interest in opening the channel.
|
* is showing interest in opening the channel.
|
||||||
*/
|
*/
|
||||||
|
spin_lock_irqsave(&edge->channels_lock, flags);
|
||||||
list_for_each_entry(channel, &edge->channels, list) {
|
list_for_each_entry(channel, &edge->channels, list) {
|
||||||
if (channel->state != SMD_CHANNEL_CLOSED)
|
if (channel->state != SMD_CHANNEL_CLOSED)
|
||||||
continue;
|
continue;
|
||||||
|
@ -1183,7 +1304,9 @@ static void qcom_channel_state_worker(struct work_struct *work)
|
||||||
remote_state != SMD_CHANNEL_OPENED)
|
remote_state != SMD_CHANNEL_OPENED)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&edge->channels_lock, flags);
|
||||||
qcom_smd_create_device(channel);
|
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)
|
remote_state == SMD_CHANNEL_OPENED)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&edge->channels_lock, flags);
|
||||||
qcom_smd_destroy_device(channel);
|
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);
|
INIT_LIST_HEAD(&edge->channels);
|
||||||
spin_lock_init(&edge->channels_lock);
|
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);
|
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) {
|
for_each_available_child_of_node(pdev->dev.of_node, node) {
|
||||||
edge = &smd->edges[i++];
|
edge = &smd->edges[i++];
|
||||||
edge->smd = smd;
|
edge->smd = smd;
|
||||||
|
init_waitqueue_head(&edge->new_channel_event);
|
||||||
|
|
||||||
ret = qcom_smd_parse_edge(&pdev->dev, node, edge);
|
ret = qcom_smd_parse_edge(&pdev->dev, node, edge);
|
||||||
if (ret)
|
if (ret)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
edge->need_rescan = true;
|
schedule_work(&edge->scan_work);
|
||||||
schedule_work(&edge->work);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
platform_set_drvdata(pdev, smd);
|
platform_set_drvdata(pdev, smd);
|
||||||
|
@ -1332,8 +1459,10 @@ static int qcom_smd_remove(struct platform_device *pdev)
|
||||||
edge = &smd->edges[i];
|
edge = &smd->edges[i];
|
||||||
|
|
||||||
disable_irq(edge->irq);
|
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) {
|
list_for_each_entry(channel, &edge->channels, list) {
|
||||||
if (!channel->qsdev)
|
if (!channel->qsdev)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -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].aux_base = (u32)r.start;
|
||||||
smem->regions[i].size = resource_size(&r);
|
smem->regions[i].size = resource_size(&r);
|
||||||
smem->regions[i].virt_base = devm_ioremap_nocache(dev, r.start,
|
smem->regions[i].virt_base = devm_ioremap_wc(dev, r.start, resource_size(&r));
|
||||||
resource_size(&r));
|
|
||||||
if (!smem->regions[i].virt_base)
|
if (!smem->regions[i].virt_base)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
|
||||||
* Copyright (c) 2014,2015, Linaro Ltd.
|
* Copyright (c) 2014,2015, Linaro Ltd.
|
||||||
*
|
*
|
||||||
|
* SAW power controller driver
|
||||||
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
* only version 2 as published by the Free Software Foundation.
|
* only version 2 as published by the Free Software Foundation.
|
||||||
|
@ -12,7 +14,6 @@
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/module.h>
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
|
@ -378,8 +379,5 @@ static struct platform_driver spm_driver = {
|
||||||
.of_match_table = spm_match_table,
|
.of_match_table = spm_match_table,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
module_platform_driver(spm_driver);
|
|
||||||
|
|
||||||
MODULE_LICENSE("GPL v2");
|
builtin_platform_driver(spm_driver);
|
||||||
MODULE_DESCRIPTION("SAW power controller driver");
|
|
||||||
MODULE_ALIAS("platform:saw");
|
|
||||||
|
|
|
@ -100,17 +100,17 @@ struct wcnss_download_nv_resp {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wcnss_ctrl_smd_callback() - handler from SMD responses
|
* wcnss_ctrl_smd_callback() - handler from SMD responses
|
||||||
* @qsdev: smd device handle
|
* @channel: smd channel handle
|
||||||
* @data: pointer to the incoming data packet
|
* @data: pointer to the incoming data packet
|
||||||
* @count: size of the incoming data packet
|
* @count: size of the incoming data packet
|
||||||
*
|
*
|
||||||
* Handles any incoming packets from the remote WCNSS_CTRL service.
|
* 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,
|
const void *data,
|
||||||
size_t count)
|
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_download_nv_resp *nvresp;
|
||||||
const struct wcnss_version_resp *version;
|
const struct wcnss_version_resp *version;
|
||||||
const struct wcnss_msg_hdr *hdr = data;
|
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_completion(&wcnss->ack);
|
||||||
INIT_WORK(&wcnss->download_nv_work, wcnss_download_nv);
|
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);
|
return wcnss_request_version(wcnss);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,8 @@ struct qcom_smd_device {
|
||||||
struct qcom_smd_channel *channel;
|
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
|
* struct qcom_smd_driver - smd driver struct
|
||||||
* @driver: underlying device driver
|
* @driver: underlying device driver
|
||||||
|
@ -42,7 +44,7 @@ struct qcom_smd_driver {
|
||||||
|
|
||||||
int (*probe)(struct qcom_smd_device *dev);
|
int (*probe)(struct qcom_smd_device *dev);
|
||||||
void (*remove)(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)
|
#if IS_ENABLED(CONFIG_QCOM_SMD)
|
||||||
|
@ -50,8 +52,14 @@ struct qcom_smd_driver {
|
||||||
int qcom_smd_driver_register(struct qcom_smd_driver *drv);
|
int qcom_smd_driver_register(struct qcom_smd_driver *drv);
|
||||||
void qcom_smd_driver_unregister(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);
|
int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len);
|
||||||
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static inline int qcom_smd_driver_register(struct qcom_smd_driver *drv)
|
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);
|
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,
|
static inline int qcom_smd_send(struct qcom_smd_channel *channel,
|
||||||
const void *data, int len)
|
const void *data, int len)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,12 +1,17 @@
|
||||||
#ifndef __QCOM_SMEM_STATE__
|
#ifndef __QCOM_SMEM_STATE__
|
||||||
#define __QCOM_SMEM_STATE__
|
#define __QCOM_SMEM_STATE__
|
||||||
|
|
||||||
|
#include <linux/errno.h>
|
||||||
|
|
||||||
|
struct device_node;
|
||||||
struct qcom_smem_state;
|
struct qcom_smem_state;
|
||||||
|
|
||||||
struct qcom_smem_state_ops {
|
struct qcom_smem_state_ops {
|
||||||
int (*update_bits)(void *, u32, u32);
|
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);
|
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 *);
|
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);
|
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);
|
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
|
#endif
|
||||||
|
|
|
@ -21,13 +21,14 @@
|
||||||
struct qrtr_smd_dev {
|
struct qrtr_smd_dev {
|
||||||
struct qrtr_endpoint ep;
|
struct qrtr_endpoint ep;
|
||||||
struct qcom_smd_channel *channel;
|
struct qcom_smd_channel *channel;
|
||||||
|
struct device *dev;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* from smd to qrtr */
|
/* 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)
|
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;
|
int rc;
|
||||||
|
|
||||||
if (!qdev)
|
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);
|
rc = qrtr_endpoint_post(&qdev->ep, data, len);
|
||||||
if (rc == -EINVAL) {
|
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 */
|
/* return 0 to let smd drop the packet */
|
||||||
rc = 0;
|
rc = 0;
|
||||||
}
|
}
|
||||||
|
@ -73,12 +74,14 @@ static int qcom_smd_qrtr_probe(struct qcom_smd_device *sdev)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
qdev->channel = sdev->channel;
|
qdev->channel = sdev->channel;
|
||||||
|
qdev->dev = &sdev->dev;
|
||||||
qdev->ep.xmit = qcom_smd_qrtr_send;
|
qdev->ep.xmit = qcom_smd_qrtr_send;
|
||||||
|
|
||||||
rc = qrtr_endpoint_register(&qdev->ep, QRTR_EP_NID_AUTO);
|
rc = qrtr_endpoint_register(&qdev->ep, QRTR_EP_NID_AUTO);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
qcom_smd_set_drvdata(sdev->channel, qdev);
|
||||||
dev_set_drvdata(&sdev->dev, qdev);
|
dev_set_drvdata(&sdev->dev, qdev);
|
||||||
|
|
||||||
dev_dbg(&sdev->dev, "Qualcomm SMD QRTR driver probed\n");
|
dev_dbg(&sdev->dev, "Qualcomm SMD QRTR driver probed\n");
|
||||||
|
|
Loading…
Reference in New Issue