Source
22
22
* with buffers
23
23
*/
24
24
void slim_msg_response(struct slim_controller *ctrl, u8 *reply, u8 tid, u8 len)
25
25
{
26
26
struct slim_msg_txn *txn;
27
27
struct slim_val_inf *msg;
28
28
unsigned long flags;
29
29
30
30
spin_lock_irqsave(&ctrl->txn_lock, flags);
31
31
txn = idr_find(&ctrl->tid_idr, tid);
32
-
if (txn == NULL) {
33
-
spin_unlock_irqrestore(&ctrl->txn_lock, flags);
32
+
spin_unlock_irqrestore(&ctrl->txn_lock, flags);
33
+
34
+
if (txn == NULL)
34
35
return;
35
-
}
36
36
37
37
msg = txn->msg;
38
38
if (msg == NULL || msg->rbuf == NULL) {
39
39
dev_err(ctrl->dev, "Got response to invalid TID:%d, len:%d\n",
40
40
tid, len);
41
-
spin_unlock_irqrestore(&ctrl->txn_lock, flags);
42
41
return;
43
42
}
44
43
45
-
idr_remove(&ctrl->tid_idr, tid);
46
-
spin_unlock_irqrestore(&ctrl->txn_lock, flags);
47
-
44
+
slim_free_txn_tid(ctrl, txn);
48
45
memcpy(msg->rbuf, reply, len);
49
46
if (txn->comp)
50
47
complete(txn->comp);
51
48
52
49
/* Remove runtime-pm vote now that response was received for TID txn */
53
50
pm_runtime_mark_last_busy(ctrl->dev);
54
51
pm_runtime_put_autosuspend(ctrl->dev);
55
52
}
56
53
EXPORT_SYMBOL_GPL(slim_msg_response);
57
54
55
+
/**
56
+
* slim_alloc_txn_tid() - Allocate a tid to txn
57
+
*
58
+
* @ctrl: Controller handle
59
+
* @txn: transaction to be allocated with tid.
60
+
*
61
+
* Return: zero on success with valid txn->tid and error code on failures.
62
+
*/
63
+
int slim_alloc_txn_tid(struct slim_controller *ctrl, struct slim_msg_txn *txn)
64
+
{
65
+
unsigned long flags;
66
+
int ret = 0;
67
+
68
+
spin_lock_irqsave(&ctrl->txn_lock, flags);
69
+
ret = idr_alloc_cyclic(&ctrl->tid_idr, txn, 0,
70
+
SLIM_MAX_TIDS, GFP_ATOMIC);
71
+
if (ret < 0) {
72
+
spin_unlock_irqrestore(&ctrl->txn_lock, flags);
73
+
return ret;
74
+
}
75
+
txn->tid = ret;
76
+
spin_unlock_irqrestore(&ctrl->txn_lock, flags);
77
+
return 0;
78
+
}
79
+
EXPORT_SYMBOL_GPL(slim_alloc_txn_tid);
80
+
81
+
/**
82
+
* slim_free_txn_tid() - Freee tid of txn
83
+
*
84
+
* @ctrl: Controller handle
85
+
* @txn: transaction whose tid should be freed
86
+
*/
87
+
void slim_free_txn_tid(struct slim_controller *ctrl, struct slim_msg_txn *txn)
88
+
{
89
+
unsigned long flags;
90
+
91
+
spin_lock_irqsave(&ctrl->txn_lock, flags);
92
+
idr_remove(&ctrl->tid_idr, txn->tid);
93
+
spin_unlock_irqrestore(&ctrl->txn_lock, flags);
94
+
}
95
+
EXPORT_SYMBOL_GPL(slim_free_txn_tid);
96
+
58
97
/**
59
98
* slim_do_transfer() - Process a SLIMbus-messaging transaction
60
99
*
61
100
* @ctrl: Controller handle
62
101
* @txn: Transaction to be sent over SLIMbus
63
102
*
64
103
* Called by controller to transmit messaging transactions not dealing with
65
104
* Interface/Value elements. (e.g. transmittting a message to assign logical
66
105
* address to a slave device
67
106
*
68
107
* Return: -ETIMEDOUT: If transmission of this message timed out
69
108
* (e.g. due to bus lines not being clocked or driven by controller)
70
109
*/
71
110
int slim_do_transfer(struct slim_controller *ctrl, struct slim_msg_txn *txn)
72
111
{
73
112
DECLARE_COMPLETION_ONSTACK(done);
74
113
bool need_tid = false, clk_pause_msg = false;
75
-
unsigned long flags;
76
-
int ret, tid, timeout;
114
+
int ret, timeout;
77
115
78
116
/*
79
117
* do not vote for runtime-PM if the transactions are part of clock
80
118
* pause sequence
81
119
*/
82
120
if (ctrl->sched.clk_state == SLIM_CLK_ENTERING_PAUSE &&
83
121
(txn->mt == SLIM_MSG_MT_CORE &&
84
122
txn->mc >= SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
85
123
txn->mc <= SLIM_MSG_MC_RECONFIGURE_NOW))
86
124
clk_pause_msg = true;
90
128
if (ctrl->sched.clk_state != SLIM_CLK_ACTIVE) {
91
129
dev_err(ctrl->dev, "ctrl wrong state:%d, ret:%d\n",
92
130
ctrl->sched.clk_state, ret);
93
131
goto slim_xfer_err;
94
132
}
95
133
}
96
134
97
135
need_tid = slim_tid_txn(txn->mt, txn->mc);
98
136
99
137
if (need_tid) {
100
-
spin_lock_irqsave(&ctrl->txn_lock, flags);
101
-
tid = idr_alloc(&ctrl->tid_idr, txn, 0,
102
-
SLIM_MAX_TIDS, GFP_ATOMIC);
103
-
txn->tid = tid;
138
+
ret = slim_alloc_txn_tid(ctrl, txn);
139
+
if (ret)
140
+
return ret;
104
141
105
142
if (!txn->msg->comp)
106
143
txn->comp = &done;
107
144
else
108
145
txn->comp = txn->comp;
109
-
110
-
spin_unlock_irqrestore(&ctrl->txn_lock, flags);
111
-
112
-
if (tid < 0)
113
-
return tid;
114
146
}
115
147
116
148
ret = ctrl->xfer_msg(ctrl, txn);
117
149
118
-
if (ret && need_tid && !txn->msg->comp) {
150
+
if (!ret && need_tid && !txn->msg->comp) {
119
151
unsigned long ms = txn->rl + HZ;
120
152
121
153
timeout = wait_for_completion_timeout(txn->comp,
122
154
msecs_to_jiffies(ms));
123
155
if (!timeout) {
124
156
ret = -ETIMEDOUT;
125
-
spin_lock_irqsave(&ctrl->txn_lock, flags);
126
-
idr_remove(&ctrl->tid_idr, tid);
127
-
spin_unlock_irqrestore(&ctrl->txn_lock, flags);
157
+
slim_free_txn_tid(ctrl, txn);
128
158
}
129
159
}
130
160
131
161
if (ret)
132
162
dev_err(ctrl->dev, "Tx:MT:0x%x, MC:0x%x, LA:0x%x failed:%d\n",
133
163
txn->mt, txn->mc, txn->la, ret);
134
164
135
165
slim_xfer_err:
136
166
if (!clk_pause_msg && (!need_tid || ret == -ETIMEDOUT)) {
137
167
/*