Pull networking fixes from Jakub Kicinski: "Including fixes from netfilter, wireless and bluetooth. Kalle Valo steps down after serving as the WiFi driver maintainer for over a decade. Current release - fix to a fix: - vsock: orphan socket after transport release, avoid null-deref - Bluetooth: L2CAP: fix corrupted list in hci_chan_del Current release - regressions: - eth: - stmmac: correct Rx buffer layout when SPH is enabled - iavf: fix a locking bug in an error path - rxrpc: fix alteration of headers whilst zerocopy pending - s390/qeth: move netif_napi_add_tx() and napi_enable() from under BH - Revert "netfilter: flowtable: teardown flow if cached mtu is stale" Current release - new code bugs: - rxrpc: fix ipv6 path MTU discovery, only ipv4 worked - pse-pd: fix deadlock in current limit functions Previous releases - regressions: - rtnetlink: fix netns refleak with rtnl_setlink() - wifi: brcmfmac: use random seed flag for BCM4355 and BCM4364 firmware Previous releases - always broken: - add missing RCU protection of struct net throughout the stack - can: rockchip: bail out if skb cannot be allocated - eth: ti: am65-cpsw: base XDP support fixes Misc: - ethtool: tsconfig: update the format of hwtstamp flags, changes the uAPI but this uAPI was not in any release yet" * tag 'net-6.14-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (72 commits) net: pse-pd: Fix deadlock in current limit functions rxrpc: Fix ipv6 path MTU discovery Reapply "net: skb: introduce and use a single page frag cache" s390/qeth: move netif_napi_add_tx() and napi_enable() from under BH mlxsw: Add return value check for mlxsw_sp_port_get_stats_raw() ipv6: mcast: add RCU protection to mld_newpack() team: better TEAM_OPTION_TYPE_STRING validation Bluetooth: L2CAP: Fix corrupted list in hci_chan_del Bluetooth: btintel_pcie: Fix a potential race condition Bluetooth: L2CAP: Fix slab-use-after-free Read in l2cap_send_cmd net: ethernet: ti: am65_cpsw: fix tx_cleanup for XDP case net: ethernet: ti: am65-cpsw: fix RX & TX statistics for XDP_TX case net: ethernet: ti: am65-cpsw: fix memleak in certain XDP cases vsock/test: Add test for SO_LINGER null ptr deref vsock: Orphan socket after transport release MAINTAINERS: Add sctp headers to the general netdev entry Revert "netfilter: flowtable: teardown flow if cached mtu is stale" iavf: Fix a locking bug in an error path rxrpc: Fix alteration of headers whilst zerocopy pending net: phylink: make configuring clock-stop dependent on MAC support ...
Unified · Split
| @@ -376,6 +376,7 @@ Juha Yrjola <juha.yrjola@solidboot.com> · 375 unmodified lines | ||
| 376 | 376 | Julien Thierry <julien.thierry.kdev@gmail.com> <julien.thierry@arm.com> |
| 377 | 377 | Iskren Chernev <me@iskren.info> <iskren.chernev@gmail.com> |
| 378 | 378 | Kalle Valo <kvalo@kernel.org> <kvalo@codeaurora.org> |
| 379 | +Kalle Valo <kvalo@kernel.org> <quic_kvalo@quicinc.com> | |
| 379 | 380 | Kalyan Thota <quic_kalyant@quicinc.com> <kalyan_t@codeaurora.org> |
| 380 | 381 | Karthikeyan Periyasamy <quic_periyasa@quicinc.com> <periyasa@codeaurora.org> |
| 381 | 382 | Kathiravan T <quic_kathirav@quicinc.com> <kathirav@codeaurora.org> |
| @@ -7,7 +7,6 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# · 6 unmodified lines | ||
| 7 | 7 | title: Qualcomm Technologies ath10k wireless devices |
| 8 | 8 | |
| 9 | 9 | maintainers: |
| 10 | − - Kalle Valo <kvalo@kernel.org> | |
| 11 | 10 | - Jeff Johnson <jjohnson@kernel.org> |
| 12 | 11 | |
| 13 | 12 | description: |
| @@ -8,7 +8,6 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# · 7 unmodified lines | ||
| 8 | 8 | title: Qualcomm Technologies ath11k wireless devices (PCIe) |
| 9 | 9 | |
| 10 | 10 | maintainers: |
| 11 | − - Kalle Valo <kvalo@kernel.org> | |
| 12 | 11 | - Jeff Johnson <jjohnson@kernel.org> |
| 13 | 12 | |
| 14 | 13 | description: | |
| @@ -8,7 +8,6 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# · 7 unmodified lines | ||
| 8 | 8 | title: Qualcomm Technologies ath11k wireless devices |
| 9 | 9 | |
| 10 | 10 | maintainers: |
| 11 | − - Kalle Valo <kvalo@kernel.org> | |
| 12 | 11 | - Jeff Johnson <jjohnson@kernel.org> |
| 13 | 12 | |
| 14 | 13 | description: | |
| @@ -9,7 +9,6 @@ title: Qualcomm Technologies ath12k wireless devices (PCIe) with WSI interface · 8 unmodified lines | ||
| 9 | 9 | |
| 10 | 10 | maintainers: |
| 11 | 11 | - Jeff Johnson <jjohnson@kernel.org> |
| 12 | − - Kalle Valo <kvalo@kernel.org> | |
| 13 | 12 | |
| 14 | 13 | description: | |
| 15 | 14 | Qualcomm Technologies IEEE 802.11be PCIe devices with WSI interface. |
| @@ -9,7 +9,6 @@ title: Qualcomm Technologies ath12k wireless devices (PCIe) · 8 unmodified lines | ||
| 9 | 9 | |
| 10 | 10 | maintainers: |
| 11 | 11 | - Jeff Johnson <quic_jjohnson@quicinc.com> |
| 12 | − - Kalle Valo <kvalo@kernel.org> | |
| 13 | 12 | |
| 14 | 13 | description: |
| 15 | 14 | Qualcomm Technologies IEEE 802.11be PCIe devices. |
| @@ -1524,7 +1524,8 @@ attribute-sets: · 1523 unmodified lines | ||
| 1524 | 1524 | nested-attributes: bitset |
| 1525 | 1525 | - |
| 1526 | 1526 | name: hwtstamp-flags |
| 1527 | − type: u32 | |
| 1527 | + type: nest | |
| 1528 | + nested-attributes: bitset | |
| 1528 | 1529 | |
| 1529 | 1530 | operations: |
| 1530 | 1531 | enum-model: directional |
| @@ -369,8 +369,8 @@ to their default. · 368 unmodified lines | ||
| 369 | 369 | |
| 370 | 370 | addr.can_family = AF_CAN; |
| 371 | 371 | addr.can_ifindex = if_nametoindex("can0"); |
| 372 | − addr.tp.tx_id = 0x18DA42F1 | CAN_EFF_FLAG; | |
| 373 | − addr.tp.rx_id = 0x18DAF142 | CAN_EFF_FLAG; | |
| 372 | + addr.can_addr.tp.tx_id = 0x18DA42F1 | CAN_EFF_FLAG; | |
| 373 | + addr.can_addr.tp.rx_id = 0x18DAF142 | CAN_EFF_FLAG; | |
| 374 | 374 | |
| 375 | 375 | ret = bind(s, (struct sockaddr *)&addr, sizeof(addr)); |
| 376 | 376 | if (ret < 0) |
| @@ -3654,7 +3654,6 @@ F: Documentation/devicetree/bindings/phy/phy-ath79-usb.txt · 3653 unmodified lines | ||
| 3654 | 3654 | F: drivers/phy/qualcomm/phy-ath79-usb.c |
| 3655 | 3655 | |
| 3656 | 3656 | ATHEROS ATH GENERIC UTILITIES |
| 3657 | −M: Kalle Valo <kvalo@kernel.org> | |
| 3658 | 3657 | M: Jeff Johnson <jjohnson@kernel.org> |
| 3659 | 3658 | L: linux-wireless@vger.kernel.org |
| 3660 | 3659 | S: Supported |
| @@ -16438,7 +16437,7 @@ X: drivers/net/can/ · 12777 unmodified lines | ||
| 16438 | 16437 | X: drivers/net/wireless/ |
| 16439 | 16438 | |
| 16440 | 16439 | NETWORKING DRIVERS (WIRELESS) |
| 16441 | −M: Kalle Valo <kvalo@kernel.org> | |
| 16440 | +M: Johannes Berg <johannes@sipsolutions.net> | |
| 16442 | 16441 | L: linux-wireless@vger.kernel.org |
| 16443 | 16442 | S: Maintained |
| 16444 | 16443 | W: https://wireless.wiki.kernel.org/ |
| @@ -16509,6 +16508,7 @@ F: include/linux/netdev* · 64 unmodified lines | ||
| 16509 | 16508 | F: include/linux/netlink.h |
| 16510 | 16509 | F: include/linux/netpoll.h |
| 16511 | 16510 | F: include/linux/rtnetlink.h |
| 16511 | +F: include/linux/sctp.h | |
| 16512 | 16512 | F: include/linux/seq_file_net.h |
| 16513 | 16513 | F: include/linux/skbuff* |
| 16514 | 16514 | F: include/net/ |
| @@ -16525,6 +16525,7 @@ F: include/uapi/linux/netdev* · 10 unmodified lines | ||
| 16525 | 16525 | F: include/uapi/linux/netlink.h |
| 16526 | 16526 | F: include/uapi/linux/netlink_diag.h |
| 16527 | 16527 | F: include/uapi/linux/rtnetlink.h |
| 16528 | +F: include/uapi/linux/sctp.h | |
| 16528 | 16529 | F: lib/net_utils.c |
| 16529 | 16530 | F: lib/random32.c |
| 16530 | 16531 | F: net/ |
| @@ -19355,7 +19356,6 @@ Q: http://patchwork.linuxtv.org/project/linux-media/list/ · 2824 unmodified lines | ||
| 19355 | 19356 | F: drivers/media/tuners/qt1010* |
| 19356 | 19357 | |
| 19357 | 19358 | QUALCOMM ATH12K WIRELESS DRIVER |
| 19358 | −M: Kalle Valo <kvalo@kernel.org> | |
| 19359 | 19359 | M: Jeff Johnson <jjohnson@kernel.org> |
| 19360 | 19360 | L: ath12k@lists.infradead.org |
| 19361 | 19361 | S: Supported |
| @@ -19365,7 +19365,6 @@ F: drivers/net/wireless/ath/ath12k/ · 3 unmodified lines | ||
| 19365 | 19365 | N: ath12k |
| 19366 | 19366 | |
| 19367 | 19367 | QUALCOMM ATHEROS ATH10K WIRELESS DRIVER |
| 19368 | −M: Kalle Valo <kvalo@kernel.org> | |
| 19369 | 19368 | M: Jeff Johnson <jjohnson@kernel.org> |
| 19370 | 19369 | L: ath10k@lists.infradead.org |
| 19371 | 19370 | S: Supported |
| @@ -19375,7 +19374,6 @@ F: drivers/net/wireless/ath/ath10k/ · 3 unmodified lines | ||
| 19375 | 19374 | N: ath10k |
| 19376 | 19375 | |
| 19377 | 19376 | QUALCOMM ATHEROS ATH11K WIRELESS DRIVER |
| 19378 | −M: Kalle Valo <kvalo@kernel.org> | |
| 19379 | 19377 | M: Jeff Johnson <jjohnson@kernel.org> |
| 19380 | 19378 | L: ath11k@lists.infradead.org |
| 19381 | 19379 | S: Supported |
| @@ -1320,6 +1320,10 @@ static int btintel_pcie_send_frame(struct hci_dev *hdev, · 1319 unmodified lines | ||
| 1320 | 1320 | if (opcode == 0xfc01) |
| 1321 | 1321 | btintel_pcie_inject_cmd_complete(hdev, opcode); |
| 1322 | 1322 | } |
| 1323 | + /* Firmware raises alive interrupt on HCI_OP_RESET */ | |
| 1324 | + if (opcode == HCI_OP_RESET) | |
| 1325 | + data->gp0_received = false; | |
| 1326 | + | |
| 1323 | 1327 | hdev->stat.cmd_tx++; |
| 1324 | 1328 | break; |
| 1325 | 1329 | case HCI_ACLDATA_PKT: |
| @@ -1357,7 +1361,6 @@ static int btintel_pcie_send_frame(struct hci_dev *hdev, · 31 unmodified lines | ||
| 1357 | 1361 | opcode, btintel_pcie_alivectxt_state2str(old_ctxt), |
| 1358 | 1362 | btintel_pcie_alivectxt_state2str(data->alive_intr_ctxt)); |
| 1359 | 1363 | if (opcode == HCI_OP_RESET) { |
| 1360 | − data->gp0_received = false; | |
| 1361 | 1364 | ret = wait_event_timeout(data->gp0_wait_q, |
| 1362 | 1365 | data->gp0_received, |
| 1363 | 1366 | msecs_to_jiffies(BTINTEL_DEFAULT_INTR_TIMEOUT_MS)); |
| @@ -385,15 +385,16 @@ static int c_can_plat_probe(struct platform_device *pdev) · 384 unmodified lines | ||
| 385 | 385 | if (ret) { |
| 386 | 386 | dev_err(&pdev->dev, "registering %s failed (err=%d)\n", |
| 387 | 387 | KBUILD_MODNAME, ret); |
| 388 | − goto exit_free_device; | |
| 388 | + goto exit_pm_runtime; | |
| 389 | 389 | } |
| 390 | 390 | |
| 391 | 391 | dev_info(&pdev->dev, "%s device registered (regs=%p, irq=%d)\n", |
| 392 | 392 | KBUILD_MODNAME, priv->base, dev->irq); |
| 393 | 393 | return 0; |
| 394 | 394 | |
| 395 | −exit_free_device: | |
| 395 | +exit_pm_runtime: | |
| 396 | 396 | pm_runtime_disable(priv->device); |
| 397 | +exit_free_device: | |
| 397 | 398 | free_c_can_dev(dev); |
| 398 | 399 | exit: |
| 399 | 400 | dev_err(&pdev->dev, "probe failed\n"); |
| @@ -867,10 +867,12 @@ static void ctucan_err_interrupt(struct net_device *ndev, u32 isr) · 866 unmodified lines | ||
| 867 | 867 | } |
| 868 | 868 | break; |
| 869 | 869 | case CAN_STATE_ERROR_ACTIVE: |
| 870 | − cf->can_id |= CAN_ERR_CNT; | |
| 871 | − cf->data[1] = CAN_ERR_CRTL_ACTIVE; | |
| 872 | − cf->data[6] = bec.txerr; | |
| 873 | − cf->data[7] = bec.rxerr; | |
| 870 | + if (skb) { | |
| 871 | + cf->can_id |= CAN_ERR_CNT; | |
| 872 | + cf->data[1] = CAN_ERR_CRTL_ACTIVE; | |
| 873 | + cf->data[6] = bec.txerr; | |
| 874 | + cf->data[7] = bec.rxerr; | |
| 875 | + } | |
| 874 | 876 | break; |
| 875 | 877 | default: |
| 876 | 878 | netdev_warn(ndev, "unhandled error state (%d:%s)!\n", |
| @@ -622,7 +622,7 @@ rkcanfd_handle_rx_fifo_overflow_int(struct rkcanfd_priv *priv) · 621 unmodified lines | ||
| 622 | 622 | netdev_dbg(priv->ndev, "RX-FIFO overflow\n"); |
| 623 | 623 | |
| 624 | 624 | skb = rkcanfd_alloc_can_err_skb(priv, &cf, ×tamp); |
| 625 | − if (skb) | |
| 625 | + if (!skb) | |
| 626 | 626 | return 0; |
| 627 | 627 | |
| 628 | 628 | rkcanfd_get_berr_counter_corrected(priv, &bec); |
| @@ -248,7 +248,11 @@ static int es58x_devlink_info_get(struct devlink *devlink, · 247 unmodified lines | ||
| 248 | 248 | return ret; |
| 249 | 249 | } |
| 250 | 250 | |
| 251 | − return devlink_info_serial_number_put(req, es58x_dev->udev->serial); | |
| 251 | + if (es58x_dev->udev->serial) | |
| 252 | + ret = devlink_info_serial_number_put(req, | |
| 253 | + es58x_dev->udev->serial); | |
| 254 | + | |
| 255 | + return ret; | |
| 252 | 256 | } |
| 253 | 257 | |
| 254 | 258 | const struct devlink_ops es58x_dl_ops = { |
| @@ -2903,8 +2903,8 @@ static void iavf_watchdog_task(struct work_struct *work) · 2902 unmodified lines | ||
| 2903 | 2903 | } |
| 2904 | 2904 | |
| 2905 | 2905 | mutex_unlock(&adapter->crit_lock); |
| 2906 | − netdev_unlock(netdev); | |
| 2907 | 2906 | restart_watchdog: |
| 2907 | + netdev_unlock(netdev); | |
| 2908 | 2908 | if (adapter->state >= __IAVF_DOWN) |
| 2909 | 2909 | queue_work(adapter->wq, &adapter->adminq_task); |
| 2910 | 2910 | if (adapter->aq_required) |
| @@ -2159,8 +2159,13 @@ static int idpf_open(struct net_device *netdev) · 2158 unmodified lines | ||
| 2159 | 2159 | idpf_vport_ctrl_lock(netdev); |
| 2160 | 2160 | vport = idpf_netdev_to_vport(netdev); |
| 2161 | 2161 | |
| 2162 | + err = idpf_set_real_num_queues(vport); | |
| 2163 | + if (err) | |
| 2164 | + goto unlock; | |
| 2165 | + | |
| 2162 | 2166 | err = idpf_vport_open(vport); |
| 2163 | 2167 | |
| 2168 | +unlock: | |
| 2164 | 2169 | idpf_vport_ctrl_unlock(netdev); |
| 2165 | 2170 | |
| 2166 | 2171 | return err; |
| @@ -3008,8 +3008,6 @@ static int idpf_rx_rsc(struct idpf_rx_queue *rxq, struct sk_buff *skb, · 3007 unmodified lines | ||
| 3008 | 3008 | return -EINVAL; |
| 3009 | 3009 | |
| 3010 | 3010 | rsc_segments = DIV_ROUND_UP(skb->data_len, rsc_seg_len); |
| 3011 | − if (unlikely(rsc_segments == 1)) | |
| 3012 | − return 0; | |
| 3013 | 3011 | |
| 3014 | 3012 | NAPI_GRO_CB(skb)->count = rsc_segments; |
| 3015 | 3013 | skb_shinfo(skb)->gso_size = rsc_seg_len; |
| @@ -3072,6 +3070,7 @@ idpf_rx_process_skb_fields(struct idpf_rx_queue *rxq, struct sk_buff *skb, · 56 unmodified lines | ||
| 3072 | 3070 | idpf_rx_hash(rxq, skb, rx_desc, decoded); |
| 3073 | 3071 | |
| 3074 | 3072 | skb->protocol = eth_type_trans(skb, rxq->netdev); |
| 3073 | + skb_record_rx_queue(skb, rxq->idx); | |
| 3075 | 3074 | |
| 3076 | 3075 | if (le16_get_bits(rx_desc->hdrlen_flags, |
| 3077 | 3076 | VIRTCHNL2_RX_FLEX_DESC_ADV_RSC_M)) |
| @@ -3080,8 +3079,6 @@ idpf_rx_process_skb_fields(struct idpf_rx_queue *rxq, struct sk_buff *skb, · 2 unmodified lines | ||
| 3080 | 3079 | csum_bits = idpf_rx_splitq_extract_csum_bits(rx_desc); |
| 3081 | 3080 | idpf_rx_csum(rxq, skb, csum_bits, decoded); |
| 3082 | 3081 | |
| 3083 | − skb_record_rx_queue(skb, rxq->idx); | |
| 3084 | − | |
| 3085 | 3082 | return 0; |
| 3086 | 3083 | } |
| 3087 | 3084 | |
| @@ -1096,6 +1096,7 @@ static int igc_init_empty_frame(struct igc_ring *ring, · 1095 unmodified lines | ||
| 1096 | 1096 | return -ENOMEM; |
| 1097 | 1097 | } |
| 1098 | 1098 | |
| 1099 | + buffer->type = IGC_TX_BUFFER_TYPE_SKB; | |
| 1099 | 1100 | buffer->skb = skb; |
| 1100 | 1101 | buffer->protocol = 0; |
| 1101 | 1102 | buffer->bytecount = skb->len; |
| @@ -2701,8 +2702,9 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget) · 1599 unmodified lines | ||
| 2701 | 2702 | } |
| 2702 | 2703 | |
| 2703 | 2704 | static struct sk_buff *igc_construct_skb_zc(struct igc_ring *ring, |
| 2704 | − struct xdp_buff *xdp) | |
| 2705 | + struct igc_xdp_buff *ctx) | |
| 2705 | 2706 | { |
| 2707 | + struct xdp_buff *xdp = &ctx->xdp; | |
| 2706 | 2708 | unsigned int totalsize = xdp->data_end - xdp->data_meta; |
| 2707 | 2709 | unsigned int metasize = xdp->data - xdp->data_meta; |
| 2708 | 2710 | struct sk_buff *skb; |
| @@ -2721,27 +2723,28 @@ static struct sk_buff *igc_construct_skb_zc(struct igc_ring *ring, · 12 unmodified lines | ||
| 2721 | 2723 | __skb_pull(skb, metasize); |
| 2722 | 2724 | } |
| 2723 | 2725 | |
| 2726 | + if (ctx->rx_ts) { | |
| 2727 | + skb_shinfo(skb)->tx_flags |= SKBTX_HW_TSTAMP_NETDEV; | |
| 2728 | + skb_hwtstamps(skb)->netdev_data = ctx->rx_ts; | |
| 2729 | + } | |
| 2730 | + | |
| 2724 | 2731 | return skb; |
| 2725 | 2732 | } |
| 2726 | 2733 | |
| 2727 | 2734 | static void igc_dispatch_skb_zc(struct igc_q_vector *q_vector, |
| 2728 | 2735 | union igc_adv_rx_desc *desc, |
| 2729 | − struct xdp_buff *xdp, | |
| 2730 | − ktime_t timestamp) | |
| 2736 | + struct igc_xdp_buff *ctx) | |
| 2731 | 2737 | { |
| 2732 | 2738 | struct igc_ring *ring = q_vector->rx.ring; |
| 2733 | 2739 | struct sk_buff *skb; |
| 2734 | 2740 | |
| 2735 | − skb = igc_construct_skb_zc(ring, xdp); | |
| 2741 | + skb = igc_construct_skb_zc(ring, ctx); | |
| 2736 | 2742 | if (!skb) { |
| 2737 | 2743 | ring->rx_stats.alloc_failed++; |
| 2738 | 2744 | set_bit(IGC_RING_FLAG_RX_ALLOC_FAILED, &ring->flags); |
| 2739 | 2745 | return; |
| 2740 | 2746 | } |
| 2741 | 2747 | |
| 2742 | − if (timestamp) | |
| 2743 | − skb_hwtstamps(skb)->hwtstamp = timestamp; | |
| 2744 | − | |
| 2745 | 2748 | if (igc_cleanup_headers(ring, desc, skb)) |
| 2746 | 2749 | return; |
| 2747 | 2750 | |
| @@ -2777,7 +2780,6 @@ static int igc_clean_rx_irq_zc(struct igc_q_vector *q_vector, const int budget) · 29 unmodified lines | ||
| 2777 | 2780 | union igc_adv_rx_desc *desc; |
| 2778 | 2781 | struct igc_rx_buffer *bi; |
| 2779 | 2782 | struct igc_xdp_buff *ctx; |
| 2780 | − ktime_t timestamp = 0; | |
| 2781 | 2783 | unsigned int size; |
| 2782 | 2784 | int res; |
| 2783 | 2785 | |
| @@ -2807,6 +2809,8 @@ static int igc_clean_rx_irq_zc(struct igc_q_vector *q_vector, const int budget) · 23 unmodified lines | ||
| 2807 | 2809 | */ |
| 2808 | 2810 | bi->xdp->data_meta += IGC_TS_HDR_LEN; |
| 2809 | 2811 | size -= IGC_TS_HDR_LEN; |
| 2812 | + } else { | |
| 2813 | + ctx->rx_ts = NULL; | |
| 2810 | 2814 | } |
| 2811 | 2815 | |
| 2812 | 2816 | bi->xdp->data_end = bi->xdp->data + size; |
| @@ -2815,7 +2819,7 @@ static int igc_clean_rx_irq_zc(struct igc_q_vector *q_vector, const int budget) · 2 unmodified lines | ||
| 2815 | 2819 | res = __igc_xdp_run_prog(adapter, prog, bi->xdp); |
| 2816 | 2820 | switch (res) { |
| 2817 | 2821 | case IGC_XDP_PASS: |
| 2818 | − igc_dispatch_skb_zc(q_vector, desc, bi->xdp, timestamp); | |
| 2822 | + igc_dispatch_skb_zc(q_vector, desc, ctx); | |
| 2819 | 2823 | fallthrough; |
| 2820 | 2824 | case IGC_XDP_CONSUMED: |
| 2821 | 2825 | xsk_buff_free(bi->xdp); |
| @@ -2105,7 +2105,7 @@ static void ixgbe_put_rx_buffer(struct ixgbe_ring *rx_ring, · 2104 unmodified lines | ||
| 2105 | 2105 | /* hand second half of page back to the ring */ |
| 2106 | 2106 | ixgbe_reuse_rx_page(rx_ring, rx_buffer); |
| 2107 | 2107 | } else { |
| 2108 | − if (!IS_ERR(skb) && IXGBE_CB(skb)->dma == rx_buffer->dma) { | |
| 2108 | + if (skb && IXGBE_CB(skb)->dma == rx_buffer->dma) { | |
| 2109 | 2109 | /* the page has been released from the ring */ |
| 2110 | 2110 | IXGBE_CB(skb)->page_released = true; |
| 2111 | 2111 | } else { |
| @@ -768,7 +768,9 @@ static void __mlxsw_sp_port_get_stats(struct net_device *dev, · 767 unmodified lines | ||
| 768 | 768 | err = mlxsw_sp_get_hw_stats_by_group(&hw_stats, &len, grp); |
| 769 | 769 | if (err) |
| 770 | 770 | return; |
| 771 | − mlxsw_sp_port_get_stats_raw(dev, grp, prio, ppcnt_pl); | |
| 771 | + err = mlxsw_sp_port_get_stats_raw(dev, grp, prio, ppcnt_pl); | |
| 772 | + if (err) | |
| 773 | + return; | |
| 772 | 774 | for (i = 0; i < len; i++) { |
| 773 | 775 | data[data_index + i] = hw_stats[i].getter(ppcnt_pl); |
| 774 | 776 | if (!hw_stats[i].cells_bytes) |
| @@ -2094,6 +2094,11 @@ static int __alloc_dma_rx_desc_resources(struct stmmac_priv *priv, · 2093 unmodified lines | ||
| 2094 | 2094 | pp_params.offset = stmmac_rx_offset(priv); |
| 2095 | 2095 | pp_params.max_len = dma_conf->dma_buf_sz; |
| 2096 | 2096 | |
| 2097 | + if (priv->sph) { | |
| 2098 | + pp_params.offset = 0; | |
| 2099 | + pp_params.max_len += stmmac_rx_offset(priv); | |
| 2100 | + } | |
| 2101 | + | |
| 2097 | 2102 | rx_q->page_pool = page_pool_create(&pp_params); |
| 2098 | 2103 | if (IS_ERR(rx_q->page_pool)) { |
| 2099 | 2104 | ret = PTR_ERR(rx_q->page_pool); |
| @@ -828,21 +828,30 @@ static void am65_cpsw_nuss_xmit_free(struct am65_cpsw_tx_chn *tx_chn, · 827 unmodified lines | ||
| 828 | 828 | static void am65_cpsw_nuss_tx_cleanup(void *data, dma_addr_t desc_dma) |
| 829 | 829 | { |
| 830 | 830 | struct am65_cpsw_tx_chn *tx_chn = data; |
| 831 | + enum am65_cpsw_tx_buf_type buf_type; | |
| 831 | 832 | struct cppi5_host_desc_t *desc_tx; |
| 833 | + struct xdp_frame *xdpf; | |
| 832 | 834 | struct sk_buff *skb; |
| 833 | 835 | void **swdata; |
| 834 | 836 | |
| 835 | 837 | desc_tx = k3_cppi_desc_pool_dma2virt(tx_chn->desc_pool, desc_dma); |
| 836 | 838 | swdata = cppi5_hdesc_get_swdata(desc_tx); |
| 837 | − skb = *(swdata); | |
| 838 | − am65_cpsw_nuss_xmit_free(tx_chn, desc_tx); | |
| 839 | + buf_type = am65_cpsw_nuss_buf_type(tx_chn, desc_dma); | |
| 840 | + if (buf_type == AM65_CPSW_TX_BUF_TYPE_SKB) { | |
| 841 | + skb = *(swdata); | |
| 842 | + dev_kfree_skb_any(skb); | |
| 843 | + } else { | |
| 844 | + xdpf = *(swdata); | |
| 845 | + xdp_return_frame(xdpf); | |
| 846 | + } | |
| 839 | 847 | |
| 840 | − dev_kfree_skb_any(skb); | |
| 848 | + am65_cpsw_nuss_xmit_free(tx_chn, desc_tx); | |
| 841 | 849 | } |
| 842 | 850 | |
| 843 | 851 | static struct sk_buff *am65_cpsw_build_skb(void *page_addr, |
| 844 | 852 | struct net_device *ndev, |
| 845 | − unsigned int len) | |
| 853 | + unsigned int len, | |
| 854 | + unsigned int headroom) | |
| 846 | 855 | { |
| 847 | 856 | struct sk_buff *skb; |
| 848 | 857 | |
| @@ -852,7 +861,7 @@ static struct sk_buff *am65_cpsw_build_skb(void *page_addr, · 3 unmodified lines | ||
| 852 | 861 | if (unlikely(!skb)) |
| 853 | 862 | return NULL; |
| 854 | 863 | |
| 855 | − skb_reserve(skb, AM65_CPSW_HEADROOM); | |
| 864 | + skb_reserve(skb, headroom); | |
| 856 | 865 | skb->dev = ndev; |
| 857 | 866 | |
| 858 | 867 | return skb; |
| @@ -1169,9 +1178,11 @@ static int am65_cpsw_run_xdp(struct am65_cpsw_rx_flow *flow, · 310 unmodified lines | ||
| 1169 | 1178 | struct xdp_frame *xdpf; |
| 1170 | 1179 | struct bpf_prog *prog; |
| 1171 | 1180 | struct page *page; |
| 1181 | + int pkt_len; | |
| 1172 | 1182 | u32 act; |
| 1173 | 1183 | int err; |
| 1174 | 1184 | |
| 1185 | + pkt_len = *len; | |
| 1175 | 1186 | prog = READ_ONCE(port->xdp_prog); |
| 1176 | 1187 | if (!prog) |
| 1177 | 1188 | return AM65_CPSW_XDP_PASS; |
| @@ -1189,8 +1200,10 @@ static int am65_cpsw_run_xdp(struct am65_cpsw_rx_flow *flow, · 11 unmodified lines | ||
| 1189 | 1200 | netif_txq = netdev_get_tx_queue(ndev, tx_chn->id); |
| 1190 | 1201 | |
| 1191 | 1202 | xdpf = xdp_convert_buff_to_frame(xdp); |
| 1192 | − if (unlikely(!xdpf)) | |
| 1203 | + if (unlikely(!xdpf)) { | |
| 1204 | + ndev->stats.tx_dropped++; | |
| 1193 | 1205 | goto drop; |
| 1206 | + } | |
| 1194 | 1207 | |
| 1195 | 1208 | __netif_tx_lock(netif_txq, cpu); |
| 1196 | 1209 | err = am65_cpsw_xdp_tx_frame(ndev, tx_chn, xdpf, |
| @@ -1199,14 +1212,14 @@ static int am65_cpsw_run_xdp(struct am65_cpsw_rx_flow *flow, · 2 unmodified lines | ||
| 1199 | 1212 | if (err) |
| 1200 | 1213 | goto drop; |
| 1201 | 1214 | |
| 1202 | − dev_sw_netstats_tx_add(ndev, 1, *len); | |
| 1215 | + dev_sw_netstats_rx_add(ndev, pkt_len); | |
| 1203 | 1216 | ret = AM65_CPSW_XDP_CONSUMED; |
| 1204 | 1217 | goto out; |
| 1205 | 1218 | case XDP_REDIRECT: |
| 1206 | 1219 | if (unlikely(xdp_do_redirect(ndev, xdp, prog))) |
| 1207 | 1220 | goto drop; |
| 1208 | 1221 | |
| 1209 | − dev_sw_netstats_rx_add(ndev, *len); | |
| 1222 | + dev_sw_netstats_rx_add(ndev, pkt_len); | |
| 1210 | 1223 | ret = AM65_CPSW_XDP_REDIRECT; |
| 1211 | 1224 | goto out; |
| 1212 | 1225 | default: |
| @@ -1315,16 +1328,8 @@ static int am65_cpsw_nuss_rx_packets(struct am65_cpsw_rx_flow *flow, · 102 unmodified lines | ||
| 1315 | 1328 | dev_dbg(dev, "%s rx csum_info:%#x\n", __func__, csum_info); |
| 1316 | 1329 | |
| 1317 | 1330 | dma_unmap_single(rx_chn->dma_dev, buf_dma, buf_dma_len, DMA_FROM_DEVICE); |
| 1318 | − | |
| 1319 | 1331 | k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx); |
| 1320 | 1332 | |
| 1321 | − skb = am65_cpsw_build_skb(page_addr, ndev, | |
| 1322 | − AM65_CPSW_MAX_PACKET_SIZE); | |
| 1323 | − if (unlikely(!skb)) { | |
| 1324 | − new_page = page; | |
| 1325 | − goto requeue; | |
| 1326 | − } | |
| 1327 | − | |
| 1328 | 1333 | if (port->xdp_prog) { |
| 1329 | 1334 | xdp_init_buff(&xdp, PAGE_SIZE, &port->xdp_rxq[flow->id]); |
| 1330 | 1335 | xdp_prepare_buff(&xdp, page_addr, AM65_CPSW_HEADROOM, |
| @@ -1334,9 +1339,16 @@ static int am65_cpsw_nuss_rx_packets(struct am65_cpsw_rx_flow *flow, · 3 unmodified lines | ||
| 1334 | 1339 | if (*xdp_state != AM65_CPSW_XDP_PASS) |
| 1335 | 1340 | goto allocate; |
| 1336 | 1341 | |
| 1337 | − /* Compute additional headroom to be reserved */ | |
| 1338 | − headroom = (xdp.data - xdp.data_hard_start) - skb_headroom(skb); | |
| 1339 | − skb_reserve(skb, headroom); | |
| 1342 | + headroom = xdp.data - xdp.data_hard_start; | |
| 1343 | + } else { | |
| 1344 | + headroom = AM65_CPSW_HEADROOM; | |
| 1345 | + } | |
| 1346 | + | |
| 1347 | + skb = am65_cpsw_build_skb(page_addr, ndev, | |
| 1348 | + AM65_CPSW_MAX_PACKET_SIZE, headroom); | |
| 1349 | + if (unlikely(!skb)) { | |
| 1350 | + new_page = page; | |
| 1351 | + goto requeue; | |
| 1340 | 1352 | } |
| 1341 | 1353 | |
| 1342 | 1354 | ndev_priv = netdev_priv(ndev); |
| @@ -2265,12 +2265,15 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy, · 2264 unmodified lines | ||
| 2265 | 2265 | /* Allow the MAC to stop its clock if the PHY has the capability */ |
| 2266 | 2266 | pl->mac_tx_clk_stop = phy_eee_tx_clock_stop_capable(phy) > 0; |
| 2267 | 2267 | |
| 2268 | − /* Explicitly configure whether the PHY is allowed to stop it's | |
| 2269 | − * receive clock. | |
| 2270 | − */ | |
| 2271 | − ret = phy_eee_rx_clock_stop(phy, pl->config->eee_rx_clk_stop_enable); | |
| 2272 | − if (ret == -EOPNOTSUPP) | |
| 2273 | − ret = 0; | |
| 2268 | + if (pl->mac_supports_eee_ops) { | |
| 2269 | + /* Explicitly configure whether the PHY is allowed to stop it's | |
| 2270 | + * receive clock. | |
| 2271 | + */ | |
| 2272 | + ret = phy_eee_rx_clock_stop(phy, | |
| 2273 | + pl->config->eee_rx_clk_stop_enable); | |
| 2274 | + if (ret == -EOPNOTSUPP) | |
| 2275 | + ret = 0; | |
| 2276 | + } | |
| 2274 | 2277 | |
| 2275 | 2278 | return ret; |
| 2276 | 2279 | } |
| @@ -319,7 +319,7 @@ static int pse_pi_get_current_limit(struct regulator_dev *rdev) · 318 unmodified lines | ||
| 319 | 319 | goto out; |
| 320 | 320 | mW = ret; |
| 321 | 321 | |
| 322 | − ret = pse_pi_get_voltage(rdev); | |
| 322 | + ret = _pse_pi_get_voltage(rdev); | |
| 323 | 323 | if (!ret) { |
| 324 | 324 | dev_err(pcdev->dev, "Voltage null\n"); |
| 325 | 325 | ret = -ERANGE; |
| @@ -356,7 +356,7 @@ static int pse_pi_set_current_limit(struct regulator_dev *rdev, int min_uA, · 30 unmodified lines | ||
| 356 | 356 | |
| 357 | 357 | id = rdev_get_id(rdev); |
| 358 | 358 | mutex_lock(&pcdev->lock); |
| 359 | − ret = pse_pi_get_voltage(rdev); | |
| 359 | + ret = _pse_pi_get_voltage(rdev); | |
| 360 | 360 | if (!ret) { |
| 361 | 361 | dev_err(pcdev->dev, "Voltage null\n"); |
| 362 | 362 | ret = -ERANGE; |
| @@ -2639,7 +2639,9 @@ int team_nl_options_set_doit(struct sk_buff *skb, struct genl_info *info) · 2638 unmodified lines | ||
| 2639 | 2639 | ctx.data.u32_val = nla_get_u32(attr_data); |
| 2640 | 2640 | break; |
| 2641 | 2641 | case TEAM_OPTION_TYPE_STRING: |
| 2642 | − if (nla_len(attr_data) > TEAM_STRING_MAX_LEN) { | |
| 2642 | + if (nla_len(attr_data) > TEAM_STRING_MAX_LEN || | |
| 2643 | + !memchr(nla_data(attr_data), '\0', | |
| 2644 | + nla_len(attr_data))) { | |
| 2643 | 2645 | err = -EINVAL; |
| 2644 | 2646 | goto team_put; |
| 2645 | 2647 | } |
| @@ -2898,8 +2898,11 @@ static int vxlan_init(struct net_device *dev) · 2897 unmodified lines | ||
| 2898 | 2898 | struct vxlan_dev *vxlan = netdev_priv(dev); |
| 2899 | 2899 | int err; |
| 2900 | 2900 | |
| 2901 | − if (vxlan->cfg.flags & VXLAN_F_VNIFILTER) | |
| 2902 | − vxlan_vnigroup_init(vxlan); | |
| 2901 | + if (vxlan->cfg.flags & VXLAN_F_VNIFILTER) { | |
| 2902 | + err = vxlan_vnigroup_init(vxlan); | |
| 2903 | + if (err) | |
| 2904 | + return err; | |
| 2905 | + } | |
| 2903 | 2906 | |
| 2904 | 2907 | err = gro_cells_init(&vxlan->gro_cells, dev); |
| 2905 | 2908 | if (err) |
| @@ -4851,6 +4851,22 @@ static struct ath12k_reg_rule · 4850 unmodified lines | ||
| 4851 | 4851 | return reg_rule_ptr; |
| 4852 | 4852 | } |
| 4853 | 4853 | |
| 4854 | +static u8 ath12k_wmi_ignore_num_extra_rules(struct ath12k_wmi_reg_rule_ext_params *rule, | |
| 4855 | + u32 num_reg_rules) | |
| 4856 | +{ | |
| 4857 | + u8 num_invalid_5ghz_rules = 0; | |
| 4858 | + u32 count, start_freq; | |
| 4859 | + | |
| 4860 | + for (count = 0; count < num_reg_rules; count++) { | |
| 4861 | + start_freq = le32_get_bits(rule[count].freq_info, REG_RULE_START_FREQ); | |
| 4862 | + | |
| 4863 | + if (start_freq >= ATH12K_MIN_6G_FREQ) | |
| 4864 | + num_invalid_5ghz_rules++; | |
| 4865 | + } | |
| 4866 | + | |
| 4867 | + return num_invalid_5ghz_rules; | |
| 4868 | +} | |
| 4869 | + | |
| 4854 | 4870 | static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab, |
| 4855 | 4871 | struct sk_buff *skb, |
| 4856 | 4872 | struct ath12k_reg_info *reg_info) |
| @@ -4861,6 +4877,7 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab, · 4 unmodified lines | ||
| 4861 | 4877 | u32 num_2g_reg_rules, num_5g_reg_rules; |
| 4862 | 4878 | u32 num_6g_reg_rules_ap[WMI_REG_CURRENT_MAX_AP_TYPE]; |
| 4863 | 4879 | u32 num_6g_reg_rules_cl[WMI_REG_CURRENT_MAX_AP_TYPE][WMI_REG_MAX_CLIENT_TYPE]; |
| 4880 | + u8 num_invalid_5ghz_ext_rules; | |
| 4864 | 4881 | u32 total_reg_rules = 0; |
| 4865 | 4882 | int ret, i, j; |
| 4866 | 4883 | |
| @@ -4954,20 +4971,6 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab, · 87 unmodified lines | ||
| 4954 | 4971 | |
| 4955 | 4972 | memcpy(reg_info->alpha2, &ev->alpha2, REG_ALPHA2_LEN); |
| 4956 | 4973 | |
| 4957 | − /* FIXME: Currently FW includes 6G reg rule also in 5G rule | |
| 4958 | − * list for country US. | |
| 4959 | − * Having same 6G reg rule in 5G and 6G rules list causes | |
| 4960 | − * intersect check to be true, and same rules will be shown | |
| 4961 | − * multiple times in iw cmd. So added hack below to avoid | |
| 4962 | − * parsing 6G rule from 5G reg rule list, and this can be | |
| 4963 | − * removed later, after FW updates to remove 6G reg rule | |
| 4964 | − * from 5G rules list. | |
| 4965 | − */ | |
| 4966 | − if (memcmp(reg_info->alpha2, "US", 2) == 0) { | |
| 4967 | − reg_info->num_5g_reg_rules = REG_US_5G_NUM_REG_RULES; | |
| 4968 | − num_5g_reg_rules = reg_info->num_5g_reg_rules; | |
| 4969 | − } | |
| 4970 | − | |
| 4971 | 4974 | reg_info->dfs_region = le32_to_cpu(ev->dfs_region); |
| 4972 | 4975 | reg_info->phybitmap = le32_to_cpu(ev->phybitmap); |
| 4973 | 4976 | reg_info->num_phy = le32_to_cpu(ev->num_phy); |
| @@ -5070,8 +5073,29 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab, · 96 unmodified lines | ||
| 5070 | 5073 | } |
| 5071 | 5074 | } |
| 5072 | 5075 | |
| 5076 | + ext_wmi_reg_rule += num_2g_reg_rules; | |
| 5077 | + | |
| 5078 | + /* Firmware might include 6 GHz reg rule in 5 GHz rule list | |
| 5079 | + * for few countries along with separate 6 GHz rule. | |
| 5080 | + * Having same 6 GHz reg rule in 5 GHz and 6 GHz rules list | |
| 5081 | + * causes intersect check to be true, and same rules will be | |
| 5082 | + * shown multiple times in iw cmd. | |
| 5083 | + * Hence, avoid parsing 6 GHz rule from 5 GHz reg rule list | |
| 5084 | + */ | |
| 5085 | + num_invalid_5ghz_ext_rules = ath12k_wmi_ignore_num_extra_rules(ext_wmi_reg_rule, | |
| 5086 | + num_5g_reg_rules); | |
| 5087 | + | |
| 5088 | + if (num_invalid_5ghz_ext_rules) { | |
| 5089 | + ath12k_dbg(ab, ATH12K_DBG_WMI, | |
| 5090 | + "CC: %s 5 GHz reg rules number %d from fw, %d number of invalid 5 GHz rules", | |
| 5091 | + reg_info->alpha2, reg_info->num_5g_reg_rules, | |
| 5092 | + num_invalid_5ghz_ext_rules); | |
| 5093 | + | |
| 5094 | + num_5g_reg_rules = num_5g_reg_rules - num_invalid_5ghz_ext_rules; | |
| 5095 | + reg_info->num_5g_reg_rules = num_5g_reg_rules; | |
| 5096 | + } | |
| 5097 | + | |
| 5073 | 5098 | if (num_5g_reg_rules) { |
| 5074 | − ext_wmi_reg_rule += num_2g_reg_rules; | |
| 5075 | 5099 | reg_info->reg_rules_5g_ptr = |
| 5076 | 5100 | create_ext_reg_rules_from_wmi(num_5g_reg_rules, |
| 5077 | 5101 | ext_wmi_reg_rule); |
| @@ -5083,7 +5107,12 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab, · 5 unmodified lines | ||
| 5083 | 5107 | } |
| 5084 | 5108 | } |
| 5085 | 5109 | |
| 5086 | − ext_wmi_reg_rule += num_5g_reg_rules; | |
| 5110 | + /* We have adjusted the number of 5 GHz reg rules above. But still those | |
| 5111 | + * many rules needs to be adjusted in ext_wmi_reg_rule. | |
| 5112 | + * | |
| 5113 | + * NOTE: num_invalid_5ghz_ext_rules will be 0 for rest other cases. | |
| 5114 | + */ | |
| 5115 | + ext_wmi_reg_rule += (num_5g_reg_rules + num_invalid_5ghz_ext_rules); | |
| 5087 | 5116 | |
| 5088 | 5117 | for (i = 0; i < WMI_REG_CURRENT_MAX_AP_TYPE; i++) { |
| 5089 | 5118 | reg_info->reg_rules_6g_ap_ptr[i] = |
| @@ -4073,7 +4073,6 @@ struct ath12k_wmi_eht_rate_set_params { · 4072 unmodified lines | ||
| 4073 | 4073 | #define MAX_REG_RULES 10 |
| 4074 | 4074 | #define REG_ALPHA2_LEN 2 |
| 4075 | 4075 | #define MAX_6G_REG_RULES 5 |
| 4076 | −#define REG_US_5G_NUM_REG_RULES 4 | |
| 4077 | 4076 | |
| 4078 | 4077 | enum wmi_start_event_param { |
| 4079 | 4078 | WMI_VDEV_START_RESP_EVENT = 0, |
| @@ -2712,7 +2712,7 @@ static const struct pci_device_id brcmf_pcie_devid_table[] = { · 2711 unmodified lines | ||
| 2712 | 2712 | BRCMF_PCIE_DEVICE(BRCM_PCIE_4350_DEVICE_ID, WCC), |
| 2713 | 2713 | BRCMF_PCIE_DEVICE_SUB(0x4355, BRCM_PCIE_VENDOR_ID_BROADCOM, 0x4355, WCC), |
| 2714 | 2714 | BRCMF_PCIE_DEVICE(BRCM_PCIE_4354_RAW_DEVICE_ID, WCC), |
| 2715 | − BRCMF_PCIE_DEVICE(BRCM_PCIE_4355_DEVICE_ID, WCC), | |
| 2715 | + BRCMF_PCIE_DEVICE(BRCM_PCIE_4355_DEVICE_ID, WCC_SEED), | |
| 2716 | 2716 | BRCMF_PCIE_DEVICE(BRCM_PCIE_4356_DEVICE_ID, WCC), |
| 2717 | 2717 | BRCMF_PCIE_DEVICE(BRCM_PCIE_43567_DEVICE_ID, WCC), |
| 2718 | 2718 | BRCMF_PCIE_DEVICE(BRCM_PCIE_43570_DEVICE_ID, WCC), |
| @@ -2723,7 +2723,7 @@ static const struct pci_device_id brcmf_pcie_devid_table[] = { · 4 unmodified lines | ||
| 2723 | 2723 | BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_2G_DEVICE_ID, WCC), |
| 2724 | 2724 | BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_5G_DEVICE_ID, WCC), |
| 2725 | 2725 | BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_RAW_DEVICE_ID, WCC), |
| 2726 | − BRCMF_PCIE_DEVICE(BRCM_PCIE_4364_DEVICE_ID, WCC), | |
| 2726 | + BRCMF_PCIE_DEVICE(BRCM_PCIE_4364_DEVICE_ID, WCC_SEED), | |
| 2727 | 2727 | BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_DEVICE_ID, BCA), |
| 2728 | 2728 | BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_2G_DEVICE_ID, BCA), |
| 2729 | 2729 | BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_5G_DEVICE_ID, BCA), |
| @@ -414,16 +414,16 @@ static ssize_t vmclock_miscdev_read(struct file *fp, char __user *buf, · 413 unmodified lines | ||
| 414 | 414 | } |
| 415 | 415 | |
| 416 | 416 | static const struct file_operations vmclock_miscdev_fops = { |
| 417 | + .owner = THIS_MODULE, | |
| 417 | 418 | .mmap = vmclock_miscdev_mmap, |
| 418 | 419 | .read = vmclock_miscdev_read, |
| 419 | 420 | }; |
| 420 | 421 | |
| 421 | 422 | /* module operations */ |
| 422 | 423 | |
| 423 | −static void vmclock_remove(struct platform_device *pdev) | |
| 424 | +static void vmclock_remove(void *data) | |
| 424 | 425 | { |
| 425 | − struct device *dev = &pdev->dev; | |
| 426 | − struct vmclock_state *st = dev_get_drvdata(dev); | |
| 426 | + struct vmclock_state *st = data; | |
| 427 | 427 | |
| 428 | 428 | if (st->ptp_clock) |
| 429 | 429 | ptp_clock_unregister(st->ptp_clock); |
| @@ -506,14 +506,13 @@ static int vmclock_probe(struct platform_device *pdev) · 76 unmodified lines | ||
| 506 | 506 | |
| 507 | 507 | if (ret) { |
| 508 | 508 | dev_info(dev, "Failed to obtain physical address: %d\n", ret); |
| 509 | − goto out; | |
| 509 | + return ret; | |
| 510 | 510 | } |
| 511 | 511 | |
| 512 | 512 | if (resource_size(&st->res) < VMCLOCK_MIN_SIZE) { |
| 513 | 513 | dev_info(dev, "Region too small (0x%llx)\n", |
| 514 | 514 | resource_size(&st->res)); |
| 515 | − ret = -EINVAL; | |
| 516 | − goto out; | |
| 515 | + return -EINVAL; | |
| 517 | 516 | } |
| 518 | 517 | st->clk = devm_memremap(dev, st->res.start, resource_size(&st->res), |
| 519 | 518 | MEMREMAP_WB | MEMREMAP_DEC); |
| @@ -521,31 +520,34 @@ static int vmclock_probe(struct platform_device *pdev) · 1 unmodified line | ||
| 521 | 520 | ret = PTR_ERR(st->clk); |
| 522 | 521 | dev_info(dev, "failed to map shared memory\n"); |
| 523 | 522 | st->clk = NULL; |
| 524 | − goto out; | |
| 523 | + return ret; | |
| 525 | 524 | } |
| 526 | 525 | |
| 527 | 526 | if (le32_to_cpu(st->clk->magic) != VMCLOCK_MAGIC || |
| 528 | 527 | le32_to_cpu(st->clk->size) > resource_size(&st->res) || |
| 529 | 528 | le16_to_cpu(st->clk->version) != 1) { |
| 530 | 529 | dev_info(dev, "vmclock magic fields invalid\n"); |
| 531 | − ret = -EINVAL; | |
| 532 | − goto out; | |
| 530 | + return -EINVAL; | |
| 533 | 531 | } |
| 534 | 532 | |
| 535 | 533 | ret = ida_alloc(&vmclock_ida, GFP_KERNEL); |
| 536 | 534 | if (ret < 0) |
| 537 | − goto out; | |
| 535 | + return ret; | |
| 538 | 536 | |
| 539 | 537 | st->index = ret; |
| 540 | 538 | ret = devm_add_action_or_reset(&pdev->dev, vmclock_put_idx, st); |
| 541 | 539 | if (ret) |
| 542 | − goto out; | |
| 540 | + return ret; | |
| 543 | 541 | |
| 544 | 542 | st->name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "vmclock%d", st->index); |
| 545 | − if (!st->name) { | |
| 546 | − ret = -ENOMEM; | |
| 547 | − goto out; | |
| 548 | − } | |
| 543 | + if (!st->name) | |
| 544 | + return -ENOMEM; | |
| 545 | + | |
| 546 | + st->miscdev.minor = MISC_DYNAMIC_MINOR; | |
| 547 | + | |
| 548 | + ret = devm_add_action_or_reset(&pdev->dev, vmclock_remove, st); | |
| 549 | + if (ret) | |
| 550 | + return ret; | |
| 549 | 551 | |
| 550 | 552 | /* |
| 551 | 553 | * If the structure is big enough, it can be mapped to userspace. |
| @@ -554,13 +556,12 @@ static int vmclock_probe(struct platform_device *pdev) · 2 unmodified lines | ||
| 554 | 556 | * cross that bridge if/when we come to it. |
| 555 | 557 | */ |
| 556 | 558 | if (le32_to_cpu(st->clk->size) >= PAGE_SIZE) { |
| 557 | − st->miscdev.minor = MISC_DYNAMIC_MINOR; | |
| 558 | 559 | st->miscdev.fops = &vmclock_miscdev_fops; |
| 559 | 560 | st->miscdev.name = st->name; |
| 560 | 561 | |
| 561 | 562 | ret = misc_register(&st->miscdev); |
| 562 | 563 | if (ret) |
| 563 | − goto out; | |
| 564 | + return ret; | |
| 564 | 565 | } |
| 565 | 566 | |
| 566 | 567 | /* If there is valid clock information, register a PTP clock */ |
| @@ -570,16 +571,14 @@ static int vmclock_probe(struct platform_device *pdev) · 3 unmodified lines | ||
| 570 | 571 | if (IS_ERR(st->ptp_clock)) { |
| 571 | 572 | ret = PTR_ERR(st->ptp_clock); |
| 572 | 573 | st->ptp_clock = NULL; |
| 573 | − vmclock_remove(pdev); | |
| 574 | − goto out; | |
| 574 | + return ret; | |
| 575 | 575 | } |
| 576 | 576 | } |
| 577 | 577 | |
| 578 | 578 | if (!st->miscdev.minor && !st->ptp_clock) { |
| 579 | 579 | /* Neither miscdev nor PTP registered */ |
| 580 | 580 | dev_info(dev, "vmclock: Neither miscdev nor PTP available; not registering\n"); |
| 581 | − ret = -ENODEV; | |
| 582 | − goto out; | |
| 581 | + return -ENODEV; | |
| 583 | 582 | } |
| 584 | 583 | |
| 585 | 584 | dev_info(dev, "%s: registered %s%s%s\n", st->name, |
| @@ -587,10 +586,7 @@ static int vmclock_probe(struct platform_device *pdev) · 1 unmodified line | ||
| 587 | 586 | (st->miscdev.minor && st->ptp_clock) ? ", " : "", |
| 588 | 587 | st->ptp_clock ? "PTP" : ""); |
| 589 | 588 | |
| 590 | − dev_set_drvdata(dev, st); | |
| 591 | − | |
| 592 | − out: | |
| 593 | − return ret; | |
| 589 | + return 0; | |
| 594 | 590 | } |
| 595 | 591 | |
| 596 | 592 | static const struct acpi_device_id vmclock_acpi_ids[] = { |
| @@ -601,7 +597,6 @@ MODULE_DEVICE_TABLE(acpi, vmclock_acpi_ids); · 4 unmodified lines | ||
| 601 | 597 | |
| 602 | 598 | static struct platform_driver vmclock_platform_driver = { |
| 603 | 599 | .probe = vmclock_probe, |
| 604 | − .remove = vmclock_remove, | |
| 605 | 600 | .driver = { |
| 606 | 601 | .name = "vmclock", |
| 607 | 602 | .acpi_match_table = vmclock_acpi_ids, |
| @@ -7050,14 +7050,16 @@ int qeth_open(struct net_device *dev) · 7049 unmodified lines | ||
| 7050 | 7050 | card->data.state = CH_STATE_UP; |
| 7051 | 7051 | netif_tx_start_all_queues(dev); |
| 7052 | 7052 | |
| 7053 | − local_bh_disable(); | |
| 7054 | 7053 | qeth_for_each_output_queue(card, queue, i) { |
| 7055 | 7054 | netif_napi_add_tx(dev, &queue->napi, qeth_tx_poll); |
| 7056 | 7055 | napi_enable(&queue->napi); |
| 7057 | − napi_schedule(&queue->napi); | |
| 7058 | 7056 | } |
| 7059 | − | |
| 7060 | 7057 | napi_enable(&card->napi); |
| 7058 | + | |
| 7059 | + local_bh_disable(); | |
| 7060 | + qeth_for_each_output_queue(card, queue, i) { | |
| 7061 | + napi_schedule(&queue->napi); | |
| 7062 | + } | |
| 7061 | 7063 | napi_schedule(&card->napi); |
| 7062 | 7064 | /* kick-start the NAPI softirq: */ |
| 7063 | 7065 | local_bh_enable(); |
| @@ -2663,6 +2663,12 @@ struct net *dev_net(const struct net_device *dev) · 2662 unmodified lines | ||
| 2663 | 2663 | return read_pnet(&dev->nd_net); |
| 2664 | 2664 | } |
| 2665 | 2665 | |
| 2666 | +static inline | |
| 2667 | +struct net *dev_net_rcu(const struct net_device *dev) | |
| 2668 | +{ | |
| 2669 | + return read_pnet_rcu(&dev->nd_net); | |
| 2670 | +} | |
| 2671 | + | |
| 2666 | 2672 | static inline |
| 2667 | 2673 | void dev_net_set(struct net_device *dev, struct net *net) |
| 2668 | 2674 | { |
| @@ -668,7 +668,7 @@ struct l2cap_conn { · 667 unmodified lines | ||
| 668 | 668 | struct l2cap_chan *smp; |
| 669 | 669 | |
| 670 | 670 | struct list_head chan_l; |
| 671 | − struct mutex chan_lock; | |
| 671 | + struct mutex lock; | |
| 672 | 672 | struct kref ref; |
| 673 | 673 | struct list_head users; |
| 674 | 674 | }; |
| @@ -970,6 +970,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err); · 295 unmodified lines | ||
| 970 | 970 | void l2cap_send_conn_req(struct l2cap_chan *chan); |
| 971 | 971 | |
| 972 | 972 | struct l2cap_conn *l2cap_conn_get(struct l2cap_conn *conn); |
| 973 | +struct l2cap_conn *l2cap_conn_hold_unless_zero(struct l2cap_conn *conn); | |
| 973 | 974 | void l2cap_conn_put(struct l2cap_conn *conn); |
| 974 | 975 | |
| 975 | 976 | int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user); |
| @@ -471,9 +471,12 @@ static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst, · 470 unmodified lines | ||
| 471 | 471 | bool forwarding) |
| 472 | 472 | { |
| 473 | 473 | const struct rtable *rt = dst_rtable(dst); |
| 474 | − struct net *net = dev_net(dst->dev); | |
| 475 | − unsigned int mtu; | |
| 474 | + unsigned int mtu, res; | |
| 475 | + struct net *net; | |
| 476 | + | |
| 477 | + rcu_read_lock(); | |
| 476 | 478 | |
| 479 | + net = dev_net_rcu(dst->dev); | |
| 477 | 480 | if (READ_ONCE(net->ipv4.sysctl_ip_fwd_use_pmtu) || |
| 478 | 481 | ip_mtu_locked(dst) || |
| 479 | 482 | !forwarding) { |
| @@ -497,7 +500,11 @@ static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst, · 17 unmodified lines | ||
| 497 | 500 | out: |
| 498 | 501 | mtu = min_t(unsigned int, mtu, IP_MAX_MTU); |
| 499 | 502 | |
| 500 | − return mtu - lwtunnel_headroom(dst->lwtstate, mtu); | |
| 503 | + res = mtu - lwtunnel_headroom(dst->lwtstate, mtu); | |
| 504 | + | |
| 505 | + rcu_read_unlock(); | |
| 506 | + | |
| 507 | + return res; | |
| 501 | 508 | } |
| 502 | 509 | |
| 503 | 510 | static inline unsigned int ip_skb_dst_mtu(struct sock *sk, |
| @@ -198,10 +198,12 @@ struct sk_buff *l3mdev_l3_out(struct sock *sk, struct sk_buff *skb, u16 proto) · 197 unmodified lines | ||
| 198 | 198 | if (netif_is_l3_slave(dev)) { |
| 199 | 199 | struct net_device *master; |
| 200 | 200 | |
| 201 | + rcu_read_lock(); | |
| 201 | 202 | master = netdev_master_upper_dev_get_rcu(dev); |
| 202 | 203 | if (master && master->l3mdev_ops->l3mdev_l3_out) |
| 203 | 204 | skb = master->l3mdev_ops->l3mdev_l3_out(master, sk, |
| 204 | 205 | skb, proto); |
| 206 | + rcu_read_unlock(); | |
| 205 | 207 | } |
| 206 | 208 | |
| 207 | 209 | return skb; |
| @@ -398,7 +398,7 @@ static inline struct net *read_pnet(const possible_net_t *pnet) · 397 unmodified lines | ||
| 398 | 398 | #endif |
| 399 | 399 | } |
| 400 | 400 | |
| 401 | −static inline struct net *read_pnet_rcu(possible_net_t *pnet) | |
| 401 | +static inline struct net *read_pnet_rcu(const possible_net_t *pnet) | |
| 402 | 402 | { |
| 403 | 403 | #ifdef CONFIG_NET_NS |
| 404 | 404 | return rcu_dereference(pnet->net); |
| @@ -382,10 +382,15 @@ static inline int inet_iif(const struct sk_buff *skb) · 381 unmodified lines | ||
| 382 | 382 | static inline int ip4_dst_hoplimit(const struct dst_entry *dst) |
| 383 | 383 | { |
| 384 | 384 | int hoplimit = dst_metric_raw(dst, RTAX_HOPLIMIT); |
| 385 | − struct net *net = dev_net(dst->dev); | |
| 386 | 385 | |
| 387 | − if (hoplimit == 0) | |
| 386 | + if (hoplimit == 0) { | |
| 387 | + const struct net *net; | |
| 388 | + | |
| 389 | + rcu_read_lock(); | |
| 390 | + net = dev_net_rcu(dst->dev); | |
| 388 | 391 | hoplimit = READ_ONCE(net->ipv4.sysctl_ip_default_ttl); |
| 392 | + rcu_read_unlock(); | |
| 393 | + } | |
| 389 | 394 | return hoplimit; |
| 390 | 395 | } |
| 391 | 396 | |
| @@ -682,6 +682,7 @@ enum ethtool_link_ext_substate_module { · 681 unmodified lines | ||
| 682 | 682 | * @ETH_SS_STATS_ETH_CTRL: names of IEEE 802.3 MAC Control statistics |
| 683 | 683 | * @ETH_SS_STATS_RMON: names of RMON statistics |
| 684 | 684 | * @ETH_SS_STATS_PHY: names of PHY(dev) statistics |
| 685 | + * @ETH_SS_TS_FLAGS: hardware timestamping flags | |
| 685 | 686 | * |
| 686 | 687 | * @ETH_SS_COUNT: number of defined string sets |
| 687 | 688 | */ |
| @@ -708,6 +709,7 @@ enum ethtool_stringset { · 20 unmodified lines | ||
| 708 | 709 | ETH_SS_STATS_ETH_CTRL, |
| 709 | 710 | ETH_SS_STATS_RMON, |
| 710 | 711 | ETH_SS_STATS_PHY, |
| 712 | + ETH_SS_TS_FLAGS, | |
| 711 | 713 | |
| 712 | 714 | /* add new constants above here */ |
| 713 | 715 | ETH_SS_COUNT |
| @@ -685,6 +685,15 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, · 684 unmodified lines | ||
| 685 | 685 | break; |
| 686 | 686 | } |
| 687 | 687 | |
| 688 | + if (ax25->ax25_dev) { | |
| 689 | + if (dev == ax25->ax25_dev->dev) { | |
| 690 | + rcu_read_unlock(); | |
| 691 | + break; | |
| 692 | + } | |
| 693 | + netdev_put(ax25->ax25_dev->dev, &ax25->dev_tracker); | |
| 694 | + ax25_dev_put(ax25->ax25_dev); | |
| 695 | + } | |
| 696 | + | |
| 688 | 697 | ax25->ax25_dev = ax25_dev_ax25dev(dev); |
| 689 | 698 | if (!ax25->ax25_dev) { |
| 690 | 699 | rcu_read_unlock(); |
| @@ -692,6 +701,8 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, · 1 unmodified line | ||
| 692 | 701 | break; |
| 693 | 702 | } |
| 694 | 703 | ax25_fillin_cb(ax25, ax25->ax25_dev); |
| 704 | + netdev_hold(dev, &ax25->dev_tracker, GFP_ATOMIC); | |
| 705 | + ax25_dev_hold(ax25->ax25_dev); | |
| 695 | 706 | rcu_read_unlock(); |
| 696 | 707 | break; |
| 697 | 708 | |
| @@ -113,8 +113,6 @@ static void · 112 unmodified lines | ||
| 113 | 113 | batadv_v_hardif_neigh_init(struct batadv_hardif_neigh_node *hardif_neigh) |
| 114 | 114 | { |
| 115 | 115 | ewma_throughput_init(&hardif_neigh->bat_v.throughput); |
| 116 | − INIT_WORK(&hardif_neigh->bat_v.metric_work, | |
| 117 | − batadv_v_elp_throughput_metric_update); | |
| 118 | 116 | } |
| 119 | 117 | |
| 120 | 118 | /** |
| @@ -18,6 +18,7 @@ · 17 unmodified lines | ||
| 18 | 18 | #include <linux/if_ether.h> |
| 19 | 19 | #include <linux/jiffies.h> |
| 20 | 20 | #include <linux/kref.h> |
| 21 | +#include <linux/list.h> | |
| 21 | 22 | #include <linux/minmax.h> |
| 22 | 23 | #include <linux/netdevice.h> |
| 23 | 24 | #include <linux/nl80211.h> |
| @@ -26,6 +27,7 @@ · 2 unmodified lines | ||
| 26 | 27 | #include <linux/rcupdate.h> |
| 27 | 28 | #include <linux/rtnetlink.h> |
| 28 | 29 | #include <linux/skbuff.h> |
| 30 | +#include <linux/slab.h> | |
| 29 | 31 | #include <linux/stddef.h> |
| 30 | 32 | #include <linux/string.h> |
| 31 | 33 | #include <linux/types.h> |
| @@ -41,6 +43,18 @@ · 9 unmodified lines | ||
| 41 | 43 | #include "routing.h" |
| 42 | 44 | #include "send.h" |
| 43 | 45 | |
| 46 | +/** | |
| 47 | + * struct batadv_v_metric_queue_entry - list of hardif neighbors which require | |
| 48 | + * and metric update | |
| 49 | + */ | |
| 50 | +struct batadv_v_metric_queue_entry { | |
| 51 | + /** @hardif_neigh: hardif neighbor scheduled for metric update */ | |
| 52 | + struct batadv_hardif_neigh_node *hardif_neigh; | |
| 53 | + | |
| 54 | + /** @list: list node for metric_queue */ | |
| 55 | + struct list_head list; | |
| 56 | +}; | |
| 57 | + | |
| 44 | 58 | /** |
| 45 | 59 | * batadv_v_elp_start_timer() - restart timer for ELP periodic work |
| 46 | 60 | * @hard_iface: the interface for which the timer has to be reset |
| @@ -59,25 +73,36 @@ static void batadv_v_elp_start_timer(struct batadv_hard_iface *hard_iface) · 12 unmodified lines | ||
| 59 | 73 | /** |
| 60 | 74 | * batadv_v_elp_get_throughput() - get the throughput towards a neighbour |
| 61 | 75 | * @neigh: the neighbour for which the throughput has to be obtained |
| 76 | + * @pthroughput: calculated throughput towards the given neighbour in multiples | |
| 77 | + * of 100kpbs (a value of '1' equals 0.1Mbps, '10' equals 1Mbps, etc). | |
| 62 | 78 | * |
| 63 | − * Return: The throughput towards the given neighbour in multiples of 100kpbs | |
| 64 | − * (a value of '1' equals 0.1Mbps, '10' equals 1Mbps, etc). | |
| 79 | + * Return: true when value behind @pthroughput was set | |
| 65 | 80 | */ |
| 66 | −static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh) | |
| 81 | +static bool batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh, | |
| 82 | + u32 *pthroughput) | |
| 67 | 83 | { |
| 68 | 84 | struct batadv_hard_iface *hard_iface = neigh->if_incoming; |
| 85 | + struct net_device *soft_iface = hard_iface->soft_iface; | |
| 69 | 86 | struct ethtool_link_ksettings link_settings; |
| 70 | 87 | struct net_device *real_netdev; |
| 71 | 88 | struct station_info sinfo; |
| 72 | 89 | u32 throughput; |
| 73 | 90 | int ret; |
| 74 | 91 | |
| 92 | + /* don't query throughput when no longer associated with any | |
| 93 | + * batman-adv interface | |
| 94 | + */ | |
| 95 | + if (!soft_iface) | |
| 96 | + return false; | |
| 97 | + | |
| 75 | 98 | /* if the user specified a customised value for this interface, then |
| 76 | 99 | * return it directly |
| 77 | 100 | */ |
| 78 | 101 | throughput = atomic_read(&hard_iface->bat_v.throughput_override); |
| 79 | − if (throughput != 0) | |
| 80 | − return throughput; | |
| 102 | + if (throughput != 0) { | |
| 103 | + *pthroughput = throughput; | |
| 104 | + return true; | |
| 105 | + } | |
| 81 | 106 | |
| 82 | 107 | /* if this is a wireless device, then ask its throughput through |
| 83 | 108 | * cfg80211 API |
| @@ -104,27 +129,39 @@ static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh) · 20 unmodified lines | ||
| 104 | 129 | * possible to delete this neighbor. For now set |
| 105 | 130 | * the throughput metric to 0. |
| 106 | 131 | */ |
| 107 | − return 0; | |
| 132 | + *pthroughput = 0; | |
| 133 | + return true; | |
| 108 | 134 | } |
| 109 | 135 | if (ret) |
| 110 | 136 | goto default_throughput; |
| 111 | 137 | |
| 112 | − if (sinfo.filled & BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT)) | |
| 113 | − return sinfo.expected_throughput / 100; | |
| 138 | + if (sinfo.filled & BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT)) { | |
| 139 | + *pthroughput = sinfo.expected_throughput / 100; | |
| 140 | + return true; | |
| 141 | + } | |
| 114 | 142 | |
| 115 | 143 | /* try to estimate the expected throughput based on reported tx |
| 116 | 144 | * rates |
| 117 | 145 | */ |
| 118 | − if (sinfo.filled & BIT(NL80211_STA_INFO_TX_BITRATE)) | |
| 119 | − return cfg80211_calculate_bitrate(&sinfo.txrate) / 3; | |
| 146 | + if (sinfo.filled & BIT(NL80211_STA_INFO_TX_BITRATE)) { | |
| 147 | + *pthroughput = cfg80211_calculate_bitrate(&sinfo.txrate) / 3; | |
| 148 | + return true; | |
| 149 | + } | |
| 120 | 150 | |
| 121 | 151 | goto default_throughput; |
| 122 | 152 | } |
| 123 | 153 | |
| 154 | + /* only use rtnl_trylock because the elp worker will be cancelled while | |
| 155 | + * the rntl_lock is held. the cancel_delayed_work_sync() would otherwise | |
| 156 | + * wait forever when the elp work_item was started and it is then also | |
| 157 | + * trying to rtnl_lock | |
| 158 | + */ | |
| 159 | + if (!rtnl_trylock()) | |
| 160 | + return false; | |
| 161 | + | |
| 124 | 162 | /* if not a wifi interface, check if this device provides data via |
| 125 | 163 | * ethtool (e.g. an Ethernet adapter) |
| 126 | 164 | */ |
| 127 | − rtnl_lock(); | |
| 128 | 165 | ret = __ethtool_get_link_ksettings(hard_iface->net_dev, &link_settings); |
| 129 | 166 | rtnl_unlock(); |
| 130 | 167 | if (ret == 0) { |
| @@ -135,13 +172,15 @@ static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh) · 4 unmodified lines | ||
| 135 | 172 | hard_iface->bat_v.flags &= ~BATADV_FULL_DUPLEX; |
| 136 | 173 | |
| 137 | 174 | throughput = link_settings.base.speed; |
| 138 | − if (throughput && throughput != SPEED_UNKNOWN) | |
| 139 | − return throughput * 10; | |
| 175 | + if (throughput && throughput != SPEED_UNKNOWN) { | |
| 176 | + *pthroughput = throughput * 10; | |
| 177 | + return true; | |
| 178 | + } | |
| 140 | 179 | } |
| 141 | 180 | |
| 142 | 181 | default_throughput: |
| 143 | 182 | if (!(hard_iface->bat_v.flags & BATADV_WARNING_DEFAULT)) { |
| 144 | − batadv_info(hard_iface->soft_iface, | |
| 183 | + batadv_info(soft_iface, | |
| 145 | 184 | "WiFi driver or ethtool info does not provide information about link speeds on interface %s, therefore defaulting to hardcoded throughput values of %u.%1u Mbps. Consider overriding the throughput manually or checking your driver.\n", |
| 146 | 185 | hard_iface->net_dev->name, |
| 147 | 186 | BATADV_THROUGHPUT_DEFAULT_VALUE / 10, |
| @@ -150,31 +189,26 @@ default_throughput: · 2 unmodified lines | ||
| 150 | 189 | } |
| 151 | 190 | |
| 152 | 191 | /* if none of the above cases apply, return the base_throughput */ |
| 153 | − return BATADV_THROUGHPUT_DEFAULT_VALUE; | |
| 192 | + *pthroughput = BATADV_THROUGHPUT_DEFAULT_VALUE; | |
| 193 | + return true; | |
| 154 | 194 | } |
| 155 | 195 | |
| 156 | 196 | /** |
| 157 | 197 | * batadv_v_elp_throughput_metric_update() - worker updating the throughput |
| 158 | 198 | * metric of a single hop neighbour |
| 159 | − * @work: the work queue item | |
| 199 | + * @neigh: the neighbour to probe | |
| 160 | 200 | */ |
| 161 | −void batadv_v_elp_throughput_metric_update(struct work_struct *work) | |
| 201 | +static void | |
| 202 | +batadv_v_elp_throughput_metric_update(struct batadv_hardif_neigh_node *neigh) | |
| 162 | 203 | { |
| 163 | − struct batadv_hardif_neigh_node_bat_v *neigh_bat_v; | |
| 164 | − struct batadv_hardif_neigh_node *neigh; | |
| 165 | − | |
| 166 | − neigh_bat_v = container_of(work, struct batadv_hardif_neigh_node_bat_v, | |
| 167 | − metric_work); | |
| 168 | − neigh = container_of(neigh_bat_v, struct batadv_hardif_neigh_node, | |
| 169 | − bat_v); | |
| 204 | + u32 throughput; | |
| 205 | + bool valid; | |
| 170 | 206 | |
| 171 | − ewma_throughput_add(&neigh->bat_v.throughput, | |
| 172 | − batadv_v_elp_get_throughput(neigh)); | |
| 207 | + valid = batadv_v_elp_get_throughput(neigh, &throughput); | |
| 208 | + if (!valid) | |
| 209 | + return; | |
| 173 | 210 | |
| 174 | − /* decrement refcounter to balance increment performed before scheduling | |
| 175 | − * this task | |
| 176 | − */ | |
| 177 | − batadv_hardif_neigh_put(neigh); | |
| 211 | + ewma_throughput_add(&neigh->bat_v.throughput, throughput); | |
| 178 | 212 | } |
| 179 | 213 | |
| 180 | 214 | /** |
| @@ -248,14 +282,16 @@ batadv_v_elp_wifi_neigh_probe(struct batadv_hardif_neigh_node *neigh) · 67 unmodified lines | ||
| 248 | 282 | */ |
| 249 | 283 | static void batadv_v_elp_periodic_work(struct work_struct *work) |
| 250 | 284 | { |
| 285 | + struct batadv_v_metric_queue_entry *metric_entry; | |
| 286 | + struct batadv_v_metric_queue_entry *metric_safe; | |
| 251 | 287 | struct batadv_hardif_neigh_node *hardif_neigh; |
| 252 | 288 | struct batadv_hard_iface *hard_iface; |
| 253 | 289 | struct batadv_hard_iface_bat_v *bat_v; |
| 254 | 290 | struct batadv_elp_packet *elp_packet; |
| 291 | + struct list_head metric_queue; | |
| 255 | 292 | struct batadv_priv *bat_priv; |
| 256 | 293 | struct sk_buff *skb; |
| 257 | 294 | u32 elp_interval; |
| 258 | − bool ret; | |
| 259 | 295 | |
| 260 | 296 | bat_v = container_of(work, struct batadv_hard_iface_bat_v, elp_wq.work); |
| 261 | 297 | hard_iface = container_of(bat_v, struct batadv_hard_iface, bat_v); |
| @@ -291,6 +327,8 @@ static void batadv_v_elp_periodic_work(struct work_struct *work) · 29 unmodified lines | ||
| 291 | 327 | |
| 292 | 328 | atomic_inc(&hard_iface->bat_v.elp_seqno); |
| 293 | 329 | |
| 330 | + INIT_LIST_HEAD(&metric_queue); | |
| 331 | + | |
| 294 | 332 | /* The throughput metric is updated on each sent packet. This way, if a |
| 295 | 333 | * node is dead and no longer sends packets, batman-adv is still able to |
| 296 | 334 | * react timely to its death. |
| @@ -315,16 +353,28 @@ static void batadv_v_elp_periodic_work(struct work_struct *work) · 18 unmodified lines | ||
| 315 | 353 | |
| 316 | 354 | /* Reading the estimated throughput from cfg80211 is a task that |
| 317 | 355 | * may sleep and that is not allowed in an rcu protected |
| 318 | − * context. Therefore schedule a task for that. | |
| 356 | + * context. Therefore add it to metric_queue and process it | |
| 357 | + * outside rcu protected context. | |
| 319 | 358 | */ |
| 320 | − ret = queue_work(batadv_event_workqueue, | |
| 321 | − &hardif_neigh->bat_v.metric_work); | |
| 322 | − | |
| 323 | − if (!ret) | |
| 359 | + metric_entry = kzalloc(sizeof(*metric_entry), GFP_ATOMIC); | |
| 360 | + if (!metric_entry) { | |
| 324 | 361 | batadv_hardif_neigh_put(hardif_neigh); |
| 362 | + continue; | |
| 363 | + } | |
| 364 | + | |
| 365 | + metric_entry->hardif_neigh = hardif_neigh; | |
| 366 | + list_add(&metric_entry->list, &metric_queue); | |
| 325 | 367 | } |
| 326 | 368 | rcu_read_unlock(); |
| 327 | 369 | |
| 370 | + list_for_each_entry_safe(metric_entry, metric_safe, &metric_queue, list) { | |
| 371 | + batadv_v_elp_throughput_metric_update(metric_entry->hardif_neigh); | |
| 372 | + | |
| 373 | + batadv_hardif_neigh_put(metric_entry->hardif_neigh); | |
| 374 | + list_del(&metric_entry->list); | |
| 375 | + kfree(metric_entry); | |
| 376 | + } | |
| 377 | + | |
| 328 | 378 | restart_timer: |
| 329 | 379 | batadv_v_elp_start_timer(hard_iface); |
| 330 | 380 | out: |
| @@ -10,7 +10,6 @@ · 9 unmodified lines | ||
| 10 | 10 | #include "main.h" |
| 11 | 11 | |
| 12 | 12 | #include <linux/skbuff.h> |
| 13 | −#include <linux/workqueue.h> | |
| 14 | 13 | |
| 15 | 14 | int batadv_v_elp_iface_enable(struct batadv_hard_iface *hard_iface); |
| 16 | 15 | void batadv_v_elp_iface_disable(struct batadv_hard_iface *hard_iface); |
| @@ -19,6 +18,5 @@ void batadv_v_elp_iface_activate(struct batadv_hard_iface *primary_iface, · 2 unmodified lines | ||
| 19 | 18 | void batadv_v_elp_primary_iface_set(struct batadv_hard_iface *primary_iface); |
| 20 | 19 | int batadv_v_elp_packet_recv(struct sk_buff *skb, |
| 21 | 20 | struct batadv_hard_iface *if_incoming); |
| 22 | −void batadv_v_elp_throughput_metric_update(struct work_struct *work); | |
| 23 | 21 | |
| 24 | 22 | #endif /* _NET_BATMAN_ADV_BAT_V_ELP_H_ */ |
| @@ -3937,23 +3937,21 @@ static void batadv_tt_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv, · 3936 unmodified lines | ||
| 3937 | 3937 | struct batadv_tvlv_tt_change *tt_change; |
| 3938 | 3938 | struct batadv_tvlv_tt_data *tt_data; |
| 3939 | 3939 | u16 num_entries, num_vlan; |
| 3940 | − size_t flex_size; | |
| 3940 | + size_t tt_data_sz; | |
| 3941 | 3941 | |
| 3942 | 3942 | if (tvlv_value_len < sizeof(*tt_data)) |
| 3943 | 3943 | return; |
| 3944 | 3944 | |
| 3945 | 3945 | tt_data = tvlv_value; |
| 3946 | − tvlv_value_len -= sizeof(*tt_data); | |
| 3947 | − | |
| 3948 | 3946 | num_vlan = ntohs(tt_data->num_vlan); |
| 3949 | 3947 | |
| 3950 | − flex_size = flex_array_size(tt_data, vlan_data, num_vlan); | |
| 3951 | − if (tvlv_value_len < flex_size) | |
| 3948 | + tt_data_sz = struct_size(tt_data, vlan_data, num_vlan); | |
| 3949 | + if (tvlv_value_len < tt_data_sz) | |
| 3952 | 3950 | return; |
| 3953 | 3951 | |
| 3954 | 3952 | tt_change = (struct batadv_tvlv_tt_change *)((void *)tt_data |
| 3955 | − + flex_size); | |
| 3956 | − tvlv_value_len -= flex_size; | |
| 3953 | + + tt_data_sz); | |
| 3954 | + tvlv_value_len -= tt_data_sz; | |
| 3957 | 3955 | |
| 3958 | 3956 | num_entries = batadv_tt_entries(tvlv_value_len); |
| 3959 | 3957 | |
| @@ -596,9 +596,6 @@ struct batadv_hardif_neigh_node_bat_v { · 595 unmodified lines | ||
| 596 | 596 | * neighbor |
| 597 | 597 | */ |
| 598 | 598 | unsigned long last_unicast_tx; |
| 599 | − | |
| 600 | − /** @metric_work: work queue callback item for metric update */ | |
| 601 | − struct work_struct metric_work; | |
| 602 | 599 | }; |
| 603 | 600 | |
| 604 | 601 | /** |
| @@ -119,7 +119,6 @@ static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, · 118 unmodified lines | ||
| 119 | 119 | { |
| 120 | 120 | struct l2cap_chan *c; |
| 121 | 121 | |
| 122 | − mutex_lock(&conn->chan_lock); | |
| 123 | 122 | c = __l2cap_get_chan_by_scid(conn, cid); |
| 124 | 123 | if (c) { |
| 125 | 124 | /* Only lock if chan reference is not 0 */ |
| @@ -127,7 +126,6 @@ static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, · 1 unmodified line | ||
| 127 | 126 | if (c) |
| 128 | 127 | l2cap_chan_lock(c); |
| 129 | 128 | } |
| 130 | − mutex_unlock(&conn->chan_lock); | |
| 131 | 129 | |
| 132 | 130 | return c; |
| 133 | 131 | } |
| @@ -140,7 +138,6 @@ static struct l2cap_chan *l2cap_get_chan_by_dcid(struct l2cap_conn *conn, · 6 unmodified lines | ||
| 140 | 138 | { |
| 141 | 139 | struct l2cap_chan *c; |
| 142 | 140 | |
| 143 | − mutex_lock(&conn->chan_lock); | |
| 144 | 141 | c = __l2cap_get_chan_by_dcid(conn, cid); |
| 145 | 142 | if (c) { |
| 146 | 143 | /* Only lock if chan reference is not 0 */ |
| @@ -148,7 +145,6 @@ static struct l2cap_chan *l2cap_get_chan_by_dcid(struct l2cap_conn *conn, · 1 unmodified line | ||
| 148 | 145 | if (c) |
| 149 | 146 | l2cap_chan_lock(c); |
| 150 | 147 | } |
| 151 | − mutex_unlock(&conn->chan_lock); | |
| 152 | 148 | |
| 153 | 149 | return c; |
| 154 | 150 | } |
| @@ -418,7 +414,7 @@ static void l2cap_chan_timeout(struct work_struct *work) · 263 unmodified lines | ||
| 418 | 414 | if (!conn) |
| 419 | 415 | return; |
| 420 | 416 | |
| 421 | − mutex_lock(&conn->chan_lock); | |
| 417 | + mutex_lock(&conn->lock); | |
| 422 | 418 | /* __set_chan_timer() calls l2cap_chan_hold(chan) while scheduling |
| 423 | 419 | * this work. No need to call l2cap_chan_hold(chan) here again. |
| 424 | 420 | */ |
| @@ -439,7 +435,7 @@ static void l2cap_chan_timeout(struct work_struct *work) · 14 unmodified lines | ||
| 439 | 435 | l2cap_chan_unlock(chan); |
| 440 | 436 | l2cap_chan_put(chan); |
| 441 | 437 | |
| 442 | − mutex_unlock(&conn->chan_lock); | |
| 438 | + mutex_unlock(&conn->lock); | |
| 443 | 439 | } |
| 444 | 440 | |
| 445 | 441 | struct l2cap_chan *l2cap_chan_create(void) |
| @@ -641,9 +637,9 @@ void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) · 195 unmodified lines | ||
| 641 | 637 | |
| 642 | 638 | void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) |
| 643 | 639 | { |
| 644 | − mutex_lock(&conn->chan_lock); | |
| 640 | + mutex_lock(&conn->lock); | |
| 645 | 641 | __l2cap_chan_add(conn, chan); |
| 646 | − mutex_unlock(&conn->chan_lock); | |
| 642 | + mutex_unlock(&conn->lock); | |
| 647 | 643 | } |
| 648 | 644 | |
| 649 | 645 | void l2cap_chan_del(struct l2cap_chan *chan, int err) |
| @@ -731,9 +727,9 @@ void l2cap_chan_list(struct l2cap_conn *conn, l2cap_chan_func_t func, · 81 unmodified lines | ||
| 731 | 727 | if (!conn) |
| 732 | 728 | return; |
| 733 | 729 | |
| 734 | − mutex_lock(&conn->chan_lock); | |
| 730 | + mutex_lock(&conn->lock); | |
| 735 | 731 | __l2cap_chan_list(conn, func, data); |
| 736 | − mutex_unlock(&conn->chan_lock); | |
| 732 | + mutex_unlock(&conn->lock); | |
| 737 | 733 | } |
| 738 | 734 | |
| 739 | 735 | EXPORT_SYMBOL_GPL(l2cap_chan_list); |
| @@ -745,7 +741,7 @@ static void l2cap_conn_update_id_addr(struct work_struct *work) · 5 unmodified lines | ||
| 745 | 741 | struct hci_conn *hcon = conn->hcon; |
| 746 | 742 | struct l2cap_chan *chan; |
| 747 | 743 | |
| 748 | − mutex_lock(&conn->chan_lock); | |
| 744 | + mutex_lock(&conn->lock); | |
| 749 | 745 | |
| 750 | 746 | list_for_each_entry(chan, &conn->chan_l, list) { |
| 751 | 747 | l2cap_chan_lock(chan); |
| @@ -754,7 +750,7 @@ static void l2cap_conn_update_id_addr(struct work_struct *work) · 2 unmodified lines | ||
| 754 | 750 | l2cap_chan_unlock(chan); |
| 755 | 751 | } |
| 756 | 752 | |
| 757 | − mutex_unlock(&conn->chan_lock); | |
| 753 | + mutex_unlock(&conn->lock); | |
| 758 | 754 | } |
| 759 | 755 | |
| 760 | 756 | static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan) |
| @@ -948,6 +944,16 @@ static u8 l2cap_get_ident(struct l2cap_conn *conn) · 187 unmodified lines | ||
| 948 | 944 | return id; |
| 949 | 945 | } |
| 950 | 946 | |
| 947 | +static void l2cap_send_acl(struct l2cap_conn *conn, struct sk_buff *skb, | |
| 948 | + u8 flags) | |
| 949 | +{ | |
| 950 | + /* Check if the hcon still valid before attempting to send */ | |
| 951 | + if (hci_conn_valid(conn->hcon->hdev, conn->hcon)) | |
| 952 | + hci_send_acl(conn->hchan, skb, flags); | |
| 953 | + else | |
| 954 | + kfree_skb(skb); | |
| 955 | +} | |
| 956 | + | |
| 951 | 957 | static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, |
| 952 | 958 | void *data) |
| 953 | 959 | { |
| @@ -970,7 +976,7 @@ static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, · 16 unmodified lines | ||
| 970 | 976 | bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON; |
| 971 | 977 | skb->priority = HCI_PRIO_MAX; |
| 972 | 978 | |
| 973 | − hci_send_acl(conn->hchan, skb, flags); | |
| 979 | + l2cap_send_acl(conn, skb, flags); | |
| 974 | 980 | } |
| 975 | 981 | |
| 976 | 982 | static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) |
| @@ -1497,8 +1503,6 @@ static void l2cap_conn_start(struct l2cap_conn *conn) · 520 unmodified lines | ||
| 1497 | 1503 | |
| 1498 | 1504 | BT_DBG("conn %p", conn); |
| 1499 | 1505 | |
| 1500 | − mutex_lock(&conn->chan_lock); | |
| 1501 | − | |
| 1502 | 1506 | list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { |
| 1503 | 1507 | l2cap_chan_lock(chan); |
| 1504 | 1508 | |
| @@ -1567,8 +1571,6 @@ static void l2cap_conn_start(struct l2cap_conn *conn) · 62 unmodified lines | ||
| 1567 | 1571 | |
| 1568 | 1572 | l2cap_chan_unlock(chan); |
| 1569 | 1573 | } |
| 1570 | − | |
| 1571 | − mutex_unlock(&conn->chan_lock); | |
| 1572 | 1574 | } |
| 1573 | 1575 | |
| 1574 | 1576 | static void l2cap_le_conn_ready(struct l2cap_conn *conn) |
| @@ -1614,7 +1616,7 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) · 39 unmodified lines | ||
| 1614 | 1616 | if (hcon->type == ACL_LINK) |
| 1615 | 1617 | l2cap_request_info(conn); |
| 1616 | 1618 | |
| 1617 | − mutex_lock(&conn->chan_lock); | |
| 1619 | + mutex_lock(&conn->lock); | |
| 1618 | 1620 | |
| 1619 | 1621 | list_for_each_entry(chan, &conn->chan_l, list) { |
| 1620 | 1622 | |
| @@ -1632,7 +1634,7 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) · 11 unmodified lines | ||
| 1632 | 1634 | l2cap_chan_unlock(chan); |
| 1633 | 1635 | } |
| 1634 | 1636 | |
| 1635 | − mutex_unlock(&conn->chan_lock); | |
| 1637 | + mutex_unlock(&conn->lock); | |
| 1636 | 1638 | |
| 1637 | 1639 | if (hcon->type == LE_LINK) |
| 1638 | 1640 | l2cap_le_conn_ready(conn); |
| @@ -1647,14 +1649,10 @@ static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) · 8 unmodified lines | ||
| 1647 | 1649 | |
| 1648 | 1650 | BT_DBG("conn %p", conn); |
| 1649 | 1651 | |
| 1650 | − mutex_lock(&conn->chan_lock); | |
| 1651 | − | |
| 1652 | 1652 | list_for_each_entry(chan, &conn->chan_l, list) { |
| 1653 | 1653 | if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags)) |
| 1654 | 1654 | l2cap_chan_set_err(chan, err); |
| 1655 | 1655 | } |
| 1656 | − | |
| 1657 | − mutex_unlock(&conn->chan_lock); | |
| 1658 | 1656 | } |
| 1659 | 1657 | |
| 1660 | 1658 | static void l2cap_info_timeout(struct work_struct *work) |
| @@ -1665,7 +1663,9 @@ static void l2cap_info_timeout(struct work_struct *work) · 4 unmodified lines | ||
| 1665 | 1663 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; |
| 1666 | 1664 | conn->info_ident = 0; |
| 1667 | 1665 | |
| 1666 | + mutex_lock(&conn->lock); | |
| 1668 | 1667 | l2cap_conn_start(conn); |
| 1668 | + mutex_unlock(&conn->lock); | |
| 1669 | 1669 | } |
| 1670 | 1670 | |
| 1671 | 1671 | /* |
| @@ -1757,6 +1757,8 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) · 85 unmodified lines | ||
| 1757 | 1757 | |
| 1758 | 1758 | BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); |
| 1759 | 1759 | |
| 1760 | + mutex_lock(&conn->lock); | |
| 1761 | + | |
| 1760 | 1762 | kfree_skb(conn->rx_skb); |
| 1761 | 1763 | |
| 1762 | 1764 | skb_queue_purge(&conn->pending_rx); |
| @@ -1775,8 +1777,6 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) · 12 unmodified lines | ||
| 1775 | 1777 | /* Force the connection to be immediately dropped */ |
| 1776 | 1778 | hcon->disc_timeout = 0; |
| 1777 | 1779 | |
| 1778 | − mutex_lock(&conn->chan_lock); | |
| 1779 | − | |
| 1780 | 1780 | /* Kill channels */ |
| 1781 | 1781 | list_for_each_entry_safe(chan, l, &conn->chan_l, list) { |
| 1782 | 1782 | l2cap_chan_hold(chan); |
| @@ -1790,15 +1790,14 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) · 7 unmodified lines | ||
| 1790 | 1790 | l2cap_chan_put(chan); |
| 1791 | 1791 | } |
| 1792 | 1792 | |
| 1793 | − mutex_unlock(&conn->chan_lock); | |
| 1794 | − | |
| 1795 | − hci_chan_del(conn->hchan); | |
| 1796 | − | |
| 1797 | 1793 | if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) |
| 1798 | 1794 | cancel_delayed_work_sync(&conn->info_timer); |
| 1799 | 1795 | |
| 1800 | − hcon->l2cap_data = NULL; | |
| 1796 | + hci_chan_del(conn->hchan); | |
| 1801 | 1797 | conn->hchan = NULL; |
| 1798 | + | |
| 1799 | + hcon->l2cap_data = NULL; | |
| 1800 | + mutex_unlock(&conn->lock); | |
| 1802 | 1801 | l2cap_conn_put(conn); |
| 1803 | 1802 | } |
| 1804 | 1803 | |
| @@ -2916,8 +2915,6 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) · 1111 unmodified lines | ||
| 2916 | 2915 | |
| 2917 | 2916 | BT_DBG("conn %p", conn); |
| 2918 | 2917 | |
| 2919 | − mutex_lock(&conn->chan_lock); | |
| 2920 | − | |
| 2921 | 2918 | list_for_each_entry(chan, &conn->chan_l, list) { |
| 2922 | 2919 | if (chan->chan_type != L2CAP_CHAN_RAW) |
| 2923 | 2920 | continue; |
| @@ -2932,8 +2929,6 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) · 8 unmodified lines | ||
| 2932 | 2929 | if (chan->ops->recv(chan, nskb)) |
| 2933 | 2930 | kfree_skb(nskb); |
| 2934 | 2931 | } |
| 2935 | − | |
| 2936 | − mutex_unlock(&conn->chan_lock); | |
| 2937 | 2932 | } |
| 2938 | 2933 | |
| 2939 | 2934 | /* ---- L2CAP signalling commands ---- */ |
| @@ -3952,7 +3947,6 @@ static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, · 1012 unmodified lines | ||
| 3952 | 3947 | goto response; |
| 3953 | 3948 | } |
| 3954 | 3949 | |
| 3955 | − mutex_lock(&conn->chan_lock); | |
| 3956 | 3950 | l2cap_chan_lock(pchan); |
| 3957 | 3951 | |
| 3958 | 3952 | /* Check if the ACL is secure enough (if not SDP) */ |
| @@ -4059,7 +4053,6 @@ response: · 100 unmodified lines | ||
| 4059 | 4053 | } |
| 4060 | 4054 | |
| 4061 | 4055 | l2cap_chan_unlock(pchan); |
| 4062 | − mutex_unlock(&conn->chan_lock); | |
| 4063 | 4056 | l2cap_chan_put(pchan); |
| 4064 | 4057 | } |
| 4065 | 4058 | |
| @@ -4098,27 +4091,19 @@ static int l2cap_connect_create_rsp(struct l2cap_conn *conn, · 32 unmodified lines | ||
| 4098 | 4091 | BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", |
| 4099 | 4092 | dcid, scid, result, status); |
| 4100 | 4093 | |
| 4101 | − mutex_lock(&conn->chan_lock); | |
| 4102 | − | |
| 4103 | 4094 | if (scid) { |
| 4104 | 4095 | chan = __l2cap_get_chan_by_scid(conn, scid); |
| 4105 | − if (!chan) { | |
| 4106 | − err = -EBADSLT; | |
| 4107 | − goto unlock; | |
| 4108 | − } | |
| 4096 | + if (!chan) | |
| 4097 | + return -EBADSLT; | |
| 4109 | 4098 | } else { |
| 4110 | 4099 | chan = __l2cap_get_chan_by_ident(conn, cmd->ident); |
| 4111 | − if (!chan) { | |
| 4112 | − err = -EBADSLT; | |
| 4113 | − goto unlock; | |
| 4114 | − } | |
| 4100 | + if (!chan) | |
| 4101 | + return -EBADSLT; | |
| 4115 | 4102 | } |
| 4116 | 4103 | |
| 4117 | 4104 | chan = l2cap_chan_hold_unless_zero(chan); |
| 4118 | − if (!chan) { | |
| 4119 | − err = -EBADSLT; | |
| 4120 | − goto unlock; | |
| 4121 | − } | |
| 4105 | + if (!chan) | |
| 4106 | + return -EBADSLT; | |
| 4122 | 4107 | |
| 4123 | 4108 | err = 0; |
| 4124 | 4109 | |
| @@ -4156,9 +4141,6 @@ static int l2cap_connect_create_rsp(struct l2cap_conn *conn, · 31 unmodified lines | ||
| 4156 | 4141 | l2cap_chan_unlock(chan); |
| 4157 | 4142 | l2cap_chan_put(chan); |
| 4158 | 4143 | |
| 4159 | −unlock: | |
| 4160 | − mutex_unlock(&conn->chan_lock); | |
| 4161 | − | |
| 4162 | 4144 | return err; |
| 4163 | 4145 | } |
| 4164 | 4146 | |
| @@ -4446,11 +4428,7 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, · 281 unmodified lines | ||
| 4446 | 4428 | |
| 4447 | 4429 | chan->ops->set_shutdown(chan); |
| 4448 | 4430 | |
| 4449 | − l2cap_chan_unlock(chan); | |
| 4450 | − mutex_lock(&conn->chan_lock); | |
| 4451 | − l2cap_chan_lock(chan); | |
| 4452 | 4431 | l2cap_chan_del(chan, ECONNRESET); |
| 4453 | − mutex_unlock(&conn->chan_lock); | |
| 4454 | 4432 | |
| 4455 | 4433 | chan->ops->close(chan); |
| 4456 | 4434 | |
| @@ -4487,11 +4465,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, · 30 unmodified lines | ||
| 4487 | 4465 | return 0; |
| 4488 | 4466 | } |
| 4489 | 4467 | |
| 4490 | − l2cap_chan_unlock(chan); | |
| 4491 | − mutex_lock(&conn->chan_lock); | |
| 4492 | − l2cap_chan_lock(chan); | |
| 4493 | 4468 | l2cap_chan_del(chan, 0); |
| 4494 | − mutex_unlock(&conn->chan_lock); | |
| 4495 | 4469 | |
| 4496 | 4470 | chan->ops->close(chan); |
| 4497 | 4471 | |
| @@ -4689,13 +4663,9 @@ static int l2cap_le_connect_rsp(struct l2cap_conn *conn, · 191 unmodified lines | ||
| 4689 | 4663 | BT_DBG("dcid 0x%4.4x mtu %u mps %u credits %u result 0x%2.2x", |
| 4690 | 4664 | dcid, mtu, mps, credits, result); |
| 4691 | 4665 | |
| 4692 | − mutex_lock(&conn->chan_lock); | |
| 4693 | − | |
| 4694 | 4666 | chan = __l2cap_get_chan_by_ident(conn, cmd->ident); |
| 4695 | − if (!chan) { | |
| 4696 | − err = -EBADSLT; | |
| 4697 | − goto unlock; | |
| 4698 | − } | |
| 4667 | + if (!chan) | |
| 4668 | + return -EBADSLT; | |
| 4699 | 4669 | |
| 4700 | 4670 | err = 0; |
| 4701 | 4671 | |
| @@ -4743,9 +4713,6 @@ static int l2cap_le_connect_rsp(struct l2cap_conn *conn, · 41 unmodified lines | ||
| 4743 | 4713 | |
| 4744 | 4714 | l2cap_chan_unlock(chan); |
| 4745 | 4715 | |
| 4746 | −unlock: | |
| 4747 | − mutex_unlock(&conn->chan_lock); | |
| 4748 | − | |
| 4749 | 4716 | return err; |
| 4750 | 4717 | } |
| 4751 | 4718 | |
| @@ -4857,7 +4824,6 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn, · 105 unmodified lines | ||
| 4857 | 4824 | goto response; |
| 4858 | 4825 | } |
| 4859 | 4826 | |
| 4860 | − mutex_lock(&conn->chan_lock); | |
| 4861 | 4827 | l2cap_chan_lock(pchan); |
| 4862 | 4828 | |
| 4863 | 4829 | if (!smp_sufficient_security(conn->hcon, pchan->sec_level, |
| @@ -4923,7 +4889,6 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn, · 59 unmodified lines | ||
| 4923 | 4889 | |
| 4924 | 4890 | response_unlock: |
| 4925 | 4891 | l2cap_chan_unlock(pchan); |
| 4926 | − mutex_unlock(&conn->chan_lock); | |
| 4927 | 4892 | l2cap_chan_put(pchan); |
| 4928 | 4893 | |
| 4929 | 4894 | if (result == L2CAP_CR_PEND) |
| @@ -5057,7 +5022,6 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn, · 127 unmodified lines | ||
| 5057 | 5022 | goto response; |
| 5058 | 5023 | } |
| 5059 | 5024 | |
| 5060 | − mutex_lock(&conn->chan_lock); | |
| 5061 | 5025 | l2cap_chan_lock(pchan); |
| 5062 | 5026 | |
| 5063 | 5027 | if (!smp_sufficient_security(conn->hcon, pchan->sec_level, |
| @@ -5132,7 +5096,6 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn, · 68 unmodified lines | ||
| 5132 | 5096 | |
| 5133 | 5097 | unlock: |
| 5134 | 5098 | l2cap_chan_unlock(pchan); |
| 5135 | − mutex_unlock(&conn->chan_lock); | |
| 5136 | 5099 | l2cap_chan_put(pchan); |
| 5137 | 5100 | |
| 5138 | 5101 | response: |
| @@ -5169,8 +5132,6 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn, · 30 unmodified lines | ||
| 5169 | 5132 | BT_DBG("mtu %u mps %u credits %u result 0x%4.4x", mtu, mps, credits, |
| 5170 | 5133 | result); |
| 5171 | 5134 | |
| 5172 | − mutex_lock(&conn->chan_lock); | |
| 5173 | − | |
| 5174 | 5135 | cmd_len -= sizeof(*rsp); |
| 5175 | 5136 | |
| 5176 | 5137 | list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { |
| @@ -5256,8 +5217,6 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn, · 79 unmodified lines | ||
| 5256 | 5217 | l2cap_chan_unlock(chan); |
| 5257 | 5218 | } |
| 5258 | 5219 | |
| 5259 | − mutex_unlock(&conn->chan_lock); | |
| 5260 | − | |
| 5261 | 5220 | return err; |
| 5262 | 5221 | } |
| 5263 | 5222 | |
| @@ -5370,8 +5329,6 @@ static inline int l2cap_le_command_rej(struct l2cap_conn *conn, · 106 unmodified lines | ||
| 5370 | 5329 | if (cmd_len < sizeof(*rej)) |
| 5371 | 5330 | return -EPROTO; |
| 5372 | 5331 | |
| 5373 | − mutex_lock(&conn->chan_lock); | |
| 5374 | − | |
| 5375 | 5332 | chan = __l2cap_get_chan_by_ident(conn, cmd->ident); |
| 5376 | 5333 | if (!chan) |
| 5377 | 5334 | goto done; |
| @@ -5386,7 +5343,6 @@ static inline int l2cap_le_command_rej(struct l2cap_conn *conn, · 8 unmodified lines | ||
| 5386 | 5343 | l2cap_chan_put(chan); |
| 5387 | 5344 | |
| 5388 | 5345 | done: |
| 5389 | − mutex_unlock(&conn->chan_lock); | |
| 5390 | 5346 | return 0; |
| 5391 | 5347 | } |
| 5392 | 5348 | |
| @@ -6841,8 +6797,12 @@ static void process_pending_rx(struct work_struct *work) · 1448 unmodified lines | ||
| 6841 | 6797 | |
| 6842 | 6798 | BT_DBG(""); |
| 6843 | 6799 | |
| 6800 | + mutex_lock(&conn->lock); | |
| 6801 | + | |
| 6844 | 6802 | while ((skb = skb_dequeue(&conn->pending_rx))) |
| 6845 | 6803 | l2cap_recv_frame(conn, skb); |
| 6804 | + | |
| 6805 | + mutex_unlock(&conn->lock); | |
| 6846 | 6806 | } |
| 6847 | 6807 | |
| 6848 | 6808 | static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon) |
| @@ -6881,7 +6841,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon) · 32 unmodified lines | ||
| 6881 | 6841 | conn->local_fixed_chan |= L2CAP_FC_SMP_BREDR; |
| 6882 | 6842 | |
| 6883 | 6843 | mutex_init(&conn->ident_lock); |
| 6884 | − mutex_init(&conn->chan_lock); | |
| 6844 | + mutex_init(&conn->lock); | |
| 6885 | 6845 | |
| 6886 | 6846 | INIT_LIST_HEAD(&conn->chan_l); |
| 6887 | 6847 | INIT_LIST_HEAD(&conn->users); |
| @@ -7072,7 +7032,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, · 184 unmodified lines | ||
| 7072 | 7032 | } |
| 7073 | 7033 | } |
| 7074 | 7034 | |
| 7075 | − mutex_lock(&conn->chan_lock); | |
| 7035 | + mutex_lock(&conn->lock); | |
| 7076 | 7036 | l2cap_chan_lock(chan); |
| 7077 | 7037 | |
| 7078 | 7038 | if (cid && __l2cap_get_chan_by_dcid(conn, cid)) { |
| @@ -7113,7 +7073,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, · 34 unmodified lines | ||
| 7113 | 7073 | |
| 7114 | 7074 | chan_unlock: |
| 7115 | 7075 | l2cap_chan_unlock(chan); |
| 7116 | − mutex_unlock(&conn->chan_lock); | |
| 7076 | + mutex_unlock(&conn->lock); | |
| 7117 | 7077 | done: |
| 7118 | 7078 | hci_dev_unlock(hdev); |
| 7119 | 7079 | hci_dev_put(hdev); |
| @@ -7325,7 +7285,7 @@ static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) · 205 unmodified lines | ||
| 7325 | 7285 | |
| 7326 | 7286 | BT_DBG("conn %p status 0x%2.2x encrypt %u", conn, status, encrypt); |
| 7327 | 7287 | |
| 7328 | − mutex_lock(&conn->chan_lock); | |
| 7288 | + mutex_lock(&conn->lock); | |
| 7329 | 7289 | |
| 7330 | 7290 | list_for_each_entry(chan, &conn->chan_l, list) { |
| 7331 | 7291 | l2cap_chan_lock(chan); |
| @@ -7399,7 +7359,7 @@ static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) · 67 unmodified lines | ||
| 7399 | 7359 | l2cap_chan_unlock(chan); |
| 7400 | 7360 | } |
| 7401 | 7361 | |
| 7402 | − mutex_unlock(&conn->chan_lock); | |
| 7362 | + mutex_unlock(&conn->lock); | |
| 7403 | 7363 | } |
| 7404 | 7364 | |
| 7405 | 7365 | /* Append fragment into frame respecting the maximum len of rx_skb */ |
| @@ -7466,19 +7426,45 @@ static void l2cap_recv_reset(struct l2cap_conn *conn) · 60 unmodified lines | ||
| 7466 | 7426 | conn->rx_len = 0; |
| 7467 | 7427 | } |
| 7468 | 7428 | |
| 7429 | +struct l2cap_conn *l2cap_conn_hold_unless_zero(struct l2cap_conn *c) | |
| 7430 | +{ | |
| 7431 | + if (!c) | |
| 7432 | + return NULL; | |
| 7433 | + | |
| 7434 | + BT_DBG("conn %p orig refcnt %u", c, kref_read(&c->ref)); | |
| 7435 | + | |
| 7436 | + if (!kref_get_unless_zero(&c->ref)) | |
| 7437 | + return NULL; | |
| 7438 | + | |
| 7439 | + return c; | |
| 7440 | +} | |
| 7441 | + | |
| 7469 | 7442 | void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) |
| 7470 | 7443 | { |
| 7471 | − struct l2cap_conn *conn = hcon->l2cap_data; | |
| 7444 | + struct l2cap_conn *conn; | |
| 7472 | 7445 | int len; |
| 7473 | 7446 | |
| 7447 | + /* Lock hdev to access l2cap_data to avoid race with l2cap_conn_del */ | |
| 7448 | + hci_dev_lock(hcon->hdev); | |
| 7449 | + | |
| 7450 | + conn = hcon->l2cap_data; | |
| 7451 | + | |
| 7474 | 7452 | if (!conn) |
| 7475 | 7453 | conn = l2cap_conn_add(hcon); |
| 7476 | 7454 | |
| 7477 | − if (!conn) | |
| 7478 | − goto drop; | |
| 7455 | + conn = l2cap_conn_hold_unless_zero(conn); | |
| 7456 | + | |
| 7457 | + hci_dev_unlock(hcon->hdev); | |
| 7458 | + | |
| 7459 | + if (!conn) { | |
| 7460 | + kfree_skb(skb); | |
| 7461 | + return; | |
| 7462 | + } | |
| 7479 | 7463 | |
| 7480 | 7464 | BT_DBG("conn %p len %u flags 0x%x", conn, skb->len, flags); |
| 7481 | 7465 | |
| 7466 | + mutex_lock(&conn->lock); | |
| 7467 | + | |
| 7482 | 7468 | switch (flags) { |
| 7483 | 7469 | case ACL_START: |
| 7484 | 7470 | case ACL_START_NO_FLUSH: |
| @@ -7503,7 +7489,7 @@ void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) · 18 unmodified lines | ||
| 7503 | 7489 | if (len == skb->len) { |
| 7504 | 7490 | /* Complete frame received */ |
| 7505 | 7491 | l2cap_recv_frame(conn, skb); |
| 7506 | − return; | |
| 7492 | + goto unlock; | |
| 7507 | 7493 | } |
| 7508 | 7494 | |
| 7509 | 7495 | BT_DBG("Start: total len %d, frag len %u", len, skb->len); |
| @@ -7567,6 +7553,9 @@ void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) · 57 unmodified lines | ||
| 7567 | 7553 | |
| 7568 | 7554 | drop: |
| 7569 | 7555 | kfree_skb(skb); |
| 7556 | +unlock: | |
| 7557 | + mutex_unlock(&conn->lock); | |
| 7558 | + l2cap_conn_put(conn); | |
| 7570 | 7559 | } |
| 7571 | 7560 | |
| 7572 | 7561 | static struct hci_cb l2cap_cb = { |
| @@ -1326,9 +1326,10 @@ static int l2cap_sock_shutdown(struct socket *sock, int how) · 1325 unmodified lines | ||
| 1326 | 1326 | /* prevent sk structure from being freed whilst unlocked */ |
| 1327 | 1327 | sock_hold(sk); |
| 1328 | 1328 | |
| 1329 | − chan = l2cap_pi(sk)->chan; | |
| 1330 | 1329 | /* prevent chan structure from being freed whilst unlocked */ |
| 1331 | − l2cap_chan_hold(chan); | |
| 1330 | + chan = l2cap_chan_hold_unless_zero(l2cap_pi(sk)->chan); | |
| 1331 | + if (!chan) | |
| 1332 | + goto shutdown_already; | |
| 1332 | 1333 | |
| 1333 | 1334 | BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); |
| 1334 | 1335 | |
| @@ -1358,22 +1359,20 @@ static int l2cap_sock_shutdown(struct socket *sock, int how) · 23 unmodified lines | ||
| 1358 | 1359 | release_sock(sk); |
| 1359 | 1360 | |
| 1360 | 1361 | l2cap_chan_lock(chan); |
| 1361 | − conn = chan->conn; | |
| 1362 | − if (conn) | |
| 1363 | − /* prevent conn structure from being freed */ | |
| 1364 | − l2cap_conn_get(conn); | |
| 1362 | + /* prevent conn structure from being freed */ | |
| 1363 | + conn = l2cap_conn_hold_unless_zero(chan->conn); | |
| 1365 | 1364 | l2cap_chan_unlock(chan); |
| 1366 | 1365 | |
| 1367 | 1366 | if (conn) |
| 1368 | 1367 | /* mutex lock must be taken before l2cap_chan_lock() */ |
| 1369 | − mutex_lock(&conn->chan_lock); | |
| 1368 | + mutex_lock(&conn->lock); | |
| 1370 | 1369 | |
| 1371 | 1370 | l2cap_chan_lock(chan); |
| 1372 | 1371 | l2cap_chan_close(chan, 0); |
| 1373 | 1372 | l2cap_chan_unlock(chan); |
| 1374 | 1373 | |
| 1375 | 1374 | if (conn) { |
| 1376 | − mutex_unlock(&conn->chan_lock); | |
| 1375 | + mutex_unlock(&conn->lock); | |
| 1377 | 1376 | l2cap_conn_put(conn); |
| 1378 | 1377 | } |
| 1379 | 1378 | |
| @@ -1132,7 +1132,7 @@ static int j1939_sk_send_loop(struct j1939_priv *priv, struct sock *sk, · 1131 unmodified lines | ||
| 1132 | 1132 | |
| 1133 | 1133 | todo_size = size; |
| 1134 | 1134 | |
| 1135 | − while (todo_size) { | |
| 1135 | + do { | |
| 1136 | 1136 | struct j1939_sk_buff_cb *skcb; |
| 1137 | 1137 | |
| 1138 | 1138 | segment_size = min_t(size_t, J1939_MAX_TP_PACKET_SIZE, |
| @@ -1177,7 +1177,7 @@ static int j1939_sk_send_loop(struct j1939_priv *priv, struct sock *sk, · 38 unmodified lines | ||
| 1177 | 1177 | |
| 1178 | 1178 | todo_size -= segment_size; |
| 1179 | 1179 | session->total_queued_size += segment_size; |
| 1180 | − } | |
| 1180 | + } while (todo_size); | |
| 1181 | 1181 | |
| 1182 | 1182 | switch (ret) { |
| 1183 | 1183 | case 0: /* OK */ |
| @@ -382,8 +382,9 @@ sk_buff *j1939_session_skb_get_by_offset(struct j1939_session *session, · 381 unmodified lines | ||
| 382 | 382 | skb_queue_walk(&session->skb_queue, do_skb) { |
| 383 | 383 | do_skcb = j1939_skb_to_cb(do_skb); |
| 384 | 384 | |
| 385 | − if (offset_start >= do_skcb->offset && | |
| 386 | − offset_start < (do_skcb->offset + do_skb->len)) { | |
| 385 | + if ((offset_start >= do_skcb->offset && | |
| 386 | + offset_start < (do_skcb->offset + do_skb->len)) || | |
| 387 | + (offset_start == 0 && do_skcb->offset == 0 && do_skb->len == 0)) { | |
| 387 | 388 | skb = do_skb; |
| 388 | 389 | } |
| 389 | 390 | } |
| @@ -37,8 +37,8 @@ static const struct fib_kuid_range fib_kuid_range_unset = { · 36 unmodified lines | ||
| 37 | 37 | |
| 38 | 38 | bool fib_rule_matchall(const struct fib_rule *rule) |
| 39 | 39 | { |
| 40 | − if (rule->iifindex || rule->oifindex || rule->mark || rule->tun_id || | |
| 41 | − rule->flags) | |
| 40 | + if (READ_ONCE(rule->iifindex) || READ_ONCE(rule->oifindex) || | |
| 41 | + rule->mark || rule->tun_id || rule->flags) | |
| 42 | 42 | return false; |
| 43 | 43 | if (rule->suppress_ifgroup != -1 || rule->suppress_prefixlen != -1) |
| 44 | 44 | return false; |
| @@ -261,12 +261,14 @@ static int fib_rule_match(struct fib_rule *rule, struct fib_rules_ops *ops, · 216 unmodified lines | ||
| 261 | 261 | struct flowi *fl, int flags, |
| 262 | 262 | struct fib_lookup_arg *arg) |
| 263 | 263 | { |
| 264 | − int ret = 0; | |
| 264 | + int iifindex, oifindex, ret = 0; | |
| 265 | 265 | |
| 266 | − if (rule->iifindex && (rule->iifindex != fl->flowi_iif)) | |
| 266 | + iifindex = READ_ONCE(rule->iifindex); | |
| 267 | + if (iifindex && (iifindex != fl->flowi_iif)) | |
| 267 | 268 | goto out; |
| 268 | 269 | |
| 269 | − if (rule->oifindex && (rule->oifindex != fl->flowi_oif)) | |
| 270 | + oifindex = READ_ONCE(rule->oifindex); | |
| 271 | + if (oifindex && (oifindex != fl->flowi_oif)) | |
| 270 | 272 | goto out; |
| 271 | 273 | |
| 272 | 274 | if ((rule->mark ^ fl->flowi_mark) & rule->mark_mask) |
| @@ -1041,14 +1043,14 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule, · 768 unmodified lines | ||
| 1041 | 1043 | if (rule->iifname[0]) { |
| 1042 | 1044 | if (nla_put_string(skb, FRA_IIFNAME, rule->iifname)) |
| 1043 | 1045 | goto nla_put_failure; |
| 1044 | − if (rule->iifindex == -1) | |
| 1046 | + if (READ_ONCE(rule->iifindex) == -1) | |
| 1045 | 1047 | frh->flags |= FIB_RULE_IIF_DETACHED; |
| 1046 | 1048 | } |
| 1047 | 1049 | |
| 1048 | 1050 | if (rule->oifname[0]) { |
| 1049 | 1051 | if (nla_put_string(skb, FRA_OIFNAME, rule->oifname)) |
| 1050 | 1052 | goto nla_put_failure; |
| 1051 | − if (rule->oifindex == -1) | |
| 1053 | + if (READ_ONCE(rule->oifindex) == -1) | |
| 1052 | 1054 | frh->flags |= FIB_RULE_OIF_DETACHED; |
| 1053 | 1055 | } |
| 1054 | 1056 | |
| @@ -1220,10 +1222,10 @@ static void attach_rules(struct list_head *rules, struct net_device *dev) · 165 unmodified lines | ||
| 1220 | 1222 | list_for_each_entry(rule, rules, list) { |
| 1221 | 1223 | if (rule->iifindex == -1 && |
| 1222 | 1224 | strcmp(dev->name, rule->iifname) == 0) |
| 1223 | − rule->iifindex = dev->ifindex; | |
| 1225 | + WRITE_ONCE(rule->iifindex, dev->ifindex); | |
| 1224 | 1226 | if (rule->oifindex == -1 && |
| 1225 | 1227 | strcmp(dev->name, rule->oifname) == 0) |
| 1226 | − rule->oifindex = dev->ifindex; | |
| 1228 | + WRITE_ONCE(rule->oifindex, dev->ifindex); | |
| 1227 | 1229 | } |
| 1228 | 1230 | } |
| 1229 | 1231 | |
| @@ -1233,9 +1235,9 @@ static void detach_rules(struct list_head *rules, struct net_device *dev) · 3 unmodified lines | ||
| 1233 | 1235 | |
| 1234 | 1236 | list_for_each_entry(rule, rules, list) { |
| 1235 | 1237 | if (rule->iifindex == dev->ifindex) |
| 1236 | − rule->iifindex = -1; | |
| 1238 | + WRITE_ONCE(rule->iifindex, -1); | |
| 1237 | 1239 | if (rule->oifindex == dev->ifindex) |
| 1238 | − rule->oifindex = -1; | |
| 1240 | + WRITE_ONCE(rule->oifindex, -1); | |
| 1239 | 1241 | } |
| 1240 | 1242 | } |
| 1241 | 1243 | |
| @@ -1108,10 +1108,12 @@ bool __skb_flow_dissect(const struct net *net, · 1107 unmodified lines | ||
| 1108 | 1108 | FLOW_DISSECTOR_KEY_BASIC, |
| 1109 | 1109 | target_container); |
| 1110 | 1110 | |
| 1111 | + rcu_read_lock(); | |
| 1112 | + | |
| 1111 | 1113 | if (skb) { |
| 1112 | 1114 | if (!net) { |
| 1113 | 1115 | if (skb->dev) |
| 1114 | − net = dev_net(skb->dev); | |
| 1116 | + net = dev_net_rcu(skb->dev); | |
| 1115 | 1117 | else if (skb->sk) |
| 1116 | 1118 | net = sock_net(skb->sk); |
| 1117 | 1119 | } |
| @@ -1122,7 +1124,6 @@ bool __skb_flow_dissect(const struct net *net, · 4 unmodified lines | ||
| 1122 | 1124 | enum netns_bpf_attach_type type = NETNS_BPF_FLOW_DISSECTOR; |
| 1123 | 1125 | struct bpf_prog_array *run_array; |
| 1124 | 1126 | |
| 1125 | − rcu_read_lock(); | |
| 1126 | 1127 | run_array = rcu_dereference(init_net.bpf.run_array[type]); |
| 1127 | 1128 | if (!run_array) |
| 1128 | 1129 | run_array = rcu_dereference(net->bpf.run_array[type]); |
| @@ -1150,17 +1151,17 @@ bool __skb_flow_dissect(const struct net *net, · 21 unmodified lines | ||
| 1150 | 1151 | prog = READ_ONCE(run_array->items[0].prog); |
| 1151 | 1152 | result = bpf_flow_dissect(prog, &ctx, n_proto, nhoff, |
| 1152 | 1153 | hlen, flags); |
| 1153 | − if (result == BPF_FLOW_DISSECTOR_CONTINUE) | |
| 1154 | − goto dissect_continue; | |
| 1155 | − __skb_flow_bpf_to_target(&flow_keys, flow_dissector, | |
| 1156 | − target_container); | |
| 1157 | − rcu_read_unlock(); | |
| 1158 | − return result == BPF_OK; | |
| 1154 | + if (result != BPF_FLOW_DISSECTOR_CONTINUE) { | |
| 1155 | + __skb_flow_bpf_to_target(&flow_keys, flow_dissector, | |
| 1156 | + target_container); | |
| 1157 | + rcu_read_unlock(); | |
| 1158 | + return result == BPF_OK; | |
| 1159 | + } | |
| 1159 | 1160 | } |
| 1160 | −dissect_continue: | |
| 1161 | − rcu_read_unlock(); | |
| 1162 | 1161 | } |
| 1163 | 1162 | |
| 1163 | + rcu_read_unlock(); | |
| 1164 | + | |
| 1164 | 1165 | if (dissector_uses_key(flow_dissector, |
| 1165 | 1166 | FLOW_DISSECTOR_KEY_ETH_ADDRS)) { |
| 1166 | 1167 | struct ethhdr *eth = eth_hdr(skb); |
| @@ -3447,10 +3447,12 @@ static const struct seq_operations neigh_stat_seq_ops = { · 3446 unmodified lines | ||
| 3447 | 3447 | static void __neigh_notify(struct neighbour *n, int type, int flags, |
| 3448 | 3448 | u32 pid) |
| 3449 | 3449 | { |
| 3450 | − struct net *net = dev_net(n->dev); | |
| 3451 | 3450 | struct sk_buff *skb; |
| 3452 | 3451 | int err = -ENOBUFS; |
| 3452 | + struct net *net; | |
| 3453 | 3453 | |
| 3454 | + rcu_read_lock(); | |
| 3455 | + net = dev_net_rcu(n->dev); | |
| 3454 | 3456 | skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC); |
| 3455 | 3457 | if (skb == NULL) |
| 3456 | 3458 | goto errout; |
| @@ -3463,9 +3465,11 @@ static void __neigh_notify(struct neighbour *n, int type, int flags, · 6 unmodified lines | ||
| 3463 | 3465 | goto errout; |
| 3464 | 3466 | } |
| 3465 | 3467 | rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC); |
| 3466 | − return; | |
| 3468 | + goto out; | |
| 3467 | 3469 | errout: |
| 3468 | 3470 | rtnl_set_sk_err(net, RTNLGRP_NEIGH, err); |
| 3471 | +out: | |
| 3472 | + rcu_read_unlock(); | |
| 3469 | 3473 | } |
| 3470 | 3474 | |
| 3471 | 3475 | void neigh_app_ns(struct neighbour *n) |
| @@ -3432,6 +3432,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, · 3431 unmodified lines | ||
| 3432 | 3432 | err = -ENODEV; |
| 3433 | 3433 | |
| 3434 | 3434 | rtnl_nets_unlock(&rtnl_nets); |
| 3435 | + rtnl_nets_destroy(&rtnl_nets); | |
| 3435 | 3436 | errout: |
| 3436 | 3437 | return err; |
| 3437 | 3438 | } |
| @@ -462,6 +462,11 @@ const char ts_rx_filter_names[][ETH_GSTRING_LEN] = { · 461 unmodified lines | ||
| 462 | 462 | }; |
| 463 | 463 | static_assert(ARRAY_SIZE(ts_rx_filter_names) == __HWTSTAMP_FILTER_CNT); |
| 464 | 464 | |
| 465 | +const char ts_flags_names[][ETH_GSTRING_LEN] = { | |
| 466 | + [const_ilog2(HWTSTAMP_FLAG_BONDED_PHC_INDEX)] = "bonded-phc-index", | |
| 467 | +}; | |
| 468 | +static_assert(ARRAY_SIZE(ts_flags_names) == __HWTSTAMP_FLAG_CNT); | |
| 469 | + | |
| 465 | 470 | const char udp_tunnel_type_names[][ETH_GSTRING_LEN] = { |
| 466 | 471 | [ETHTOOL_UDP_TUNNEL_TYPE_VXLAN] = "vxlan", |
| 467 | 472 | [ETHTOOL_UDP_TUNNEL_TYPE_GENEVE] = "geneve", |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | ETHTOOL_LINK_MODE_ ## speed ## base ## type ## _ ## duplex ## _BIT |
| 14 | 14 | |
| 15 | 15 | #define __SOF_TIMESTAMPING_CNT (const_ilog2(SOF_TIMESTAMPING_LAST) + 1) |
| 16 | +#define __HWTSTAMP_FLAG_CNT (const_ilog2(HWTSTAMP_FLAG_LAST) + 1) | |
| 16 | 17 | |
| 17 | 18 | struct link_mode_info { |
| 18 | 19 | int speed; |
| @@ -38,6 +39,7 @@ extern const char wol_mode_names[][ETH_GSTRING_LEN]; · 19 unmodified lines | ||
| 38 | 39 | extern const char sof_timestamping_names[][ETH_GSTRING_LEN]; |
| 39 | 40 | extern const char ts_tx_type_names[][ETH_GSTRING_LEN]; |
| 40 | 41 | extern const char ts_rx_filter_names[][ETH_GSTRING_LEN]; |
| 42 | +extern const char ts_flags_names[][ETH_GSTRING_LEN]; | |
| 41 | 43 | extern const char udp_tunnel_type_names[][ETH_GSTRING_LEN]; |
| 42 | 44 | |
| 43 | 45 | int __ethtool_get_link(struct net_device *dev); |
| @@ -75,6 +75,11 @@ static const struct strset_info info_template[] = { · 74 unmodified lines | ||
| 75 | 75 | .count = __HWTSTAMP_FILTER_CNT, |
| 76 | 76 | .strings = ts_rx_filter_names, |
| 77 | 77 | }, |
| 78 | + [ETH_SS_TS_FLAGS] = { | |
| 79 | + .per_dev = false, | |
| 80 | + .count = __HWTSTAMP_FLAG_CNT, | |
| 81 | + .strings = ts_flags_names, | |
| 82 | + }, | |
| 78 | 83 | [ETH_SS_UDP_TUNNEL_TYPES] = { |
| 79 | 84 | .per_dev = false, |
| 80 | 85 | .count = __ETHTOOL_UDP_TUNNEL_TYPE_CNT, |
| @@ -54,7 +54,7 @@ static int tsconfig_prepare_data(const struct ethnl_req_info *req_base, · 53 unmodified lines | ||
| 54 | 54 | |
| 55 | 55 | data->hwtst_config.tx_type = BIT(cfg.tx_type); |
| 56 | 56 | data->hwtst_config.rx_filter = BIT(cfg.rx_filter); |
| 57 | − data->hwtst_config.flags = BIT(cfg.flags); | |
| 57 | + data->hwtst_config.flags = cfg.flags; | |
| 58 | 58 | |
| 59 | 59 | data->hwprov_desc.index = -1; |
| 60 | 60 | hwprov = rtnl_dereference(dev->hwprov); |
| @@ -91,10 +91,16 @@ static int tsconfig_reply_size(const struct ethnl_req_info *req_base, · 30 unmodified lines | ||
| 91 | 91 | |
| 92 | 92 | BUILD_BUG_ON(__HWTSTAMP_TX_CNT > 32); |
| 93 | 93 | BUILD_BUG_ON(__HWTSTAMP_FILTER_CNT > 32); |
| 94 | + BUILD_BUG_ON(__HWTSTAMP_FLAG_CNT > 32); | |
| 94 | 95 | |
| 95 | − if (data->hwtst_config.flags) | |
| 96 | − /* _TSCONFIG_HWTSTAMP_FLAGS */ | |
| 97 | − len += nla_total_size(sizeof(u32)); | |
| 96 | + if (data->hwtst_config.flags) { | |
| 97 | + ret = ethnl_bitset32_size(&data->hwtst_config.flags, | |
| 98 | + NULL, __HWTSTAMP_FLAG_CNT, | |
| 99 | + ts_flags_names, compact); | |
| 100 | + if (ret < 0) | |
| 101 | + return ret; | |
| 102 | + len += ret; /* _TSCONFIG_HWTSTAMP_FLAGS */ | |
| 103 | + } | |
| 98 | 104 | |
| 99 | 105 | if (data->hwtst_config.tx_type) { |
| 100 | 106 | ret = ethnl_bitset32_size(&data->hwtst_config.tx_type, |
| @@ -130,8 +136,10 @@ static int tsconfig_fill_reply(struct sk_buff *skb, · 29 unmodified lines | ||
| 130 | 136 | int ret; |
| 131 | 137 | |
| 132 | 138 | if (data->hwtst_config.flags) { |
| 133 | − ret = nla_put_u32(skb, ETHTOOL_A_TSCONFIG_HWTSTAMP_FLAGS, | |
| 134 | − data->hwtst_config.flags); | |
| 139 | + ret = ethnl_put_bitset32(skb, ETHTOOL_A_TSCONFIG_HWTSTAMP_FLAGS, | |
| 140 | + &data->hwtst_config.flags, NULL, | |
| 141 | + __HWTSTAMP_FLAG_CNT, | |
| 142 | + ts_flags_names, compact); | |
| 135 | 143 | if (ret < 0) |
| 136 | 144 | return ret; |
| 137 | 145 | } |
| @@ -180,7 +188,7 @@ const struct nla_policy ethnl_tsconfig_set_policy[ETHTOOL_A_TSCONFIG_MAX + 1] = · 42 unmodified lines | ||
| 180 | 188 | [ETHTOOL_A_TSCONFIG_HEADER] = NLA_POLICY_NESTED(ethnl_header_policy), |
| 181 | 189 | [ETHTOOL_A_TSCONFIG_HWTSTAMP_PROVIDER] = |
| 182 | 190 | NLA_POLICY_NESTED(ethnl_ts_hwtst_prov_policy), |
| 183 | − [ETHTOOL_A_TSCONFIG_HWTSTAMP_FLAGS] = { .type = NLA_U32 }, | |
| 191 | + [ETHTOOL_A_TSCONFIG_HWTSTAMP_FLAGS] = { .type = NLA_NESTED }, | |
| 184 | 192 | [ETHTOOL_A_TSCONFIG_RX_FILTERS] = { .type = NLA_NESTED }, |
| 185 | 193 | [ETHTOOL_A_TSCONFIG_TX_TYPES] = { .type = NLA_NESTED }, |
| 186 | 194 | }; |
| @@ -296,6 +304,7 @@ static int ethnl_set_tsconfig(struct ethnl_req_info *req_base, · 109 unmodified lines | ||
| 296 | 304 | |
| 297 | 305 | BUILD_BUG_ON(__HWTSTAMP_TX_CNT >= 32); |
| 298 | 306 | BUILD_BUG_ON(__HWTSTAMP_FILTER_CNT >= 32); |
| 307 | + BUILD_BUG_ON(__HWTSTAMP_FLAG_CNT > 32); | |
| 299 | 308 | |
| 300 | 309 | if (!netif_device_present(dev)) |
| 301 | 310 | return -ENODEV; |
| @@ -377,9 +386,13 @@ static int ethnl_set_tsconfig(struct ethnl_req_info *req_base, · 75 unmodified lines | ||
| 377 | 386 | } |
| 378 | 387 | |
| 379 | 388 | if (tb[ETHTOOL_A_TSCONFIG_HWTSTAMP_FLAGS]) { |
| 380 | − ethnl_update_u32(&hwtst_config.flags, | |
| 381 | − tb[ETHTOOL_A_TSCONFIG_HWTSTAMP_FLAGS], | |
| 382 | − &config_mod); | |
| 389 | + ret = ethnl_update_bitset32(&hwtst_config.flags, | |
| 390 | + __HWTSTAMP_FLAG_CNT, | |
| 391 | + tb[ETHTOOL_A_TSCONFIG_HWTSTAMP_FLAGS], | |
| 392 | + ts_flags_names, info->extack, | |
| 393 | + &config_mod); | |
| 394 | + if (ret < 0) | |
| 395 | + goto err_free_hwprov; | |
| 383 | 396 | } |
| 384 | 397 | |
| 385 | 398 | ret = net_hwtstamp_validate(&hwtst_config); |
| @@ -659,10 +659,12 @@ static int arp_xmit_finish(struct net *net, struct sock *sk, struct sk_buff *skb · 658 unmodified lines | ||
| 659 | 659 | */ |
| 660 | 660 | void arp_xmit(struct sk_buff *skb) |
| 661 | 661 | { |
| 662 | + rcu_read_lock(); | |
| 662 | 663 | /* Send it off, maybe filter it using firewalling first. */ |
| 663 | 664 | NF_HOOK(NFPROTO_ARP, NF_ARP_OUT, |
| 664 | − dev_net(skb->dev), NULL, skb, NULL, skb->dev, | |
| 665 | + dev_net_rcu(skb->dev), NULL, skb, NULL, skb->dev, | |
| 665 | 666 | arp_xmit_finish); |
| 667 | + rcu_read_unlock(); | |
| 666 | 668 | } |
| 667 | 669 | EXPORT_SYMBOL(arp_xmit); |
| 668 | 670 | |
| @@ -1371,10 +1371,11 @@ __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope) · 1370 unmodified lines | ||
| 1371 | 1371 | __be32 addr = 0; |
| 1372 | 1372 | unsigned char localnet_scope = RT_SCOPE_HOST; |
| 1373 | 1373 | struct in_device *in_dev; |
| 1374 | − struct net *net = dev_net(dev); | |
| 1374 | + struct net *net; | |
| 1375 | 1375 | int master_idx; |
| 1376 | 1376 | |
| 1377 | 1377 | rcu_read_lock(); |
| 1378 | + net = dev_net_rcu(dev); | |
| 1378 | 1379 | in_dev = __in_dev_get_rcu(dev); |
| 1379 | 1380 | if (!in_dev) |
| 1380 | 1381 | goto no_in_dev; |
| @@ -399,10 +399,10 @@ static void icmp_push_reply(struct sock *sk, · 398 unmodified lines | ||
| 399 | 399 | |
| 400 | 400 | static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) |
| 401 | 401 | { |
| 402 | − struct ipcm_cookie ipc; | |
| 403 | 402 | struct rtable *rt = skb_rtable(skb); |
| 404 | − struct net *net = dev_net(rt->dst.dev); | |
| 403 | + struct net *net = dev_net_rcu(rt->dst.dev); | |
| 405 | 404 | bool apply_ratelimit = false; |
| 405 | + struct ipcm_cookie ipc; | |
| 406 | 406 | struct flowi4 fl4; |
| 407 | 407 | struct sock *sk; |
| 408 | 408 | struct inet_sock *inet; |
| @@ -608,12 +608,14 @@ void __icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info, · 199 unmodified lines | ||
| 608 | 608 | struct sock *sk; |
| 609 | 609 | |
| 610 | 610 | if (!rt) |
| 611 | − goto out; | |
| 611 | + return; | |
| 612 | + | |
| 613 | + rcu_read_lock(); | |
| 612 | 614 | |
| 613 | 615 | if (rt->dst.dev) |
| 614 | − net = dev_net(rt->dst.dev); | |
| 616 | + net = dev_net_rcu(rt->dst.dev); | |
| 615 | 617 | else if (skb_in->dev) |
| 616 | − net = dev_net(skb_in->dev); | |
| 618 | + net = dev_net_rcu(skb_in->dev); | |
| 617 | 619 | else |
| 618 | 620 | goto out; |
| 619 | 621 | |
| @@ -785,7 +787,8 @@ out_unlock: · 165 unmodified lines | ||
| 785 | 787 | icmp_xmit_unlock(sk); |
| 786 | 788 | out_bh_enable: |
| 787 | 789 | local_bh_enable(); |
| 788 | −out:; | |
| 790 | +out: | |
| 791 | + rcu_read_unlock(); | |
| 789 | 792 | } |
| 790 | 793 | EXPORT_SYMBOL(__icmp_send); |
| 791 | 794 | |
| @@ -834,7 +837,7 @@ static void icmp_socket_deliver(struct sk_buff *skb, u32 info) · 42 unmodified lines | ||
| 834 | 837 | * avoid additional coding at protocol handlers. |
| 835 | 838 | */ |
| 836 | 839 | if (!pskb_may_pull(skb, iph->ihl * 4 + 8)) { |
| 837 | − __ICMP_INC_STATS(dev_net(skb->dev), ICMP_MIB_INERRORS); | |
| 840 | + __ICMP_INC_STATS(dev_net_rcu(skb->dev), ICMP_MIB_INERRORS); | |
| 838 | 841 | return; |
| 839 | 842 | } |
| 840 | 843 | |
| @@ -868,7 +871,7 @@ static enum skb_drop_reason icmp_unreach(struct sk_buff *skb) · 27 unmodified lines | ||
| 868 | 871 | struct net *net; |
| 869 | 872 | u32 info = 0; |
| 870 | 873 | |
| 871 | − net = dev_net(skb_dst(skb)->dev); | |
| 874 | + net = dev_net_rcu(skb_dst(skb)->dev); | |
| 872 | 875 | |
| 873 | 876 | /* |
| 874 | 877 | * Incomplete header ? |
| @@ -979,7 +982,7 @@ out_err: · 104 unmodified lines | ||
| 979 | 982 | static enum skb_drop_reason icmp_redirect(struct sk_buff *skb) |
| 980 | 983 | { |
| 981 | 984 | if (skb->len < sizeof(struct iphdr)) { |
| 982 | − __ICMP_INC_STATS(dev_net(skb->dev), ICMP_MIB_INERRORS); | |
| 985 | + __ICMP_INC_STATS(dev_net_rcu(skb->dev), ICMP_MIB_INERRORS); | |
| 983 | 986 | return SKB_DROP_REASON_PKT_TOO_SMALL; |
| 984 | 987 | } |
| 985 | 988 | |
| @@ -1011,7 +1014,7 @@ static enum skb_drop_reason icmp_echo(struct sk_buff *skb) · 25 unmodified lines | ||
| 1011 | 1014 | struct icmp_bxm icmp_param; |
| 1012 | 1015 | struct net *net; |
| 1013 | 1016 | |
| 1014 | − net = dev_net(skb_dst(skb)->dev); | |
| 1017 | + net = dev_net_rcu(skb_dst(skb)->dev); | |
| 1015 | 1018 | /* should there be an ICMP stat for ignored echos? */ |
| 1016 | 1019 | if (READ_ONCE(net->ipv4.sysctl_icmp_echo_ignore_all)) |
| 1017 | 1020 | return SKB_NOT_DROPPED_YET; |
| @@ -1040,9 +1043,9 @@ static enum skb_drop_reason icmp_echo(struct sk_buff *skb) · 22 unmodified lines | ||
| 1040 | 1043 | |
| 1041 | 1044 | bool icmp_build_probe(struct sk_buff *skb, struct icmphdr *icmphdr) |
| 1042 | 1045 | { |
| 1046 | + struct net *net = dev_net_rcu(skb->dev); | |
| 1043 | 1047 | struct icmp_ext_hdr *ext_hdr, _ext_hdr; |
| 1044 | 1048 | struct icmp_ext_echo_iio *iio, _iio; |
| 1045 | − struct net *net = dev_net(skb->dev); | |
| 1046 | 1049 | struct inet6_dev *in6_dev; |
| 1047 | 1050 | struct in_device *in_dev; |
| 1048 | 1051 | struct net_device *dev; |
| @@ -1181,7 +1184,7 @@ static enum skb_drop_reason icmp_timestamp(struct sk_buff *skb) · 132 unmodified lines | ||
| 1181 | 1184 | return SKB_NOT_DROPPED_YET; |
| 1182 | 1185 | |
| 1183 | 1186 | out_err: |
| 1184 | − __ICMP_INC_STATS(dev_net(skb_dst(skb)->dev), ICMP_MIB_INERRORS); | |
| 1187 | + __ICMP_INC_STATS(dev_net_rcu(skb_dst(skb)->dev), ICMP_MIB_INERRORS); | |
| 1185 | 1188 | return SKB_DROP_REASON_PKT_TOO_SMALL; |
| 1186 | 1189 | } |
| 1187 | 1190 | |
| @@ -1198,7 +1201,7 @@ int icmp_rcv(struct sk_buff *skb) · 10 unmodified lines | ||
| 1198 | 1201 | { |
| 1199 | 1202 | enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED; |
| 1200 | 1203 | struct rtable *rt = skb_rtable(skb); |
| 1201 | − struct net *net = dev_net(rt->dst.dev); | |
| 1204 | + struct net *net = dev_net_rcu(rt->dst.dev); | |
| 1202 | 1205 | struct icmphdr *icmph; |
| 1203 | 1206 | |
| 1204 | 1207 | if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) { |
| @@ -1371,9 +1374,9 @@ int icmp_err(struct sk_buff *skb, u32 info) · 166 unmodified lines | ||
| 1371 | 1374 | struct iphdr *iph = (struct iphdr *)skb->data; |
| 1372 | 1375 | int offset = iph->ihl<<2; |
| 1373 | 1376 | struct icmphdr *icmph = (struct icmphdr *)(skb->data + offset); |
| 1377 | + struct net *net = dev_net_rcu(skb->dev); | |
| 1374 | 1378 | int type = icmp_hdr(skb)->type; |
| 1375 | 1379 | int code = icmp_hdr(skb)->code; |
| 1376 | − struct net *net = dev_net(skb->dev); | |
| 1377 | 1380 | |
| 1378 | 1381 | /* |
| 1379 | 1382 | * Use ping_err to handle all icmp errors except those |
| @@ -390,7 +390,13 @@ static inline int ip_rt_proc_init(void) · 389 unmodified lines | ||
| 390 | 390 | |
| 391 | 391 | static inline bool rt_is_expired(const struct rtable *rth) |
| 392 | 392 | { |
| 393 | − return rth->rt_genid != rt_genid_ipv4(dev_net(rth->dst.dev)); | |
| 393 | + bool res; | |
| 394 | + | |
| 395 | + rcu_read_lock(); | |
| 396 | + res = rth->rt_genid != rt_genid_ipv4(dev_net_rcu(rth->dst.dev)); | |
| 397 | + rcu_read_unlock(); | |
| 398 | + | |
| 399 | + return res; | |
| 394 | 400 | } |
| 395 | 401 | |
| 396 | 402 | void rt_cache_flush(struct net *net) |
| @@ -1002,9 +1008,9 @@ out: kfree_skb_reason(skb, reason); · 605 unmodified lines | ||
| 1002 | 1008 | static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu) |
| 1003 | 1009 | { |
| 1004 | 1010 | struct dst_entry *dst = &rt->dst; |
| 1005 | − struct net *net = dev_net(dst->dev); | |
| 1006 | 1011 | struct fib_result res; |
| 1007 | 1012 | bool lock = false; |
| 1013 | + struct net *net; | |
| 1008 | 1014 | u32 old_mtu; |
| 1009 | 1015 | |
| 1010 | 1016 | if (ip_mtu_locked(dst)) |
| @@ -1014,6 +1020,8 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu) · 3 unmodified lines | ||
| 1014 | 1020 | if (old_mtu < mtu) |
| 1015 | 1021 | return; |
| 1016 | 1022 | |
| 1023 | + rcu_read_lock(); | |
| 1024 | + net = dev_net_rcu(dst->dev); | |
| 1017 | 1025 | if (mtu < net->ipv4.ip_rt_min_pmtu) { |
| 1018 | 1026 | lock = true; |
| 1019 | 1027 | mtu = min(old_mtu, net->ipv4.ip_rt_min_pmtu); |
| @@ -1021,9 +1029,8 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu) · 1 unmodified line | ||
| 1021 | 1029 | |
| 1022 | 1030 | if (rt->rt_pmtu == mtu && !lock && |
| 1023 | 1031 | time_before(jiffies, dst->expires - net->ipv4.ip_rt_mtu_expires / 2)) |
| 1024 | − return; | |
| 1032 | + goto out; | |
| 1025 | 1033 | |
| 1026 | − rcu_read_lock(); | |
| 1027 | 1034 | if (fib_lookup(net, fl4, &res, 0) == 0) { |
| 1028 | 1035 | struct fib_nh_common *nhc; |
| 1029 | 1036 | |
| @@ -1037,14 +1044,14 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu) · 7 unmodified lines | ||
| 1037 | 1044 | update_or_create_fnhe(nhc, fl4->daddr, 0, mtu, lock, |
| 1038 | 1045 | jiffies + net->ipv4.ip_rt_mtu_expires); |
| 1039 | 1046 | } |
| 1040 | − rcu_read_unlock(); | |
| 1041 | − return; | |
| 1047 | + goto out; | |
| 1042 | 1048 | } |
| 1043 | 1049 | #endif /* CONFIG_IP_ROUTE_MULTIPATH */ |
| 1044 | 1050 | nhc = FIB_RES_NHC(res); |
| 1045 | 1051 | update_or_create_fnhe(nhc, fl4->daddr, 0, mtu, lock, |
| 1046 | 1052 | jiffies + net->ipv4.ip_rt_mtu_expires); |
| 1047 | 1053 | } |
| 1054 | +out: | |
| 1048 | 1055 | rcu_read_unlock(); |
| 1049 | 1056 | } |
| 1050 | 1057 | |
| @@ -1307,10 +1314,15 @@ static void set_class_tag(struct rtable *rt, u32 tag) · 256 unmodified lines | ||
| 1307 | 1314 | |
| 1308 | 1315 | static unsigned int ipv4_default_advmss(const struct dst_entry *dst) |
| 1309 | 1316 | { |
| 1310 | − struct net *net = dev_net(dst->dev); | |
| 1311 | 1317 | unsigned int header_size = sizeof(struct tcphdr) + sizeof(struct iphdr); |
| 1312 | − unsigned int advmss = max_t(unsigned int, ipv4_mtu(dst) - header_size, | |
| 1313 | − net->ipv4.ip_rt_min_advmss); | |
| 1318 | + unsigned int advmss; | |
| 1319 | + struct net *net; | |
| 1320 | + | |
| 1321 | + rcu_read_lock(); | |
| 1322 | + net = dev_net_rcu(dst->dev); | |
| 1323 | + advmss = max_t(unsigned int, ipv4_mtu(dst) - header_size, | |
| 1324 | + net->ipv4.ip_rt_min_advmss); | |
| 1325 | + rcu_read_unlock(); | |
| 1314 | 1326 | |
| 1315 | 1327 | return min(advmss, IPV4_MAX_PMTU - header_size); |
| 1316 | 1328 | } |
| @@ -76,7 +76,7 @@ static int icmpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, · 75 unmodified lines | ||
| 76 | 76 | { |
| 77 | 77 | /* icmpv6_notify checks 8 bytes can be pulled, icmp6hdr is 8 bytes */ |
| 78 | 78 | struct icmp6hdr *icmp6 = (struct icmp6hdr *) (skb->data + offset); |
| 79 | − struct net *net = dev_net(skb->dev); | |
| 79 | + struct net *net = dev_net_rcu(skb->dev); | |
| 80 | 80 | |
| 81 | 81 | if (type == ICMPV6_PKT_TOOBIG) |
| 82 | 82 | ip6_update_pmtu(skb, net, info, skb->dev->ifindex, 0, sock_net_uid(net, NULL)); |
| @@ -473,7 +473,10 @@ void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, · 390 unmodified lines | ||
| 473 | 473 | |
| 474 | 474 | if (!skb->dev) |
| 475 | 475 | return; |
| 476 | − net = dev_net(skb->dev); | |
| 476 | + | |
| 477 | + rcu_read_lock(); | |
| 478 | + | |
| 479 | + net = dev_net_rcu(skb->dev); | |
| 477 | 480 | mark = IP6_REPLY_MARK(net, skb->mark); |
| 478 | 481 | /* |
| 479 | 482 | * Make sure we respect the rules |
| @@ -496,7 +499,7 @@ void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, · 16 unmodified lines | ||
| 496 | 499 | !(type == ICMPV6_PARAMPROB && |
| 497 | 500 | code == ICMPV6_UNK_OPTION && |
| 498 | 501 | (opt_unrec(skb, info)))) |
| 499 | − return; | |
| 502 | + goto out; | |
| 500 | 503 | |
| 501 | 504 | saddr = NULL; |
| 502 | 505 | } |
| @@ -526,7 +529,7 @@ void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, · 23 unmodified lines | ||
| 526 | 529 | if ((addr_type == IPV6_ADDR_ANY) || (addr_type & IPV6_ADDR_MULTICAST)) { |
| 527 | 530 | net_dbg_ratelimited("icmp6_send: addr_any/mcast source [%pI6c > %pI6c]\n", |
| 528 | 531 | &hdr->saddr, &hdr->daddr); |
| 529 | − return; | |
| 532 | + goto out; | |
| 530 | 533 | } |
| 531 | 534 | |
| 532 | 535 | /* |
| @@ -535,7 +538,7 @@ void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, · 2 unmodified lines | ||
| 535 | 538 | if (is_ineligible(skb)) { |
| 536 | 539 | net_dbg_ratelimited("icmp6_send: no reply to icmp error [%pI6c > %pI6c]\n", |
| 537 | 540 | &hdr->saddr, &hdr->daddr); |
| 538 | − return; | |
| 541 | + goto out; | |
| 539 | 542 | } |
| 540 | 543 | |
| 541 | 544 | /* Needed by both icmpv6_global_allow and icmpv6_xmit_lock */ |
| @@ -582,7 +585,7 @@ void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, · 40 unmodified lines | ||
| 582 | 585 | np = inet6_sk(sk); |
| 583 | 586 | |
| 584 | 587 | if (!icmpv6_xrlim_allow(sk, type, &fl6, apply_ratelimit)) |
| 585 | − goto out; | |
| 588 | + goto out_unlock; | |
| 586 | 589 | |
| 587 | 590 | tmp_hdr.icmp6_type = type; |
| 588 | 591 | tmp_hdr.icmp6_code = code; |
| @@ -600,7 +603,7 @@ void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, · 11 unmodified lines | ||
| 600 | 603 | |
| 601 | 604 | dst = icmpv6_route_lookup(net, skb, sk, &fl6); |
| 602 | 605 | if (IS_ERR(dst)) |
| 603 | − goto out; | |
| 606 | + goto out_unlock; | |
| 604 | 607 | |
| 605 | 608 | ipc6.hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst); |
| 606 | 609 | |
| @@ -616,7 +619,6 @@ void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, · 9 unmodified lines | ||
| 616 | 619 | goto out_dst_release; |
| 617 | 620 | } |
| 618 | 621 | |
| 619 | − rcu_read_lock(); | |
| 620 | 622 | idev = __in6_dev_get(skb->dev); |
| 621 | 623 | |
| 622 | 624 | if (ip6_append_data(sk, icmpv6_getfrag, &msg, |
| @@ -630,13 +632,15 @@ void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, · 7 unmodified lines | ||
| 630 | 632 | icmpv6_push_pending_frames(sk, &fl6, &tmp_hdr, |
| 631 | 633 | len + sizeof(struct icmp6hdr)); |
| 632 | 634 | } |
| 633 | − rcu_read_unlock(); | |
| 635 | + | |
| 634 | 636 | out_dst_release: |
| 635 | 637 | dst_release(dst); |
| 636 | −out: | |
| 638 | +out_unlock: | |
| 637 | 639 | icmpv6_xmit_unlock(sk); |
| 638 | 640 | out_bh_enable: |
| 639 | 641 | local_bh_enable(); |
| 642 | +out: | |
| 643 | + rcu_read_unlock(); | |
| 640 | 644 | } |
| 641 | 645 | EXPORT_SYMBOL(icmp6_send); |
| 642 | 646 | |
| @@ -679,8 +683,8 @@ int ip6_err_gen_icmpv6_unreach(struct sk_buff *skb, int nhs, int type, · 36 unmodified lines | ||
| 679 | 683 | skb_pull(skb2, nhs); |
| 680 | 684 | skb_reset_network_header(skb2); |
| 681 | 685 | |
| 682 | − rt = rt6_lookup(dev_net(skb->dev), &ipv6_hdr(skb2)->saddr, NULL, 0, | |
| 683 | − skb, 0); | |
| 686 | + rt = rt6_lookup(dev_net_rcu(skb->dev), &ipv6_hdr(skb2)->saddr, | |
| 687 | + NULL, 0, skb, 0); | |
| 684 | 688 | |
| 685 | 689 | if (rt && rt->dst.dev) |
| 686 | 690 | skb2->dev = rt->dst.dev; |
| @@ -717,7 +721,7 @@ EXPORT_SYMBOL(ip6_err_gen_icmpv6_unreach); · 30 unmodified lines | ||
| 717 | 721 | |
| 718 | 722 | static enum skb_drop_reason icmpv6_echo_reply(struct sk_buff *skb) |
| 719 | 723 | { |
| 720 | − struct net *net = dev_net(skb->dev); | |
| 724 | + struct net *net = dev_net_rcu(skb->dev); | |
| 721 | 725 | struct sock *sk; |
| 722 | 726 | struct inet6_dev *idev; |
| 723 | 727 | struct ipv6_pinfo *np; |
| @@ -832,7 +836,7 @@ enum skb_drop_reason icmpv6_notify(struct sk_buff *skb, u8 type, · 108 unmodified lines | ||
| 832 | 836 | u8 code, __be32 info) |
| 833 | 837 | { |
| 834 | 838 | struct inet6_skb_parm *opt = IP6CB(skb); |
| 835 | − struct net *net = dev_net(skb->dev); | |
| 839 | + struct net *net = dev_net_rcu(skb->dev); | |
| 836 | 840 | const struct inet6_protocol *ipprot; |
| 837 | 841 | enum skb_drop_reason reason; |
| 838 | 842 | int inner_offset; |
| @@ -889,7 +893,7 @@ out: · 50 unmodified lines | ||
| 889 | 893 | static int icmpv6_rcv(struct sk_buff *skb) |
| 890 | 894 | { |
| 891 | 895 | enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED; |
| 892 | − struct net *net = dev_net(skb->dev); | |
| 896 | + struct net *net = dev_net_rcu(skb->dev); | |
| 893 | 897 | struct net_device *dev = icmp6_dev(skb); |
| 894 | 898 | struct inet6_dev *idev = __in6_dev_get(dev); |
| 895 | 899 | const struct in6_addr *saddr, *daddr; |
| @@ -921,7 +925,7 @@ static int icmpv6_rcv(struct sk_buff *skb) · 25 unmodified lines | ||
| 921 | 925 | skb_set_network_header(skb, nh); |
| 922 | 926 | } |
| 923 | 927 | |
| 924 | − __ICMP6_INC_STATS(dev_net(dev), idev, ICMP6_MIB_INMSGS); | |
| 928 | + __ICMP6_INC_STATS(dev_net_rcu(dev), idev, ICMP6_MIB_INMSGS); | |
| 925 | 929 | |
| 926 | 930 | saddr = &ipv6_hdr(skb)->saddr; |
| 927 | 931 | daddr = &ipv6_hdr(skb)->daddr; |
| @@ -939,7 +943,7 @@ static int icmpv6_rcv(struct sk_buff *skb) · 11 unmodified lines | ||
| 939 | 943 | |
| 940 | 944 | type = hdr->icmp6_type; |
| 941 | 945 | |
| 942 | − ICMP6MSGIN_INC_STATS(dev_net(dev), idev, type); | |
| 946 | + ICMP6MSGIN_INC_STATS(dev_net_rcu(dev), idev, type); | |
| 943 | 947 | |
| 944 | 948 | switch (type) { |
| 945 | 949 | case ICMPV6_ECHO_REQUEST: |
| @@ -1034,9 +1038,9 @@ static int icmpv6_rcv(struct sk_buff *skb) · 88 unmodified lines | ||
| 1034 | 1038 | |
| 1035 | 1039 | csum_error: |
| 1036 | 1040 | reason = SKB_DROP_REASON_ICMP_CSUM; |
| 1037 | − __ICMP6_INC_STATS(dev_net(dev), idev, ICMP6_MIB_CSUMERRORS); | |
| 1041 | + __ICMP6_INC_STATS(dev_net_rcu(dev), idev, ICMP6_MIB_CSUMERRORS); | |
| 1038 | 1042 | discard_it: |
| 1039 | − __ICMP6_INC_STATS(dev_net(dev), idev, ICMP6_MIB_INERRORS); | |
| 1043 | + __ICMP6_INC_STATS(dev_net_rcu(dev), idev, ICMP6_MIB_INERRORS); | |
| 1040 | 1044 | drop_no_count: |
| 1041 | 1045 | kfree_skb_reason(skb, reason); |
| 1042 | 1046 | return 0; |
| @@ -477,9 +477,7 @@ discard: · 476 unmodified lines | ||
| 477 | 477 | static int ip6_input_finish(struct net *net, struct sock *sk, struct sk_buff *skb) |
| 478 | 478 | { |
| 479 | 479 | skb_clear_delivery_time(skb); |
| 480 | − rcu_read_lock(); | |
| 481 | 480 | ip6_protocol_deliver_rcu(net, skb, 0, false); |
| 482 | − rcu_read_unlock(); | |
| 483 | 481 | |
| 484 | 482 | return 0; |
| 485 | 483 | } |
| @@ -487,9 +485,15 @@ static int ip6_input_finish(struct net *net, struct sock *sk, struct sk_buff *sk · 1 unmodified line | ||
| 487 | 485 | |
| 488 | 486 | int ip6_input(struct sk_buff *skb) |
| 489 | 487 | { |
| 490 | − return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_IN, | |
| 491 | − dev_net(skb->dev), NULL, skb, skb->dev, NULL, | |
| 492 | − ip6_input_finish); | |
| 488 | + int res; | |
| 489 | + | |
| 490 | + rcu_read_lock(); | |
| 491 | + res = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_IN, | |
| 492 | + dev_net_rcu(skb->dev), NULL, skb, skb->dev, NULL, | |
| 493 | + ip6_input_finish); | |
| 494 | + rcu_read_unlock(); | |
| 495 | + | |
| 496 | + return res; | |
| 493 | 497 | } |
| 494 | 498 | EXPORT_SYMBOL_GPL(ip6_input); |
| 495 | 499 | |
| @@ -1773,21 +1773,19 @@ static struct sk_buff *mld_newpack(struct inet6_dev *idev, unsigned int mtu) · 1772 unmodified lines | ||
| 1773 | 1773 | struct net_device *dev = idev->dev; |
| 1774 | 1774 | int hlen = LL_RESERVED_SPACE(dev); |
| 1775 | 1775 | int tlen = dev->needed_tailroom; |
| 1776 | − struct net *net = dev_net(dev); | |
| 1777 | 1776 | const struct in6_addr *saddr; |
| 1778 | 1777 | struct in6_addr addr_buf; |
| 1779 | 1778 | struct mld2_report *pmr; |
| 1780 | 1779 | struct sk_buff *skb; |
| 1781 | 1780 | unsigned int size; |
| 1782 | 1781 | struct sock *sk; |
| 1783 | − int err; | |
| 1782 | + struct net *net; | |
| 1784 | 1783 | |
| 1785 | − sk = net->ipv6.igmp_sk; | |
| 1786 | 1784 | /* we assume size > sizeof(ra) here |
| 1787 | 1785 | * Also try to not allocate high-order pages for big MTU |
| 1788 | 1786 | */ |
| 1789 | 1787 | size = min_t(int, mtu, PAGE_SIZE / 2) + hlen + tlen; |
| 1790 | − skb = sock_alloc_send_skb(sk, size, 1, &err); | |
| 1788 | + skb = alloc_skb(size, GFP_KERNEL); | |
| 1791 | 1789 | if (!skb) |
| 1792 | 1790 | return NULL; |
| 1793 | 1791 | |
| @@ -1795,6 +1793,12 @@ static struct sk_buff *mld_newpack(struct inet6_dev *idev, unsigned int mtu) · 1 unmodified line | ||
| 1795 | 1793 | skb_reserve(skb, hlen); |
| 1796 | 1794 | skb_tailroom_reserve(skb, mtu, tlen); |
| 1797 | 1795 | |
| 1796 | + rcu_read_lock(); | |
| 1797 | + | |
| 1798 | + net = dev_net_rcu(dev); | |
| 1799 | + sk = net->ipv6.igmp_sk; | |
| 1800 | + skb_set_owner_w(skb, sk); | |
| 1801 | + | |
| 1798 | 1802 | if (ipv6_get_lladdr(dev, &addr_buf, IFA_F_TENTATIVE)) { |
| 1799 | 1803 | /* <draft-ietf-magma-mld-source-05.txt>: |
| 1800 | 1804 | * use unspecified address as the source address |
| @@ -1806,6 +1810,8 @@ static struct sk_buff *mld_newpack(struct inet6_dev *idev, unsigned int mtu) · 5 unmodified lines | ||
| 1806 | 1810 | |
| 1807 | 1811 | ip6_mc_hdr(sk, skb, dev, saddr, &mld2_all_mcr, NEXTHDR_HOP, 0); |
| 1808 | 1812 | |
| 1813 | + rcu_read_unlock(); | |
| 1814 | + | |
| 1809 | 1815 | skb_put_data(skb, ra, sizeof(ra)); |
| 1810 | 1816 | |
| 1811 | 1817 | skb_set_transport_header(skb, skb_tail_pointer(skb) - skb->data); |
| @@ -2165,21 +2171,21 @@ static void mld_send_cr(struct inet6_dev *idev) · 353 unmodified lines | ||
| 2165 | 2171 | |
| 2166 | 2172 | static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) |
| 2167 | 2173 | { |
| 2168 | − struct net *net = dev_net(dev); | |
| 2169 | − struct sock *sk = net->ipv6.igmp_sk; | |
| 2174 | + const struct in6_addr *snd_addr, *saddr; | |
| 2175 | + int err, len, payload_len, full_len; | |
| 2176 | + struct in6_addr addr_buf; | |
| 2170 | 2177 | struct inet6_dev *idev; |
| 2171 | 2178 | struct sk_buff *skb; |
| 2172 | 2179 | struct mld_msg *hdr; |
| 2173 | − const struct in6_addr *snd_addr, *saddr; | |
| 2174 | − struct in6_addr addr_buf; | |
| 2175 | 2180 | int hlen = LL_RESERVED_SPACE(dev); |
| 2176 | 2181 | int tlen = dev->needed_tailroom; |
| 2177 | − int err, len, payload_len, full_len; | |
| 2178 | 2182 | u8 ra[8] = { IPPROTO_ICMPV6, 0, |
| 2179 | 2183 | IPV6_TLV_ROUTERALERT, 2, 0, 0, |
| 2180 | 2184 | IPV6_TLV_PADN, 0 }; |
| 2181 | − struct flowi6 fl6; | |
| 2182 | 2185 | struct dst_entry *dst; |
| 2186 | + struct flowi6 fl6; | |
| 2187 | + struct net *net; | |
| 2188 | + struct sock *sk; | |
| 2183 | 2189 | |
| 2184 | 2190 | if (type == ICMPV6_MGM_REDUCTION) |
| 2185 | 2191 | snd_addr = &in6addr_linklocal_allrouters; |
| @@ -2190,19 +2196,21 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) · 4 unmodified lines | ||
| 2190 | 2196 | payload_len = len + sizeof(ra); |
| 2191 | 2197 | full_len = sizeof(struct ipv6hdr) + payload_len; |
| 2192 | 2198 | |
| 2193 | − rcu_read_lock(); | |
| 2194 | − IP6_INC_STATS(net, __in6_dev_get(dev), IPSTATS_MIB_OUTREQUESTS); | |
| 2195 | − rcu_read_unlock(); | |
| 2199 | + skb = alloc_skb(hlen + tlen + full_len, GFP_KERNEL); | |
| 2196 | 2200 | |
| 2197 | − skb = sock_alloc_send_skb(sk, hlen + tlen + full_len, 1, &err); | |
| 2201 | + rcu_read_lock(); | |
| 2198 | 2202 | |
| 2203 | + net = dev_net_rcu(dev); | |
| 2204 | + idev = __in6_dev_get(dev); | |
| 2205 | + IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS); | |
| 2199 | 2206 | if (!skb) { |
| 2200 | − rcu_read_lock(); | |
| 2201 | − IP6_INC_STATS(net, __in6_dev_get(dev), | |
| 2202 | − IPSTATS_MIB_OUTDISCARDS); | |
| 2207 | + IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS); | |
| 2203 | 2208 | rcu_read_unlock(); |
| 2204 | 2209 | return; |
| 2205 | 2210 | } |
| 2211 | + sk = net->ipv6.igmp_sk; | |
| 2212 | + skb_set_owner_w(skb, sk); | |
| 2213 | + | |
| 2206 | 2214 | skb->priority = TC_PRIO_CONTROL; |
| 2207 | 2215 | skb_reserve(skb, hlen); |
| 2208 | 2216 | |
| @@ -2227,9 +2235,6 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) · 18 unmodified lines | ||
| 2227 | 2235 | IPPROTO_ICMPV6, |
| 2228 | 2236 | csum_partial(hdr, len, 0)); |
| 2229 | 2237 | |
| 2230 | − rcu_read_lock(); | |
| 2231 | − idev = __in6_dev_get(skb->dev); | |
| 2232 | − | |
| 2233 | 2238 | icmpv6_flow_init(sk, &fl6, type, |
| 2234 | 2239 | &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, |
| 2235 | 2240 | skb->dev->ifindex); |
| @@ -418,15 +418,11 @@ static struct sk_buff *ndisc_alloc_skb(struct net_device *dev, · 417 unmodified lines | ||
| 418 | 418 | { |
| 419 | 419 | int hlen = LL_RESERVED_SPACE(dev); |
| 420 | 420 | int tlen = dev->needed_tailroom; |
| 421 | − struct sock *sk = dev_net(dev)->ipv6.ndisc_sk; | |
| 422 | 421 | struct sk_buff *skb; |
| 423 | 422 | |
| 424 | 423 | skb = alloc_skb(hlen + sizeof(struct ipv6hdr) + len + tlen, GFP_ATOMIC); |
| 425 | − if (!skb) { | |
| 426 | − ND_PRINTK(0, err, "ndisc: %s failed to allocate an skb\n", | |
| 427 | − __func__); | |
| 424 | + if (!skb) | |
| 428 | 425 | return NULL; |
| 429 | − } | |
| 430 | 426 | |
| 431 | 427 | skb->protocol = htons(ETH_P_IPV6); |
| 432 | 428 | skb->dev = dev; |
| @@ -437,7 +433,9 @@ static struct sk_buff *ndisc_alloc_skb(struct net_device *dev, · 4 unmodified lines | ||
| 437 | 433 | /* Manually assign socket ownership as we avoid calling |
| 438 | 434 | * sock_alloc_send_pskb() to bypass wmem buffer limits |
| 439 | 435 | */ |
| 440 | − skb_set_owner_w(skb, sk); | |
| 436 | + rcu_read_lock(); | |
| 437 | + skb_set_owner_w(skb, dev_net_rcu(dev)->ipv6.ndisc_sk); | |
| 438 | + rcu_read_unlock(); | |
| 441 | 439 | |
| 442 | 440 | return skb; |
| 443 | 441 | } |
| @@ -473,16 +471,20 @@ static void ip6_nd_hdr(struct sk_buff *skb, · 29 unmodified lines | ||
| 473 | 471 | void ndisc_send_skb(struct sk_buff *skb, const struct in6_addr *daddr, |
| 474 | 472 | const struct in6_addr *saddr) |
| 475 | 473 | { |
| 474 | + struct icmp6hdr *icmp6h = icmp6_hdr(skb); | |
| 476 | 475 | struct dst_entry *dst = skb_dst(skb); |
| 477 | − struct net *net = dev_net(skb->dev); | |
| 478 | − struct sock *sk = net->ipv6.ndisc_sk; | |
| 479 | 476 | struct inet6_dev *idev; |
| 477 | + struct net *net; | |
| 478 | + struct sock *sk; | |
| 480 | 479 | int err; |
| 481 | − struct icmp6hdr *icmp6h = icmp6_hdr(skb); | |
| 482 | 480 | u8 type; |
| 483 | 481 | |
| 484 | 482 | type = icmp6h->icmp6_type; |
| 485 | 483 | |
| 484 | + rcu_read_lock(); | |
| 485 | + | |
| 486 | + net = dev_net_rcu(skb->dev); | |
| 487 | + sk = net->ipv6.ndisc_sk; | |
| 486 | 488 | if (!dst) { |
| 487 | 489 | struct flowi6 fl6; |
| 488 | 490 | int oif = skb->dev->ifindex; |
| @@ -490,6 +492,7 @@ void ndisc_send_skb(struct sk_buff *skb, const struct in6_addr *daddr, · 1 unmodified line | ||
| 490 | 492 | icmpv6_flow_init(sk, &fl6, type, saddr, daddr, oif); |
| 491 | 493 | dst = icmp6_dst_alloc(skb->dev, &fl6); |
| 492 | 494 | if (IS_ERR(dst)) { |
| 495 | + rcu_read_unlock(); | |
| 493 | 496 | kfree_skb(skb); |
| 494 | 497 | return; |
| 495 | 498 | } |
| @@ -504,7 +507,6 @@ void ndisc_send_skb(struct sk_buff *skb, const struct in6_addr *daddr, · 8 unmodified lines | ||
| 504 | 507 | |
| 505 | 508 | ip6_nd_hdr(skb, saddr, daddr, READ_ONCE(inet6_sk(sk)->hop_limit), skb->len); |
| 506 | 509 | |
| 507 | − rcu_read_lock(); | |
| 508 | 510 | idev = __in6_dev_get(dst->dev); |
| 509 | 511 | IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS); |
| 510 | 512 | |
| @@ -1694,7 +1696,7 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target) · 1183 unmodified lines | ||
| 1694 | 1696 | bool ret; |
| 1695 | 1697 | |
| 1696 | 1698 | if (netif_is_l3_master(skb->dev)) { |
| 1697 | − dev = __dev_get_by_index(dev_net(skb->dev), IPCB(skb)->iif); | |
| 1699 | + dev = dev_get_by_index_rcu(dev_net(skb->dev), IPCB(skb)->iif); | |
| 1698 | 1700 | if (!dev) |
| 1699 | 1701 | return; |
| 1700 | 1702 | } |
| @@ -3196,13 +3196,18 @@ static unsigned int ip6_default_advmss(const struct dst_entry *dst) · 3195 unmodified lines | ||
| 3196 | 3196 | { |
| 3197 | 3197 | struct net_device *dev = dst->dev; |
| 3198 | 3198 | unsigned int mtu = dst_mtu(dst); |
| 3199 | − struct net *net = dev_net(dev); | |
| 3199 | + struct net *net; | |
| 3200 | 3200 | |
| 3201 | 3201 | mtu -= sizeof(struct ipv6hdr) + sizeof(struct tcphdr); |
| 3202 | 3202 | |
| 3203 | + rcu_read_lock(); | |
| 3204 | + | |
| 3205 | + net = dev_net_rcu(dev); | |
| 3203 | 3206 | if (mtu < net->ipv6.sysctl.ip6_rt_min_advmss) |
| 3204 | 3207 | mtu = net->ipv6.sysctl.ip6_rt_min_advmss; |
| 3205 | 3208 | |
| 3209 | + rcu_read_unlock(); | |
| 3210 | + | |
| 3206 | 3211 | /* |
| 3207 | 3212 | * Maximal non-jumbo IPv6 payload is IPV6_MAXPLEN and |
| 3208 | 3213 | * corresponding MSS is IPV6_MAXPLEN - tcp_header_size. |
| @@ -381,10 +381,8 @@ static int nf_flow_offload_forward(struct nf_flowtable_ctx *ctx, · 380 unmodified lines | ||
| 381 | 381 | flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); |
| 382 | 382 | |
| 383 | 383 | mtu = flow->tuplehash[dir].tuple.mtu + ctx->offset; |
| 384 | − if (unlikely(nf_flow_exceeds_mtu(skb, mtu))) { | |
| 385 | − flow_offload_teardown(flow); | |
| 384 | + if (unlikely(nf_flow_exceeds_mtu(skb, mtu))) | |
| 386 | 385 | return 0; |
| 387 | − } | |
| 388 | 386 | |
| 389 | 387 | iph = (struct iphdr *)(skb_network_header(skb) + ctx->offset); |
| 390 | 388 | thoff = (iph->ihl * 4) + ctx->offset; |
| @@ -662,10 +660,8 @@ static int nf_flow_offload_ipv6_forward(struct nf_flowtable_ctx *ctx, · 271 unmodified lines | ||
| 662 | 660 | flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); |
| 663 | 661 | |
| 664 | 662 | mtu = flow->tuplehash[dir].tuple.mtu + ctx->offset; |
| 665 | − if (unlikely(nf_flow_exceeds_mtu(skb, mtu))) { | |
| 666 | − flow_offload_teardown(flow); | |
| 663 | + if (unlikely(nf_flow_exceeds_mtu(skb, mtu))) | |
| 667 | 664 | return 0; |
| 668 | − } | |
| 669 | 665 | |
| 670 | 666 | ip6h = (struct ipv6hdr *)(skb_network_header(skb) + ctx->offset); |
| 671 | 667 | thoff = sizeof(*ip6h) + ctx->offset; |
| @@ -2101,6 +2101,7 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb, · 2100 unmodified lines | ||
| 2101 | 2101 | { |
| 2102 | 2102 | struct ovs_header *ovs_header; |
| 2103 | 2103 | struct ovs_vport_stats vport_stats; |
| 2104 | + struct net *net_vport; | |
| 2104 | 2105 | int err; |
| 2105 | 2106 | |
| 2106 | 2107 | ovs_header = genlmsg_put(skb, portid, seq, &dp_vport_genl_family, |
| @@ -2117,12 +2118,15 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb, · 10 unmodified lines | ||
| 2117 | 2118 | nla_put_u32(skb, OVS_VPORT_ATTR_IFINDEX, vport->dev->ifindex)) |
| 2118 | 2119 | goto nla_put_failure; |
| 2119 | 2120 | |
| 2120 | − if (!net_eq(net, dev_net(vport->dev))) { | |
| 2121 | − int id = peernet2id_alloc(net, dev_net(vport->dev), gfp); | |
| 2121 | + rcu_read_lock(); | |
| 2122 | + net_vport = dev_net_rcu(vport->dev); | |
| 2123 | + if (!net_eq(net, net_vport)) { | |
| 2124 | + int id = peernet2id_alloc(net, net_vport, GFP_ATOMIC); | |
| 2122 | 2125 | |
| 2123 | 2126 | if (nla_put_s32(skb, OVS_VPORT_ATTR_NETNSID, id)) |
| 2124 | − goto nla_put_failure; | |
| 2127 | + goto nla_put_failure_unlock; | |
| 2125 | 2128 | } |
| 2129 | + rcu_read_unlock(); | |
| 2126 | 2130 | |
| 2127 | 2131 | ovs_vport_get_stats(vport, &vport_stats); |
| 2128 | 2132 | if (nla_put_64bit(skb, OVS_VPORT_ATTR_STATS, |
| @@ -2143,6 +2147,8 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb, · 14 unmodified lines | ||
| 2143 | 2147 | genlmsg_end(skb, ovs_header); |
| 2144 | 2148 | return 0; |
| 2145 | 2149 | |
| 2150 | +nla_put_failure_unlock: | |
| 2151 | + rcu_read_unlock(); | |
| 2146 | 2152 | nla_put_failure: |
| 2147 | 2153 | err = -EMSGSIZE; |
| 2148 | 2154 | error: |
| @@ -327,8 +327,8 @@ struct rxrpc_local { · 326 unmodified lines | ||
| 327 | 327 | * packet with a maximum set of jumbo subpackets or a PING ACK padded |
| 328 | 328 | * out to 64K with zeropages for PMTUD. |
| 329 | 329 | */ |
| 330 | − struct kvec kvec[RXRPC_MAX_NR_JUMBO > 3 + 16 ? | |
| 331 | − RXRPC_MAX_NR_JUMBO : 3 + 16]; | |
| 330 | + struct kvec kvec[1 + RXRPC_MAX_NR_JUMBO > 3 + 16 ? | |
| 331 | + 1 + RXRPC_MAX_NR_JUMBO : 3 + 16]; | |
| 332 | 332 | }; |
| 333 | 333 | |
| 334 | 334 | /* |
| @@ -874,8 +874,7 @@ struct rxrpc_txbuf { · 539 unmodified lines | ||
| 874 | 874 | #define RXRPC_TXBUF_RESENT 0x100 /* Set if has been resent */ |
| 875 | 875 | __be16 cksum; /* Checksum to go in header */ |
| 876 | 876 | bool jumboable; /* Can be non-terminal jumbo subpacket */ |
| 877 | − u8 nr_kvec; /* Amount of kvec[] used */ | |
| 878 | − struct kvec kvec[1]; | |
| 877 | + void *data; /* Data with preceding jumbo header */ | |
| 879 | 878 | }; |
| 880 | 879 | |
| 881 | 880 | static inline bool rxrpc_sending_to_server(const struct rxrpc_txbuf *txb) |
| @@ -428,13 +428,13 @@ int rxrpc_send_abort_packet(struct rxrpc_call *call) · 427 unmodified lines | ||
| 428 | 428 | static size_t rxrpc_prepare_data_subpacket(struct rxrpc_call *call, |
| 429 | 429 | struct rxrpc_send_data_req *req, |
| 430 | 430 | struct rxrpc_txbuf *txb, |
| 431 | + struct rxrpc_wire_header *whdr, | |
| 431 | 432 | rxrpc_serial_t serial, int subpkt) |
| 432 | 433 | { |
| 433 | − struct rxrpc_wire_header *whdr = txb->kvec[0].iov_base; | |
| 434 | − struct rxrpc_jumbo_header *jumbo = (void *)(whdr + 1) - sizeof(*jumbo); | |
| 434 | + struct rxrpc_jumbo_header *jumbo = txb->data - sizeof(*jumbo); | |
| 435 | 435 | enum rxrpc_req_ack_trace why; |
| 436 | 436 | struct rxrpc_connection *conn = call->conn; |
| 437 | − struct kvec *kv = &call->local->kvec[subpkt]; | |
| 437 | + struct kvec *kv = &call->local->kvec[1 + subpkt]; | |
| 438 | 438 | size_t len = txb->pkt_len; |
| 439 | 439 | bool last; |
| 440 | 440 | u8 flags; |
| @@ -491,18 +491,15 @@ static size_t rxrpc_prepare_data_subpacket(struct rxrpc_call *call, · 50 unmodified lines | ||
| 491 | 491 | } |
| 492 | 492 | dont_set_request_ack: |
| 493 | 493 | |
| 494 | − /* The jumbo header overlays the wire header in the txbuf. */ | |
| 494 | + /* There's a jumbo header prepended to the data if we need it. */ | |
| 495 | 495 | if (subpkt < req->n - 1) |
| 496 | 496 | flags |= RXRPC_JUMBO_PACKET; |
| 497 | 497 | else |
| 498 | 498 | flags &= ~RXRPC_JUMBO_PACKET; |
| 499 | 499 | if (subpkt == 0) { |
| 500 | 500 | whdr->flags = flags; |
| 501 | − whdr->serial = htonl(txb->serial); | |
| 502 | 501 | whdr->cksum = txb->cksum; |
| 503 | − whdr->serviceId = htons(conn->service_id); | |
| 504 | − kv->iov_base = whdr; | |
| 505 | − len += sizeof(*whdr); | |
| 502 | + kv->iov_base = txb->data; | |
| 506 | 503 | } else { |
| 507 | 504 | jumbo->flags = flags; |
| 508 | 505 | jumbo->pad = 0; |
| @@ -535,7 +532,9 @@ static unsigned int rxrpc_prepare_txqueue(struct rxrpc_txqueue *tq, · 26 unmodified lines | ||
| 535 | 532 | /* |
| 536 | 533 | * Prepare a (jumbo) packet for transmission. |
| 537 | 534 | */ |
| 538 | −static size_t rxrpc_prepare_data_packet(struct rxrpc_call *call, struct rxrpc_send_data_req *req) | |
| 535 | +static size_t rxrpc_prepare_data_packet(struct rxrpc_call *call, | |
| 536 | + struct rxrpc_send_data_req *req, | |
| 537 | + struct rxrpc_wire_header *whdr) | |
| 539 | 538 | { |
| 540 | 539 | struct rxrpc_txqueue *tq = req->tq; |
| 541 | 540 | rxrpc_serial_t serial; |
| @@ -549,6 +548,18 @@ static size_t rxrpc_prepare_data_packet(struct rxrpc_call *call, struct rxrpc_se · 7 unmodified lines | ||
| 549 | 548 | /* Each transmission of a Tx packet needs a new serial number */ |
| 550 | 549 | serial = rxrpc_get_next_serials(call->conn, req->n); |
| 551 | 550 | |
| 551 | + whdr->epoch = htonl(call->conn->proto.epoch); | |
| 552 | + whdr->cid = htonl(call->cid); | |
| 553 | + whdr->callNumber = htonl(call->call_id); | |
| 554 | + whdr->seq = htonl(seq); | |
| 555 | + whdr->serial = htonl(serial); | |
| 556 | + whdr->type = RXRPC_PACKET_TYPE_DATA; | |
| 557 | + whdr->flags = 0; | |
| 558 | + whdr->userStatus = 0; | |
| 559 | + whdr->securityIndex = call->security_ix; | |
| 560 | + whdr->_rsvd = 0; | |
| 561 | + whdr->serviceId = htons(call->conn->service_id); | |
| 562 | + | |
| 552 | 563 | call->tx_last_serial = serial + req->n - 1; |
| 553 | 564 | call->tx_last_sent = req->now; |
| 554 | 565 | xmit_ts = rxrpc_prepare_txqueue(tq, req); |
| @@ -576,7 +587,7 @@ static size_t rxrpc_prepare_data_packet(struct rxrpc_call *call, struct rxrpc_se · 21 unmodified lines | ||
| 576 | 587 | if (i + 1 == req->n) |
| 577 | 588 | /* Only sample the last subpacket in a jumbo. */ |
| 578 | 589 | __set_bit(ix, &tq->rtt_samples); |
| 579 | − len += rxrpc_prepare_data_subpacket(call, req, txb, serial, i); | |
| 590 | + len += rxrpc_prepare_data_subpacket(call, req, txb, whdr, serial, i); | |
| 580 | 591 | serial++; |
| 581 | 592 | seq++; |
| 582 | 593 | i++; |
| @@ -618,6 +629,7 @@ static size_t rxrpc_prepare_data_packet(struct rxrpc_call *call, struct rxrpc_se · 35 unmodified lines | ||
| 618 | 629 | } |
| 619 | 630 | |
| 620 | 631 | rxrpc_set_keepalive(call, req->now); |
| 632 | + page_frag_free(whdr); | |
| 621 | 633 | return len; |
| 622 | 634 | } |
| 623 | 635 | |
| @@ -626,25 +638,33 @@ static size_t rxrpc_prepare_data_packet(struct rxrpc_call *call, struct rxrpc_se · 2 unmodified lines | ||
| 626 | 638 | */ |
| 627 | 639 | void rxrpc_send_data_packet(struct rxrpc_call *call, struct rxrpc_send_data_req *req) |
| 628 | 640 | { |
| 641 | + struct rxrpc_wire_header *whdr; | |
| 629 | 642 | struct rxrpc_connection *conn = call->conn; |
| 630 | 643 | enum rxrpc_tx_point frag; |
| 631 | 644 | struct rxrpc_txqueue *tq = req->tq; |
| 632 | 645 | struct rxrpc_txbuf *txb; |
| 633 | 646 | struct msghdr msg; |
| 634 | 647 | rxrpc_seq_t seq = req->seq; |
| 635 | − size_t len; | |
| 648 | + size_t len = sizeof(*whdr); | |
| 636 | 649 | bool new_call = test_bit(RXRPC_CALL_BEGAN_RX_TIMER, &call->flags); |
| 637 | 650 | int ret, stat_ix; |
| 638 | 651 | |
| 639 | 652 | _enter("%x,%x-%x", tq->qbase, seq, seq + req->n - 1); |
| 640 | 653 | |
| 654 | + whdr = page_frag_alloc(&call->local->tx_alloc, sizeof(*whdr), GFP_NOFS); | |
| 655 | + if (!whdr) | |
| 656 | + return; /* Drop the packet if no memory. */ | |
| 657 | + | |
| 658 | + call->local->kvec[0].iov_base = whdr; | |
| 659 | + call->local->kvec[0].iov_len = sizeof(*whdr); | |
| 660 | + | |
| 641 | 661 | stat_ix = umin(req->n, ARRAY_SIZE(call->rxnet->stat_tx_jumbo)) - 1; |
| 642 | 662 | atomic_inc(&call->rxnet->stat_tx_jumbo[stat_ix]); |
| 643 | 663 | |
| 644 | − len = rxrpc_prepare_data_packet(call, req); | |
| 664 | + len += rxrpc_prepare_data_packet(call, req, whdr); | |
| 645 | 665 | txb = tq->bufs[seq & RXRPC_TXQ_MASK]; |
| 646 | 666 | |
| 647 | − iov_iter_kvec(&msg.msg_iter, WRITE, call->local->kvec, req->n, len); | |
| 667 | + iov_iter_kvec(&msg.msg_iter, WRITE, call->local->kvec, 1 + req->n, len); | |
| 648 | 668 | |
| 649 | 669 | msg.msg_name = &call->peer->srx.transport; |
| 650 | 670 | msg.msg_namelen = call->peer->srx.transport_len; |
| @@ -695,13 +715,13 @@ void rxrpc_send_data_packet(struct rxrpc_call *call, struct rxrpc_send_data_req · 44 unmodified lines | ||
| 695 | 715 | |
| 696 | 716 | if (ret == -EMSGSIZE) { |
| 697 | 717 | rxrpc_inc_stat(call->rxnet, stat_tx_data_send_msgsize); |
| 698 | − trace_rxrpc_tx_packet(call->debug_id, call->local->kvec[0].iov_base, frag); | |
| 718 | + trace_rxrpc_tx_packet(call->debug_id, whdr, frag); | |
| 699 | 719 | ret = 0; |
| 700 | 720 | } else if (ret < 0) { |
| 701 | 721 | rxrpc_inc_stat(call->rxnet, stat_tx_data_send_fail); |
| 702 | 722 | trace_rxrpc_tx_fail(call->debug_id, txb->serial, ret, frag); |
| 703 | 723 | } else { |
| 704 | − trace_rxrpc_tx_packet(call->debug_id, call->local->kvec[0].iov_base, frag); | |
| 724 | + trace_rxrpc_tx_packet(call->debug_id, whdr, frag); | |
| 705 | 725 | } |
| 706 | 726 | |
| 707 | 727 | rxrpc_tx_backoff(call, ret); |
| @@ -169,6 +169,13 @@ void rxrpc_input_error(struct rxrpc_local *local, struct sk_buff *skb) · 168 unmodified lines | ||
| 169 | 169 | goto out; |
| 170 | 170 | } |
| 171 | 171 | |
| 172 | + if ((serr->ee.ee_origin == SO_EE_ORIGIN_ICMP6 && | |
| 173 | + serr->ee.ee_type == ICMPV6_PKT_TOOBIG && | |
| 174 | + serr->ee.ee_code == 0)) { | |
| 175 | + rxrpc_adjust_mtu(peer, serr->ee.ee_info); | |
| 176 | + goto out; | |
| 177 | + } | |
| 178 | + | |
| 172 | 179 | rxrpc_store_error(peer, skb); |
| 173 | 180 | out: |
| 174 | 181 | rxrpc_put_peer(peer, rxrpc_peer_put_input_error); |
| @@ -257,8 +257,7 @@ static int rxkad_secure_packet_auth(const struct rxrpc_call *call, · 256 unmodified lines | ||
| 257 | 257 | struct rxrpc_txbuf *txb, |
| 258 | 258 | struct skcipher_request *req) |
| 259 | 259 | { |
| 260 | − struct rxrpc_wire_header *whdr = txb->kvec[0].iov_base; | |
| 261 | − struct rxkad_level1_hdr *hdr = (void *)(whdr + 1); | |
| 260 | + struct rxkad_level1_hdr *hdr = txb->data; | |
| 262 | 261 | struct rxrpc_crypt iv; |
| 263 | 262 | struct scatterlist sg; |
| 264 | 263 | size_t pad; |
| @@ -274,7 +273,7 @@ static int rxkad_secure_packet_auth(const struct rxrpc_call *call, · 9 unmodified lines | ||
| 274 | 273 | pad = RXKAD_ALIGN - pad; |
| 275 | 274 | pad &= RXKAD_ALIGN - 1; |
| 276 | 275 | if (pad) { |
| 277 | − memset(txb->kvec[0].iov_base + txb->offset, 0, pad); | |
| 276 | + memset(txb->data + txb->offset, 0, pad); | |
| 278 | 277 | txb->pkt_len += pad; |
| 279 | 278 | } |
| 280 | 279 | |
| @@ -300,8 +299,7 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call, · 19 unmodified lines | ||
| 300 | 299 | struct skcipher_request *req) |
| 301 | 300 | { |
| 302 | 301 | const struct rxrpc_key_token *token; |
| 303 | − struct rxrpc_wire_header *whdr = txb->kvec[0].iov_base; | |
| 304 | − struct rxkad_level2_hdr *rxkhdr = (void *)(whdr + 1); | |
| 302 | + struct rxkad_level2_hdr *rxkhdr = txb->data; | |
| 305 | 303 | struct rxrpc_crypt iv; |
| 306 | 304 | struct scatterlist sg; |
| 307 | 305 | size_t content, pad; |
| @@ -319,7 +317,7 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call, · 11 unmodified lines | ||
| 319 | 317 | txb->pkt_len = round_up(content, RXKAD_ALIGN); |
| 320 | 318 | pad = txb->pkt_len - content; |
| 321 | 319 | if (pad) |
| 322 | − memset(txb->kvec[0].iov_base + txb->offset, 0, pad); | |
| 320 | + memset(txb->data + txb->offset, 0, pad); | |
| 323 | 321 | |
| 324 | 322 | /* encrypt from the session key */ |
| 325 | 323 | token = call->conn->key->payload.data[0]; |
| @@ -407,9 +405,8 @@ static int rxkad_secure_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb) · 81 unmodified lines | ||
| 407 | 405 | |
| 408 | 406 | /* Clear excess space in the packet */ |
| 409 | 407 | if (txb->pkt_len < txb->alloc_size) { |
| 410 | − struct rxrpc_wire_header *whdr = txb->kvec[0].iov_base; | |
| 411 | 408 | size_t gap = txb->alloc_size - txb->pkt_len; |
| 412 | − void *p = whdr + 1; | |
| 409 | + void *p = txb->data; | |
| 413 | 410 | |
| 414 | 411 | memset(p + txb->pkt_len, 0, gap); |
| 415 | 412 | } |
| @@ -419,7 +419,7 @@ reload: · 418 unmodified lines | ||
| 419 | 419 | size_t copy = umin(txb->space, msg_data_left(msg)); |
| 420 | 420 | |
| 421 | 421 | _debug("add %zu", copy); |
| 422 | − if (!copy_from_iter_full(txb->kvec[0].iov_base + txb->offset, | |
| 422 | + if (!copy_from_iter_full(txb->data + txb->offset, | |
| 423 | 423 | copy, &msg->msg_iter)) |
| 424 | 424 | goto efault; |
| 425 | 425 | _debug("added"); |
| @@ -445,8 +445,6 @@ reload: · 19 unmodified lines | ||
| 445 | 445 | ret = call->security->secure_packet(call, txb); |
| 446 | 446 | if (ret < 0) |
| 447 | 447 | goto out; |
| 448 | − | |
| 449 | − txb->kvec[0].iov_len += txb->len; | |
| 450 | 448 | rxrpc_queue_packet(rx, call, txb, notify_end_tx); |
| 451 | 449 | txb = NULL; |
| 452 | 450 | } |
| @@ -19,17 +19,19 @@ atomic_t rxrpc_nr_txbuf; · 18 unmodified lines | ||
| 19 | 19 | struct rxrpc_txbuf *rxrpc_alloc_data_txbuf(struct rxrpc_call *call, size_t data_size, |
| 20 | 20 | size_t data_align, gfp_t gfp) |
| 21 | 21 | { |
| 22 | − struct rxrpc_wire_header *whdr; | |
| 23 | 22 | struct rxrpc_txbuf *txb; |
| 24 | − size_t total, hoff; | |
| 23 | + size_t total, doff, jsize = sizeof(struct rxrpc_jumbo_header); | |
| 25 | 24 | void *buf; |
| 26 | 25 | |
| 27 | 26 | txb = kzalloc(sizeof(*txb), gfp); |
| 28 | 27 | if (!txb) |
| 29 | 28 | return NULL; |
| 30 | 29 | |
| 31 | − hoff = round_up(sizeof(*whdr), data_align) - sizeof(*whdr); | |
| 32 | − total = hoff + sizeof(*whdr) + data_size; | |
| 30 | + /* We put a jumbo header in the buffer, but not a full wire header to | |
| 31 | + * avoid delayed-corruption problems with zerocopy. | |
| 32 | + */ | |
| 33 | + doff = round_up(jsize, data_align); | |
| 34 | + total = doff + data_size; | |
| 33 | 35 | |
| 34 | 36 | data_align = umax(data_align, L1_CACHE_BYTES); |
| 35 | 37 | mutex_lock(&call->conn->tx_data_alloc_lock); |
| @@ -41,30 +43,15 @@ struct rxrpc_txbuf *rxrpc_alloc_data_txbuf(struct rxrpc_call *call, size_t data_ · 5 unmodified lines | ||
| 41 | 43 | return NULL; |
| 42 | 44 | } |
| 43 | 45 | |
| 44 | − whdr = buf + hoff; | |
| 45 | − | |
| 46 | 46 | refcount_set(&txb->ref, 1); |
| 47 | 47 | txb->call_debug_id = call->debug_id; |
| 48 | 48 | txb->debug_id = atomic_inc_return(&rxrpc_txbuf_debug_ids); |
| 49 | 49 | txb->alloc_size = data_size; |
| 50 | 50 | txb->space = data_size; |
| 51 | − txb->offset = sizeof(*whdr); | |
| 51 | + txb->offset = 0; | |
| 52 | 52 | txb->flags = call->conn->out_clientflag; |
| 53 | 53 | txb->seq = call->send_top + 1; |
| 54 | − txb->nr_kvec = 1; | |
| 55 | − txb->kvec[0].iov_base = whdr; | |
| 56 | − txb->kvec[0].iov_len = sizeof(*whdr); | |
| 57 | − | |
| 58 | − whdr->epoch = htonl(call->conn->proto.epoch); | |
| 59 | − whdr->cid = htonl(call->cid); | |
| 60 | − whdr->callNumber = htonl(call->call_id); | |
| 61 | − whdr->seq = htonl(txb->seq); | |
| 62 | − whdr->type = RXRPC_PACKET_TYPE_DATA; | |
| 63 | − whdr->flags = 0; | |
| 64 | − whdr->userStatus = 0; | |
| 65 | − whdr->securityIndex = call->security_ix; | |
| 66 | − whdr->_rsvd = 0; | |
| 67 | − whdr->serviceId = htons(call->dest_srx.srx_service); | |
| 54 | + txb->data = buf + doff; | |
| 68 | 55 | |
| 69 | 56 | trace_rxrpc_txbuf(txb->debug_id, txb->call_debug_id, txb->seq, 1, |
| 70 | 57 | rxrpc_txbuf_alloc_data); |
| @@ -90,14 +77,10 @@ void rxrpc_see_txbuf(struct rxrpc_txbuf *txb, enum rxrpc_txbuf_trace what) · 19 unmodified lines | ||
| 90 | 77 | |
| 91 | 78 | static void rxrpc_free_txbuf(struct rxrpc_txbuf *txb) |
| 92 | 79 | { |
| 93 | − int i; | |
| 94 | − | |
| 95 | 80 | trace_rxrpc_txbuf(txb->debug_id, txb->call_debug_id, txb->seq, 0, |
| 96 | 81 | rxrpc_txbuf_free); |
| 97 | − for (i = 0; i < txb->nr_kvec; i++) | |
| 98 | − if (txb->kvec[i].iov_base && | |
| 99 | − !is_zero_pfn(page_to_pfn(virt_to_page(txb->kvec[i].iov_base)))) | |
| 100 | − page_frag_free(txb->kvec[i].iov_base); | |
| 82 | + if (txb->data) | |
| 83 | + page_frag_free(txb->data); | |
| 101 | 84 | kfree(txb); |
| 102 | 85 | atomic_dec(&rxrpc_nr_txbuf); |
| 103 | 86 | } |
| @@ -824,13 +824,19 @@ static void __vsock_release(struct sock *sk, int level) · 823 unmodified lines | ||
| 824 | 824 | */ |
| 825 | 825 | lock_sock_nested(sk, level); |
| 826 | 826 | |
| 827 | − sock_orphan(sk); | |
| 827 | + /* Indicate to vsock_remove_sock() that the socket is being released and | |
| 828 | + * can be removed from the bound_table. Unlike transport reassignment | |
| 829 | + * case, where the socket must remain bound despite vsock_remove_sock() | |
| 830 | + * being called from the transport release() callback. | |
| 831 | + */ | |
| 832 | + sock_set_flag(sk, SOCK_DEAD); | |
| 828 | 833 | |
| 829 | 834 | if (vsk->transport) |
| 830 | 835 | vsk->transport->release(vsk); |
| 831 | 836 | else if (sock_type_connectible(sk->sk_type)) |
| 832 | 837 | vsock_remove_sock(vsk); |
| 833 | 838 | |
| 839 | + sock_orphan(sk); | |
| 834 | 840 | sk->sk_shutdown = SHUTDOWN_MASK; |
| 835 | 841 | |
| 836 | 842 | skb_queue_purge(&sk->sk_receive_queue); |
| @@ -1788,6 +1788,42 @@ static void test_stream_connect_retry_server(const struct test_opts *opts) · 1787 unmodified lines | ||
| 1788 | 1788 | close(fd); |
| 1789 | 1789 | } |
| 1790 | 1790 | |
| 1791 | +static void test_stream_linger_client(const struct test_opts *opts) | |
| 1792 | +{ | |
| 1793 | + struct linger optval = { | |
| 1794 | + .l_onoff = 1, | |
| 1795 | + .l_linger = 1 | |
| 1796 | + }; | |
| 1797 | + int fd; | |
| 1798 | + | |
| 1799 | + fd = vsock_stream_connect(opts->peer_cid, opts->peer_port); | |
| 1800 | + if (fd < 0) { | |
| 1801 | + perror("connect"); | |
| 1802 | + exit(EXIT_FAILURE); | |
| 1803 | + } | |
| 1804 | + | |
| 1805 | + if (setsockopt(fd, SOL_SOCKET, SO_LINGER, &optval, sizeof(optval))) { | |
| 1806 | + perror("setsockopt(SO_LINGER)"); | |
| 1807 | + exit(EXIT_FAILURE); | |
| 1808 | + } | |
| 1809 | + | |
| 1810 | + close(fd); | |
| 1811 | +} | |
| 1812 | + | |
| 1813 | +static void test_stream_linger_server(const struct test_opts *opts) | |
| 1814 | +{ | |
| 1815 | + int fd; | |
| 1816 | + | |
| 1817 | + fd = vsock_stream_accept(VMADDR_CID_ANY, opts->peer_port, NULL); | |
| 1818 | + if (fd < 0) { | |
| 1819 | + perror("accept"); | |
| 1820 | + exit(EXIT_FAILURE); | |
| 1821 | + } | |
| 1822 | + | |
| 1823 | + vsock_wait_remote_close(fd); | |
| 1824 | + close(fd); | |
| 1825 | +} | |
| 1826 | + | |
| 1791 | 1827 | static struct test_case test_cases[] = { |
| 1792 | 1828 | { |
| 1793 | 1829 | .name = "SOCK_STREAM connection reset", |
| @@ -1943,6 +1979,11 @@ static struct test_case test_cases[] = { · 149 unmodified lines | ||
| 1943 | 1979 | .run_client = test_stream_connect_retry_client, |
| 1944 | 1980 | .run_server = test_stream_connect_retry_server, |
| 1945 | 1981 | }, |
| 1982 | + { | |
| 1983 | + .name = "SOCK_STREAM SO_LINGER null-ptr-deref", | |
| 1984 | + .run_client = test_stream_linger_client, | |
| 1985 | + .run_server = test_stream_linger_server, | |
| 1986 | + }, | |
| 1946 | 1987 | {}, |
| 1947 | 1988 | }; |
| 1948 | 1989 | |