1 /***********************************************************************
3 * Copyright(c) 2013 Mauro Carvalho Chehab <mchehab@redhat.com>
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 ***********************************************************************/
20 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
22 #include <linux/module.h>
23 #include <linux/slab.h>
24 #include <linux/init.h>
25 #include <linux/debugfs.h>
26 #include <linux/spinlock.h>
27 #include <linux/usb.h>
31 #include "dvb_demux.h"
32 #include "dvb_frontend.h"
34 #include "smscoreapi.h"
38 static struct dentry
*smsdvb_debugfs_usb_root
;
40 struct smsdvb_debugfs
{
44 char stats_data
[PAGE_SIZE
];
48 wait_queue_head_t stats_queue
;
51 static void smsdvb_print_dvb_stats(struct smsdvb_debugfs
*debug_data
,
57 spin_lock(&debug_data
->lock
);
58 if (debug_data
->stats_count
) {
59 spin_unlock(&debug_data
->lock
);
63 buf
= debug_data
->stats_data
;
65 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
66 "is_rf_locked = %d\n", p
->is_rf_locked
);
67 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
68 "is_demod_locked = %d\n", p
->is_demod_locked
);
69 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
70 "is_external_lna_on = %d\n", p
->is_external_lna_on
);
71 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
72 "SNR = %d\n", p
->SNR
);
73 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
74 "ber = %d\n", p
->ber
);
75 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
76 "FIB_CRC = %d\n", p
->FIB_CRC
);
77 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
78 "ts_per = %d\n", p
->ts_per
);
79 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
80 "MFER = %d\n", p
->MFER
);
81 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
82 "RSSI = %d\n", p
->RSSI
);
83 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
84 "in_band_pwr = %d\n", p
->in_band_pwr
);
85 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
86 "carrier_offset = %d\n", p
->carrier_offset
);
87 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
88 "modem_state = %d\n", p
->modem_state
);
89 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
90 "frequency = %d\n", p
->frequency
);
91 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
92 "bandwidth = %d\n", p
->bandwidth
);
93 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
94 "transmission_mode = %d\n", p
->transmission_mode
);
95 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
96 "modem_state = %d\n", p
->modem_state
);
97 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
98 "guard_interval = %d\n", p
->guard_interval
);
99 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
100 "code_rate = %d\n", p
->code_rate
);
101 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
102 "lp_code_rate = %d\n", p
->lp_code_rate
);
103 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
104 "hierarchy = %d\n", p
->hierarchy
);
105 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
106 "constellation = %d\n", p
->constellation
);
107 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
108 "burst_size = %d\n", p
->burst_size
);
109 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
110 "burst_duration = %d\n", p
->burst_duration
);
111 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
112 "burst_cycle_time = %d\n", p
->burst_cycle_time
);
113 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
114 "calc_burst_cycle_time = %d\n",
115 p
->calc_burst_cycle_time
);
116 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
117 "num_of_rows = %d\n", p
->num_of_rows
);
118 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
119 "num_of_padd_cols = %d\n", p
->num_of_padd_cols
);
120 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
121 "num_of_punct_cols = %d\n", p
->num_of_punct_cols
);
122 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
123 "error_ts_packets = %d\n", p
->error_ts_packets
);
124 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
125 "total_ts_packets = %d\n", p
->total_ts_packets
);
126 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
127 "num_of_valid_mpe_tlbs = %d\n", p
->num_of_valid_mpe_tlbs
);
128 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
129 "num_of_invalid_mpe_tlbs = %d\n", p
->num_of_invalid_mpe_tlbs
);
130 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
131 "num_of_corrected_mpe_tlbs = %d\n", p
->num_of_corrected_mpe_tlbs
);
132 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
133 "ber_error_count = %d\n", p
->ber_error_count
);
134 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
135 "ber_bit_count = %d\n", p
->ber_bit_count
);
136 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
137 "sms_to_host_tx_errors = %d\n", p
->sms_to_host_tx_errors
);
138 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
139 "pre_ber = %d\n", p
->pre_ber
);
140 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
141 "cell_id = %d\n", p
->cell_id
);
142 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
143 "dvbh_srv_ind_hp = %d\n", p
->dvbh_srv_ind_hp
);
144 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
145 "dvbh_srv_ind_lp = %d\n", p
->dvbh_srv_ind_lp
);
146 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
147 "num_mpe_received = %d\n", p
->num_mpe_received
);
149 debug_data
->stats_count
= n
;
150 spin_unlock(&debug_data
->lock
);
151 wake_up(&debug_data
->stats_queue
);
154 static void smsdvb_print_isdb_stats(struct smsdvb_debugfs
*debug_data
,
155 struct sms_isdbt_stats
*p
)
160 spin_lock(&debug_data
->lock
);
161 if (debug_data
->stats_count
) {
162 spin_unlock(&debug_data
->lock
);
166 buf
= debug_data
->stats_data
;
168 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
169 "statistics_type = %d\t", p
->statistics_type
);
170 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
171 "full_size = %d\n", p
->full_size
);
173 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
174 "is_rf_locked = %d\t\t", p
->is_rf_locked
);
175 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
176 "is_demod_locked = %d\t", p
->is_demod_locked
);
177 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
178 "is_external_lna_on = %d\n", p
->is_external_lna_on
);
179 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
180 "SNR = %d dB\t\t", p
->SNR
);
181 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
182 "RSSI = %d dBm\t\t", p
->RSSI
);
183 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
184 "in_band_pwr = %d dBm\n", p
->in_band_pwr
);
185 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
186 "carrier_offset = %d\t", p
->carrier_offset
);
187 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
188 "bandwidth = %d\t\t", p
->bandwidth
);
189 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
190 "frequency = %d Hz\n", p
->frequency
);
191 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
192 "transmission_mode = %d\t", p
->transmission_mode
);
193 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
194 "modem_state = %d\t\t", p
->modem_state
);
195 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
196 "guard_interval = %d\n", p
->guard_interval
);
197 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
198 "system_type = %d\t\t", p
->system_type
);
199 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
200 "partial_reception = %d\t", p
->partial_reception
);
201 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
202 "num_of_layers = %d\n", p
->num_of_layers
);
203 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
204 "sms_to_host_tx_errors = %d\n", p
->sms_to_host_tx_errors
);
206 for (i
= 0; i
< 3; i
++) {
207 if (p
->layer_info
[i
].number_of_segments
< 1 ||
208 p
->layer_info
[i
].number_of_segments
> 13)
211 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
, "\nLayer %d\n", i
);
212 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
, "\tcode_rate = %d\t",
213 p
->layer_info
[i
].code_rate
);
214 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
, "constellation = %d\n",
215 p
->layer_info
[i
].constellation
);
216 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
, "\tber = %-5d\t",
217 p
->layer_info
[i
].ber
);
218 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
, "\tber_error_count = %-5d\t",
219 p
->layer_info
[i
].ber_error_count
);
220 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
, "ber_bit_count = %-5d\n",
221 p
->layer_info
[i
].ber_bit_count
);
222 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
, "\tpre_ber = %-5d\t",
223 p
->layer_info
[i
].pre_ber
);
224 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
, "\tts_per = %-5d\n",
225 p
->layer_info
[i
].ts_per
);
226 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
, "\terror_ts_packets = %-5d\t",
227 p
->layer_info
[i
].error_ts_packets
);
228 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
, "total_ts_packets = %-5d\t",
229 p
->layer_info
[i
].total_ts_packets
);
230 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
, "ti_ldepth_i = %d\n",
231 p
->layer_info
[i
].ti_ldepth_i
);
232 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
233 "\tnumber_of_segments = %d\t",
234 p
->layer_info
[i
].number_of_segments
);
235 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
, "tmcc_errors = %d\n",
236 p
->layer_info
[i
].tmcc_errors
);
239 debug_data
->stats_count
= n
;
240 spin_unlock(&debug_data
->lock
);
241 wake_up(&debug_data
->stats_queue
);
244 static void smsdvb_print_isdb_stats_ex(struct smsdvb_debugfs
*debug_data
,
245 struct sms_isdbt_stats_ex
*p
)
250 spin_lock(&debug_data
->lock
);
251 if (debug_data
->stats_count
) {
252 spin_unlock(&debug_data
->lock
);
256 buf
= debug_data
->stats_data
;
258 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
259 "statistics_type = %d\t", p
->statistics_type
);
260 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
261 "full_size = %d\n", p
->full_size
);
263 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
264 "is_rf_locked = %d\t\t", p
->is_rf_locked
);
265 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
266 "is_demod_locked = %d\t", p
->is_demod_locked
);
267 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
268 "is_external_lna_on = %d\n", p
->is_external_lna_on
);
269 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
270 "SNR = %d dB\t\t", p
->SNR
);
271 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
272 "RSSI = %d dBm\t\t", p
->RSSI
);
273 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
274 "in_band_pwr = %d dBm\n", p
->in_band_pwr
);
275 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
276 "carrier_offset = %d\t", p
->carrier_offset
);
277 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
278 "bandwidth = %d\t\t", p
->bandwidth
);
279 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
280 "frequency = %d Hz\n", p
->frequency
);
281 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
282 "transmission_mode = %d\t", p
->transmission_mode
);
283 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
284 "modem_state = %d\t\t", p
->modem_state
);
285 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
286 "guard_interval = %d\n", p
->guard_interval
);
287 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
288 "system_type = %d\t\t", p
->system_type
);
289 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
290 "partial_reception = %d\t", p
->partial_reception
);
291 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
292 "num_of_layers = %d\n", p
->num_of_layers
);
293 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
, "segment_number = %d\t",
295 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
, "tune_bw = %d\n",
298 for (i
= 0; i
< 3; i
++) {
299 if (p
->layer_info
[i
].number_of_segments
< 1 ||
300 p
->layer_info
[i
].number_of_segments
> 13)
303 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
, "\nLayer %d\n", i
);
304 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
, "\tcode_rate = %d\t",
305 p
->layer_info
[i
].code_rate
);
306 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
, "constellation = %d\n",
307 p
->layer_info
[i
].constellation
);
308 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
, "\tber = %-5d\t",
309 p
->layer_info
[i
].ber
);
310 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
, "\tber_error_count = %-5d\t",
311 p
->layer_info
[i
].ber_error_count
);
312 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
, "ber_bit_count = %-5d\n",
313 p
->layer_info
[i
].ber_bit_count
);
314 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
, "\tpre_ber = %-5d\t",
315 p
->layer_info
[i
].pre_ber
);
316 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
, "\tts_per = %-5d\n",
317 p
->layer_info
[i
].ts_per
);
318 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
, "\terror_ts_packets = %-5d\t",
319 p
->layer_info
[i
].error_ts_packets
);
320 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
, "total_ts_packets = %-5d\t",
321 p
->layer_info
[i
].total_ts_packets
);
322 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
, "ti_ldepth_i = %d\n",
323 p
->layer_info
[i
].ti_ldepth_i
);
324 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
,
325 "\tnumber_of_segments = %d\t",
326 p
->layer_info
[i
].number_of_segments
);
327 n
+= snprintf(&buf
[n
], PAGE_SIZE
- n
, "tmcc_errors = %d\n",
328 p
->layer_info
[i
].tmcc_errors
);
332 debug_data
->stats_count
= n
;
333 spin_unlock(&debug_data
->lock
);
335 wake_up(&debug_data
->stats_queue
);
338 static int smsdvb_stats_open(struct inode
*inode
, struct file
*file
)
340 struct smsdvb_client_t
*client
= inode
->i_private
;
341 struct smsdvb_debugfs
*debug_data
= client
->debug_data
;
343 kref_get(&debug_data
->refcount
);
345 spin_lock(&debug_data
->lock
);
346 debug_data
->stats_count
= 0;
347 debug_data
->stats_was_read
= false;
348 spin_unlock(&debug_data
->lock
);
350 file
->private_data
= debug_data
;
355 static void smsdvb_debugfs_data_release(struct kref
*ref
)
357 struct smsdvb_debugfs
*debug_data
;
359 debug_data
= container_of(ref
, struct smsdvb_debugfs
, refcount
);
363 static int smsdvb_stats_wait_read(struct smsdvb_debugfs
*debug_data
)
367 spin_lock(&debug_data
->lock
);
369 if (debug_data
->stats_was_read
)
372 rc
= debug_data
->stats_count
;
375 spin_unlock(&debug_data
->lock
);
379 static unsigned int smsdvb_stats_poll(struct file
*file
, poll_table
*wait
)
381 struct smsdvb_debugfs
*debug_data
= file
->private_data
;
384 kref_get(&debug_data
->refcount
);
386 poll_wait(file
, &debug_data
->stats_queue
, wait
);
388 rc
= smsdvb_stats_wait_read(debug_data
);
390 rc
= POLLIN
| POLLRDNORM
;
392 kref_put(&debug_data
->refcount
, smsdvb_debugfs_data_release
);
397 static ssize_t
smsdvb_stats_read(struct file
*file
, char __user
*user_buf
,
398 size_t nbytes
, loff_t
*ppos
)
401 struct smsdvb_debugfs
*debug_data
= file
->private_data
;
403 kref_get(&debug_data
->refcount
);
405 if (file
->f_flags
& O_NONBLOCK
) {
406 rc
= smsdvb_stats_wait_read(debug_data
);
412 rc
= wait_event_interruptible(debug_data
->stats_queue
,
413 smsdvb_stats_wait_read(debug_data
));
418 if (debug_data
->stats_was_read
) {
423 len
= debug_data
->stats_count
- *ppos
;
425 rc
= simple_read_from_buffer(user_buf
, nbytes
, ppos
,
426 debug_data
->stats_data
, len
);
430 if (*ppos
>= debug_data
->stats_count
) {
431 spin_lock(&debug_data
->lock
);
432 debug_data
->stats_was_read
= true;
433 spin_unlock(&debug_data
->lock
);
436 kref_put(&debug_data
->refcount
, smsdvb_debugfs_data_release
);
440 static int smsdvb_stats_release(struct inode
*inode
, struct file
*file
)
442 struct smsdvb_debugfs
*debug_data
= file
->private_data
;
444 spin_lock(&debug_data
->lock
);
445 debug_data
->stats_was_read
= true; /* return EOF to read() */
446 spin_unlock(&debug_data
->lock
);
447 wake_up_interruptible_sync(&debug_data
->stats_queue
);
449 kref_put(&debug_data
->refcount
, smsdvb_debugfs_data_release
);
450 file
->private_data
= NULL
;
455 static const struct file_operations debugfs_stats_ops
= {
456 .open
= smsdvb_stats_open
,
457 .poll
= smsdvb_stats_poll
,
458 .read
= smsdvb_stats_read
,
459 .release
= smsdvb_stats_release
,
460 .llseek
= generic_file_llseek
,
464 * Functions used by smsdvb, in order to create the interfaces
467 int smsdvb_debugfs_create(struct smsdvb_client_t
*client
)
469 struct smscore_device_t
*coredev
= client
->coredev
;
471 struct smsdvb_debugfs
*debug_data
;
473 if (!smsdvb_debugfs_usb_root
|| !coredev
->is_usb_device
)
476 client
->debugfs
= debugfs_create_dir(coredev
->devpath
,
477 smsdvb_debugfs_usb_root
);
478 if (IS_ERR_OR_NULL(client
->debugfs
)) {
479 pr_info("Unable to create debugfs %s directory.\n",
484 d
= debugfs_create_file("stats", S_IRUGO
| S_IWUSR
, client
->debugfs
,
485 client
, &debugfs_stats_ops
);
487 debugfs_remove(client
->debugfs
);
491 debug_data
= kzalloc(sizeof(*client
->debug_data
), GFP_KERNEL
);
495 client
->debug_data
= debug_data
;
496 client
->prt_dvb_stats
= smsdvb_print_dvb_stats
;
497 client
->prt_isdb_stats
= smsdvb_print_isdb_stats
;
498 client
->prt_isdb_stats_ex
= smsdvb_print_isdb_stats_ex
;
500 init_waitqueue_head(&debug_data
->stats_queue
);
501 spin_lock_init(&debug_data
->lock
);
502 kref_init(&debug_data
->refcount
);
507 void smsdvb_debugfs_release(struct smsdvb_client_t
*client
)
509 if (!client
->debugfs
)
512 client
->prt_dvb_stats
= NULL
;
513 client
->prt_isdb_stats
= NULL
;
514 client
->prt_isdb_stats_ex
= NULL
;
516 debugfs_remove_recursive(client
->debugfs
);
517 kref_put(&client
->debug_data
->refcount
, smsdvb_debugfs_data_release
);
519 client
->debug_data
= NULL
;
520 client
->debugfs
= NULL
;
523 int smsdvb_debugfs_register(void)
528 * FIXME: This was written to debug Siano USB devices. So, it creates
529 * the debugfs node under <debugfs>/usb.
530 * A similar logic would be needed for Siano sdio devices, but, in that
531 * case, usb_debug_root is not a good choice.
533 * Perhaps the right fix here would be to create another sysfs root
534 * node for sdio-based boards, but this may need some logic at sdio
537 d
= debugfs_create_dir("smsdvb", usb_debug_root
);
538 if (IS_ERR_OR_NULL(d
)) {
539 sms_err("Couldn't create sysfs node for smsdvb");
542 smsdvb_debugfs_usb_root
= d
;
547 void smsdvb_debugfs_unregister(void)
549 debugfs_remove_recursive(smsdvb_debugfs_usb_root
);
550 smsdvb_debugfs_usb_root
= NULL
;