| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * hfcmulti.c low level driver for hfc-4s/hfc-8s/hfc-e1 based cards |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 9 | 10 | * Copyright 1999 by Werner Cornelius (werner@isdn-development.de) |
|---|
| 10 | 11 | * Copyright 2008 by Karsten Keil (kkeil@suse.de) |
|---|
| 11 | 12 | * Copyright 2008 by Andreas Eversberg (jolly@eversberg.eu) |
|---|
| 12 | | - * |
|---|
| 13 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 14 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 15 | | - * the Free Software Foundation; either version 2, or (at your option) |
|---|
| 16 | | - * any later version. |
|---|
| 17 | | - * |
|---|
| 18 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 19 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 20 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 21 | | - * GNU General Public License for more details. |
|---|
| 22 | | - * |
|---|
| 23 | | - * You should have received a copy of the GNU General Public License |
|---|
| 24 | | - * along with this program; if not, write to the Free Software |
|---|
| 25 | | - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|---|
| 26 | | - * |
|---|
| 27 | 13 | * |
|---|
| 28 | 14 | * Thanks to Cologne Chip AG for this great controller! |
|---|
| 29 | 15 | */ |
|---|
| .. | .. |
|---|
| 2262 | 2248 | if (bch) { |
|---|
| 2263 | 2249 | maxlen = bchannel_get_rxbuf(bch, Zsize); |
|---|
| 2264 | 2250 | if (maxlen < 0) { |
|---|
| 2265 | | - pr_warning("card%d.B%d: No bufferspace for %d bytes\n", |
|---|
| 2266 | | - hc->id + 1, bch->nr, Zsize); |
|---|
| 2251 | + pr_warn("card%d.B%d: No bufferspace for %d bytes\n", |
|---|
| 2252 | + hc->id + 1, bch->nr, Zsize); |
|---|
| 2267 | 2253 | return; |
|---|
| 2268 | 2254 | } |
|---|
| 2269 | 2255 | sp = &bch->rx_skb; |
|---|
| .. | .. |
|---|
| 2274 | 2260 | if (*sp == NULL) { |
|---|
| 2275 | 2261 | *sp = mI_alloc_skb(maxlen, GFP_ATOMIC); |
|---|
| 2276 | 2262 | if (*sp == NULL) { |
|---|
| 2277 | | - pr_warning("card%d: No mem for dch rx_skb\n", |
|---|
| 2278 | | - hc->id + 1); |
|---|
| 2263 | + pr_warn("card%d: No mem for dch rx_skb\n", |
|---|
| 2264 | + hc->id + 1); |
|---|
| 2279 | 2265 | return; |
|---|
| 2280 | 2266 | } |
|---|
| 2281 | 2267 | } |
|---|
| .. | .. |
|---|
| 3233 | 3219 | hfcm_l1callback(struct dchannel *dch, u_int cmd) |
|---|
| 3234 | 3220 | { |
|---|
| 3235 | 3221 | struct hfc_multi *hc = dch->hw; |
|---|
| 3222 | + struct sk_buff_head free_queue; |
|---|
| 3236 | 3223 | u_long flags; |
|---|
| 3237 | 3224 | |
|---|
| 3238 | 3225 | switch (cmd) { |
|---|
| .. | .. |
|---|
| 3261 | 3248 | l1_event(dch->l1, HW_POWERUP_IND); |
|---|
| 3262 | 3249 | break; |
|---|
| 3263 | 3250 | case HW_DEACT_REQ: |
|---|
| 3251 | + __skb_queue_head_init(&free_queue); |
|---|
| 3264 | 3252 | /* start deactivation */ |
|---|
| 3265 | 3253 | spin_lock_irqsave(&hc->lock, flags); |
|---|
| 3266 | 3254 | if (hc->ctype == HFC_TYPE_E1) { |
|---|
| .. | .. |
|---|
| 3280 | 3268 | plxsd_checksync(hc, 0); |
|---|
| 3281 | 3269 | } |
|---|
| 3282 | 3270 | } |
|---|
| 3283 | | - skb_queue_purge(&dch->squeue); |
|---|
| 3271 | + skb_queue_splice_init(&dch->squeue, &free_queue); |
|---|
| 3284 | 3272 | if (dch->tx_skb) { |
|---|
| 3285 | | - dev_kfree_skb(dch->tx_skb); |
|---|
| 3273 | + __skb_queue_tail(&free_queue, dch->tx_skb); |
|---|
| 3286 | 3274 | dch->tx_skb = NULL; |
|---|
| 3287 | 3275 | } |
|---|
| 3288 | 3276 | dch->tx_idx = 0; |
|---|
| 3289 | 3277 | if (dch->rx_skb) { |
|---|
| 3290 | | - dev_kfree_skb(dch->rx_skb); |
|---|
| 3278 | + __skb_queue_tail(&free_queue, dch->rx_skb); |
|---|
| 3291 | 3279 | dch->rx_skb = NULL; |
|---|
| 3292 | 3280 | } |
|---|
| 3293 | 3281 | test_and_clear_bit(FLG_TX_BUSY, &dch->Flags); |
|---|
| 3294 | 3282 | if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags)) |
|---|
| 3295 | 3283 | del_timer(&dch->timer); |
|---|
| 3296 | 3284 | spin_unlock_irqrestore(&hc->lock, flags); |
|---|
| 3285 | + __skb_queue_purge(&free_queue); |
|---|
| 3297 | 3286 | break; |
|---|
| 3298 | 3287 | case HW_POWERUP_REQ: |
|---|
| 3299 | 3288 | spin_lock_irqsave(&hc->lock, flags); |
|---|
| .. | .. |
|---|
| 3400 | 3389 | case PH_DEACTIVATE_REQ: |
|---|
| 3401 | 3390 | test_and_clear_bit(FLG_L2_ACTIVATED, &dch->Flags); |
|---|
| 3402 | 3391 | if (dch->dev.D.protocol != ISDN_P_TE_S0) { |
|---|
| 3392 | + struct sk_buff_head free_queue; |
|---|
| 3393 | + |
|---|
| 3394 | + __skb_queue_head_init(&free_queue); |
|---|
| 3403 | 3395 | spin_lock_irqsave(&hc->lock, flags); |
|---|
| 3404 | 3396 | if (debug & DEBUG_HFCMULTI_MSG) |
|---|
| 3405 | 3397 | printk(KERN_DEBUG |
|---|
| .. | .. |
|---|
| 3421 | 3413 | /* deactivate */ |
|---|
| 3422 | 3414 | dch->state = 1; |
|---|
| 3423 | 3415 | } |
|---|
| 3424 | | - skb_queue_purge(&dch->squeue); |
|---|
| 3416 | + skb_queue_splice_init(&dch->squeue, &free_queue); |
|---|
| 3425 | 3417 | if (dch->tx_skb) { |
|---|
| 3426 | | - dev_kfree_skb(dch->tx_skb); |
|---|
| 3418 | + __skb_queue_tail(&free_queue, dch->tx_skb); |
|---|
| 3427 | 3419 | dch->tx_skb = NULL; |
|---|
| 3428 | 3420 | } |
|---|
| 3429 | 3421 | dch->tx_idx = 0; |
|---|
| 3430 | 3422 | if (dch->rx_skb) { |
|---|
| 3431 | | - dev_kfree_skb(dch->rx_skb); |
|---|
| 3423 | + __skb_queue_tail(&free_queue, dch->rx_skb); |
|---|
| 3432 | 3424 | dch->rx_skb = NULL; |
|---|
| 3433 | 3425 | } |
|---|
| 3434 | 3426 | test_and_clear_bit(FLG_TX_BUSY, &dch->Flags); |
|---|
| .. | .. |
|---|
| 3440 | 3432 | #endif |
|---|
| 3441 | 3433 | ret = 0; |
|---|
| 3442 | 3434 | spin_unlock_irqrestore(&hc->lock, flags); |
|---|
| 3435 | + __skb_queue_purge(&free_queue); |
|---|
| 3443 | 3436 | } else |
|---|
| 3444 | 3437 | ret = l1_event(dch->l1, hh->prim); |
|---|
| 3445 | 3438 | break; |
|---|