@@ -167,9 +167,9 @@ struct qcom_smd_endpoint {
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,7 +205,7 @@ struct qcom_smd_channel {
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,6 +729,7 @@ static int __qcom_smd_send(struct qcom_smd_channel *channel, const void *data,
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 */
@@ -739,9 +740,11 @@ static int __qcom_smd_send(struct qcom_smd_channel *channel, const void *data,
739
740
if (tlen >= channel -> fifo_size )
740
741
return - EINVAL ;
741
742
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 );
745
748
746
749
while (qcom_smd_get_tx_avail (channel ) < tlen &&
747
750
channel -> state == SMD_CHANNEL_OPENED ) {
@@ -753,17 +756,15 @@ static int __qcom_smd_send(struct qcom_smd_channel *channel, const void *data,
753
756
SET_TX_CHANNEL_FLAG (channel , fBLOCKREADINTR , 0 );
754
757
755
758
/* Wait without holding the tx_lock */
756
- mutex_unlock (& channel -> tx_lock );
759
+ spin_unlock_irqrestore (& channel -> tx_lock , flags );
757
760
758
761
ret = wait_event_interruptible (channel -> fblockread_event ,
759
762
qcom_smd_get_tx_avail (channel ) >= tlen ||
760
763
channel -> state != SMD_CHANNEL_OPENED );
761
764
if (ret )
762
765
return ret ;
763
766
764
- ret = mutex_lock_interruptible (& channel -> tx_lock );
765
- if (ret )
766
- return ret ;
767
+ spin_lock_irqsave (& channel -> tx_lock , flags );
767
768
768
769
SET_TX_CHANNEL_FLAG (channel , fBLOCKREADINTR , 1 );
769
770
}
@@ -787,7 +788,7 @@ static int __qcom_smd_send(struct qcom_smd_channel *channel, const void *data,
787
788
qcom_smd_signal_channel (channel );
788
789
789
790
out_unlock :
790
- mutex_unlock (& channel -> tx_lock );
791
+ spin_unlock_irqrestore (& channel -> tx_lock , flags );
791
792
792
793
return ret ;
793
794
}
@@ -996,8 +997,26 @@ static struct device_node *qcom_smd_match_channel(struct device_node *edge_node,
996
997
return NULL ;
997
998
}
998
999
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
+
999
1017
static const struct rpmsg_device_ops qcom_smd_device_ops = {
1000
1018
.create_ept = qcom_smd_create_ept ,
1019
+ .announce_create = qcom_smd_announce_create ,
1001
1020
};
1002
1021
1003
1022
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
1090
1109
if (!channel -> name )
1091
1110
return ERR_PTR (- ENOMEM );
1092
1111
1093
- mutex_init (& channel -> tx_lock );
1112
+ spin_lock_init (& channel -> tx_lock );
1094
1113
spin_lock_init (& channel -> recv_lock );
1095
1114
init_waitqueue_head (& channel -> fblockread_event );
1096
1115
init_waitqueue_head (& channel -> state_change_event );
@@ -1234,6 +1253,11 @@ static void qcom_channel_state_worker(struct work_struct *work)
1234
1253
if (channel -> state != SMD_CHANNEL_CLOSED )
1235
1254
continue ;
1236
1255
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
+
1237
1261
if (channel -> registered )
1238
1262
continue ;
1239
1263
@@ -1408,6 +1432,7 @@ struct qcom_smd_edge *qcom_smd_register_edge(struct device *parent,
1408
1432
ret = device_register (& edge -> dev );
1409
1433
if (ret ) {
1410
1434
pr_err ("failed to register smd edge\n" );
1435
+ put_device (& edge -> dev );
1411
1436
return ERR_PTR (ret );
1412
1437
}
1413
1438
@@ -1428,7 +1453,7 @@ struct qcom_smd_edge *qcom_smd_register_edge(struct device *parent,
1428
1453
return edge ;
1429
1454
1430
1455
unregister_dev :
1431
- put_device (& edge -> dev );
1456
+ device_unregister (& edge -> dev );
1432
1457
return ERR_PTR (ret );
1433
1458
}
1434
1459
EXPORT_SYMBOL (qcom_smd_register_edge );
0 commit comments