24
24
/* Time in msecs to wait for message response */
25
25
#define OCTEP_CTRL_MBOX_MSG_WAIT_MS 10
26
26
27
- #define OCTEP_CTRL_MBOX_INFO_MAGIC_NUM_OFFSET (m ) (m)
28
- #define OCTEP_CTRL_MBOX_INFO_BARMEM_SZ_OFFSET (m ) ((m) + 8)
29
- #define OCTEP_CTRL_MBOX_INFO_HOST_STATUS_OFFSET (m ) ((m) + 24)
30
- #define OCTEP_CTRL_MBOX_INFO_FW_STATUS_OFFSET (m ) ((m) + 144)
31
-
32
- #define OCTEP_CTRL_MBOX_H2FQ_INFO_OFFSET (m ) ((m) + OCTEP_CTRL_MBOX_INFO_SZ)
33
- #define OCTEP_CTRL_MBOX_H2FQ_PROD_OFFSET (m ) (OCTEP_CTRL_MBOX_H2FQ_INFO_OFFSET(m))
34
- #define OCTEP_CTRL_MBOX_H2FQ_CONS_OFFSET (m ) ((OCTEP_CTRL_MBOX_H2FQ_INFO_OFFSET(m)) + 4)
35
- #define OCTEP_CTRL_MBOX_H2FQ_ELEM_SZ_OFFSET (m ) ((OCTEP_CTRL_MBOX_H2FQ_INFO_OFFSET(m)) + 8)
36
- #define OCTEP_CTRL_MBOX_H2FQ_ELEM_CNT_OFFSET (m ) ((OCTEP_CTRL_MBOX_H2FQ_INFO_OFFSET(m)) + 12)
37
-
38
- #define OCTEP_CTRL_MBOX_F2HQ_INFO_OFFSET (m ) ((m) + \
39
- OCTEP_CTRL_MBOX_INFO_SZ + \
40
- OCTEP_CTRL_MBOX_H2FQ_INFO_SZ)
41
- #define OCTEP_CTRL_MBOX_F2HQ_PROD_OFFSET (m ) (OCTEP_CTRL_MBOX_F2HQ_INFO_OFFSET(m))
42
- #define OCTEP_CTRL_MBOX_F2HQ_CONS_OFFSET (m ) ((OCTEP_CTRL_MBOX_F2HQ_INFO_OFFSET(m)) + 4)
43
- #define OCTEP_CTRL_MBOX_F2HQ_ELEM_SZ_OFFSET (m ) ((OCTEP_CTRL_MBOX_F2HQ_INFO_OFFSET(m)) + 8)
44
- #define OCTEP_CTRL_MBOX_F2HQ_ELEM_CNT_OFFSET (m ) ((OCTEP_CTRL_MBOX_F2HQ_INFO_OFFSET(m)) + 12)
45
-
46
- #define OCTEP_CTRL_MBOX_Q_OFFSET (m , i ) ((m) + \
47
- (sizeof(struct octep_ctrl_mbox_msg) * (i)))
48
-
49
- static u32 octep_ctrl_mbox_circq_inc (u32 index , u32 mask )
27
+ /* Size of mbox info in bytes */
28
+ #define OCTEP_CTRL_MBOX_INFO_SZ 256
29
+ /* Size of mbox host to fw queue info in bytes */
30
+ #define OCTEP_CTRL_MBOX_H2FQ_INFO_SZ 16
31
+ /* Size of mbox fw to host queue info in bytes */
32
+ #define OCTEP_CTRL_MBOX_F2HQ_INFO_SZ 16
33
+
34
+ #define OCTEP_CTRL_MBOX_TOTAL_INFO_SZ (OCTEP_CTRL_MBOX_INFO_SZ + \
35
+ OCTEP_CTRL_MBOX_H2FQ_INFO_SZ + \
36
+ OCTEP_CTRL_MBOX_F2HQ_INFO_SZ)
37
+
38
+ #define OCTEP_CTRL_MBOX_INFO_MAGIC_NUM (m ) (m)
39
+ #define OCTEP_CTRL_MBOX_INFO_BARMEM_SZ (m ) ((m) + 8)
40
+ #define OCTEP_CTRL_MBOX_INFO_HOST_STATUS (m ) ((m) + 24)
41
+ #define OCTEP_CTRL_MBOX_INFO_FW_STATUS (m ) ((m) + 144)
42
+
43
+ #define OCTEP_CTRL_MBOX_H2FQ_INFO (m ) ((m) + OCTEP_CTRL_MBOX_INFO_SZ)
44
+ #define OCTEP_CTRL_MBOX_H2FQ_PROD (m ) (OCTEP_CTRL_MBOX_H2FQ_INFO(m))
45
+ #define OCTEP_CTRL_MBOX_H2FQ_CONS (m ) ((OCTEP_CTRL_MBOX_H2FQ_INFO(m)) + 4)
46
+ #define OCTEP_CTRL_MBOX_H2FQ_SZ (m ) ((OCTEP_CTRL_MBOX_H2FQ_INFO(m)) + 8)
47
+
48
+ #define OCTEP_CTRL_MBOX_F2HQ_INFO (m ) ((m) + \
49
+ OCTEP_CTRL_MBOX_INFO_SZ + \
50
+ OCTEP_CTRL_MBOX_H2FQ_INFO_SZ)
51
+ #define OCTEP_CTRL_MBOX_F2HQ_PROD (m ) (OCTEP_CTRL_MBOX_F2HQ_INFO(m))
52
+ #define OCTEP_CTRL_MBOX_F2HQ_CONS (m ) ((OCTEP_CTRL_MBOX_F2HQ_INFO(m)) + 4)
53
+ #define OCTEP_CTRL_MBOX_F2HQ_SZ (m ) ((OCTEP_CTRL_MBOX_F2HQ_INFO(m)) + 8)
54
+
55
+ static const u32 mbox_hdr_sz = sizeof (union octep_ctrl_mbox_msg_hdr );
56
+
57
+ static u32 octep_ctrl_mbox_circq_inc (u32 index , u32 inc , u32 sz )
50
58
{
51
- return (index + 1 ) & mask ;
59
+ return (index + inc ) % sz ;
52
60
}
53
61
54
- static u32 octep_ctrl_mbox_circq_space (u32 pi , u32 ci , u32 mask )
62
+ static u32 octep_ctrl_mbox_circq_space (u32 pi , u32 ci , u32 sz )
55
63
{
56
- return mask - ((pi - ci ) & mask );
64
+ return sz - (abs (pi - ci ) % sz );
57
65
}
58
66
59
- static u32 octep_ctrl_mbox_circq_depth (u32 pi , u32 ci , u32 mask )
67
+ static u32 octep_ctrl_mbox_circq_depth (u32 pi , u32 ci , u32 sz )
60
68
{
61
- return ((pi - ci ) & mask );
69
+ return (abs (pi - ci ) % sz );
62
70
}
63
71
64
72
int octep_ctrl_mbox_init (struct octep_ctrl_mbox * mbox )
@@ -73,172 +81,188 @@ int octep_ctrl_mbox_init(struct octep_ctrl_mbox *mbox)
73
81
return - EINVAL ;
74
82
}
75
83
76
- magic_num = readq (OCTEP_CTRL_MBOX_INFO_MAGIC_NUM_OFFSET (mbox -> barmem ));
84
+ magic_num = readq (OCTEP_CTRL_MBOX_INFO_MAGIC_NUM (mbox -> barmem ));
77
85
if (magic_num != OCTEP_CTRL_MBOX_MAGIC_NUMBER ) {
78
86
pr_info ("octep_ctrl_mbox : Invalid magic number %llx\n" , magic_num );
79
87
return - EINVAL ;
80
88
}
81
89
82
- status = readq (OCTEP_CTRL_MBOX_INFO_FW_STATUS_OFFSET (mbox -> barmem ));
90
+ status = readq (OCTEP_CTRL_MBOX_INFO_FW_STATUS (mbox -> barmem ));
83
91
if (status != OCTEP_CTRL_MBOX_STATUS_READY ) {
84
92
pr_info ("octep_ctrl_mbox : Firmware is not ready.\n" );
85
93
return - EINVAL ;
86
94
}
87
95
88
- mbox -> barmem_sz = readl (OCTEP_CTRL_MBOX_INFO_BARMEM_SZ_OFFSET (mbox -> barmem ));
96
+ mbox -> barmem_sz = readl (OCTEP_CTRL_MBOX_INFO_BARMEM_SZ (mbox -> barmem ));
89
97
90
- writeq (OCTEP_CTRL_MBOX_STATUS_INIT , OCTEP_CTRL_MBOX_INFO_HOST_STATUS_OFFSET (mbox -> barmem ));
98
+ writeq (OCTEP_CTRL_MBOX_STATUS_INIT ,
99
+ OCTEP_CTRL_MBOX_INFO_HOST_STATUS (mbox -> barmem ));
91
100
92
- mbox -> h2fq .elem_cnt = readl (OCTEP_CTRL_MBOX_H2FQ_ELEM_CNT_OFFSET (mbox -> barmem ));
93
- mbox -> h2fq .elem_sz = readl ( OCTEP_CTRL_MBOX_H2FQ_ELEM_SZ_OFFSET ( mbox -> barmem ) );
94
- mbox -> h2fq .mask = (mbox -> h2fq . elem_cnt - 1 );
95
- mutex_init ( & mbox -> h2fq_lock ) ;
101
+ mbox -> h2fq .sz = readl (OCTEP_CTRL_MBOX_H2FQ_SZ (mbox -> barmem ));
102
+ mbox -> h2fq .hw_prod = OCTEP_CTRL_MBOX_H2FQ_PROD ( mbox -> barmem );
103
+ mbox -> h2fq .hw_cons = OCTEP_CTRL_MBOX_H2FQ_CONS (mbox -> barmem );
104
+ mbox -> h2fq . hw_q = mbox -> barmem + OCTEP_CTRL_MBOX_TOTAL_INFO_SZ ;
96
105
97
- mbox -> f2hq .elem_cnt = readl (OCTEP_CTRL_MBOX_F2HQ_ELEM_CNT_OFFSET (mbox -> barmem ));
98
- mbox -> f2hq .elem_sz = readl (OCTEP_CTRL_MBOX_F2HQ_ELEM_SZ_OFFSET (mbox -> barmem ));
99
- mbox -> f2hq .mask = (mbox -> f2hq .elem_cnt - 1 );
100
- mutex_init (& mbox -> f2hq_lock );
101
-
102
- mbox -> h2fq .hw_prod = OCTEP_CTRL_MBOX_H2FQ_PROD_OFFSET (mbox -> barmem );
103
- mbox -> h2fq .hw_cons = OCTEP_CTRL_MBOX_H2FQ_CONS_OFFSET (mbox -> barmem );
104
- mbox -> h2fq .hw_q = mbox -> barmem +
105
- OCTEP_CTRL_MBOX_INFO_SZ +
106
- OCTEP_CTRL_MBOX_H2FQ_INFO_SZ +
107
- OCTEP_CTRL_MBOX_F2HQ_INFO_SZ ;
108
-
109
- mbox -> f2hq .hw_prod = OCTEP_CTRL_MBOX_F2HQ_PROD_OFFSET (mbox -> barmem );
110
- mbox -> f2hq .hw_cons = OCTEP_CTRL_MBOX_F2HQ_CONS_OFFSET (mbox -> barmem );
111
- mbox -> f2hq .hw_q = mbox -> h2fq .hw_q +
112
- ((mbox -> h2fq .elem_sz + sizeof (union octep_ctrl_mbox_msg_hdr )) *
113
- mbox -> h2fq .elem_cnt );
106
+ mbox -> f2hq .sz = readl (OCTEP_CTRL_MBOX_F2HQ_SZ (mbox -> barmem ));
107
+ mbox -> f2hq .hw_prod = OCTEP_CTRL_MBOX_F2HQ_PROD (mbox -> barmem );
108
+ mbox -> f2hq .hw_cons = OCTEP_CTRL_MBOX_F2HQ_CONS (mbox -> barmem );
109
+ mbox -> f2hq .hw_q = mbox -> barmem +
110
+ OCTEP_CTRL_MBOX_TOTAL_INFO_SZ +
111
+ mbox -> h2fq .sz ;
114
112
115
113
/* ensure ready state is seen after everything is initialized */
116
114
wmb ();
117
- writeq (OCTEP_CTRL_MBOX_STATUS_READY , OCTEP_CTRL_MBOX_INFO_HOST_STATUS_OFFSET (mbox -> barmem ));
115
+ writeq (OCTEP_CTRL_MBOX_STATUS_READY ,
116
+ OCTEP_CTRL_MBOX_INFO_HOST_STATUS (mbox -> barmem ));
118
117
119
118
pr_info ("Octep ctrl mbox : Init successful.\n" );
120
119
121
120
return 0 ;
122
121
}
123
122
123
+ static void
124
+ octep_write_mbox_data (struct octep_ctrl_mbox_q * q , u32 * pi , u32 ci , void * buf , u32 w_sz )
125
+ {
126
+ u8 __iomem * qbuf ;
127
+ u32 cp_sz ;
128
+
129
+ /* Assumption: Caller has ensured enough write space */
130
+ qbuf = (q -> hw_q + * pi );
131
+ if (* pi < ci ) {
132
+ /* copy entire w_sz */
133
+ memcpy_toio (qbuf , buf , w_sz );
134
+ * pi = octep_ctrl_mbox_circq_inc (* pi , w_sz , q -> sz );
135
+ } else {
136
+ /* copy up to end of queue */
137
+ cp_sz = min ((q -> sz - * pi ), w_sz );
138
+ memcpy_toio (qbuf , buf , cp_sz );
139
+ w_sz -= cp_sz ;
140
+ * pi = octep_ctrl_mbox_circq_inc (* pi , cp_sz , q -> sz );
141
+ if (w_sz ) {
142
+ /* roll over and copy remaining w_sz */
143
+ buf += cp_sz ;
144
+ qbuf = (q -> hw_q + * pi );
145
+ memcpy_toio (qbuf , buf , w_sz );
146
+ * pi = octep_ctrl_mbox_circq_inc (* pi , w_sz , q -> sz );
147
+ }
148
+ }
149
+ }
150
+
124
151
int octep_ctrl_mbox_send (struct octep_ctrl_mbox * mbox , struct octep_ctrl_mbox_msg * msg )
125
152
{
126
- unsigned long timeout = msecs_to_jiffies (OCTEP_CTRL_MBOX_MSG_TIMEOUT_MS );
127
- unsigned long period = msecs_to_jiffies (OCTEP_CTRL_MBOX_MSG_WAIT_MS );
153
+ struct octep_ctrl_mbox_msg_buf * sg ;
128
154
struct octep_ctrl_mbox_q * q ;
129
- unsigned long expire ;
130
- u64 * mbuf , * word0 ;
131
- u8 __iomem * qidx ;
132
- u16 pi , ci ;
133
- int i ;
155
+ u32 pi , ci , buf_sz , w_sz ;
156
+ int s ;
134
157
135
158
if (!mbox || !msg )
136
159
return - EINVAL ;
137
160
161
+ if (readq (OCTEP_CTRL_MBOX_INFO_FW_STATUS (mbox -> barmem )) != OCTEP_CTRL_MBOX_STATUS_READY )
162
+ return - EIO ;
163
+
164
+ mutex_lock (& mbox -> h2fq_lock );
138
165
q = & mbox -> h2fq ;
139
166
pi = readl (q -> hw_prod );
140
167
ci = readl (q -> hw_cons );
141
168
142
- if (!octep_ctrl_mbox_circq_space (pi , ci , q -> mask ))
143
- return - ENOMEM ;
144
-
145
- qidx = OCTEP_CTRL_MBOX_Q_OFFSET (q -> hw_q , pi );
146
- mbuf = (u64 * )msg -> msg ;
147
- word0 = & msg -> hdr .word0 ;
148
-
149
- mutex_lock (& mbox -> h2fq_lock );
150
- for (i = 1 ; i <= msg -> hdr .sizew ; i ++ )
151
- writeq (* mbuf ++ , (qidx + (i * 8 )));
152
-
153
- writeq (* word0 , qidx );
169
+ if (octep_ctrl_mbox_circq_space (pi , ci , q -> sz ) < (msg -> hdr .s .sz + mbox_hdr_sz )) {
170
+ mutex_unlock (& mbox -> f2hq_lock );
171
+ return - EAGAIN ;
172
+ }
154
173
155
- pi = octep_ctrl_mbox_circq_inc (pi , q -> mask );
174
+ octep_write_mbox_data (q , & pi , ci , (void * )& msg -> hdr , mbox_hdr_sz );
175
+ buf_sz = msg -> hdr .s .sz ;
176
+ for (s = 0 ; ((s < msg -> sg_num ) && (buf_sz > 0 )); s ++ ) {
177
+ sg = & msg -> sg_list [s ];
178
+ w_sz = (sg -> sz <= buf_sz ) ? sg -> sz : buf_sz ;
179
+ octep_write_mbox_data (q , & pi , ci , sg -> msg , w_sz );
180
+ buf_sz -= w_sz ;
181
+ }
156
182
writel (pi , q -> hw_prod );
157
183
mutex_unlock (& mbox -> h2fq_lock );
158
184
159
- /* don't check for notification response */
160
- if (msg -> hdr .flags & OCTEP_CTRL_MBOX_MSG_HDR_FLAG_NOTIFY )
161
- return 0 ;
162
-
163
- expire = jiffies + timeout ;
164
- while (true) {
165
- * word0 = readq (qidx );
166
- if (msg -> hdr .flags == OCTEP_CTRL_MBOX_MSG_HDR_FLAG_RESP )
167
- break ;
168
- schedule_timeout_interruptible (period );
169
- if (signal_pending (current ) || time_after (jiffies , expire )) {
170
- pr_info ("octep_ctrl_mbox: Timed out\n" );
171
- return - EBUSY ;
185
+ return 0 ;
186
+ }
187
+
188
+ static void
189
+ octep_read_mbox_data (struct octep_ctrl_mbox_q * q , u32 pi , u32 * ci , void * buf , u32 r_sz )
190
+ {
191
+ u8 __iomem * qbuf ;
192
+ u32 cp_sz ;
193
+
194
+ /* Assumption: Caller has ensured enough read space */
195
+ qbuf = (q -> hw_q + * ci );
196
+ if (* ci < pi ) {
197
+ /* copy entire r_sz */
198
+ memcpy_fromio (buf , qbuf , r_sz );
199
+ * ci = octep_ctrl_mbox_circq_inc (* ci , r_sz , q -> sz );
200
+ } else {
201
+ /* copy up to end of queue */
202
+ cp_sz = min ((q -> sz - * ci ), r_sz );
203
+ memcpy_fromio (buf , qbuf , cp_sz );
204
+ r_sz -= cp_sz ;
205
+ * ci = octep_ctrl_mbox_circq_inc (* ci , cp_sz , q -> sz );
206
+ if (r_sz ) {
207
+ /* roll over and copy remaining r_sz */
208
+ buf += cp_sz ;
209
+ qbuf = (q -> hw_q + * ci );
210
+ memcpy_fromio (buf , qbuf , r_sz );
211
+ * ci = octep_ctrl_mbox_circq_inc (* ci , r_sz , q -> sz );
172
212
}
173
213
}
174
- mbuf = (u64 * )msg -> msg ;
175
- for (i = 1 ; i <= msg -> hdr .sizew ; i ++ )
176
- * mbuf ++ = readq (qidx + (i * 8 ));
177
-
178
- return 0 ;
179
214
}
180
215
181
216
int octep_ctrl_mbox_recv (struct octep_ctrl_mbox * mbox , struct octep_ctrl_mbox_msg * msg )
182
217
{
218
+ struct octep_ctrl_mbox_msg_buf * sg ;
219
+ u32 pi , ci , r_sz , buf_sz , q_depth ;
183
220
struct octep_ctrl_mbox_q * q ;
184
- u32 count , pi , ci ;
185
- u8 __iomem * qidx ;
186
- u64 * mbuf ;
187
- int i ;
221
+ int s ;
188
222
189
- if (! mbox || ! msg )
190
- return - EINVAL ;
223
+ if (readq ( OCTEP_CTRL_MBOX_INFO_FW_STATUS ( mbox -> barmem )) != OCTEP_CTRL_MBOX_STATUS_READY )
224
+ return - EIO ;
191
225
226
+ mutex_lock (& mbox -> f2hq_lock );
192
227
q = & mbox -> f2hq ;
193
228
pi = readl (q -> hw_prod );
194
229
ci = readl (q -> hw_cons );
195
- count = octep_ctrl_mbox_circq_depth (pi , ci , q -> mask );
196
- if (!count )
197
- return - EAGAIN ;
198
-
199
- qidx = OCTEP_CTRL_MBOX_Q_OFFSET (q -> hw_q , ci );
200
- mbuf = (u64 * )msg -> msg ;
201
230
202
- mutex_lock ( & mbox -> f2hq_lock );
203
-
204
- msg -> hdr . word0 = readq ( qidx );
205
- for ( i = 1 ; i <= msg -> hdr . sizew ; i ++ )
206
- * mbuf ++ = readq ( qidx + ( i * 8 ));
231
+ q_depth = octep_ctrl_mbox_circq_depth ( pi , ci , q -> sz );
232
+ if ( q_depth < mbox_hdr_sz ) {
233
+ mutex_unlock ( & mbox -> f2hq_lock );
234
+ return - EAGAIN ;
235
+ }
207
236
208
- ci = octep_ctrl_mbox_circq_inc (ci , q -> mask );
237
+ octep_read_mbox_data (q , pi , & ci , (void * )& msg -> hdr , mbox_hdr_sz );
238
+ buf_sz = msg -> hdr .s .sz ;
239
+ for (s = 0 ; ((s < msg -> sg_num ) && (buf_sz > 0 )); s ++ ) {
240
+ sg = & msg -> sg_list [s ];
241
+ r_sz = (sg -> sz <= buf_sz ) ? sg -> sz : buf_sz ;
242
+ octep_read_mbox_data (q , pi , & ci , sg -> msg , r_sz );
243
+ buf_sz -= r_sz ;
244
+ }
209
245
writel (ci , q -> hw_cons );
210
-
211
246
mutex_unlock (& mbox -> f2hq_lock );
212
247
213
- if (msg -> hdr .flags != OCTEP_CTRL_MBOX_MSG_HDR_FLAG_REQ || !mbox -> process_req )
214
- return 0 ;
215
-
216
- mbox -> process_req (mbox -> user_ctx , msg );
217
- mbuf = (u64 * )msg -> msg ;
218
- for (i = 1 ; i <= msg -> hdr .sizew ; i ++ )
219
- writeq (* mbuf ++ , (qidx + (i * 8 )));
220
-
221
- writeq (msg -> hdr .word0 , qidx );
222
-
223
248
return 0 ;
224
249
}
225
250
226
251
int octep_ctrl_mbox_uninit (struct octep_ctrl_mbox * mbox )
227
252
{
228
253
if (!mbox )
229
254
return - EINVAL ;
255
+ if (!mbox -> barmem )
256
+ return - EINVAL ;
230
257
231
- writeq (OCTEP_CTRL_MBOX_STATUS_UNINIT ,
232
- OCTEP_CTRL_MBOX_INFO_HOST_STATUS_OFFSET (mbox -> barmem ));
258
+ writeq (OCTEP_CTRL_MBOX_STATUS_INVALID ,
259
+ OCTEP_CTRL_MBOX_INFO_HOST_STATUS (mbox -> barmem ));
233
260
/* ensure uninit state is written before uninitialization */
234
261
wmb ();
235
262
236
263
mutex_destroy (& mbox -> h2fq_lock );
237
264
mutex_destroy (& mbox -> f2hq_lock );
238
265
239
- writeq (OCTEP_CTRL_MBOX_STATUS_INVALID ,
240
- OCTEP_CTRL_MBOX_INFO_HOST_STATUS_OFFSET (mbox -> barmem ));
241
-
242
266
pr_info ("Octep ctrl mbox : Uninit successful.\n" );
243
267
244
268
return 0 ;
0 commit comments