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