1 // SPDX-License-Identifier: GPL-2.0+
3 // Copyright(c) 2013 Mauro Carvalho Chehab
5 #include "smscoreapi.h"
7 #include <linux/module.h>
8 #include <linux/slab.h>
9 #include <linux/init.h>
10 #include <linux/debugfs.h>
11 #include <linux/spinlock.h>
12 #include <linux/usb.h>
14 #include <media/dmxdev.h>
15 #include <media/dvbdev.h>
16 #include <media/dvb_demux.h>
17 #include <media/dvb_frontend.h>
21 static struct dentry
*smsdvb_debugfs_usb_root
;
23 struct smsdvb_debugfs
{
27 char stats_data
[PAGE_SIZE
];
31 wait_queue_head_t stats_queue
;
34 static void smsdvb_print_dvb_stats(struct smsdvb_debugfs
*debug_data
,
40 spin_lock(&debug_data
->lock
);
41 if (debug_data
->stats_count
) {
42 spin_unlock(&debug_data
->lock
);
46 buf
= debug_data
->stats_data
;
48 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
49 "is_rf_locked = %d\n", p
->is_rf_locked
);
50 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
51 "is_demod_locked = %d\n", p
->is_demod_locked
);
52 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
53 "is_external_lna_on = %d\n", p
->is_external_lna_on
);
54 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
55 "SNR = %d\n", p
->SNR
);
56 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
57 "ber = %d\n", p
->ber
);
58 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
59 "FIB_CRC = %d\n", p
->FIB_CRC
);
60 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
61 "ts_per = %d\n", p
->ts_per
);
62 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
63 "MFER = %d\n", p
->MFER
);
64 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
65 "RSSI = %d\n", p
->RSSI
);
66 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
67 "in_band_pwr = %d\n", p
->in_band_pwr
);
68 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
69 "carrier_offset = %d\n", p
->carrier_offset
);
70 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
71 "modem_state = %d\n", p
->modem_state
);
72 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
73 "frequency = %d\n", p
->frequency
);
74 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
75 "bandwidth = %d\n", p
->bandwidth
);
76 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
77 "transmission_mode = %d\n", p
->transmission_mode
);
78 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
79 "modem_state = %d\n", p
->modem_state
);
80 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
81 "guard_interval = %d\n", p
->guard_interval
);
82 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
83 "code_rate = %d\n", p
->code_rate
);
84 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
85 "lp_code_rate = %d\n", p
->lp_code_rate
);
86 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
87 "hierarchy = %d\n", p
->hierarchy
);
88 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
89 "constellation = %d\n", p
->constellation
);
90 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
91 "burst_size = %d\n", p
->burst_size
);
92 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
93 "burst_duration = %d\n", p
->burst_duration
);
94 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
95 "burst_cycle_time = %d\n", p
->burst_cycle_time
);
96 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
97 "calc_burst_cycle_time = %d\n",
98 p
->calc_burst_cycle_time
);
99 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
100 "num_of_rows = %d\n", p
->num_of_rows
);
101 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
102 "num_of_padd_cols = %d\n", p
->num_of_padd_cols
);
103 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
104 "num_of_punct_cols = %d\n", p
->num_of_punct_cols
);
105 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
106 "error_ts_packets = %d\n", p
->error_ts_packets
);
107 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
108 "total_ts_packets = %d\n", p
->total_ts_packets
);
109 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
110 "num_of_valid_mpe_tlbs = %d\n", p
->num_of_valid_mpe_tlbs
);
111 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
112 "num_of_invalid_mpe_tlbs = %d\n", p
->num_of_invalid_mpe_tlbs
);
113 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
114 "num_of_corrected_mpe_tlbs = %d\n", p
->num_of_corrected_mpe_tlbs
);
115 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
116 "ber_error_count = %d\n", p
->ber_error_count
);
117 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
118 "ber_bit_count = %d\n", p
->ber_bit_count
);
119 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
120 "sms_to_host_tx_errors = %d\n", p
->sms_to_host_tx_errors
);
121 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
122 "pre_ber = %d\n", p
->pre_ber
);
123 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
124 "cell_id = %d\n", p
->cell_id
);
125 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
126 "dvbh_srv_ind_hp = %d\n", p
->dvbh_srv_ind_hp
);
127 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
128 "dvbh_srv_ind_lp = %d\n", p
->dvbh_srv_ind_lp
);
129 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
130 "num_mpe_received = %d\n", p
->num_mpe_received
);
132 debug_data
->stats_count
= n
;
133 spin_unlock(&debug_data
->lock
);
134 wake_up(&debug_data
->stats_queue
);
137 static void smsdvb_print_isdb_stats(struct smsdvb_debugfs
*debug_data
,
138 struct sms_isdbt_stats
*p
)
143 spin_lock(&debug_data
->lock
);
144 if (debug_data
->stats_count
) {
145 spin_unlock(&debug_data
->lock
);
149 buf
= debug_data
->stats_data
;
151 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
152 "statistics_type = %d\t", p
->statistics_type
);
153 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
154 "full_size = %d\n", p
->full_size
);
156 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
157 "is_rf_locked = %d\t\t", p
->is_rf_locked
);
158 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
159 "is_demod_locked = %d\t", p
->is_demod_locked
);
160 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
161 "is_external_lna_on = %d\n", p
->is_external_lna_on
);
162 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
163 "SNR = %d dB\t\t", p
->SNR
);
164 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
165 "RSSI = %d dBm\t\t", p
->RSSI
);
166 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
167 "in_band_pwr = %d dBm\n", p
->in_band_pwr
);
168 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
169 "carrier_offset = %d\t", p
->carrier_offset
);
170 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
171 "bandwidth = %d\t\t", p
->bandwidth
);
172 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
173 "frequency = %d Hz\n", p
->frequency
);
174 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
175 "transmission_mode = %d\t", p
->transmission_mode
);
176 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
177 "modem_state = %d\t\t", p
->modem_state
);
178 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
179 "guard_interval = %d\n", p
->guard_interval
);
180 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
181 "system_type = %d\t\t", p
->system_type
);
182 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
183 "partial_reception = %d\t", p
->partial_reception
);
184 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
185 "num_of_layers = %d\n", p
->num_of_layers
);
186 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
187 "sms_to_host_tx_errors = %d\n", p
->sms_to_host_tx_errors
);
189 for (i
= 0; i
< 3; i
++) {
190 if (p
->layer_info
[i
].number_of_segments
< 1 ||
191 p
->layer_info
[i
].number_of_segments
> 13)
194 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
, "\nLayer %d\n", i
);
195 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
, "\tcode_rate = %d\t",
196 p
->layer_info
[i
].code_rate
);
197 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
, "constellation = %d\n",
198 p
->layer_info
[i
].constellation
);
199 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
, "\tber = %-5d\t",
200 p
->layer_info
[i
].ber
);
201 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
202 "\tber_error_count = %-5d\t",
203 p
->layer_info
[i
].ber_error_count
);
204 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
, "ber_bit_count = %-5d\n",
205 p
->layer_info
[i
].ber_bit_count
);
206 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
, "\tpre_ber = %-5d\t",
207 p
->layer_info
[i
].pre_ber
);
208 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
, "\tts_per = %-5d\n",
209 p
->layer_info
[i
].ts_per
);
210 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
211 "\terror_ts_packets = %-5d\t",
212 p
->layer_info
[i
].error_ts_packets
);
213 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
214 "total_ts_packets = %-5d\t",
215 p
->layer_info
[i
].total_ts_packets
);
216 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
, "ti_ldepth_i = %d\n",
217 p
->layer_info
[i
].ti_ldepth_i
);
218 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
219 "\tnumber_of_segments = %d\t",
220 p
->layer_info
[i
].number_of_segments
);
221 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
, "tmcc_errors = %d\n",
222 p
->layer_info
[i
].tmcc_errors
);
225 debug_data
->stats_count
= n
;
226 spin_unlock(&debug_data
->lock
);
227 wake_up(&debug_data
->stats_queue
);
230 static void smsdvb_print_isdb_stats_ex(struct smsdvb_debugfs
*debug_data
,
231 struct sms_isdbt_stats_ex
*p
)
236 spin_lock(&debug_data
->lock
);
237 if (debug_data
->stats_count
) {
238 spin_unlock(&debug_data
->lock
);
242 buf
= debug_data
->stats_data
;
244 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
245 "statistics_type = %d\t", p
->statistics_type
);
246 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
247 "full_size = %d\n", p
->full_size
);
249 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
250 "is_rf_locked = %d\t\t", p
->is_rf_locked
);
251 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
252 "is_demod_locked = %d\t", p
->is_demod_locked
);
253 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
254 "is_external_lna_on = %d\n", p
->is_external_lna_on
);
255 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
256 "SNR = %d dB\t\t", p
->SNR
);
257 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
258 "RSSI = %d dBm\t\t", p
->RSSI
);
259 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
260 "in_band_pwr = %d dBm\n", p
->in_band_pwr
);
261 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
262 "carrier_offset = %d\t", p
->carrier_offset
);
263 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
264 "bandwidth = %d\t\t", p
->bandwidth
);
265 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
266 "frequency = %d Hz\n", p
->frequency
);
267 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
268 "transmission_mode = %d\t", p
->transmission_mode
);
269 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
270 "modem_state = %d\t\t", p
->modem_state
);
271 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
272 "guard_interval = %d\n", p
->guard_interval
);
273 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
274 "system_type = %d\t\t", p
->system_type
);
275 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
276 "partial_reception = %d\t", p
->partial_reception
);
277 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
278 "num_of_layers = %d\n", p
->num_of_layers
);
279 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
, "segment_number = %d\t",
281 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
, "tune_bw = %d\n",
284 for (i
= 0; i
< 3; i
++) {
285 if (p
->layer_info
[i
].number_of_segments
< 1 ||
286 p
->layer_info
[i
].number_of_segments
> 13)
289 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
, "\nLayer %d\n", i
);
290 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
, "\tcode_rate = %d\t",
291 p
->layer_info
[i
].code_rate
);
292 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
, "constellation = %d\n",
293 p
->layer_info
[i
].constellation
);
294 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
, "\tber = %-5d\t",
295 p
->layer_info
[i
].ber
);
296 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
297 "\tber_error_count = %-5d\t",
298 p
->layer_info
[i
].ber_error_count
);
299 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
, "ber_bit_count = %-5d\n",
300 p
->layer_info
[i
].ber_bit_count
);
301 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
, "\tpre_ber = %-5d\t",
302 p
->layer_info
[i
].pre_ber
);
303 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
, "\tts_per = %-5d\n",
304 p
->layer_info
[i
].ts_per
);
305 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
306 "\terror_ts_packets = %-5d\t",
307 p
->layer_info
[i
].error_ts_packets
);
308 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
309 "total_ts_packets = %-5d\t",
310 p
->layer_info
[i
].total_ts_packets
);
311 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
, "ti_ldepth_i = %d\n",
312 p
->layer_info
[i
].ti_ldepth_i
);
313 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
,
314 "\tnumber_of_segments = %d\t",
315 p
->layer_info
[i
].number_of_segments
);
316 n
+= scnprintf(&buf
[n
], PAGE_SIZE
- n
, "tmcc_errors = %d\n",
317 p
->layer_info
[i
].tmcc_errors
);
321 debug_data
->stats_count
= n
;
322 spin_unlock(&debug_data
->lock
);
324 wake_up(&debug_data
->stats_queue
);
327 static int smsdvb_stats_open(struct inode
*inode
, struct file
*file
)
329 struct smsdvb_client_t
*client
= inode
->i_private
;
330 struct smsdvb_debugfs
*debug_data
= client
->debug_data
;
332 kref_get(&debug_data
->refcount
);
334 spin_lock(&debug_data
->lock
);
335 debug_data
->stats_count
= 0;
336 debug_data
->stats_was_read
= false;
337 spin_unlock(&debug_data
->lock
);
339 file
->private_data
= debug_data
;
344 static void smsdvb_debugfs_data_release(struct kref
*ref
)
346 struct smsdvb_debugfs
*debug_data
;
348 debug_data
= container_of(ref
, struct smsdvb_debugfs
, refcount
);
352 static int smsdvb_stats_wait_read(struct smsdvb_debugfs
*debug_data
)
356 spin_lock(&debug_data
->lock
);
358 if (debug_data
->stats_was_read
)
361 rc
= debug_data
->stats_count
;
364 spin_unlock(&debug_data
->lock
);
368 static __poll_t
smsdvb_stats_poll(struct file
*file
, poll_table
*wait
)
370 struct smsdvb_debugfs
*debug_data
= file
->private_data
;
373 kref_get(&debug_data
->refcount
);
375 poll_wait(file
, &debug_data
->stats_queue
, wait
);
377 rc
= smsdvb_stats_wait_read(debug_data
);
378 kref_put(&debug_data
->refcount
, smsdvb_debugfs_data_release
);
380 return rc
> 0 ? EPOLLIN
| EPOLLRDNORM
: 0;
383 static ssize_t
smsdvb_stats_read(struct file
*file
, char __user
*user_buf
,
384 size_t nbytes
, loff_t
*ppos
)
387 struct smsdvb_debugfs
*debug_data
= file
->private_data
;
389 kref_get(&debug_data
->refcount
);
391 if (file
->f_flags
& O_NONBLOCK
) {
392 rc
= smsdvb_stats_wait_read(debug_data
);
398 rc
= wait_event_interruptible(debug_data
->stats_queue
,
399 smsdvb_stats_wait_read(debug_data
));
404 if (debug_data
->stats_was_read
) {
409 len
= debug_data
->stats_count
- *ppos
;
411 rc
= simple_read_from_buffer(user_buf
, nbytes
, ppos
,
412 debug_data
->stats_data
, len
);
416 if (*ppos
>= debug_data
->stats_count
) {
417 spin_lock(&debug_data
->lock
);
418 debug_data
->stats_was_read
= true;
419 spin_unlock(&debug_data
->lock
);
422 kref_put(&debug_data
->refcount
, smsdvb_debugfs_data_release
);
426 static int smsdvb_stats_release(struct inode
*inode
, struct file
*file
)
428 struct smsdvb_debugfs
*debug_data
= file
->private_data
;
430 spin_lock(&debug_data
->lock
);
431 debug_data
->stats_was_read
= true; /* return EOF to read() */
432 spin_unlock(&debug_data
->lock
);
433 wake_up_interruptible_sync(&debug_data
->stats_queue
);
435 kref_put(&debug_data
->refcount
, smsdvb_debugfs_data_release
);
436 file
->private_data
= NULL
;
441 static const struct file_operations debugfs_stats_ops
= {
442 .open
= smsdvb_stats_open
,
443 .poll
= smsdvb_stats_poll
,
444 .read
= smsdvb_stats_read
,
445 .release
= smsdvb_stats_release
,
446 .llseek
= generic_file_llseek
,
450 * Functions used by smsdvb, in order to create the interfaces
453 int smsdvb_debugfs_create(struct smsdvb_client_t
*client
)
455 struct smscore_device_t
*coredev
= client
->coredev
;
457 struct smsdvb_debugfs
*debug_data
;
459 if (!smsdvb_debugfs_usb_root
|| !coredev
->is_usb_device
)
462 client
->debugfs
= debugfs_create_dir(coredev
->devpath
,
463 smsdvb_debugfs_usb_root
);
464 if (IS_ERR_OR_NULL(client
->debugfs
)) {
465 pr_info("Unable to create debugfs %s directory.\n",
470 d
= debugfs_create_file("stats", S_IRUGO
| S_IWUSR
, client
->debugfs
,
471 client
, &debugfs_stats_ops
);
473 debugfs_remove(client
->debugfs
);
477 debug_data
= kzalloc(sizeof(*client
->debug_data
), GFP_KERNEL
);
481 client
->debug_data
= debug_data
;
482 client
->prt_dvb_stats
= smsdvb_print_dvb_stats
;
483 client
->prt_isdb_stats
= smsdvb_print_isdb_stats
;
484 client
->prt_isdb_stats_ex
= smsdvb_print_isdb_stats_ex
;
486 init_waitqueue_head(&debug_data
->stats_queue
);
487 spin_lock_init(&debug_data
->lock
);
488 kref_init(&debug_data
->refcount
);
493 void smsdvb_debugfs_release(struct smsdvb_client_t
*client
)
495 if (!client
->debugfs
)
498 client
->prt_dvb_stats
= NULL
;
499 client
->prt_isdb_stats
= NULL
;
500 client
->prt_isdb_stats_ex
= NULL
;
502 debugfs_remove_recursive(client
->debugfs
);
503 kref_put(&client
->debug_data
->refcount
, smsdvb_debugfs_data_release
);
505 client
->debug_data
= NULL
;
506 client
->debugfs
= NULL
;
509 void smsdvb_debugfs_register(void)
514 * FIXME: This was written to debug Siano USB devices. So, it creates
515 * the debugfs node under <debugfs>/usb.
516 * A similar logic would be needed for Siano sdio devices, but, in that
517 * case, usb_debug_root is not a good choice.
519 * Perhaps the right fix here would be to create another sysfs root
520 * node for sdio-based boards, but this may need some logic at sdio
523 d
= debugfs_create_dir("smsdvb", usb_debug_root
);
524 if (IS_ERR_OR_NULL(d
)) {
525 pr_err("Couldn't create sysfs node for smsdvb\n");
528 smsdvb_debugfs_usb_root
= d
;
531 void smsdvb_debugfs_unregister(void)
533 if (!smsdvb_debugfs_usb_root
)
535 debugfs_remove_recursive(smsdvb_debugfs_usb_root
);
536 smsdvb_debugfs_usb_root
= NULL
;