| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * CAIF Interface registration. |
|---|
| 3 | 4 | * Copyright (C) ST-Ericsson AB 2010 |
|---|
| 4 | 5 | * Author: Sjur Brendeland |
|---|
| 5 | | - * License terms: GNU General Public License (GPL) version 2 |
|---|
| 6 | 6 | * |
|---|
| 7 | 7 | * Borrowed heavily from file: pn_dev.c. Thanks to Remi Denis-Courmont |
|---|
| 8 | 8 | * and Sakari Ailus <sakari.ailus@nokia.com> |
|---|
| .. | .. |
|---|
| 112 | 112 | caif_device_list(dev_net(dev)); |
|---|
| 113 | 113 | struct caif_device_entry *caifd; |
|---|
| 114 | 114 | |
|---|
| 115 | | - list_for_each_entry_rcu(caifd, &caifdevs->list, list) { |
|---|
| 115 | + list_for_each_entry_rcu(caifd, &caifdevs->list, list, |
|---|
| 116 | + lockdep_rtnl_is_held()) { |
|---|
| 116 | 117 | if (caifd->netdev == dev) |
|---|
| 117 | 118 | return caifd; |
|---|
| 118 | 119 | } |
|---|
| .. | .. |
|---|
| 141 | 142 | |
|---|
| 142 | 143 | spin_lock_bh(&caifd->flow_lock); |
|---|
| 143 | 144 | send_xoff = caifd->xoff; |
|---|
| 144 | | - caifd->xoff = 0; |
|---|
| 145 | + caifd->xoff = false; |
|---|
| 145 | 146 | dtor = caifd->xoff_skb_dtor; |
|---|
| 146 | 147 | |
|---|
| 147 | 148 | if (WARN_ON(caifd->xoff_skb != skb)) |
|---|
| .. | .. |
|---|
| 186 | 187 | goto noxoff; |
|---|
| 187 | 188 | |
|---|
| 188 | 189 | if (likely(!netif_queue_stopped(caifd->netdev))) { |
|---|
| 190 | + struct Qdisc *sch; |
|---|
| 191 | + |
|---|
| 189 | 192 | /* If we run with a TX queue, check if the queue is too long*/ |
|---|
| 190 | 193 | txq = netdev_get_tx_queue(skb->dev, 0); |
|---|
| 191 | | - qlen = qdisc_qlen(rcu_dereference_bh(txq->qdisc)); |
|---|
| 192 | | - |
|---|
| 193 | | - if (likely(qlen == 0)) |
|---|
| 194 | + sch = rcu_dereference_bh(txq->qdisc); |
|---|
| 195 | + if (likely(qdisc_is_empty(sch))) |
|---|
| 194 | 196 | goto noxoff; |
|---|
| 195 | 197 | |
|---|
| 198 | + /* can check for explicit qdisc len value only !NOLOCK, |
|---|
| 199 | + * always set flow off otherwise |
|---|
| 200 | + */ |
|---|
| 196 | 201 | high = (caifd->netdev->tx_queue_len * q_high) / 100; |
|---|
| 197 | | - if (likely(qlen < high)) |
|---|
| 202 | + if (!(sch->flags & TCQ_F_NOLOCK) && likely(sch->q.qlen < high)) |
|---|
| 198 | 203 | goto noxoff; |
|---|
| 199 | 204 | } |
|---|
| 200 | 205 | |
|---|
| .. | .. |
|---|
| 215 | 220 | pr_debug("queue has stopped(%d) or is full (%d > %d)\n", |
|---|
| 216 | 221 | netif_queue_stopped(caifd->netdev), |
|---|
| 217 | 222 | qlen, high); |
|---|
| 218 | | - caifd->xoff = 1; |
|---|
| 223 | + caifd->xoff = true; |
|---|
| 219 | 224 | caifd->xoff_skb = skb; |
|---|
| 220 | 225 | caifd->xoff_skb_dtor = skb->destructor; |
|---|
| 221 | 226 | skb->destructor = caif_flow_cb; |
|---|
| .. | .. |
|---|
| 407 | 412 | break; |
|---|
| 408 | 413 | } |
|---|
| 409 | 414 | |
|---|
| 410 | | - caifd->xoff = 0; |
|---|
| 415 | + caifd->xoff = false; |
|---|
| 411 | 416 | cfcnfg_set_phy_state(cfg, &caifd->layer, true); |
|---|
| 412 | 417 | rcu_read_unlock(); |
|---|
| 413 | 418 | |
|---|
| .. | .. |
|---|
| 442 | 447 | if (caifd->xoff_skb_dtor != NULL && caifd->xoff_skb != NULL) |
|---|
| 443 | 448 | caifd->xoff_skb->destructor = caifd->xoff_skb_dtor; |
|---|
| 444 | 449 | |
|---|
| 445 | | - caifd->xoff = 0; |
|---|
| 450 | + caifd->xoff = false; |
|---|
| 446 | 451 | caifd->xoff_skb_dtor = NULL; |
|---|
| 447 | 452 | caifd->xoff_skb = NULL; |
|---|
| 448 | 453 | |
|---|