1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun //
3*4882a593Smuzhiyun // Copyright(c) 2013 Mauro Carvalho Chehab
4*4882a593Smuzhiyun
5*4882a593Smuzhiyun #include "smscoreapi.h"
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include <linux/module.h>
8*4882a593Smuzhiyun #include <linux/slab.h>
9*4882a593Smuzhiyun #include <linux/init.h>
10*4882a593Smuzhiyun #include <linux/debugfs.h>
11*4882a593Smuzhiyun #include <linux/spinlock.h>
12*4882a593Smuzhiyun #include <linux/usb.h>
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun #include <media/dmxdev.h>
15*4882a593Smuzhiyun #include <media/dvbdev.h>
16*4882a593Smuzhiyun #include <media/dvb_demux.h>
17*4882a593Smuzhiyun #include <media/dvb_frontend.h>
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #include "smsdvb.h"
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun static struct dentry *smsdvb_debugfs_usb_root;
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun struct smsdvb_debugfs {
24*4882a593Smuzhiyun struct kref refcount;
25*4882a593Smuzhiyun spinlock_t lock;
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun char stats_data[PAGE_SIZE];
28*4882a593Smuzhiyun unsigned stats_count;
29*4882a593Smuzhiyun bool stats_was_read;
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun wait_queue_head_t stats_queue;
32*4882a593Smuzhiyun };
33*4882a593Smuzhiyun
smsdvb_print_dvb_stats(struct smsdvb_debugfs * debug_data,struct sms_stats * p)34*4882a593Smuzhiyun static void smsdvb_print_dvb_stats(struct smsdvb_debugfs *debug_data,
35*4882a593Smuzhiyun struct sms_stats *p)
36*4882a593Smuzhiyun {
37*4882a593Smuzhiyun int n = 0;
38*4882a593Smuzhiyun char *buf;
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun spin_lock(&debug_data->lock);
41*4882a593Smuzhiyun if (debug_data->stats_count) {
42*4882a593Smuzhiyun spin_unlock(&debug_data->lock);
43*4882a593Smuzhiyun return;
44*4882a593Smuzhiyun }
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun buf = debug_data->stats_data;
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
49*4882a593Smuzhiyun "is_rf_locked = %d\n", p->is_rf_locked);
50*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
51*4882a593Smuzhiyun "is_demod_locked = %d\n", p->is_demod_locked);
52*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
53*4882a593Smuzhiyun "is_external_lna_on = %d\n", p->is_external_lna_on);
54*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
55*4882a593Smuzhiyun "SNR = %d\n", p->SNR);
56*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
57*4882a593Smuzhiyun "ber = %d\n", p->ber);
58*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
59*4882a593Smuzhiyun "FIB_CRC = %d\n", p->FIB_CRC);
60*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
61*4882a593Smuzhiyun "ts_per = %d\n", p->ts_per);
62*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
63*4882a593Smuzhiyun "MFER = %d\n", p->MFER);
64*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
65*4882a593Smuzhiyun "RSSI = %d\n", p->RSSI);
66*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
67*4882a593Smuzhiyun "in_band_pwr = %d\n", p->in_band_pwr);
68*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
69*4882a593Smuzhiyun "carrier_offset = %d\n", p->carrier_offset);
70*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
71*4882a593Smuzhiyun "modem_state = %d\n", p->modem_state);
72*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
73*4882a593Smuzhiyun "frequency = %d\n", p->frequency);
74*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
75*4882a593Smuzhiyun "bandwidth = %d\n", p->bandwidth);
76*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
77*4882a593Smuzhiyun "transmission_mode = %d\n", p->transmission_mode);
78*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
79*4882a593Smuzhiyun "modem_state = %d\n", p->modem_state);
80*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
81*4882a593Smuzhiyun "guard_interval = %d\n", p->guard_interval);
82*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
83*4882a593Smuzhiyun "code_rate = %d\n", p->code_rate);
84*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
85*4882a593Smuzhiyun "lp_code_rate = %d\n", p->lp_code_rate);
86*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
87*4882a593Smuzhiyun "hierarchy = %d\n", p->hierarchy);
88*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
89*4882a593Smuzhiyun "constellation = %d\n", p->constellation);
90*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
91*4882a593Smuzhiyun "burst_size = %d\n", p->burst_size);
92*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
93*4882a593Smuzhiyun "burst_duration = %d\n", p->burst_duration);
94*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
95*4882a593Smuzhiyun "burst_cycle_time = %d\n", p->burst_cycle_time);
96*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
97*4882a593Smuzhiyun "calc_burst_cycle_time = %d\n",
98*4882a593Smuzhiyun p->calc_burst_cycle_time);
99*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
100*4882a593Smuzhiyun "num_of_rows = %d\n", p->num_of_rows);
101*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
102*4882a593Smuzhiyun "num_of_padd_cols = %d\n", p->num_of_padd_cols);
103*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
104*4882a593Smuzhiyun "num_of_punct_cols = %d\n", p->num_of_punct_cols);
105*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
106*4882a593Smuzhiyun "error_ts_packets = %d\n", p->error_ts_packets);
107*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
108*4882a593Smuzhiyun "total_ts_packets = %d\n", p->total_ts_packets);
109*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
110*4882a593Smuzhiyun "num_of_valid_mpe_tlbs = %d\n", p->num_of_valid_mpe_tlbs);
111*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
112*4882a593Smuzhiyun "num_of_invalid_mpe_tlbs = %d\n", p->num_of_invalid_mpe_tlbs);
113*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
114*4882a593Smuzhiyun "num_of_corrected_mpe_tlbs = %d\n", p->num_of_corrected_mpe_tlbs);
115*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
116*4882a593Smuzhiyun "ber_error_count = %d\n", p->ber_error_count);
117*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
118*4882a593Smuzhiyun "ber_bit_count = %d\n", p->ber_bit_count);
119*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
120*4882a593Smuzhiyun "sms_to_host_tx_errors = %d\n", p->sms_to_host_tx_errors);
121*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
122*4882a593Smuzhiyun "pre_ber = %d\n", p->pre_ber);
123*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
124*4882a593Smuzhiyun "cell_id = %d\n", p->cell_id);
125*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
126*4882a593Smuzhiyun "dvbh_srv_ind_hp = %d\n", p->dvbh_srv_ind_hp);
127*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
128*4882a593Smuzhiyun "dvbh_srv_ind_lp = %d\n", p->dvbh_srv_ind_lp);
129*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
130*4882a593Smuzhiyun "num_mpe_received = %d\n", p->num_mpe_received);
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun debug_data->stats_count = n;
133*4882a593Smuzhiyun spin_unlock(&debug_data->lock);
134*4882a593Smuzhiyun wake_up(&debug_data->stats_queue);
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun
smsdvb_print_isdb_stats(struct smsdvb_debugfs * debug_data,struct sms_isdbt_stats * p)137*4882a593Smuzhiyun static void smsdvb_print_isdb_stats(struct smsdvb_debugfs *debug_data,
138*4882a593Smuzhiyun struct sms_isdbt_stats *p)
139*4882a593Smuzhiyun {
140*4882a593Smuzhiyun int i, n = 0;
141*4882a593Smuzhiyun char *buf;
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun spin_lock(&debug_data->lock);
144*4882a593Smuzhiyun if (debug_data->stats_count) {
145*4882a593Smuzhiyun spin_unlock(&debug_data->lock);
146*4882a593Smuzhiyun return;
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun buf = debug_data->stats_data;
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
152*4882a593Smuzhiyun "statistics_type = %d\t", p->statistics_type);
153*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
154*4882a593Smuzhiyun "full_size = %d\n", p->full_size);
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
157*4882a593Smuzhiyun "is_rf_locked = %d\t\t", p->is_rf_locked);
158*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
159*4882a593Smuzhiyun "is_demod_locked = %d\t", p->is_demod_locked);
160*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
161*4882a593Smuzhiyun "is_external_lna_on = %d\n", p->is_external_lna_on);
162*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
163*4882a593Smuzhiyun "SNR = %d dB\t\t", p->SNR);
164*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
165*4882a593Smuzhiyun "RSSI = %d dBm\t\t", p->RSSI);
166*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
167*4882a593Smuzhiyun "in_band_pwr = %d dBm\n", p->in_band_pwr);
168*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
169*4882a593Smuzhiyun "carrier_offset = %d\t", p->carrier_offset);
170*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
171*4882a593Smuzhiyun "bandwidth = %d\t\t", p->bandwidth);
172*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
173*4882a593Smuzhiyun "frequency = %d Hz\n", p->frequency);
174*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
175*4882a593Smuzhiyun "transmission_mode = %d\t", p->transmission_mode);
176*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
177*4882a593Smuzhiyun "modem_state = %d\t\t", p->modem_state);
178*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
179*4882a593Smuzhiyun "guard_interval = %d\n", p->guard_interval);
180*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
181*4882a593Smuzhiyun "system_type = %d\t\t", p->system_type);
182*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
183*4882a593Smuzhiyun "partial_reception = %d\t", p->partial_reception);
184*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
185*4882a593Smuzhiyun "num_of_layers = %d\n", p->num_of_layers);
186*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
187*4882a593Smuzhiyun "sms_to_host_tx_errors = %d\n", p->sms_to_host_tx_errors);
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun for (i = 0; i < 3; i++) {
190*4882a593Smuzhiyun if (p->layer_info[i].number_of_segments < 1 ||
191*4882a593Smuzhiyun p->layer_info[i].number_of_segments > 13)
192*4882a593Smuzhiyun continue;
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n, "\nLayer %d\n", i);
195*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n, "\tcode_rate = %d\t",
196*4882a593Smuzhiyun p->layer_info[i].code_rate);
197*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n, "constellation = %d\n",
198*4882a593Smuzhiyun p->layer_info[i].constellation);
199*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n, "\tber = %-5d\t",
200*4882a593Smuzhiyun p->layer_info[i].ber);
201*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
202*4882a593Smuzhiyun "\tber_error_count = %-5d\t",
203*4882a593Smuzhiyun p->layer_info[i].ber_error_count);
204*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n, "ber_bit_count = %-5d\n",
205*4882a593Smuzhiyun p->layer_info[i].ber_bit_count);
206*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n, "\tpre_ber = %-5d\t",
207*4882a593Smuzhiyun p->layer_info[i].pre_ber);
208*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n, "\tts_per = %-5d\n",
209*4882a593Smuzhiyun p->layer_info[i].ts_per);
210*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
211*4882a593Smuzhiyun "\terror_ts_packets = %-5d\t",
212*4882a593Smuzhiyun p->layer_info[i].error_ts_packets);
213*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
214*4882a593Smuzhiyun "total_ts_packets = %-5d\t",
215*4882a593Smuzhiyun p->layer_info[i].total_ts_packets);
216*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n, "ti_ldepth_i = %d\n",
217*4882a593Smuzhiyun p->layer_info[i].ti_ldepth_i);
218*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
219*4882a593Smuzhiyun "\tnumber_of_segments = %d\t",
220*4882a593Smuzhiyun p->layer_info[i].number_of_segments);
221*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n, "tmcc_errors = %d\n",
222*4882a593Smuzhiyun p->layer_info[i].tmcc_errors);
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun debug_data->stats_count = n;
226*4882a593Smuzhiyun spin_unlock(&debug_data->lock);
227*4882a593Smuzhiyun wake_up(&debug_data->stats_queue);
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun
smsdvb_print_isdb_stats_ex(struct smsdvb_debugfs * debug_data,struct sms_isdbt_stats_ex * p)230*4882a593Smuzhiyun static void smsdvb_print_isdb_stats_ex(struct smsdvb_debugfs *debug_data,
231*4882a593Smuzhiyun struct sms_isdbt_stats_ex *p)
232*4882a593Smuzhiyun {
233*4882a593Smuzhiyun int i, n = 0;
234*4882a593Smuzhiyun char *buf;
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun spin_lock(&debug_data->lock);
237*4882a593Smuzhiyun if (debug_data->stats_count) {
238*4882a593Smuzhiyun spin_unlock(&debug_data->lock);
239*4882a593Smuzhiyun return;
240*4882a593Smuzhiyun }
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun buf = debug_data->stats_data;
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
245*4882a593Smuzhiyun "statistics_type = %d\t", p->statistics_type);
246*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
247*4882a593Smuzhiyun "full_size = %d\n", p->full_size);
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
250*4882a593Smuzhiyun "is_rf_locked = %d\t\t", p->is_rf_locked);
251*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
252*4882a593Smuzhiyun "is_demod_locked = %d\t", p->is_demod_locked);
253*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
254*4882a593Smuzhiyun "is_external_lna_on = %d\n", p->is_external_lna_on);
255*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
256*4882a593Smuzhiyun "SNR = %d dB\t\t", p->SNR);
257*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
258*4882a593Smuzhiyun "RSSI = %d dBm\t\t", p->RSSI);
259*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
260*4882a593Smuzhiyun "in_band_pwr = %d dBm\n", p->in_band_pwr);
261*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
262*4882a593Smuzhiyun "carrier_offset = %d\t", p->carrier_offset);
263*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
264*4882a593Smuzhiyun "bandwidth = %d\t\t", p->bandwidth);
265*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
266*4882a593Smuzhiyun "frequency = %d Hz\n", p->frequency);
267*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
268*4882a593Smuzhiyun "transmission_mode = %d\t", p->transmission_mode);
269*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
270*4882a593Smuzhiyun "modem_state = %d\t\t", p->modem_state);
271*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
272*4882a593Smuzhiyun "guard_interval = %d\n", p->guard_interval);
273*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
274*4882a593Smuzhiyun "system_type = %d\t\t", p->system_type);
275*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
276*4882a593Smuzhiyun "partial_reception = %d\t", p->partial_reception);
277*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
278*4882a593Smuzhiyun "num_of_layers = %d\n", p->num_of_layers);
279*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n, "segment_number = %d\t",
280*4882a593Smuzhiyun p->segment_number);
281*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n, "tune_bw = %d\n",
282*4882a593Smuzhiyun p->tune_bw);
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun for (i = 0; i < 3; i++) {
285*4882a593Smuzhiyun if (p->layer_info[i].number_of_segments < 1 ||
286*4882a593Smuzhiyun p->layer_info[i].number_of_segments > 13)
287*4882a593Smuzhiyun continue;
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n, "\nLayer %d\n", i);
290*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n, "\tcode_rate = %d\t",
291*4882a593Smuzhiyun p->layer_info[i].code_rate);
292*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n, "constellation = %d\n",
293*4882a593Smuzhiyun p->layer_info[i].constellation);
294*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n, "\tber = %-5d\t",
295*4882a593Smuzhiyun p->layer_info[i].ber);
296*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
297*4882a593Smuzhiyun "\tber_error_count = %-5d\t",
298*4882a593Smuzhiyun p->layer_info[i].ber_error_count);
299*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n, "ber_bit_count = %-5d\n",
300*4882a593Smuzhiyun p->layer_info[i].ber_bit_count);
301*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n, "\tpre_ber = %-5d\t",
302*4882a593Smuzhiyun p->layer_info[i].pre_ber);
303*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n, "\tts_per = %-5d\n",
304*4882a593Smuzhiyun p->layer_info[i].ts_per);
305*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
306*4882a593Smuzhiyun "\terror_ts_packets = %-5d\t",
307*4882a593Smuzhiyun p->layer_info[i].error_ts_packets);
308*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
309*4882a593Smuzhiyun "total_ts_packets = %-5d\t",
310*4882a593Smuzhiyun p->layer_info[i].total_ts_packets);
311*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n, "ti_ldepth_i = %d\n",
312*4882a593Smuzhiyun p->layer_info[i].ti_ldepth_i);
313*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n,
314*4882a593Smuzhiyun "\tnumber_of_segments = %d\t",
315*4882a593Smuzhiyun p->layer_info[i].number_of_segments);
316*4882a593Smuzhiyun n += scnprintf(&buf[n], PAGE_SIZE - n, "tmcc_errors = %d\n",
317*4882a593Smuzhiyun p->layer_info[i].tmcc_errors);
318*4882a593Smuzhiyun }
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun debug_data->stats_count = n;
322*4882a593Smuzhiyun spin_unlock(&debug_data->lock);
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun wake_up(&debug_data->stats_queue);
325*4882a593Smuzhiyun }
326*4882a593Smuzhiyun
smsdvb_stats_open(struct inode * inode,struct file * file)327*4882a593Smuzhiyun static int smsdvb_stats_open(struct inode *inode, struct file *file)
328*4882a593Smuzhiyun {
329*4882a593Smuzhiyun struct smsdvb_client_t *client = inode->i_private;
330*4882a593Smuzhiyun struct smsdvb_debugfs *debug_data = client->debug_data;
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun kref_get(&debug_data->refcount);
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun spin_lock(&debug_data->lock);
335*4882a593Smuzhiyun debug_data->stats_count = 0;
336*4882a593Smuzhiyun debug_data->stats_was_read = false;
337*4882a593Smuzhiyun spin_unlock(&debug_data->lock);
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun file->private_data = debug_data;
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun return 0;
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun
smsdvb_debugfs_data_release(struct kref * ref)344*4882a593Smuzhiyun static void smsdvb_debugfs_data_release(struct kref *ref)
345*4882a593Smuzhiyun {
346*4882a593Smuzhiyun struct smsdvb_debugfs *debug_data;
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun debug_data = container_of(ref, struct smsdvb_debugfs, refcount);
349*4882a593Smuzhiyun kfree(debug_data);
350*4882a593Smuzhiyun }
351*4882a593Smuzhiyun
smsdvb_stats_wait_read(struct smsdvb_debugfs * debug_data)352*4882a593Smuzhiyun static int smsdvb_stats_wait_read(struct smsdvb_debugfs *debug_data)
353*4882a593Smuzhiyun {
354*4882a593Smuzhiyun int rc = 1;
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun spin_lock(&debug_data->lock);
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun if (debug_data->stats_was_read)
359*4882a593Smuzhiyun goto exit;
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun rc = debug_data->stats_count;
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun exit:
364*4882a593Smuzhiyun spin_unlock(&debug_data->lock);
365*4882a593Smuzhiyun return rc;
366*4882a593Smuzhiyun }
367*4882a593Smuzhiyun
smsdvb_stats_poll(struct file * file,poll_table * wait)368*4882a593Smuzhiyun static __poll_t smsdvb_stats_poll(struct file *file, poll_table *wait)
369*4882a593Smuzhiyun {
370*4882a593Smuzhiyun struct smsdvb_debugfs *debug_data = file->private_data;
371*4882a593Smuzhiyun int rc;
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun kref_get(&debug_data->refcount);
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun poll_wait(file, &debug_data->stats_queue, wait);
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun rc = smsdvb_stats_wait_read(debug_data);
378*4882a593Smuzhiyun kref_put(&debug_data->refcount, smsdvb_debugfs_data_release);
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun return rc > 0 ? EPOLLIN | EPOLLRDNORM : 0;
381*4882a593Smuzhiyun }
382*4882a593Smuzhiyun
smsdvb_stats_read(struct file * file,char __user * user_buf,size_t nbytes,loff_t * ppos)383*4882a593Smuzhiyun static ssize_t smsdvb_stats_read(struct file *file, char __user *user_buf,
384*4882a593Smuzhiyun size_t nbytes, loff_t *ppos)
385*4882a593Smuzhiyun {
386*4882a593Smuzhiyun int rc = 0, len;
387*4882a593Smuzhiyun struct smsdvb_debugfs *debug_data = file->private_data;
388*4882a593Smuzhiyun
389*4882a593Smuzhiyun kref_get(&debug_data->refcount);
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun if (file->f_flags & O_NONBLOCK) {
392*4882a593Smuzhiyun rc = smsdvb_stats_wait_read(debug_data);
393*4882a593Smuzhiyun if (!rc) {
394*4882a593Smuzhiyun rc = -EWOULDBLOCK;
395*4882a593Smuzhiyun goto ret;
396*4882a593Smuzhiyun }
397*4882a593Smuzhiyun } else {
398*4882a593Smuzhiyun rc = wait_event_interruptible(debug_data->stats_queue,
399*4882a593Smuzhiyun smsdvb_stats_wait_read(debug_data));
400*4882a593Smuzhiyun if (rc < 0)
401*4882a593Smuzhiyun goto ret;
402*4882a593Smuzhiyun }
403*4882a593Smuzhiyun
404*4882a593Smuzhiyun if (debug_data->stats_was_read) {
405*4882a593Smuzhiyun rc = 0; /* EOF */
406*4882a593Smuzhiyun goto ret;
407*4882a593Smuzhiyun }
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun len = debug_data->stats_count - *ppos;
410*4882a593Smuzhiyun if (len >= 0)
411*4882a593Smuzhiyun rc = simple_read_from_buffer(user_buf, nbytes, ppos,
412*4882a593Smuzhiyun debug_data->stats_data, len);
413*4882a593Smuzhiyun else
414*4882a593Smuzhiyun rc = 0;
415*4882a593Smuzhiyun
416*4882a593Smuzhiyun if (*ppos >= debug_data->stats_count) {
417*4882a593Smuzhiyun spin_lock(&debug_data->lock);
418*4882a593Smuzhiyun debug_data->stats_was_read = true;
419*4882a593Smuzhiyun spin_unlock(&debug_data->lock);
420*4882a593Smuzhiyun }
421*4882a593Smuzhiyun ret:
422*4882a593Smuzhiyun kref_put(&debug_data->refcount, smsdvb_debugfs_data_release);
423*4882a593Smuzhiyun return rc;
424*4882a593Smuzhiyun }
425*4882a593Smuzhiyun
smsdvb_stats_release(struct inode * inode,struct file * file)426*4882a593Smuzhiyun static int smsdvb_stats_release(struct inode *inode, struct file *file)
427*4882a593Smuzhiyun {
428*4882a593Smuzhiyun struct smsdvb_debugfs *debug_data = file->private_data;
429*4882a593Smuzhiyun
430*4882a593Smuzhiyun spin_lock(&debug_data->lock);
431*4882a593Smuzhiyun debug_data->stats_was_read = true; /* return EOF to read() */
432*4882a593Smuzhiyun spin_unlock(&debug_data->lock);
433*4882a593Smuzhiyun wake_up_interruptible_sync(&debug_data->stats_queue);
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun kref_put(&debug_data->refcount, smsdvb_debugfs_data_release);
436*4882a593Smuzhiyun file->private_data = NULL;
437*4882a593Smuzhiyun
438*4882a593Smuzhiyun return 0;
439*4882a593Smuzhiyun }
440*4882a593Smuzhiyun
441*4882a593Smuzhiyun static const struct file_operations debugfs_stats_ops = {
442*4882a593Smuzhiyun .open = smsdvb_stats_open,
443*4882a593Smuzhiyun .poll = smsdvb_stats_poll,
444*4882a593Smuzhiyun .read = smsdvb_stats_read,
445*4882a593Smuzhiyun .release = smsdvb_stats_release,
446*4882a593Smuzhiyun .llseek = generic_file_llseek,
447*4882a593Smuzhiyun };
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun /*
450*4882a593Smuzhiyun * Functions used by smsdvb, in order to create the interfaces
451*4882a593Smuzhiyun */
452*4882a593Smuzhiyun
smsdvb_debugfs_create(struct smsdvb_client_t * client)453*4882a593Smuzhiyun int smsdvb_debugfs_create(struct smsdvb_client_t *client)
454*4882a593Smuzhiyun {
455*4882a593Smuzhiyun struct smscore_device_t *coredev = client->coredev;
456*4882a593Smuzhiyun struct dentry *d;
457*4882a593Smuzhiyun struct smsdvb_debugfs *debug_data;
458*4882a593Smuzhiyun
459*4882a593Smuzhiyun if (!smsdvb_debugfs_usb_root || !coredev->is_usb_device)
460*4882a593Smuzhiyun return -ENODEV;
461*4882a593Smuzhiyun
462*4882a593Smuzhiyun client->debugfs = debugfs_create_dir(coredev->devpath,
463*4882a593Smuzhiyun smsdvb_debugfs_usb_root);
464*4882a593Smuzhiyun if (IS_ERR_OR_NULL(client->debugfs)) {
465*4882a593Smuzhiyun pr_info("Unable to create debugfs %s directory.\n",
466*4882a593Smuzhiyun coredev->devpath);
467*4882a593Smuzhiyun return -ENODEV;
468*4882a593Smuzhiyun }
469*4882a593Smuzhiyun
470*4882a593Smuzhiyun d = debugfs_create_file("stats", S_IRUGO | S_IWUSR, client->debugfs,
471*4882a593Smuzhiyun client, &debugfs_stats_ops);
472*4882a593Smuzhiyun if (!d) {
473*4882a593Smuzhiyun debugfs_remove(client->debugfs);
474*4882a593Smuzhiyun return -ENOMEM;
475*4882a593Smuzhiyun }
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun debug_data = kzalloc(sizeof(*client->debug_data), GFP_KERNEL);
478*4882a593Smuzhiyun if (!debug_data)
479*4882a593Smuzhiyun return -ENOMEM;
480*4882a593Smuzhiyun
481*4882a593Smuzhiyun client->debug_data = debug_data;
482*4882a593Smuzhiyun client->prt_dvb_stats = smsdvb_print_dvb_stats;
483*4882a593Smuzhiyun client->prt_isdb_stats = smsdvb_print_isdb_stats;
484*4882a593Smuzhiyun client->prt_isdb_stats_ex = smsdvb_print_isdb_stats_ex;
485*4882a593Smuzhiyun
486*4882a593Smuzhiyun init_waitqueue_head(&debug_data->stats_queue);
487*4882a593Smuzhiyun spin_lock_init(&debug_data->lock);
488*4882a593Smuzhiyun kref_init(&debug_data->refcount);
489*4882a593Smuzhiyun
490*4882a593Smuzhiyun return 0;
491*4882a593Smuzhiyun }
492*4882a593Smuzhiyun
smsdvb_debugfs_release(struct smsdvb_client_t * client)493*4882a593Smuzhiyun void smsdvb_debugfs_release(struct smsdvb_client_t *client)
494*4882a593Smuzhiyun {
495*4882a593Smuzhiyun if (!client->debugfs)
496*4882a593Smuzhiyun return;
497*4882a593Smuzhiyun
498*4882a593Smuzhiyun client->prt_dvb_stats = NULL;
499*4882a593Smuzhiyun client->prt_isdb_stats = NULL;
500*4882a593Smuzhiyun client->prt_isdb_stats_ex = NULL;
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun debugfs_remove_recursive(client->debugfs);
503*4882a593Smuzhiyun kref_put(&client->debug_data->refcount, smsdvb_debugfs_data_release);
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun client->debug_data = NULL;
506*4882a593Smuzhiyun client->debugfs = NULL;
507*4882a593Smuzhiyun }
508*4882a593Smuzhiyun
smsdvb_debugfs_register(void)509*4882a593Smuzhiyun void smsdvb_debugfs_register(void)
510*4882a593Smuzhiyun {
511*4882a593Smuzhiyun struct dentry *d;
512*4882a593Smuzhiyun
513*4882a593Smuzhiyun /*
514*4882a593Smuzhiyun * FIXME: This was written to debug Siano USB devices. So, it creates
515*4882a593Smuzhiyun * the debugfs node under <debugfs>/usb.
516*4882a593Smuzhiyun * A similar logic would be needed for Siano sdio devices, but, in that
517*4882a593Smuzhiyun * case, usb_debug_root is not a good choice.
518*4882a593Smuzhiyun *
519*4882a593Smuzhiyun * Perhaps the right fix here would be to create another sysfs root
520*4882a593Smuzhiyun * node for sdio-based boards, but this may need some logic at sdio
521*4882a593Smuzhiyun * subsystem.
522*4882a593Smuzhiyun */
523*4882a593Smuzhiyun d = debugfs_create_dir("smsdvb", usb_debug_root);
524*4882a593Smuzhiyun if (IS_ERR_OR_NULL(d)) {
525*4882a593Smuzhiyun pr_err("Couldn't create sysfs node for smsdvb\n");
526*4882a593Smuzhiyun return;
527*4882a593Smuzhiyun }
528*4882a593Smuzhiyun smsdvb_debugfs_usb_root = d;
529*4882a593Smuzhiyun }
530*4882a593Smuzhiyun
smsdvb_debugfs_unregister(void)531*4882a593Smuzhiyun void smsdvb_debugfs_unregister(void)
532*4882a593Smuzhiyun {
533*4882a593Smuzhiyun if (!smsdvb_debugfs_usb_root)
534*4882a593Smuzhiyun return;
535*4882a593Smuzhiyun debugfs_remove_recursive(smsdvb_debugfs_usb_root);
536*4882a593Smuzhiyun smsdvb_debugfs_usb_root = NULL;
537*4882a593Smuzhiyun }
538