xref: /OK3568_Linux_fs/kernel/drivers/media/common/siano/smsdvb-debugfs.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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