mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-05-09 21:42:09 +02:00
Merge tag 'net-7.1-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Pull networking fixes from Jakub Kicinski:
"Including fixes from Netfilter, IPsec, Bluetooth and WiFi.
Current release - fix to a fix:
- ipmr: add __rcu to netns_ipv4.mrt, make sure we hold the RCU lock
in all relevant places
Current release - new code bugs:
- fixes for the recently added resizable hash tables
- ipv6: make sure we default IPv6 tunnel drivers to =m now that IPv6
itself is built in
- drv: octeontx2-af: fixes for parser/CAM fixes
Previous releases - regressions:
- phy: micrel: fix LAN8814 QSGMII soft reset
- wifi:
- cw1200: revert "Fix locking in error paths"
- ath12k: fix crash on WCN7850, due to adding the same queue
buffer to a list multiple times
Previous releases - always broken:
- number of info leak fixes
- ipv6: implement limits on extension header parsing
- wifi: number of fixes for missing bound checks in the drivers
- Bluetooth: fixes for races and locking issues
- af_unix:
- fix an issue between garbage collection and PEEK
- fix yet another issue with OOB data
- xfrm: esp: avoid in-place decrypt on shared skb frags
- netfilter: replace skb_try_make_writable() by skb_ensure_writable()
- openvswitch: vport: fix race between tunnel creation and linking
leading to invalid memory accesses (type confusion)
- drv: amd-xgbe: fix PTP addend overflow causing frozen clock
Misc:
- sched/isolation: make HK_TYPE_KTHREAD an alias of HK_TYPE_DOMAIN
(for relevant IPVS change)"
* tag 'net-7.1-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (190 commits)
net: sparx5: configure serdes for 1000BASE-X in sparx5_port_init()
net: sparx5: fix wrong chip ids for TSN SKUs
net: stmmac: dwmac-nuvoton: fix NULL pointer dereference in nvt_set_phy_intf_sel()
tcp: Fix dst leak in tcp_v6_connect().
ipmr: Call ipmr_fib_lookup() under RCU.
net: phy: broadcom: Save PHY counters during suspend
net/smc: fix missing sk_err when TCP handshake fails
af_unix: Reject SIOCATMARK on non-stream sockets
veth: fix OOB txq access in veth_poll() with asymmetric queue counts
eth: fbnic: fix double-free of PCS on phylink creation failure
net: ethernet: cortina: Drop half-assembled SKB
selftests: mptcp: pm: restrict 'unknown' check to pm_nl_ctl
selftests: mptcp: check output: catch cmd errors
mptcp: pm: prio: skip closed subflows
mptcp: pm: ADD_ADDR rtx: return early if no retrans
mptcp: pm: ADD_ADDR rtx: skip inactive subflows
mptcp: pm: ADD_ADDR rtx: resched blocked ADD_ADDR quicker
mptcp: pm: ADD_ADDR rtx: free sk if last
mptcp: pm: ADD_ADDR rtx: always decrease sk refcount
mptcp: pm: ADD_ADDR rtx: fix potential data-race
...
This commit is contained in:
@@ -7077,6 +7077,12 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git core/debugobjec
|
||||
F: include/linux/debugobjects.h
|
||||
F: lib/debugobjects.c
|
||||
|
||||
DEC LANCE NETWORK DRIVER
|
||||
M: "Maciej W. Rozycki" <macro@orcam.me.uk>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/net/ethernet/amd/declance.c
|
||||
|
||||
DECSTATION PLATFORM SUPPORT
|
||||
M: "Maciej W. Rozycki" <macro@orcam.me.uk>
|
||||
L: linux-mips@vger.kernel.org
|
||||
|
||||
@@ -289,6 +289,9 @@ static inline void btintel_pcie_dump_debug_registers(struct hci_dev *hdev)
|
||||
skb_put_data(skb, buf, strlen(buf));
|
||||
data->boot_stage_cache = reg;
|
||||
|
||||
if (reg & BTINTEL_PCIE_CSR_BOOT_STAGE_DEVICE_WARNING)
|
||||
bt_dev_warn(hdev, "Controller device warning (boot_stage: 0x%8.8x)", reg);
|
||||
|
||||
reg = btintel_pcie_rd_reg32(data, BTINTEL_PCIE_CSR_IPC_STATUS_REG);
|
||||
snprintf(buf, sizeof(buf), "ipc status: 0x%8.8x", reg);
|
||||
skb_put_data(skb, buf, strlen(buf));
|
||||
@@ -880,8 +883,11 @@ static inline bool btintel_pcie_in_lockdown(struct btintel_pcie_data *data)
|
||||
|
||||
static inline bool btintel_pcie_in_error(struct btintel_pcie_data *data)
|
||||
{
|
||||
return (data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_DEVICE_ERR) ||
|
||||
(data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_ABORT_HANDLER);
|
||||
if (data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_DEVICE_WARNING)
|
||||
bt_dev_warn(data->hdev, "Controller device warning (boot_stage: 0x%8.8x)",
|
||||
data->boot_stage_cache);
|
||||
|
||||
return data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_ABORT_HANDLER;
|
||||
}
|
||||
|
||||
static void btintel_pcie_msix_gp1_handler(struct btintel_pcie_data *data)
|
||||
@@ -914,7 +920,8 @@ static void btintel_pcie_msix_gp0_handler(struct btintel_pcie_data *data)
|
||||
data->img_resp_cache = reg;
|
||||
|
||||
if (btintel_pcie_in_error(data)) {
|
||||
bt_dev_err(data->hdev, "Controller in error state");
|
||||
bt_dev_err(data->hdev, "Controller in error state (boot_stage: 0x%8.8x)",
|
||||
data->boot_stage_cache);
|
||||
btintel_pcie_dump_debug_registers(data->hdev);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
#define BTINTEL_PCIE_CSR_BOOT_STAGE_OPFW (BIT(2))
|
||||
#define BTINTEL_PCIE_CSR_BOOT_STAGE_ROM_LOCKDOWN (BIT(10))
|
||||
#define BTINTEL_PCIE_CSR_BOOT_STAGE_IML_LOCKDOWN (BIT(11))
|
||||
#define BTINTEL_PCIE_CSR_BOOT_STAGE_DEVICE_ERR (BIT(12))
|
||||
#define BTINTEL_PCIE_CSR_BOOT_STAGE_DEVICE_WARNING (BIT(12))
|
||||
#define BTINTEL_PCIE_CSR_BOOT_STAGE_ABORT_HANDLER (BIT(13))
|
||||
#define BTINTEL_PCIE_CSR_BOOT_STAGE_DEVICE_HALTED (BIT(14))
|
||||
#define BTINTEL_PCIE_CSR_BOOT_STAGE_MAC_ACCESS_ON (BIT(16))
|
||||
|
||||
@@ -695,8 +695,13 @@ static int btmtk_usb_hci_wmt_sync(struct hci_dev *hdev,
|
||||
if (data->evt_skb == NULL)
|
||||
goto err_free_wc;
|
||||
|
||||
/* Parse and handle the return WMT event */
|
||||
wmt_evt = (struct btmtk_hci_wmt_evt *)data->evt_skb->data;
|
||||
wmt_evt = skb_pull_data(data->evt_skb, sizeof(*wmt_evt));
|
||||
if (!wmt_evt) {
|
||||
bt_dev_err(hdev, "WMT event too short (%u bytes)",
|
||||
data->evt_skb->len);
|
||||
err = -EINVAL;
|
||||
goto err_free_skb;
|
||||
}
|
||||
if (wmt_evt->whdr.op != hdr->op) {
|
||||
bt_dev_err(hdev, "Wrong op received %d expected %d",
|
||||
wmt_evt->whdr.op, hdr->op);
|
||||
@@ -712,6 +717,12 @@ static int btmtk_usb_hci_wmt_sync(struct hci_dev *hdev,
|
||||
status = BTMTK_WMT_PATCH_DONE;
|
||||
break;
|
||||
case BTMTK_WMT_FUNC_CTRL:
|
||||
if (!skb_pull_data(data->evt_skb,
|
||||
sizeof(wmt_evt_funcc->status))) {
|
||||
err = -EINVAL;
|
||||
goto err_free_skb;
|
||||
}
|
||||
|
||||
wmt_evt_funcc = (struct btmtk_hci_wmt_evt_funcc *)wmt_evt;
|
||||
if (be16_to_cpu(wmt_evt_funcc->status) == 0x404)
|
||||
status = BTMTK_WMT_ON_DONE;
|
||||
|
||||
@@ -191,6 +191,9 @@ static int ath_recv(struct hci_uart *hu, const void *data, int count)
|
||||
{
|
||||
struct ath_struct *ath = hu->priv;
|
||||
|
||||
if (!ath)
|
||||
return -ENODEV;
|
||||
|
||||
ath->rx_skb = h4_recv_buf(hu, ath->rx_skb, data, count,
|
||||
ath_recv_pkts, ARRAY_SIZE(ath_recv_pkts));
|
||||
if (IS_ERR(ath->rx_skb)) {
|
||||
|
||||
@@ -585,6 +585,9 @@ static int bcsp_recv(struct hci_uart *hu, const void *data, int count)
|
||||
if (!test_bit(HCI_UART_REGISTERED, &hu->flags))
|
||||
return -EUNATCH;
|
||||
|
||||
if (!bcsp)
|
||||
return -ENODEV;
|
||||
|
||||
BT_DBG("hu %p count %d rx_state %d rx_count %ld",
|
||||
hu, count, bcsp->rx_state, bcsp->rx_count);
|
||||
|
||||
|
||||
@@ -109,6 +109,9 @@ static int h4_recv(struct hci_uart *hu, const void *data, int count)
|
||||
{
|
||||
struct h4_struct *h4 = hu->priv;
|
||||
|
||||
if (!h4)
|
||||
return -ENODEV;
|
||||
|
||||
h4->rx_skb = h4_recv_buf(hu, h4->rx_skb, data, count,
|
||||
h4_recv_pkts, ARRAY_SIZE(h4_recv_pkts));
|
||||
if (IS_ERR(h4->rx_skb)) {
|
||||
|
||||
@@ -587,6 +587,9 @@ static int h5_recv(struct hci_uart *hu, const void *data, int count)
|
||||
struct h5 *h5 = hu->priv;
|
||||
const unsigned char *ptr = data;
|
||||
|
||||
if (!h5)
|
||||
return -ENODEV;
|
||||
|
||||
BT_DBG("%s pending %zu count %d", hu->hdev->name, h5->rx_pending,
|
||||
count);
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
|
||||
#define VERSION "0.1"
|
||||
#define VIRTBT_RX_BUF_SIZE 1000
|
||||
|
||||
enum {
|
||||
VIRTBT_VQ_TX,
|
||||
@@ -33,11 +34,11 @@ static int virtbt_add_inbuf(struct virtio_bluetooth *vbt)
|
||||
struct sk_buff *skb;
|
||||
int err;
|
||||
|
||||
skb = alloc_skb(1000, GFP_KERNEL);
|
||||
skb = alloc_skb(VIRTBT_RX_BUF_SIZE, GFP_KERNEL);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
sg_init_one(sg, skb->data, 1000);
|
||||
sg_init_one(sg, skb->data, VIRTBT_RX_BUF_SIZE);
|
||||
|
||||
err = virtqueue_add_inbuf(vq, sg, 1, skb, GFP_KERNEL);
|
||||
if (err < 0) {
|
||||
@@ -197,6 +198,7 @@ static int virtbt_shutdown_generic(struct hci_dev *hdev)
|
||||
|
||||
static void virtbt_rx_handle(struct virtio_bluetooth *vbt, struct sk_buff *skb)
|
||||
{
|
||||
size_t min_hdr;
|
||||
__u8 pkt_type;
|
||||
|
||||
pkt_type = *((__u8 *) skb->data);
|
||||
@@ -204,16 +206,32 @@ static void virtbt_rx_handle(struct virtio_bluetooth *vbt, struct sk_buff *skb)
|
||||
|
||||
switch (pkt_type) {
|
||||
case HCI_EVENT_PKT:
|
||||
min_hdr = sizeof(struct hci_event_hdr);
|
||||
break;
|
||||
case HCI_ACLDATA_PKT:
|
||||
min_hdr = sizeof(struct hci_acl_hdr);
|
||||
break;
|
||||
case HCI_SCODATA_PKT:
|
||||
min_hdr = sizeof(struct hci_sco_hdr);
|
||||
break;
|
||||
case HCI_ISODATA_PKT:
|
||||
hci_skb_pkt_type(skb) = pkt_type;
|
||||
hci_recv_frame(vbt->hdev, skb);
|
||||
min_hdr = sizeof(struct hci_iso_hdr);
|
||||
break;
|
||||
default:
|
||||
kfree_skb(skb);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
if (skb->len < min_hdr) {
|
||||
bt_dev_err_ratelimited(vbt->hdev,
|
||||
"rx pkt_type 0x%02x payload %u < hdr %zu\n",
|
||||
pkt_type, skb->len, min_hdr);
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
hci_skb_pkt_type(skb) = pkt_type;
|
||||
hci_recv_frame(vbt->hdev, skb);
|
||||
}
|
||||
|
||||
static void virtbt_rx_work(struct work_struct *work)
|
||||
@@ -227,8 +245,15 @@ static void virtbt_rx_work(struct work_struct *work)
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
skb_put(skb, len);
|
||||
virtbt_rx_handle(vbt, skb);
|
||||
if (!len || len > VIRTBT_RX_BUF_SIZE) {
|
||||
bt_dev_err_ratelimited(vbt->hdev,
|
||||
"rx reply len %u outside [1, %u]\n",
|
||||
len, VIRTBT_RX_BUF_SIZE);
|
||||
kfree_skb(skb);
|
||||
} else {
|
||||
skb_put(skb, len);
|
||||
virtbt_rx_handle(vbt, skb);
|
||||
}
|
||||
|
||||
if (virtbt_add_inbuf(vbt) < 0)
|
||||
return;
|
||||
|
||||
@@ -25,6 +25,9 @@
|
||||
|
||||
#include "mt7530.h"
|
||||
|
||||
#define MT7530_STATS_POLL_INTERVAL (1 * HZ)
|
||||
#define MT7530_STATS_RATE_LIMIT (HZ / 10)
|
||||
|
||||
static struct mt753x_pcs *pcs_to_mt753x_pcs(struct phylink_pcs *pcs)
|
||||
{
|
||||
return container_of(pcs, struct mt753x_pcs, pcs);
|
||||
@@ -906,10 +909,9 @@ static void mt7530_get_rmon_stats(struct dsa_switch *ds, int port,
|
||||
*ranges = mt7530_rmon_ranges;
|
||||
}
|
||||
|
||||
static void mt7530_get_stats64(struct dsa_switch *ds, int port,
|
||||
struct rtnl_link_stats64 *storage)
|
||||
static void mt7530_read_port_stats64(struct mt7530_priv *priv, int port,
|
||||
struct rtnl_link_stats64 *storage)
|
||||
{
|
||||
struct mt7530_priv *priv = ds->priv;
|
||||
uint64_t data;
|
||||
|
||||
/* MIB counter doesn't provide a FramesTransmittedOK but instead
|
||||
@@ -951,6 +953,54 @@ static void mt7530_get_stats64(struct dsa_switch *ds, int port,
|
||||
&storage->rx_crc_errors);
|
||||
}
|
||||
|
||||
static void mt7530_stats_refresh(struct mt7530_priv *priv)
|
||||
{
|
||||
struct rtnl_link_stats64 stats = {};
|
||||
struct dsa_port *dp;
|
||||
int port;
|
||||
|
||||
dsa_switch_for_each_user_port(dp, priv->ds) {
|
||||
port = dp->index;
|
||||
|
||||
mt7530_read_port_stats64(priv, port, &stats);
|
||||
|
||||
spin_lock_bh(&priv->stats_lock);
|
||||
priv->ports[port].stats = stats;
|
||||
priv->stats_last = jiffies;
|
||||
spin_unlock_bh(&priv->stats_lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void mt7530_stats_poll(struct work_struct *work)
|
||||
{
|
||||
struct mt7530_priv *priv = container_of(work, struct mt7530_priv,
|
||||
stats_work.work);
|
||||
|
||||
mt7530_stats_refresh(priv);
|
||||
schedule_delayed_work(&priv->stats_work,
|
||||
MT7530_STATS_POLL_INTERVAL);
|
||||
}
|
||||
|
||||
static void mt7530_get_stats64(struct dsa_switch *ds, int port,
|
||||
struct rtnl_link_stats64 *storage)
|
||||
{
|
||||
struct mt7530_priv *priv = ds->priv;
|
||||
bool refresh;
|
||||
|
||||
if (priv->bus) {
|
||||
spin_lock_bh(&priv->stats_lock);
|
||||
*storage = priv->ports[port].stats;
|
||||
refresh = time_after(jiffies, priv->stats_last +
|
||||
MT7530_STATS_RATE_LIMIT);
|
||||
spin_unlock_bh(&priv->stats_lock);
|
||||
if (refresh)
|
||||
mod_delayed_work(system_percpu_wq,
|
||||
&priv->stats_work, 0);
|
||||
} else {
|
||||
mt7530_read_port_stats64(priv, port, storage);
|
||||
}
|
||||
}
|
||||
|
||||
static void mt7530_get_eth_ctrl_stats(struct dsa_switch *ds, int port,
|
||||
struct ethtool_eth_ctrl_stats *ctrl_stats)
|
||||
{
|
||||
@@ -3137,9 +3187,24 @@ mt753x_setup(struct dsa_switch *ds)
|
||||
if (ret && priv->irq_domain)
|
||||
mt7530_free_mdio_irq(priv);
|
||||
|
||||
if (!ret && priv->bus) {
|
||||
mt7530_stats_refresh(priv);
|
||||
schedule_delayed_work(&priv->stats_work,
|
||||
MT7530_STATS_POLL_INTERVAL);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
mt753x_teardown(struct dsa_switch *ds)
|
||||
{
|
||||
struct mt7530_priv *priv = ds->priv;
|
||||
|
||||
if (priv->bus)
|
||||
cancel_delayed_work_sync(&priv->stats_work);
|
||||
}
|
||||
|
||||
static int mt753x_set_mac_eee(struct dsa_switch *ds, int port,
|
||||
struct ethtool_keee *e)
|
||||
{
|
||||
@@ -3257,6 +3322,7 @@ static int mt7988_setup(struct dsa_switch *ds)
|
||||
static const struct dsa_switch_ops mt7530_switch_ops = {
|
||||
.get_tag_protocol = mtk_get_tag_protocol,
|
||||
.setup = mt753x_setup,
|
||||
.teardown = mt753x_teardown,
|
||||
.preferred_default_local_cpu_port = mt753x_preferred_default_local_cpu_port,
|
||||
.get_strings = mt7530_get_strings,
|
||||
.get_ethtool_stats = mt7530_get_ethtool_stats,
|
||||
@@ -3395,6 +3461,9 @@ mt7530_probe_common(struct mt7530_priv *priv)
|
||||
priv->ds->ops = &mt7530_switch_ops;
|
||||
priv->ds->phylink_mac_ops = &mt753x_phylink_mac_ops;
|
||||
mutex_init(&priv->reg_mutex);
|
||||
spin_lock_init(&priv->stats_lock);
|
||||
INIT_DELAYED_WORK(&priv->stats_work, mt7530_stats_poll);
|
||||
|
||||
dev_set_drvdata(dev, priv);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -796,6 +796,7 @@ struct mt7530_fdb {
|
||||
* @pvid: The VLAN specified is to be considered a PVID at ingress. Any
|
||||
* untagged frames will be assigned to the related VLAN.
|
||||
* @sgmii_pcs: Pointer to PCS instance for SerDes ports
|
||||
* @stats: Cached port statistics for MDIO-connected switches
|
||||
*/
|
||||
struct mt7530_port {
|
||||
bool enable;
|
||||
@@ -803,6 +804,7 @@ struct mt7530_port {
|
||||
u32 pm;
|
||||
u16 pvid;
|
||||
struct phylink_pcs *sgmii_pcs;
|
||||
struct rtnl_link_stats64 stats;
|
||||
};
|
||||
|
||||
/* Port 5 mode definitions of the MT7530 switch */
|
||||
@@ -875,6 +877,9 @@ struct mt753x_info {
|
||||
* @create_sgmii: Pointer to function creating SGMII PCS instance(s)
|
||||
* @active_cpu_ports: Holding the active CPU ports
|
||||
* @mdiodev: The pointer to the MDIO device structure
|
||||
* @stats_lock: Protects cached per-port stats from concurrent access
|
||||
* @stats_work: Delayed work for polling MIB counters on MDIO switches
|
||||
* @stats_last: Jiffies timestamp of last MIB counter poll
|
||||
*/
|
||||
struct mt7530_priv {
|
||||
struct device *dev;
|
||||
@@ -900,6 +905,9 @@ struct mt7530_priv {
|
||||
int (*create_sgmii)(struct mt7530_priv *priv);
|
||||
u8 active_cpu_ports;
|
||||
struct mdio_device *mdiodev;
|
||||
spinlock_t stats_lock; /* protects cached stats counters */
|
||||
struct delayed_work stats_work;
|
||||
unsigned long stats_last;
|
||||
};
|
||||
|
||||
struct mt7530_hw_vlan_entry {
|
||||
|
||||
@@ -2120,14 +2120,12 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
error_unmap:
|
||||
while (!list_empty(&tx_list)) {
|
||||
e = list_first_entry(&tx_list, struct airoha_queue_entry,
|
||||
list);
|
||||
list_for_each_entry(e, &tx_list, list) {
|
||||
dma_unmap_single(dev->dev.parent, e->dma_addr, e->dma_len,
|
||||
DMA_TO_DEVICE);
|
||||
e->dma_addr = 0;
|
||||
list_move_tail(&e->list, &q->tx_list);
|
||||
}
|
||||
list_splice(&tx_list, &q->tx_list);
|
||||
|
||||
spin_unlock_bh(&q->lock);
|
||||
error:
|
||||
|
||||
@@ -135,11 +135,11 @@
|
||||
*/
|
||||
#define XGBE_TSTAMP_SSINC 20
|
||||
#define XGBE_TSTAMP_SNSINC 0
|
||||
#define XGBE_PTP_ACT_CLK_FREQ 500000000
|
||||
#define XGBE_PTP_ACT_CLK_FREQ (NSEC_PER_SEC / XGBE_TSTAMP_SSINC)
|
||||
|
||||
#define XGBE_V2_TSTAMP_SSINC 0xA
|
||||
#define XGBE_V2_TSTAMP_SNSINC 0
|
||||
#define XGBE_V2_PTP_ACT_CLK_FREQ 1000000000
|
||||
#define XGBE_V2_PTP_ACT_CLK_FREQ (NSEC_PER_SEC / XGBE_V2_TSTAMP_SSINC)
|
||||
|
||||
/* Define maximum supported values */
|
||||
#define XGBE_MAX_PPS_OUT 4
|
||||
|
||||
@@ -3825,7 +3825,10 @@ static int bnxt_alloc_tpa_info(struct bnxt *bp)
|
||||
if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) {
|
||||
if (!bp->max_tpa_v2)
|
||||
return 0;
|
||||
bp->max_tpa = max_t(u16, bp->max_tpa_v2, MAX_TPA_P5);
|
||||
bp->max_tpa = min_t(u16, bp->max_tpa_v2, MAX_TPA_P5);
|
||||
/* Older P5 FW sets max_tpa_v2 low by mistake except NPAR */
|
||||
if (bp->max_tpa <= 32 && BNXT_CHIP_P5(bp) && !BNXT_NPAR(bp))
|
||||
bp->max_tpa = MAX_TPA_P5;
|
||||
}
|
||||
|
||||
for (i = 0; i < bp->rx_nr_rings; i++) {
|
||||
@@ -17360,9 +17363,14 @@ static pci_ers_result_t bnxt_io_slot_reset(struct pci_dev *pdev)
|
||||
|
||||
netdev_info(bp->dev, "PCI Slot Reset\n");
|
||||
|
||||
if (!(bp->flags & BNXT_FLAG_CHIP_P5_PLUS) &&
|
||||
test_bit(BNXT_STATE_PCI_CHANNEL_IO_FROZEN, &bp->state))
|
||||
msleep(900);
|
||||
if (test_bit(BNXT_STATE_PCI_CHANNEL_IO_FROZEN, &bp->state)) {
|
||||
/* After DPC, the chip should return CRS when the vendor ID
|
||||
* config register is read until it is ready. On all chips,
|
||||
* this is not happening reliably so add a 5-second delay as a
|
||||
* workaround.
|
||||
*/
|
||||
msleep(5000);
|
||||
}
|
||||
|
||||
netdev_lock(netdev);
|
||||
|
||||
|
||||
@@ -419,31 +419,13 @@ void bnxt_ptp_reapply_pps(struct bnxt *bp)
|
||||
}
|
||||
}
|
||||
|
||||
static int bnxt_get_target_cycles(struct bnxt_ptp_cfg *ptp, u64 target_ns,
|
||||
u64 *cycles_delta)
|
||||
{
|
||||
u64 cycles_now;
|
||||
u64 nsec_now, nsec_delta;
|
||||
int rc;
|
||||
|
||||
rc = bnxt_refclk_read(ptp->bp, NULL, &cycles_now);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
nsec_now = bnxt_timecounter_cyc2time(ptp, cycles_now);
|
||||
|
||||
nsec_delta = target_ns - nsec_now;
|
||||
*cycles_delta = div64_u64(nsec_delta << ptp->cc.shift, ptp->cc.mult);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bnxt_ptp_perout_cfg(struct bnxt_ptp_cfg *ptp,
|
||||
struct ptp_clock_request *rq)
|
||||
{
|
||||
struct hwrm_func_ptp_cfg_input *req;
|
||||
struct bnxt *bp = ptp->bp;
|
||||
struct timespec64 ts;
|
||||
u64 target_ns, delta;
|
||||
u64 target_ns;
|
||||
u16 enables;
|
||||
int rc;
|
||||
|
||||
@@ -451,10 +433,6 @@ static int bnxt_ptp_perout_cfg(struct bnxt_ptp_cfg *ptp,
|
||||
ts.tv_nsec = rq->perout.start.nsec;
|
||||
target_ns = timespec64_to_ns(&ts);
|
||||
|
||||
rc = bnxt_get_target_cycles(ptp, target_ns, &delta);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = hwrm_req_init(bp, req, HWRM_FUNC_PTP_CFG);
|
||||
if (rc)
|
||||
return rc;
|
||||
@@ -468,7 +446,10 @@ static int bnxt_ptp_perout_cfg(struct bnxt_ptp_cfg *ptp,
|
||||
req->ptp_freq_adj_dll_phase = 0;
|
||||
req->ptp_freq_adj_ext_period = cpu_to_le32(NSEC_PER_SEC);
|
||||
req->ptp_freq_adj_ext_up = 0;
|
||||
req->ptp_freq_adj_ext_phase_lower = cpu_to_le32(delta);
|
||||
req->ptp_freq_adj_ext_phase_lower =
|
||||
cpu_to_le32(lower_32_bits(target_ns));
|
||||
req->ptp_freq_adj_ext_phase_upper =
|
||||
cpu_to_le32(upper_32_bits(target_ns));
|
||||
|
||||
return hwrm_req_send(bp, req);
|
||||
}
|
||||
|
||||
@@ -175,8 +175,14 @@ int bnxt_register_dev(struct bnxt_en_dev *edev,
|
||||
ulp->handle = handle;
|
||||
rcu_assign_pointer(ulp->ulp_ops, ulp_ops);
|
||||
|
||||
if (test_bit(BNXT_STATE_OPEN, &bp->state))
|
||||
bnxt_hwrm_vnic_cfg(bp, &bp->vnic_info[BNXT_VNIC_DEFAULT]);
|
||||
if (test_bit(BNXT_STATE_OPEN, &bp->state)) {
|
||||
rc = bnxt_hwrm_vnic_cfg(bp, &bp->vnic_info[BNXT_VNIC_DEFAULT]);
|
||||
if (rc) {
|
||||
netdev_err(dev, "Failed to configure dual VNIC mode\n");
|
||||
RCU_INIT_POINTER(ulp->ulp_ops, NULL);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
edev->ulp_tbl->msix_requested = bnxt_get_ulp_msix_num(bp);
|
||||
|
||||
|
||||
@@ -1491,6 +1491,11 @@ static unsigned int gmac_rx(struct net_device *netdev, unsigned int budget)
|
||||
gpage = gmac_get_queue_page(geth, port, mapping + PAGE_SIZE);
|
||||
if (!gpage) {
|
||||
dev_err(geth->dev, "could not find mapping\n");
|
||||
if (skb) {
|
||||
napi_free_frags(&port->napi);
|
||||
port->stats.rx_dropped++;
|
||||
skb = NULL;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
page = gpage->page;
|
||||
|
||||
@@ -330,6 +330,7 @@ struct enetc_si {
|
||||
struct workqueue_struct *workqueue;
|
||||
struct work_struct rx_mode_task;
|
||||
struct dentry *debugfs_root;
|
||||
struct enetc_msg_swbd msg; /* Only valid for VSI */
|
||||
};
|
||||
|
||||
#define ENETC_SI_ALIGN 32
|
||||
|
||||
@@ -17,11 +17,36 @@ static void enetc_msg_vsi_write_msg(struct enetc_hw *hw,
|
||||
enetc_wr(hw, ENETC_VSIMSGSNDAR0, val);
|
||||
}
|
||||
|
||||
static void enetc_msg_dma_free(struct device *dev, struct enetc_msg_swbd *msg)
|
||||
{
|
||||
if (msg->vaddr) {
|
||||
dma_free_coherent(dev, msg->size, msg->vaddr, msg->dma);
|
||||
msg->vaddr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int enetc_msg_vsi_send(struct enetc_si *si, struct enetc_msg_swbd *msg)
|
||||
{
|
||||
struct device *dev = &si->pdev->dev;
|
||||
int timeout = 100;
|
||||
u32 vsimsgsr;
|
||||
|
||||
/* The VSI mailbox may be busy if last message was not yet processed
|
||||
* by PSI. So need to check the mailbox status before sending.
|
||||
*/
|
||||
vsimsgsr = enetc_rd(&si->hw, ENETC_VSIMSGSR);
|
||||
if (vsimsgsr & ENETC_VSIMSGSR_MB) {
|
||||
/* It is safe to free the DMA buffer here, the caller does
|
||||
* not access the DMA buffer if enetc_msg_vsi_send() fails.
|
||||
*/
|
||||
enetc_msg_dma_free(dev, msg);
|
||||
dev_err(dev, "VSI mailbox is busy\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Free the DMA buffer of the last message */
|
||||
enetc_msg_dma_free(dev, &si->msg);
|
||||
si->msg = *msg;
|
||||
enetc_msg_vsi_write_msg(&si->hw, msg);
|
||||
|
||||
do {
|
||||
@@ -32,12 +57,15 @@ static int enetc_msg_vsi_send(struct enetc_si *si, struct enetc_msg_swbd *msg)
|
||||
usleep_range(1000, 2000);
|
||||
} while (--timeout);
|
||||
|
||||
if (!timeout)
|
||||
if (!timeout) {
|
||||
dev_err(dev, "VSI mailbox timeout\n");
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
/* check for message delivery error */
|
||||
if (vsimsgsr & ENETC_VSIMSGSR_MS) {
|
||||
dev_err(&si->pdev->dev, "VSI command execute error: %d\n",
|
||||
dev_err(dev, "VSI command execute error: %d\n",
|
||||
ENETC_SIMSGSR_GET_MC(vsimsgsr));
|
||||
return -EIO;
|
||||
}
|
||||
@@ -50,7 +78,6 @@ static int enetc_msg_vsi_set_primary_mac_addr(struct enetc_ndev_priv *priv,
|
||||
{
|
||||
struct enetc_msg_cmd_set_primary_mac *cmd;
|
||||
struct enetc_msg_swbd msg;
|
||||
int err;
|
||||
|
||||
msg.size = ALIGN(sizeof(struct enetc_msg_cmd_set_primary_mac), 64);
|
||||
msg.vaddr = dma_alloc_coherent(priv->dev, msg.size, &msg.dma,
|
||||
@@ -67,11 +94,7 @@ static int enetc_msg_vsi_set_primary_mac_addr(struct enetc_ndev_priv *priv,
|
||||
memcpy(&cmd->mac, saddr, sizeof(struct sockaddr));
|
||||
|
||||
/* send the command and wait */
|
||||
err = enetc_msg_vsi_send(priv->si, &msg);
|
||||
|
||||
dma_free_coherent(priv->dev, msg.size, msg.vaddr, msg.dma);
|
||||
|
||||
return err;
|
||||
return enetc_msg_vsi_send(priv->si, &msg);
|
||||
}
|
||||
|
||||
static int enetc_vf_set_mac_addr(struct net_device *ndev, void *addr)
|
||||
@@ -259,6 +282,7 @@ static void enetc_vf_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct enetc_si *si = pci_get_drvdata(pdev);
|
||||
struct enetc_ndev_priv *priv;
|
||||
struct enetc_msg_swbd msg;
|
||||
|
||||
priv = netdev_priv(si->ndev);
|
||||
unregister_netdev(si->ndev);
|
||||
@@ -270,7 +294,9 @@ static void enetc_vf_remove(struct pci_dev *pdev)
|
||||
|
||||
free_netdev(si->ndev);
|
||||
|
||||
msg = si->msg;
|
||||
enetc_pci_remove(pdev);
|
||||
enetc_msg_dma_free(&pdev->dev, &msg);
|
||||
}
|
||||
|
||||
static const struct pci_device_id enetc_vf_id_table[] = {
|
||||
|
||||
@@ -249,34 +249,21 @@ DEFINE_SHOW_ATTRIBUTE(npc_defrag);
|
||||
int npc_cn20k_debugfs_init(struct rvu *rvu)
|
||||
{
|
||||
struct npc_priv_t *npc_priv = npc_priv_get();
|
||||
struct dentry *npc_dentry;
|
||||
|
||||
npc_dentry = debugfs_create_file("mcam_layout", 0444, rvu->rvu_dbg.npc,
|
||||
npc_priv, &npc_mcam_layout_fops);
|
||||
debugfs_create_file("mcam_layout", 0444, rvu->rvu_dbg.npc,
|
||||
npc_priv, &npc_mcam_layout_fops);
|
||||
|
||||
if (!npc_dentry)
|
||||
return -EFAULT;
|
||||
debugfs_create_file("mcam_default", 0444, rvu->rvu_dbg.npc,
|
||||
rvu, &npc_mcam_default_fops);
|
||||
|
||||
npc_dentry = debugfs_create_file("mcam_default", 0444, rvu->rvu_dbg.npc,
|
||||
rvu, &npc_mcam_default_fops);
|
||||
debugfs_create_file("vidx2idx", 0444, rvu->rvu_dbg.npc,
|
||||
npc_priv, &npc_vidx2idx_map_fops);
|
||||
|
||||
if (!npc_dentry)
|
||||
return -EFAULT;
|
||||
debugfs_create_file("idx2vidx", 0444, rvu->rvu_dbg.npc,
|
||||
npc_priv, &npc_idx2vidx_map_fops);
|
||||
|
||||
npc_dentry = debugfs_create_file("vidx2idx", 0444, rvu->rvu_dbg.npc,
|
||||
npc_priv, &npc_vidx2idx_map_fops);
|
||||
if (!npc_dentry)
|
||||
return -EFAULT;
|
||||
|
||||
npc_dentry = debugfs_create_file("idx2vidx", 0444, rvu->rvu_dbg.npc,
|
||||
npc_priv, &npc_idx2vidx_map_fops);
|
||||
if (!npc_dentry)
|
||||
return -EFAULT;
|
||||
|
||||
npc_dentry = debugfs_create_file("defrag", 0444, rvu->rvu_dbg.npc,
|
||||
npc_priv, &npc_defrag_fops);
|
||||
if (!npc_dentry)
|
||||
return -EFAULT;
|
||||
debugfs_create_file("defrag", 0444, rvu->rvu_dbg.npc,
|
||||
npc_priv, &npc_defrag_fops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -798,7 +798,7 @@ program_mkex_extr:
|
||||
iounmap(mkex_prfl_addr);
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
npc_cn20k_enable_mcam_entry(struct rvu *rvu, int blkaddr,
|
||||
int index, bool enable)
|
||||
{
|
||||
@@ -808,7 +808,12 @@ npc_cn20k_enable_mcam_entry(struct rvu *rvu, int blkaddr,
|
||||
u64 cfg, hw_prio;
|
||||
u8 kw_type;
|
||||
|
||||
npc_mcam_idx_2_key_type(rvu, index, &kw_type);
|
||||
if (index < 0 || index >= mcam->total_entries)
|
||||
return -EINVAL;
|
||||
|
||||
if (npc_mcam_idx_2_key_type(rvu, index, &kw_type))
|
||||
return -EINVAL;
|
||||
|
||||
if (kw_type == NPC_MCAM_KEY_X2) {
|
||||
cfg = rvu_read64(rvu, blkaddr,
|
||||
NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(mcam_idx,
|
||||
@@ -819,7 +824,7 @@ npc_cn20k_enable_mcam_entry(struct rvu *rvu, int blkaddr,
|
||||
rvu_write64(rvu, blkaddr,
|
||||
NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(mcam_idx, bank),
|
||||
cfg);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* For NPC_CN20K_MCAM_KEY_X4 keys, both the banks
|
||||
@@ -836,10 +841,12 @@ npc_cn20k_enable_mcam_entry(struct rvu *rvu, int blkaddr,
|
||||
NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(mcam_idx, bank),
|
||||
cfg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
npc_cn20k_clear_mcam_entry(struct rvu *rvu, int blkaddr, int bank, int index)
|
||||
static void
|
||||
npc_clear_x2_entry(struct rvu *rvu, int blkaddr, int bank, int index)
|
||||
{
|
||||
rvu_write64(rvu, blkaddr,
|
||||
NPC_AF_CN20K_MCAMEX_BANKX_CAMX_INTF_EXT(index, bank, 1),
|
||||
@@ -873,6 +880,33 @@ npc_cn20k_clear_mcam_entry(struct rvu *rvu, int blkaddr, int bank, int index)
|
||||
NPC_AF_CN20K_MCAMEX_BANKX_STAT_EXT(index, bank), 0);
|
||||
}
|
||||
|
||||
int
|
||||
npc_cn20k_clear_mcam_entry(struct rvu *rvu, int blkaddr, int mcam_idx)
|
||||
{
|
||||
struct npc_mcam *mcam = &rvu->hw->mcam;
|
||||
int bank = npc_get_bank(mcam, mcam_idx);
|
||||
u8 kw_type;
|
||||
int index;
|
||||
|
||||
if (npc_mcam_idx_2_key_type(rvu, mcam_idx, &kw_type))
|
||||
return -EINVAL;
|
||||
|
||||
index = mcam_idx & (mcam->banksize - 1);
|
||||
|
||||
if (kw_type == NPC_MCAM_KEY_X2) {
|
||||
npc_clear_x2_entry(rvu, blkaddr, bank, index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* For NPC_MCAM_KEY_X4 keys, both the banks
|
||||
* need to be programmed with the same value.
|
||||
*/
|
||||
for (bank = 0; bank < mcam->banks_per_entry; bank++)
|
||||
npc_clear_x2_entry(rvu, blkaddr, bank, index);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void npc_cn20k_get_keyword(struct cn20k_mcam_entry *entry, int idx,
|
||||
u64 *cam0, u64 *cam1)
|
||||
{
|
||||
@@ -1014,48 +1048,27 @@ static void npc_cn20k_config_kw_x4(struct rvu *rvu, struct npc_mcam *mcam,
|
||||
kw, req_kw_type);
|
||||
}
|
||||
|
||||
static void
|
||||
npc_cn20k_set_mcam_bank_cfg(struct rvu *rvu, int blkaddr, int mcam_idx,
|
||||
int bank, u8 kw_type, bool enable, u8 hw_prio)
|
||||
{
|
||||
struct npc_mcam *mcam = &rvu->hw->mcam;
|
||||
u64 bank_cfg;
|
||||
|
||||
bank_cfg = (u64)hw_prio << 24;
|
||||
if (enable)
|
||||
bank_cfg |= 0x1;
|
||||
|
||||
if (kw_type == NPC_MCAM_KEY_X2) {
|
||||
rvu_write64(rvu, blkaddr,
|
||||
NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(mcam_idx, bank),
|
||||
bank_cfg);
|
||||
return;
|
||||
}
|
||||
|
||||
/* For NPC_MCAM_KEY_X4 keys, both the banks
|
||||
* need to be programmed with the same value.
|
||||
*/
|
||||
for (bank = 0; bank < mcam->banks_per_entry; bank++) {
|
||||
rvu_write64(rvu, blkaddr,
|
||||
NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(mcam_idx, bank),
|
||||
bank_cfg);
|
||||
}
|
||||
}
|
||||
|
||||
void npc_cn20k_config_mcam_entry(struct rvu *rvu, int blkaddr, int index,
|
||||
u8 intf, struct cn20k_mcam_entry *entry,
|
||||
bool enable, u8 hw_prio, u8 req_kw_type)
|
||||
int npc_cn20k_config_mcam_entry(struct rvu *rvu, int blkaddr, int index,
|
||||
u8 intf, struct cn20k_mcam_entry *entry,
|
||||
bool enable, u8 hw_prio, u8 req_kw_type)
|
||||
{
|
||||
struct npc_mcam *mcam = &rvu->hw->mcam;
|
||||
int mcam_idx = index % mcam->banksize;
|
||||
int bank = index / mcam->banksize;
|
||||
u64 bank_cfg = (u64)hw_prio << 24;
|
||||
int kw = 0;
|
||||
u8 kw_type;
|
||||
|
||||
/* Disable before mcam entry update */
|
||||
npc_cn20k_enable_mcam_entry(rvu, blkaddr, index, false);
|
||||
if (index < 0 || index >= mcam->total_entries)
|
||||
return -EINVAL;
|
||||
|
||||
if (npc_mcam_idx_2_key_type(rvu, index, &kw_type))
|
||||
return -EINVAL;
|
||||
|
||||
/* Disable before mcam entry update */
|
||||
if (npc_cn20k_enable_mcam_entry(rvu, blkaddr, index, false))
|
||||
return -EINVAL;
|
||||
|
||||
npc_mcam_idx_2_key_type(rvu, index, &kw_type);
|
||||
/* CAM1 takes the comparison value and
|
||||
* CAM0 specifies match for a bit in key being '0' or '1' or 'dontcare'.
|
||||
* CAM1<n> = 0 & CAM0<n> = 1 => match if key<n> = 0
|
||||
@@ -1064,7 +1077,7 @@ void npc_cn20k_config_mcam_entry(struct rvu *rvu, int blkaddr, int index,
|
||||
*/
|
||||
if (kw_type == NPC_MCAM_KEY_X2) {
|
||||
/* Clear mcam entry to avoid writes being suppressed by NPC */
|
||||
npc_cn20k_clear_mcam_entry(rvu, blkaddr, bank, mcam_idx);
|
||||
npc_clear_x2_entry(rvu, blkaddr, bank, mcam_idx);
|
||||
npc_cn20k_config_kw_x2(rvu, mcam, blkaddr,
|
||||
mcam_idx, intf, entry,
|
||||
bank, kw_type, kw, req_kw_type);
|
||||
@@ -1085,44 +1098,55 @@ void npc_cn20k_config_mcam_entry(struct rvu *rvu, int blkaddr, int index,
|
||||
NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(mcam_idx,
|
||||
bank, 1),
|
||||
entry->vtag_action);
|
||||
goto set_cfg;
|
||||
|
||||
/* Set HW priority */
|
||||
rvu_write64(rvu, blkaddr,
|
||||
NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(mcam_idx, bank),
|
||||
bank_cfg);
|
||||
|
||||
} else {
|
||||
/* Clear mcam entry to avoid writes being suppressed by NPC */
|
||||
npc_clear_x2_entry(rvu, blkaddr, 0, mcam_idx);
|
||||
npc_clear_x2_entry(rvu, blkaddr, 1, mcam_idx);
|
||||
|
||||
npc_cn20k_config_kw_x4(rvu, mcam, blkaddr,
|
||||
mcam_idx, intf, entry,
|
||||
kw_type, req_kw_type);
|
||||
for (bank = 0; bank < mcam->banks_per_entry; bank++) {
|
||||
/* Set 'action' */
|
||||
rvu_write64(rvu, blkaddr,
|
||||
NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(mcam_idx,
|
||||
bank, 0),
|
||||
entry->action);
|
||||
|
||||
/* Set TAG 'action' */
|
||||
rvu_write64(rvu, blkaddr,
|
||||
NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(mcam_idx,
|
||||
bank, 1),
|
||||
entry->vtag_action);
|
||||
|
||||
/* Set 'action2' for inline receive */
|
||||
rvu_write64(rvu, blkaddr,
|
||||
NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(mcam_idx,
|
||||
bank, 2),
|
||||
entry->action2);
|
||||
|
||||
/* Set HW priority */
|
||||
rvu_write64(rvu, blkaddr,
|
||||
NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(mcam_idx, bank),
|
||||
bank_cfg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear mcam entry to avoid writes being suppressed by NPC */
|
||||
npc_cn20k_clear_mcam_entry(rvu, blkaddr, 0, mcam_idx);
|
||||
npc_cn20k_clear_mcam_entry(rvu, blkaddr, 1, mcam_idx);
|
||||
|
||||
npc_cn20k_config_kw_x4(rvu, mcam, blkaddr,
|
||||
mcam_idx, intf, entry,
|
||||
kw_type, req_kw_type);
|
||||
for (bank = 0; bank < mcam->banks_per_entry; bank++) {
|
||||
/* Set 'action' */
|
||||
rvu_write64(rvu, blkaddr,
|
||||
NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(mcam_idx,
|
||||
bank, 0),
|
||||
entry->action);
|
||||
|
||||
/* Set TAG 'action' */
|
||||
rvu_write64(rvu, blkaddr,
|
||||
NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(mcam_idx,
|
||||
bank, 1),
|
||||
entry->vtag_action);
|
||||
|
||||
/* Set 'action2' for inline receive */
|
||||
rvu_write64(rvu, blkaddr,
|
||||
NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(mcam_idx,
|
||||
bank, 2),
|
||||
entry->action2);
|
||||
}
|
||||
|
||||
set_cfg:
|
||||
/* TODO: */
|
||||
/* PF installing VF rule */
|
||||
npc_cn20k_set_mcam_bank_cfg(rvu, blkaddr, mcam_idx, bank,
|
||||
kw_type, enable, hw_prio);
|
||||
if (npc_cn20k_enable_mcam_entry(rvu, blkaddr, index, enable))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void npc_cn20k_copy_mcam_entry(struct rvu *rvu, int blkaddr, u16 src, u16 dest)
|
||||
int npc_cn20k_copy_mcam_entry(struct rvu *rvu, int blkaddr, u16 src, u16 dest)
|
||||
{
|
||||
struct npc_mcam *mcam = &rvu->hw->mcam;
|
||||
u64 cfg, sreg, dreg, soff, doff;
|
||||
@@ -1130,12 +1154,20 @@ void npc_cn20k_copy_mcam_entry(struct rvu *rvu, int blkaddr, u16 src, u16 dest)
|
||||
int bank, i, sb, db;
|
||||
int dbank, sbank;
|
||||
|
||||
if (src >= mcam->total_entries || dest >= mcam->total_entries)
|
||||
return -EINVAL;
|
||||
|
||||
dbank = npc_get_bank(mcam, dest);
|
||||
sbank = npc_get_bank(mcam, src);
|
||||
npc_mcam_idx_2_key_type(rvu, src, &src_kwtype);
|
||||
npc_mcam_idx_2_key_type(rvu, dest, &dest_kwtype);
|
||||
|
||||
if (npc_mcam_idx_2_key_type(rvu, src, &src_kwtype))
|
||||
return -EINVAL;
|
||||
|
||||
if (npc_mcam_idx_2_key_type(rvu, dest, &dest_kwtype))
|
||||
return -EINVAL;
|
||||
|
||||
if (src_kwtype != dest_kwtype)
|
||||
return;
|
||||
return -EINVAL;
|
||||
|
||||
src &= (mcam->banksize - 1);
|
||||
dest &= (mcam->banksize - 1);
|
||||
@@ -1170,6 +1202,8 @@ void npc_cn20k_copy_mcam_entry(struct rvu *rvu, int blkaddr, u16 src, u16 dest)
|
||||
if (src_kwtype == NPC_MCAM_KEY_X2)
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void npc_cn20k_fill_entryword(struct cn20k_mcam_entry *entry, int idx,
|
||||
@@ -1179,20 +1213,36 @@ static void npc_cn20k_fill_entryword(struct cn20k_mcam_entry *entry, int idx,
|
||||
entry->kw_mask[idx] = cam1 ^ cam0;
|
||||
}
|
||||
|
||||
void npc_cn20k_read_mcam_entry(struct rvu *rvu, int blkaddr, u16 index,
|
||||
struct cn20k_mcam_entry *entry,
|
||||
u8 *intf, u8 *ena, u8 *hw_prio)
|
||||
int npc_cn20k_read_mcam_entry(struct rvu *rvu, int blkaddr, u16 index,
|
||||
struct cn20k_mcam_entry *entry,
|
||||
u8 *intf, u8 *ena, u8 *hw_prio)
|
||||
{
|
||||
struct npc_mcam *mcam = &rvu->hw->mcam;
|
||||
u64 cam0, cam1, bank_cfg, cfg;
|
||||
int kw = 0, bank;
|
||||
u8 kw_type;
|
||||
|
||||
npc_mcam_idx_2_key_type(rvu, index, &kw_type);
|
||||
if (index >= mcam->total_entries)
|
||||
return -EINVAL;
|
||||
|
||||
if (npc_mcam_idx_2_key_type(rvu, index, &kw_type))
|
||||
return -EINVAL;
|
||||
|
||||
bank = npc_get_bank(mcam, index);
|
||||
index &= (mcam->banksize - 1);
|
||||
|
||||
cfg = rvu_read64(rvu, blkaddr,
|
||||
NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(index, bank, 0));
|
||||
entry->action = cfg;
|
||||
|
||||
cfg = rvu_read64(rvu, blkaddr,
|
||||
NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(index, bank, 1));
|
||||
entry->vtag_action = cfg;
|
||||
|
||||
cfg = rvu_read64(rvu, blkaddr,
|
||||
NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(index, bank, 2));
|
||||
entry->action2 = cfg;
|
||||
|
||||
cfg = rvu_read64(rvu, blkaddr,
|
||||
NPC_AF_CN20K_MCAMEX_BANKX_CAMX_INTF_EXT(index,
|
||||
bank, 1)) & 3;
|
||||
@@ -1242,7 +1292,7 @@ void npc_cn20k_read_mcam_entry(struct rvu *rvu, int blkaddr, u16 index,
|
||||
bank,
|
||||
0));
|
||||
npc_cn20k_fill_entryword(entry, kw + 3, cam0, cam1);
|
||||
goto read_action;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (bank = 0; bank < mcam->banks_per_entry; bank++, kw = kw + 4) {
|
||||
@@ -1287,17 +1337,7 @@ void npc_cn20k_read_mcam_entry(struct rvu *rvu, int blkaddr, u16 index,
|
||||
npc_cn20k_fill_entryword(entry, kw + 3, cam0, cam1);
|
||||
}
|
||||
|
||||
read_action:
|
||||
/* 'action' is set to same value for both bank '0' and '1'.
|
||||
* Hence, reading bank '0' should be enough.
|
||||
*/
|
||||
cfg = rvu_read64(rvu, blkaddr,
|
||||
NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(index, 0, 0));
|
||||
entry->action = cfg;
|
||||
|
||||
cfg = rvu_read64(rvu, blkaddr,
|
||||
NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(index, 0, 1));
|
||||
entry->vtag_action = cfg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rvu_mbox_handler_npc_cn20k_mcam_write_entry(struct rvu *rvu,
|
||||
@@ -1335,11 +1375,10 @@ int rvu_mbox_handler_npc_cn20k_mcam_write_entry(struct rvu *rvu,
|
||||
if (is_pffunc_af(req->hdr.pcifunc))
|
||||
nix_intf = req->intf;
|
||||
|
||||
npc_cn20k_config_mcam_entry(rvu, blkaddr, req->entry, nix_intf,
|
||||
&req->entry_data, req->enable_entry,
|
||||
req->hw_prio, req->req_kw_type);
|
||||
rc = npc_cn20k_config_mcam_entry(rvu, blkaddr, req->entry, nix_intf,
|
||||
&req->entry_data, req->enable_entry,
|
||||
req->hw_prio, req->req_kw_type);
|
||||
|
||||
rc = 0;
|
||||
exit:
|
||||
mutex_unlock(&mcam->lock);
|
||||
return rc;
|
||||
@@ -1361,11 +1400,13 @@ int rvu_mbox_handler_npc_cn20k_mcam_read_entry(struct rvu *rvu,
|
||||
|
||||
mutex_lock(&mcam->lock);
|
||||
rc = npc_mcam_verify_entry(mcam, pcifunc, req->entry);
|
||||
if (!rc)
|
||||
npc_cn20k_read_mcam_entry(rvu, blkaddr, req->entry,
|
||||
&rsp->entry_data, &rsp->intf,
|
||||
&rsp->enable, &rsp->hw_prio);
|
||||
if (rc)
|
||||
goto fail;
|
||||
|
||||
rc = npc_cn20k_read_mcam_entry(rvu, blkaddr, req->entry,
|
||||
&rsp->entry_data, &rsp->intf,
|
||||
&rsp->enable, &rsp->hw_prio);
|
||||
fail:
|
||||
mutex_unlock(&mcam->lock);
|
||||
return rc;
|
||||
}
|
||||
@@ -1375,11 +1416,13 @@ int rvu_mbox_handler_npc_cn20k_mcam_alloc_and_write_entry(struct rvu *rvu,
|
||||
struct npc_mcam_alloc_and_write_entry_rsp *rsp)
|
||||
{
|
||||
struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, req->hdr.pcifunc);
|
||||
struct npc_mcam_free_entry_req free_req = { 0 };
|
||||
struct npc_mcam_alloc_entry_req entry_req;
|
||||
struct npc_mcam_alloc_entry_rsp entry_rsp;
|
||||
struct npc_mcam *mcam = &rvu->hw->mcam;
|
||||
u16 entry = NPC_MCAM_ENTRY_INVALID;
|
||||
int blkaddr, rc;
|
||||
struct msg_rsp free_rsp;
|
||||
int blkaddr, rc, err;
|
||||
u8 nix_intf;
|
||||
|
||||
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
|
||||
@@ -1415,12 +1458,23 @@ int rvu_mbox_handler_npc_cn20k_mcam_alloc_and_write_entry(struct rvu *rvu,
|
||||
else
|
||||
nix_intf = pfvf->nix_rx_intf;
|
||||
|
||||
npc_cn20k_config_mcam_entry(rvu, blkaddr, entry, nix_intf,
|
||||
&req->entry_data, req->enable_entry,
|
||||
req->hw_prio, req->req_kw_type);
|
||||
rc = npc_cn20k_config_mcam_entry(rvu, blkaddr, entry, nix_intf,
|
||||
&req->entry_data, req->enable_entry,
|
||||
req->hw_prio, req->req_kw_type);
|
||||
|
||||
mutex_unlock(&mcam->lock);
|
||||
|
||||
if (rc) {
|
||||
free_req.hdr.pcifunc = req->hdr.pcifunc;
|
||||
free_req.entry = entry_rsp.entry;
|
||||
err = rvu_mbox_handler_npc_mcam_free_entry(rvu, &free_req, &free_rsp);
|
||||
if (err)
|
||||
dev_err(rvu->dev,
|
||||
"%s: Error to free mcam idx %u\n",
|
||||
__func__, entry_rsp.entry);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rsp->entry = entry_rsp.entry;
|
||||
return 0;
|
||||
}
|
||||
@@ -1480,9 +1534,9 @@ int rvu_mbox_handler_npc_cn20k_read_base_steer_rule(struct rvu *rvu,
|
||||
|
||||
read_entry:
|
||||
/* Read the mcam entry */
|
||||
npc_cn20k_read_mcam_entry(rvu, blkaddr, index,
|
||||
&rsp->entry, &intf,
|
||||
&enable, &hw_prio);
|
||||
rc = npc_cn20k_read_mcam_entry(rvu, blkaddr, index,
|
||||
&rsp->entry, &intf,
|
||||
&enable, &hw_prio);
|
||||
mutex_unlock(&mcam->lock);
|
||||
out:
|
||||
return rc;
|
||||
@@ -2305,6 +2359,7 @@ err2:
|
||||
__npc_subbank_mark_free(rvu, sb);
|
||||
err1:
|
||||
kfree(save);
|
||||
*alloc_cnt = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -3482,7 +3537,7 @@ static int npc_defrag_alloc_free_slots(struct rvu *rvu,
|
||||
{
|
||||
int alloc_cnt1, alloc_cnt2;
|
||||
struct npc_subbank *sb;
|
||||
int rc, sb_off, i;
|
||||
int rc, sb_off, i, err;
|
||||
bool deleted;
|
||||
|
||||
sb = &npc_priv.sb[f->idx];
|
||||
@@ -3496,6 +3551,7 @@ static int npc_defrag_alloc_free_slots(struct rvu *rvu,
|
||||
NPC_MCAM_LOWER_PRIO,
|
||||
false, cnt, save, cnt, true,
|
||||
&alloc_cnt1);
|
||||
|
||||
if (alloc_cnt1 < cnt) {
|
||||
rc = __npc_subbank_alloc(rvu, sb,
|
||||
NPC_MCAM_KEY_X2, sb->b1b,
|
||||
@@ -3511,15 +3567,17 @@ static int npc_defrag_alloc_free_slots(struct rvu *rvu,
|
||||
dev_err(rvu->dev,
|
||||
"%s: Failed to alloc cnt=%u alloc_cnt1=%u alloc_cnt2=%u\n",
|
||||
__func__, cnt, alloc_cnt1, alloc_cnt2);
|
||||
rc = -ENOSPC;
|
||||
goto fail_free_alloc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail_free_alloc:
|
||||
for (i = 0; i < alloc_cnt1 + alloc_cnt2; i++) {
|
||||
rc = npc_mcam_idx_2_subbank_idx(rvu, save[i],
|
||||
&sb, &sb_off);
|
||||
if (rc) {
|
||||
err = npc_mcam_idx_2_subbank_idx(rvu, save[i],
|
||||
&sb, &sb_off);
|
||||
if (err) {
|
||||
dev_err(rvu->dev,
|
||||
"%s: Error to find subbank for mcam idx=%u\n",
|
||||
__func__, save[i]);
|
||||
@@ -3565,9 +3623,10 @@ int npc_defrag_move_vdx_to_free(struct rvu *rvu,
|
||||
struct npc_defrag_node *v,
|
||||
int cnt, u16 *save)
|
||||
{
|
||||
u16 new_midx, old_midx, vidx, target_pf;
|
||||
struct npc_mcam *mcam = &rvu->hw->mcam;
|
||||
struct rvu_npc_mcam_rule *rule, *tmp;
|
||||
int i, vidx_cnt, rc, sb_off;
|
||||
u16 new_midx, old_midx, vidx;
|
||||
struct npc_subbank *sb;
|
||||
bool deleted;
|
||||
u16 pcifunc;
|
||||
@@ -3607,9 +3666,30 @@ int npc_defrag_move_vdx_to_free(struct rvu *rvu,
|
||||
NPC_AF_CN20K_MCAMEX_BANKX_STAT_EXT(midx,
|
||||
bank));
|
||||
|
||||
npc_cn20k_enable_mcam_entry(rvu, blkaddr, old_midx, false);
|
||||
npc_cn20k_copy_mcam_entry(rvu, blkaddr, old_midx, new_midx);
|
||||
npc_cn20k_enable_mcam_entry(rvu, blkaddr, new_midx, true);
|
||||
/* If bug happened during copy/enable mcam, then there is a bug in allocation
|
||||
* algorithm itself. There is no point in rewinding and returning, as it
|
||||
* will face further issue. Return error after printing error
|
||||
*/
|
||||
if (npc_cn20k_enable_mcam_entry(rvu, blkaddr, old_midx, false)) {
|
||||
dev_err(rvu->dev,
|
||||
"%s: Error happened while disabling old_mid=%u\n",
|
||||
__func__, old_midx);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (npc_cn20k_copy_mcam_entry(rvu, blkaddr, old_midx, new_midx)) {
|
||||
dev_err(rvu->dev,
|
||||
"%s: Error happened while copying old_midx=%u new_midx=%u\n",
|
||||
__func__, old_midx, new_midx);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (npc_cn20k_enable_mcam_entry(rvu, blkaddr, new_midx, true)) {
|
||||
dev_err(rvu->dev,
|
||||
"%s: Error happened while enabling new_mid=%u\n",
|
||||
__func__, new_midx);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
midx = new_midx % mcam->banksize;
|
||||
bank = new_midx / mcam->banksize;
|
||||
@@ -3665,8 +3745,21 @@ int npc_defrag_move_vdx_to_free(struct rvu *rvu,
|
||||
mcam->entry2pfvf_map[new_midx] = pcifunc;
|
||||
/* Counter is not preserved */
|
||||
mcam->entry2cntr_map[new_midx] = new_midx;
|
||||
target_pf = mcam->entry2target_pffunc[old_midx];
|
||||
mcam->entry2target_pffunc[new_midx] = target_pf;
|
||||
mcam->entry2target_pffunc[old_midx] = NPC_MCAM_INVALID_MAP;
|
||||
|
||||
npc_mcam_set_bit(mcam, new_midx);
|
||||
|
||||
/* Note: list order is not functionally required for mcam_rules */
|
||||
list_for_each_entry_safe(rule, tmp, &mcam->mcam_rules, list) {
|
||||
if (rule->entry != old_midx)
|
||||
continue;
|
||||
|
||||
rule->entry = new_midx;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Mark as invalid */
|
||||
v->vidx[vidx_cnt - i - 1] = -1;
|
||||
save[cnt - i - 1] = -1;
|
||||
@@ -3935,6 +4028,13 @@ int npc_cn20k_dft_rules_idx_get(struct rvu *rvu, u16 pcifunc, u16 *bcast,
|
||||
void *val;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ptr); i++) {
|
||||
if (!ptr[i])
|
||||
continue;
|
||||
|
||||
*ptr[i] = USHRT_MAX;
|
||||
}
|
||||
|
||||
if (!npc_priv.init_done)
|
||||
return 0;
|
||||
|
||||
@@ -3950,7 +4050,6 @@ int npc_cn20k_dft_rules_idx_get(struct rvu *rvu, u16 pcifunc, u16 *bcast,
|
||||
npc_dft_rule_name[NPC_DFT_RULE_PROMISC_ID],
|
||||
pcifunc);
|
||||
|
||||
*ptr[0] = USHRT_MAX;
|
||||
return -ESRCH;
|
||||
}
|
||||
|
||||
@@ -3970,7 +4069,6 @@ int npc_cn20k_dft_rules_idx_get(struct rvu *rvu, u16 pcifunc, u16 *bcast,
|
||||
npc_dft_rule_name[NPC_DFT_RULE_UCAST_ID],
|
||||
pcifunc);
|
||||
|
||||
*ptr[3] = USHRT_MAX;
|
||||
return -ESRCH;
|
||||
}
|
||||
|
||||
@@ -3990,7 +4088,6 @@ int npc_cn20k_dft_rules_idx_get(struct rvu *rvu, u16 pcifunc, u16 *bcast,
|
||||
__func__,
|
||||
npc_dft_rule_name[i], pcifunc);
|
||||
|
||||
*ptr[j] = USHRT_MAX;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -4085,7 +4182,7 @@ int rvu_mbox_handler_npc_get_dft_rl_idxs(struct rvu *rvu, struct msg_req *req,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool npc_is_cgx_or_lbk(struct rvu *rvu, u16 pcifunc)
|
||||
bool npc_is_cgx_or_lbk(struct rvu *rvu, u16 pcifunc)
|
||||
{
|
||||
return is_pf_cgxmapped(rvu, rvu_get_pf(rvu->pdev, pcifunc)) ||
|
||||
is_lbk_vf(rvu, pcifunc);
|
||||
@@ -4093,11 +4190,11 @@ static bool npc_is_cgx_or_lbk(struct rvu *rvu, u16 pcifunc)
|
||||
|
||||
void npc_cn20k_dft_rules_free(struct rvu *rvu, u16 pcifunc)
|
||||
{
|
||||
struct npc_mcam_free_entry_req free_req = { 0 };
|
||||
struct npc_mcam *mcam = &rvu->hw->mcam;
|
||||
u16 ptr[4] = {[0 ... 3] = USHRT_MAX};
|
||||
struct rvu_npc_mcam_rule *rule, *tmp;
|
||||
unsigned long index;
|
||||
struct msg_rsp rsp;
|
||||
u16 ptr[4];
|
||||
int rc, i;
|
||||
int blkaddr, rc, i;
|
||||
void *map;
|
||||
|
||||
if (!npc_priv.init_done)
|
||||
@@ -4155,14 +4252,43 @@ void npc_cn20k_dft_rules_free(struct rvu *rvu, u16 pcifunc)
|
||||
}
|
||||
|
||||
free_rules:
|
||||
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
|
||||
if (blkaddr < 0)
|
||||
return;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (ptr[i] == USHRT_MAX)
|
||||
continue;
|
||||
|
||||
free_req.hdr.pcifunc = pcifunc;
|
||||
free_req.all = 1;
|
||||
rc = rvu_mbox_handler_npc_mcam_free_entry(rvu, &free_req, &rsp);
|
||||
if (rc)
|
||||
dev_err(rvu->dev,
|
||||
"%s: Error deleting default entries (pcifunc=%#x\n",
|
||||
__func__, pcifunc);
|
||||
mutex_lock(&mcam->lock);
|
||||
npc_mcam_clear_bit(mcam, ptr[i]);
|
||||
mcam->entry2pfvf_map[ptr[i]] = NPC_MCAM_INVALID_MAP;
|
||||
npc_cn20k_enable_mcam_entry(rvu, blkaddr, ptr[i], false);
|
||||
mcam->entry2target_pffunc[ptr[i]] = 0x0;
|
||||
mutex_unlock(&mcam->lock);
|
||||
|
||||
rc = npc_cn20k_idx_free(rvu, &ptr[i], 1);
|
||||
if (rc) {
|
||||
/* Non recoverable error. Let us WARN and return. Keep system alive to
|
||||
* enable debugging
|
||||
*/
|
||||
WARN(1, "%s Error deleting default entries (pcifunc=%#x) mcam_idx=%u\n",
|
||||
__func__, pcifunc, ptr[i]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_lock(&mcam->lock);
|
||||
list_for_each_entry_safe(rule, tmp, &mcam->mcam_rules, list) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (ptr[i] != rule->entry)
|
||||
continue;
|
||||
|
||||
list_del(&rule->list);
|
||||
kfree(rule);
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&mcam->lock);
|
||||
}
|
||||
|
||||
int npc_cn20k_dft_rules_alloc(struct rvu *rvu, u16 pcifunc)
|
||||
|
||||
@@ -320,21 +320,21 @@ void npc_cn20k_dft_rules_free(struct rvu *rvu, u16 pcifunc);
|
||||
int npc_cn20k_dft_rules_idx_get(struct rvu *rvu, u16 pcifunc, u16 *bcast,
|
||||
u16 *mcast, u16 *promisc, u16 *ucast);
|
||||
|
||||
void npc_cn20k_config_mcam_entry(struct rvu *rvu, int blkaddr, int index,
|
||||
u8 intf, struct cn20k_mcam_entry *entry,
|
||||
bool enable, u8 hw_prio, u8 req_kw_type);
|
||||
void npc_cn20k_enable_mcam_entry(struct rvu *rvu, int blkaddr,
|
||||
int index, bool enable);
|
||||
void npc_cn20k_copy_mcam_entry(struct rvu *rvu, int blkaddr,
|
||||
u16 src, u16 dest);
|
||||
void npc_cn20k_read_mcam_entry(struct rvu *rvu, int blkaddr, u16 index,
|
||||
struct cn20k_mcam_entry *entry, u8 *intf,
|
||||
u8 *ena, u8 *hw_prio);
|
||||
void npc_cn20k_clear_mcam_entry(struct rvu *rvu, int blkaddr,
|
||||
int bank, int index);
|
||||
int npc_cn20k_config_mcam_entry(struct rvu *rvu, int blkaddr, int index,
|
||||
u8 intf, struct cn20k_mcam_entry *entry,
|
||||
bool enable, u8 hw_prio, u8 req_kw_type);
|
||||
int npc_cn20k_enable_mcam_entry(struct rvu *rvu, int blkaddr,
|
||||
int index, bool enable);
|
||||
int npc_cn20k_copy_mcam_entry(struct rvu *rvu, int blkaddr,
|
||||
u16 src, u16 dest);
|
||||
int npc_cn20k_read_mcam_entry(struct rvu *rvu, int blkaddr, u16 index,
|
||||
struct cn20k_mcam_entry *entry, u8 *intf,
|
||||
u8 *ena, u8 *hw_prio);
|
||||
int npc_cn20k_clear_mcam_entry(struct rvu *rvu, int blkaddr, int index);
|
||||
int npc_mcam_idx_2_key_type(struct rvu *rvu, u16 mcam_idx, u8 *key_type);
|
||||
u16 npc_cn20k_vidx2idx(u16 index);
|
||||
u16 npc_cn20k_idx2vidx(u16 idx);
|
||||
int npc_cn20k_defrag(struct rvu *rvu);
|
||||
bool npc_is_cgx_or_lbk(struct rvu *rvu, u16 pcifunc);
|
||||
|
||||
#endif /* NPC_CN20K_H */
|
||||
|
||||
@@ -3577,6 +3577,9 @@ static int nix_update_mce_rule(struct rvu *rvu, u16 pcifunc,
|
||||
mcam_index = npc_get_nixlf_mcam_index(mcam,
|
||||
pcifunc & ~RVU_PFVF_FUNC_MASK,
|
||||
nixlf, type);
|
||||
if (mcam_index < 0)
|
||||
return -EINVAL;
|
||||
|
||||
err = nix_update_mce_list(rvu, pcifunc, mce_list,
|
||||
mce_idx, mcam_index, add);
|
||||
return err;
|
||||
|
||||
@@ -163,14 +163,35 @@ int npc_get_nixlf_mcam_index(struct npc_mcam *mcam,
|
||||
if (rc)
|
||||
return -EFAULT;
|
||||
|
||||
if (is_lbk_vf(rvu, pcifunc)) {
|
||||
if (promisc == USHRT_MAX)
|
||||
return -EINVAL;
|
||||
return promisc;
|
||||
}
|
||||
|
||||
if (is_cgx_vf(rvu, pcifunc)) {
|
||||
if (ucast == USHRT_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
return ucast;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case NIXLF_BCAST_ENTRY:
|
||||
if (bcast == USHRT_MAX)
|
||||
return -EINVAL;
|
||||
return bcast;
|
||||
case NIXLF_ALLMULTI_ENTRY:
|
||||
if (mcast == USHRT_MAX)
|
||||
return -EINVAL;
|
||||
return mcast;
|
||||
case NIXLF_PROMISC_ENTRY:
|
||||
if (promisc == USHRT_MAX)
|
||||
return -EINVAL;
|
||||
return promisc;
|
||||
case NIXLF_UCAST_ENTRY:
|
||||
if (ucast == USHRT_MAX)
|
||||
return -EINVAL;
|
||||
return ucast;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@@ -238,10 +259,10 @@ void npc_enable_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
|
||||
int actbank = bank;
|
||||
|
||||
if (is_cn20k(rvu->pdev)) {
|
||||
if (index < 0 || index >= mcam->banksize * mcam->banks)
|
||||
return;
|
||||
|
||||
return npc_cn20k_enable_mcam_entry(rvu, blkaddr, index, enable);
|
||||
if (npc_cn20k_enable_mcam_entry(rvu, blkaddr, index, enable))
|
||||
dev_err(rvu->dev, "Error to %s mcam %u entry\n",
|
||||
enable ? "enable" : "disable", index);
|
||||
return;
|
||||
}
|
||||
|
||||
index &= (mcam->banksize - 1);
|
||||
@@ -258,6 +279,13 @@ static void npc_clear_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
|
||||
int bank = npc_get_bank(mcam, index);
|
||||
int actbank = bank;
|
||||
|
||||
if (is_cn20k(rvu->pdev)) {
|
||||
if (npc_cn20k_clear_mcam_entry(rvu, blkaddr, index))
|
||||
dev_err(rvu->dev, "%s Failed to clear mcam %u\n",
|
||||
__func__, index);
|
||||
return;
|
||||
}
|
||||
|
||||
index &= (mcam->banksize - 1);
|
||||
for (; bank < (actbank + mcam->banks_per_entry); bank++) {
|
||||
rvu_write64(rvu, blkaddr,
|
||||
@@ -424,6 +452,15 @@ static u64 npc_get_default_entry_action(struct rvu *rvu, struct npc_mcam *mcam,
|
||||
|
||||
index = npc_get_nixlf_mcam_index(mcam, pf_func, nixlf,
|
||||
NIXLF_UCAST_ENTRY);
|
||||
|
||||
if (index < 0) {
|
||||
dev_err(rvu->dev,
|
||||
"%s: failed to get ucast entry pcifunc:0x%x\n",
|
||||
__func__, pf_func);
|
||||
/* Action 0 is drop */
|
||||
return 0;
|
||||
}
|
||||
|
||||
bank = npc_get_bank(mcam, index);
|
||||
index &= (mcam->banksize - 1);
|
||||
|
||||
@@ -589,8 +626,8 @@ void npc_read_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
|
||||
NPC_AF_MCAMEX_BANKX_CFG(src, sbank)) & 1;
|
||||
}
|
||||
|
||||
static void npc_copy_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
|
||||
int blkaddr, u16 src, u16 dest)
|
||||
static int npc_copy_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
|
||||
int blkaddr, u16 src, u16 dest)
|
||||
{
|
||||
int dbank = npc_get_bank(mcam, dest);
|
||||
int sbank = npc_get_bank(mcam, src);
|
||||
@@ -630,6 +667,7 @@ static void npc_copy_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
|
||||
NPC_AF_MCAMEX_BANKX_CFG(src, sbank));
|
||||
rvu_write64(rvu, blkaddr,
|
||||
NPC_AF_MCAMEX_BANKX_CFG(dest, dbank), cfg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
u64 npc_get_mcam_action(struct rvu *rvu, struct npc_mcam *mcam,
|
||||
@@ -689,6 +727,12 @@ void rvu_npc_install_ucast_entry(struct rvu *rvu, u16 pcifunc,
|
||||
|
||||
index = npc_get_nixlf_mcam_index(mcam, pcifunc,
|
||||
nixlf, NIXLF_UCAST_ENTRY);
|
||||
if (index < 0) {
|
||||
dev_err(rvu->dev,
|
||||
"%s: Error to get ucast entry for pcifunc=%#x\n",
|
||||
__func__, pcifunc);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Don't change the action if entry is already enabled
|
||||
* Otherwise RSS action may get overwritten.
|
||||
@@ -744,16 +788,38 @@ void rvu_npc_install_promisc_entry(struct rvu *rvu, u16 pcifunc,
|
||||
index = npc_get_nixlf_mcam_index(mcam, pcifunc,
|
||||
nixlf, NIXLF_PROMISC_ENTRY);
|
||||
|
||||
/* In cn20k, default indexes are installed only for CGX mapped
|
||||
* and lbk interfaces
|
||||
*/
|
||||
if (is_cgx_vf(rvu, pcifunc))
|
||||
index = npc_get_nixlf_mcam_index(mcam,
|
||||
pcifunc & ~RVU_PFVF_FUNC_MASK,
|
||||
nixlf, NIXLF_PROMISC_ENTRY);
|
||||
|
||||
if (index < 0) {
|
||||
dev_err(rvu->dev,
|
||||
"%s: Error to get promisc entry for pcifunc=%#x\n",
|
||||
__func__, pcifunc);
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the corresponding PF's ucast action is RSS,
|
||||
* use the same action for promisc also
|
||||
* Please note that for lbk(s) "index" and "ucast_idx"
|
||||
* will be same.
|
||||
*/
|
||||
ucast_idx = npc_get_nixlf_mcam_index(mcam, pcifunc,
|
||||
nixlf, NIXLF_UCAST_ENTRY);
|
||||
if (is_lbk_vf(rvu, pcifunc))
|
||||
ucast_idx = index;
|
||||
else
|
||||
ucast_idx = npc_get_nixlf_mcam_index(mcam, pcifunc,
|
||||
nixlf, NIXLF_UCAST_ENTRY);
|
||||
if (ucast_idx < 0) {
|
||||
dev_err(rvu->dev,
|
||||
"%s: Error to get ucast/promisc entry for pcifunc=%#x\n",
|
||||
__func__, pcifunc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_mcam_entry_enabled(rvu, mcam, blkaddr, ucast_idx))
|
||||
*(u64 *)&action = npc_get_mcam_action(rvu, mcam,
|
||||
blkaddr, ucast_idx);
|
||||
@@ -827,6 +893,14 @@ void rvu_npc_enable_promisc_entry(struct rvu *rvu, u16 pcifunc,
|
||||
|
||||
index = npc_get_nixlf_mcam_index(mcam, pcifunc,
|
||||
nixlf, NIXLF_PROMISC_ENTRY);
|
||||
|
||||
if (index < 0) {
|
||||
dev_err(rvu->dev,
|
||||
"%s: Error to get promisc entry for pcifunc=%#x\n",
|
||||
__func__, pcifunc);
|
||||
return;
|
||||
}
|
||||
|
||||
npc_enable_mcam_entry(rvu, mcam, blkaddr, index, enable);
|
||||
}
|
||||
|
||||
@@ -867,6 +941,12 @@ void rvu_npc_install_bcast_match_entry(struct rvu *rvu, u16 pcifunc,
|
||||
|
||||
index = npc_get_nixlf_mcam_index(mcam, pcifunc,
|
||||
nixlf, NIXLF_BCAST_ENTRY);
|
||||
if (index < 0) {
|
||||
dev_err(rvu->dev,
|
||||
"%s: Error to get bcast entry for pcifunc=%#x\n",
|
||||
__func__, pcifunc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!hw->cap.nix_rx_multicast) {
|
||||
/* Early silicon doesn't support pkt replication,
|
||||
@@ -931,12 +1011,25 @@ void rvu_npc_install_allmulti_entry(struct rvu *rvu, u16 pcifunc, int nixlf,
|
||||
|
||||
index = npc_get_nixlf_mcam_index(mcam, pcifunc,
|
||||
nixlf, NIXLF_ALLMULTI_ENTRY);
|
||||
if (index < 0) {
|
||||
dev_err(rvu->dev,
|
||||
"%s: Error to get mcast entry for pcifunc=%#x\n",
|
||||
__func__, pcifunc);
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the corresponding PF's ucast action is RSS,
|
||||
* use the same action for multicast entry also
|
||||
*/
|
||||
ucast_idx = npc_get_nixlf_mcam_index(mcam, pcifunc,
|
||||
nixlf, NIXLF_UCAST_ENTRY);
|
||||
if (ucast_idx < 0) {
|
||||
dev_err(rvu->dev,
|
||||
"%s: Error to get ucast entry for pcifunc=%#x\n",
|
||||
__func__, pcifunc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_mcam_entry_enabled(rvu, mcam, blkaddr, ucast_idx))
|
||||
*(u64 *)&action = npc_get_mcam_action(rvu, mcam,
|
||||
blkaddr, ucast_idx);
|
||||
@@ -1001,6 +1094,13 @@ void rvu_npc_enable_allmulti_entry(struct rvu *rvu, u16 pcifunc, int nixlf,
|
||||
|
||||
index = npc_get_nixlf_mcam_index(mcam, pcifunc, nixlf,
|
||||
NIXLF_ALLMULTI_ENTRY);
|
||||
if (index < 0) {
|
||||
dev_err(rvu->dev,
|
||||
"%s: Error to get mcast entry for pcifunc=%#x\n",
|
||||
__func__, pcifunc);
|
||||
return;
|
||||
}
|
||||
|
||||
npc_enable_mcam_entry(rvu, mcam, blkaddr, index, enable);
|
||||
}
|
||||
|
||||
@@ -1113,8 +1213,12 @@ void rvu_npc_update_flowkey_alg_idx(struct rvu *rvu, u16 pcifunc, int nixlf,
|
||||
index = mcam_index;
|
||||
}
|
||||
|
||||
if (index >= mcam->total_entries)
|
||||
if (index < 0 || index >= mcam->total_entries) {
|
||||
dev_err(rvu->dev,
|
||||
"%s: Invalid mcam index, pcifunc=%#x\n",
|
||||
__func__, pcifunc);
|
||||
return;
|
||||
}
|
||||
|
||||
bank = npc_get_bank(mcam, index);
|
||||
index &= (mcam->banksize - 1);
|
||||
@@ -1158,16 +1262,18 @@ void rvu_npc_update_flowkey_alg_idx(struct rvu *rvu, u16 pcifunc, int nixlf,
|
||||
/* If PF's promiscuous entry is enabled,
|
||||
* Set RSS action for that entry as well
|
||||
*/
|
||||
npc_update_rx_action_with_alg_idx(rvu, action, pfvf, index,
|
||||
blkaddr, alg_idx);
|
||||
if (index >= 0)
|
||||
npc_update_rx_action_with_alg_idx(rvu, action, pfvf, index,
|
||||
blkaddr, alg_idx);
|
||||
|
||||
index = npc_get_nixlf_mcam_index(mcam, pcifunc,
|
||||
nixlf, NIXLF_ALLMULTI_ENTRY);
|
||||
/* If PF's allmulti entry is enabled,
|
||||
* Set RSS action for that entry as well
|
||||
*/
|
||||
npc_update_rx_action_with_alg_idx(rvu, action, pfvf, index,
|
||||
blkaddr, alg_idx);
|
||||
if (index >= 0)
|
||||
npc_update_rx_action_with_alg_idx(rvu, action, pfvf, index,
|
||||
blkaddr, alg_idx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1180,12 +1286,22 @@ void npc_enadis_default_mce_entry(struct rvu *rvu, u16 pcifunc,
|
||||
int index, blkaddr, mce_idx;
|
||||
struct rvu_pfvf *pfvf;
|
||||
|
||||
/* multicast pkt replication is not enabled for AF's VFs & SDP links */
|
||||
if (is_lbk_vf(rvu, pcifunc) || is_sdp_pfvf(rvu, pcifunc))
|
||||
return;
|
||||
|
||||
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
|
||||
if (blkaddr < 0)
|
||||
return;
|
||||
|
||||
index = npc_get_nixlf_mcam_index(mcam, pcifunc & ~RVU_PFVF_FUNC_MASK,
|
||||
nixlf, type);
|
||||
if (index < 0) {
|
||||
dev_err(rvu->dev,
|
||||
"%s: Error to get entry for pcifunc=%#x, type=%u\n",
|
||||
__func__, pcifunc, type);
|
||||
return;
|
||||
}
|
||||
|
||||
/* disable MCAM entry when packet replication is not supported by hw */
|
||||
if (!hw->cap.nix_rx_multicast && !is_vf(pcifunc)) {
|
||||
@@ -1214,6 +1330,10 @@ static void npc_enadis_default_entries(struct rvu *rvu, u16 pcifunc,
|
||||
struct npc_mcam *mcam = &rvu->hw->mcam;
|
||||
int index, blkaddr;
|
||||
|
||||
/* only CGX or LBK interfaces have default entries */
|
||||
if (is_cn20k(rvu->pdev) && !npc_is_cgx_or_lbk(rvu, pcifunc))
|
||||
return;
|
||||
|
||||
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
|
||||
if (blkaddr < 0)
|
||||
return;
|
||||
@@ -1223,6 +1343,12 @@ static void npc_enadis_default_entries(struct rvu *rvu, u16 pcifunc,
|
||||
pfvf->nix_rx_intf)) {
|
||||
index = npc_get_nixlf_mcam_index(mcam, pcifunc,
|
||||
nixlf, NIXLF_UCAST_ENTRY);
|
||||
if (index < 0) {
|
||||
dev_err(rvu->dev,
|
||||
"%s: Error to get ucast entry for pcifunc=%#x\n",
|
||||
__func__, pcifunc);
|
||||
return;
|
||||
}
|
||||
npc_enable_mcam_entry(rvu, mcam, blkaddr, index, enable);
|
||||
}
|
||||
|
||||
@@ -2504,33 +2630,58 @@ void npc_mcam_clear_bit(struct npc_mcam *mcam, u16 index)
|
||||
static void npc_mcam_free_all_entries(struct rvu *rvu, struct npc_mcam *mcam,
|
||||
int blkaddr, u16 pcifunc)
|
||||
{
|
||||
u16 dft_idxs[NPC_DFT_RULE_MAX_ID] = {[0 ... NPC_DFT_RULE_MAX_ID - 1] = USHRT_MAX};
|
||||
bool cn20k_dft_rl;
|
||||
u16 index, cntr;
|
||||
int rc;
|
||||
|
||||
npc_cn20k_dft_rules_idx_get(rvu, pcifunc,
|
||||
&dft_idxs[NPC_DFT_RULE_BCAST_ID],
|
||||
&dft_idxs[NPC_DFT_RULE_MCAST_ID],
|
||||
&dft_idxs[NPC_DFT_RULE_PROMISC_ID],
|
||||
&dft_idxs[NPC_DFT_RULE_UCAST_ID]);
|
||||
|
||||
/* Scan all MCAM entries and free the ones mapped to 'pcifunc' */
|
||||
for (index = 0; index < mcam->bmap_entries; index++) {
|
||||
if (mcam->entry2pfvf_map[index] == pcifunc) {
|
||||
if (mcam->entry2pfvf_map[index] != pcifunc)
|
||||
continue;
|
||||
|
||||
cn20k_dft_rl = false;
|
||||
|
||||
if (is_cn20k(rvu->pdev)) {
|
||||
if (dft_idxs[NPC_DFT_RULE_BCAST_ID] == index ||
|
||||
dft_idxs[NPC_DFT_RULE_MCAST_ID] == index ||
|
||||
dft_idxs[NPC_DFT_RULE_PROMISC_ID] == index ||
|
||||
dft_idxs[NPC_DFT_RULE_UCAST_ID] == index) {
|
||||
cn20k_dft_rl = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the entry */
|
||||
npc_enable_mcam_entry(rvu, mcam, blkaddr, index, false);
|
||||
|
||||
if (!cn20k_dft_rl) {
|
||||
mcam->entry2pfvf_map[index] = NPC_MCAM_INVALID_MAP;
|
||||
/* Free the entry in bitmap */
|
||||
npc_mcam_clear_bit(mcam, index);
|
||||
/* Disable the entry */
|
||||
npc_enable_mcam_entry(rvu, mcam, blkaddr, index, false);
|
||||
|
||||
/* Update entry2counter mapping */
|
||||
cntr = mcam->entry2cntr_map[index];
|
||||
if (cntr != NPC_MCAM_INVALID_MAP)
|
||||
npc_unmap_mcam_entry_and_cntr(rvu, mcam,
|
||||
blkaddr, index,
|
||||
cntr);
|
||||
mcam->entry2target_pffunc[index] = 0x0;
|
||||
if (is_cn20k(rvu->pdev)) {
|
||||
rc = npc_cn20k_idx_free(rvu, &index, 1);
|
||||
if (rc)
|
||||
dev_err(rvu->dev,
|
||||
"Failed to free mcam idx=%u pcifunc=%#x\n",
|
||||
index, pcifunc);
|
||||
}
|
||||
}
|
||||
|
||||
/* Update entry2counter mapping */
|
||||
cntr = mcam->entry2cntr_map[index];
|
||||
if (cntr != NPC_MCAM_INVALID_MAP)
|
||||
npc_unmap_mcam_entry_and_cntr(rvu, mcam,
|
||||
blkaddr, index,
|
||||
cntr);
|
||||
|
||||
if (!is_cn20k(rvu->pdev) || cn20k_dft_rl)
|
||||
continue;
|
||||
|
||||
rc = npc_cn20k_idx_free(rvu, &index, 1);
|
||||
if (rc)
|
||||
dev_err(rvu->dev,
|
||||
"Failed to free mcam idx=%u pcifunc=%#x\n",
|
||||
index, pcifunc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3266,7 +3417,10 @@ int rvu_mbox_handler_npc_mcam_shift_entry(struct rvu *rvu,
|
||||
npc_enable_mcam_entry(rvu, mcam, blkaddr, new_entry, false);
|
||||
|
||||
/* Copy rule from old entry to new entry */
|
||||
npc_copy_mcam_entry(rvu, mcam, blkaddr, old_entry, new_entry);
|
||||
if (npc_copy_mcam_entry(rvu, mcam, blkaddr, old_entry, new_entry)) {
|
||||
rc = NPC_MCAM_INVALID_REQ;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Copy counter mapping, if any */
|
||||
cntr = mcam->entry2cntr_map[old_entry];
|
||||
@@ -3284,7 +3438,8 @@ int rvu_mbox_handler_npc_mcam_shift_entry(struct rvu *rvu,
|
||||
|
||||
/* If shift has failed then report the failed index */
|
||||
if (index != req->shift_count) {
|
||||
rc = NPC_MCAM_PERM_DENIED;
|
||||
if (!rc)
|
||||
rc = NPC_MCAM_PERM_DENIED;
|
||||
rsp->failed_entry_idx = index;
|
||||
}
|
||||
|
||||
@@ -3851,6 +4006,12 @@ int rvu_mbox_handler_npc_read_base_steer_rule(struct rvu *rvu,
|
||||
/* Read the default ucast entry if there is no pkt steering rule */
|
||||
index = npc_get_nixlf_mcam_index(mcam, pcifunc, nixlf,
|
||||
NIXLF_UCAST_ENTRY);
|
||||
if (index < 0) {
|
||||
mutex_unlock(&mcam->lock);
|
||||
rc = NIX_AF_ERR_AF_LF_INVALID;
|
||||
goto out;
|
||||
}
|
||||
|
||||
read_entry:
|
||||
/* Read the mcam entry */
|
||||
npc_read_mcam_entry(rvu, mcam, blkaddr, index, &rsp->entry, &intf,
|
||||
@@ -3924,6 +4085,12 @@ void rvu_npc_clear_ucast_entry(struct rvu *rvu, int pcifunc, int nixlf)
|
||||
|
||||
ucast_idx = npc_get_nixlf_mcam_index(mcam, pcifunc,
|
||||
nixlf, NIXLF_UCAST_ENTRY);
|
||||
if (ucast_idx < 0) {
|
||||
dev_err(rvu->dev,
|
||||
"%s: Error to get ucast entry for pcifunc=%#x\n",
|
||||
__func__, pcifunc);
|
||||
return;
|
||||
}
|
||||
|
||||
npc_enable_mcam_entry(rvu, mcam, blkaddr, ucast_idx, false);
|
||||
|
||||
|
||||
@@ -1444,7 +1444,7 @@ static int npc_install_flow(struct rvu *rvu, int blkaddr, u16 target,
|
||||
struct msg_rsp write_rsp;
|
||||
struct mcam_entry *entry;
|
||||
bool new = false;
|
||||
u16 entry_index;
|
||||
int entry_index;
|
||||
int err;
|
||||
|
||||
installed_features = req->features;
|
||||
@@ -1477,6 +1477,14 @@ static int npc_install_flow(struct rvu *rvu, int blkaddr, u16 target,
|
||||
if (req->default_rule) {
|
||||
entry_index = npc_get_nixlf_mcam_index(mcam, target, nixlf,
|
||||
NIXLF_UCAST_ENTRY);
|
||||
|
||||
if (entry_index < 0) {
|
||||
dev_err(rvu->dev,
|
||||
"%s: Error to get ucast entry for target=%#x\n",
|
||||
__func__, target);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
enable = is_mcam_entry_enabled(rvu, mcam, blkaddr, entry_index);
|
||||
}
|
||||
|
||||
@@ -1980,13 +1988,15 @@ static int npc_update_dmac_value(struct rvu *rvu, int npcblkaddr,
|
||||
|
||||
ether_addr_copy(rule->packet.dmac, pfvf->mac_addr);
|
||||
|
||||
if (is_cn20k(rvu->pdev))
|
||||
npc_cn20k_read_mcam_entry(rvu, npcblkaddr, rule->entry,
|
||||
cn20k_entry, &intf,
|
||||
&enable, &hw_prio);
|
||||
else
|
||||
if (is_cn20k(rvu->pdev)) {
|
||||
if (npc_cn20k_read_mcam_entry(rvu, npcblkaddr, rule->entry,
|
||||
cn20k_entry, &intf,
|
||||
&enable, &hw_prio))
|
||||
return -EINVAL;
|
||||
} else {
|
||||
npc_read_mcam_entry(rvu, mcam, npcblkaddr, rule->entry,
|
||||
entry, &intf, &enable);
|
||||
}
|
||||
|
||||
npc_update_entry(rvu, NPC_DMAC, &mdata,
|
||||
ether_addr_to_u64(pfvf->mac_addr), 0,
|
||||
@@ -2038,8 +2048,12 @@ void npc_mcam_enable_flows(struct rvu *rvu, u16 target)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rule->vfvlan_cfg)
|
||||
npc_update_dmac_value(rvu, blkaddr, rule, pfvf);
|
||||
if (rule->vfvlan_cfg) {
|
||||
if (npc_update_dmac_value(rvu, blkaddr, rule, pfvf))
|
||||
dev_err(rvu->dev,
|
||||
"Update dmac failed for %u, target=%#x\n",
|
||||
rule->entry, target);
|
||||
}
|
||||
|
||||
if (rule->rx_action.op == NIX_RX_ACTION_DEFAULT) {
|
||||
if (!def_ucast_rule)
|
||||
|
||||
@@ -1070,29 +1070,37 @@ static struct psp_dev_ops mlx5_psp_ops = {
|
||||
|
||||
void mlx5e_psp_unregister(struct mlx5e_priv *priv)
|
||||
{
|
||||
if (!priv->psp || !priv->psp->psp)
|
||||
struct mlx5e_psp *psp = priv->psp;
|
||||
|
||||
if (!psp || !psp->psp)
|
||||
return;
|
||||
|
||||
psp_dev_unregister(priv->psp->psp);
|
||||
psp_dev_unregister(psp->psp);
|
||||
psp->psp = NULL;
|
||||
}
|
||||
|
||||
void mlx5e_psp_register(struct mlx5e_priv *priv)
|
||||
{
|
||||
struct mlx5e_psp *psp = priv->psp;
|
||||
struct psp_dev *psd;
|
||||
|
||||
/* FW Caps missing */
|
||||
if (!priv->psp)
|
||||
return;
|
||||
|
||||
priv->psp->caps.assoc_drv_spc = sizeof(u32);
|
||||
priv->psp->caps.versions = 1 << PSP_VERSION_HDR0_AES_GCM_128;
|
||||
psp->caps.assoc_drv_spc = sizeof(u32);
|
||||
psp->caps.versions = 1 << PSP_VERSION_HDR0_AES_GCM_128;
|
||||
if (MLX5_CAP_PSP(priv->mdev, psp_crypto_esp_aes_gcm_256_encrypt) &&
|
||||
MLX5_CAP_PSP(priv->mdev, psp_crypto_esp_aes_gcm_256_decrypt))
|
||||
priv->psp->caps.versions |= 1 << PSP_VERSION_HDR0_AES_GCM_256;
|
||||
psp->caps.versions |= 1 << PSP_VERSION_HDR0_AES_GCM_256;
|
||||
|
||||
priv->psp->psp = psp_dev_create(priv->netdev, &mlx5_psp_ops,
|
||||
&priv->psp->caps, NULL);
|
||||
if (IS_ERR(priv->psp->psp))
|
||||
psd = psp_dev_create(priv->netdev, &mlx5_psp_ops, &psp->caps, NULL);
|
||||
if (IS_ERR(psd)) {
|
||||
mlx5_core_err(priv->mdev, "PSP failed to register due to %pe\n",
|
||||
priv->psp->psp);
|
||||
psd);
|
||||
return;
|
||||
}
|
||||
psp->psp = psd;
|
||||
}
|
||||
|
||||
int mlx5e_psp_init(struct mlx5e_priv *priv)
|
||||
@@ -1131,22 +1139,18 @@ int mlx5e_psp_init(struct mlx5e_priv *priv)
|
||||
if (!psp)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->psp = psp;
|
||||
fs = mlx5e_accel_psp_fs_init(priv);
|
||||
if (IS_ERR(fs)) {
|
||||
err = PTR_ERR(fs);
|
||||
goto out_err;
|
||||
kfree(psp);
|
||||
return err;
|
||||
}
|
||||
|
||||
psp->fs = fs;
|
||||
priv->psp = psp;
|
||||
|
||||
mlx5_core_dbg(priv->mdev, "PSP attached to netdevice\n");
|
||||
return 0;
|
||||
|
||||
out_err:
|
||||
priv->psp = NULL;
|
||||
kfree(psp);
|
||||
return err;
|
||||
}
|
||||
|
||||
void mlx5e_psp_cleanup(struct mlx5e_priv *priv)
|
||||
|
||||
@@ -6023,7 +6023,6 @@ static int mlx5e_nic_init(struct mlx5_core_dev *mdev,
|
||||
if (take_rtnl)
|
||||
rtnl_lock();
|
||||
|
||||
mlx5e_psp_register(priv);
|
||||
/* update XDP supported features */
|
||||
mlx5e_set_xdp_feature(priv);
|
||||
|
||||
@@ -6036,7 +6035,6 @@ static int mlx5e_nic_init(struct mlx5_core_dev *mdev,
|
||||
static void mlx5e_nic_cleanup(struct mlx5e_priv *priv)
|
||||
{
|
||||
mlx5e_health_destroy_reporters(priv);
|
||||
mlx5e_psp_unregister(priv);
|
||||
mlx5e_ktls_cleanup(priv);
|
||||
mlx5e_psp_cleanup(priv);
|
||||
mlx5e_fs_cleanup(priv->fs);
|
||||
@@ -6160,6 +6158,7 @@ static void mlx5e_nic_enable(struct mlx5e_priv *priv)
|
||||
|
||||
mlx5e_fs_init_l2_addr(priv->fs, netdev);
|
||||
mlx5e_ipsec_init(priv);
|
||||
mlx5e_psp_register(priv);
|
||||
|
||||
err = mlx5e_macsec_init(priv);
|
||||
if (err)
|
||||
@@ -6230,6 +6229,7 @@ static void mlx5e_nic_disable(struct mlx5e_priv *priv)
|
||||
mlx5_lag_remove_netdev(mdev, priv->netdev);
|
||||
mlx5_vxlan_reset_to_default(mdev->vxlan);
|
||||
mlx5e_macsec_cleanup(priv);
|
||||
mlx5e_psp_unregister(priv);
|
||||
mlx5e_ipsec_cleanup(priv);
|
||||
}
|
||||
|
||||
@@ -6774,9 +6774,11 @@ static int mlx5e_resume(struct auxiliary_device *adev)
|
||||
return err;
|
||||
|
||||
actual_adev = mlx5_sd_get_adev(mdev, adev, edev->idx);
|
||||
if (actual_adev)
|
||||
return _mlx5e_resume(actual_adev);
|
||||
return 0;
|
||||
if (actual_adev) {
|
||||
err = _mlx5e_resume(actual_adev);
|
||||
mlx5_sd_put_adev(actual_adev, adev);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int _mlx5e_suspend(struct auxiliary_device *adev, bool pre_netdev_reg)
|
||||
@@ -6815,6 +6817,8 @@ static int mlx5e_suspend(struct auxiliary_device *adev, pm_message_t state)
|
||||
err = _mlx5e_suspend(actual_adev, false);
|
||||
|
||||
mlx5_sd_cleanup(mdev);
|
||||
if (actual_adev)
|
||||
mlx5_sd_put_adev(actual_adev, adev);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -6912,9 +6916,19 @@ static int mlx5e_probe(struct auxiliary_device *adev,
|
||||
return err;
|
||||
|
||||
actual_adev = mlx5_sd_get_adev(mdev, adev, edev->idx);
|
||||
if (actual_adev)
|
||||
return _mlx5e_probe(actual_adev);
|
||||
if (actual_adev) {
|
||||
err = _mlx5e_probe(actual_adev);
|
||||
if (err)
|
||||
goto sd_cleanup;
|
||||
mlx5_sd_put_adev(actual_adev, adev);
|
||||
}
|
||||
return 0;
|
||||
|
||||
sd_cleanup:
|
||||
mlx5_sd_cleanup(mdev);
|
||||
if (actual_adev)
|
||||
mlx5_sd_put_adev(actual_adev, adev);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void _mlx5e_remove(struct auxiliary_device *adev)
|
||||
@@ -6966,6 +6980,8 @@ static void mlx5e_remove(struct auxiliary_device *adev)
|
||||
_mlx5e_remove(actual_adev);
|
||||
|
||||
mlx5_sd_cleanup(mdev);
|
||||
if (actual_adev)
|
||||
mlx5_sd_put_adev(actual_adev, adev);
|
||||
}
|
||||
|
||||
static const struct auxiliary_device_id mlx5e_id_table[] = {
|
||||
|
||||
@@ -18,6 +18,7 @@ struct mlx5_sd {
|
||||
u8 host_buses;
|
||||
struct mlx5_devcom_comp_dev *devcom;
|
||||
struct dentry *dfs;
|
||||
u8 state;
|
||||
bool primary;
|
||||
union {
|
||||
struct { /* primary */
|
||||
@@ -31,6 +32,11 @@ struct mlx5_sd {
|
||||
};
|
||||
};
|
||||
|
||||
enum mlx5_sd_state {
|
||||
MLX5_SD_STATE_DOWN = 0,
|
||||
MLX5_SD_STATE_UP,
|
||||
};
|
||||
|
||||
static int mlx5_sd_get_host_buses(struct mlx5_core_dev *dev)
|
||||
{
|
||||
struct mlx5_sd *sd = mlx5_get_sd(dev);
|
||||
@@ -270,9 +276,6 @@ static void sd_unregister(struct mlx5_core_dev *dev)
|
||||
{
|
||||
struct mlx5_sd *sd = mlx5_get_sd(dev);
|
||||
|
||||
mlx5_devcom_comp_lock(sd->devcom);
|
||||
mlx5_devcom_comp_set_ready(sd->devcom, false);
|
||||
mlx5_devcom_comp_unlock(sd->devcom);
|
||||
mlx5_devcom_unregister_component(sd->devcom);
|
||||
}
|
||||
|
||||
@@ -426,6 +429,7 @@ int mlx5_sd_init(struct mlx5_core_dev *dev)
|
||||
struct mlx5_core_dev *primary, *pos, *to;
|
||||
struct mlx5_sd *sd = mlx5_get_sd(dev);
|
||||
u8 alias_key[ACCESS_KEY_LEN];
|
||||
struct mlx5_sd *primary_sd;
|
||||
int err, i;
|
||||
|
||||
err = sd_init(dev);
|
||||
@@ -440,10 +444,17 @@ int mlx5_sd_init(struct mlx5_core_dev *dev)
|
||||
if (err)
|
||||
goto err_sd_cleanup;
|
||||
|
||||
mlx5_devcom_comp_lock(sd->devcom);
|
||||
if (!mlx5_devcom_comp_is_ready(sd->devcom))
|
||||
return 0;
|
||||
goto out;
|
||||
|
||||
primary = mlx5_sd_get_primary(dev);
|
||||
if (!primary)
|
||||
goto out;
|
||||
|
||||
primary_sd = mlx5_get_sd(primary);
|
||||
if (primary_sd->state != MLX5_SD_STATE_DOWN)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < ACCESS_KEY_LEN; i++)
|
||||
alias_key[i] = get_random_u8();
|
||||
@@ -452,9 +463,13 @@ int mlx5_sd_init(struct mlx5_core_dev *dev)
|
||||
if (err)
|
||||
goto err_sd_unregister;
|
||||
|
||||
sd->dfs = debugfs_create_dir("multi-pf", mlx5_debugfs_get_dev_root(primary));
|
||||
debugfs_create_x32("group_id", 0400, sd->dfs, &sd->group_id);
|
||||
debugfs_create_file("primary", 0400, sd->dfs, primary, &dev_fops);
|
||||
primary_sd->dfs =
|
||||
debugfs_create_dir("multi-pf",
|
||||
mlx5_debugfs_get_dev_root(primary));
|
||||
debugfs_create_x32("group_id", 0400, primary_sd->dfs,
|
||||
&primary_sd->group_id);
|
||||
debugfs_create_file("primary", 0400, primary_sd->dfs, primary,
|
||||
&dev_fops);
|
||||
|
||||
mlx5_sd_for_each_secondary(i, primary, pos) {
|
||||
char name[32];
|
||||
@@ -464,7 +479,8 @@ int mlx5_sd_init(struct mlx5_core_dev *dev)
|
||||
goto err_unset_secondaries;
|
||||
|
||||
snprintf(name, sizeof(name), "secondary_%d", i - 1);
|
||||
debugfs_create_file(name, 0400, sd->dfs, pos, &dev_fops);
|
||||
debugfs_create_file(name, 0400, primary_sd->dfs, pos,
|
||||
&dev_fops);
|
||||
|
||||
}
|
||||
|
||||
@@ -472,6 +488,9 @@ int mlx5_sd_init(struct mlx5_core_dev *dev)
|
||||
sd->group_id, mlx5_devcom_comp_get_size(sd->devcom));
|
||||
sd_print_group(primary);
|
||||
|
||||
primary_sd->state = MLX5_SD_STATE_UP;
|
||||
out:
|
||||
mlx5_devcom_comp_unlock(sd->devcom);
|
||||
return 0;
|
||||
|
||||
err_unset_secondaries:
|
||||
@@ -479,8 +498,18 @@ err_unset_secondaries:
|
||||
mlx5_sd_for_each_secondary_to(i, primary, to, pos)
|
||||
sd_cmd_unset_secondary(pos);
|
||||
sd_cmd_unset_primary(primary);
|
||||
debugfs_remove_recursive(sd->dfs);
|
||||
debugfs_remove_recursive(primary_sd->dfs);
|
||||
primary_sd->dfs = NULL;
|
||||
err_sd_unregister:
|
||||
mlx5_sd_for_each_secondary(i, primary, pos) {
|
||||
struct mlx5_sd *peer_sd = mlx5_get_sd(pos);
|
||||
|
||||
primary_sd->secondaries[i - 1] = NULL;
|
||||
peer_sd->primary_dev = NULL;
|
||||
}
|
||||
primary_sd->primary = false;
|
||||
mlx5_devcom_comp_set_ready(sd->devcom, false);
|
||||
mlx5_devcom_comp_unlock(sd->devcom);
|
||||
sd_unregister(dev);
|
||||
err_sd_cleanup:
|
||||
sd_cleanup(dev);
|
||||
@@ -491,42 +520,97 @@ void mlx5_sd_cleanup(struct mlx5_core_dev *dev)
|
||||
{
|
||||
struct mlx5_sd *sd = mlx5_get_sd(dev);
|
||||
struct mlx5_core_dev *primary, *pos;
|
||||
struct mlx5_sd *primary_sd;
|
||||
int i;
|
||||
|
||||
if (!sd)
|
||||
return;
|
||||
|
||||
mlx5_devcom_comp_lock(sd->devcom);
|
||||
if (!mlx5_devcom_comp_is_ready(sd->devcom))
|
||||
goto out;
|
||||
goto out_unlock;
|
||||
|
||||
primary = mlx5_sd_get_primary(dev);
|
||||
if (!primary)
|
||||
goto out_ready_false;
|
||||
|
||||
primary_sd = mlx5_get_sd(primary);
|
||||
if (primary_sd->state != MLX5_SD_STATE_UP)
|
||||
goto out_clear_peers;
|
||||
|
||||
mlx5_sd_for_each_secondary(i, primary, pos)
|
||||
sd_cmd_unset_secondary(pos);
|
||||
sd_cmd_unset_primary(primary);
|
||||
debugfs_remove_recursive(sd->dfs);
|
||||
debugfs_remove_recursive(primary_sd->dfs);
|
||||
primary_sd->dfs = NULL;
|
||||
|
||||
sd_info(primary, "group id %#x, uncombined\n", sd->group_id);
|
||||
out:
|
||||
primary_sd->state = MLX5_SD_STATE_DOWN;
|
||||
out_clear_peers:
|
||||
mlx5_sd_for_each_secondary(i, primary, pos) {
|
||||
struct mlx5_sd *peer_sd = mlx5_get_sd(pos);
|
||||
|
||||
primary_sd->secondaries[i - 1] = NULL;
|
||||
peer_sd->primary_dev = NULL;
|
||||
}
|
||||
primary_sd->primary = false;
|
||||
out_ready_false:
|
||||
mlx5_devcom_comp_set_ready(sd->devcom, false);
|
||||
out_unlock:
|
||||
mlx5_devcom_comp_unlock(sd->devcom);
|
||||
sd_unregister(dev);
|
||||
sd_cleanup(dev);
|
||||
}
|
||||
|
||||
/* Lock order:
|
||||
* primary: actual_adev_lock -> SD devcom comp lock
|
||||
* secondary: SD devcom comp lock -> (drop) -> actual_adev_lock
|
||||
* The two locks are never held together, so no ABBA.
|
||||
*/
|
||||
struct auxiliary_device *mlx5_sd_get_adev(struct mlx5_core_dev *dev,
|
||||
struct auxiliary_device *adev,
|
||||
int idx)
|
||||
{
|
||||
struct mlx5_sd *sd = mlx5_get_sd(dev);
|
||||
struct mlx5_core_dev *primary;
|
||||
struct mlx5_adev *primary_adev;
|
||||
|
||||
if (!sd)
|
||||
return adev;
|
||||
|
||||
if (!mlx5_devcom_comp_is_ready(sd->devcom))
|
||||
mlx5_devcom_comp_lock(sd->devcom);
|
||||
if (!mlx5_devcom_comp_is_ready(sd->devcom)) {
|
||||
mlx5_devcom_comp_unlock(sd->devcom);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
primary = mlx5_sd_get_primary(dev);
|
||||
if (dev == primary)
|
||||
if (!primary || dev == primary) {
|
||||
mlx5_devcom_comp_unlock(sd->devcom);
|
||||
return adev;
|
||||
}
|
||||
|
||||
return &primary->priv.adev[idx]->adev;
|
||||
primary_adev = primary->priv.adev[idx];
|
||||
get_device(&primary_adev->adev.dev);
|
||||
mlx5_devcom_comp_unlock(sd->devcom);
|
||||
|
||||
device_lock(&primary_adev->adev.dev);
|
||||
/* Primary may have completed remove between dropping devcom and
|
||||
* acquiring device_lock; recheck.
|
||||
*/
|
||||
if (!mlx5_devcom_comp_is_ready(sd->devcom)) {
|
||||
device_unlock(&primary_adev->adev.dev);
|
||||
put_device(&primary_adev->adev.dev);
|
||||
return NULL;
|
||||
}
|
||||
return &primary_adev->adev;
|
||||
}
|
||||
|
||||
void mlx5_sd_put_adev(struct auxiliary_device *actual_adev,
|
||||
struct auxiliary_device *adev)
|
||||
{
|
||||
if (actual_adev != adev) {
|
||||
device_unlock(&actual_adev->dev);
|
||||
put_device(&actual_adev->dev);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ struct mlx5_core_dev *mlx5_sd_ch_ix_get_dev(struct mlx5_core_dev *primary, int c
|
||||
struct auxiliary_device *mlx5_sd_get_adev(struct mlx5_core_dev *dev,
|
||||
struct auxiliary_device *adev,
|
||||
int idx);
|
||||
void mlx5_sd_put_adev(struct auxiliary_device *actual_adev,
|
||||
struct auxiliary_device *adev);
|
||||
|
||||
int mlx5_sd_init(struct mlx5_core_dev *dev);
|
||||
void mlx5_sd_cleanup(struct mlx5_core_dev *dev);
|
||||
|
||||
@@ -826,7 +826,8 @@ struct net_device *fbnic_netdev_alloc(struct fbnic_dev *fbd)
|
||||
netif_tx_stop_all_queues(netdev);
|
||||
|
||||
if (fbnic_phylink_create(netdev)) {
|
||||
fbnic_netdev_free(fbd);
|
||||
free_netdev(netdev);
|
||||
fbd->netdev = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,11 +31,11 @@ enum spx5_target_chiptype {
|
||||
SPX5_TARGET_CT_7552 = 0x7552, /* SparX-5-128 Enterprise */
|
||||
SPX5_TARGET_CT_7556 = 0x7556, /* SparX-5-160 Enterprise */
|
||||
SPX5_TARGET_CT_7558 = 0x7558, /* SparX-5-200 Enterprise */
|
||||
SPX5_TARGET_CT_7546TSN = 0x47546, /* SparX-5-64i Industrial */
|
||||
SPX5_TARGET_CT_7549TSN = 0x47549, /* SparX-5-90i Industrial */
|
||||
SPX5_TARGET_CT_7552TSN = 0x47552, /* SparX-5-128i Industrial */
|
||||
SPX5_TARGET_CT_7556TSN = 0x47556, /* SparX-5-160i Industrial */
|
||||
SPX5_TARGET_CT_7558TSN = 0x47558, /* SparX-5-200i Industrial */
|
||||
SPX5_TARGET_CT_7546TSN = 0x0546, /* SparX-5-64i Industrial */
|
||||
SPX5_TARGET_CT_7549TSN = 0x0549, /* SparX-5-90i Industrial */
|
||||
SPX5_TARGET_CT_7552TSN = 0x0552, /* SparX-5-128i Industrial */
|
||||
SPX5_TARGET_CT_7556TSN = 0x0556, /* SparX-5-160i Industrial */
|
||||
SPX5_TARGET_CT_7558TSN = 0x0558, /* SparX-5-200i Industrial */
|
||||
SPX5_TARGET_CT_LAN9694 = 0x9694, /* lan969x-40 */
|
||||
SPX5_TARGET_CT_LAN9691VAO = 0x9691, /* lan969x-40-VAO */
|
||||
SPX5_TARGET_CT_LAN9694TSN = 0x9695, /* lan969x-40-TSN */
|
||||
|
||||
@@ -1128,7 +1128,8 @@ int sparx5_port_init(struct sparx5 *sparx5,
|
||||
DEV2G5_PCS1G_SD_CFG(port->portno));
|
||||
|
||||
if (conf->portmode == PHY_INTERFACE_MODE_QSGMII ||
|
||||
conf->portmode == PHY_INTERFACE_MODE_SGMII) {
|
||||
conf->portmode == PHY_INTERFACE_MODE_SGMII ||
|
||||
conf->portmode == PHY_INTERFACE_MODE_1000BASEX) {
|
||||
err = sparx5_serdes_set(sparx5, port, conf);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -43,8 +43,9 @@ static u64 mana_gd_r64(struct gdma_context *g, u64 offset)
|
||||
static int mana_gd_init_pf_regs(struct pci_dev *pdev)
|
||||
{
|
||||
struct gdma_context *gc = pci_get_drvdata(pdev);
|
||||
void __iomem *sriov_base_va;
|
||||
u64 remaining_barsize;
|
||||
u64 sriov_base_off;
|
||||
u64 sriov_shm_off;
|
||||
|
||||
gc->db_page_size = mana_gd_r32(gc, GDMA_PF_REG_DB_PAGE_SIZE) & 0xFFFF;
|
||||
|
||||
@@ -73,10 +74,28 @@ static int mana_gd_init_pf_regs(struct pci_dev *pdev)
|
||||
gc->phys_db_page_base = gc->bar0_pa + gc->db_page_off;
|
||||
|
||||
sriov_base_off = mana_gd_r64(gc, GDMA_SRIOV_REG_CFG_BASE_OFF);
|
||||
if (sriov_base_off >= gc->bar0_size ||
|
||||
gc->bar0_size - sriov_base_off <
|
||||
GDMA_PF_REG_SHM_OFF + sizeof(u64) ||
|
||||
!IS_ALIGNED(sriov_base_off, sizeof(u64))) {
|
||||
dev_err(gc->dev,
|
||||
"SRIOV base offset 0x%llx out of range or unaligned (BAR0 size 0x%llx)\n",
|
||||
sriov_base_off, (u64)gc->bar0_size);
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
sriov_base_va = gc->bar0_va + sriov_base_off;
|
||||
gc->shm_base = sriov_base_va +
|
||||
mana_gd_r64(gc, sriov_base_off + GDMA_PF_REG_SHM_OFF);
|
||||
remaining_barsize = gc->bar0_size - sriov_base_off;
|
||||
sriov_shm_off = mana_gd_r64(gc, sriov_base_off + GDMA_PF_REG_SHM_OFF);
|
||||
if (sriov_shm_off >= remaining_barsize ||
|
||||
remaining_barsize - sriov_shm_off < SMC_APERTURE_SIZE ||
|
||||
!IS_ALIGNED(sriov_shm_off, sizeof(u32))) {
|
||||
dev_err(gc->dev,
|
||||
"SRIOV SHM offset 0x%llx out of range or unaligned (BAR0 size 0x%llx)\n",
|
||||
sriov_shm_off, (u64)gc->bar0_size);
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
gc->shm_base = gc->bar0_va + sriov_base_off + sriov_shm_off;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -84,6 +103,7 @@ static int mana_gd_init_pf_regs(struct pci_dev *pdev)
|
||||
static int mana_gd_init_vf_regs(struct pci_dev *pdev)
|
||||
{
|
||||
struct gdma_context *gc = pci_get_drvdata(pdev);
|
||||
u64 shm_off;
|
||||
|
||||
gc->db_page_size = mana_gd_r32(gc, GDMA_REG_DB_PAGE_SIZE) & 0xFFFF;
|
||||
|
||||
@@ -111,7 +131,17 @@ static int mana_gd_init_vf_regs(struct pci_dev *pdev)
|
||||
gc->db_page_base = gc->bar0_va + gc->db_page_off;
|
||||
gc->phys_db_page_base = gc->bar0_pa + gc->db_page_off;
|
||||
|
||||
gc->shm_base = gc->bar0_va + mana_gd_r64(gc, GDMA_REG_SHM_OFFSET);
|
||||
shm_off = mana_gd_r64(gc, GDMA_REG_SHM_OFFSET);
|
||||
if (shm_off >= gc->bar0_size ||
|
||||
gc->bar0_size - shm_off < SMC_APERTURE_SIZE ||
|
||||
!IS_ALIGNED(shm_off, sizeof(u32))) {
|
||||
dev_err(gc->dev,
|
||||
"SHM offset 0x%llx out of range or unaligned (BAR0 size 0x%llx)\n",
|
||||
shm_off, (u64)gc->bar0_size);
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
gc->shm_base = gc->bar0_va + shm_off;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2520,9 +2520,12 @@ static void mana_destroy_rxq(struct mana_port_context *apc,
|
||||
napi_disable_locked(napi);
|
||||
netif_napi_del_locked(napi);
|
||||
}
|
||||
xdp_rxq_info_unreg(&rxq->xdp_rxq);
|
||||
|
||||
mana_destroy_wq_obj(apc, GDMA_RQ, rxq->rxobj);
|
||||
if (xdp_rxq_info_is_reg(&rxq->xdp_rxq))
|
||||
xdp_rxq_info_unreg(&rxq->xdp_rxq);
|
||||
|
||||
if (rxq->rxobj != INVALID_MANA_HANDLE)
|
||||
mana_destroy_wq_obj(apc, GDMA_RQ, rxq->rxobj);
|
||||
|
||||
mana_deinit_cq(apc, &rxq->rx_cq);
|
||||
|
||||
@@ -2796,9 +2799,6 @@ out:
|
||||
|
||||
mana_destroy_rxq(apc, rxq, false);
|
||||
|
||||
if (cq)
|
||||
mana_deinit_cq(apc, cq);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -61,11 +61,6 @@ union smc_proto_hdr {
|
||||
};
|
||||
}; /* HW DATA */
|
||||
|
||||
#define SMC_APERTURE_BITS 256
|
||||
#define SMC_BASIC_UNIT (sizeof(u32))
|
||||
#define SMC_APERTURE_DWORDS (SMC_APERTURE_BITS / (SMC_BASIC_UNIT * 8))
|
||||
#define SMC_LAST_DWORD (SMC_APERTURE_DWORDS - 1)
|
||||
|
||||
static int mana_smc_poll_register(void __iomem *base, bool reset)
|
||||
{
|
||||
void __iomem *ptr = base + SMC_LAST_DWORD * SMC_BASIC_UNIT;
|
||||
|
||||
@@ -797,11 +797,11 @@ static int rtsn_mdio_alloc(struct rtsn_private *priv)
|
||||
/* Enter config mode before registering the MDIO bus */
|
||||
ret = rtsn_reset(priv);
|
||||
if (ret)
|
||||
goto out_free_bus;
|
||||
goto out_put_node;
|
||||
|
||||
ret = rtsn_change_mode(priv, OCR_OPC_CONFIG);
|
||||
if (ret)
|
||||
goto out_free_bus;
|
||||
goto out_put_node;
|
||||
|
||||
rtsn_modify(priv, MPIC, MPIC_PSMCS_MASK | MPIC_PSMHT_MASK,
|
||||
MPIC_PSMCS_DEFAULT | MPIC_PSMHT_DEFAULT);
|
||||
@@ -824,6 +824,8 @@ static int rtsn_mdio_alloc(struct rtsn_private *priv)
|
||||
|
||||
return 0;
|
||||
|
||||
out_put_node:
|
||||
of_node_put(mdio_node);
|
||||
out_free_bus:
|
||||
mdiobus_free(mii);
|
||||
return ret;
|
||||
|
||||
@@ -100,6 +100,8 @@ static int nvt_gmac_probe(struct platform_device *pdev)
|
||||
if (!priv)
|
||||
return dev_err_probe(dev, -ENOMEM, "Failed to allocate private data\n");
|
||||
|
||||
priv->dev = dev;
|
||||
|
||||
priv->regmap = syscon_regmap_lookup_by_phandle_args(dev->of_node, "nuvoton,sys",
|
||||
1, &priv->macid);
|
||||
if (IS_ERR(priv->regmap))
|
||||
|
||||
@@ -2480,8 +2480,11 @@ int wx_sw_init(struct wx *wx)
|
||||
wx->oem_svid = pdev->subsystem_vendor;
|
||||
wx->oem_ssid = pdev->subsystem_device;
|
||||
wx->bus.device = PCI_SLOT(pdev->devfn);
|
||||
wx->bus.func = FIELD_GET(WX_CFG_PORT_ST_LANID,
|
||||
rd32(wx, WX_CFG_PORT_ST));
|
||||
if (pdev->is_virtfn)
|
||||
wx->bus.func = PCI_FUNC(pdev->devfn);
|
||||
else
|
||||
wx->bus.func = FIELD_GET(WX_CFG_PORT_ST_LANID,
|
||||
rd32(wx, WX_CFG_PORT_ST));
|
||||
|
||||
if (wx->oem_svid == PCI_VENDOR_ID_WANGXUN ||
|
||||
pdev->is_virtfn) {
|
||||
|
||||
@@ -99,8 +99,8 @@ int wx_request_msix_irqs_vf(struct wx *wx)
|
||||
}
|
||||
}
|
||||
|
||||
err = request_threaded_irq(wx->msix_entry->vector, wx_msix_misc_vf,
|
||||
NULL, IRQF_ONESHOT, netdev->name, wx);
|
||||
err = request_irq(wx->msix_entry->vector, wx_msix_misc_vf,
|
||||
0, netdev->name, wx);
|
||||
if (err) {
|
||||
wx_err(wx, "request_irq for msix_other failed: %d\n", err);
|
||||
goto free_queue_irqs;
|
||||
|
||||
@@ -1182,7 +1182,8 @@ void nsim_destroy(struct netdevsim *ns)
|
||||
unregister_netdevice_notifier_dev_net(ns->netdev, &ns->nb,
|
||||
&ns->nn);
|
||||
|
||||
nsim_psp_uninit(ns);
|
||||
if (nsim_dev_port_is_pf(ns->nsim_dev_port))
|
||||
nsim_psp_uninit(ns);
|
||||
|
||||
rtnl_lock();
|
||||
peer = rtnl_dereference(ns->peer);
|
||||
|
||||
@@ -120,7 +120,9 @@ struct netdevsim {
|
||||
u64_stats_t tx_packets;
|
||||
u64_stats_t tx_bytes;
|
||||
struct u64_stats_sync syncp;
|
||||
struct psp_dev *dev;
|
||||
struct psp_dev __rcu *dev;
|
||||
struct dentry *rereg;
|
||||
struct mutex rereg_lock;
|
||||
u32 spi;
|
||||
u32 assoc_cnt;
|
||||
} psp;
|
||||
|
||||
+46
-19
@@ -19,6 +19,7 @@ nsim_do_psp(struct sk_buff *skb, struct netdevsim *ns,
|
||||
struct netdevsim *peer_ns, struct skb_ext **psp_ext)
|
||||
{
|
||||
enum skb_drop_reason rc = 0;
|
||||
struct psp_dev *peer_psd;
|
||||
struct psp_assoc *pas;
|
||||
struct net *net;
|
||||
void **ptr;
|
||||
@@ -48,7 +49,8 @@ nsim_do_psp(struct sk_buff *skb, struct netdevsim *ns,
|
||||
}
|
||||
|
||||
/* Now pretend we just received this frame */
|
||||
if (peer_ns->psp.dev->config.versions & (1 << pas->version)) {
|
||||
peer_psd = rcu_dereference(peer_ns->psp.dev);
|
||||
if (peer_psd && peer_psd->config.versions & (1 << pas->version)) {
|
||||
bool strip_icv = false;
|
||||
u8 generation;
|
||||
|
||||
@@ -61,8 +63,7 @@ nsim_do_psp(struct sk_buff *skb, struct netdevsim *ns,
|
||||
|
||||
skb_ext_reset(skb);
|
||||
skb->mac_len = ETH_HLEN;
|
||||
if (psp_dev_rcv(skb, peer_ns->psp.dev->id, generation,
|
||||
strip_icv)) {
|
||||
if (psp_dev_rcv(skb, peer_psd->id, generation, strip_icv)) {
|
||||
rc = SKB_DROP_REASON_PSP_OUTPUT;
|
||||
goto out_unlock;
|
||||
}
|
||||
@@ -209,11 +210,26 @@ static struct psp_dev_caps nsim_psp_caps = {
|
||||
.assoc_drv_spc = sizeof(void *),
|
||||
};
|
||||
|
||||
static void __nsim_psp_uninit(struct netdevsim *ns, bool teardown)
|
||||
{
|
||||
struct psp_dev *psd;
|
||||
|
||||
psd = rcu_dereference_protected(ns->psp.dev,
|
||||
teardown ||
|
||||
lockdep_is_held(&ns->psp.rereg_lock));
|
||||
if (psd) {
|
||||
rcu_assign_pointer(ns->psp.dev, NULL);
|
||||
synchronize_rcu();
|
||||
psp_dev_unregister(psd);
|
||||
}
|
||||
WARN_ON(ns->psp.assoc_cnt);
|
||||
}
|
||||
|
||||
void nsim_psp_uninit(struct netdevsim *ns)
|
||||
{
|
||||
if (!IS_ERR(ns->psp.dev))
|
||||
psp_dev_unregister(ns->psp.dev);
|
||||
WARN_ON(ns->psp.assoc_cnt);
|
||||
debugfs_remove(ns->psp.rereg);
|
||||
mutex_destroy(&ns->psp.rereg_lock);
|
||||
__nsim_psp_uninit(ns, true);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
@@ -221,14 +237,23 @@ nsim_psp_rereg_write(struct file *file, const char __user *data, size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct netdevsim *ns = file->private_data;
|
||||
int err;
|
||||
struct psp_dev *psd;
|
||||
ssize_t ret;
|
||||
|
||||
nsim_psp_uninit(ns);
|
||||
mutex_lock(&ns->psp.rereg_lock);
|
||||
__nsim_psp_uninit(ns, false);
|
||||
|
||||
ns->psp.dev = psp_dev_create(ns->netdev, &nsim_psp_ops,
|
||||
&nsim_psp_caps, ns);
|
||||
err = PTR_ERR_OR_ZERO(ns->psp.dev);
|
||||
return err ?: count;
|
||||
psd = psp_dev_create(ns->netdev, &nsim_psp_ops, &nsim_psp_caps, ns);
|
||||
if (IS_ERR(psd)) {
|
||||
ret = PTR_ERR(psd);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rcu_assign_pointer(ns->psp.dev, psd);
|
||||
ret = count;
|
||||
out:
|
||||
mutex_unlock(&ns->psp.rereg_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct file_operations nsim_psp_rereg_fops = {
|
||||
@@ -241,14 +266,16 @@ static const struct file_operations nsim_psp_rereg_fops = {
|
||||
int nsim_psp_init(struct netdevsim *ns)
|
||||
{
|
||||
struct dentry *ddir = ns->nsim_dev_port->ddir;
|
||||
int err;
|
||||
struct psp_dev *psd;
|
||||
|
||||
ns->psp.dev = psp_dev_create(ns->netdev, &nsim_psp_ops,
|
||||
&nsim_psp_caps, ns);
|
||||
err = PTR_ERR_OR_ZERO(ns->psp.dev);
|
||||
if (err)
|
||||
return err;
|
||||
psd = psp_dev_create(ns->netdev, &nsim_psp_ops, &nsim_psp_caps, ns);
|
||||
if (IS_ERR(psd))
|
||||
return PTR_ERR(psd);
|
||||
|
||||
debugfs_create_file("psp_rereg", 0200, ddir, ns, &nsim_psp_rereg_fops);
|
||||
rcu_assign_pointer(ns->psp.dev, psd);
|
||||
|
||||
mutex_init(&ns->psp.rereg_lock);
|
||||
ns->psp.rereg = debugfs_create_file("psp_rereg", 0200, ddir, ns,
|
||||
&nsim_psp_rereg_fops);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -85,17 +85,24 @@ static void ovpn_netdev_write(struct ovpn_peer *peer, struct sk_buff *skb)
|
||||
skb_scrub_packet(skb, true);
|
||||
|
||||
/* network header reset in ovpn_decrypt_post() */
|
||||
skb_reset_mac_header(skb);
|
||||
skb_reset_transport_header(skb);
|
||||
skb_reset_inner_headers(skb);
|
||||
|
||||
/* cause packet to be "received" by the interface */
|
||||
pkt_len = skb->len;
|
||||
/* we may get here in process context in case of TCP connections,
|
||||
* therefore we have to disable BHs to ensure gro_cells_receive()
|
||||
* and dev_dstats_rx_add() do not get corrupted or enter deadlock
|
||||
*/
|
||||
local_bh_disable();
|
||||
ret = gro_cells_receive(&peer->ovpn->gro_cells, skb);
|
||||
if (likely(ret == NET_RX_SUCCESS)) {
|
||||
/* update RX stats with the size of decrypted packet */
|
||||
ovpn_peer_stats_increment_rx(&peer->vpn_stats, pkt_len);
|
||||
dev_dstats_rx_add(peer->ovpn->dev, pkt_len);
|
||||
}
|
||||
local_bh_enable();
|
||||
}
|
||||
|
||||
void ovpn_decrypt_post(void *data, int ret)
|
||||
|
||||
@@ -563,6 +563,15 @@ void bcm_phy_get_stats(struct phy_device *phydev, u64 *shadow,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bcm_phy_get_stats);
|
||||
|
||||
void bcm_phy_update_stats_shadow(struct phy_device *phydev, u64 *shadow)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bcm_phy_hw_stats); i++)
|
||||
bcm_phy_get_stat(phydev, shadow, i);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bcm_phy_update_stats_shadow);
|
||||
|
||||
void bcm_phy_r_rc_cal_reset(struct phy_device *phydev)
|
||||
{
|
||||
/* Reset R_CAL/RC_CAL Engine */
|
||||
|
||||
@@ -85,6 +85,7 @@ int bcm_phy_get_sset_count(struct phy_device *phydev);
|
||||
void bcm_phy_get_strings(struct phy_device *phydev, u8 *data);
|
||||
void bcm_phy_get_stats(struct phy_device *phydev, u64 *shadow,
|
||||
struct ethtool_stats *stats, u64 *data);
|
||||
void bcm_phy_update_stats_shadow(struct phy_device *phydev, u64 *shadow);
|
||||
void bcm_phy_r_rc_cal_reset(struct phy_device *phydev);
|
||||
int bcm_phy_28nm_a0b0_afe_config_init(struct phy_device *phydev);
|
||||
int bcm_phy_enable_jumbo(struct phy_device *phydev);
|
||||
|
||||
@@ -807,6 +807,17 @@ static void bcm7xxx_28nm_get_phy_stats(struct phy_device *phydev,
|
||||
bcm_phy_get_stats(phydev, priv->stats, stats, data);
|
||||
}
|
||||
|
||||
static int bcm7xxx_28nm_suspend(struct phy_device *phydev)
|
||||
{
|
||||
struct bcm7xxx_phy_priv *priv = phydev->priv;
|
||||
|
||||
mutex_lock(&phydev->lock);
|
||||
bcm_phy_update_stats_shadow(phydev, priv->stats);
|
||||
mutex_unlock(&phydev->lock);
|
||||
|
||||
return genphy_suspend(phydev);
|
||||
}
|
||||
|
||||
static int bcm7xxx_28nm_probe(struct phy_device *phydev)
|
||||
{
|
||||
struct bcm7xxx_phy_priv *priv;
|
||||
@@ -849,6 +860,7 @@ static int bcm7xxx_28nm_probe(struct phy_device *phydev)
|
||||
.flags = PHY_IS_INTERNAL, \
|
||||
.config_init = bcm7xxx_28nm_config_init, \
|
||||
.resume = bcm7xxx_28nm_resume, \
|
||||
.suspend = bcm7xxx_28nm_suspend, \
|
||||
.get_tunable = bcm7xxx_28nm_get_tunable, \
|
||||
.set_tunable = bcm7xxx_28nm_set_tunable, \
|
||||
.get_sset_count = bcm_phy_get_sset_count, \
|
||||
@@ -866,6 +878,7 @@ static int bcm7xxx_28nm_probe(struct phy_device *phydev)
|
||||
.flags = PHY_IS_INTERNAL, \
|
||||
.config_init = bcm7xxx_28nm_ephy_config_init, \
|
||||
.resume = bcm7xxx_28nm_ephy_resume, \
|
||||
.suspend = bcm7xxx_28nm_suspend, \
|
||||
.get_sset_count = bcm_phy_get_sset_count, \
|
||||
.get_strings = bcm_phy_get_strings, \
|
||||
.get_stats = bcm7xxx_28nm_get_phy_stats, \
|
||||
@@ -902,6 +915,7 @@ static int bcm7xxx_28nm_probe(struct phy_device *phydev)
|
||||
.config_aneg = genphy_config_aneg, \
|
||||
.read_status = genphy_read_status, \
|
||||
.resume = bcm7xxx_16nm_ephy_resume, \
|
||||
.suspend = bcm7xxx_28nm_suspend, \
|
||||
}
|
||||
|
||||
static struct phy_driver bcm7xxx_driver[] = {
|
||||
|
||||
@@ -592,8 +592,13 @@ static int bcm54xx_set_wakeup_irq(struct phy_device *phydev, bool state)
|
||||
|
||||
static int bcm54xx_suspend(struct phy_device *phydev)
|
||||
{
|
||||
struct bcm54xx_phy_priv *priv = phydev->priv;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&phydev->lock);
|
||||
bcm_phy_update_stats_shadow(phydev, priv->stats);
|
||||
mutex_unlock(&phydev->lock);
|
||||
|
||||
bcm54xx_ptp_stop(phydev);
|
||||
|
||||
/* Acknowledge any Wake-on-LAN interrupt prior to suspend */
|
||||
|
||||
@@ -4548,6 +4548,13 @@ static int lan8814_config_init(struct phy_device *phydev)
|
||||
struct kszphy_priv *lan8814 = phydev->priv;
|
||||
int ret;
|
||||
|
||||
if (phy_package_init_once(phydev))
|
||||
/* Reset the PHY */
|
||||
lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS,
|
||||
LAN8814_QSGMII_SOFT_RESET,
|
||||
LAN8814_QSGMII_SOFT_RESET_BIT,
|
||||
LAN8814_QSGMII_SOFT_RESET_BIT);
|
||||
|
||||
/* Based on the interface type select how the advertise ability is
|
||||
* encoded, to set as SGMII or as USGMII.
|
||||
*/
|
||||
@@ -4655,13 +4662,7 @@ static int lan8814_probe(struct phy_device *phydev)
|
||||
priv->is_ptp_available = err == LAN8814_REV_LAN8814 ||
|
||||
err == LAN8814_REV_LAN8818;
|
||||
|
||||
if (phy_package_init_once(phydev)) {
|
||||
/* Reset the PHY */
|
||||
lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS,
|
||||
LAN8814_QSGMII_SOFT_RESET,
|
||||
LAN8814_QSGMII_SOFT_RESET_BIT,
|
||||
LAN8814_QSGMII_SOFT_RESET_BIT);
|
||||
|
||||
if (phy_package_probe_once(phydev)) {
|
||||
err = lan8814_release_coma_mode(phydev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -756,6 +756,7 @@ static void ax88772_mac_link_down(struct phylink_config *config,
|
||||
struct usbnet *dev = netdev_priv(to_net_dev(config->dev));
|
||||
|
||||
asix_write_medium_mode(dev, 0, 0);
|
||||
usbnet_link_change(dev, false, false);
|
||||
}
|
||||
|
||||
static void ax88772_mac_link_up(struct phylink_config *config,
|
||||
@@ -786,6 +787,7 @@ static void ax88772_mac_link_up(struct phylink_config *config,
|
||||
m |= AX_MEDIUM_RFC;
|
||||
|
||||
asix_write_medium_mode(dev, m, 0);
|
||||
usbnet_link_change(dev, true, false);
|
||||
}
|
||||
|
||||
static const struct phylink_mac_ops ax88772_phylink_mac_ops = {
|
||||
|
||||
@@ -2012,6 +2012,14 @@ static const struct usb_device_id cdc_devs[] = {
|
||||
.driver_info = (unsigned long)&apple_private_interface_info,
|
||||
},
|
||||
|
||||
/* Mac */
|
||||
{ USB_DEVICE_INTERFACE_NUMBER(0x05ac, 0x1905, 0),
|
||||
.driver_info = (unsigned long)&apple_private_interface_info,
|
||||
},
|
||||
{ USB_DEVICE_INTERFACE_NUMBER(0x05ac, 0x1905, 2),
|
||||
.driver_info = (unsigned long)&apple_private_interface_info,
|
||||
},
|
||||
|
||||
/* Ericsson MBM devices like F5521gw */
|
||||
{ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
|
||||
| USB_DEVICE_ID_MATCH_VENDOR,
|
||||
|
||||
@@ -10138,6 +10138,7 @@ static const struct usb_device_id rtl8152_table[] = {
|
||||
{ USB_DEVICE(VENDOR_ID_DELL, 0xb097) },
|
||||
{ USB_DEVICE(VENDOR_ID_ASUS, 0x1976) },
|
||||
{ USB_DEVICE(VENDOR_ID_TRENDNET, 0xe02b) },
|
||||
{ USB_DEVICE(VENDOR_ID_TRENDNET, 0xe02c) },
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
+2
-1
@@ -972,7 +972,8 @@ static int veth_poll(struct napi_struct *napi, int budget)
|
||||
|
||||
/* NAPI functions as RCU section */
|
||||
peer_dev = rcu_dereference_check(priv->peer, rcu_read_lock_bh_held());
|
||||
peer_txq = peer_dev ? netdev_get_tx_queue(peer_dev, queue_idx) : NULL;
|
||||
peer_txq = (peer_dev && queue_idx < peer_dev->real_num_tx_queues) ?
|
||||
netdev_get_tx_queue(peer_dev, queue_idx) : NULL;
|
||||
|
||||
xdp_set_return_frame_no_direct();
|
||||
done = veth_xdp_rcv(rq, budget, &bq, &stats);
|
||||
|
||||
@@ -773,11 +773,6 @@ static void uhdlc_memclean(struct ucc_hdlc_private *priv)
|
||||
kfree(priv->tx_skbuff);
|
||||
priv->tx_skbuff = NULL;
|
||||
|
||||
if (priv->uf_regs) {
|
||||
iounmap(priv->uf_regs);
|
||||
priv->uf_regs = NULL;
|
||||
}
|
||||
|
||||
if (priv->uccf) {
|
||||
ucc_fast_free(priv->uccf);
|
||||
priv->uccf = NULL;
|
||||
@@ -1255,12 +1250,12 @@ static void ucc_hdlc_remove(struct platform_device *pdev)
|
||||
|
||||
uhdlc_memclean(priv);
|
||||
|
||||
if (priv->utdm->si_regs) {
|
||||
if (priv->utdm && priv->utdm->si_regs) {
|
||||
iounmap(priv->utdm->si_regs);
|
||||
priv->utdm->si_regs = NULL;
|
||||
}
|
||||
|
||||
if (priv->utdm->siram) {
|
||||
if (priv->utdm && priv->utdm->siram) {
|
||||
iounmap(priv->utdm->siram);
|
||||
priv->utdm->siram = NULL;
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ config ATH10K_SNOC
|
||||
depends on ARCH_QCOM || COMPILE_TEST
|
||||
depends on QCOM_SMEM
|
||||
depends on QCOM_RPROC_COMMON || QCOM_RPROC_COMMON=n
|
||||
select POWER_SEQUENCING
|
||||
select QCOM_SCM
|
||||
select QCOM_QMI_HELPERS
|
||||
help
|
||||
|
||||
@@ -1838,10 +1838,22 @@ static struct ath12k_hw_group *ath12k_core_hw_group_alloc(struct ath12k_base *ab
|
||||
return ag;
|
||||
}
|
||||
|
||||
static void ath12k_core_free_wsi_info(struct ath12k_hw_group *ag)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ag->num_devices; i++) {
|
||||
of_node_put(ag->wsi_node[i]);
|
||||
ag->wsi_node[i] = NULL;
|
||||
}
|
||||
ag->num_devices = 0;
|
||||
}
|
||||
|
||||
static void ath12k_core_hw_group_free(struct ath12k_hw_group *ag)
|
||||
{
|
||||
mutex_lock(&ath12k_hw_group_mutex);
|
||||
|
||||
ath12k_core_free_wsi_info(ag);
|
||||
list_del(&ag->list);
|
||||
kfree(ag);
|
||||
|
||||
@@ -1867,52 +1879,59 @@ static struct ath12k_hw_group *ath12k_core_hw_group_find_by_dt(struct ath12k_bas
|
||||
static int ath12k_core_get_wsi_info(struct ath12k_hw_group *ag,
|
||||
struct ath12k_base *ab)
|
||||
{
|
||||
struct device_node *wsi_dev = ab->dev->of_node, *next_wsi_dev;
|
||||
struct device_node *tx_endpoint, *next_rx_endpoint;
|
||||
int device_count = 0;
|
||||
struct device_node *next_wsi_dev;
|
||||
int device_count = 0, ret = 0;
|
||||
struct device_node *wsi_dev;
|
||||
|
||||
next_wsi_dev = wsi_dev;
|
||||
|
||||
if (!next_wsi_dev)
|
||||
wsi_dev = of_node_get(ab->dev->of_node);
|
||||
if (!wsi_dev)
|
||||
return -ENODEV;
|
||||
|
||||
do {
|
||||
ag->wsi_node[device_count] = next_wsi_dev;
|
||||
if (device_count >= ATH12K_MAX_DEVICES) {
|
||||
ath12k_warn(ab, "device count in DT %d is more than limit %d\n",
|
||||
device_count, ATH12K_MAX_DEVICES);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
tx_endpoint = of_graph_get_endpoint_by_regs(next_wsi_dev, 0, -1);
|
||||
ag->wsi_node[device_count++] = of_node_get(wsi_dev);
|
||||
|
||||
struct device_node *tx_endpoint __free(device_node) =
|
||||
of_graph_get_endpoint_by_regs(wsi_dev, 0, -1);
|
||||
if (!tx_endpoint) {
|
||||
of_node_put(next_wsi_dev);
|
||||
return -ENODEV;
|
||||
ret = -ENODEV;
|
||||
break;
|
||||
}
|
||||
|
||||
next_rx_endpoint = of_graph_get_remote_endpoint(tx_endpoint);
|
||||
struct device_node *next_rx_endpoint __free(device_node) =
|
||||
of_graph_get_remote_endpoint(tx_endpoint);
|
||||
if (!next_rx_endpoint) {
|
||||
of_node_put(next_wsi_dev);
|
||||
of_node_put(tx_endpoint);
|
||||
return -ENODEV;
|
||||
ret = -ENODEV;
|
||||
break;
|
||||
}
|
||||
|
||||
of_node_put(tx_endpoint);
|
||||
of_node_put(next_wsi_dev);
|
||||
|
||||
next_wsi_dev = of_graph_get_port_parent(next_rx_endpoint);
|
||||
if (!next_wsi_dev) {
|
||||
of_node_put(next_rx_endpoint);
|
||||
return -ENODEV;
|
||||
ret = -ENODEV;
|
||||
break;
|
||||
}
|
||||
|
||||
of_node_put(next_rx_endpoint);
|
||||
of_node_put(wsi_dev);
|
||||
wsi_dev = next_wsi_dev;
|
||||
} while (ab->dev->of_node != wsi_dev);
|
||||
|
||||
device_count++;
|
||||
if (device_count > ATH12K_MAX_DEVICES) {
|
||||
ath12k_warn(ab, "device count in DT %d is more than limit %d\n",
|
||||
device_count, ATH12K_MAX_DEVICES);
|
||||
of_node_put(next_wsi_dev);
|
||||
return -EINVAL;
|
||||
if (ret) {
|
||||
while (--device_count >= 0) {
|
||||
of_node_put(ag->wsi_node[device_count]);
|
||||
ag->wsi_node[device_count] = NULL;
|
||||
}
|
||||
} while (wsi_dev != next_wsi_dev);
|
||||
|
||||
of_node_put(next_wsi_dev);
|
||||
of_node_put(wsi_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
of_node_put(wsi_dev);
|
||||
ag->num_devices = device_count;
|
||||
|
||||
return 0;
|
||||
@@ -1983,9 +2002,9 @@ static struct ath12k_hw_group *ath12k_core_hw_group_assign(struct ath12k_base *a
|
||||
ath12k_core_get_wsi_index(ag, ab)) {
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT,
|
||||
"unable to get wsi info from dt, grouping single device");
|
||||
ath12k_core_free_wsi_info(ag);
|
||||
ag->id = ATH12K_INVALID_GROUP_ID;
|
||||
ag->num_devices = 1;
|
||||
memset(ag->wsi_node, 0, sizeof(ag->wsi_node));
|
||||
wsi->index = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -565,6 +565,9 @@ static int ath12k_dp_prepare_reo_update_elem(struct ath12k_dp *dp,
|
||||
|
||||
lockdep_assert_held(&dp->dp_lock);
|
||||
|
||||
if (!peer->primary_link)
|
||||
return 0;
|
||||
|
||||
elem = kzalloc_obj(*elem, GFP_ATOMIC);
|
||||
if (!elem)
|
||||
return -ENOMEM;
|
||||
@@ -1337,7 +1340,7 @@ void ath12k_dp_rx_deliver_msdu(struct ath12k_pdev_dp *dp_pdev, struct napi_struc
|
||||
bool is_mcbc = rxcb->is_mcbc;
|
||||
bool is_eapol = rxcb->is_eapol;
|
||||
|
||||
peer = ath12k_dp_peer_find_by_peerid(dp_pdev, rx_info->peer_id);
|
||||
peer = ath12k_dp_peer_find_by_peerid(dp_pdev, rxcb->peer_id);
|
||||
|
||||
pubsta = peer ? peer->sta : NULL;
|
||||
|
||||
|
||||
@@ -788,7 +788,7 @@ struct ath12k_link_vif *ath12k_mac_get_arvif(struct ath12k *ar, u32 vdev_id)
|
||||
|
||||
/* To use the arvif returned, caller must have held rcu read lock.
|
||||
*/
|
||||
WARN_ON(!rcu_read_lock_any_held());
|
||||
lockdep_assert_in_rcu_read_lock();
|
||||
arvif_iter.vdev_id = vdev_id;
|
||||
arvif_iter.ar = ar;
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ static void ath12k_p2p_noa_update_vdev_iter(void *data, u8 *mac,
|
||||
struct ath12k_p2p_noa_arg *arg = data;
|
||||
struct ath12k_link_vif *arvif;
|
||||
|
||||
WARN_ON(!rcu_read_lock_any_held());
|
||||
lockdep_assert_in_rcu_read_lock();
|
||||
arvif = &ahvif->deflink;
|
||||
if (!arvif->is_created || arvif->ar != arg->ar || arvif->vdev_id != arg->vdev_id)
|
||||
return;
|
||||
|
||||
@@ -9778,7 +9778,7 @@ static void
|
||||
ath12k_wmi_rssi_dbm_conversion_params_info_event(struct ath12k_base *ab,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ath12k_wmi_rssi_dbm_conv_info_arg rssi_info;
|
||||
struct ath12k_wmi_rssi_dbm_conv_info_arg rssi_info = {};
|
||||
struct ath12k *ar;
|
||||
s32 noise_floor;
|
||||
u32 pdev_id;
|
||||
@@ -10251,7 +10251,7 @@ int ath12k_wmi_hw_data_filter_cmd(struct ath12k *ar, struct wmi_hw_data_filter_a
|
||||
{
|
||||
struct wmi_hw_data_filter_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
int len;
|
||||
int ret, len;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
@@ -10275,7 +10275,13 @@ int ath12k_wmi_hw_data_filter_cmd(struct ath12k *ar, struct wmi_hw_data_filter_a
|
||||
"wmi hw data filter enable %d filter_bitmap 0x%x\n",
|
||||
arg->enable, arg->hw_filter_bitmap);
|
||||
|
||||
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_HW_DATA_FILTER_CMDID);
|
||||
ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_HW_DATA_FILTER_CMDID);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to send WMI_HW_DATA_FILTER_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath12k_wmi_wow_host_wakeup_ind(struct ath12k *ar)
|
||||
@@ -10283,6 +10289,7 @@ int ath12k_wmi_wow_host_wakeup_ind(struct ath12k *ar)
|
||||
struct wmi_wow_host_wakeup_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
@@ -10295,14 +10302,20 @@ int ath12k_wmi_wow_host_wakeup_ind(struct ath12k *ar)
|
||||
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "wmi tlv wow host wakeup ind\n");
|
||||
|
||||
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID);
|
||||
ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to send WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath12k_wmi_wow_enable(struct ath12k *ar)
|
||||
{
|
||||
struct wmi_wow_enable_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
int len;
|
||||
int ret, len;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
@@ -10317,7 +10330,13 @@ int ath12k_wmi_wow_enable(struct ath12k *ar)
|
||||
cmd->pause_iface_config = cpu_to_le32(WOW_IFACE_PAUSE_ENABLED);
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "wmi tlv wow enable\n");
|
||||
|
||||
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ENABLE_CMDID);
|
||||
ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ENABLE_CMDID);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to send WMI_WOW_ENABLE_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath12k_wmi_wow_add_wakeup_event(struct ath12k *ar, u32 vdev_id,
|
||||
@@ -10327,6 +10346,7 @@ int ath12k_wmi_wow_add_wakeup_event(struct ath12k *ar, u32 vdev_id,
|
||||
struct wmi_wow_add_del_event_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
@@ -10343,7 +10363,13 @@ int ath12k_wmi_wow_add_wakeup_event(struct ath12k *ar, u32 vdev_id,
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "wmi tlv wow add wakeup event %s enable %d vdev_id %d\n",
|
||||
wow_wakeup_event(event), enable, vdev_id);
|
||||
|
||||
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID);
|
||||
ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to send WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath12k_wmi_wow_add_pattern(struct ath12k *ar, u32 vdev_id, u32 pattern_id,
|
||||
@@ -10356,6 +10382,7 @@ int ath12k_wmi_wow_add_pattern(struct ath12k *ar, u32 vdev_id, u32 pattern_id,
|
||||
struct sk_buff *skb;
|
||||
void *ptr;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
len = sizeof(*cmd) +
|
||||
sizeof(*tlv) + /* array struct */
|
||||
@@ -10435,7 +10462,13 @@ int ath12k_wmi_wow_add_pattern(struct ath12k *ar, u32 vdev_id, u32 pattern_id,
|
||||
ath12k_dbg_dump(ar->ab, ATH12K_DBG_WMI, NULL, "wow bitmask: ",
|
||||
bitmap->bitmaskbuf, pattern_len);
|
||||
|
||||
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ADD_WAKE_PATTERN_CMDID);
|
||||
ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ADD_WAKE_PATTERN_CMDID);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to send WMI_WOW_ADD_WAKE_PATTERN_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath12k_wmi_wow_del_pattern(struct ath12k *ar, u32 vdev_id, u32 pattern_id)
|
||||
@@ -10443,6 +10476,7 @@ int ath12k_wmi_wow_del_pattern(struct ath12k *ar, u32 vdev_id, u32 pattern_id)
|
||||
struct wmi_wow_del_pattern_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
@@ -10459,7 +10493,13 @@ int ath12k_wmi_wow_del_pattern(struct ath12k *ar, u32 vdev_id, u32 pattern_id)
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "wmi tlv wow del pattern vdev_id %d pattern_id %d\n",
|
||||
vdev_id, pattern_id);
|
||||
|
||||
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_DEL_WAKE_PATTERN_CMDID);
|
||||
ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_DEL_WAKE_PATTERN_CMDID);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to send WMI_WOW_DEL_WAKE_PATTERN_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct sk_buff *
|
||||
@@ -10595,6 +10635,7 @@ int ath12k_wmi_wow_config_pno(struct ath12k *ar, u32 vdev_id,
|
||||
struct wmi_pno_scan_req_arg *pno_scan)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
int ret;
|
||||
|
||||
if (pno_scan->enable)
|
||||
skb = ath12k_wmi_op_gen_config_pno_start(ar, vdev_id, pno_scan);
|
||||
@@ -10604,7 +10645,13 @@ int ath12k_wmi_wow_config_pno(struct ath12k *ar, u32 vdev_id,
|
||||
if (IS_ERR_OR_NULL(skb))
|
||||
return -ENOMEM;
|
||||
|
||||
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID);
|
||||
ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to send WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath12k_wmi_fill_ns_offload(struct ath12k *ar,
|
||||
@@ -10717,6 +10764,7 @@ int ath12k_wmi_arp_ns_offload(struct ath12k *ar,
|
||||
void *buf_ptr;
|
||||
size_t len;
|
||||
u8 ns_cnt, ns_ext_tuples = 0;
|
||||
int ret;
|
||||
|
||||
ns_cnt = offload->ipv6_count;
|
||||
|
||||
@@ -10752,7 +10800,13 @@ int ath12k_wmi_arp_ns_offload(struct ath12k *ar,
|
||||
if (ns_ext_tuples)
|
||||
ath12k_wmi_fill_ns_offload(ar, offload, &buf_ptr, enable, 1);
|
||||
|
||||
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_SET_ARP_NS_OFFLOAD_CMDID);
|
||||
ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_SET_ARP_NS_OFFLOAD_CMDID);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to send WMI_SET_ARP_NS_OFFLOAD_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath12k_wmi_gtk_rekey_offload(struct ath12k *ar,
|
||||
@@ -10762,7 +10816,7 @@ int ath12k_wmi_gtk_rekey_offload(struct ath12k *ar,
|
||||
struct wmi_gtk_rekey_offload_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
__le64 replay_ctr;
|
||||
int len;
|
||||
int ret, len;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
@@ -10789,7 +10843,13 @@ int ath12k_wmi_gtk_rekey_offload(struct ath12k *ar,
|
||||
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "offload gtk rekey vdev: %d %d\n",
|
||||
arvif->vdev_id, enable);
|
||||
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_GTK_OFFLOAD_CMDID);
|
||||
ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_GTK_OFFLOAD_CMDID);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to send WMI_GTK_OFFLOAD_CMDID offload\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath12k_wmi_gtk_rekey_getinfo(struct ath12k *ar,
|
||||
@@ -10797,7 +10857,7 @@ int ath12k_wmi_gtk_rekey_getinfo(struct ath12k *ar,
|
||||
{
|
||||
struct wmi_gtk_rekey_offload_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
int len;
|
||||
int ret, len;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
@@ -10811,7 +10871,13 @@ int ath12k_wmi_gtk_rekey_getinfo(struct ath12k *ar,
|
||||
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "get gtk rekey vdev_id: %d\n",
|
||||
arvif->vdev_id);
|
||||
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_GTK_OFFLOAD_CMDID);
|
||||
ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_GTK_OFFLOAD_CMDID);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to send WMI_GTK_OFFLOAD_CMDID getinfo\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath12k_wmi_sta_keepalive(struct ath12k *ar,
|
||||
@@ -10822,6 +10888,7 @@ int ath12k_wmi_sta_keepalive(struct ath12k *ar,
|
||||
struct wmi_sta_keepalive_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
len = sizeof(*cmd) + sizeof(*arp);
|
||||
skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);
|
||||
@@ -10849,7 +10916,13 @@ int ath12k_wmi_sta_keepalive(struct ath12k *ar,
|
||||
"wmi sta keepalive vdev %d enabled %d method %d interval %d\n",
|
||||
arg->vdev_id, arg->enabled, arg->method, arg->interval);
|
||||
|
||||
return ath12k_wmi_cmd_send(wmi, skb, WMI_STA_KEEPALIVE_CMDID);
|
||||
ret = ath12k_wmi_cmd_send(wmi, skb, WMI_STA_KEEPALIVE_CMDID);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to send WMI_STA_KEEPALIVE_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath12k_wmi_mlo_setup(struct ath12k *ar, struct wmi_mlo_setup_arg *mlo_params)
|
||||
|
||||
@@ -1738,7 +1738,8 @@ ath5k_tx_frame_completed(struct ath5k_hw *ah, struct sk_buff *skb,
|
||||
}
|
||||
|
||||
info->status.rates[ts->ts_final_idx].count = ts->ts_final_retry;
|
||||
info->status.rates[ts->ts_final_idx + 1].idx = -1;
|
||||
if (ts->ts_final_idx + 1 < IEEE80211_TX_MAX_RATES)
|
||||
info->status.rates[ts->ts_final_idx + 1].idx = -1;
|
||||
|
||||
if (unlikely(ts->ts_status)) {
|
||||
ah->stats.ack_fail++;
|
||||
|
||||
@@ -702,7 +702,8 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
|
||||
* key index, but the ucode passed it slightly different.
|
||||
*/
|
||||
keyidx = b43_kidx_to_raw(dev, keyidx);
|
||||
B43_WARN_ON(keyidx >= ARRAY_SIZE(dev->key));
|
||||
if (B43_WARN_ON(keyidx >= ARRAY_SIZE(dev->key)))
|
||||
goto drop;
|
||||
|
||||
if (dev->key[keyidx].algorithm != B43_SEC_ALGO_NONE) {
|
||||
wlhdr_len = ieee80211_hdrlen(fctl);
|
||||
|
||||
@@ -476,7 +476,8 @@ void b43legacy_rx(struct b43legacy_wldev *dev,
|
||||
* key index, but the ucode passed it slightly different.
|
||||
*/
|
||||
keyidx = b43legacy_kidx_to_raw(dev, keyidx);
|
||||
B43legacy_WARN_ON(keyidx >= dev->max_nr_keys);
|
||||
if (B43legacy_WARN_ON(keyidx >= dev->max_nr_keys))
|
||||
goto drop;
|
||||
|
||||
if (dev->key[keyidx].algorithm != B43legacy_SEC_ALGO_NONE) {
|
||||
/* Remove PROTECTED flag to mark it as decrypted. */
|
||||
|
||||
@@ -2476,8 +2476,9 @@ static void brcmf_sdio_bus_stop(struct device *dev)
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
if (bus->watchdog_tsk) {
|
||||
get_task_struct(bus->watchdog_tsk);
|
||||
send_sig(SIGTERM, bus->watchdog_tsk, 1);
|
||||
kthread_stop(bus->watchdog_tsk);
|
||||
kthread_stop_put(bus->watchdog_tsk);
|
||||
bus->watchdog_tsk = NULL;
|
||||
}
|
||||
|
||||
@@ -4567,8 +4568,9 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus)
|
||||
if (bus) {
|
||||
/* Stop watchdog task */
|
||||
if (bus->watchdog_tsk) {
|
||||
get_task_struct(bus->watchdog_tsk);
|
||||
send_sig(SIGTERM, bus->watchdog_tsk, 1);
|
||||
kthread_stop(bus->watchdog_tsk);
|
||||
kthread_stop_put(bus->watchdog_tsk);
|
||||
bus->watchdog_tsk = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -310,6 +310,7 @@ static void if_usb_disconnect(struct usb_interface *intf)
|
||||
struct lbs_private *priv = cardp->priv;
|
||||
|
||||
cardp->surprise_removed = 1;
|
||||
wake_up(&cardp->fw_wq);
|
||||
|
||||
if (priv) {
|
||||
lbs_stop_card(priv);
|
||||
@@ -633,9 +634,10 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff,
|
||||
unsigned long flags;
|
||||
u8 i;
|
||||
|
||||
if (recvlength > LBS_CMD_BUFFER_SIZE) {
|
||||
if (recvlength < MESSAGE_HEADER_LEN ||
|
||||
recvlength > LBS_CMD_BUFFER_SIZE) {
|
||||
lbs_deb_usbd(&cardp->udev->dev,
|
||||
"The receive buffer is too large\n");
|
||||
"The receive buffer is invalid: %d\n", recvlength);
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -70,12 +70,11 @@ static inline int rsi_create_kthread(struct rsi_common *common,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int rsi_kill_thread(struct rsi_thread *handle)
|
||||
static inline void rsi_kill_thread(struct rsi_thread *handle)
|
||||
{
|
||||
atomic_inc(&handle->thread_done);
|
||||
rsi_set_event(&handle->event);
|
||||
|
||||
return kthread_stop(handle->task);
|
||||
wait_for_completion(&handle->completion);
|
||||
}
|
||||
|
||||
void rsi_mac80211_detach(struct rsi_hw *hw);
|
||||
|
||||
@@ -264,14 +264,12 @@ int cw1200_wow_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
|
||||
wiphy_err(priv->hw->wiphy,
|
||||
"PM request failed: %d. WoW is disabled.\n", ret);
|
||||
cw1200_wow_resume(hw);
|
||||
mutex_unlock(&priv->conf_mutex);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* Force resume if event is coming from the device. */
|
||||
if (atomic_read(&priv->bh_rx)) {
|
||||
cw1200_wow_resume(hw);
|
||||
mutex_unlock(&priv->conf_mutex);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
|
||||
@@ -457,8 +457,20 @@ static int t7xx_parse_host_rt_data(struct t7xx_fsm_ctl *ctl, struct t7xx_sys_inf
|
||||
|
||||
offset = sizeof(struct feature_query);
|
||||
for (i = 0; i < FEATURE_COUNT && offset < data_length; i++) {
|
||||
size_t remaining = data_length - offset;
|
||||
size_t feat_data_len, feat_total;
|
||||
|
||||
if (remaining < sizeof(*rt_feature))
|
||||
break;
|
||||
|
||||
rt_feature = data + offset;
|
||||
offset += sizeof(*rt_feature) + le32_to_cpu(rt_feature->data_len);
|
||||
feat_data_len = le32_to_cpu(rt_feature->data_len);
|
||||
|
||||
if (feat_data_len > remaining - sizeof(*rt_feature))
|
||||
break;
|
||||
|
||||
feat_total = sizeof(*rt_feature) + feat_data_len;
|
||||
offset += feat_total;
|
||||
|
||||
ft_spt_cfg = FIELD_GET(FEATURE_MSK, core->feature_set[i]);
|
||||
if (ft_spt_cfg != MTK_FEATURE_MUST_BE_SUPPORTED)
|
||||
@@ -468,8 +480,10 @@ static int t7xx_parse_host_rt_data(struct t7xx_fsm_ctl *ctl, struct t7xx_sys_inf
|
||||
if (ft_spt_st != MTK_FEATURE_MUST_BE_SUPPORTED)
|
||||
return -EINVAL;
|
||||
|
||||
if (i == RT_ID_MD_PORT_ENUM || i == RT_ID_AP_PORT_ENUM)
|
||||
t7xx_port_enum_msg_handler(ctl->md, rt_feature->data);
|
||||
if (i == RT_ID_MD_PORT_ENUM || i == RT_ID_AP_PORT_ENUM) {
|
||||
t7xx_port_enum_msg_handler(ctl->md, rt_feature->data,
|
||||
feat_data_len);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -117,6 +117,7 @@ static int fsm_ee_message_handler(struct t7xx_port *port, struct t7xx_fsm_ctl *c
|
||||
* t7xx_port_enum_msg_handler() - Parse the port enumeration message to create/remove nodes.
|
||||
* @md: Modem context.
|
||||
* @msg: Message.
|
||||
* @msg_len: Length of @msg in bytes.
|
||||
*
|
||||
* Used to control create/remove device node.
|
||||
*
|
||||
@@ -124,12 +125,18 @@ static int fsm_ee_message_handler(struct t7xx_port *port, struct t7xx_fsm_ctl *c
|
||||
* * 0 - Success.
|
||||
* * -EFAULT - Message check failure.
|
||||
*/
|
||||
int t7xx_port_enum_msg_handler(struct t7xx_modem *md, void *msg)
|
||||
int t7xx_port_enum_msg_handler(struct t7xx_modem *md, void *msg, size_t msg_len)
|
||||
{
|
||||
struct device *dev = &md->t7xx_dev->pdev->dev;
|
||||
unsigned int version, port_count, i;
|
||||
struct port_msg *port_msg = msg;
|
||||
|
||||
if (msg_len < sizeof(*port_msg)) {
|
||||
dev_err(dev, "Port enum msg too short for header: need %zu, have %zu\n",
|
||||
sizeof(*port_msg), msg_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
version = FIELD_GET(PORT_MSG_VERSION, le32_to_cpu(port_msg->info));
|
||||
if (version != PORT_ENUM_VER ||
|
||||
le32_to_cpu(port_msg->head_pattern) != PORT_ENUM_HEAD_PATTERN ||
|
||||
@@ -141,6 +148,13 @@ int t7xx_port_enum_msg_handler(struct t7xx_modem *md, void *msg)
|
||||
}
|
||||
|
||||
port_count = FIELD_GET(PORT_MSG_PRT_CNT, le32_to_cpu(port_msg->info));
|
||||
|
||||
if (msg_len < struct_size(port_msg, data, port_count)) {
|
||||
dev_err(dev, "Port enum msg too short: need %zu, have %zu\n",
|
||||
struct_size(port_msg, data, port_count), msg_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < port_count; i++) {
|
||||
u32 port_info = le32_to_cpu(port_msg->data[i]);
|
||||
unsigned int ch_id;
|
||||
@@ -191,7 +205,7 @@ static int control_msg_handler(struct t7xx_port *port, struct sk_buff *skb)
|
||||
|
||||
case CTL_ID_PORT_ENUM:
|
||||
skb_pull(skb, sizeof(*ctrl_msg_h));
|
||||
ret = t7xx_port_enum_msg_handler(ctl->md, (struct port_msg *)skb->data);
|
||||
ret = t7xx_port_enum_msg_handler(ctl->md, (struct port_msg *)skb->data, skb->len);
|
||||
if (!ret)
|
||||
ret = port_ctl_send_msg_to_md(port, CTL_ID_PORT_ENUM, 0);
|
||||
else
|
||||
|
||||
@@ -103,7 +103,7 @@ void t7xx_port_proxy_reset(struct port_proxy *port_prox);
|
||||
void t7xx_port_proxy_uninit(struct port_proxy *port_prox);
|
||||
int t7xx_port_proxy_init(struct t7xx_modem *md);
|
||||
void t7xx_port_proxy_md_status_notify(struct port_proxy *port_prox, unsigned int state);
|
||||
int t7xx_port_enum_msg_handler(struct t7xx_modem *md, void *msg);
|
||||
int t7xx_port_enum_msg_handler(struct t7xx_modem *md, void *msg, size_t msg_len);
|
||||
int t7xx_port_proxy_chl_enable_disable(struct port_proxy *port_prox, unsigned int ch_id,
|
||||
bool en_flag);
|
||||
void t7xx_port_proxy_set_cfg(struct t7xx_modem *md, enum port_cfg_id cfg_id);
|
||||
|
||||
@@ -146,6 +146,9 @@ struct xt_match {
|
||||
/* Called when user tries to insert an entry of this type. */
|
||||
int (*checkentry)(const struct xt_mtchk_param *);
|
||||
|
||||
/* Called to validate hooks based on the match configuration. */
|
||||
int (*check_hooks)(const struct xt_mtchk_param *);
|
||||
|
||||
/* Called when entry of this type deleted. */
|
||||
void (*destroy)(const struct xt_mtdtor_param *);
|
||||
#ifdef CONFIG_NETFILTER_XTABLES_COMPAT
|
||||
@@ -187,6 +190,9 @@ struct xt_target {
|
||||
/* Should return 0 on success or an error code otherwise (-Exxxx). */
|
||||
int (*checkentry)(const struct xt_tgchk_param *);
|
||||
|
||||
/* Called to validate hooks based on the target configuration. */
|
||||
int (*check_hooks)(const struct xt_tgchk_param *);
|
||||
|
||||
/* Called when entry of this type deleted. */
|
||||
void (*destroy)(const struct xt_tgdtor_param *);
|
||||
#ifdef CONFIG_NETFILTER_XTABLES_COMPAT
|
||||
@@ -279,8 +285,10 @@ bool xt_find_jump_offset(const unsigned int *offsets,
|
||||
|
||||
int xt_check_proc_name(const char *name, unsigned int size);
|
||||
|
||||
int xt_check_hooks_match(struct xt_mtchk_param *par);
|
||||
int xt_check_match(struct xt_mtchk_param *, unsigned int size, u16 proto,
|
||||
bool inv_proto);
|
||||
int xt_check_hooks_target(struct xt_tgchk_param *par);
|
||||
int xt_check_target(struct xt_tgchk_param *, unsigned int size, u16 proto,
|
||||
bool inv_proto);
|
||||
|
||||
|
||||
@@ -20,6 +20,11 @@ enum hk_type {
|
||||
HK_TYPE_KERNEL_NOISE,
|
||||
HK_TYPE_MAX,
|
||||
|
||||
/*
|
||||
* HK_TYPE_KTHREAD is now an alias of HK_TYPE_DOMAIN
|
||||
*/
|
||||
HK_TYPE_KTHREAD = HK_TYPE_DOMAIN,
|
||||
|
||||
/*
|
||||
* The following housekeeping types are only set by the nohz_full
|
||||
* boot commandline option. So they can share the same value.
|
||||
@@ -29,7 +34,6 @@ enum hk_type {
|
||||
HK_TYPE_RCU = HK_TYPE_KERNEL_NOISE,
|
||||
HK_TYPE_MISC = HK_TYPE_KERNEL_NOISE,
|
||||
HK_TYPE_WQ = HK_TYPE_KERNEL_NOISE,
|
||||
HK_TYPE_KTHREAD = HK_TYPE_KERNEL_NOISE
|
||||
};
|
||||
|
||||
#ifdef CONFIG_CPU_ISOLATION
|
||||
|
||||
@@ -2495,7 +2495,7 @@ void mgmt_adv_monitor_device_lost(struct hci_dev *hdev, u16 handle,
|
||||
bdaddr_t *bdaddr, u8 addr_type);
|
||||
|
||||
int hci_abort_conn(struct hci_conn *conn, u8 reason);
|
||||
u8 hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, u16 latency,
|
||||
void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, u16 latency,
|
||||
u16 to_multiplier);
|
||||
void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __le64 rand,
|
||||
__u8 ltk[16], __u8 key_size);
|
||||
|
||||
@@ -99,6 +99,7 @@
|
||||
FN(FRAG_TOO_FAR) \
|
||||
FN(TCP_MINTTL) \
|
||||
FN(IPV6_BAD_EXTHDR) \
|
||||
FN(IPV6_TOO_MANY_EXTHDRS) \
|
||||
FN(IPV6_NDISC_FRAG) \
|
||||
FN(IPV6_NDISC_HOP_LIMIT) \
|
||||
FN(IPV6_NDISC_BAD_CODE) \
|
||||
@@ -494,6 +495,11 @@ enum skb_drop_reason {
|
||||
SKB_DROP_REASON_TCP_MINTTL,
|
||||
/** @SKB_DROP_REASON_IPV6_BAD_EXTHDR: Bad IPv6 extension header. */
|
||||
SKB_DROP_REASON_IPV6_BAD_EXTHDR,
|
||||
/**
|
||||
* @SKB_DROP_REASON_IPV6_TOO_MANY_EXTHDRS: Number of IPv6 extension
|
||||
* headers in the packet exceeds IP6_MAX_EXT_HDRS_CNT.
|
||||
*/
|
||||
SKB_DROP_REASON_IPV6_TOO_MANY_EXTHDRS,
|
||||
/** @SKB_DROP_REASON_IPV6_NDISC_FRAG: invalid frag (suppress_frag_ndisc). */
|
||||
SKB_DROP_REASON_IPV6_NDISC_FRAG,
|
||||
/** @SKB_DROP_REASON_IPV6_NDISC_HOP_LIMIT: invalid hop limit. */
|
||||
|
||||
+26
-5
@@ -491,6 +491,7 @@ struct ip_vs_est_kt_data {
|
||||
DECLARE_BITMAP(avail, IPVS_EST_NTICKS); /* tick has space for ests */
|
||||
unsigned long est_timer; /* estimation timer (jiffies) */
|
||||
struct ip_vs_stats *calc_stats; /* Used for calculation */
|
||||
int needed; /* task is needed */
|
||||
int tick_len[IPVS_EST_NTICKS]; /* est count */
|
||||
int id; /* ktid per netns */
|
||||
int chain_max; /* max ests per tick chain */
|
||||
@@ -1411,7 +1412,7 @@ static inline int sysctl_run_estimation(struct netns_ipvs *ipvs)
|
||||
return ipvs->sysctl_run_estimation;
|
||||
}
|
||||
|
||||
static inline const struct cpumask *sysctl_est_cpulist(struct netns_ipvs *ipvs)
|
||||
static inline const struct cpumask *__sysctl_est_cpulist(struct netns_ipvs *ipvs)
|
||||
{
|
||||
if (ipvs->est_cpulist_valid)
|
||||
return ipvs->sysctl_est_cpulist;
|
||||
@@ -1529,7 +1530,7 @@ static inline int sysctl_run_estimation(struct netns_ipvs *ipvs)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline const struct cpumask *sysctl_est_cpulist(struct netns_ipvs *ipvs)
|
||||
static inline const struct cpumask *__sysctl_est_cpulist(struct netns_ipvs *ipvs)
|
||||
{
|
||||
return housekeeping_cpumask(HK_TYPE_KTHREAD);
|
||||
}
|
||||
@@ -1564,6 +1565,18 @@ static inline int sysctl_svc_lfactor(struct netns_ipvs *ipvs)
|
||||
return READ_ONCE(ipvs->sysctl_svc_lfactor);
|
||||
}
|
||||
|
||||
static inline bool sysctl_est_cpulist_empty(struct netns_ipvs *ipvs)
|
||||
{
|
||||
guard(rcu)();
|
||||
return cpumask_empty(__sysctl_est_cpulist(ipvs));
|
||||
}
|
||||
|
||||
static inline unsigned int sysctl_est_cpulist_weight(struct netns_ipvs *ipvs)
|
||||
{
|
||||
guard(rcu)();
|
||||
return cpumask_weight(__sysctl_est_cpulist(ipvs));
|
||||
}
|
||||
|
||||
/* IPVS core functions
|
||||
* (from ip_vs_core.c)
|
||||
*/
|
||||
@@ -1884,18 +1897,26 @@ int ip_vs_start_estimator(struct netns_ipvs *ipvs, struct ip_vs_stats *stats);
|
||||
void ip_vs_stop_estimator(struct netns_ipvs *ipvs, struct ip_vs_stats *stats);
|
||||
void ip_vs_zero_estimator(struct ip_vs_stats *stats);
|
||||
void ip_vs_read_estimator(struct ip_vs_kstats *dst, struct ip_vs_stats *stats);
|
||||
void ip_vs_est_reload_start(struct netns_ipvs *ipvs);
|
||||
void ip_vs_est_reload_start(struct netns_ipvs *ipvs, bool restart);
|
||||
int ip_vs_est_kthread_start(struct netns_ipvs *ipvs,
|
||||
struct ip_vs_est_kt_data *kd);
|
||||
void ip_vs_est_kthread_stop(struct ip_vs_est_kt_data *kd);
|
||||
|
||||
static inline void ip_vs_stop_estimator_tot_stats(struct netns_ipvs *ipvs)
|
||||
{
|
||||
#ifdef CONFIG_SYSCTL
|
||||
ip_vs_stop_estimator(ipvs, &ipvs->tot_stats->s);
|
||||
ipvs->tot_stats->s.est.ktid = -2;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void ip_vs_est_stopped_recalc(struct netns_ipvs *ipvs)
|
||||
{
|
||||
#ifdef CONFIG_SYSCTL
|
||||
/* Stop tasks while cpulist is empty or if disabled with flag */
|
||||
ipvs->est_stopped = !sysctl_run_estimation(ipvs) ||
|
||||
(ipvs->est_cpulist_valid &&
|
||||
cpumask_empty(sysctl_est_cpulist(ipvs)));
|
||||
sysctl_est_cpulist_empty(ipvs));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1911,7 +1932,7 @@ static inline bool ip_vs_est_stopped(struct netns_ipvs *ipvs)
|
||||
static inline int ip_vs_est_max_threads(struct netns_ipvs *ipvs)
|
||||
{
|
||||
unsigned int limit = IPVS_EST_CPU_KTHREADS *
|
||||
cpumask_weight(sysctl_est_cpulist(ipvs));
|
||||
sysctl_est_cpulist_weight(ipvs);
|
||||
|
||||
return max(1U, limit);
|
||||
}
|
||||
|
||||
@@ -90,6 +90,9 @@ struct ip_tunnel_info;
|
||||
#define IP6_DEFAULT_MAX_DST_OPTS_LEN INT_MAX /* No limit */
|
||||
#define IP6_DEFAULT_MAX_HBH_OPTS_LEN INT_MAX /* No limit */
|
||||
|
||||
/* Hard limit on traversed IPv6 extension headers */
|
||||
#define IP6_MAX_EXT_HDRS_CNT 12
|
||||
|
||||
/*
|
||||
* Addr type
|
||||
*
|
||||
|
||||
@@ -4,6 +4,12 @@
|
||||
#ifndef _SHM_CHANNEL_H
|
||||
#define _SHM_CHANNEL_H
|
||||
|
||||
#define SMC_APERTURE_BITS 256
|
||||
#define SMC_BASIC_UNIT (sizeof(u32))
|
||||
#define SMC_APERTURE_DWORDS (SMC_APERTURE_BITS / (SMC_BASIC_UNIT * 8))
|
||||
#define SMC_LAST_DWORD (SMC_APERTURE_DWORDS - 1)
|
||||
#define SMC_APERTURE_SIZE (SMC_APERTURE_BITS / 8)
|
||||
|
||||
struct shm_channel {
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
|
||||
@@ -3,10 +3,23 @@
|
||||
#define _NF_DUP_NETDEV_H_
|
||||
|
||||
#include <net/netfilter/nf_tables.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
void nf_dup_netdev_egress(const struct nft_pktinfo *pkt, int oif);
|
||||
void nf_fwd_netdev_egress(const struct nft_pktinfo *pkt, int oif);
|
||||
|
||||
#define NF_RECURSION_LIMIT 2
|
||||
|
||||
static inline u8 *nf_get_nf_dup_skb_recursion(void)
|
||||
{
|
||||
#ifndef CONFIG_PREEMPT_RT
|
||||
return this_cpu_ptr(&softnet_data.xmit.nf_dup_skb_recursion);
|
||||
#else
|
||||
return ¤t->net_xmit.nf_dup_skb_recursion;
|
||||
#endif
|
||||
}
|
||||
|
||||
struct nft_offload_ctx;
|
||||
struct nft_flow_rule;
|
||||
|
||||
|
||||
@@ -148,9 +148,10 @@ struct flow_offload_tuple {
|
||||
/* All members above are keys for lookups, see flow_offload_hash(). */
|
||||
struct { } __hash;
|
||||
|
||||
u8 dir:2,
|
||||
u16 dir:2,
|
||||
xmit_type:3,
|
||||
encap_num:2,
|
||||
needs_gso_segment:1,
|
||||
tun_num:2,
|
||||
in_vlan_ingress:2;
|
||||
u16 mtu;
|
||||
@@ -232,6 +233,7 @@ struct nf_flow_route {
|
||||
u32 hw_ifindex;
|
||||
u8 h_source[ETH_ALEN];
|
||||
u8 h_dest[ETH_ALEN];
|
||||
u8 needs_gso_segment:1;
|
||||
} out;
|
||||
enum flow_offload_xmit_type xmit_type;
|
||||
} tuple[FLOW_OFFLOAD_DIR_MAX];
|
||||
|
||||
@@ -275,7 +275,7 @@ struct netns_ipv4 {
|
||||
|
||||
#ifdef CONFIG_IP_MROUTE
|
||||
#ifndef CONFIG_IP_MROUTE_MULTIPLE_TABLES
|
||||
struct mr_table *mrt;
|
||||
struct mr_table __rcu *mrt;
|
||||
#else
|
||||
struct list_head mr_tables;
|
||||
struct fib_rules_ops *mr_rules_ops;
|
||||
|
||||
@@ -330,11 +330,18 @@ static int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
|
||||
goto badframe;
|
||||
break;
|
||||
case BNEP_FILTER_MULTI_ADDR_SET:
|
||||
case BNEP_FILTER_NET_TYPE_SET:
|
||||
/* Pull: ctrl type (1 b), len (2 b), data (len bytes) */
|
||||
if (!skb_pull(skb, 3 + *(u16 *)(skb->data + 1) * 2))
|
||||
case BNEP_FILTER_NET_TYPE_SET: {
|
||||
u8 *hdr;
|
||||
|
||||
/* Pull ctrl type (1 b) + len (2 b) */
|
||||
hdr = skb_pull_data(skb, 3);
|
||||
if (!hdr)
|
||||
goto badframe;
|
||||
/* Pull data (len bytes); length is big-endian */
|
||||
if (!skb_pull(skb, get_unaligned_be16(&hdr[1])))
|
||||
goto badframe;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
|
||||
+104
-20
@@ -480,40 +480,107 @@ bool hci_setup_sync(struct hci_conn *conn, __u16 handle)
|
||||
return hci_setup_sync_conn(conn, handle);
|
||||
}
|
||||
|
||||
u8 hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, u16 latency,
|
||||
u16 to_multiplier)
|
||||
struct le_conn_update_data {
|
||||
struct hci_conn *conn;
|
||||
u16 min;
|
||||
u16 max;
|
||||
u16 latency;
|
||||
u16 to_multiplier;
|
||||
};
|
||||
|
||||
static int le_conn_update_sync(struct hci_dev *hdev, void *data)
|
||||
{
|
||||
struct hci_dev *hdev = conn->hdev;
|
||||
struct le_conn_update_data *d = data;
|
||||
struct hci_conn *conn = d->conn;
|
||||
struct hci_conn_params *params;
|
||||
struct hci_cp_le_conn_update cp;
|
||||
u16 timeout;
|
||||
u8 store_hint;
|
||||
int err;
|
||||
|
||||
/* Verify connection is still alive and read conn fields under
|
||||
* the same lock to prevent a concurrent disconnect from freeing
|
||||
* or reusing the connection while we build the HCI command.
|
||||
*/
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
if (!hci_conn_valid(hdev, conn)) {
|
||||
hci_dev_unlock(hdev);
|
||||
return -ECANCELED;
|
||||
}
|
||||
|
||||
memset(&cp, 0, sizeof(cp));
|
||||
cp.handle = cpu_to_le16(conn->handle);
|
||||
cp.conn_interval_min = cpu_to_le16(d->min);
|
||||
cp.conn_interval_max = cpu_to_le16(d->max);
|
||||
cp.conn_latency = cpu_to_le16(d->latency);
|
||||
cp.supervision_timeout = cpu_to_le16(d->to_multiplier);
|
||||
cp.min_ce_len = cpu_to_le16(0x0000);
|
||||
cp.max_ce_len = cpu_to_le16(0x0000);
|
||||
timeout = conn->conn_timeout;
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
|
||||
err = __hci_cmd_sync_status_sk(hdev, HCI_OP_LE_CONN_UPDATE,
|
||||
sizeof(cp), &cp,
|
||||
HCI_EV_LE_CONN_UPDATE_COMPLETE,
|
||||
timeout, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Update stored connection parameters after the controller has
|
||||
* confirmed the update via the LE Connection Update Complete event.
|
||||
*/
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
|
||||
if (params) {
|
||||
params->conn_min_interval = min;
|
||||
params->conn_max_interval = max;
|
||||
params->conn_latency = latency;
|
||||
params->supervision_timeout = to_multiplier;
|
||||
params->conn_min_interval = d->min;
|
||||
params->conn_max_interval = d->max;
|
||||
params->conn_latency = d->latency;
|
||||
params->supervision_timeout = d->to_multiplier;
|
||||
store_hint = 0x01;
|
||||
} else {
|
||||
store_hint = 0x00;
|
||||
}
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
|
||||
memset(&cp, 0, sizeof(cp));
|
||||
cp.handle = cpu_to_le16(conn->handle);
|
||||
cp.conn_interval_min = cpu_to_le16(min);
|
||||
cp.conn_interval_max = cpu_to_le16(max);
|
||||
cp.conn_latency = cpu_to_le16(latency);
|
||||
cp.supervision_timeout = cpu_to_le16(to_multiplier);
|
||||
cp.min_ce_len = cpu_to_le16(0x0000);
|
||||
cp.max_ce_len = cpu_to_le16(0x0000);
|
||||
mgmt_new_conn_param(hdev, &conn->dst, conn->dst_type, store_hint,
|
||||
d->min, d->max, d->latency, d->to_multiplier);
|
||||
|
||||
hci_send_cmd(hdev, HCI_OP_LE_CONN_UPDATE, sizeof(cp), &cp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (params)
|
||||
return 0x01;
|
||||
static void le_conn_update_complete(struct hci_dev *hdev, void *data, int err)
|
||||
{
|
||||
struct le_conn_update_data *d = data;
|
||||
|
||||
return 0x00;
|
||||
hci_conn_put(d->conn);
|
||||
kfree(d);
|
||||
}
|
||||
|
||||
void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, u16 latency,
|
||||
u16 to_multiplier)
|
||||
{
|
||||
struct le_conn_update_data *d;
|
||||
|
||||
d = kzalloc_obj(*d);
|
||||
if (!d)
|
||||
return;
|
||||
|
||||
hci_conn_get(conn);
|
||||
d->conn = conn;
|
||||
d->min = min;
|
||||
d->max = max;
|
||||
d->latency = latency;
|
||||
d->to_multiplier = to_multiplier;
|
||||
|
||||
if (hci_cmd_sync_queue(conn->hdev, le_conn_update_sync, d,
|
||||
le_conn_update_complete) < 0) {
|
||||
hci_conn_put(conn);
|
||||
kfree(d);
|
||||
}
|
||||
}
|
||||
|
||||
void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __le64 rand,
|
||||
@@ -2130,6 +2197,9 @@ static int create_big_sync(struct hci_dev *hdev, void *data)
|
||||
u32 flags = 0;
|
||||
int err;
|
||||
|
||||
if (!hci_conn_valid(hdev, conn))
|
||||
return -ECANCELED;
|
||||
|
||||
if (qos->bcast.out.phys == BIT(1))
|
||||
flags |= MGMT_ADV_FLAG_SEC_2M;
|
||||
|
||||
@@ -2204,11 +2274,24 @@ static void create_big_complete(struct hci_dev *hdev, void *data, int err)
|
||||
|
||||
bt_dev_dbg(hdev, "conn %p", conn);
|
||||
|
||||
if (err == -ECANCELED)
|
||||
goto done;
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
if (!hci_conn_valid(hdev, conn))
|
||||
goto unlock;
|
||||
|
||||
if (err) {
|
||||
bt_dev_err(hdev, "Unable to create BIG: %d", err);
|
||||
hci_connect_cfm(conn, err);
|
||||
hci_conn_del(conn);
|
||||
}
|
||||
|
||||
unlock:
|
||||
hci_dev_unlock(hdev);
|
||||
done:
|
||||
hci_conn_put(conn);
|
||||
}
|
||||
|
||||
struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst, __u8 sid,
|
||||
@@ -2336,10 +2419,11 @@ struct hci_conn *hci_connect_bis(struct hci_dev *hdev, bdaddr_t *dst,
|
||||
BT_BOUND, &data);
|
||||
|
||||
/* Queue start periodic advertising and create BIG */
|
||||
err = hci_cmd_sync_queue(hdev, create_big_sync, conn,
|
||||
err = hci_cmd_sync_queue(hdev, create_big_sync, hci_conn_get(conn),
|
||||
create_big_complete);
|
||||
if (err < 0) {
|
||||
hci_conn_drop(conn);
|
||||
hci_conn_put(conn);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
|
||||
@@ -7118,9 +7118,29 @@ static void hci_le_create_big_complete_evt(struct hci_dev *hdev, void *data,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hci_conn_set_handle(conn,
|
||||
__le16_to_cpu(ev->bis_handle[i++])))
|
||||
if (ev->num_bis <= i) {
|
||||
bt_dev_err(hdev,
|
||||
"Not enough BIS handles for BIG 0x%2.2x",
|
||||
ev->handle);
|
||||
ev->status = HCI_ERROR_UNSPECIFIED;
|
||||
hci_connect_cfm(conn, ev->status);
|
||||
hci_conn_del(conn);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hci_conn_set_handle(conn,
|
||||
__le16_to_cpu(ev->bis_handle[i++]))) {
|
||||
bt_dev_err(hdev,
|
||||
"Failed to set BIS handle for BIG 0x%2.2x",
|
||||
ev->handle);
|
||||
/* Force error so BIG gets terminated as not all BIS
|
||||
* could be connected.
|
||||
*/
|
||||
ev->status = HCI_ERROR_UNSPECIFIED;
|
||||
hci_connect_cfm(conn, ev->status);
|
||||
hci_conn_del(conn);
|
||||
continue;
|
||||
}
|
||||
|
||||
conn->state = BT_CONNECTED;
|
||||
set_bit(HCI_CONN_BIG_CREATED, &conn->flags);
|
||||
@@ -7129,7 +7149,10 @@ static void hci_le_create_big_complete_evt(struct hci_dev *hdev, void *data,
|
||||
hci_iso_setup_path(conn);
|
||||
}
|
||||
|
||||
if (!ev->status && !i)
|
||||
/* If there is an unexpected error or if no BISes have been connected
|
||||
* for the BIG, terminate it.
|
||||
*/
|
||||
if (ev->status == HCI_ERROR_UNSPECIFIED || (!ev->status && !i))
|
||||
/* If no BISes have been connected for the BIG,
|
||||
* terminate. This is in case all bound connections
|
||||
* have been closed before the BIG creation
|
||||
@@ -7168,7 +7191,7 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data,
|
||||
clear_bit(HCI_CONN_CREATE_BIG_SYNC, &conn->flags);
|
||||
|
||||
conn->num_bis = 0;
|
||||
memset(conn->bis, 0, sizeof(conn->num_bis));
|
||||
memset(conn->bis, 0, sizeof(conn->bis));
|
||||
|
||||
for (i = 0; i < ev->num_bis; i++) {
|
||||
u16 handle = le16_to_cpu(ev->bis[i]);
|
||||
|
||||
@@ -1035,6 +1035,28 @@ static struct hidp_session *hidp_session_find(const bdaddr_t *bdaddr)
|
||||
return session;
|
||||
}
|
||||
|
||||
/*
|
||||
* Consume session->conn: clear the member under hidp_session_sem, then
|
||||
* l2cap_unregister_user() and l2cap_conn_put() the snapshot outside the
|
||||
* sem. At most one caller wins; later callers see NULL and skip. The
|
||||
* reference is the one hidp_session_new() took via l2cap_conn_get().
|
||||
*/
|
||||
static void hidp_session_unregister_conn(struct hidp_session *session)
|
||||
{
|
||||
struct l2cap_conn *conn;
|
||||
|
||||
down_write(&hidp_session_sem);
|
||||
conn = session->conn;
|
||||
if (conn)
|
||||
session->conn = NULL;
|
||||
up_write(&hidp_session_sem);
|
||||
|
||||
if (conn) {
|
||||
l2cap_unregister_user(conn, &session->user);
|
||||
l2cap_conn_put(conn);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Start session synchronously
|
||||
* This starts a session thread and waits until initialization
|
||||
@@ -1311,8 +1333,7 @@ static int hidp_session_thread(void *arg)
|
||||
* Instead, this call has the same semantics as if user-space tried to
|
||||
* delete the session.
|
||||
*/
|
||||
if (session->conn)
|
||||
l2cap_unregister_user(session->conn, &session->user);
|
||||
hidp_session_unregister_conn(session);
|
||||
|
||||
hidp_session_put(session);
|
||||
|
||||
@@ -1418,7 +1439,7 @@ int hidp_connection_del(struct hidp_conndel_req *req)
|
||||
HIDP_CTRL_VIRTUAL_CABLE_UNPLUG,
|
||||
NULL, 0);
|
||||
else
|
||||
l2cap_unregister_user(session->conn, &session->user);
|
||||
hidp_session_unregister_conn(session);
|
||||
|
||||
hidp_session_put(session);
|
||||
|
||||
|
||||
+31
-25
@@ -347,6 +347,7 @@ static int iso_connect_bis(struct sock *sk)
|
||||
return -EHOSTUNREACH;
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
lock_sock(sk);
|
||||
|
||||
if (!bis_capable(hdev)) {
|
||||
err = -EOPNOTSUPP;
|
||||
@@ -399,13 +400,9 @@ static int iso_connect_bis(struct sock *sk)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
lock_sock(sk);
|
||||
|
||||
err = iso_chan_add(conn, sk, NULL);
|
||||
if (err) {
|
||||
release_sock(sk);
|
||||
if (err)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
/* Update source addr of the socket */
|
||||
bacpy(&iso_pi(sk)->src, &hcon->src);
|
||||
@@ -421,9 +418,8 @@ static int iso_connect_bis(struct sock *sk)
|
||||
iso_sock_set_timer(sk, READ_ONCE(sk->sk_sndtimeo));
|
||||
}
|
||||
|
||||
release_sock(sk);
|
||||
|
||||
unlock:
|
||||
release_sock(sk);
|
||||
hci_dev_unlock(hdev);
|
||||
hci_dev_put(hdev);
|
||||
return err;
|
||||
@@ -444,6 +440,7 @@ static int iso_connect_cis(struct sock *sk)
|
||||
return -EHOSTUNREACH;
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
lock_sock(sk);
|
||||
|
||||
if (!cis_central_capable(hdev)) {
|
||||
err = -EOPNOTSUPP;
|
||||
@@ -498,13 +495,9 @@ static int iso_connect_cis(struct sock *sk)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
lock_sock(sk);
|
||||
|
||||
err = iso_chan_add(conn, sk, NULL);
|
||||
if (err) {
|
||||
release_sock(sk);
|
||||
if (err)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
/* Update source addr of the socket */
|
||||
bacpy(&iso_pi(sk)->src, &hcon->src);
|
||||
@@ -520,9 +513,8 @@ static int iso_connect_cis(struct sock *sk)
|
||||
iso_sock_set_timer(sk, READ_ONCE(sk->sk_sndtimeo));
|
||||
}
|
||||
|
||||
release_sock(sk);
|
||||
|
||||
unlock:
|
||||
release_sock(sk);
|
||||
hci_dev_unlock(hdev);
|
||||
hci_dev_put(hdev);
|
||||
return err;
|
||||
@@ -1193,7 +1185,7 @@ static int iso_sock_connect(struct socket *sock, struct sockaddr_unsized *addr,
|
||||
|
||||
release_sock(sk);
|
||||
|
||||
if (bacmp(&iso_pi(sk)->dst, BDADDR_ANY))
|
||||
if (bacmp(&sa->iso_bdaddr, BDADDR_ANY))
|
||||
err = iso_connect_cis(sk);
|
||||
else
|
||||
err = iso_connect_bis(sk);
|
||||
@@ -2256,8 +2248,10 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
|
||||
sk = iso_get_sock(hdev, &hdev->bdaddr, bdaddr, BT_LISTEN,
|
||||
iso_match_sid, ev1);
|
||||
if (sk && !ev1->status) {
|
||||
lock_sock(sk);
|
||||
iso_pi(sk)->sync_handle = le16_to_cpu(ev1->handle);
|
||||
iso_pi(sk)->bc_sid = ev1->sid;
|
||||
release_sock(sk);
|
||||
}
|
||||
|
||||
goto done;
|
||||
@@ -2268,8 +2262,10 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
|
||||
sk = iso_get_sock(hdev, &hdev->bdaddr, bdaddr, BT_LISTEN,
|
||||
iso_match_sid_past, ev1a);
|
||||
if (sk && !ev1a->status) {
|
||||
lock_sock(sk);
|
||||
iso_pi(sk)->sync_handle = le16_to_cpu(ev1a->sync_handle);
|
||||
iso_pi(sk)->bc_sid = ev1a->sid;
|
||||
release_sock(sk);
|
||||
}
|
||||
|
||||
goto done;
|
||||
@@ -2296,27 +2292,35 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
|
||||
ev2);
|
||||
|
||||
if (sk) {
|
||||
int err;
|
||||
struct hci_conn *hcon = iso_pi(sk)->conn->hcon;
|
||||
int err = 0;
|
||||
bool big_sync;
|
||||
struct hci_conn *hcon;
|
||||
|
||||
lock_sock(sk);
|
||||
|
||||
hcon = iso_pi(sk)->conn->hcon;
|
||||
iso_pi(sk)->qos.bcast.encryption = ev2->encryption;
|
||||
|
||||
if (ev2->num_bis < iso_pi(sk)->bc_num_bis)
|
||||
iso_pi(sk)->bc_num_bis = ev2->num_bis;
|
||||
|
||||
if (!test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags) &&
|
||||
!test_and_set_bit(BT_SK_BIG_SYNC, &iso_pi(sk)->flags)) {
|
||||
big_sync = !test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags) &&
|
||||
!test_and_set_bit(BT_SK_BIG_SYNC, &iso_pi(sk)->flags);
|
||||
|
||||
if (big_sync)
|
||||
err = hci_conn_big_create_sync(hdev, hcon,
|
||||
&iso_pi(sk)->qos,
|
||||
iso_pi(sk)->sync_handle,
|
||||
iso_pi(sk)->bc_num_bis,
|
||||
iso_pi(sk)->bc_bis);
|
||||
if (err) {
|
||||
bt_dev_err(hdev, "hci_le_big_create_sync: %d",
|
||||
err);
|
||||
sock_put(sk);
|
||||
sk = NULL;
|
||||
}
|
||||
|
||||
release_sock(sk);
|
||||
|
||||
if (big_sync && err) {
|
||||
bt_dev_err(hdev, "hci_le_big_create_sync: %d",
|
||||
err);
|
||||
sock_put(sk);
|
||||
sk = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2370,8 +2374,10 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
|
||||
if (!base || base_len > BASE_MAX_LENGTH)
|
||||
goto done;
|
||||
|
||||
lock_sock(sk);
|
||||
memcpy(iso_pi(sk)->base, base, base_len);
|
||||
iso_pi(sk)->base_len = base_len;
|
||||
release_sock(sk);
|
||||
} else {
|
||||
/* This is a PA data fragment. Keep pa_data_len set to 0
|
||||
* until all data has been reassembled.
|
||||
|
||||
@@ -4706,16 +4706,8 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
|
||||
l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
|
||||
sizeof(rsp), &rsp);
|
||||
|
||||
if (!err) {
|
||||
u8 store_hint;
|
||||
|
||||
store_hint = hci_le_conn_update(hcon, min, max, latency,
|
||||
to_multiplier);
|
||||
mgmt_new_conn_param(hcon->hdev, &hcon->dst, hcon->dst_type,
|
||||
store_hint, min, max, latency,
|
||||
to_multiplier);
|
||||
|
||||
}
|
||||
if (!err)
|
||||
hci_le_conn_update(hcon, min, max, latency, to_multiplier);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -5428,7 +5420,7 @@ static inline int l2cap_ecred_reconf_req(struct l2cap_conn *conn,
|
||||
* configured, the MPS field may be less than the current MPS
|
||||
* of that channel.
|
||||
*/
|
||||
if (chan[i]->remote_mps >= mps && i) {
|
||||
if (chan[i]->remote_mps > mps && num_scid > 1) {
|
||||
BT_ERR("chan %p decreased MPS %u -> %u", chan[i],
|
||||
chan[i]->remote_mps, mps);
|
||||
result = L2CAP_RECONF_INVALID_MPS;
|
||||
|
||||
@@ -1498,6 +1498,9 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)
|
||||
{
|
||||
struct sock *sk, *parent = chan->data;
|
||||
|
||||
if (!parent)
|
||||
return NULL;
|
||||
|
||||
lock_sock(parent);
|
||||
|
||||
/* Check for backlog size */
|
||||
@@ -1657,6 +1660,9 @@ static void l2cap_sock_state_change_cb(struct l2cap_chan *chan, int state,
|
||||
{
|
||||
struct sock *sk = chan->data;
|
||||
|
||||
if (!sk)
|
||||
return;
|
||||
|
||||
sk->sk_state = state;
|
||||
|
||||
if (err)
|
||||
@@ -1758,6 +1764,9 @@ static long l2cap_sock_get_sndtimeo_cb(struct l2cap_chan *chan)
|
||||
{
|
||||
struct sock *sk = chan->data;
|
||||
|
||||
if (!sk)
|
||||
return 0;
|
||||
|
||||
return READ_ONCE(sk->sk_sndtimeo);
|
||||
}
|
||||
|
||||
|
||||
@@ -1715,9 +1715,12 @@ static int rfcomm_recv_data(struct rfcomm_session *s, u8 dlci, int pf, struct sk
|
||||
}
|
||||
|
||||
if (pf && d->cfc) {
|
||||
u8 credits = *(u8 *) skb->data; skb_pull(skb, 1);
|
||||
u8 *credits = skb_pull_data(skb, 1);
|
||||
|
||||
d->tx_credits += credits;
|
||||
if (!credits)
|
||||
goto drop;
|
||||
|
||||
d->tx_credits += *credits;
|
||||
if (d->tx_credits)
|
||||
clear_bit(RFCOMM_TX_THROTTLED, &d->flags);
|
||||
}
|
||||
|
||||
+40
-22
@@ -472,9 +472,13 @@ static struct sock *sco_get_sock_listen(bdaddr_t *src)
|
||||
sk1 = sk;
|
||||
}
|
||||
|
||||
sk = sk ? sk : sk1;
|
||||
if (sk)
|
||||
sock_hold(sk);
|
||||
|
||||
read_unlock(&sco_sk_list.lock);
|
||||
|
||||
return sk ? sk : sk1;
|
||||
return sk;
|
||||
}
|
||||
|
||||
static void sco_sock_destruct(struct sock *sk)
|
||||
@@ -515,11 +519,13 @@ static void sco_sock_kill(struct sock *sk)
|
||||
BT_DBG("sk %p state %d", sk, sk->sk_state);
|
||||
|
||||
/* Sock is dead, so set conn->sk to NULL to avoid possible UAF */
|
||||
lock_sock(sk);
|
||||
if (sco_pi(sk)->conn) {
|
||||
sco_conn_lock(sco_pi(sk)->conn);
|
||||
sco_pi(sk)->conn->sk = NULL;
|
||||
sco_conn_unlock(sco_pi(sk)->conn);
|
||||
}
|
||||
release_sock(sk);
|
||||
|
||||
/* Kill poor orphan */
|
||||
bt_sock_unlink(&sco_sk_list, sk);
|
||||
@@ -1365,40 +1371,51 @@ static int sco_sock_release(struct socket *sock)
|
||||
|
||||
static void sco_conn_ready(struct sco_conn *conn)
|
||||
{
|
||||
struct sock *parent;
|
||||
struct sock *sk = conn->sk;
|
||||
struct sock *parent, *sk;
|
||||
|
||||
sco_conn_lock(conn);
|
||||
sk = sco_sock_hold(conn);
|
||||
sco_conn_unlock(conn);
|
||||
|
||||
BT_DBG("conn %p", conn);
|
||||
|
||||
if (sk) {
|
||||
lock_sock(sk);
|
||||
sco_sock_clear_timer(sk);
|
||||
sk->sk_state = BT_CONNECTED;
|
||||
sk->sk_state_change(sk);
|
||||
release_sock(sk);
|
||||
} else {
|
||||
sco_conn_lock(conn);
|
||||
|
||||
if (!conn->hcon) {
|
||||
sco_conn_unlock(conn);
|
||||
return;
|
||||
/* conn->sk may have become NULL if racing with sk close, but
|
||||
* due to held hdev->lock, it can't become different sk.
|
||||
*/
|
||||
if (conn->sk) {
|
||||
sco_sock_clear_timer(sk);
|
||||
sk->sk_state = BT_CONNECTED;
|
||||
sk->sk_state_change(sk);
|
||||
}
|
||||
|
||||
release_sock(sk);
|
||||
sock_put(sk);
|
||||
} else {
|
||||
if (!conn->hcon)
|
||||
return;
|
||||
|
||||
lockdep_assert_held(&conn->hcon->hdev->lock);
|
||||
|
||||
parent = sco_get_sock_listen(&conn->hcon->src);
|
||||
if (!parent) {
|
||||
sco_conn_unlock(conn);
|
||||
if (!parent)
|
||||
return;
|
||||
}
|
||||
|
||||
lock_sock(parent);
|
||||
|
||||
sco_conn_lock(conn);
|
||||
|
||||
/* hdev->lock guarantees conn->sk == NULL still here */
|
||||
|
||||
if (parent->sk_state != BT_LISTEN)
|
||||
goto release;
|
||||
|
||||
sk = sco_sock_alloc(sock_net(parent), NULL,
|
||||
BTPROTO_SCO, GFP_ATOMIC, 0);
|
||||
if (!sk) {
|
||||
release_sock(parent);
|
||||
sco_conn_unlock(conn);
|
||||
return;
|
||||
}
|
||||
if (!sk)
|
||||
goto release;
|
||||
|
||||
sco_sock_init(sk, parent);
|
||||
|
||||
@@ -1417,9 +1434,10 @@ static void sco_conn_ready(struct sco_conn *conn)
|
||||
/* Wake up parent */
|
||||
parent->sk_data_ready(parent);
|
||||
|
||||
release_sock(parent);
|
||||
|
||||
release:
|
||||
sco_conn_unlock(conn);
|
||||
release_sock(parent);
|
||||
sock_put(parent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -371,7 +371,7 @@ static void netdev_name_node_alt_free(struct rcu_head *head)
|
||||
static void __netdev_name_node_alt_destroy(struct netdev_name_node *name_node)
|
||||
{
|
||||
netdev_name_node_del(name_node);
|
||||
list_del(&name_node->list);
|
||||
list_del_rcu(&name_node->list);
|
||||
call_rcu(&name_node->rcu, netdev_name_node_alt_free);
|
||||
}
|
||||
|
||||
|
||||
+13
-10
@@ -608,14 +608,16 @@ EXPORT_SYMBOL_GPL(__netpoll_setup);
|
||||
/*
|
||||
* Returns a pointer to a string representation of the identifier used
|
||||
* to select the egress interface for the given netpoll instance. buf
|
||||
* must be a buffer of length at least MAC_ADDR_STR_LEN + 1.
|
||||
* is used to format np->dev_mac when np->dev_name is empty; bufsz must
|
||||
* be at least MAC_ADDR_STR_LEN + 1 to fit the formatted MAC address
|
||||
* and its NUL terminator.
|
||||
*/
|
||||
static char *egress_dev(struct netpoll *np, char *buf)
|
||||
static char *egress_dev(struct netpoll *np, char *buf, size_t bufsz)
|
||||
{
|
||||
if (np->dev_name[0])
|
||||
return np->dev_name;
|
||||
|
||||
snprintf(buf, MAC_ADDR_STR_LEN, "%pM", np->dev_mac);
|
||||
snprintf(buf, bufsz, "%pM", np->dev_mac);
|
||||
return buf;
|
||||
}
|
||||
|
||||
@@ -645,7 +647,7 @@ static int netpoll_take_ipv6(struct netpoll *np, struct net_device *ndev)
|
||||
|
||||
if (!IS_ENABLED(CONFIG_IPV6)) {
|
||||
np_err(np, "IPv6 is not supported %s, aborting\n",
|
||||
egress_dev(np, buf));
|
||||
egress_dev(np, buf, sizeof(buf)));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -667,7 +669,7 @@ static int netpoll_take_ipv6(struct netpoll *np, struct net_device *ndev)
|
||||
}
|
||||
if (err) {
|
||||
np_err(np, "no IPv6 address for %s, aborting\n",
|
||||
egress_dev(np, buf));
|
||||
egress_dev(np, buf, sizeof(buf)));
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -687,14 +689,14 @@ static int netpoll_take_ipv4(struct netpoll *np, struct net_device *ndev)
|
||||
in_dev = __in_dev_get_rtnl(ndev);
|
||||
if (!in_dev) {
|
||||
np_err(np, "no IP address for %s, aborting\n",
|
||||
egress_dev(np, buf));
|
||||
egress_dev(np, buf, sizeof(buf)));
|
||||
return -EDESTADDRREQ;
|
||||
}
|
||||
|
||||
ifa = rtnl_dereference(in_dev->ifa_list);
|
||||
if (!ifa) {
|
||||
np_err(np, "no IP address for %s, aborting\n",
|
||||
egress_dev(np, buf));
|
||||
egress_dev(np, buf, sizeof(buf)));
|
||||
return -EDESTADDRREQ;
|
||||
}
|
||||
|
||||
@@ -736,7 +738,8 @@ int netpoll_setup(struct netpoll *np)
|
||||
ndev = dev_getbyhwaddr(net, ARPHRD_ETHER, np->dev_mac);
|
||||
|
||||
if (!ndev) {
|
||||
np_err(np, "%s doesn't exist, aborting\n", egress_dev(np, buf));
|
||||
np_err(np, "%s doesn't exist, aborting\n",
|
||||
egress_dev(np, buf, sizeof(buf)));
|
||||
err = -ENODEV;
|
||||
goto unlock;
|
||||
}
|
||||
@@ -744,14 +747,14 @@ int netpoll_setup(struct netpoll *np)
|
||||
|
||||
if (netdev_master_upper_dev_get(ndev)) {
|
||||
np_err(np, "%s is a slave device, aborting\n",
|
||||
egress_dev(np, buf));
|
||||
egress_dev(np, buf, sizeof(buf)));
|
||||
err = -EBUSY;
|
||||
goto put;
|
||||
}
|
||||
|
||||
if (!netif_running(ndev)) {
|
||||
np_info(np, "device %s not up yet, forcing it\n",
|
||||
egress_dev(np, buf));
|
||||
egress_dev(np, buf, sizeof(buf)));
|
||||
|
||||
err = dev_open(ndev, NULL);
|
||||
if (err) {
|
||||
|
||||
@@ -1572,6 +1572,7 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb,
|
||||
port_guid.vf = ivi.vf;
|
||||
|
||||
memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac));
|
||||
memset(&vf_broadcast, 0, sizeof(vf_broadcast));
|
||||
memcpy(vf_broadcast.broadcast, dev->broadcast, dev->addr_len);
|
||||
vf_vlan.vlan = ivi.vlan;
|
||||
vf_vlan.qos = ivi.qos;
|
||||
|
||||
+12
-2
@@ -124,9 +124,14 @@ static void ah_output_done(void *data, int err)
|
||||
struct iphdr *top_iph = ip_hdr(skb);
|
||||
struct ip_auth_hdr *ah = ip_auth_hdr(skb);
|
||||
int ihl = ip_hdrlen(skb);
|
||||
int seqhi_len = 0;
|
||||
__be32 *seqhi;
|
||||
|
||||
if (x->props.flags & XFRM_STATE_ESN)
|
||||
seqhi_len = sizeof(*seqhi);
|
||||
iph = AH_SKB_CB(skb)->tmp;
|
||||
icv = ah_tmp_icv(iph, ihl);
|
||||
seqhi = (__be32 *)((char *)iph + ihl);
|
||||
icv = ah_tmp_icv(seqhi, seqhi_len);
|
||||
memcpy(ah->auth_data, icv, ahp->icv_trunc_len);
|
||||
|
||||
top_iph->tos = iph->tos;
|
||||
@@ -270,12 +275,17 @@ static void ah_input_done(void *data, int err)
|
||||
struct ip_auth_hdr *ah = ip_auth_hdr(skb);
|
||||
int ihl = ip_hdrlen(skb);
|
||||
int ah_hlen = (ah->hdrlen + 2) << 2;
|
||||
int seqhi_len = 0;
|
||||
__be32 *seqhi;
|
||||
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
if (x->props.flags & XFRM_STATE_ESN)
|
||||
seqhi_len = sizeof(*seqhi);
|
||||
work_iph = AH_SKB_CB(skb)->tmp;
|
||||
auth_data = ah_tmp_auth(work_iph, ihl);
|
||||
seqhi = (__be32 *)((char *)work_iph + ihl);
|
||||
auth_data = ah_tmp_auth(seqhi, seqhi_len);
|
||||
icv = ah_tmp_icv(auth_data, ahp->icv_trunc_len);
|
||||
|
||||
err = crypto_memneq(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG : 0;
|
||||
|
||||
+2
-1
@@ -873,7 +873,8 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
|
||||
nfrags = 1;
|
||||
|
||||
goto skip_cow;
|
||||
} else if (!skb_has_frag_list(skb)) {
|
||||
} else if (!skb_has_frag_list(skb) &&
|
||||
!skb_has_shared_frag(skb)) {
|
||||
nfrags = skb_shinfo(skb)->nr_frags;
|
||||
nfrags++;
|
||||
|
||||
|
||||
+36
-22
@@ -122,16 +122,29 @@
|
||||
* contradict to specs provided this delay is small enough.
|
||||
*/
|
||||
|
||||
#define IGMP_V1_SEEN(in_dev) \
|
||||
(IPV4_DEVCONF_ALL_RO(dev_net(in_dev->dev), FORCE_IGMP_VERSION) == 1 || \
|
||||
IN_DEV_CONF_GET((in_dev), FORCE_IGMP_VERSION) == 1 || \
|
||||
((in_dev)->mr_v1_seen && \
|
||||
time_before(jiffies, (in_dev)->mr_v1_seen)))
|
||||
#define IGMP_V2_SEEN(in_dev) \
|
||||
(IPV4_DEVCONF_ALL_RO(dev_net(in_dev->dev), FORCE_IGMP_VERSION) == 2 || \
|
||||
IN_DEV_CONF_GET((in_dev), FORCE_IGMP_VERSION) == 2 || \
|
||||
((in_dev)->mr_v2_seen && \
|
||||
time_before(jiffies, (in_dev)->mr_v2_seen)))
|
||||
static bool IGMP_V1_SEEN(const struct in_device *in_dev)
|
||||
{
|
||||
unsigned long seen;
|
||||
|
||||
if (IPV4_DEVCONF_ALL_RO(dev_net(in_dev->dev), FORCE_IGMP_VERSION) == 1)
|
||||
return true;
|
||||
if (IN_DEV_CONF_GET((in_dev), FORCE_IGMP_VERSION) == 1)
|
||||
return true;
|
||||
seen = READ_ONCE(in_dev->mr_v1_seen);
|
||||
return seen && time_before(jiffies, seen);
|
||||
}
|
||||
|
||||
static bool IGMP_V2_SEEN(const struct in_device *in_dev)
|
||||
{
|
||||
unsigned long seen;
|
||||
|
||||
if (IPV4_DEVCONF_ALL_RO(dev_net(in_dev->dev), FORCE_IGMP_VERSION) == 2)
|
||||
return true;
|
||||
if (IN_DEV_CONF_GET((in_dev), FORCE_IGMP_VERSION) == 2)
|
||||
return true;
|
||||
seen = READ_ONCE(in_dev->mr_v2_seen);
|
||||
return seen && time_before(jiffies, seen);
|
||||
}
|
||||
|
||||
static int unsolicited_report_interval(struct in_device *in_dev)
|
||||
{
|
||||
@@ -954,23 +967,21 @@ static bool igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb,
|
||||
int max_delay;
|
||||
int mark = 0;
|
||||
struct net *net = dev_net(in_dev->dev);
|
||||
|
||||
unsigned long seen;
|
||||
|
||||
if (len == 8) {
|
||||
seen = jiffies + READ_ONCE(in_dev->mr_qrv) * READ_ONCE(in_dev->mr_qi) +
|
||||
READ_ONCE(in_dev->mr_qri);
|
||||
if (ih->code == 0) {
|
||||
/* Alas, old v1 router presents here. */
|
||||
|
||||
max_delay = IGMP_QUERY_RESPONSE_INTERVAL;
|
||||
in_dev->mr_v1_seen = jiffies +
|
||||
(in_dev->mr_qrv * in_dev->mr_qi) +
|
||||
in_dev->mr_qri;
|
||||
WRITE_ONCE(in_dev->mr_v1_seen, seen);
|
||||
group = 0;
|
||||
} else {
|
||||
/* v2 router present */
|
||||
max_delay = ih->code*(HZ/IGMP_TIMER_SCALE);
|
||||
in_dev->mr_v2_seen = jiffies +
|
||||
(in_dev->mr_qrv * in_dev->mr_qi) +
|
||||
in_dev->mr_qri;
|
||||
WRITE_ONCE(in_dev->mr_v2_seen, seen);
|
||||
}
|
||||
/* cancel the interface change timer */
|
||||
WRITE_ONCE(in_dev->mr_ifc_count, 0);
|
||||
@@ -995,6 +1006,8 @@ static bool igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb,
|
||||
if (!max_delay)
|
||||
max_delay = 1; /* can't mod w/ 0 */
|
||||
} else { /* v3 */
|
||||
unsigned long mr_qi;
|
||||
|
||||
if (!pskb_may_pull(skb, sizeof(struct igmpv3_query)))
|
||||
return true;
|
||||
|
||||
@@ -1015,15 +1028,16 @@ static bool igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb,
|
||||
* received value was zero, use the default or statically
|
||||
* configured value.
|
||||
*/
|
||||
in_dev->mr_qrv = ih3->qrv ?: READ_ONCE(net->ipv4.sysctl_igmp_qrv);
|
||||
in_dev->mr_qi = IGMPV3_QQIC(ih3->qqic)*HZ ?: IGMP_QUERY_INTERVAL;
|
||||
|
||||
WRITE_ONCE(in_dev->mr_qrv,
|
||||
ih3->qrv ?: READ_ONCE(net->ipv4.sysctl_igmp_qrv));
|
||||
mr_qi = IGMPV3_QQIC(ih3->qqic)*HZ ?: IGMP_QUERY_INTERVAL;
|
||||
WRITE_ONCE(in_dev->mr_qi, mr_qi);
|
||||
/* RFC3376, 8.3. Query Response Interval:
|
||||
* The number of seconds represented by the [Query Response
|
||||
* Interval] must be less than the [Query Interval].
|
||||
*/
|
||||
if (in_dev->mr_qri >= in_dev->mr_qi)
|
||||
in_dev->mr_qri = (in_dev->mr_qi/HZ - 1)*HZ;
|
||||
if (READ_ONCE(in_dev->mr_qri) >= mr_qi)
|
||||
WRITE_ONCE(in_dev->mr_qri, (mr_qi/HZ - 1) * HZ);
|
||||
|
||||
if (!group) { /* general query */
|
||||
if (ih3->nsrcs)
|
||||
|
||||
+2
-1
@@ -179,7 +179,8 @@ struct inet_peer *inet_getpeer(struct inet_peer_base *base,
|
||||
seq = read_seqbegin(&base->lock);
|
||||
p = lookup(daddr, base, seq, NULL, &gc_cnt, &parent, &pp);
|
||||
|
||||
if (p)
|
||||
/* Make sure tree was not modified during our lookup. */
|
||||
if (p && !read_seqretry(&base->lock, seq))
|
||||
return p;
|
||||
|
||||
/* retry an exact lookup, taking the lock before.
|
||||
|
||||
@@ -1233,6 +1233,8 @@ alloc_new_skb:
|
||||
if (err < 0)
|
||||
goto error;
|
||||
copy = err;
|
||||
if (!(flags & MSG_NO_SHARED_FRAGS))
|
||||
skb_shinfo(skb)->flags |= SKBFL_SHARED_FRAG;
|
||||
wmem_alloc_delta += copy;
|
||||
} else if (!zc) {
|
||||
int i = skb_shinfo(skb)->nr_frags;
|
||||
|
||||
+6
-4
@@ -537,15 +537,16 @@ static netdev_tx_t reg_vif_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
};
|
||||
int err;
|
||||
|
||||
rcu_read_lock();
|
||||
err = ipmr_fib_lookup(net, &fl4, &mrt);
|
||||
if (err < 0) {
|
||||
rcu_read_unlock();
|
||||
kfree_skb(skb);
|
||||
return err;
|
||||
}
|
||||
|
||||
DEV_STATS_ADD(dev, tx_bytes, skb->len);
|
||||
DEV_STATS_INC(dev, tx_packets);
|
||||
rcu_read_lock();
|
||||
|
||||
/* Pairs with WRITE_ONCE() in vif_add() and vif_delete() */
|
||||
ipmr_cache_report(mrt, skb, READ_ONCE(mrt->mroute_reg_vif_num),
|
||||
@@ -1112,11 +1113,12 @@ static int ipmr_cache_report(const struct mr_table *mrt,
|
||||
msg->im_vif_hi = vifi >> 8;
|
||||
ipv4_pktinfo_prepare(mroute_sk, pkt, false);
|
||||
memcpy(skb->cb, pkt->cb, sizeof(skb->cb));
|
||||
/* Add our header */
|
||||
igmp = skb_put(skb, sizeof(struct igmphdr));
|
||||
/* Add our header.
|
||||
* Note that code, csum and group fields are cleared.
|
||||
*/
|
||||
igmp = skb_put_zero(skb, sizeof(struct igmphdr));
|
||||
igmp->type = assert;
|
||||
msg->im_msgtype = assert;
|
||||
igmp->code = 0;
|
||||
ip_hdr(skb)->tot_len = htons(skb->len); /* Fix the length */
|
||||
skb->transport_header = skb->network_header;
|
||||
}
|
||||
|
||||
@@ -94,6 +94,9 @@ struct sock *nf_sk_lookup_slow_v4(struct net *net, const struct sk_buff *skb,
|
||||
#endif
|
||||
int doff = 0;
|
||||
|
||||
if (ntohs(iph->frag_off) & IP_OFFSET)
|
||||
return NULL;
|
||||
|
||||
if (iph->protocol == IPPROTO_UDP || iph->protocol == IPPROTO_TCP) {
|
||||
struct tcphdr _hdr;
|
||||
struct udphdr *hp;
|
||||
|
||||
+6
-8
@@ -1827,7 +1827,6 @@ INDIRECT_CALLABLE_DECLARE(struct dst_entry *ipv4_dst_check(struct dst_entry *,
|
||||
int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
enum skb_drop_reason reason;
|
||||
struct sock *rsk;
|
||||
|
||||
reason = psp_sk_rx_policy_check(sk, skb);
|
||||
if (reason)
|
||||
@@ -1863,24 +1862,21 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
|
||||
return 0;
|
||||
if (nsk != sk) {
|
||||
reason = tcp_child_process(sk, nsk, skb);
|
||||
if (reason) {
|
||||
rsk = nsk;
|
||||
sock_put(nsk);
|
||||
if (reason)
|
||||
goto reset;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
sock_rps_save_rxhash(sk, skb);
|
||||
|
||||
reason = tcp_rcv_state_process(sk, skb);
|
||||
if (reason) {
|
||||
rsk = sk;
|
||||
if (reason)
|
||||
goto reset;
|
||||
}
|
||||
return 0;
|
||||
|
||||
reset:
|
||||
tcp_v4_send_reset(rsk, skb, sk_rst_convert_drop_reason(reason));
|
||||
tcp_v4_send_reset(sk, skb, sk_rst_convert_drop_reason(reason));
|
||||
discard:
|
||||
sk_skb_reason_drop(sk, skb, reason);
|
||||
/* Be careful here. If this function gets more complicated and
|
||||
@@ -2193,8 +2189,10 @@ lookup:
|
||||
|
||||
rst_reason = sk_rst_convert_drop_reason(drop_reason);
|
||||
tcp_v4_send_reset(nsk, skb, rst_reason);
|
||||
sock_put(nsk);
|
||||
goto discard_and_relse;
|
||||
}
|
||||
sock_put(nsk);
|
||||
sock_put(sk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1012,6 +1012,6 @@ enum skb_drop_reason tcp_child_process(struct sock *parent, struct sock *child,
|
||||
}
|
||||
|
||||
bh_unlock_sock(child);
|
||||
sock_put(child);
|
||||
|
||||
return reason;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user