Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+52 -22
+38 -13
drivers/rpmsg/qcom_smd.c
··· 167 167 struct qcom_smd_channel *qsch; 168 168 }; 169 169 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) 171 171 #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) 173 173 174 174 /** 175 175 * struct qcom_smd_channel - smd channel struct ··· 205 205 struct smd_channel_info_pair *info; 206 206 struct smd_channel_info_word_pair *info_word; 207 207 208 - struct mutex tx_lock; 208 + spinlock_t tx_lock; 209 209 wait_queue_head_t fblockread_event; 210 210 211 211 void *tx_fifo; ··· 729 729 { 730 730 __le32 hdr[5] = { cpu_to_le32(len), }; 731 731 int tlen = sizeof(hdr) + len; 732 + unsigned long flags; 732 733 int ret; 733 734 734 735 /* Word aligned channels only accept word size aligned data */ ··· 740 739 if (tlen >= channel->fifo_size) 741 740 return -EINVAL; 742 741 743 - ret = mutex_lock_interruptible(&channel->tx_lock); 744 - if (ret) 745 - return ret; 742 + /* Highlight the fact that if we enter the loop below we might sleep */ 743 + if (wait) 744 + might_sleep(); 745 + 746 + spin_lock_irqsave(&channel->tx_lock, flags); 746 747 747 748 while (qcom_smd_get_tx_avail(channel) < tlen && 748 749 channel->state == SMD_CHANNEL_OPENED) { ··· 756 753 SET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR, 0); 757 754 758 755 /* Wait without holding the tx_lock */ 759 - mutex_unlock(&channel->tx_lock); 756 + spin_unlock_irqrestore(&channel->tx_lock, flags); 760 757 761 758 ret = wait_event_interruptible(channel->fblockread_event, 762 759 qcom_smd_get_tx_avail(channel) >= tlen || ··· 764 761 if (ret) 765 762 return ret; 766 763 767 - ret = mutex_lock_interruptible(&channel->tx_lock); 768 - if (ret) 769 - return ret; 764 + spin_lock_irqsave(&channel->tx_lock, flags); 770 765 771 766 SET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR, 1); 772 767 } ··· 788 787 qcom_smd_signal_channel(channel); 789 788 790 789 out_unlock: 791 - mutex_unlock(&channel->tx_lock); 790 + spin_unlock_irqrestore(&channel->tx_lock, flags); 792 791 793 792 return ret; 794 793 } ··· 997 996 return NULL; 998 997 } 999 998 999 + static int qcom_smd_announce_create(struct rpmsg_device *rpdev) 1000 + { 1001 + struct qcom_smd_endpoint *qept = to_smd_endpoint(rpdev->ept); 1002 + struct qcom_smd_channel *channel = qept->qsch; 1003 + unsigned long flags; 1004 + bool kick_state; 1005 + 1006 + spin_lock_irqsave(&channel->recv_lock, flags); 1007 + kick_state = qcom_smd_channel_intr(channel); 1008 + spin_unlock_irqrestore(&channel->recv_lock, flags); 1009 + 1010 + if (kick_state) 1011 + schedule_work(&channel->edge->state_work); 1012 + 1013 + return 0; 1014 + } 1015 + 1000 1016 static const struct rpmsg_device_ops qcom_smd_device_ops = { 1001 1017 .create_ept = qcom_smd_create_ept, 1018 + .announce_create = qcom_smd_announce_create, 1002 1019 }; 1003 1020 1004 1021 static const struct rpmsg_endpoint_ops qcom_smd_endpoint_ops = { ··· 1109 1090 if (!channel->name) 1110 1091 return ERR_PTR(-ENOMEM); 1111 1092 1112 - mutex_init(&channel->tx_lock); 1093 + spin_lock_init(&channel->tx_lock); 1113 1094 spin_lock_init(&channel->recv_lock); 1114 1095 init_waitqueue_head(&channel->fblockread_event); 1115 1096 init_waitqueue_head(&channel->state_change_event); ··· 1251 1232 spin_lock_irqsave(&edge->channels_lock, flags); 1252 1233 list_for_each_entry(channel, &edge->channels, list) { 1253 1234 if (channel->state != SMD_CHANNEL_CLOSED) 1235 + continue; 1236 + 1237 + remote_state = GET_RX_CHANNEL_INFO(channel, state); 1238 + if (remote_state != SMD_CHANNEL_OPENING && 1239 + remote_state != SMD_CHANNEL_OPENED) 1254 1240 continue; 1255 1241 1256 1242 if (channel->registered) ··· 1432 1408 ret = device_register(&edge->dev); 1433 1409 if (ret) { 1434 1410 pr_err("failed to register smd edge\n"); 1411 + put_device(&edge->dev); 1435 1412 return ERR_PTR(ret); 1436 1413 } 1437 1414 ··· 1453 1428 return edge; 1454 1429 1455 1430 unregister_dev: 1456 - put_device(&edge->dev); 1431 + device_unregister(&edge->dev); 1457 1432 return ERR_PTR(ret); 1458 1433 } 1459 1434 EXPORT_SYMBOL(qcom_smd_register_edge);
+1 -1
drivers/rpmsg/rpmsg_core.c
··· 442 442 goto out; 443 443 } 444 444 445 - if (rpdev->ops->announce_create) 445 + if (ept && rpdev->ops->announce_create) 446 446 err = rpdev->ops->announce_create(rpdev); 447 447 out: 448 448 return err;