mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 22:21:40 +00:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
This commit is contained in:
commit
d489ded1a3
@ -651,16 +651,15 @@ tcp_rmem - vector of 3 INTEGERs: min, default, max
|
||||
|
||||
default: initial size of receive buffer used by TCP sockets.
|
||||
This value overrides net.core.rmem_default used by other protocols.
|
||||
Default: 87380 bytes. This value results in window of 65535 with
|
||||
default setting of tcp_adv_win_scale and tcp_app_win:0 and a bit
|
||||
less for default tcp_app_win. See below about these variables.
|
||||
Default: 131072 bytes.
|
||||
This value results in initial window of 65535.
|
||||
|
||||
max: maximal size of receive buffer allowed for automatically
|
||||
selected receiver buffers for TCP socket. This value does not override
|
||||
net.core.rmem_max. Calling setsockopt() with SO_RCVBUF disables
|
||||
automatic tuning of that socket's receive buffer size, in which
|
||||
case this value is ignored.
|
||||
Default: between 87380B and 6MB, depending on RAM size.
|
||||
Default: between 131072 and 6MB, depending on RAM size.
|
||||
|
||||
tcp_sack - BOOLEAN
|
||||
Enable select acknowledgments (SACKS).
|
||||
|
@ -272,6 +272,22 @@ to the mailing list, e.g.::
|
||||
Posting as one thread is discouraged because it confuses patchwork
|
||||
(as of patchwork 2.2.2).
|
||||
|
||||
Can I reproduce the checks from patchwork on my local machine?
|
||||
--------------------------------------------------------------
|
||||
|
||||
Checks in patchwork are mostly simple wrappers around existing kernel
|
||||
scripts, the sources are available at:
|
||||
|
||||
https://github.com/kuba-moo/nipa/tree/master/tests
|
||||
|
||||
Running all the builds and checks locally is a pain, can I post my patches and have the patchwork bot validate them?
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
No, you must ensure that your patches are ready by testing them locally
|
||||
before posting to the mailing list. The patchwork build bot instance
|
||||
gets overloaded very easily and netdev@vger really doesn't need more
|
||||
traffic if we can help it.
|
||||
|
||||
Any other tips to help ensure my net/net-next patch gets OK'd?
|
||||
--------------------------------------------------------------
|
||||
Attention to detail. Re-read your own work as if you were the
|
||||
|
@ -3743,16 +3743,7 @@ static int __init idt77252_init(void)
|
||||
struct sk_buff *skb;
|
||||
|
||||
printk("%s: at %p\n", __func__, idt77252_init);
|
||||
|
||||
if (sizeof(skb->cb) < sizeof(struct atm_skb_data) +
|
||||
sizeof(struct idt77252_skb_prv)) {
|
||||
printk(KERN_ERR "%s: skb->cb is too small (%lu < %lu)\n",
|
||||
__func__, (unsigned long) sizeof(skb->cb),
|
||||
(unsigned long) sizeof(struct atm_skb_data) +
|
||||
sizeof(struct idt77252_skb_prv));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
BUILD_BUG_ON(sizeof(skb->cb) < sizeof(struct idt77252_skb_prv) + sizeof(struct atm_skb_data));
|
||||
return pci_register_driver(&idt77252_driver);
|
||||
}
|
||||
|
||||
|
@ -789,7 +789,7 @@ struct idt77252_skb_prv {
|
||||
struct scqe tbd; /* Transmit Buffer Descriptor */
|
||||
dma_addr_t paddr; /* DMA handle */
|
||||
u32 pool; /* sb_pool handle */
|
||||
};
|
||||
} __packed;
|
||||
|
||||
#define IDT77252_PRV_TBD(skb) \
|
||||
(((struct idt77252_skb_prv *)(ATM_SKB(skb)+1))->tbd)
|
||||
|
@ -1279,10 +1279,18 @@
|
||||
#define MDIO_PMA_10GBR_FECCTRL 0x00ab
|
||||
#endif
|
||||
|
||||
#ifndef MDIO_PMA_RX_CTRL1
|
||||
#define MDIO_PMA_RX_CTRL1 0x8051
|
||||
#endif
|
||||
|
||||
#ifndef MDIO_PCS_DIG_CTRL
|
||||
#define MDIO_PCS_DIG_CTRL 0x8000
|
||||
#endif
|
||||
|
||||
#ifndef MDIO_PCS_DIGITAL_STAT
|
||||
#define MDIO_PCS_DIGITAL_STAT 0x8010
|
||||
#endif
|
||||
|
||||
#ifndef MDIO_AN_XNP
|
||||
#define MDIO_AN_XNP 0x0016
|
||||
#endif
|
||||
@ -1358,6 +1366,8 @@
|
||||
#define XGBE_KR_TRAINING_ENABLE BIT(1)
|
||||
|
||||
#define XGBE_PCS_CL37_BP BIT(12)
|
||||
#define XGBE_PCS_PSEQ_STATE_MASK 0x1c
|
||||
#define XGBE_PCS_PSEQ_STATE_POWER_GOOD 0x10
|
||||
|
||||
#define XGBE_AN_CL37_INT_CMPLT BIT(0)
|
||||
#define XGBE_AN_CL37_INT_MASK 0x01
|
||||
@ -1375,6 +1385,10 @@
|
||||
#define XGBE_PMA_CDR_TRACK_EN_OFF 0x00
|
||||
#define XGBE_PMA_CDR_TRACK_EN_ON 0x01
|
||||
|
||||
#define XGBE_PMA_RX_RST_0_MASK BIT(4)
|
||||
#define XGBE_PMA_RX_RST_0_RESET_ON 0x10
|
||||
#define XGBE_PMA_RX_RST_0_RESET_OFF 0x00
|
||||
|
||||
/* Bit setting and getting macros
|
||||
* The get macro will extract the current bit field value from within
|
||||
* the variable
|
||||
|
@ -1368,6 +1368,7 @@ static void xgbe_stop(struct xgbe_prv_data *pdata)
|
||||
return;
|
||||
|
||||
netif_tx_stop_all_queues(netdev);
|
||||
netif_carrier_off(pdata->netdev);
|
||||
|
||||
xgbe_stop_timers(pdata);
|
||||
flush_workqueue(pdata->dev_workqueue);
|
||||
|
@ -1345,7 +1345,7 @@ static void xgbe_phy_status(struct xgbe_prv_data *pdata)
|
||||
&an_restart);
|
||||
if (an_restart) {
|
||||
xgbe_phy_config_aneg(pdata);
|
||||
return;
|
||||
goto adjust_link;
|
||||
}
|
||||
|
||||
if (pdata->phy.link) {
|
||||
@ -1396,7 +1396,6 @@ static void xgbe_phy_stop(struct xgbe_prv_data *pdata)
|
||||
pdata->phy_if.phy_impl.stop(pdata);
|
||||
|
||||
pdata->phy.link = 0;
|
||||
netif_carrier_off(pdata->netdev);
|
||||
|
||||
xgbe_phy_adjust_link(pdata);
|
||||
}
|
||||
|
@ -922,6 +922,9 @@ static bool xgbe_phy_belfuse_phy_quirks(struct xgbe_prv_data *pdata)
|
||||
if ((phy_id & 0xfffffff0) != 0x03625d10)
|
||||
return false;
|
||||
|
||||
/* Reset PHY - wait for self-clearing reset bit to clear */
|
||||
genphy_soft_reset(phy_data->phydev);
|
||||
|
||||
/* Disable RGMII mode */
|
||||
phy_write(phy_data->phydev, 0x18, 0x7007);
|
||||
reg = phy_read(phy_data->phydev, 0x18);
|
||||
@ -1953,6 +1956,27 @@ static void xgbe_phy_set_redrv_mode(struct xgbe_prv_data *pdata)
|
||||
xgbe_phy_put_comm_ownership(pdata);
|
||||
}
|
||||
|
||||
static void xgbe_phy_rx_reset(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
int reg;
|
||||
|
||||
reg = XMDIO_READ_BITS(pdata, MDIO_MMD_PCS, MDIO_PCS_DIGITAL_STAT,
|
||||
XGBE_PCS_PSEQ_STATE_MASK);
|
||||
if (reg == XGBE_PCS_PSEQ_STATE_POWER_GOOD) {
|
||||
/* Mailbox command timed out, reset of RX block is required.
|
||||
* This can be done by asseting the reset bit and wait for
|
||||
* its compeletion.
|
||||
*/
|
||||
XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_RX_CTRL1,
|
||||
XGBE_PMA_RX_RST_0_MASK, XGBE_PMA_RX_RST_0_RESET_ON);
|
||||
ndelay(20);
|
||||
XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_RX_CTRL1,
|
||||
XGBE_PMA_RX_RST_0_MASK, XGBE_PMA_RX_RST_0_RESET_OFF);
|
||||
usleep_range(40, 50);
|
||||
netif_err(pdata, link, pdata->netdev, "firmware mailbox reset performed\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata,
|
||||
unsigned int cmd, unsigned int sub_cmd)
|
||||
{
|
||||
@ -1960,9 +1984,11 @@ static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata,
|
||||
unsigned int wait;
|
||||
|
||||
/* Log if a previous command did not complete */
|
||||
if (XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS))
|
||||
if (XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS)) {
|
||||
netif_dbg(pdata, link, pdata->netdev,
|
||||
"firmware mailbox not ready for command\n");
|
||||
xgbe_phy_rx_reset(pdata);
|
||||
}
|
||||
|
||||
/* Construct the command */
|
||||
XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, cmd);
|
||||
@ -1984,6 +2010,9 @@ static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata,
|
||||
|
||||
netif_dbg(pdata, link, pdata->netdev,
|
||||
"firmware mailbox command did not complete\n");
|
||||
|
||||
/* Reset on error */
|
||||
xgbe_phy_rx_reset(pdata);
|
||||
}
|
||||
|
||||
static void xgbe_phy_rrc(struct xgbe_prv_data *pdata)
|
||||
@ -2584,6 +2613,14 @@ static int xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart)
|
||||
if (reg & MDIO_STAT1_LSTATUS)
|
||||
return 1;
|
||||
|
||||
if (pdata->phy.autoneg == AUTONEG_ENABLE &&
|
||||
phy_data->port_mode == XGBE_PORT_MODE_BACKPLANE) {
|
||||
if (!test_bit(XGBE_LINK_INIT, &pdata->dev_state)) {
|
||||
netif_carrier_off(pdata->netdev);
|
||||
*an_restart = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* No link, attempt a receiver reset cycle */
|
||||
if (phy_data->rrc_count++ > XGBE_RRC_FREQUENCY) {
|
||||
phy_data->rrc_count = 0;
|
||||
|
@ -71,8 +71,10 @@ static int aq_ndev_open(struct net_device *ndev)
|
||||
goto err_exit;
|
||||
|
||||
err = aq_nic_start(aq_nic);
|
||||
if (err < 0)
|
||||
if (err < 0) {
|
||||
aq_nic_stop(aq_nic);
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
err_exit:
|
||||
if (err < 0)
|
||||
|
@ -8984,9 +8984,10 @@ void bnxt_tx_disable(struct bnxt *bp)
|
||||
txr->dev_state = BNXT_DEV_STATE_CLOSING;
|
||||
}
|
||||
}
|
||||
/* Drop carrier first to prevent TX timeout */
|
||||
netif_carrier_off(bp->dev);
|
||||
/* Stop all TX queues */
|
||||
netif_tx_disable(bp->dev);
|
||||
netif_carrier_off(bp->dev);
|
||||
}
|
||||
|
||||
void bnxt_tx_enable(struct bnxt *bp)
|
||||
|
@ -471,8 +471,8 @@ static int bnxt_dl_info_get(struct devlink *dl, struct devlink_info_req *req,
|
||||
if (BNXT_PF(bp) && !bnxt_hwrm_get_nvm_cfg_ver(bp, &nvm_cfg_ver)) {
|
||||
u32 ver = nvm_cfg_ver.vu32;
|
||||
|
||||
sprintf(buf, "%X.%X.%X", (ver >> 16) & 0xF, (ver >> 8) & 0xF,
|
||||
ver & 0xF);
|
||||
sprintf(buf, "%d.%d.%d", (ver >> 16) & 0xf, (ver >> 8) & 0xf,
|
||||
ver & 0xf);
|
||||
rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_STORED,
|
||||
DEVLINK_INFO_VERSION_GENERIC_FW_PSID,
|
||||
buf);
|
||||
|
@ -46,6 +46,9 @@
|
||||
#define MAX_ULD_QSETS 16
|
||||
#define MAX_ULD_NPORTS 4
|
||||
|
||||
/* ulp_mem_io + ulptx_idata + payload + padding */
|
||||
#define MAX_IMM_ULPTX_WR_LEN (32 + 8 + 256 + 8)
|
||||
|
||||
/* CPL message priority levels */
|
||||
enum {
|
||||
CPL_PRIORITY_DATA = 0, /* data messages */
|
||||
|
@ -2846,17 +2846,22 @@ int t4_mgmt_tx(struct adapter *adap, struct sk_buff *skb)
|
||||
* @skb: the packet
|
||||
*
|
||||
* Returns true if a packet can be sent as an offload WR with immediate
|
||||
* data. We currently use the same limit as for Ethernet packets.
|
||||
* data.
|
||||
* FW_OFLD_TX_DATA_WR limits the payload to 255 bytes due to 8-bit field.
|
||||
* However, FW_ULPTX_WR commands have a 256 byte immediate only
|
||||
* payload limit.
|
||||
*/
|
||||
static inline int is_ofld_imm(const struct sk_buff *skb)
|
||||
{
|
||||
struct work_request_hdr *req = (struct work_request_hdr *)skb->data;
|
||||
unsigned long opcode = FW_WR_OP_G(ntohl(req->wr_hi));
|
||||
|
||||
if (opcode == FW_CRYPTO_LOOKASIDE_WR)
|
||||
if (unlikely(opcode == FW_ULPTX_WR))
|
||||
return skb->len <= MAX_IMM_ULPTX_WR_LEN;
|
||||
else if (opcode == FW_CRYPTO_LOOKASIDE_WR)
|
||||
return skb->len <= SGE_MAX_WR_LEN;
|
||||
else
|
||||
return skb->len <= MAX_IMM_TX_PKT_LEN;
|
||||
return skb->len <= MAX_IMM_OFLD_TX_DATA_WR_LEN;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -50,9 +50,6 @@
|
||||
#define MIN_RCV_WND (24 * 1024U)
|
||||
#define LOOPBACK(x) (((x) & htonl(0xff000000)) == htonl(0x7f000000))
|
||||
|
||||
/* ulp_mem_io + ulptx_idata + payload + padding */
|
||||
#define MAX_IMM_ULPTX_WR_LEN (32 + 8 + 256 + 8)
|
||||
|
||||
/* for TX: a skb must have a headroom of at least TX_HEADER_LEN bytes */
|
||||
#define TX_HEADER_LEN \
|
||||
(sizeof(struct fw_ofld_tx_data_wr) + sizeof(struct sge_opaque_hdr))
|
||||
|
@ -395,10 +395,20 @@ static u32 dpaa2_eth_run_xdp(struct dpaa2_eth_priv *priv,
|
||||
xdp.frame_sz = DPAA2_ETH_RX_BUF_RAW_SIZE;
|
||||
|
||||
err = xdp_do_redirect(priv->net_dev, &xdp, xdp_prog);
|
||||
if (unlikely(err))
|
||||
if (unlikely(err)) {
|
||||
addr = dma_map_page(priv->net_dev->dev.parent,
|
||||
virt_to_page(vaddr), 0,
|
||||
priv->rx_buf_size, DMA_BIDIRECTIONAL);
|
||||
if (unlikely(dma_mapping_error(priv->net_dev->dev.parent, addr))) {
|
||||
free_pages((unsigned long)vaddr, 0);
|
||||
} else {
|
||||
ch->buf_count++;
|
||||
dpaa2_eth_xdp_release_buf(priv, ch, addr);
|
||||
}
|
||||
ch->stats.xdp_drop++;
|
||||
else
|
||||
} else {
|
||||
ch->stats.xdp_redirect++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ config FSL_ENETC_VF
|
||||
|
||||
config FSL_ENETC_MDIO
|
||||
tristate "ENETC MDIO driver"
|
||||
depends on PCI
|
||||
depends on PCI && MDIO_DEVRES && MDIO_BUS
|
||||
help
|
||||
This driver supports NXP ENETC Central MDIO controller as a PCIe
|
||||
physical function (PF) device.
|
||||
|
@ -1157,14 +1157,15 @@ static void enetc_pf_remove(struct pci_dev *pdev)
|
||||
struct enetc_ndev_priv *priv;
|
||||
|
||||
priv = netdev_priv(si->ndev);
|
||||
enetc_phylink_destroy(priv);
|
||||
enetc_mdiobus_destroy(pf);
|
||||
|
||||
if (pf->num_vfs)
|
||||
enetc_sriov_configure(pdev, 0);
|
||||
|
||||
unregister_netdev(si->ndev);
|
||||
|
||||
enetc_phylink_destroy(priv);
|
||||
enetc_mdiobus_destroy(pf);
|
||||
|
||||
enetc_free_msix(priv);
|
||||
|
||||
enetc_free_si_resources(priv);
|
||||
|
@ -247,8 +247,13 @@ static void free_long_term_buff(struct ibmvnic_adapter *adapter,
|
||||
if (!ltb->buff)
|
||||
return;
|
||||
|
||||
/* VIOS automatically unmaps the long term buffer at remote
|
||||
* end for the following resets:
|
||||
* FAILOVER, MOBILITY, TIMEOUT.
|
||||
*/
|
||||
if (adapter->reset_reason != VNIC_RESET_FAILOVER &&
|
||||
adapter->reset_reason != VNIC_RESET_MOBILITY)
|
||||
adapter->reset_reason != VNIC_RESET_MOBILITY &&
|
||||
adapter->reset_reason != VNIC_RESET_TIMEOUT)
|
||||
send_request_unmap(adapter, ltb->map_id);
|
||||
dma_free_coherent(dev, ltb->size, ltb->buff, ltb->addr);
|
||||
}
|
||||
@ -1322,10 +1327,8 @@ static int __ibmvnic_close(struct net_device *netdev)
|
||||
|
||||
adapter->state = VNIC_CLOSING;
|
||||
rc = set_link_state(adapter, IBMVNIC_LOGICAL_LNK_DN);
|
||||
if (rc)
|
||||
return rc;
|
||||
adapter->state = VNIC_CLOSED;
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int ibmvnic_close(struct net_device *netdev)
|
||||
@ -1670,6 +1673,9 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
|
||||
skb_copy_from_linear_data(skb, dst, skb->len);
|
||||
}
|
||||
|
||||
/* post changes to long_term_buff *dst before VIOS accessing it */
|
||||
dma_wmb();
|
||||
|
||||
tx_pool->consumer_index =
|
||||
(tx_pool->consumer_index + 1) % tx_pool->num_buffers;
|
||||
|
||||
@ -2288,7 +2294,8 @@ static int ibmvnic_reset(struct ibmvnic_adapter *adapter,
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
/* If failover is pending don't schedule any other reset.
|
||||
/*
|
||||
* If failover is pending don't schedule any other reset.
|
||||
* Instead let the failover complete. If there is already a
|
||||
* a failover reset scheduled, we will detect and drop the
|
||||
* duplicate reset when walking the ->rwi_list below.
|
||||
@ -2308,14 +2315,11 @@ static int ibmvnic_reset(struct ibmvnic_adapter *adapter,
|
||||
goto err;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&adapter->rwi_lock, flags);
|
||||
|
||||
list_for_each(entry, &adapter->rwi_list) {
|
||||
tmp = list_entry(entry, struct ibmvnic_rwi, list);
|
||||
if (tmp->reset_reason == reason) {
|
||||
netdev_dbg(netdev, "Skipping matching reset, reason=%d\n",
|
||||
reason);
|
||||
spin_unlock_irqrestore(&adapter->rwi_lock, flags);
|
||||
ret = EBUSY;
|
||||
goto err;
|
||||
}
|
||||
@ -2323,8 +2327,6 @@ static int ibmvnic_reset(struct ibmvnic_adapter *adapter,
|
||||
|
||||
rwi = kzalloc(sizeof(*rwi), GFP_ATOMIC);
|
||||
if (!rwi) {
|
||||
spin_unlock_irqrestore(&adapter->rwi_lock, flags);
|
||||
ibmvnic_close(netdev);
|
||||
ret = ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
@ -2337,12 +2339,17 @@ static int ibmvnic_reset(struct ibmvnic_adapter *adapter,
|
||||
}
|
||||
rwi->reset_reason = reason;
|
||||
list_add_tail(&rwi->list, &adapter->rwi_list);
|
||||
spin_unlock_irqrestore(&adapter->rwi_lock, flags);
|
||||
netdev_dbg(adapter->netdev, "Scheduling reset (reason %d)\n", reason);
|
||||
schedule_work(&adapter->ibmvnic_reset);
|
||||
|
||||
return 0;
|
||||
ret = 0;
|
||||
err:
|
||||
/* ibmvnic_close() below can block, so drop the lock first */
|
||||
spin_unlock_irqrestore(&adapter->rwi_lock, flags);
|
||||
|
||||
if (ret == ENOMEM)
|
||||
ibmvnic_close(netdev);
|
||||
|
||||
return -ret;
|
||||
}
|
||||
|
||||
@ -2433,6 +2440,8 @@ restart_poll:
|
||||
offset = be16_to_cpu(next->rx_comp.off_frame_data);
|
||||
flags = next->rx_comp.flags;
|
||||
skb = rx_buff->skb;
|
||||
/* load long_term_buff before copying to skb */
|
||||
dma_rmb();
|
||||
skb_copy_to_linear_data(skb, rx_buff->data + offset,
|
||||
length);
|
||||
|
||||
@ -5346,7 +5355,18 @@ static int ibmvnic_remove(struct vio_dev *dev)
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&adapter->state_lock, flags);
|
||||
|
||||
/* If ibmvnic_reset() is scheduling a reset, wait for it to
|
||||
* finish. Then, set the state to REMOVING to prevent it from
|
||||
* scheduling any more work and to have reset functions ignore
|
||||
* any resets that have already been scheduled. Drop the lock
|
||||
* after setting state, so __ibmvnic_reset() which is called
|
||||
* from the flush_work() below, can make progress.
|
||||
*/
|
||||
spin_lock_irqsave(&adapter->rwi_lock, flags);
|
||||
adapter->state = VNIC_REMOVING;
|
||||
spin_unlock_irqrestore(&adapter->rwi_lock, flags);
|
||||
|
||||
spin_unlock_irqrestore(&adapter->state_lock, flags);
|
||||
|
||||
flush_work(&adapter->ibmvnic_reset);
|
||||
|
@ -31,7 +31,7 @@
|
||||
#define IBMVNIC_BUFFS_PER_POOL 100
|
||||
#define IBMVNIC_MAX_QUEUES 16
|
||||
#define IBMVNIC_MAX_QUEUE_SZ 4096
|
||||
#define IBMVNIC_MAX_IND_DESCS 128
|
||||
#define IBMVNIC_MAX_IND_DESCS 16
|
||||
#define IBMVNIC_IND_ARR_SZ (IBMVNIC_MAX_IND_DESCS * 32)
|
||||
|
||||
#define IBMVNIC_TSO_BUF_SZ 65536
|
||||
@ -1084,6 +1084,8 @@ struct ibmvnic_adapter {
|
||||
/* Used for serializatin of state field */
|
||||
spinlock_t state_lock;
|
||||
enum ibmvnic_reset_reason reset_reason;
|
||||
/* when taking both state and rwi locks, take state lock first */
|
||||
spinlock_t rwi_lock;
|
||||
struct list_head rwi_list;
|
||||
/* Used for serialization of rwi_list */
|
||||
spinlock_t rwi_lock;
|
||||
|
@ -141,6 +141,11 @@ static int mlx5_devlink_reload_down(struct devlink *devlink, bool netns_change,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (mlx5_lag_is_active(dev)) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "reload is unsupported in Lag mode\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
switch (action) {
|
||||
case DEVLINK_RELOAD_ACTION_DRIVER_REINIT:
|
||||
mlx5_unload_one(dev, false);
|
||||
@ -428,6 +433,10 @@ static int mlx5_devlink_enable_roce_validate(struct devlink *devlink, u32 id,
|
||||
NL_SET_ERR_MSG_MOD(extack, "Device doesn't support RoCE");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
if (mlx5_core_is_mp_slave(dev) || mlx5_lag_is_active(dev)) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Multi port slave/Lag device can't configure RoCE");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <net/flow_offload.h>
|
||||
#include <net/netfilter/nf_flow_table.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/refcount.h>
|
||||
#include <linux/xarray.h>
|
||||
|
||||
#include "lib/fs_chains.h"
|
||||
@ -52,11 +53,11 @@ struct mlx5_tc_ct_priv {
|
||||
struct mlx5_flow_table *ct_nat;
|
||||
struct mlx5_flow_table *post_ct;
|
||||
struct mutex control_lock; /* guards parallel adds/dels */
|
||||
struct mutex shared_counter_lock;
|
||||
struct mapping_ctx *zone_mapping;
|
||||
struct mapping_ctx *labels_mapping;
|
||||
enum mlx5_flow_namespace_type ns_type;
|
||||
struct mlx5_fs_chains *chains;
|
||||
spinlock_t ht_lock; /* protects ft entries */
|
||||
};
|
||||
|
||||
struct mlx5_ct_flow {
|
||||
@ -125,6 +126,10 @@ struct mlx5_ct_counter {
|
||||
bool is_shared;
|
||||
};
|
||||
|
||||
enum {
|
||||
MLX5_CT_ENTRY_FLAG_VALID,
|
||||
};
|
||||
|
||||
struct mlx5_ct_entry {
|
||||
struct rhash_head node;
|
||||
struct rhash_head tuple_node;
|
||||
@ -135,6 +140,12 @@ struct mlx5_ct_entry {
|
||||
struct mlx5_ct_tuple tuple;
|
||||
struct mlx5_ct_tuple tuple_nat;
|
||||
struct mlx5_ct_zone_rule zone_rules[2];
|
||||
|
||||
struct mlx5_tc_ct_priv *ct_priv;
|
||||
struct work_struct work;
|
||||
|
||||
refcount_t refcnt;
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
static const struct rhashtable_params cts_ht_params = {
|
||||
@ -742,6 +753,87 @@ err_attr:
|
||||
return err;
|
||||
}
|
||||
|
||||
static bool
|
||||
mlx5_tc_ct_entry_valid(struct mlx5_ct_entry *entry)
|
||||
{
|
||||
return test_bit(MLX5_CT_ENTRY_FLAG_VALID, &entry->flags);
|
||||
}
|
||||
|
||||
static struct mlx5_ct_entry *
|
||||
mlx5_tc_ct_entry_get(struct mlx5_tc_ct_priv *ct_priv, struct mlx5_ct_tuple *tuple)
|
||||
{
|
||||
struct mlx5_ct_entry *entry;
|
||||
|
||||
entry = rhashtable_lookup_fast(&ct_priv->ct_tuples_ht, tuple,
|
||||
tuples_ht_params);
|
||||
if (entry && mlx5_tc_ct_entry_valid(entry) &&
|
||||
refcount_inc_not_zero(&entry->refcnt)) {
|
||||
return entry;
|
||||
} else if (!entry) {
|
||||
entry = rhashtable_lookup_fast(&ct_priv->ct_tuples_nat_ht,
|
||||
tuple, tuples_nat_ht_params);
|
||||
if (entry && mlx5_tc_ct_entry_valid(entry) &&
|
||||
refcount_inc_not_zero(&entry->refcnt))
|
||||
return entry;
|
||||
}
|
||||
|
||||
return entry ? ERR_PTR(-EINVAL) : NULL;
|
||||
}
|
||||
|
||||
static void mlx5_tc_ct_entry_remove_from_tuples(struct mlx5_ct_entry *entry)
|
||||
{
|
||||
struct mlx5_tc_ct_priv *ct_priv = entry->ct_priv;
|
||||
|
||||
rhashtable_remove_fast(&ct_priv->ct_tuples_nat_ht,
|
||||
&entry->tuple_nat_node,
|
||||
tuples_nat_ht_params);
|
||||
rhashtable_remove_fast(&ct_priv->ct_tuples_ht, &entry->tuple_node,
|
||||
tuples_ht_params);
|
||||
}
|
||||
|
||||
static void mlx5_tc_ct_entry_del(struct mlx5_ct_entry *entry)
|
||||
{
|
||||
struct mlx5_tc_ct_priv *ct_priv = entry->ct_priv;
|
||||
|
||||
mlx5_tc_ct_entry_del_rules(ct_priv, entry);
|
||||
|
||||
spin_lock_bh(&ct_priv->ht_lock);
|
||||
mlx5_tc_ct_entry_remove_from_tuples(entry);
|
||||
spin_unlock_bh(&ct_priv->ht_lock);
|
||||
|
||||
mlx5_tc_ct_counter_put(ct_priv, entry);
|
||||
kfree(entry);
|
||||
}
|
||||
|
||||
static void
|
||||
mlx5_tc_ct_entry_put(struct mlx5_ct_entry *entry)
|
||||
{
|
||||
if (!refcount_dec_and_test(&entry->refcnt))
|
||||
return;
|
||||
|
||||
mlx5_tc_ct_entry_del(entry);
|
||||
}
|
||||
|
||||
static void mlx5_tc_ct_entry_del_work(struct work_struct *work)
|
||||
{
|
||||
struct mlx5_ct_entry *entry = container_of(work, struct mlx5_ct_entry, work);
|
||||
|
||||
mlx5_tc_ct_entry_del(entry);
|
||||
}
|
||||
|
||||
static void
|
||||
__mlx5_tc_ct_entry_put(struct mlx5_ct_entry *entry)
|
||||
{
|
||||
struct mlx5e_priv *priv;
|
||||
|
||||
if (!refcount_dec_and_test(&entry->refcnt))
|
||||
return;
|
||||
|
||||
priv = netdev_priv(entry->ct_priv->netdev);
|
||||
INIT_WORK(&entry->work, mlx5_tc_ct_entry_del_work);
|
||||
queue_work(priv->wq, &entry->work);
|
||||
}
|
||||
|
||||
static struct mlx5_ct_counter *
|
||||
mlx5_tc_ct_counter_create(struct mlx5_tc_ct_priv *ct_priv)
|
||||
{
|
||||
@ -793,16 +885,26 @@ mlx5_tc_ct_shared_counter_get(struct mlx5_tc_ct_priv *ct_priv,
|
||||
}
|
||||
|
||||
/* Use the same counter as the reverse direction */
|
||||
mutex_lock(&ct_priv->shared_counter_lock);
|
||||
rev_entry = rhashtable_lookup_fast(&ct_priv->ct_tuples_ht, &rev_tuple,
|
||||
tuples_ht_params);
|
||||
if (rev_entry) {
|
||||
if (refcount_inc_not_zero(&rev_entry->counter->refcount)) {
|
||||
mutex_unlock(&ct_priv->shared_counter_lock);
|
||||
return rev_entry->counter;
|
||||
}
|
||||
spin_lock_bh(&ct_priv->ht_lock);
|
||||
rev_entry = mlx5_tc_ct_entry_get(ct_priv, &rev_tuple);
|
||||
|
||||
if (IS_ERR(rev_entry)) {
|
||||
spin_unlock_bh(&ct_priv->ht_lock);
|
||||
goto create_counter;
|
||||
}
|
||||
mutex_unlock(&ct_priv->shared_counter_lock);
|
||||
|
||||
if (rev_entry && refcount_inc_not_zero(&rev_entry->counter->refcount)) {
|
||||
ct_dbg("Using shared counter entry=0x%p rev=0x%p\n", entry, rev_entry);
|
||||
shared_counter = rev_entry->counter;
|
||||
spin_unlock_bh(&ct_priv->ht_lock);
|
||||
|
||||
mlx5_tc_ct_entry_put(rev_entry);
|
||||
return shared_counter;
|
||||
}
|
||||
|
||||
spin_unlock_bh(&ct_priv->ht_lock);
|
||||
|
||||
create_counter:
|
||||
|
||||
shared_counter = mlx5_tc_ct_counter_create(ct_priv);
|
||||
if (IS_ERR(shared_counter))
|
||||
@ -865,10 +967,14 @@ mlx5_tc_ct_block_flow_offload_add(struct mlx5_ct_ft *ft,
|
||||
if (!meta_action)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
entry = rhashtable_lookup_fast(&ft->ct_entries_ht, &cookie,
|
||||
cts_ht_params);
|
||||
if (entry)
|
||||
return 0;
|
||||
spin_lock_bh(&ct_priv->ht_lock);
|
||||
entry = rhashtable_lookup_fast(&ft->ct_entries_ht, &cookie, cts_ht_params);
|
||||
if (entry && refcount_inc_not_zero(&entry->refcnt)) {
|
||||
spin_unlock_bh(&ct_priv->ht_lock);
|
||||
mlx5_tc_ct_entry_put(entry);
|
||||
return -EEXIST;
|
||||
}
|
||||
spin_unlock_bh(&ct_priv->ht_lock);
|
||||
|
||||
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
|
||||
if (!entry)
|
||||
@ -877,6 +983,8 @@ mlx5_tc_ct_block_flow_offload_add(struct mlx5_ct_ft *ft,
|
||||
entry->tuple.zone = ft->zone;
|
||||
entry->cookie = flow->cookie;
|
||||
entry->restore_cookie = meta_action->ct_metadata.cookie;
|
||||
refcount_set(&entry->refcnt, 2);
|
||||
entry->ct_priv = ct_priv;
|
||||
|
||||
err = mlx5_tc_ct_rule_to_tuple(&entry->tuple, flow_rule);
|
||||
if (err)
|
||||
@ -887,35 +995,40 @@ mlx5_tc_ct_block_flow_offload_add(struct mlx5_ct_ft *ft,
|
||||
if (err)
|
||||
goto err_set;
|
||||
|
||||
err = rhashtable_insert_fast(&ct_priv->ct_tuples_ht,
|
||||
&entry->tuple_node,
|
||||
tuples_ht_params);
|
||||
spin_lock_bh(&ct_priv->ht_lock);
|
||||
|
||||
err = rhashtable_lookup_insert_fast(&ft->ct_entries_ht, &entry->node,
|
||||
cts_ht_params);
|
||||
if (err)
|
||||
goto err_entries;
|
||||
|
||||
err = rhashtable_lookup_insert_fast(&ct_priv->ct_tuples_ht,
|
||||
&entry->tuple_node,
|
||||
tuples_ht_params);
|
||||
if (err)
|
||||
goto err_tuple;
|
||||
|
||||
if (memcmp(&entry->tuple, &entry->tuple_nat, sizeof(entry->tuple))) {
|
||||
err = rhashtable_insert_fast(&ct_priv->ct_tuples_nat_ht,
|
||||
&entry->tuple_nat_node,
|
||||
tuples_nat_ht_params);
|
||||
err = rhashtable_lookup_insert_fast(&ct_priv->ct_tuples_nat_ht,
|
||||
&entry->tuple_nat_node,
|
||||
tuples_nat_ht_params);
|
||||
if (err)
|
||||
goto err_tuple_nat;
|
||||
}
|
||||
spin_unlock_bh(&ct_priv->ht_lock);
|
||||
|
||||
err = mlx5_tc_ct_entry_add_rules(ct_priv, flow_rule, entry,
|
||||
ft->zone_restore_id);
|
||||
if (err)
|
||||
goto err_rules;
|
||||
|
||||
err = rhashtable_insert_fast(&ft->ct_entries_ht, &entry->node,
|
||||
cts_ht_params);
|
||||
if (err)
|
||||
goto err_insert;
|
||||
set_bit(MLX5_CT_ENTRY_FLAG_VALID, &entry->flags);
|
||||
mlx5_tc_ct_entry_put(entry); /* this function reference */
|
||||
|
||||
return 0;
|
||||
|
||||
err_insert:
|
||||
mlx5_tc_ct_entry_del_rules(ct_priv, entry);
|
||||
err_rules:
|
||||
spin_lock_bh(&ct_priv->ht_lock);
|
||||
if (mlx5_tc_ct_entry_has_nat(entry))
|
||||
rhashtable_remove_fast(&ct_priv->ct_tuples_nat_ht,
|
||||
&entry->tuple_nat_node, tuples_nat_ht_params);
|
||||
@ -924,47 +1037,43 @@ err_tuple_nat:
|
||||
&entry->tuple_node,
|
||||
tuples_ht_params);
|
||||
err_tuple:
|
||||
rhashtable_remove_fast(&ft->ct_entries_ht,
|
||||
&entry->node,
|
||||
cts_ht_params);
|
||||
err_entries:
|
||||
spin_unlock_bh(&ct_priv->ht_lock);
|
||||
err_set:
|
||||
kfree(entry);
|
||||
netdev_warn(ct_priv->netdev,
|
||||
"Failed to offload ct entry, err: %d\n", err);
|
||||
if (err != -EEXIST)
|
||||
netdev_warn(ct_priv->netdev, "Failed to offload ct entry, err: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void
|
||||
mlx5_tc_ct_del_ft_entry(struct mlx5_tc_ct_priv *ct_priv,
|
||||
struct mlx5_ct_entry *entry)
|
||||
{
|
||||
mlx5_tc_ct_entry_del_rules(ct_priv, entry);
|
||||
mutex_lock(&ct_priv->shared_counter_lock);
|
||||
if (mlx5_tc_ct_entry_has_nat(entry))
|
||||
rhashtable_remove_fast(&ct_priv->ct_tuples_nat_ht,
|
||||
&entry->tuple_nat_node,
|
||||
tuples_nat_ht_params);
|
||||
rhashtable_remove_fast(&ct_priv->ct_tuples_ht, &entry->tuple_node,
|
||||
tuples_ht_params);
|
||||
mutex_unlock(&ct_priv->shared_counter_lock);
|
||||
mlx5_tc_ct_counter_put(ct_priv, entry);
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
mlx5_tc_ct_block_flow_offload_del(struct mlx5_ct_ft *ft,
|
||||
struct flow_cls_offload *flow)
|
||||
{
|
||||
struct mlx5_tc_ct_priv *ct_priv = ft->ct_priv;
|
||||
unsigned long cookie = flow->cookie;
|
||||
struct mlx5_ct_entry *entry;
|
||||
|
||||
entry = rhashtable_lookup_fast(&ft->ct_entries_ht, &cookie,
|
||||
cts_ht_params);
|
||||
if (!entry)
|
||||
spin_lock_bh(&ct_priv->ht_lock);
|
||||
entry = rhashtable_lookup_fast(&ft->ct_entries_ht, &cookie, cts_ht_params);
|
||||
if (!entry) {
|
||||
spin_unlock_bh(&ct_priv->ht_lock);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
mlx5_tc_ct_del_ft_entry(ft->ct_priv, entry);
|
||||
WARN_ON(rhashtable_remove_fast(&ft->ct_entries_ht,
|
||||
&entry->node,
|
||||
cts_ht_params));
|
||||
kfree(entry);
|
||||
if (!mlx5_tc_ct_entry_valid(entry)) {
|
||||
spin_unlock_bh(&ct_priv->ht_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rhashtable_remove_fast(&ft->ct_entries_ht, &entry->node, cts_ht_params);
|
||||
mlx5_tc_ct_entry_remove_from_tuples(entry);
|
||||
spin_unlock_bh(&ct_priv->ht_lock);
|
||||
|
||||
mlx5_tc_ct_entry_put(entry);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -973,19 +1082,30 @@ static int
|
||||
mlx5_tc_ct_block_flow_offload_stats(struct mlx5_ct_ft *ft,
|
||||
struct flow_cls_offload *f)
|
||||
{
|
||||
struct mlx5_tc_ct_priv *ct_priv = ft->ct_priv;
|
||||
unsigned long cookie = f->cookie;
|
||||
struct mlx5_ct_entry *entry;
|
||||
u64 lastuse, packets, bytes;
|
||||
|
||||
entry = rhashtable_lookup_fast(&ft->ct_entries_ht, &cookie,
|
||||
cts_ht_params);
|
||||
if (!entry)
|
||||
spin_lock_bh(&ct_priv->ht_lock);
|
||||
entry = rhashtable_lookup_fast(&ft->ct_entries_ht, &cookie, cts_ht_params);
|
||||
if (!entry) {
|
||||
spin_unlock_bh(&ct_priv->ht_lock);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (!mlx5_tc_ct_entry_valid(entry) || !refcount_inc_not_zero(&entry->refcnt)) {
|
||||
spin_unlock_bh(&ct_priv->ht_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spin_unlock_bh(&ct_priv->ht_lock);
|
||||
|
||||
mlx5_fc_query_cached(entry->counter->counter, &bytes, &packets, &lastuse);
|
||||
flow_stats_update(&f->stats, bytes, packets, 0, lastuse,
|
||||
FLOW_ACTION_HW_STATS_DELAYED);
|
||||
|
||||
mlx5_tc_ct_entry_put(entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1481,11 +1601,9 @@ err_mapping:
|
||||
static void
|
||||
mlx5_tc_ct_flush_ft_entry(void *ptr, void *arg)
|
||||
{
|
||||
struct mlx5_tc_ct_priv *ct_priv = arg;
|
||||
struct mlx5_ct_entry *entry = ptr;
|
||||
|
||||
mlx5_tc_ct_del_ft_entry(ct_priv, entry);
|
||||
kfree(entry);
|
||||
mlx5_tc_ct_entry_put(entry);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1962,6 +2080,7 @@ mlx5_tc_ct_init(struct mlx5e_priv *priv, struct mlx5_fs_chains *chains,
|
||||
goto err_mapping_labels;
|
||||
}
|
||||
|
||||
spin_lock_init(&ct_priv->ht_lock);
|
||||
ct_priv->ns_type = ns_type;
|
||||
ct_priv->chains = chains;
|
||||
ct_priv->netdev = priv->netdev;
|
||||
@ -1996,7 +2115,6 @@ mlx5_tc_ct_init(struct mlx5e_priv *priv, struct mlx5_fs_chains *chains,
|
||||
|
||||
idr_init(&ct_priv->fte_ids);
|
||||
mutex_init(&ct_priv->control_lock);
|
||||
mutex_init(&ct_priv->shared_counter_lock);
|
||||
rhashtable_init(&ct_priv->zone_ht, &zone_params);
|
||||
rhashtable_init(&ct_priv->ct_tuples_ht, &tuples_ht_params);
|
||||
rhashtable_init(&ct_priv->ct_tuples_nat_ht, &tuples_nat_ht_params);
|
||||
@ -2039,7 +2157,6 @@ mlx5_tc_ct_clean(struct mlx5_tc_ct_priv *ct_priv)
|
||||
rhashtable_destroy(&ct_priv->ct_tuples_nat_ht);
|
||||
rhashtable_destroy(&ct_priv->zone_ht);
|
||||
mutex_destroy(&ct_priv->control_lock);
|
||||
mutex_destroy(&ct_priv->shared_counter_lock);
|
||||
idr_destroy(&ct_priv->fte_ids);
|
||||
kfree(ct_priv);
|
||||
}
|
||||
@ -2061,14 +2178,22 @@ mlx5e_tc_ct_restore_flow(struct mlx5_tc_ct_priv *ct_priv,
|
||||
if (!mlx5_tc_ct_skb_to_tuple(skb, &tuple, zone))
|
||||
return false;
|
||||
|
||||
entry = rhashtable_lookup_fast(&ct_priv->ct_tuples_ht, &tuple,
|
||||
tuples_ht_params);
|
||||
if (!entry)
|
||||
entry = rhashtable_lookup_fast(&ct_priv->ct_tuples_nat_ht,
|
||||
&tuple, tuples_nat_ht_params);
|
||||
if (!entry)
|
||||
spin_lock(&ct_priv->ht_lock);
|
||||
|
||||
entry = mlx5_tc_ct_entry_get(ct_priv, &tuple);
|
||||
if (!entry) {
|
||||
spin_unlock(&ct_priv->ht_lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IS_ERR(entry)) {
|
||||
spin_unlock(&ct_priv->ht_lock);
|
||||
return false;
|
||||
}
|
||||
spin_unlock(&ct_priv->ht_lock);
|
||||
|
||||
tcf_ct_flow_table_restore_skb(skb, entry->restore_cookie);
|
||||
__mlx5_tc_ct_entry_put(entry);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ static inline void mlx5e_xdp_tx_disable(struct mlx5e_priv *priv)
|
||||
|
||||
clear_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state);
|
||||
/* Let other device's napi(s) and XSK wakeups see our new state. */
|
||||
synchronize_rcu();
|
||||
synchronize_net();
|
||||
}
|
||||
|
||||
static inline bool mlx5e_xdp_tx_is_enabled(struct mlx5e_priv *priv)
|
||||
|
@ -111,7 +111,7 @@ err_free_cparam:
|
||||
void mlx5e_close_xsk(struct mlx5e_channel *c)
|
||||
{
|
||||
clear_bit(MLX5E_CHANNEL_STATE_XSK, c->state);
|
||||
synchronize_rcu(); /* Sync with the XSK wakeup and with NAPI. */
|
||||
synchronize_net(); /* Sync with the XSK wakeup and with NAPI. */
|
||||
|
||||
mlx5e_close_rq(&c->xskrq);
|
||||
mlx5e_close_cq(&c->xskrq.cq);
|
||||
|
@ -173,7 +173,7 @@ static inline bool mlx5e_accel_tx_eseg(struct mlx5e_priv *priv,
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_GENEVE)
|
||||
if (skb->encapsulation)
|
||||
if (skb->encapsulation && skb->ip_summed == CHECKSUM_PARTIAL)
|
||||
mlx5e_tx_tunnel_accel(skb, eseg, ihs);
|
||||
#endif
|
||||
|
||||
|
@ -57,6 +57,20 @@ struct mlx5e_ktls_offload_context_rx {
|
||||
struct mlx5e_ktls_rx_resync_ctx resync;
|
||||
};
|
||||
|
||||
static bool mlx5e_ktls_priv_rx_put(struct mlx5e_ktls_offload_context_rx *priv_rx)
|
||||
{
|
||||
if (!refcount_dec_and_test(&priv_rx->resync.refcnt))
|
||||
return false;
|
||||
|
||||
kfree(priv_rx);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void mlx5e_ktls_priv_rx_get(struct mlx5e_ktls_offload_context_rx *priv_rx)
|
||||
{
|
||||
refcount_inc(&priv_rx->resync.refcnt);
|
||||
}
|
||||
|
||||
static int mlx5e_ktls_create_tir(struct mlx5_core_dev *mdev, u32 *tirn, u32 rqtn)
|
||||
{
|
||||
int err, inlen;
|
||||
@ -326,7 +340,7 @@ static void resync_handle_work(struct work_struct *work)
|
||||
priv_rx = container_of(resync, struct mlx5e_ktls_offload_context_rx, resync);
|
||||
|
||||
if (unlikely(test_bit(MLX5E_PRIV_RX_FLAG_DELETING, priv_rx->flags))) {
|
||||
refcount_dec(&resync->refcnt);
|
||||
mlx5e_ktls_priv_rx_put(priv_rx);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -334,7 +348,7 @@ static void resync_handle_work(struct work_struct *work)
|
||||
sq = &c->async_icosq;
|
||||
|
||||
if (resync_post_get_progress_params(sq, priv_rx))
|
||||
refcount_dec(&resync->refcnt);
|
||||
mlx5e_ktls_priv_rx_put(priv_rx);
|
||||
}
|
||||
|
||||
static void resync_init(struct mlx5e_ktls_rx_resync_ctx *resync,
|
||||
@ -377,7 +391,11 @@ unlock:
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Function is called with elevated refcount, it decreases it. */
|
||||
/* Function can be called with the refcount being either elevated or not.
|
||||
* It decreases the refcount and may free the kTLS priv context.
|
||||
* Refcount is not elevated only if tls_dev_del has been called, but GET_PSV was
|
||||
* already in flight.
|
||||
*/
|
||||
void mlx5e_ktls_handle_get_psv_completion(struct mlx5e_icosq_wqe_info *wi,
|
||||
struct mlx5e_icosq *sq)
|
||||
{
|
||||
@ -410,7 +428,7 @@ void mlx5e_ktls_handle_get_psv_completion(struct mlx5e_icosq_wqe_info *wi,
|
||||
tls_offload_rx_resync_async_request_end(priv_rx->sk, cpu_to_be32(hw_seq));
|
||||
priv_rx->stats->tls_resync_req_end++;
|
||||
out:
|
||||
refcount_dec(&resync->refcnt);
|
||||
mlx5e_ktls_priv_rx_put(priv_rx);
|
||||
dma_unmap_single(dev, buf->dma_addr, PROGRESS_PARAMS_PADDED_SIZE, DMA_FROM_DEVICE);
|
||||
kfree(buf);
|
||||
}
|
||||
@ -431,9 +449,9 @@ static bool resync_queue_get_psv(struct sock *sk)
|
||||
return false;
|
||||
|
||||
resync = &priv_rx->resync;
|
||||
refcount_inc(&resync->refcnt);
|
||||
mlx5e_ktls_priv_rx_get(priv_rx);
|
||||
if (unlikely(!queue_work(resync->priv->tls->rx_wq, &resync->work)))
|
||||
refcount_dec(&resync->refcnt);
|
||||
mlx5e_ktls_priv_rx_put(priv_rx);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -625,31 +643,6 @@ err_create_key:
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Elevated refcount on the resync object means there are
|
||||
* outstanding operations (uncompleted GET_PSV WQEs) that
|
||||
* will read the resync / priv_rx objects once completed.
|
||||
* Wait for them to avoid use-after-free.
|
||||
*/
|
||||
static void wait_for_resync(struct net_device *netdev,
|
||||
struct mlx5e_ktls_rx_resync_ctx *resync)
|
||||
{
|
||||
#define MLX5E_KTLS_RX_RESYNC_TIMEOUT 20000 /* msecs */
|
||||
unsigned long exp_time = jiffies + msecs_to_jiffies(MLX5E_KTLS_RX_RESYNC_TIMEOUT);
|
||||
unsigned int refcnt;
|
||||
|
||||
do {
|
||||
refcnt = refcount_read(&resync->refcnt);
|
||||
if (refcnt == 1)
|
||||
return;
|
||||
|
||||
msleep(20);
|
||||
} while (time_before(jiffies, exp_time));
|
||||
|
||||
netdev_warn(netdev,
|
||||
"Failed waiting for kTLS RX resync refcnt to be released (%u).\n",
|
||||
refcnt);
|
||||
}
|
||||
|
||||
void mlx5e_ktls_del_rx(struct net_device *netdev, struct tls_context *tls_ctx)
|
||||
{
|
||||
struct mlx5e_ktls_offload_context_rx *priv_rx;
|
||||
@ -663,7 +656,7 @@ void mlx5e_ktls_del_rx(struct net_device *netdev, struct tls_context *tls_ctx)
|
||||
priv_rx = mlx5e_get_ktls_rx_priv_ctx(tls_ctx);
|
||||
set_bit(MLX5E_PRIV_RX_FLAG_DELETING, priv_rx->flags);
|
||||
mlx5e_set_ktls_rx_priv_ctx(tls_ctx, NULL);
|
||||
synchronize_rcu(); /* Sync with NAPI */
|
||||
synchronize_net(); /* Sync with NAPI */
|
||||
if (!cancel_work_sync(&priv_rx->rule.work))
|
||||
/* completion is needed, as the priv_rx in the add flow
|
||||
* is maintained on the wqe info (wi), not on the socket.
|
||||
@ -671,8 +664,7 @@ void mlx5e_ktls_del_rx(struct net_device *netdev, struct tls_context *tls_ctx)
|
||||
wait_for_completion(&priv_rx->add_ctx);
|
||||
resync = &priv_rx->resync;
|
||||
if (cancel_work_sync(&resync->work))
|
||||
refcount_dec(&resync->refcnt);
|
||||
wait_for_resync(netdev, resync);
|
||||
mlx5e_ktls_priv_rx_put(priv_rx);
|
||||
|
||||
priv_rx->stats->tls_del++;
|
||||
if (priv_rx->rule.rule)
|
||||
@ -680,5 +672,9 @@ void mlx5e_ktls_del_rx(struct net_device *netdev, struct tls_context *tls_ctx)
|
||||
|
||||
mlx5_core_destroy_tir(mdev, priv_rx->tirn);
|
||||
mlx5_ktls_destroy_key(mdev, priv_rx->key_id);
|
||||
kfree(priv_rx);
|
||||
/* priv_rx should normally be freed here, but if there is an outstanding
|
||||
* GET_PSV, deallocation will be delayed until the CQE for GET_PSV is
|
||||
* processed.
|
||||
*/
|
||||
mlx5e_ktls_priv_rx_put(priv_rx);
|
||||
}
|
||||
|
@ -536,7 +536,7 @@ static int mlx5e_get_coalesce(struct net_device *netdev,
|
||||
#define MLX5E_MAX_COAL_FRAMES MLX5_MAX_CQ_COUNT
|
||||
|
||||
static void
|
||||
mlx5e_set_priv_channels_coalesce(struct mlx5e_priv *priv, struct ethtool_coalesce *coal)
|
||||
mlx5e_set_priv_channels_tx_coalesce(struct mlx5e_priv *priv, struct ethtool_coalesce *coal)
|
||||
{
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
int tc;
|
||||
@ -551,6 +551,17 @@ mlx5e_set_priv_channels_coalesce(struct mlx5e_priv *priv, struct ethtool_coalesc
|
||||
coal->tx_coalesce_usecs,
|
||||
coal->tx_max_coalesced_frames);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mlx5e_set_priv_channels_rx_coalesce(struct mlx5e_priv *priv, struct ethtool_coalesce *coal)
|
||||
{
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < priv->channels.num; ++i) {
|
||||
struct mlx5e_channel *c = priv->channels.c[i];
|
||||
|
||||
mlx5_core_modify_cq_moderation(mdev, &c->rq.cq.mcq,
|
||||
coal->rx_coalesce_usecs,
|
||||
@ -597,21 +608,9 @@ int mlx5e_ethtool_set_coalesce(struct mlx5e_priv *priv,
|
||||
tx_moder->pkts = coal->tx_max_coalesced_frames;
|
||||
new_channels.params.tx_dim_enabled = !!coal->use_adaptive_tx_coalesce;
|
||||
|
||||
if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) {
|
||||
priv->channels.params = new_channels.params;
|
||||
goto out;
|
||||
}
|
||||
/* we are opened */
|
||||
|
||||
reset_rx = !!coal->use_adaptive_rx_coalesce != priv->channels.params.rx_dim_enabled;
|
||||
reset_tx = !!coal->use_adaptive_tx_coalesce != priv->channels.params.tx_dim_enabled;
|
||||
|
||||
if (!reset_rx && !reset_tx) {
|
||||
mlx5e_set_priv_channels_coalesce(priv, coal);
|
||||
priv->channels.params = new_channels.params;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (reset_rx) {
|
||||
u8 mode = MLX5E_GET_PFLAG(&new_channels.params,
|
||||
MLX5E_PFLAG_RX_CQE_BASED_MODER);
|
||||
@ -625,6 +624,20 @@ int mlx5e_ethtool_set_coalesce(struct mlx5e_priv *priv,
|
||||
mlx5e_reset_tx_moderation(&new_channels.params, mode);
|
||||
}
|
||||
|
||||
if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) {
|
||||
priv->channels.params = new_channels.params;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!reset_rx && !reset_tx) {
|
||||
if (!coal->use_adaptive_rx_coalesce)
|
||||
mlx5e_set_priv_channels_rx_coalesce(priv, coal);
|
||||
if (!coal->use_adaptive_tx_coalesce)
|
||||
mlx5e_set_priv_channels_tx_coalesce(priv, coal);
|
||||
priv->channels.params = new_channels.params;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = mlx5e_safe_switch_channels(priv, &new_channels, NULL, NULL);
|
||||
|
||||
out:
|
||||
|
@ -67,6 +67,7 @@
|
||||
#include "en/ptp.h"
|
||||
#include "qos.h"
|
||||
#include "en/trap.h"
|
||||
#include "fpga/ipsec.h"
|
||||
|
||||
bool mlx5e_check_fragmented_striding_rq_cap(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
@ -108,7 +109,7 @@ bool mlx5e_striding_rq_possible(struct mlx5_core_dev *mdev,
|
||||
if (!mlx5e_check_fragmented_striding_rq_cap(mdev))
|
||||
return false;
|
||||
|
||||
if (MLX5_IPSEC_DEV(mdev))
|
||||
if (mlx5_fpga_is_ipsec_device(mdev))
|
||||
return false;
|
||||
|
||||
if (params->xdp_prog) {
|
||||
@ -947,7 +948,7 @@ void mlx5e_activate_rq(struct mlx5e_rq *rq)
|
||||
void mlx5e_deactivate_rq(struct mlx5e_rq *rq)
|
||||
{
|
||||
clear_bit(MLX5E_RQ_STATE_ENABLED, &rq->state);
|
||||
synchronize_rcu(); /* Sync with NAPI to prevent mlx5e_post_rx_wqes. */
|
||||
synchronize_net(); /* Sync with NAPI to prevent mlx5e_post_rx_wqes. */
|
||||
}
|
||||
|
||||
void mlx5e_close_rq(struct mlx5e_rq *rq)
|
||||
@ -1401,7 +1402,7 @@ void mlx5e_deactivate_txqsq(struct mlx5e_txqsq *sq)
|
||||
struct mlx5_wq_cyc *wq = &sq->wq;
|
||||
|
||||
clear_bit(MLX5E_SQ_STATE_ENABLED, &sq->state);
|
||||
synchronize_rcu(); /* Sync with NAPI to prevent netif_tx_wake_queue. */
|
||||
synchronize_net(); /* Sync with NAPI to prevent netif_tx_wake_queue. */
|
||||
|
||||
mlx5e_tx_disable_queue(sq->txq);
|
||||
|
||||
@ -1476,7 +1477,7 @@ void mlx5e_activate_icosq(struct mlx5e_icosq *icosq)
|
||||
void mlx5e_deactivate_icosq(struct mlx5e_icosq *icosq)
|
||||
{
|
||||
clear_bit(MLX5E_SQ_STATE_ENABLED, &icosq->state);
|
||||
synchronize_rcu(); /* Sync with NAPI. */
|
||||
synchronize_net(); /* Sync with NAPI. */
|
||||
}
|
||||
|
||||
void mlx5e_close_icosq(struct mlx5e_icosq *sq)
|
||||
@ -1555,7 +1556,7 @@ void mlx5e_close_xdpsq(struct mlx5e_xdpsq *sq)
|
||||
struct mlx5e_channel *c = sq->channel;
|
||||
|
||||
clear_bit(MLX5E_SQ_STATE_ENABLED, &sq->state);
|
||||
synchronize_rcu(); /* Sync with NAPI. */
|
||||
synchronize_net(); /* Sync with NAPI. */
|
||||
|
||||
mlx5e_destroy_sq(c->mdev, sq->sqn);
|
||||
mlx5e_free_xdpsq_descs(sq);
|
||||
@ -1879,12 +1880,12 @@ static int mlx5e_open_queues(struct mlx5e_channel *c,
|
||||
|
||||
mlx5e_build_create_cq_param(&ccp, c);
|
||||
|
||||
err = mlx5e_open_cq(c->priv, icocq_moder, &cparam->icosq.cqp, &ccp,
|
||||
err = mlx5e_open_cq(c->priv, icocq_moder, &cparam->async_icosq.cqp, &ccp,
|
||||
&c->async_icosq.cq);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mlx5e_open_cq(c->priv, icocq_moder, &cparam->async_icosq.cqp, &ccp,
|
||||
err = mlx5e_open_cq(c->priv, icocq_moder, &cparam->icosq.cqp, &ccp,
|
||||
&c->icosq.cq);
|
||||
if (err)
|
||||
goto err_close_async_icosq_cq;
|
||||
@ -2122,7 +2123,12 @@ static void mlx5e_build_rq_frags_info(struct mlx5_core_dev *mdev,
|
||||
u32 buf_size = 0;
|
||||
int i;
|
||||
|
||||
<<<<<<< HEAD
|
||||
if (MLX5_IPSEC_DEV(mdev))
|
||||
=======
|
||||
#ifdef CONFIG_MLX5_EN_IPSEC
|
||||
if (mlx5_fpga_is_ipsec_device(mdev))
|
||||
>>>>>>> 3af409ca278d4a8d50e91f9f7c4c33b175645cf3
|
||||
byte_count += MLX5E_METADATA_ETHER_LEN;
|
||||
|
||||
if (mlx5e_rx_is_linear_skb(params, xsk)) {
|
||||
@ -4590,8 +4596,9 @@ static int mlx5e_xdp_allowed(struct mlx5e_priv *priv, struct bpf_prog *prog)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (MLX5_IPSEC_DEV(priv->mdev)) {
|
||||
netdev_warn(netdev, "can't set XDP with IPSec offload\n");
|
||||
if (mlx5_fpga_is_ipsec_device(priv->mdev)) {
|
||||
netdev_warn(netdev,
|
||||
"XDP is not available on Innova cards with IPsec support\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -1783,8 +1783,8 @@ int mlx5e_rq_set_handlers(struct mlx5e_rq *rq, struct mlx5e_params *params, bool
|
||||
rq->dealloc_wqe = mlx5e_dealloc_rx_mpwqe;
|
||||
|
||||
rq->handle_rx_cqe = priv->profile->rx_handlers->handle_rx_cqe_mpwqe;
|
||||
if (MLX5_IPSEC_DEV(mdev)) {
|
||||
netdev_err(netdev, "MPWQE RQ with IPSec offload not supported\n");
|
||||
if (mlx5_fpga_is_ipsec_device(mdev)) {
|
||||
netdev_err(netdev, "MPWQE RQ with Innova IPSec offload not supported\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!rq->handle_rx_cqe) {
|
||||
|
@ -4445,7 +4445,7 @@ static int apply_police_params(struct mlx5e_priv *priv, u64 rate,
|
||||
*/
|
||||
if (rate) {
|
||||
rate = (rate * BITS_PER_BYTE) + 500000;
|
||||
rate_mbps = max_t(u32, do_div(rate, 1000000), 1);
|
||||
rate_mbps = max_t(u64, do_div(rate, 1000000), 1);
|
||||
}
|
||||
|
||||
err = mlx5_esw_modify_vport_rate(esw, vport_num, rate_mbps);
|
||||
|
@ -124,7 +124,7 @@ struct mlx5_fpga_ipsec {
|
||||
struct ida halloc;
|
||||
};
|
||||
|
||||
static bool mlx5_fpga_is_ipsec_device(struct mlx5_core_dev *mdev)
|
||||
bool mlx5_fpga_is_ipsec_device(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
if (!mdev->fpga || !MLX5_CAP_GEN(mdev, fpga))
|
||||
return false;
|
||||
|
@ -43,6 +43,7 @@ u32 mlx5_fpga_ipsec_device_caps(struct mlx5_core_dev *mdev);
|
||||
const struct mlx5_flow_cmds *
|
||||
mlx5_fs_cmd_get_default_ipsec_fpga_cmds(enum fs_flow_table_type type);
|
||||
void mlx5_fpga_ipsec_build_fs_cmds(void);
|
||||
bool mlx5_fpga_is_ipsec_device(struct mlx5_core_dev *mdev);
|
||||
#else
|
||||
static inline
|
||||
const struct mlx5_accel_ipsec_ops *mlx5_fpga_ipsec_ops(struct mlx5_core_dev *mdev)
|
||||
@ -55,6 +56,7 @@ mlx5_fs_cmd_get_default_ipsec_fpga_cmds(enum fs_flow_table_type type)
|
||||
}
|
||||
|
||||
static inline void mlx5_fpga_ipsec_build_fs_cmds(void) {};
|
||||
static inline bool mlx5_fpga_is_ipsec_device(struct mlx5_core_dev *mdev) { return false; }
|
||||
|
||||
#endif /* CONFIG_MLX5_FPGA_IPSEC */
|
||||
#endif /* __MLX5_FPGA_IPSEC_H__ */
|
||||
|
@ -190,6 +190,16 @@ static bool reset_fw_if_needed(struct mlx5_core_dev *dev)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void enter_error_state(struct mlx5_core_dev *dev, bool force)
|
||||
{
|
||||
if (mlx5_health_check_fatal_sensors(dev) || force) { /* protected state setting */
|
||||
dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR;
|
||||
mlx5_cmd_flush(dev);
|
||||
}
|
||||
|
||||
mlx5_notifier_call_chain(dev->priv.events, MLX5_DEV_EVENT_SYS_ERROR, (void *)1);
|
||||
}
|
||||
|
||||
void mlx5_enter_error_state(struct mlx5_core_dev *dev, bool force)
|
||||
{
|
||||
bool err_detected = false;
|
||||
@ -208,12 +218,7 @@ void mlx5_enter_error_state(struct mlx5_core_dev *dev, bool force)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (mlx5_health_check_fatal_sensors(dev) || force) { /* protected state setting */
|
||||
dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR;
|
||||
mlx5_cmd_flush(dev);
|
||||
}
|
||||
|
||||
mlx5_notifier_call_chain(dev->priv.events, MLX5_DEV_EVENT_SYS_ERROR, (void *)1);
|
||||
enter_error_state(dev, force);
|
||||
unlock:
|
||||
mutex_unlock(&dev->intf_state_mutex);
|
||||
}
|
||||
@ -613,7 +618,7 @@ static void mlx5_fw_fatal_reporter_err_work(struct work_struct *work)
|
||||
priv = container_of(health, struct mlx5_priv, health);
|
||||
dev = container_of(priv, struct mlx5_core_dev, priv);
|
||||
|
||||
mlx5_enter_error_state(dev, false);
|
||||
enter_error_state(dev, false);
|
||||
if (IS_ERR_OR_NULL(health->fw_fatal_reporter)) {
|
||||
if (mlx5_health_try_recover(dev))
|
||||
mlx5_core_err(dev, "health recovery failed\n");
|
||||
@ -707,8 +712,9 @@ static void poll_health(struct timer_list *t)
|
||||
mlx5_core_err(dev, "Fatal error %u detected\n", fatal_error);
|
||||
dev->priv.health.fatal_error = fatal_error;
|
||||
print_health_info(dev);
|
||||
dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR;
|
||||
mlx5_trigger_health_work(dev);
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
count = ioread32be(health->health_counter);
|
||||
|
@ -1445,7 +1445,8 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
dev_err(&pdev->dev, "mlx5_crdump_enable failed with error code %d\n", err);
|
||||
|
||||
pci_save_state(pdev);
|
||||
devlink_reload_enable(devlink);
|
||||
if (!mlx5_core_is_mp_slave(dev))
|
||||
devlink_reload_enable(devlink);
|
||||
return 0;
|
||||
|
||||
err_load_one:
|
||||
|
@ -2230,6 +2230,31 @@ static void rtl_prepare_power_down(struct rtl8169_private *tp)
|
||||
phy_speed_down(tp->phydev, false);
|
||||
rtl_wol_enable_rx(tp);
|
||||
}
|
||||
|
||||
switch (tp->mac_version) {
|
||||
case RTL_GIGA_MAC_VER_25 ... RTL_GIGA_MAC_VER_26:
|
||||
case RTL_GIGA_MAC_VER_29 ... RTL_GIGA_MAC_VER_30:
|
||||
case RTL_GIGA_MAC_VER_32 ... RTL_GIGA_MAC_VER_33:
|
||||
case RTL_GIGA_MAC_VER_37:
|
||||
case RTL_GIGA_MAC_VER_39:
|
||||
case RTL_GIGA_MAC_VER_43:
|
||||
case RTL_GIGA_MAC_VER_44:
|
||||
case RTL_GIGA_MAC_VER_45:
|
||||
case RTL_GIGA_MAC_VER_46:
|
||||
case RTL_GIGA_MAC_VER_47:
|
||||
case RTL_GIGA_MAC_VER_48:
|
||||
case RTL_GIGA_MAC_VER_50 ... RTL_GIGA_MAC_VER_63:
|
||||
RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) & ~0x80);
|
||||
break;
|
||||
case RTL_GIGA_MAC_VER_40:
|
||||
case RTL_GIGA_MAC_VER_41:
|
||||
case RTL_GIGA_MAC_VER_49:
|
||||
rtl_eri_clear_bits(tp, 0x1a8, 0xfc000000);
|
||||
RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) & ~0x80);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void rtl_init_rxcfg(struct rtl8169_private *tp)
|
||||
|
@ -1862,6 +1862,18 @@ static int axienet_probe(struct platform_device *pdev)
|
||||
lp->options = XAE_OPTION_DEFAULTS;
|
||||
lp->rx_bd_num = RX_BD_NUM_DEFAULT;
|
||||
lp->tx_bd_num = TX_BD_NUM_DEFAULT;
|
||||
|
||||
lp->clk = devm_clk_get_optional(&pdev->dev, NULL);
|
||||
if (IS_ERR(lp->clk)) {
|
||||
ret = PTR_ERR(lp->clk);
|
||||
goto free_netdev;
|
||||
}
|
||||
ret = clk_prepare_enable(lp->clk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Unable to enable clock: %d\n", ret);
|
||||
goto free_netdev;
|
||||
}
|
||||
|
||||
/* Map device registers */
|
||||
ethres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
lp->regs = devm_ioremap_resource(&pdev->dev, ethres);
|
||||
@ -2046,20 +2058,6 @@ static int axienet_probe(struct platform_device *pdev)
|
||||
|
||||
lp->phy_node = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0);
|
||||
if (lp->phy_node) {
|
||||
lp->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(lp->clk)) {
|
||||
dev_warn(&pdev->dev, "Failed to get clock: %ld\n",
|
||||
PTR_ERR(lp->clk));
|
||||
lp->clk = NULL;
|
||||
} else {
|
||||
ret = clk_prepare_enable(lp->clk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Unable to enable clock: %d\n",
|
||||
ret);
|
||||
goto free_netdev;
|
||||
}
|
||||
}
|
||||
|
||||
ret = axienet_mdio_setup(lp);
|
||||
if (ret)
|
||||
dev_warn(&pdev->dev,
|
||||
|
@ -580,10 +580,10 @@ ipa_resource_config(struct ipa *ipa, const struct ipa_resource_data *data)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < data->resource_src_count; i++)
|
||||
ipa_resource_config_src(ipa, data->resource_src);
|
||||
ipa_resource_config_src(ipa, &data->resource_src[i]);
|
||||
|
||||
for (i = 0; i < data->resource_dst_count; i++)
|
||||
ipa_resource_config_dst(ipa, data->resource_dst);
|
||||
ipa_resource_config_dst(ipa, &data->resource_dst[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -300,10 +300,13 @@ static int mdio_bus_phy_resume(struct device *dev)
|
||||
|
||||
phydev->suspended_by_mdio_bus = 0;
|
||||
|
||||
ret = phy_resume(phydev);
|
||||
ret = phy_init_hw(phydev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = phy_resume(phydev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
no_resume:
|
||||
if (phydev->attached_dev && phydev->adjust_link)
|
||||
phy_start_machine(phydev);
|
||||
@ -311,39 +314,8 @@ no_resume:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mdio_bus_phy_restore(struct device *dev)
|
||||
{
|
||||
struct phy_device *phydev = to_phy_device(dev);
|
||||
struct net_device *netdev = phydev->attached_dev;
|
||||
int ret;
|
||||
|
||||
if (!netdev)
|
||||
return 0;
|
||||
|
||||
ret = phy_init_hw(phydev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (phydev->attached_dev && phydev->adjust_link)
|
||||
phy_start_machine(phydev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops mdio_bus_phy_pm_ops = {
|
||||
.suspend = mdio_bus_phy_suspend,
|
||||
.resume = mdio_bus_phy_resume,
|
||||
.freeze = mdio_bus_phy_suspend,
|
||||
.thaw = mdio_bus_phy_resume,
|
||||
.restore = mdio_bus_phy_restore,
|
||||
};
|
||||
|
||||
#define MDIO_BUS_PHY_PM_OPS (&mdio_bus_phy_pm_ops)
|
||||
|
||||
#else
|
||||
|
||||
#define MDIO_BUS_PHY_PM_OPS NULL
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(mdio_bus_phy_pm_ops, mdio_bus_phy_suspend,
|
||||
mdio_bus_phy_resume);
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
/**
|
||||
@ -554,7 +526,7 @@ static const struct device_type mdio_bus_phy_type = {
|
||||
.name = "PHY",
|
||||
.groups = phy_dev_groups,
|
||||
.release = phy_device_release,
|
||||
.pm = MDIO_BUS_PHY_PM_OPS,
|
||||
.pm = pm_ptr(&mdio_bus_phy_pm_ops),
|
||||
};
|
||||
|
||||
static int phy_request_driver_module(struct phy_device *dev, u32 phy_id)
|
||||
@ -1144,10 +1116,19 @@ int phy_init_hw(struct phy_device *phydev)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (phydev->drv->config_init)
|
||||
if (phydev->drv->config_init) {
|
||||
ret = phydev->drv->config_init(phydev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
if (phydev->drv->config_intr) {
|
||||
ret = phydev->drv->config_intr(phydev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(phy_init_hw);
|
||||
|
||||
|
@ -854,7 +854,7 @@ static int lmc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
spin_lock_init(&sc->lmc_lock);
|
||||
pci_set_master(pdev);
|
||||
|
||||
printk(KERN_INFO "%s: detected at %lx, irq %d\n", dev->name,
|
||||
printk(KERN_INFO "hdlc: detected at %lx, irq %d\n",
|
||||
dev->base_addr, dev->irq);
|
||||
|
||||
err = register_hdlc_device(dev);
|
||||
@ -899,6 +899,8 @@ static int lmc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
break;
|
||||
default:
|
||||
printk(KERN_WARNING "%s: LMC UNKNOWN CARD!\n", dev->name);
|
||||
unregister_hdlc_device(dev);
|
||||
return -EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -5311,7 +5311,7 @@ static void b43_nphy_restore_cal(struct b43_wldev *dev)
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (dev->phy.rev >= 3)
|
||||
table[i] = coef[i];
|
||||
coef[i] = table[i];
|
||||
else
|
||||
coef[i] = 0;
|
||||
}
|
||||
|
@ -86,8 +86,7 @@ static int cxgbit_is_ofld_imm(const struct sk_buff *skb)
|
||||
if (likely(cxgbit_skcb_flags(skb) & SKCBF_TX_ISO))
|
||||
length += sizeof(struct cpl_tx_data_iso);
|
||||
|
||||
#define MAX_IMM_TX_PKT_LEN 256
|
||||
return length <= MAX_IMM_TX_PKT_LEN;
|
||||
return length <= MAX_IMM_OFLD_TX_DATA_WR_LEN;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -207,7 +207,7 @@ struct atm_skb_data {
|
||||
struct atm_vcc *vcc; /* ATM VCC */
|
||||
unsigned long atm_options; /* ATM layer options */
|
||||
unsigned int acct_truesize; /* truesize accounted to vcc */
|
||||
};
|
||||
} __packed;
|
||||
|
||||
#define VCC_HTABLE_SIZE 32
|
||||
|
||||
|
@ -166,6 +166,7 @@ int tcf_idr_create_from_flags(struct tc_action_net *tn, u32 index,
|
||||
struct nlattr *est, struct tc_action **a,
|
||||
const struct tc_action_ops *ops, int bind,
|
||||
u32 flags);
|
||||
void tcf_idr_insert_many(struct tc_action *actions[]);
|
||||
void tcf_idr_cleanup(struct tc_action_net *tn, u32 index);
|
||||
int tcf_idr_check_alloc(struct tc_action_net *tn, u32 *index,
|
||||
struct tc_action **a, int bind);
|
||||
|
@ -593,6 +593,7 @@ enum {
|
||||
TCA_FLOWER_KEY_CT_FLAGS_TRACKED = 1 << 3, /* Conntrack has occurred. */
|
||||
TCA_FLOWER_KEY_CT_FLAGS_INVALID = 1 << 4, /* Conntrack is invalid. */
|
||||
TCA_FLOWER_KEY_CT_FLAGS_REPLY = 1 << 5, /* Packet is in the reply direction. */
|
||||
__TCA_FLOWER_KEY_CT_FLAGS_MAX,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -11563,7 +11563,7 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env)
|
||||
bool isdiv = BPF_OP(insn->code) == BPF_DIV;
|
||||
struct bpf_insn *patchlet;
|
||||
struct bpf_insn chk_and_div[] = {
|
||||
/* Rx div 0 -> 0 */
|
||||
/* [R,W]x div 0 -> 0 */
|
||||
BPF_RAW_INSN((is64 ? BPF_JMP : BPF_JMP32) |
|
||||
BPF_JNE | BPF_K, insn->src_reg,
|
||||
0, 2, 0),
|
||||
@ -11572,16 +11572,18 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env)
|
||||
*insn,
|
||||
};
|
||||
struct bpf_insn chk_and_mod[] = {
|
||||
/* Rx mod 0 -> Rx */
|
||||
/* [R,W]x mod 0 -> [R,W]x */
|
||||
BPF_RAW_INSN((is64 ? BPF_JMP : BPF_JMP32) |
|
||||
BPF_JEQ | BPF_K, insn->src_reg,
|
||||
0, 1, 0),
|
||||
0, 1 + (is64 ? 0 : 1), 0),
|
||||
*insn,
|
||||
BPF_JMP_IMM(BPF_JA, 0, 0, 1),
|
||||
BPF_MOV32_REG(insn->dst_reg, insn->dst_reg),
|
||||
};
|
||||
|
||||
patchlet = isdiv ? chk_and_div : chk_and_mod;
|
||||
cnt = isdiv ? ARRAY_SIZE(chk_and_div) :
|
||||
ARRAY_SIZE(chk_and_mod);
|
||||
ARRAY_SIZE(chk_and_mod) - (is64 ? 2 : 0);
|
||||
|
||||
new_prog = bpf_patch_insn_data(env, i + delta, patchlet, cnt);
|
||||
if (!new_prog)
|
||||
|
@ -1577,8 +1577,8 @@ static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
|
||||
struct sk_buff *skb;
|
||||
struct net_device *dev;
|
||||
struct ddpehdr *ddp;
|
||||
int size;
|
||||
struct atalk_route *rt;
|
||||
int size, hard_header_len;
|
||||
struct atalk_route *rt, *rt_lo = NULL;
|
||||
int err;
|
||||
|
||||
if (flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT))
|
||||
@ -1641,7 +1641,22 @@ static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
|
||||
SOCK_DEBUG(sk, "SK %p: Size needed %d, device %s\n",
|
||||
sk, size, dev->name);
|
||||
|
||||
size += dev->hard_header_len;
|
||||
hard_header_len = dev->hard_header_len;
|
||||
/* Leave room for loopback hardware header if necessary */
|
||||
if (usat->sat_addr.s_node == ATADDR_BCAST &&
|
||||
(dev->flags & IFF_LOOPBACK || !(rt->flags & RTF_GATEWAY))) {
|
||||
struct atalk_addr at_lo;
|
||||
|
||||
at_lo.s_node = 0;
|
||||
at_lo.s_net = 0;
|
||||
|
||||
rt_lo = atrtr_find(&at_lo);
|
||||
|
||||
if (rt_lo && rt_lo->dev->hard_header_len > hard_header_len)
|
||||
hard_header_len = rt_lo->dev->hard_header_len;
|
||||
}
|
||||
|
||||
size += hard_header_len;
|
||||
release_sock(sk);
|
||||
skb = sock_alloc_send_skb(sk, size, (flags & MSG_DONTWAIT), &err);
|
||||
lock_sock(sk);
|
||||
@ -1649,7 +1664,7 @@ static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
|
||||
goto out;
|
||||
|
||||
skb_reserve(skb, ddp_dl->header_length);
|
||||
skb_reserve(skb, dev->hard_header_len);
|
||||
skb_reserve(skb, hard_header_len);
|
||||
skb->dev = dev;
|
||||
|
||||
SOCK_DEBUG(sk, "SK %p: Begin build.\n", sk);
|
||||
@ -1700,18 +1715,12 @@ static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
|
||||
/* loop back */
|
||||
skb_orphan(skb);
|
||||
if (ddp->deh_dnode == ATADDR_BCAST) {
|
||||
struct atalk_addr at_lo;
|
||||
|
||||
at_lo.s_node = 0;
|
||||
at_lo.s_net = 0;
|
||||
|
||||
rt = atrtr_find(&at_lo);
|
||||
if (!rt) {
|
||||
if (!rt_lo) {
|
||||
kfree_skb(skb);
|
||||
err = -ENETUNREACH;
|
||||
goto out;
|
||||
}
|
||||
dev = rt->dev;
|
||||
dev = rt_lo->dev;
|
||||
skb->dev = dev;
|
||||
}
|
||||
ddp_dl->request(ddp_dl, skb, dev->dev_addr);
|
||||
|
@ -115,10 +115,7 @@ static int chnl_recv_cb(struct cflayer *layr, struct cfpkt *pkt)
|
||||
else
|
||||
skb->ip_summed = CHECKSUM_NONE;
|
||||
|
||||
if (in_interrupt())
|
||||
netif_rx(skb);
|
||||
else
|
||||
netif_rx_ni(skb);
|
||||
netif_rx_any_context(skb);
|
||||
|
||||
/* Update statistics. */
|
||||
priv->netdev->stats.rx_packets++;
|
||||
|
@ -1056,6 +1056,9 @@ proto_again:
|
||||
key_control->addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS;
|
||||
}
|
||||
|
||||
__skb_flow_dissect_ipv4(skb, flow_dissector,
|
||||
target_container, data, iph);
|
||||
|
||||
if (ip_is_fragment(iph)) {
|
||||
key_control->flags |= FLOW_DIS_IS_FRAGMENT;
|
||||
|
||||
@ -1072,9 +1075,6 @@ proto_again:
|
||||
}
|
||||
}
|
||||
|
||||
__skb_flow_dissect_ipv4(skb, flow_dissector,
|
||||
target_container, data, iph);
|
||||
|
||||
break;
|
||||
}
|
||||
case htons(ETH_P_IPV6): {
|
||||
|
@ -508,8 +508,8 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
|
||||
{
|
||||
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
|
||||
struct mptcp_sock *msk = mptcp_sk(subflow->conn);
|
||||
u64 snd_data_fin_enable, ack_seq;
|
||||
unsigned int dss_size = 0;
|
||||
u64 snd_data_fin_enable;
|
||||
struct mptcp_ext *mpext;
|
||||
unsigned int ack_size;
|
||||
bool ret = false;
|
||||
@ -541,13 +541,14 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
|
||||
return ret;
|
||||
}
|
||||
|
||||
ack_seq = READ_ONCE(msk->ack_seq);
|
||||
if (READ_ONCE(msk->use_64bit_ack)) {
|
||||
ack_size = TCPOLEN_MPTCP_DSS_ACK64;
|
||||
opts->ext_copy.data_ack = READ_ONCE(msk->ack_seq);
|
||||
opts->ext_copy.data_ack = ack_seq;
|
||||
opts->ext_copy.ack64 = 1;
|
||||
} else {
|
||||
ack_size = TCPOLEN_MPTCP_DSS_ACK32;
|
||||
opts->ext_copy.data_ack32 = (uint32_t)READ_ONCE(msk->ack_seq);
|
||||
opts->ext_copy.data_ack32 = (uint32_t)ack_seq;
|
||||
opts->ext_copy.ack64 = 0;
|
||||
}
|
||||
opts->ext_copy.use_ack = 1;
|
||||
@ -918,8 +919,7 @@ static void ack_update_msk(struct mptcp_sock *msk,
|
||||
msk->wnd_end = new_wnd_end;
|
||||
|
||||
/* this assumes mptcp_incoming_options() is invoked after tcp_ack() */
|
||||
if (after64(msk->wnd_end, READ_ONCE(msk->snd_nxt)) &&
|
||||
sk_stream_memory_free(ssk))
|
||||
if (after64(msk->wnd_end, READ_ONCE(msk->snd_nxt)))
|
||||
__mptcp_check_push(sk, ssk);
|
||||
|
||||
if (after64(new_snd_una, old_snd_una)) {
|
||||
|
@ -363,8 +363,6 @@ static void mptcp_check_data_fin_ack(struct sock *sk)
|
||||
|
||||
/* Look for an acknowledged DATA_FIN */
|
||||
if (mptcp_pending_data_fin_ack(sk)) {
|
||||
mptcp_stop_timer(sk);
|
||||
|
||||
WRITE_ONCE(msk->snd_data_fin_enable, 0);
|
||||
|
||||
switch (sk->sk_state) {
|
||||
@ -458,7 +456,18 @@ static bool mptcp_subflow_cleanup_rbuf(struct sock *ssk)
|
||||
static void mptcp_cleanup_rbuf(struct mptcp_sock *msk)
|
||||
{
|
||||
struct sock *ack_hint = READ_ONCE(msk->ack_hint);
|
||||
int old_space = READ_ONCE(msk->old_wspace);
|
||||
struct mptcp_subflow_context *subflow;
|
||||
struct sock *sk = (struct sock *)msk;
|
||||
bool cleanup;
|
||||
|
||||
/* this is a simple superset of what tcp_cleanup_rbuf() implements
|
||||
* so that we don't have to acquire the ssk socket lock most of the time
|
||||
* to do actually nothing
|
||||
*/
|
||||
cleanup = __mptcp_space(sk) - old_space >= max(0, old_space);
|
||||
if (!cleanup)
|
||||
return;
|
||||
|
||||
/* if the hinted ssk is still active, try to use it */
|
||||
if (likely(ack_hint)) {
|
||||
@ -1565,6 +1574,9 @@ out:
|
||||
mptcp_set_timeout(sk, ssk);
|
||||
tcp_push(ssk, 0, info.mss_now, tcp_sk(ssk)->nonagle,
|
||||
info.size_goal);
|
||||
if (!mptcp_timer_pending(sk))
|
||||
mptcp_reset_timer(sk);
|
||||
|
||||
if (msk->snd_data_fin_enable &&
|
||||
msk->snd_nxt + 1 == msk->write_seq)
|
||||
mptcp_schedule_work(sk);
|
||||
@ -1868,7 +1880,7 @@ static void __mptcp_splice_receive_queue(struct sock *sk)
|
||||
skb_queue_splice_tail_init(&sk->sk_receive_queue, &msk->receive_queue);
|
||||
}
|
||||
|
||||
static bool __mptcp_move_skbs(struct mptcp_sock *msk, unsigned int rcv)
|
||||
static bool __mptcp_move_skbs(struct mptcp_sock *msk)
|
||||
{
|
||||
struct sock *sk = (struct sock *)msk;
|
||||
unsigned int moved = 0;
|
||||
@ -1888,13 +1900,10 @@ static bool __mptcp_move_skbs(struct mptcp_sock *msk, unsigned int rcv)
|
||||
|
||||
slowpath = lock_sock_fast(ssk);
|
||||
mptcp_data_lock(sk);
|
||||
__mptcp_update_rmem(sk);
|
||||
done = __mptcp_move_skbs_from_subflow(msk, ssk, &moved);
|
||||
mptcp_data_unlock(sk);
|
||||
if (moved && rcv) {
|
||||
WRITE_ONCE(msk->rmem_pending, min(rcv, moved));
|
||||
tcp_cleanup_rbuf(ssk, 1);
|
||||
WRITE_ONCE(msk->rmem_pending, 0);
|
||||
}
|
||||
tcp_cleanup_rbuf(ssk, moved);
|
||||
unlock_sock_fast(ssk, slowpath);
|
||||
} while (!done);
|
||||
|
||||
@ -1907,6 +1916,7 @@ static bool __mptcp_move_skbs(struct mptcp_sock *msk, unsigned int rcv)
|
||||
ret |= __mptcp_ofo_queue(msk);
|
||||
__mptcp_splice_receive_queue(sk);
|
||||
mptcp_data_unlock(sk);
|
||||
mptcp_cleanup_rbuf(msk);
|
||||
}
|
||||
if (ret)
|
||||
mptcp_check_data_fin((struct sock *)msk);
|
||||
@ -1936,7 +1946,7 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
|
||||
target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);
|
||||
|
||||
while (copied < len) {
|
||||
int bytes_read, old_space;
|
||||
int bytes_read;
|
||||
|
||||
bytes_read = __mptcp_recvmsg_mskq(msk, msg, len - copied);
|
||||
if (unlikely(bytes_read < 0)) {
|
||||
@ -1947,14 +1957,11 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
|
||||
|
||||
copied += bytes_read;
|
||||
|
||||
if (skb_queue_empty(&msk->receive_queue) &&
|
||||
__mptcp_move_skbs(msk, len - copied))
|
||||
continue;
|
||||
|
||||
/* be sure to advertise window change */
|
||||
old_space = READ_ONCE(msk->old_wspace);
|
||||
if ((tcp_space(sk) - old_space) >= old_space)
|
||||
mptcp_cleanup_rbuf(msk);
|
||||
mptcp_cleanup_rbuf(msk);
|
||||
|
||||
if (skb_queue_empty(&msk->receive_queue) && __mptcp_move_skbs(msk))
|
||||
continue;
|
||||
|
||||
/* only the master socket status is relevant here. The exit
|
||||
* conditions mirror closely tcp_recvmsg()
|
||||
@ -1982,7 +1989,7 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
|
||||
/* race breaker: the shutdown could be after the
|
||||
* previous receive queue check
|
||||
*/
|
||||
if (__mptcp_move_skbs(msk, len - copied))
|
||||
if (__mptcp_move_skbs(msk))
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
@ -2015,7 +2022,7 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
|
||||
/* .. race-breaker: ssk might have gotten new data
|
||||
* after last __mptcp_move_skbs() returned false.
|
||||
*/
|
||||
if (unlikely(__mptcp_move_skbs(msk, 0)))
|
||||
if (unlikely(__mptcp_move_skbs(msk)))
|
||||
set_bit(MPTCP_DATA_READY, &msk->flags);
|
||||
} else if (unlikely(!test_bit(MPTCP_DATA_READY, &msk->flags))) {
|
||||
/* data to read but mptcp_wait_data() cleared DATA_READY */
|
||||
@ -2275,6 +2282,7 @@ static void mptcp_worker(struct work_struct *work)
|
||||
if (!test_and_clear_bit(MPTCP_WORK_RTX, &msk->flags))
|
||||
goto unlock;
|
||||
|
||||
__mptcp_clean_una(sk);
|
||||
dfrag = mptcp_rtx_head(sk);
|
||||
if (!dfrag)
|
||||
goto unlock;
|
||||
@ -2943,6 +2951,8 @@ static void mptcp_release_cb(struct sock *sk)
|
||||
mptcp_push_pending(sk, 0);
|
||||
spin_lock_bh(&sk->sk_lock.slock);
|
||||
}
|
||||
if (test_and_clear_bit(MPTCP_ERROR_REPORT, &mptcp_sk(sk)->flags))
|
||||
__mptcp_error_report(sk);
|
||||
|
||||
/* clear any wmem reservation and errors */
|
||||
__mptcp_update_wmem(sk);
|
||||
@ -3319,7 +3329,7 @@ static __poll_t mptcp_check_writeable(struct mptcp_sock *msk)
|
||||
struct sock *sk = (struct sock *)msk;
|
||||
|
||||
if (unlikely(sk->sk_shutdown & SEND_SHUTDOWN))
|
||||
return 0;
|
||||
return EPOLLOUT | EPOLLWRNORM;
|
||||
|
||||
if (sk_stream_is_writeable(sk))
|
||||
return EPOLLOUT | EPOLLWRNORM;
|
||||
@ -3352,9 +3362,16 @@ static __poll_t mptcp_poll(struct file *file, struct socket *sock,
|
||||
mask |= mptcp_check_readable(msk);
|
||||
mask |= mptcp_check_writeable(msk);
|
||||
}
|
||||
if (sk->sk_shutdown == SHUTDOWN_MASK || state == TCP_CLOSE)
|
||||
mask |= EPOLLHUP;
|
||||
if (sk->sk_shutdown & RCV_SHUTDOWN)
|
||||
mask |= EPOLLIN | EPOLLRDNORM | EPOLLRDHUP;
|
||||
|
||||
/* This barrier is coupled with smp_wmb() in tcp_reset() */
|
||||
smp_rmb();
|
||||
if (sk->sk_err)
|
||||
mask |= EPOLLERR;
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
|
@ -102,6 +102,7 @@
|
||||
#define MPTCP_WORK_CLOSE_SUBFLOW 5
|
||||
#define MPTCP_PUSH_PENDING 6
|
||||
#define MPTCP_CLEAN_UNA 7
|
||||
#define MPTCP_ERROR_REPORT 8
|
||||
|
||||
static inline bool before64(__u64 seq1, __u64 seq2)
|
||||
{
|
||||
@ -237,7 +238,6 @@ struct mptcp_sock {
|
||||
u64 wnd_end;
|
||||
unsigned long timer_ival;
|
||||
u32 token;
|
||||
int rmem_pending;
|
||||
int rmem_released;
|
||||
unsigned long flags;
|
||||
bool can_ack;
|
||||
@ -301,7 +301,7 @@ static inline struct mptcp_sock *mptcp_sk(const struct sock *sk)
|
||||
|
||||
static inline int __mptcp_space(const struct sock *sk)
|
||||
{
|
||||
return tcp_space(sk) + READ_ONCE(mptcp_sk(sk)->rmem_pending);
|
||||
return tcp_space(sk) + READ_ONCE(mptcp_sk(sk)->rmem_released);
|
||||
}
|
||||
|
||||
static inline struct mptcp_data_frag *mptcp_send_head(const struct sock *sk)
|
||||
@ -334,20 +334,13 @@ static inline struct mptcp_data_frag *mptcp_pending_tail(const struct sock *sk)
|
||||
return list_last_entry(&msk->rtx_queue, struct mptcp_data_frag, list);
|
||||
}
|
||||
|
||||
static inline struct mptcp_data_frag *mptcp_rtx_tail(const struct sock *sk)
|
||||
{
|
||||
struct mptcp_sock *msk = mptcp_sk(sk);
|
||||
|
||||
if (!before64(msk->snd_nxt, READ_ONCE(msk->snd_una)))
|
||||
return NULL;
|
||||
|
||||
return list_last_entry(&msk->rtx_queue, struct mptcp_data_frag, list);
|
||||
}
|
||||
|
||||
static inline struct mptcp_data_frag *mptcp_rtx_head(const struct sock *sk)
|
||||
{
|
||||
struct mptcp_sock *msk = mptcp_sk(sk);
|
||||
|
||||
if (msk->snd_una == READ_ONCE(msk->snd_nxt))
|
||||
return NULL;
|
||||
|
||||
return list_first_entry_or_null(&msk->rtx_queue, struct mptcp_data_frag, list);
|
||||
}
|
||||
|
||||
@ -436,6 +429,7 @@ struct mptcp_subflow_context {
|
||||
void (*tcp_data_ready)(struct sock *sk);
|
||||
void (*tcp_state_change)(struct sock *sk);
|
||||
void (*tcp_write_space)(struct sock *sk);
|
||||
void (*tcp_error_report)(struct sock *sk);
|
||||
|
||||
struct rcu_head rcu;
|
||||
};
|
||||
@ -560,6 +554,7 @@ static inline void mptcp_subflow_tcp_fallback(struct sock *sk,
|
||||
sk->sk_data_ready = ctx->tcp_data_ready;
|
||||
sk->sk_state_change = ctx->tcp_state_change;
|
||||
sk->sk_write_space = ctx->tcp_write_space;
|
||||
sk->sk_error_report = ctx->tcp_error_report;
|
||||
|
||||
inet_csk(sk)->icsk_af_ops = ctx->icsk_af_ops;
|
||||
}
|
||||
@ -587,6 +582,7 @@ bool mptcp_finish_join(struct sock *sk);
|
||||
bool mptcp_schedule_work(struct sock *sk);
|
||||
void __mptcp_check_push(struct sock *sk, struct sock *ssk);
|
||||
void __mptcp_data_acked(struct sock *sk);
|
||||
void __mptcp_error_report(struct sock *sk);
|
||||
void mptcp_subflow_eof(struct sock *sk);
|
||||
bool mptcp_update_rcv_data_fin(struct mptcp_sock *msk, u64 data_fin_seq, bool use_64bit);
|
||||
void __mptcp_flush_join_list(struct mptcp_sock *msk);
|
||||
|
@ -100,7 +100,7 @@ static struct mptcp_sock *subflow_token_join_request(struct request_sock *req)
|
||||
return msk;
|
||||
}
|
||||
|
||||
static int __subflow_init_req(struct request_sock *req, const struct sock *sk_listener)
|
||||
static void subflow_init_req(struct request_sock *req, const struct sock *sk_listener)
|
||||
{
|
||||
struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req);
|
||||
|
||||
@ -108,16 +108,6 @@ static int __subflow_init_req(struct request_sock *req, const struct sock *sk_li
|
||||
subflow_req->mp_join = 0;
|
||||
subflow_req->msk = NULL;
|
||||
mptcp_token_init_request(req);
|
||||
|
||||
#ifdef CONFIG_TCP_MD5SIG
|
||||
/* no MPTCP if MD5SIG is enabled on this socket or we may run out of
|
||||
* TCP option space.
|
||||
*/
|
||||
if (rcu_access_pointer(tcp_sk(sk_listener)->md5sig_info))
|
||||
return -EINVAL;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool subflow_use_different_sport(struct mptcp_sock *msk, const struct sock *sk)
|
||||
@ -130,20 +120,23 @@ static bool subflow_use_different_sport(struct mptcp_sock *msk, const struct soc
|
||||
* Returns an error code if a JOIN has failed and a TCP reset
|
||||
* should be sent.
|
||||
*/
|
||||
static int subflow_init_req(struct request_sock *req,
|
||||
const struct sock *sk_listener,
|
||||
struct sk_buff *skb)
|
||||
static int subflow_check_req(struct request_sock *req,
|
||||
const struct sock *sk_listener,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct mptcp_subflow_context *listener = mptcp_subflow_ctx(sk_listener);
|
||||
struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req);
|
||||
struct mptcp_options_received mp_opt;
|
||||
int ret;
|
||||
|
||||
pr_debug("subflow_req=%p, listener=%p", subflow_req, listener);
|
||||
|
||||
ret = __subflow_init_req(req, sk_listener);
|
||||
if (ret)
|
||||
return 0;
|
||||
#ifdef CONFIG_TCP_MD5SIG
|
||||
/* no MPTCP if MD5SIG is enabled on this socket or we may run out of
|
||||
* TCP option space.
|
||||
*/
|
||||
if (rcu_access_pointer(tcp_sk(sk_listener)->md5sig_info))
|
||||
return -EINVAL;
|
||||
#endif
|
||||
|
||||
mptcp_get_options(skb, &mp_opt);
|
||||
|
||||
@ -236,10 +229,7 @@ int mptcp_subflow_init_cookie_req(struct request_sock *req,
|
||||
struct mptcp_options_received mp_opt;
|
||||
int err;
|
||||
|
||||
err = __subflow_init_req(req, sk_listener);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
subflow_init_req(req, sk_listener);
|
||||
mptcp_get_options(skb, &mp_opt);
|
||||
|
||||
if (mp_opt.mp_capable && mp_opt.mp_join)
|
||||
@ -279,12 +269,13 @@ static struct dst_entry *subflow_v4_route_req(const struct sock *sk,
|
||||
int err;
|
||||
|
||||
tcp_rsk(req)->is_mptcp = 1;
|
||||
subflow_init_req(req, sk);
|
||||
|
||||
dst = tcp_request_sock_ipv4_ops.route_req(sk, skb, fl, req);
|
||||
if (!dst)
|
||||
return NULL;
|
||||
|
||||
err = subflow_init_req(req, sk, skb);
|
||||
err = subflow_check_req(req, sk, skb);
|
||||
if (err == 0)
|
||||
return dst;
|
||||
|
||||
@ -304,12 +295,13 @@ static struct dst_entry *subflow_v6_route_req(const struct sock *sk,
|
||||
int err;
|
||||
|
||||
tcp_rsk(req)->is_mptcp = 1;
|
||||
subflow_init_req(req, sk);
|
||||
|
||||
dst = tcp_request_sock_ipv6_ops.route_req(sk, skb, fl, req);
|
||||
if (!dst)
|
||||
return NULL;
|
||||
|
||||
err = subflow_init_req(req, sk, skb);
|
||||
err = subflow_check_req(req, sk, skb);
|
||||
if (err == 0)
|
||||
return dst;
|
||||
|
||||
@ -1124,6 +1116,46 @@ static void subflow_write_space(struct sock *ssk)
|
||||
mptcp_write_space(sk);
|
||||
}
|
||||
|
||||
void __mptcp_error_report(struct sock *sk)
|
||||
{
|
||||
struct mptcp_subflow_context *subflow;
|
||||
struct mptcp_sock *msk = mptcp_sk(sk);
|
||||
|
||||
mptcp_for_each_subflow(msk, subflow) {
|
||||
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
|
||||
int err = sock_error(ssk);
|
||||
|
||||
if (!err)
|
||||
continue;
|
||||
|
||||
/* only propagate errors on fallen-back sockets or
|
||||
* on MPC connect
|
||||
*/
|
||||
if (sk->sk_state != TCP_SYN_SENT && !__mptcp_check_fallback(msk))
|
||||
continue;
|
||||
|
||||
inet_sk_state_store(sk, inet_sk_state_load(ssk));
|
||||
sk->sk_err = -err;
|
||||
|
||||
/* This barrier is coupled with smp_rmb() in mptcp_poll() */
|
||||
smp_wmb();
|
||||
sk->sk_error_report(sk);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void subflow_error_report(struct sock *ssk)
|
||||
{
|
||||
struct sock *sk = mptcp_subflow_ctx(ssk)->conn;
|
||||
|
||||
mptcp_data_lock(sk);
|
||||
if (!sock_owned_by_user(sk))
|
||||
__mptcp_error_report(sk);
|
||||
else
|
||||
set_bit(MPTCP_ERROR_REPORT, &mptcp_sk(sk)->flags);
|
||||
mptcp_data_unlock(sk);
|
||||
}
|
||||
|
||||
static struct inet_connection_sock_af_ops *
|
||||
subflow_default_af_ops(struct sock *sk)
|
||||
{
|
||||
@ -1470,9 +1502,11 @@ static int subflow_ulp_init(struct sock *sk)
|
||||
ctx->tcp_data_ready = sk->sk_data_ready;
|
||||
ctx->tcp_state_change = sk->sk_state_change;
|
||||
ctx->tcp_write_space = sk->sk_write_space;
|
||||
ctx->tcp_error_report = sk->sk_error_report;
|
||||
sk->sk_data_ready = subflow_data_ready;
|
||||
sk->sk_write_space = subflow_write_space;
|
||||
sk->sk_state_change = subflow_state_change;
|
||||
sk->sk_error_report = subflow_error_report;
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
@ -1526,6 +1560,7 @@ static void subflow_ulp_clone(const struct request_sock *req,
|
||||
new_ctx->tcp_data_ready = old_ctx->tcp_data_ready;
|
||||
new_ctx->tcp_state_change = old_ctx->tcp_state_change;
|
||||
new_ctx->tcp_write_space = old_ctx->tcp_write_space;
|
||||
new_ctx->tcp_error_report = old_ctx->tcp_error_report;
|
||||
new_ctx->rel_write_seq = 1;
|
||||
new_ctx->tcp_sock = newsk;
|
||||
|
||||
|
@ -908,7 +908,7 @@ static const struct nla_policy tcf_action_policy[TCA_ACT_MAX + 1] = {
|
||||
[TCA_ACT_HW_STATS] = NLA_POLICY_BITFIELD32(TCA_ACT_HW_STATS_ANY),
|
||||
};
|
||||
|
||||
static void tcf_idr_insert_many(struct tc_action *actions[])
|
||||
void tcf_idr_insert_many(struct tc_action *actions[])
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -3060,6 +3060,7 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb,
|
||||
act->type = exts->type = TCA_OLD_COMPAT;
|
||||
exts->actions[0] = act;
|
||||
exts->nr_actions = 1;
|
||||
tcf_idr_insert_many(exts->actions);
|
||||
} else if (exts->action && tb[exts->action]) {
|
||||
int err;
|
||||
|
||||
|
@ -30,6 +30,11 @@
|
||||
|
||||
#include <uapi/linux/netfilter/nf_conntrack_common.h>
|
||||
|
||||
#define TCA_FLOWER_KEY_CT_FLAGS_MAX \
|
||||
((__TCA_FLOWER_KEY_CT_FLAGS_MAX - 1) << 1)
|
||||
#define TCA_FLOWER_KEY_CT_FLAGS_MASK \
|
||||
(TCA_FLOWER_KEY_CT_FLAGS_MAX - 1)
|
||||
|
||||
struct fl_flow_key {
|
||||
struct flow_dissector_key_meta meta;
|
||||
struct flow_dissector_key_control control;
|
||||
@ -690,8 +695,10 @@ static const struct nla_policy fl_policy[TCA_FLOWER_MAX + 1] = {
|
||||
[TCA_FLOWER_KEY_ENC_IP_TTL_MASK] = { .type = NLA_U8 },
|
||||
[TCA_FLOWER_KEY_ENC_OPTS] = { .type = NLA_NESTED },
|
||||
[TCA_FLOWER_KEY_ENC_OPTS_MASK] = { .type = NLA_NESTED },
|
||||
[TCA_FLOWER_KEY_CT_STATE] = { .type = NLA_U16 },
|
||||
[TCA_FLOWER_KEY_CT_STATE_MASK] = { .type = NLA_U16 },
|
||||
[TCA_FLOWER_KEY_CT_STATE] =
|
||||
NLA_POLICY_MASK(NLA_U16, TCA_FLOWER_KEY_CT_FLAGS_MASK),
|
||||
[TCA_FLOWER_KEY_CT_STATE_MASK] =
|
||||
NLA_POLICY_MASK(NLA_U16, TCA_FLOWER_KEY_CT_FLAGS_MASK),
|
||||
[TCA_FLOWER_KEY_CT_ZONE] = { .type = NLA_U16 },
|
||||
[TCA_FLOWER_KEY_CT_ZONE_MASK] = { .type = NLA_U16 },
|
||||
[TCA_FLOWER_KEY_CT_MARK] = { .type = NLA_U32 },
|
||||
@ -1394,12 +1401,33 @@ static int fl_set_enc_opt(struct nlattr **tb, struct fl_flow_key *key,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fl_validate_ct_state(u16 state, struct nlattr *tb,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
if (state && !(state & TCA_FLOWER_KEY_CT_FLAGS_TRACKED)) {
|
||||
NL_SET_ERR_MSG_ATTR(extack, tb,
|
||||
"no trk, so no other flag can be set");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (state & TCA_FLOWER_KEY_CT_FLAGS_NEW &&
|
||||
state & TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED) {
|
||||
NL_SET_ERR_MSG_ATTR(extack, tb,
|
||||
"new and est are mutually exclusive");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fl_set_key_ct(struct nlattr **tb,
|
||||
struct flow_dissector_key_ct *key,
|
||||
struct flow_dissector_key_ct *mask,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
if (tb[TCA_FLOWER_KEY_CT_STATE]) {
|
||||
int err;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_NF_CONNTRACK)) {
|
||||
NL_SET_ERR_MSG(extack, "Conntrack isn't enabled");
|
||||
return -EOPNOTSUPP;
|
||||
@ -1407,6 +1435,13 @@ static int fl_set_key_ct(struct nlattr **tb,
|
||||
fl_set_key_val(tb, &key->ct_state, TCA_FLOWER_KEY_CT_STATE,
|
||||
&mask->ct_state, TCA_FLOWER_KEY_CT_STATE_MASK,
|
||||
sizeof(key->ct_state));
|
||||
|
||||
err = fl_validate_ct_state(mask->ct_state,
|
||||
tb[TCA_FLOWER_KEY_CT_STATE_MASK],
|
||||
extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
}
|
||||
if (tb[TCA_FLOWER_KEY_CT_ZONE]) {
|
||||
if (!IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES)) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
# Create 2 namespaces with two veth peers, and
|
||||
# forward packets in-between using generic XDP
|
||||
#
|
||||
@ -57,12 +57,8 @@ test_xdp_redirect()
|
||||
ip link set dev veth1 $xdpmode obj test_xdp_redirect.o sec redirect_to_222 &> /dev/null
|
||||
ip link set dev veth2 $xdpmode obj test_xdp_redirect.o sec redirect_to_111 &> /dev/null
|
||||
|
||||
ip netns exec ns1 ping -c 1 10.1.1.22 &> /dev/null
|
||||
local ret1=$?
|
||||
ip netns exec ns2 ping -c 1 10.1.1.11 &> /dev/null
|
||||
local ret2=$?
|
||||
|
||||
if [ $ret1 -eq 0 -a $ret2 -eq 0 ]; then
|
||||
if ip netns exec ns1 ping -c 1 10.1.1.22 &> /dev/null &&
|
||||
ip netns exec ns2 ping -c 1 10.1.1.11 &> /dev/null; then
|
||||
echo "selftests: test_xdp_redirect $xdpmode [PASS]";
|
||||
else
|
||||
ret=1
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
ALL_TESTS="match_dst_mac_test match_src_mac_test match_dst_ip_test \
|
||||
match_src_ip_test match_ip_flags_test match_pcp_test match_vlan_test \
|
||||
match_ip_tos_test match_indev_test match_mpls_label_test \
|
||||
match_ip_tos_test match_indev_testmatch_ip_ttl_test match_mpls_label_test \
|
||||
match_mpls_tc_test match_mpls_bos_test match_mpls_ttl_test \
|
||||
match_mpls_lse_test"
|
||||
NUM_NETIFS=2
|
||||
@ -312,6 +312,42 @@ match_ip_tos_test()
|
||||
log_test "ip_tos match ($tcflags)"
|
||||
}
|
||||
|
||||
match_ip_ttl_test()
|
||||
{
|
||||
RET=0
|
||||
|
||||
tc filter add dev $h2 ingress protocol ip pref 1 handle 101 flower \
|
||||
$tcflags dst_ip 192.0.2.2 ip_ttl 63 action drop
|
||||
tc filter add dev $h2 ingress protocol ip pref 2 handle 102 flower \
|
||||
$tcflags dst_ip 192.0.2.2 action drop
|
||||
|
||||
$MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
|
||||
-t ip "ttl=63" -q
|
||||
|
||||
$MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
|
||||
-t ip "ttl=63,mf,frag=256" -q
|
||||
|
||||
tc_check_packets "dev $h2 ingress" 102 1
|
||||
check_fail $? "Matched on the wrong filter (no check on ttl)"
|
||||
|
||||
tc_check_packets "dev $h2 ingress" 101 2
|
||||
check_err $? "Did not match on correct filter (ttl=63)"
|
||||
|
||||
$MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
|
||||
-t ip "ttl=255" -q
|
||||
|
||||
tc_check_packets "dev $h2 ingress" 101 3
|
||||
check_fail $? "Matched on a wrong filter (ttl=63)"
|
||||
|
||||
tc_check_packets "dev $h2 ingress" 102 1
|
||||
check_err $? "Did not match on correct filter (no check on ttl)"
|
||||
|
||||
tc filter del dev $h2 ingress protocol ip pref 2 handle 102 flower
|
||||
tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower
|
||||
|
||||
log_test "ip_ttl match ($tcflags)"
|
||||
}
|
||||
|
||||
match_indev_test()
|
||||
{
|
||||
RET=0
|
||||
|
Loading…
Reference in New Issue
Block a user