.. | .. |
---|
| 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); |
---|