@@ -168,6 +168,13 @@ static bool parse_line(char **line, u32 *offs, u32 *val, int short_fmt_len,
168
168
* offset relative_offset cap_id vs_cap_id value\n
169
169
* v[0] v[1] v[2] v[3] v[4]
170
170
*
171
+ * For Path configuration space:
172
+ * Short format is: offset value\n
173
+ * v[0] v[1]
174
+ * Long format as produced from the read side:
175
+ * offset relative_offset in_hop_id value\n
176
+ * v[0] v[1] v[2] v[3]
177
+ *
171
178
* For Counter configuration space:
172
179
* Short format is: offset\n
173
180
* v[0]
@@ -191,14 +198,33 @@ static bool parse_line(char **line, u32 *offs, u32 *val, int short_fmt_len,
191
198
}
192
199
193
200
#if IS_ENABLED (CONFIG_USB4_DEBUGFS_WRITE )
201
+ /*
202
+ * Path registers need to be written in double word pairs and they both must be
203
+ * read before written. This writes one double word in patch config space
204
+ * following the spec flow.
205
+ */
206
+ static int path_write_one (struct tb_port * port , u32 val , u32 offset )
207
+ {
208
+ u32 index = offset % PATH_LEN ;
209
+ u32 offs = offset - index ;
210
+ u32 data [PATH_LEN ];
211
+ int ret ;
212
+
213
+ ret = tb_port_read (port , data , TB_CFG_HOPS , offs , PATH_LEN );
214
+ if (ret )
215
+ return ret ;
216
+ data [index ] = val ;
217
+ return tb_port_write (port , data , TB_CFG_HOPS , offs , PATH_LEN );
218
+ }
219
+
194
220
static ssize_t regs_write (struct tb_switch * sw , struct tb_port * port ,
195
- const char __user * user_buf , size_t count ,
196
- loff_t * ppos )
221
+ enum tb_cfg_space space , const char __user * user_buf ,
222
+ size_t count , loff_t * ppos )
197
223
{
224
+ int long_fmt_len , ret = 0 ;
198
225
struct tb * tb = sw -> tb ;
199
226
char * line , * buf ;
200
227
u32 val , offset ;
201
- int ret = 0 ;
202
228
203
229
buf = validate_and_copy_from_user (user_buf , & count );
204
230
if (IS_ERR (buf ))
@@ -214,12 +240,21 @@ static ssize_t regs_write(struct tb_switch *sw, struct tb_port *port,
214
240
/* User did hardware changes behind the driver's back */
215
241
add_taint (TAINT_USER , LOCKDEP_STILL_OK );
216
242
243
+ if (space == TB_CFG_HOPS )
244
+ long_fmt_len = 4 ;
245
+ else
246
+ long_fmt_len = 5 ;
247
+
217
248
line = buf ;
218
- while (parse_line (& line , & offset , & val , 2 , 5 )) {
219
- if (port )
220
- ret = tb_port_write (port , & val , TB_CFG_PORT , offset , 1 );
221
- else
249
+ while (parse_line (& line , & offset , & val , 2 , long_fmt_len )) {
250
+ if (port ) {
251
+ if (space == TB_CFG_HOPS )
252
+ ret = path_write_one (port , val , offset );
253
+ else
254
+ ret = tb_port_write (port , & val , space , offset , 1 );
255
+ } else {
222
256
ret = tb_sw_write (sw , & val , TB_CFG_SWITCH , offset , 1 );
257
+ }
223
258
if (ret )
224
259
break ;
225
260
}
@@ -240,7 +275,16 @@ static ssize_t port_regs_write(struct file *file, const char __user *user_buf,
240
275
struct seq_file * s = file -> private_data ;
241
276
struct tb_port * port = s -> private ;
242
277
243
- return regs_write (port -> sw , port , user_buf , count , ppos );
278
+ return regs_write (port -> sw , port , TB_CFG_PORT , user_buf , count , ppos );
279
+ }
280
+
281
+ static ssize_t path_write (struct file * file , const char __user * user_buf ,
282
+ size_t count , loff_t * ppos )
283
+ {
284
+ struct seq_file * s = file -> private_data ;
285
+ struct tb_port * port = s -> private ;
286
+
287
+ return regs_write (port -> sw , port , TB_CFG_HOPS , user_buf , count , ppos );
244
288
}
245
289
246
290
static ssize_t switch_regs_write (struct file * file , const char __user * user_buf ,
@@ -249,7 +293,7 @@ static ssize_t switch_regs_write(struct file *file, const char __user *user_buf,
249
293
struct seq_file * s = file -> private_data ;
250
294
struct tb_switch * sw = s -> private ;
251
295
252
- return regs_write (sw , NULL , user_buf , count , ppos );
296
+ return regs_write (sw , NULL , TB_CFG_SWITCH , user_buf , count , ppos );
253
297
}
254
298
255
299
static bool parse_sb_line (char * * line , u8 * reg , u8 * data , size_t data_size ,
@@ -401,6 +445,7 @@ static ssize_t retimer_sb_regs_write(struct file *file,
401
445
#define DEBUGFS_MODE 0600
402
446
#else
403
447
#define port_regs_write NULL
448
+ #define path_write NULL
404
449
#define switch_regs_write NULL
405
450
#define port_sb_regs_write NULL
406
451
#define retimer_sb_regs_write NULL
@@ -2243,7 +2288,7 @@ static int path_show(struct seq_file *s, void *not_used)
2243
2288
2244
2289
return ret ;
2245
2290
}
2246
- DEBUGFS_ATTR_RO (path );
2291
+ DEBUGFS_ATTR_RW (path );
2247
2292
2248
2293
static int counter_set_regs_show (struct tb_port * port , struct seq_file * s ,
2249
2294
int counter )
0 commit comments