| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* hfcsusb.c |
|---|
| 2 | 3 | * mISDN driver for Colognechip HFC-S USB chip |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright 2001 by Peter Sprenger (sprenger@moving-bytes.de) |
|---|
| 5 | 6 | * Copyright 2008 by Martin Bachem (info@bachem-it.com) |
|---|
| 6 | | - * |
|---|
| 7 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 8 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 9 | | - * the Free Software Foundation; either version 2, or (at your option) |
|---|
| 10 | | - * any later version. |
|---|
| 11 | | - * |
|---|
| 12 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 13 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 14 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 15 | | - * GNU General Public License for more details. |
|---|
| 16 | | - * |
|---|
| 17 | | - * You should have received a copy of the GNU General Public License |
|---|
| 18 | | - * along with this program; if not, write to the Free Software |
|---|
| 19 | | - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|---|
| 20 | | - * |
|---|
| 21 | 7 | * |
|---|
| 22 | 8 | * module params |
|---|
| 23 | 9 | * debug=<n>, default=0, with n=0xHHHHGGGG |
|---|
| .. | .. |
|---|
| 60 | 46 | static void hfcsusb_stop_endpoint(struct hfcsusb *hw, int channel); |
|---|
| 61 | 47 | static int hfcsusb_setup_bch(struct bchannel *bch, int protocol); |
|---|
| 62 | 48 | static void deactivate_bchannel(struct bchannel *bch); |
|---|
| 63 | | -static void hfcsusb_ph_info(struct hfcsusb *hw); |
|---|
| 49 | +static int hfcsusb_ph_info(struct hfcsusb *hw); |
|---|
| 64 | 50 | |
|---|
| 65 | 51 | /* start next background transfer for control channel */ |
|---|
| 66 | 52 | static void |
|---|
| .. | .. |
|---|
| 255 | 241 | * send full D/B channel status information |
|---|
| 256 | 242 | * as MPH_INFORMATION_IND |
|---|
| 257 | 243 | */ |
|---|
| 258 | | -static void |
|---|
| 244 | +static int |
|---|
| 259 | 245 | hfcsusb_ph_info(struct hfcsusb *hw) |
|---|
| 260 | 246 | { |
|---|
| 261 | 247 | struct ph_info *phi; |
|---|
| 262 | 248 | struct dchannel *dch = &hw->dch; |
|---|
| 263 | 249 | int i; |
|---|
| 264 | 250 | |
|---|
| 265 | | - phi = kzalloc(sizeof(struct ph_info) + |
|---|
| 266 | | - dch->dev.nrbchan * sizeof(struct ph_info_ch), GFP_ATOMIC); |
|---|
| 251 | + phi = kzalloc(struct_size(phi, bch, dch->dev.nrbchan), GFP_ATOMIC); |
|---|
| 252 | + if (!phi) |
|---|
| 253 | + return -ENOMEM; |
|---|
| 254 | + |
|---|
| 267 | 255 | phi->dch.ch.protocol = hw->protocol; |
|---|
| 268 | 256 | phi->dch.ch.Flags = dch->Flags; |
|---|
| 269 | 257 | phi->dch.state = dch->state; |
|---|
| .. | .. |
|---|
| 273 | 261 | phi->bch[i].Flags = hw->bch[i].Flags; |
|---|
| 274 | 262 | } |
|---|
| 275 | 263 | _queue_data(&dch->dev.D, MPH_INFORMATION_IND, MISDN_ID_ANY, |
|---|
| 276 | | - sizeof(struct ph_info_dch) + dch->dev.nrbchan * |
|---|
| 277 | | - sizeof(struct ph_info_ch), phi, GFP_ATOMIC); |
|---|
| 264 | + struct_size(phi, bch, dch->dev.nrbchan), phi, GFP_ATOMIC); |
|---|
| 278 | 265 | kfree(phi); |
|---|
| 266 | + |
|---|
| 267 | + return 0; |
|---|
| 279 | 268 | } |
|---|
| 280 | 269 | |
|---|
| 281 | 270 | /* |
|---|
| .. | .. |
|---|
| 337 | 326 | test_and_clear_bit(FLG_L2_ACTIVATED, &dch->Flags); |
|---|
| 338 | 327 | |
|---|
| 339 | 328 | if (hw->protocol == ISDN_P_NT_S0) { |
|---|
| 329 | + struct sk_buff_head free_queue; |
|---|
| 330 | + |
|---|
| 331 | + __skb_queue_head_init(&free_queue); |
|---|
| 340 | 332 | hfcsusb_ph_command(hw, HFC_L1_DEACTIVATE_NT); |
|---|
| 341 | 333 | spin_lock_irqsave(&hw->lock, flags); |
|---|
| 342 | | - skb_queue_purge(&dch->squeue); |
|---|
| 334 | + skb_queue_splice_init(&dch->squeue, &free_queue); |
|---|
| 343 | 335 | if (dch->tx_skb) { |
|---|
| 344 | | - dev_kfree_skb(dch->tx_skb); |
|---|
| 336 | + __skb_queue_tail(&free_queue, dch->tx_skb); |
|---|
| 345 | 337 | dch->tx_skb = NULL; |
|---|
| 346 | 338 | } |
|---|
| 347 | 339 | dch->tx_idx = 0; |
|---|
| 348 | 340 | if (dch->rx_skb) { |
|---|
| 349 | | - dev_kfree_skb(dch->rx_skb); |
|---|
| 341 | + __skb_queue_tail(&free_queue, dch->rx_skb); |
|---|
| 350 | 342 | dch->rx_skb = NULL; |
|---|
| 351 | 343 | } |
|---|
| 352 | 344 | test_and_clear_bit(FLG_TX_BUSY, &dch->Flags); |
|---|
| 353 | 345 | spin_unlock_irqrestore(&hw->lock, flags); |
|---|
| 346 | + __skb_queue_purge(&free_queue); |
|---|
| 354 | 347 | #ifdef FIXME |
|---|
| 355 | 348 | if (test_and_clear_bit(FLG_L1_BUSY, &dch->Flags)) |
|---|
| 356 | 349 | dchannel_sched_event(&hc->dch, D_CLEARBUSY); |
|---|
| .. | .. |
|---|
| 360 | 353 | ret = l1_event(dch->l1, hh->prim); |
|---|
| 361 | 354 | break; |
|---|
| 362 | 355 | case MPH_INFORMATION_REQ: |
|---|
| 363 | | - hfcsusb_ph_info(hw); |
|---|
| 364 | | - ret = 0; |
|---|
| 356 | + ret = hfcsusb_ph_info(hw); |
|---|
| 365 | 357 | break; |
|---|
| 366 | 358 | } |
|---|
| 367 | 359 | |
|---|
| .. | .. |
|---|
| 416 | 408 | hw->name, __func__, cmd); |
|---|
| 417 | 409 | return -1; |
|---|
| 418 | 410 | } |
|---|
| 419 | | - hfcsusb_ph_info(hw); |
|---|
| 420 | | - return 0; |
|---|
| 411 | + return hfcsusb_ph_info(hw); |
|---|
| 421 | 412 | } |
|---|
| 422 | 413 | |
|---|
| 423 | 414 | static int |
|---|
| .. | .. |
|---|
| 708 | 699 | switch (protocol) { |
|---|
| 709 | 700 | case (-1): /* used for init */ |
|---|
| 710 | 701 | bch->state = -1; |
|---|
| 711 | | - /* fall through */ |
|---|
| 702 | + fallthrough; |
|---|
| 712 | 703 | case (ISDN_P_NONE): |
|---|
| 713 | 704 | if (bch->state == ISDN_P_NONE) |
|---|
| 714 | 705 | return 0; /* already in idle state */ |
|---|
| .. | .. |
|---|
| 759 | 750 | handle_led(hw, (bch->nr == 1) ? LED_B1_OFF : |
|---|
| 760 | 751 | LED_B2_OFF); |
|---|
| 761 | 752 | } |
|---|
| 762 | | - hfcsusb_ph_info(hw); |
|---|
| 763 | | - return 0; |
|---|
| 753 | + return hfcsusb_ph_info(hw); |
|---|
| 764 | 754 | } |
|---|
| 765 | 755 | |
|---|
| 766 | 756 | static void |
|---|
| .. | .. |
|---|
| 853 | 843 | if (maxlen < 0) { |
|---|
| 854 | 844 | if (rx_skb) |
|---|
| 855 | 845 | skb_trim(rx_skb, 0); |
|---|
| 856 | | - pr_warning("%s.B%d: No bufferspace for %d bytes\n", |
|---|
| 857 | | - hw->name, fifo->bch->nr, len); |
|---|
| 846 | + pr_warn("%s.B%d: No bufferspace for %d bytes\n", |
|---|
| 847 | + hw->name, fifo->bch->nr, len); |
|---|
| 858 | 848 | spin_unlock_irqrestore(&hw->lock, flags); |
|---|
| 859 | 849 | return; |
|---|
| 860 | 850 | } |
|---|
| .. | .. |
|---|
| 1344 | 1334 | printk("\n"); |
|---|
| 1345 | 1335 | } |
|---|
| 1346 | 1336 | |
|---|
| 1347 | | - dev_kfree_skb(tx_skb); |
|---|
| 1337 | + dev_consume_skb_irq(tx_skb); |
|---|
| 1348 | 1338 | tx_skb = NULL; |
|---|
| 1349 | 1339 | if (fifo->dch && get_next_dframe(fifo->dch)) |
|---|
| 1350 | 1340 | tx_skb = fifo->dch->tx_skb; |
|---|