| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * FM Driver for Connectivity chip of Texas Instruments. |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 16 | 17 | * Copyright (C) 2011 Texas Instruments |
|---|
| 17 | 18 | * Author: Raja Mani <raja_mani@ti.com> |
|---|
| 18 | 19 | * Author: Manjunatha Halli <manjunatha_halli@ti.com> |
|---|
| 19 | | - * |
|---|
| 20 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 21 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 22 | | - * published by the Free Software Foundation. |
|---|
| 23 | | - * |
|---|
| 24 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 25 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 26 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 27 | | - * GNU General Public License for more details. |
|---|
| 28 | | - * |
|---|
| 29 | 20 | */ |
|---|
| 30 | 21 | |
|---|
| 31 | | -#include <linux/module.h> |
|---|
| 32 | | -#include <linux/firmware.h> |
|---|
| 33 | 22 | #include <linux/delay.h> |
|---|
| 23 | +#include <linux/firmware.h> |
|---|
| 24 | +#include <linux/module.h> |
|---|
| 25 | +#include <linux/nospec.h> |
|---|
| 26 | + |
|---|
| 34 | 27 | #include "fmdrv.h" |
|---|
| 35 | 28 | #include "fmdrv_v4l2.h" |
|---|
| 36 | 29 | #include "fmdrv_common.h" |
|---|
| .. | .. |
|---|
| 253 | 246 | * FM common sub-module will schedule this tasklet whenever it receives |
|---|
| 254 | 247 | * FM packet from ST driver. |
|---|
| 255 | 248 | */ |
|---|
| 256 | | -static void recv_tasklet(unsigned long arg) |
|---|
| 249 | +static void recv_tasklet(struct tasklet_struct *t) |
|---|
| 257 | 250 | { |
|---|
| 258 | 251 | struct fmdev *fmdev; |
|---|
| 259 | 252 | struct fm_irq *irq_info; |
|---|
| .. | .. |
|---|
| 262 | 255 | u8 num_fm_hci_cmds; |
|---|
| 263 | 256 | unsigned long flags; |
|---|
| 264 | 257 | |
|---|
| 265 | | - fmdev = (struct fmdev *)arg; |
|---|
| 258 | + fmdev = from_tasklet(fmdev, t, tx_task); |
|---|
| 266 | 259 | irq_info = &fmdev->irq_info; |
|---|
| 267 | 260 | /* Process all packets in the RX queue */ |
|---|
| 268 | 261 | while ((skb = skb_dequeue(&fmdev->rx_q))) { |
|---|
| .. | .. |
|---|
| 337 | 330 | } |
|---|
| 338 | 331 | |
|---|
| 339 | 332 | /* FM send tasklet: is scheduled when FM packet has to be sent to chip */ |
|---|
| 340 | | -static void send_tasklet(unsigned long arg) |
|---|
| 333 | +static void send_tasklet(struct tasklet_struct *t) |
|---|
| 341 | 334 | { |
|---|
| 342 | 335 | struct fmdev *fmdev; |
|---|
| 343 | 336 | struct sk_buff *skb; |
|---|
| 344 | 337 | int len; |
|---|
| 345 | 338 | |
|---|
| 346 | | - fmdev = (struct fmdev *)arg; |
|---|
| 339 | + fmdev = from_tasklet(fmdev, t, tx_task); |
|---|
| 347 | 340 | |
|---|
| 348 | 341 | if (!atomic_read(&fmdev->tx_cnt)) |
|---|
| 349 | 342 | return; |
|---|
| .. | .. |
|---|
| 709 | 702 | struct fm_rds *rds = &fmdev->rx.rds; |
|---|
| 710 | 703 | unsigned long group_idx, flags; |
|---|
| 711 | 704 | u8 *rds_data, meta_data, tmpbuf[FM_RDS_BLK_SIZE]; |
|---|
| 712 | | - u8 type, blk_idx; |
|---|
| 705 | + u8 type, blk_idx, idx; |
|---|
| 713 | 706 | u16 cur_picode; |
|---|
| 714 | 707 | u32 rds_len; |
|---|
| 715 | 708 | |
|---|
| .. | .. |
|---|
| 742 | 735 | } |
|---|
| 743 | 736 | |
|---|
| 744 | 737 | /* Skip checkword (control) byte and copy only data byte */ |
|---|
| 745 | | - memcpy(&rds_fmt.data.groupdatabuff. |
|---|
| 746 | | - buff[blk_idx * (FM_RDS_BLK_SIZE - 1)], |
|---|
| 747 | | - rds_data, (FM_RDS_BLK_SIZE - 1)); |
|---|
| 738 | + idx = array_index_nospec(blk_idx * (FM_RDS_BLK_SIZE - 1), |
|---|
| 739 | + FM_RX_RDS_INFO_FIELD_MAX - (FM_RDS_BLK_SIZE - 1)); |
|---|
| 740 | + |
|---|
| 741 | + memcpy(&rds_fmt.data.groupdatabuff.buff[idx], rds_data, |
|---|
| 742 | + FM_RDS_BLK_SIZE - 1); |
|---|
| 748 | 743 | |
|---|
| 749 | 744 | rds->last_blk_idx = blk_idx; |
|---|
| 750 | 745 | |
|---|
| .. | .. |
|---|
| 911 | 906 | u16 frq_index; |
|---|
| 912 | 907 | u16 payload; |
|---|
| 913 | 908 | |
|---|
| 914 | | - fmdbg("Swtich to %d KHz\n", fmdev->rx.stat_info.af_cache[fmdev->rx.afjump_idx]); |
|---|
| 909 | + fmdbg("Switch to %d KHz\n", fmdev->rx.stat_info.af_cache[fmdev->rx.afjump_idx]); |
|---|
| 915 | 910 | frq_index = (fmdev->rx.stat_info.af_cache[fmdev->rx.afjump_idx] - |
|---|
| 916 | 911 | fmdev->rx.region.bot_freq) / FM_FREQ_MUL; |
|---|
| 917 | 912 | |
|---|
| .. | .. |
|---|
| 1050 | 1045 | clear_bit(FM_INTTASK_RUNNING, &fmdev->flag); |
|---|
| 1051 | 1046 | } |
|---|
| 1052 | 1047 | |
|---|
| 1053 | | -/* Returns availability of RDS data in internel buffer */ |
|---|
| 1048 | +/* Returns availability of RDS data in internal buffer */ |
|---|
| 1054 | 1049 | int fmc_is_rds_data_available(struct fmdev *fmdev, struct file *file, |
|---|
| 1055 | 1050 | struct poll_table_struct *pts) |
|---|
| 1056 | 1051 | { |
|---|
| .. | .. |
|---|
| 1524 | 1519 | } |
|---|
| 1525 | 1520 | |
|---|
| 1526 | 1521 | ret = 0; |
|---|
| 1527 | | - } else if (ret == -1) { |
|---|
| 1522 | + } else if (ret < 0) { |
|---|
| 1528 | 1523 | fmerr("st_register failed %d\n", ret); |
|---|
| 1529 | 1524 | return -EAGAIN; |
|---|
| 1530 | 1525 | } |
|---|
| .. | .. |
|---|
| 1544 | 1539 | |
|---|
| 1545 | 1540 | /* Initialize TX queue and TX tasklet */ |
|---|
| 1546 | 1541 | skb_queue_head_init(&fmdev->tx_q); |
|---|
| 1547 | | - tasklet_init(&fmdev->tx_task, send_tasklet, (unsigned long)fmdev); |
|---|
| 1542 | + tasklet_setup(&fmdev->tx_task, send_tasklet); |
|---|
| 1548 | 1543 | |
|---|
| 1549 | 1544 | /* Initialize RX Queue and RX tasklet */ |
|---|
| 1550 | 1545 | skb_queue_head_init(&fmdev->rx_q); |
|---|
| 1551 | | - tasklet_init(&fmdev->rx_task, recv_tasklet, (unsigned long)fmdev); |
|---|
| 1546 | + tasklet_setup(&fmdev->rx_task, recv_tasklet); |
|---|
| 1552 | 1547 | |
|---|
| 1553 | 1548 | fmdev->irq_info.stage = 0; |
|---|
| 1554 | 1549 | atomic_set(&fmdev->tx_cnt, 1); |
|---|