Skip to content

Commit 9ab89c4

Browse files
committed
Merge tag 'rpmsg-v4.17' of git://github.com/andersson/remoteproc
Pull rpmsg updates from Bjorn Andersson: - transition the rpmsg_trysend() code paths of SMD and GLINK to use non-sleeping locks - revert the overly optimistic handling of discovered SMD channels - fix an issue in SMD where incoming messages race with the probing of a client driver * tag 'rpmsg-v4.17' of git://github.com/andersson/remoteproc: rpmsg: smd: Use announce_create to process any receive work rpmsg: Only invoke announce_create for rpdev with endpoints rpmsg: smd: Fix container_of macros Revert "rpmsg: smd: Create device for all channels" rpmsg: glink: Use spinlock in tx path rpmsg: smd: Use spinlock in tx path rpmsg: smd: use put_device() if device_register fail rpmsg: glink: use put_device() if device_register fail
2 parents f77cfbe + 0d72038 commit 9ab89c4

File tree

4 files changed

+52
-22
lines changed

4 files changed

+52
-22
lines changed

drivers/rpmsg/qcom_glink_native.c

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ struct qcom_glink {
113113
spinlock_t rx_lock;
114114
struct list_head rx_queue;
115115

116-
struct mutex tx_lock;
116+
spinlock_t tx_lock;
117117

118118
spinlock_t idr_lock;
119119
struct idr lcids;
@@ -288,23 +288,27 @@ static int qcom_glink_tx(struct qcom_glink *glink,
288288
const void *data, size_t dlen, bool wait)
289289
{
290290
unsigned int tlen = hlen + dlen;
291-
int ret;
291+
unsigned long flags;
292+
int ret = 0;
292293

293294
/* Reject packets that are too big */
294295
if (tlen >= glink->tx_pipe->length)
295296
return -EINVAL;
296297

297-
ret = mutex_lock_interruptible(&glink->tx_lock);
298-
if (ret)
299-
return ret;
298+
spin_lock_irqsave(&glink->tx_lock, flags);
300299

301300
while (qcom_glink_tx_avail(glink) < tlen) {
302301
if (!wait) {
303302
ret = -EAGAIN;
304303
goto out;
305304
}
306305

306+
/* Wait without holding the tx_lock */
307+
spin_unlock_irqrestore(&glink->tx_lock, flags);
308+
307309
usleep_range(10000, 15000);
310+
311+
spin_lock_irqsave(&glink->tx_lock, flags);
308312
}
309313

310314
qcom_glink_tx_write(glink, hdr, hlen, data, dlen);
@@ -313,7 +317,7 @@ static int qcom_glink_tx(struct qcom_glink *glink,
313317
mbox_client_txdone(glink->mbox_chan, 0);
314318

315319
out:
316-
mutex_unlock(&glink->tx_lock);
320+
spin_unlock_irqrestore(&glink->tx_lock, flags);
317321

318322
return ret;
319323
}
@@ -1567,7 +1571,7 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev,
15671571
glink->features = features;
15681572
glink->intentless = intentless;
15691573

1570-
mutex_init(&glink->tx_lock);
1574+
spin_lock_init(&glink->tx_lock);
15711575
spin_lock_init(&glink->rx_lock);
15721576
INIT_LIST_HEAD(&glink->rx_queue);
15731577
INIT_WORK(&glink->rx_work, qcom_glink_work);

drivers/rpmsg/qcom_glink_smem.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ struct qcom_glink *qcom_glink_smem_register(struct device *parent,
217217
ret = device_register(dev);
218218
if (ret) {
219219
pr_err("failed to register glink edge\n");
220+
put_device(dev);
220221
return ERR_PTR(ret);
221222
}
222223

@@ -299,7 +300,7 @@ struct qcom_glink *qcom_glink_smem_register(struct device *parent,
299300
return glink;
300301

301302
err_put_dev:
302-
put_device(dev);
303+
device_unregister(dev);
303304

304305
return ERR_PTR(ret);
305306
}

drivers/rpmsg/qcom_smd.c

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -167,9 +167,9 @@ struct qcom_smd_endpoint {
167167
struct qcom_smd_channel *qsch;
168168
};
169169

170-
#define to_smd_device(_rpdev) container_of(_rpdev, struct qcom_smd_device, rpdev)
170+
#define to_smd_device(r) container_of(r, struct qcom_smd_device, rpdev)
171171
#define to_smd_edge(d) container_of(d, struct qcom_smd_edge, dev)
172-
#define to_smd_endpoint(ept) container_of(ept, struct qcom_smd_endpoint, ept)
172+
#define to_smd_endpoint(e) container_of(e, struct qcom_smd_endpoint, ept)
173173

174174
/**
175175
* struct qcom_smd_channel - smd channel struct
@@ -205,7 +205,7 @@ struct qcom_smd_channel {
205205
struct smd_channel_info_pair *info;
206206
struct smd_channel_info_word_pair *info_word;
207207

208-
struct mutex tx_lock;
208+
spinlock_t tx_lock;
209209
wait_queue_head_t fblockread_event;
210210

211211
void *tx_fifo;
@@ -729,6 +729,7 @@ static int __qcom_smd_send(struct qcom_smd_channel *channel, const void *data,
729729
{
730730
__le32 hdr[5] = { cpu_to_le32(len), };
731731
int tlen = sizeof(hdr) + len;
732+
unsigned long flags;
732733
int ret;
733734

734735
/* Word aligned channels only accept word size aligned data */
@@ -739,9 +740,11 @@ static int __qcom_smd_send(struct qcom_smd_channel *channel, const void *data,
739740
if (tlen >= channel->fifo_size)
740741
return -EINVAL;
741742

742-
ret = mutex_lock_interruptible(&channel->tx_lock);
743-
if (ret)
744-
return ret;
743+
/* Highlight the fact that if we enter the loop below we might sleep */
744+
if (wait)
745+
might_sleep();
746+
747+
spin_lock_irqsave(&channel->tx_lock, flags);
745748

746749
while (qcom_smd_get_tx_avail(channel) < tlen &&
747750
channel->state == SMD_CHANNEL_OPENED) {
@@ -753,17 +756,15 @@ static int __qcom_smd_send(struct qcom_smd_channel *channel, const void *data,
753756
SET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR, 0);
754757

755758
/* Wait without holding the tx_lock */
756-
mutex_unlock(&channel->tx_lock);
759+
spin_unlock_irqrestore(&channel->tx_lock, flags);
757760

758761
ret = wait_event_interruptible(channel->fblockread_event,
759762
qcom_smd_get_tx_avail(channel) >= tlen ||
760763
channel->state != SMD_CHANNEL_OPENED);
761764
if (ret)
762765
return ret;
763766

764-
ret = mutex_lock_interruptible(&channel->tx_lock);
765-
if (ret)
766-
return ret;
767+
spin_lock_irqsave(&channel->tx_lock, flags);
767768

768769
SET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR, 1);
769770
}
@@ -787,7 +788,7 @@ static int __qcom_smd_send(struct qcom_smd_channel *channel, const void *data,
787788
qcom_smd_signal_channel(channel);
788789

789790
out_unlock:
790-
mutex_unlock(&channel->tx_lock);
791+
spin_unlock_irqrestore(&channel->tx_lock, flags);
791792

792793
return ret;
793794
}
@@ -996,8 +997,26 @@ static struct device_node *qcom_smd_match_channel(struct device_node *edge_node,
996997
return NULL;
997998
}
998999

1000+
static int qcom_smd_announce_create(struct rpmsg_device *rpdev)
1001+
{
1002+
struct qcom_smd_endpoint *qept = to_smd_endpoint(rpdev->ept);
1003+
struct qcom_smd_channel *channel = qept->qsch;
1004+
unsigned long flags;
1005+
bool kick_state;
1006+
1007+
spin_lock_irqsave(&channel->recv_lock, flags);
1008+
kick_state = qcom_smd_channel_intr(channel);
1009+
spin_unlock_irqrestore(&channel->recv_lock, flags);
1010+
1011+
if (kick_state)
1012+
schedule_work(&channel->edge->state_work);
1013+
1014+
return 0;
1015+
}
1016+
9991017
static const struct rpmsg_device_ops qcom_smd_device_ops = {
10001018
.create_ept = qcom_smd_create_ept,
1019+
.announce_create = qcom_smd_announce_create,
10011020
};
10021021

10031022
static const struct rpmsg_endpoint_ops qcom_smd_endpoint_ops = {
@@ -1090,7 +1109,7 @@ static struct qcom_smd_channel *qcom_smd_create_channel(struct qcom_smd_edge *ed
10901109
if (!channel->name)
10911110
return ERR_PTR(-ENOMEM);
10921111

1093-
mutex_init(&channel->tx_lock);
1112+
spin_lock_init(&channel->tx_lock);
10941113
spin_lock_init(&channel->recv_lock);
10951114
init_waitqueue_head(&channel->fblockread_event);
10961115
init_waitqueue_head(&channel->state_change_event);
@@ -1234,6 +1253,11 @@ static void qcom_channel_state_worker(struct work_struct *work)
12341253
if (channel->state != SMD_CHANNEL_CLOSED)
12351254
continue;
12361255

1256+
remote_state = GET_RX_CHANNEL_INFO(channel, state);
1257+
if (remote_state != SMD_CHANNEL_OPENING &&
1258+
remote_state != SMD_CHANNEL_OPENED)
1259+
continue;
1260+
12371261
if (channel->registered)
12381262
continue;
12391263

@@ -1408,6 +1432,7 @@ struct qcom_smd_edge *qcom_smd_register_edge(struct device *parent,
14081432
ret = device_register(&edge->dev);
14091433
if (ret) {
14101434
pr_err("failed to register smd edge\n");
1435+
put_device(&edge->dev);
14111436
return ERR_PTR(ret);
14121437
}
14131438

@@ -1428,7 +1453,7 @@ struct qcom_smd_edge *qcom_smd_register_edge(struct device *parent,
14281453
return edge;
14291454

14301455
unregister_dev:
1431-
put_device(&edge->dev);
1456+
device_unregister(&edge->dev);
14321457
return ERR_PTR(ret);
14331458
}
14341459
EXPORT_SYMBOL(qcom_smd_register_edge);

drivers/rpmsg/rpmsg_core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ static int rpmsg_dev_probe(struct device *dev)
442442
goto out;
443443
}
444444

445-
if (rpdev->ops->announce_create)
445+
if (ept && rpdev->ops->announce_create)
446446
err = rpdev->ops->announce_create(rpdev);
447447
out:
448448
return err;

0 commit comments

Comments
 (0)