forked from Minki/linux
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
drivers/net/ethernet/cadence/macb_main.c5cebb40bc9
("net: macb: Fix PTP one step sync support")138badbc21
("net: macb: use NAPI for TX completion path") https://lore.kernel.org/all/20220523111021.31489367@canb.auug.org.au/ net/smc/af_smc.c75c1edf23b
("net/smc: postpone sk_refcnt increment in connect()")3aba103006
("net/smc: align the connect behaviour with TCP") https://lore.kernel.org/all/20220524114408.4bf1af38@canb.auug.org.au/ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
677fb75253
@ -382,6 +382,15 @@ option is set to SOCK_TXREHASH_DEFAULT (i. e. not overridden by setsockopt).
|
|||||||
If set to 1 (default), hash rethink is performed on listening socket.
|
If set to 1 (default), hash rethink is performed on listening socket.
|
||||||
If set to 0, hash rethink is not performed.
|
If set to 0, hash rethink is not performed.
|
||||||
|
|
||||||
|
gro_normal_batch
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Maximum number of the segments to batch up on output of GRO. When a packet
|
||||||
|
exits GRO, either as a coalesced superframe or as an original packet which
|
||||||
|
GRO has decided not to coalesce, it is placed on a per-NAPI list. This
|
||||||
|
list is then passed to the stack when the number of segments reaches the
|
||||||
|
gro_normal_batch limit.
|
||||||
|
|
||||||
2. /proc/sys/net/unix - Parameters for Unix domain sockets
|
2. /proc/sys/net/unix - Parameters for Unix domain sockets
|
||||||
----------------------------------------------------------
|
----------------------------------------------------------
|
||||||
|
|
||||||
|
@ -943,7 +943,7 @@ static void amt_req_work(struct work_struct *work)
|
|||||||
if (amt->status < AMT_STATUS_RECEIVED_ADVERTISEMENT)
|
if (amt->status < AMT_STATUS_RECEIVED_ADVERTISEMENT)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (amt->req_cnt++ > AMT_MAX_REQ_COUNT) {
|
if (amt->req_cnt > AMT_MAX_REQ_COUNT) {
|
||||||
netdev_dbg(amt->dev, "Gateway is not ready");
|
netdev_dbg(amt->dev, "Gateway is not ready");
|
||||||
amt->qi = AMT_INIT_REQ_TIMEOUT;
|
amt->qi = AMT_INIT_REQ_TIMEOUT;
|
||||||
amt->ready4 = false;
|
amt->ready4 = false;
|
||||||
@ -951,13 +951,15 @@ static void amt_req_work(struct work_struct *work)
|
|||||||
amt->remote_ip = 0;
|
amt->remote_ip = 0;
|
||||||
__amt_update_gw_status(amt, AMT_STATUS_INIT, false);
|
__amt_update_gw_status(amt, AMT_STATUS_INIT, false);
|
||||||
amt->req_cnt = 0;
|
amt->req_cnt = 0;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
spin_unlock_bh(&amt->lock);
|
spin_unlock_bh(&amt->lock);
|
||||||
|
|
||||||
amt_send_request(amt, false);
|
amt_send_request(amt, false);
|
||||||
amt_send_request(amt, true);
|
amt_send_request(amt, true);
|
||||||
amt_update_gw_status(amt, AMT_STATUS_SENT_REQUEST, true);
|
|
||||||
spin_lock_bh(&amt->lock);
|
spin_lock_bh(&amt->lock);
|
||||||
|
__amt_update_gw_status(amt, AMT_STATUS_SENT_REQUEST, true);
|
||||||
|
amt->req_cnt++;
|
||||||
out:
|
out:
|
||||||
exp = min_t(u32, (1 * (1 << amt->req_cnt)), AMT_MAX_REQ_TIMEOUT);
|
exp = min_t(u32, (1 * (1 << amt->req_cnt)), AMT_MAX_REQ_TIMEOUT);
|
||||||
mod_delayed_work(amt_wq, &amt->req_wq, msecs_to_jiffies(exp * 1000));
|
mod_delayed_work(amt_wq, &amt->req_wq, msecs_to_jiffies(exp * 1000));
|
||||||
@ -2696,9 +2698,8 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb)
|
|||||||
err = true;
|
err = true;
|
||||||
goto drop;
|
goto drop;
|
||||||
}
|
}
|
||||||
if (amt_advertisement_handler(amt, skb))
|
err = amt_advertisement_handler(amt, skb);
|
||||||
amt->dev->stats.rx_dropped++;
|
break;
|
||||||
goto out;
|
|
||||||
case AMT_MSG_MULTICAST_DATA:
|
case AMT_MSG_MULTICAST_DATA:
|
||||||
if (iph->saddr != amt->remote_ip) {
|
if (iph->saddr != amt->remote_ip) {
|
||||||
netdev_dbg(amt->dev, "Invalid Relay IP\n");
|
netdev_dbg(amt->dev, "Invalid Relay IP\n");
|
||||||
|
@ -5591,16 +5591,23 @@ static int bond_ethtool_get_ts_info(struct net_device *bond_dev,
|
|||||||
const struct ethtool_ops *ops;
|
const struct ethtool_ops *ops;
|
||||||
struct net_device *real_dev;
|
struct net_device *real_dev;
|
||||||
struct phy_device *phydev;
|
struct phy_device *phydev;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
real_dev = bond_option_active_slave_get_rcu(bond);
|
real_dev = bond_option_active_slave_get_rcu(bond);
|
||||||
|
dev_hold(real_dev);
|
||||||
|
rcu_read_unlock();
|
||||||
|
|
||||||
if (real_dev) {
|
if (real_dev) {
|
||||||
ops = real_dev->ethtool_ops;
|
ops = real_dev->ethtool_ops;
|
||||||
phydev = real_dev->phydev;
|
phydev = real_dev->phydev;
|
||||||
|
|
||||||
if (phy_has_tsinfo(phydev)) {
|
if (phy_has_tsinfo(phydev)) {
|
||||||
return phy_ts_info(phydev, info);
|
ret = phy_ts_info(phydev, info);
|
||||||
|
goto out;
|
||||||
} else if (ops->get_ts_info) {
|
} else if (ops->get_ts_info) {
|
||||||
return ops->get_ts_info(real_dev, info);
|
ret = ops->get_ts_info(real_dev, info);
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5608,7 +5615,9 @@ static int bond_ethtool_get_ts_info(struct net_device *bond_dev,
|
|||||||
SOF_TIMESTAMPING_SOFTWARE;
|
SOF_TIMESTAMPING_SOFTWARE;
|
||||||
info->phc_index = -1;
|
info->phc_index = -1;
|
||||||
|
|
||||||
return 0;
|
out:
|
||||||
|
dev_put(real_dev);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct ethtool_ops bond_ethtool_ops = {
|
static const struct ethtool_ops bond_ethtool_ops = {
|
||||||
|
@ -72,7 +72,6 @@ source "drivers/net/dsa/realtek/Kconfig"
|
|||||||
|
|
||||||
config NET_DSA_SMSC_LAN9303
|
config NET_DSA_SMSC_LAN9303
|
||||||
tristate
|
tristate
|
||||||
depends on VLAN_8021Q || VLAN_8021Q=n
|
|
||||||
select NET_DSA_TAG_LAN9303
|
select NET_DSA_TAG_LAN9303
|
||||||
select REGMAP
|
select REGMAP
|
||||||
help
|
help
|
||||||
@ -82,6 +81,7 @@ config NET_DSA_SMSC_LAN9303
|
|||||||
config NET_DSA_SMSC_LAN9303_I2C
|
config NET_DSA_SMSC_LAN9303_I2C
|
||||||
tristate "SMSC/Microchip LAN9303 3-ports 10/100 ethernet switch in I2C managed mode"
|
tristate "SMSC/Microchip LAN9303 3-ports 10/100 ethernet switch in I2C managed mode"
|
||||||
depends on I2C
|
depends on I2C
|
||||||
|
depends on VLAN_8021Q || VLAN_8021Q=n
|
||||||
select NET_DSA_SMSC_LAN9303
|
select NET_DSA_SMSC_LAN9303
|
||||||
select REGMAP_I2C
|
select REGMAP_I2C
|
||||||
help
|
help
|
||||||
@ -91,6 +91,7 @@ config NET_DSA_SMSC_LAN9303_I2C
|
|||||||
config NET_DSA_SMSC_LAN9303_MDIO
|
config NET_DSA_SMSC_LAN9303_MDIO
|
||||||
tristate "SMSC/Microchip LAN9303 3-ports 10/100 ethernet switch in MDIO managed mode"
|
tristate "SMSC/Microchip LAN9303 3-ports 10/100 ethernet switch in MDIO managed mode"
|
||||||
select NET_DSA_SMSC_LAN9303
|
select NET_DSA_SMSC_LAN9303
|
||||||
|
depends on VLAN_8021Q || VLAN_8021Q=n
|
||||||
help
|
help
|
||||||
Enable access functions if the SMSC/Microchip LAN9303 is configured
|
Enable access functions if the SMSC/Microchip LAN9303 is configured
|
||||||
for MDIO managed mode.
|
for MDIO managed mode.
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#include <linux/iopoll.h>
|
#include <linux/iopoll.h>
|
||||||
#include <linux/phy/phy.h>
|
#include <linux/phy/phy.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/ptp_classify.h>
|
||||||
#include <linux/reset.h>
|
#include <linux/reset.h>
|
||||||
#include "macb.h"
|
#include "macb.h"
|
||||||
|
|
||||||
@ -1122,6 +1123,36 @@ static void macb_tx_error_task(struct work_struct *work)
|
|||||||
napi_enable(&queue->napi_tx);
|
napi_enable(&queue->napi_tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool ptp_one_step_sync(struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
struct ptp_header *hdr;
|
||||||
|
unsigned int ptp_class;
|
||||||
|
u8 msgtype;
|
||||||
|
|
||||||
|
/* No need to parse packet if PTP TS is not involved */
|
||||||
|
if (likely(!(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)))
|
||||||
|
goto not_oss;
|
||||||
|
|
||||||
|
/* Identify and return whether PTP one step sync is being processed */
|
||||||
|
ptp_class = ptp_classify_raw(skb);
|
||||||
|
if (ptp_class == PTP_CLASS_NONE)
|
||||||
|
goto not_oss;
|
||||||
|
|
||||||
|
hdr = ptp_parse_header(skb, ptp_class);
|
||||||
|
if (!hdr)
|
||||||
|
goto not_oss;
|
||||||
|
|
||||||
|
if (hdr->flag_field[0] & PTP_FLAG_TWOSTEP)
|
||||||
|
goto not_oss;
|
||||||
|
|
||||||
|
msgtype = ptp_get_msgtype(hdr, ptp_class);
|
||||||
|
if (msgtype == PTP_MSGTYPE_SYNC)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
not_oss:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static int macb_tx_complete(struct macb_queue *queue, int budget)
|
static int macb_tx_complete(struct macb_queue *queue, int budget)
|
||||||
{
|
{
|
||||||
struct macb *bp = queue->bp;
|
struct macb *bp = queue->bp;
|
||||||
@ -1158,8 +1189,8 @@ static int macb_tx_complete(struct macb_queue *queue, int budget)
|
|||||||
|
|
||||||
/* First, update TX stats if needed */
|
/* First, update TX stats if needed */
|
||||||
if (skb) {
|
if (skb) {
|
||||||
if (unlikely(skb_shinfo(skb)->tx_flags &
|
if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
|
||||||
SKBTX_HW_TSTAMP) &&
|
!ptp_one_step_sync(skb) &&
|
||||||
gem_ptp_do_txstamp(queue, skb, desc) == 0) {
|
gem_ptp_do_txstamp(queue, skb, desc) == 0) {
|
||||||
/* skb now belongs to timestamp buffer
|
/* skb now belongs to timestamp buffer
|
||||||
* and will be removed later
|
* and will be removed later
|
||||||
@ -2063,7 +2094,8 @@ static unsigned int macb_tx_map(struct macb *bp,
|
|||||||
ctrl |= MACB_BF(TX_LSO, lso_ctrl);
|
ctrl |= MACB_BF(TX_LSO, lso_ctrl);
|
||||||
ctrl |= MACB_BF(TX_TCP_SEQ_SRC, seq_ctrl);
|
ctrl |= MACB_BF(TX_TCP_SEQ_SRC, seq_ctrl);
|
||||||
if ((bp->dev->features & NETIF_F_HW_CSUM) &&
|
if ((bp->dev->features & NETIF_F_HW_CSUM) &&
|
||||||
skb->ip_summed != CHECKSUM_PARTIAL && !lso_ctrl)
|
skb->ip_summed != CHECKSUM_PARTIAL && !lso_ctrl &&
|
||||||
|
!ptp_one_step_sync(skb))
|
||||||
ctrl |= MACB_BIT(TX_NOCRC);
|
ctrl |= MACB_BIT(TX_NOCRC);
|
||||||
} else
|
} else
|
||||||
/* Only set MSS/MFS on payload descriptors
|
/* Only set MSS/MFS on payload descriptors
|
||||||
@ -2161,7 +2193,7 @@ static int macb_pad_and_fcs(struct sk_buff **skb, struct net_device *ndev)
|
|||||||
|
|
||||||
if (!(ndev->features & NETIF_F_HW_CSUM) ||
|
if (!(ndev->features & NETIF_F_HW_CSUM) ||
|
||||||
!((*skb)->ip_summed != CHECKSUM_PARTIAL) ||
|
!((*skb)->ip_summed != CHECKSUM_PARTIAL) ||
|
||||||
skb_shinfo(*skb)->gso_size) /* Not available for GSO */
|
skb_shinfo(*skb)->gso_size || ptp_one_step_sync(*skb))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (padlen <= 0) {
|
if (padlen <= 0) {
|
||||||
|
@ -470,8 +470,10 @@ int gem_set_hwtst(struct net_device *dev, struct ifreq *ifr, int cmd)
|
|||||||
case HWTSTAMP_TX_ONESTEP_SYNC:
|
case HWTSTAMP_TX_ONESTEP_SYNC:
|
||||||
if (gem_ptp_set_one_step_sync(bp, 1) != 0)
|
if (gem_ptp_set_one_step_sync(bp, 1) != 0)
|
||||||
return -ERANGE;
|
return -ERANGE;
|
||||||
fallthrough;
|
tx_bd_control = TSTAMP_ALL_FRAMES;
|
||||||
|
break;
|
||||||
case HWTSTAMP_TX_ON:
|
case HWTSTAMP_TX_ON:
|
||||||
|
gem_ptp_set_one_step_sync(bp, 0);
|
||||||
tx_bd_control = TSTAMP_ALL_FRAMES;
|
tx_bd_control = TSTAMP_ALL_FRAMES;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1097,6 +1097,7 @@ static void dpaa2_eth_free_tx_fd(struct dpaa2_eth_priv *priv,
|
|||||||
u32 fd_len = dpaa2_fd_get_len(fd);
|
u32 fd_len = dpaa2_fd_get_len(fd);
|
||||||
struct dpaa2_sg_entry *sgt;
|
struct dpaa2_sg_entry *sgt;
|
||||||
int should_free_skb = 1;
|
int should_free_skb = 1;
|
||||||
|
void *tso_hdr;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
fd_addr = dpaa2_fd_get_addr(fd);
|
fd_addr = dpaa2_fd_get_addr(fd);
|
||||||
@ -1135,20 +1136,21 @@ static void dpaa2_eth_free_tx_fd(struct dpaa2_eth_priv *priv,
|
|||||||
sgt = (struct dpaa2_sg_entry *)(buffer_start +
|
sgt = (struct dpaa2_sg_entry *)(buffer_start +
|
||||||
priv->tx_data_offset);
|
priv->tx_data_offset);
|
||||||
|
|
||||||
|
/* Unmap the SGT buffer */
|
||||||
|
dma_unmap_single(dev, fd_addr, swa->tso.sgt_size,
|
||||||
|
DMA_BIDIRECTIONAL);
|
||||||
|
|
||||||
/* Unmap and free the header */
|
/* Unmap and free the header */
|
||||||
|
tso_hdr = dpaa2_iova_to_virt(priv->iommu_domain, dpaa2_sg_get_addr(sgt));
|
||||||
dma_unmap_single(dev, dpaa2_sg_get_addr(sgt), TSO_HEADER_SIZE,
|
dma_unmap_single(dev, dpaa2_sg_get_addr(sgt), TSO_HEADER_SIZE,
|
||||||
DMA_TO_DEVICE);
|
DMA_TO_DEVICE);
|
||||||
kfree(dpaa2_iova_to_virt(priv->iommu_domain, dpaa2_sg_get_addr(sgt)));
|
kfree(tso_hdr);
|
||||||
|
|
||||||
/* Unmap the other SG entries for the data */
|
/* Unmap the other SG entries for the data */
|
||||||
for (i = 1; i < swa->tso.num_sg; i++)
|
for (i = 1; i < swa->tso.num_sg; i++)
|
||||||
dma_unmap_single(dev, dpaa2_sg_get_addr(&sgt[i]),
|
dma_unmap_single(dev, dpaa2_sg_get_addr(&sgt[i]),
|
||||||
dpaa2_sg_get_len(&sgt[i]), DMA_TO_DEVICE);
|
dpaa2_sg_get_len(&sgt[i]), DMA_TO_DEVICE);
|
||||||
|
|
||||||
/* Unmap the SGT buffer */
|
|
||||||
dma_unmap_single(dev, fd_addr, swa->sg.sgt_size,
|
|
||||||
DMA_BIDIRECTIONAL);
|
|
||||||
|
|
||||||
if (!swa->tso.is_last_fd)
|
if (!swa->tso.is_last_fd)
|
||||||
should_free_skb = 0;
|
should_free_skb = 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -3876,9 +3876,11 @@ fec_probe(struct platform_device *pdev)
|
|||||||
mutex_init(&fep->ptp_clk_mutex);
|
mutex_init(&fep->ptp_clk_mutex);
|
||||||
|
|
||||||
/* clk_ref is optional, depends on board */
|
/* clk_ref is optional, depends on board */
|
||||||
fep->clk_ref = devm_clk_get(&pdev->dev, "enet_clk_ref");
|
fep->clk_ref = devm_clk_get_optional(&pdev->dev, "enet_clk_ref");
|
||||||
if (IS_ERR(fep->clk_ref))
|
if (IS_ERR(fep->clk_ref)) {
|
||||||
fep->clk_ref = NULL;
|
ret = PTR_ERR(fep->clk_ref);
|
||||||
|
goto failed_clk;
|
||||||
|
}
|
||||||
fep->clk_ref_rate = clk_get_rate(fep->clk_ref);
|
fep->clk_ref_rate = clk_get_rate(fep->clk_ref);
|
||||||
|
|
||||||
/* clk_2x_txclk is optional, depends on board */
|
/* clk_2x_txclk is optional, depends on board */
|
||||||
|
@ -386,7 +386,7 @@ static int alloc_wqes_shadow(struct hinic_wq *wq)
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
wq->shadow_idx = devm_kcalloc(&pdev->dev, wq->num_q_pages,
|
wq->shadow_idx = devm_kcalloc(&pdev->dev, wq->num_q_pages,
|
||||||
sizeof(wq->prod_idx), GFP_KERNEL);
|
sizeof(*wq->shadow_idx), GFP_KERNEL);
|
||||||
if (!wq->shadow_idx)
|
if (!wq->shadow_idx)
|
||||||
goto err_shadow_idx;
|
goto err_shadow_idx;
|
||||||
|
|
||||||
|
@ -1084,8 +1084,9 @@ static int stmmac_test_rxp(struct stmmac_priv *priv)
|
|||||||
unsigned char addr[ETH_ALEN] = {0xde, 0xad, 0xbe, 0xef, 0x00, 0x00};
|
unsigned char addr[ETH_ALEN] = {0xde, 0xad, 0xbe, 0xef, 0x00, 0x00};
|
||||||
struct tc_cls_u32_offload cls_u32 = { };
|
struct tc_cls_u32_offload cls_u32 = { };
|
||||||
struct stmmac_packet_attrs attr = { };
|
struct stmmac_packet_attrs attr = { };
|
||||||
struct tc_action **actions, *act;
|
struct tc_action **actions;
|
||||||
struct tc_u32_sel *sel;
|
struct tc_u32_sel *sel;
|
||||||
|
struct tcf_gact *gact;
|
||||||
struct tcf_exts *exts;
|
struct tcf_exts *exts;
|
||||||
int ret, i, nk = 1;
|
int ret, i, nk = 1;
|
||||||
|
|
||||||
@ -1110,8 +1111,8 @@ static int stmmac_test_rxp(struct stmmac_priv *priv)
|
|||||||
goto cleanup_exts;
|
goto cleanup_exts;
|
||||||
}
|
}
|
||||||
|
|
||||||
act = kcalloc(nk, sizeof(*act), GFP_KERNEL);
|
gact = kcalloc(nk, sizeof(*gact), GFP_KERNEL);
|
||||||
if (!act) {
|
if (!gact) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto cleanup_actions;
|
goto cleanup_actions;
|
||||||
}
|
}
|
||||||
@ -1126,9 +1127,7 @@ static int stmmac_test_rxp(struct stmmac_priv *priv)
|
|||||||
exts->nr_actions = nk;
|
exts->nr_actions = nk;
|
||||||
exts->actions = actions;
|
exts->actions = actions;
|
||||||
for (i = 0; i < nk; i++) {
|
for (i = 0; i < nk; i++) {
|
||||||
struct tcf_gact *gact = to_gact(&act[i]);
|
actions[i] = (struct tc_action *)&gact[i];
|
||||||
|
|
||||||
actions[i] = &act[i];
|
|
||||||
gact->tcf_action = TC_ACT_SHOT;
|
gact->tcf_action = TC_ACT_SHOT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1152,7 +1151,7 @@ static int stmmac_test_rxp(struct stmmac_priv *priv)
|
|||||||
stmmac_tc_setup_cls_u32(priv, priv, &cls_u32);
|
stmmac_tc_setup_cls_u32(priv, priv, &cls_u32);
|
||||||
|
|
||||||
cleanup_act:
|
cleanup_act:
|
||||||
kfree(act);
|
kfree(gact);
|
||||||
cleanup_actions:
|
cleanup_actions:
|
||||||
kfree(actions);
|
kfree(actions);
|
||||||
cleanup_exts:
|
cleanup_exts:
|
||||||
|
@ -2643,7 +2643,10 @@ static int netvsc_suspend(struct hv_device *dev)
|
|||||||
|
|
||||||
/* Save the current config info */
|
/* Save the current config info */
|
||||||
ndev_ctx->saved_netvsc_dev_info = netvsc_devinfo_get(nvdev);
|
ndev_ctx->saved_netvsc_dev_info = netvsc_devinfo_get(nvdev);
|
||||||
|
if (!ndev_ctx->saved_netvsc_dev_info) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
ret = netvsc_detach(net, nvdev);
|
ret = netvsc_detach(net, nvdev);
|
||||||
out:
|
out:
|
||||||
rtnl_unlock();
|
rtnl_unlock();
|
||||||
|
@ -241,7 +241,7 @@ int st21nfca_hci_se_io(struct nfc_hci_dev *hdev, u32 se_idx,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(st21nfca_hci_se_io);
|
EXPORT_SYMBOL(st21nfca_hci_se_io);
|
||||||
|
|
||||||
static void st21nfca_se_wt_timeout(struct timer_list *t)
|
static void st21nfca_se_wt_work(struct work_struct *work)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* No answer from the secure element
|
* No answer from the secure element
|
||||||
@ -254,8 +254,9 @@ static void st21nfca_se_wt_timeout(struct timer_list *t)
|
|||||||
*/
|
*/
|
||||||
/* hardware reset managed through VCC_UICC_OUT power supply */
|
/* hardware reset managed through VCC_UICC_OUT power supply */
|
||||||
u8 param = 0x01;
|
u8 param = 0x01;
|
||||||
struct st21nfca_hci_info *info = from_timer(info, t,
|
struct st21nfca_hci_info *info = container_of(work,
|
||||||
se_info.bwi_timer);
|
struct st21nfca_hci_info,
|
||||||
|
se_info.timeout_work);
|
||||||
|
|
||||||
info->se_info.bwi_active = false;
|
info->se_info.bwi_active = false;
|
||||||
|
|
||||||
@ -271,6 +272,13 @@ static void st21nfca_se_wt_timeout(struct timer_list *t)
|
|||||||
info->se_info.cb(info->se_info.cb_context, NULL, 0, -ETIME);
|
info->se_info.cb(info->se_info.cb_context, NULL, 0, -ETIME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void st21nfca_se_wt_timeout(struct timer_list *t)
|
||||||
|
{
|
||||||
|
struct st21nfca_hci_info *info = from_timer(info, t, se_info.bwi_timer);
|
||||||
|
|
||||||
|
schedule_work(&info->se_info.timeout_work);
|
||||||
|
}
|
||||||
|
|
||||||
static void st21nfca_se_activation_timeout(struct timer_list *t)
|
static void st21nfca_se_activation_timeout(struct timer_list *t)
|
||||||
{
|
{
|
||||||
struct st21nfca_hci_info *info = from_timer(info, t,
|
struct st21nfca_hci_info *info = from_timer(info, t,
|
||||||
@ -360,6 +368,7 @@ int st21nfca_apdu_reader_event_received(struct nfc_hci_dev *hdev,
|
|||||||
switch (event) {
|
switch (event) {
|
||||||
case ST21NFCA_EVT_TRANSMIT_DATA:
|
case ST21NFCA_EVT_TRANSMIT_DATA:
|
||||||
del_timer_sync(&info->se_info.bwi_timer);
|
del_timer_sync(&info->se_info.bwi_timer);
|
||||||
|
cancel_work_sync(&info->se_info.timeout_work);
|
||||||
info->se_info.bwi_active = false;
|
info->se_info.bwi_active = false;
|
||||||
r = nfc_hci_send_event(hdev, ST21NFCA_DEVICE_MGNT_GATE,
|
r = nfc_hci_send_event(hdev, ST21NFCA_DEVICE_MGNT_GATE,
|
||||||
ST21NFCA_EVT_SE_END_OF_APDU_TRANSFER, NULL, 0);
|
ST21NFCA_EVT_SE_END_OF_APDU_TRANSFER, NULL, 0);
|
||||||
@ -389,6 +398,7 @@ void st21nfca_se_init(struct nfc_hci_dev *hdev)
|
|||||||
struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
|
struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
|
||||||
|
|
||||||
init_completion(&info->se_info.req_completion);
|
init_completion(&info->se_info.req_completion);
|
||||||
|
INIT_WORK(&info->se_info.timeout_work, st21nfca_se_wt_work);
|
||||||
/* initialize timers */
|
/* initialize timers */
|
||||||
timer_setup(&info->se_info.bwi_timer, st21nfca_se_wt_timeout, 0);
|
timer_setup(&info->se_info.bwi_timer, st21nfca_se_wt_timeout, 0);
|
||||||
info->se_info.bwi_active = false;
|
info->se_info.bwi_active = false;
|
||||||
@ -416,6 +426,7 @@ void st21nfca_se_deinit(struct nfc_hci_dev *hdev)
|
|||||||
if (info->se_info.se_active)
|
if (info->se_info.se_active)
|
||||||
del_timer_sync(&info->se_info.se_active_timer);
|
del_timer_sync(&info->se_info.se_active_timer);
|
||||||
|
|
||||||
|
cancel_work_sync(&info->se_info.timeout_work);
|
||||||
info->se_info.bwi_active = false;
|
info->se_info.bwi_active = false;
|
||||||
info->se_info.se_active = false;
|
info->se_info.se_active = false;
|
||||||
}
|
}
|
||||||
|
@ -141,6 +141,7 @@ struct st21nfca_se_info {
|
|||||||
|
|
||||||
se_io_cb_t cb;
|
se_io_cb_t cb;
|
||||||
void *cb_context;
|
void *cb_context;
|
||||||
|
struct work_struct timeout_work;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct st21nfca_hci_info {
|
struct st21nfca_hci_info {
|
||||||
|
@ -43,6 +43,9 @@
|
|||||||
#define OFF_PTP_SOURCE_UUID 22 /* PTPv1 only */
|
#define OFF_PTP_SOURCE_UUID 22 /* PTPv1 only */
|
||||||
#define OFF_PTP_SEQUENCE_ID 30
|
#define OFF_PTP_SEQUENCE_ID 30
|
||||||
|
|
||||||
|
/* PTP header flag fields */
|
||||||
|
#define PTP_FLAG_TWOSTEP BIT(1)
|
||||||
|
|
||||||
/* Below defines should actually be removed at some point in time. */
|
/* Below defines should actually be removed at some point in time. */
|
||||||
#define IP6_HLEN 40
|
#define IP6_HLEN 40
|
||||||
#define UDP_HLEN 8
|
#define UDP_HLEN 8
|
||||||
|
@ -1330,7 +1330,7 @@ TRACE_EVENT(rxrpc_call_reset,
|
|||||||
__entry->call_serial = call->rx_serial;
|
__entry->call_serial = call->rx_serial;
|
||||||
__entry->conn_serial = call->conn->hi_serial;
|
__entry->conn_serial = call->conn->hi_serial;
|
||||||
__entry->tx_seq = call->tx_hard_ack;
|
__entry->tx_seq = call->tx_hard_ack;
|
||||||
__entry->rx_seq = call->ackr_seen;
|
__entry->rx_seq = call->rx_hard_ack;
|
||||||
),
|
),
|
||||||
|
|
||||||
TP_printk("c=%08x %08x:%08x r=%08x/%08x tx=%08x rx=%08x",
|
TP_printk("c=%08x %08x:%08x r=%08x/%08x tx=%08x rx=%08x",
|
||||||
|
@ -943,10 +943,11 @@ static void create_le_conn_complete(struct hci_dev *hdev, void *data, int err)
|
|||||||
|
|
||||||
bt_dev_err(hdev, "request failed to create LE connection: err %d", err);
|
bt_dev_err(hdev, "request failed to create LE connection: err %d", err);
|
||||||
|
|
||||||
if (!conn)
|
/* Check if connection is still pending */
|
||||||
|
if (conn != hci_lookup_le_connect(hdev))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
hci_le_conn_failed(conn, err);
|
hci_conn_failed(conn, err);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
hci_dev_unlock(hdev);
|
hci_dev_unlock(hdev);
|
||||||
|
@ -5632,10 +5632,12 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
|
|||||||
status = HCI_ERROR_INVALID_PARAMETERS;
|
status = HCI_ERROR_INVALID_PARAMETERS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status) {
|
/* All connection failure handling is taken care of by the
|
||||||
hci_conn_failed(conn, status);
|
* hci_conn_failed function which is triggered by the HCI
|
||||||
|
* request completion callbacks used for connecting.
|
||||||
|
*/
|
||||||
|
if (status)
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
|
||||||
|
|
||||||
if (conn->dst_type == ADDR_LE_DEV_PUBLIC)
|
if (conn->dst_type == ADDR_LE_DEV_PUBLIC)
|
||||||
addr_type = BDADDR_LE_PUBLIC;
|
addr_type = BDADDR_LE_PUBLIC;
|
||||||
|
@ -668,13 +668,12 @@ struct rxrpc_call {
|
|||||||
|
|
||||||
spinlock_t input_lock; /* Lock for packet input to this call */
|
spinlock_t input_lock; /* Lock for packet input to this call */
|
||||||
|
|
||||||
/* receive-phase ACK management */
|
/* Receive-phase ACK management (ACKs we send). */
|
||||||
u8 ackr_reason; /* reason to ACK */
|
u8 ackr_reason; /* reason to ACK */
|
||||||
rxrpc_serial_t ackr_serial; /* serial of packet being ACK'd */
|
rxrpc_serial_t ackr_serial; /* serial of packet being ACK'd */
|
||||||
rxrpc_serial_t ackr_first_seq; /* first sequence number received */
|
rxrpc_seq_t ackr_highest_seq; /* Higest sequence number received */
|
||||||
rxrpc_seq_t ackr_prev_seq; /* previous sequence number received */
|
atomic_t ackr_nr_unacked; /* Number of unacked packets */
|
||||||
rxrpc_seq_t ackr_consumed; /* Highest packet shown consumed */
|
atomic_t ackr_nr_consumed; /* Number of packets needing hard ACK */
|
||||||
rxrpc_seq_t ackr_seen; /* Highest packet shown seen */
|
|
||||||
|
|
||||||
/* RTT management */
|
/* RTT management */
|
||||||
rxrpc_serial_t rtt_serial[4]; /* Serial number of DATA or PING sent */
|
rxrpc_serial_t rtt_serial[4]; /* Serial number of DATA or PING sent */
|
||||||
@ -684,8 +683,10 @@ struct rxrpc_call {
|
|||||||
#define RXRPC_CALL_RTT_AVAIL_MASK 0xf
|
#define RXRPC_CALL_RTT_AVAIL_MASK 0xf
|
||||||
#define RXRPC_CALL_RTT_PEND_SHIFT 8
|
#define RXRPC_CALL_RTT_PEND_SHIFT 8
|
||||||
|
|
||||||
/* transmission-phase ACK management */
|
/* Transmission-phase ACK management (ACKs we've received). */
|
||||||
ktime_t acks_latest_ts; /* Timestamp of latest ACK received */
|
ktime_t acks_latest_ts; /* Timestamp of latest ACK received */
|
||||||
|
rxrpc_seq_t acks_first_seq; /* first sequence number received */
|
||||||
|
rxrpc_seq_t acks_prev_seq; /* Highest previousPacket received */
|
||||||
rxrpc_seq_t acks_lowest_nak; /* Lowest NACK in the buffer (or ==tx_hard_ack) */
|
rxrpc_seq_t acks_lowest_nak; /* Lowest NACK in the buffer (or ==tx_hard_ack) */
|
||||||
rxrpc_seq_t acks_lost_top; /* tx_top at the time lost-ack ping sent */
|
rxrpc_seq_t acks_lost_top; /* tx_top at the time lost-ack ping sent */
|
||||||
rxrpc_serial_t acks_lost_ping; /* Serial number of probe ACK */
|
rxrpc_serial_t acks_lost_ping; /* Serial number of probe ACK */
|
||||||
|
@ -406,7 +406,8 @@ recheck_state:
|
|||||||
goto recheck_state;
|
goto recheck_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test_and_clear_bit(RXRPC_CALL_EV_RESEND, &call->events)) {
|
if (test_and_clear_bit(RXRPC_CALL_EV_RESEND, &call->events) &&
|
||||||
|
call->state != RXRPC_CALL_CLIENT_RECV_REPLY) {
|
||||||
rxrpc_resend(call, now);
|
rxrpc_resend(call, now);
|
||||||
goto recheck_state;
|
goto recheck_state;
|
||||||
}
|
}
|
||||||
|
@ -412,8 +412,8 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
|
|||||||
{
|
{
|
||||||
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
|
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
|
||||||
enum rxrpc_call_state state;
|
enum rxrpc_call_state state;
|
||||||
unsigned int j, nr_subpackets;
|
unsigned int j, nr_subpackets, nr_unacked = 0;
|
||||||
rxrpc_serial_t serial = sp->hdr.serial, ack_serial = 0;
|
rxrpc_serial_t serial = sp->hdr.serial, ack_serial = serial;
|
||||||
rxrpc_seq_t seq0 = sp->hdr.seq, hard_ack;
|
rxrpc_seq_t seq0 = sp->hdr.seq, hard_ack;
|
||||||
bool immediate_ack = false, jumbo_bad = false;
|
bool immediate_ack = false, jumbo_bad = false;
|
||||||
u8 ack = 0;
|
u8 ack = 0;
|
||||||
@ -453,7 +453,6 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
|
|||||||
!rxrpc_receiving_reply(call))
|
!rxrpc_receiving_reply(call))
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
|
||||||
call->ackr_prev_seq = seq0;
|
|
||||||
hard_ack = READ_ONCE(call->rx_hard_ack);
|
hard_ack = READ_ONCE(call->rx_hard_ack);
|
||||||
|
|
||||||
nr_subpackets = sp->nr_subpackets;
|
nr_subpackets = sp->nr_subpackets;
|
||||||
@ -534,6 +533,9 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
|
|||||||
ack_serial = serial;
|
ack_serial = serial;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (after(seq0, call->ackr_highest_seq))
|
||||||
|
call->ackr_highest_seq = seq0;
|
||||||
|
|
||||||
/* Queue the packet. We use a couple of memory barriers here as need
|
/* Queue the packet. We use a couple of memory barriers here as need
|
||||||
* to make sure that rx_top is perceived to be set after the buffer
|
* to make sure that rx_top is perceived to be set after the buffer
|
||||||
* pointer and that the buffer pointer is set after the annotation and
|
* pointer and that the buffer pointer is set after the annotation and
|
||||||
@ -567,6 +569,8 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
|
|||||||
sp = NULL;
|
sp = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nr_unacked++;
|
||||||
|
|
||||||
if (last) {
|
if (last) {
|
||||||
set_bit(RXRPC_CALL_RX_LAST, &call->flags);
|
set_bit(RXRPC_CALL_RX_LAST, &call->flags);
|
||||||
if (!ack) {
|
if (!ack) {
|
||||||
@ -586,9 +590,14 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
|
|||||||
}
|
}
|
||||||
call->rx_expect_next = seq + 1;
|
call->rx_expect_next = seq + 1;
|
||||||
}
|
}
|
||||||
|
if (!ack)
|
||||||
|
ack_serial = serial;
|
||||||
}
|
}
|
||||||
|
|
||||||
ack:
|
ack:
|
||||||
|
if (atomic_add_return(nr_unacked, &call->ackr_nr_unacked) > 2 && !ack)
|
||||||
|
ack = RXRPC_ACK_IDLE;
|
||||||
|
|
||||||
if (ack)
|
if (ack)
|
||||||
rxrpc_propose_ACK(call, ack, ack_serial,
|
rxrpc_propose_ACK(call, ack, ack_serial,
|
||||||
immediate_ack, true,
|
immediate_ack, true,
|
||||||
@ -812,7 +821,7 @@ static void rxrpc_input_soft_acks(struct rxrpc_call *call, u8 *acks,
|
|||||||
static bool rxrpc_is_ack_valid(struct rxrpc_call *call,
|
static bool rxrpc_is_ack_valid(struct rxrpc_call *call,
|
||||||
rxrpc_seq_t first_pkt, rxrpc_seq_t prev_pkt)
|
rxrpc_seq_t first_pkt, rxrpc_seq_t prev_pkt)
|
||||||
{
|
{
|
||||||
rxrpc_seq_t base = READ_ONCE(call->ackr_first_seq);
|
rxrpc_seq_t base = READ_ONCE(call->acks_first_seq);
|
||||||
|
|
||||||
if (after(first_pkt, base))
|
if (after(first_pkt, base))
|
||||||
return true; /* The window advanced */
|
return true; /* The window advanced */
|
||||||
@ -820,7 +829,7 @@ static bool rxrpc_is_ack_valid(struct rxrpc_call *call,
|
|||||||
if (before(first_pkt, base))
|
if (before(first_pkt, base))
|
||||||
return false; /* firstPacket regressed */
|
return false; /* firstPacket regressed */
|
||||||
|
|
||||||
if (after_eq(prev_pkt, call->ackr_prev_seq))
|
if (after_eq(prev_pkt, call->acks_prev_seq))
|
||||||
return true; /* previousPacket hasn't regressed. */
|
return true; /* previousPacket hasn't regressed. */
|
||||||
|
|
||||||
/* Some rx implementations put a serial number in previousPacket. */
|
/* Some rx implementations put a serial number in previousPacket. */
|
||||||
@ -933,8 +942,8 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
|
|||||||
/* Discard any out-of-order or duplicate ACKs (outside lock). */
|
/* Discard any out-of-order or duplicate ACKs (outside lock). */
|
||||||
if (!rxrpc_is_ack_valid(call, first_soft_ack, prev_pkt)) {
|
if (!rxrpc_is_ack_valid(call, first_soft_ack, prev_pkt)) {
|
||||||
trace_rxrpc_rx_discard_ack(call->debug_id, ack_serial,
|
trace_rxrpc_rx_discard_ack(call->debug_id, ack_serial,
|
||||||
first_soft_ack, call->ackr_first_seq,
|
first_soft_ack, call->acks_first_seq,
|
||||||
prev_pkt, call->ackr_prev_seq);
|
prev_pkt, call->acks_prev_seq);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -949,14 +958,14 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
|
|||||||
/* Discard any out-of-order or duplicate ACKs (inside lock). */
|
/* Discard any out-of-order or duplicate ACKs (inside lock). */
|
||||||
if (!rxrpc_is_ack_valid(call, first_soft_ack, prev_pkt)) {
|
if (!rxrpc_is_ack_valid(call, first_soft_ack, prev_pkt)) {
|
||||||
trace_rxrpc_rx_discard_ack(call->debug_id, ack_serial,
|
trace_rxrpc_rx_discard_ack(call->debug_id, ack_serial,
|
||||||
first_soft_ack, call->ackr_first_seq,
|
first_soft_ack, call->acks_first_seq,
|
||||||
prev_pkt, call->ackr_prev_seq);
|
prev_pkt, call->acks_prev_seq);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
call->acks_latest_ts = skb->tstamp;
|
call->acks_latest_ts = skb->tstamp;
|
||||||
|
|
||||||
call->ackr_first_seq = first_soft_ack;
|
call->acks_first_seq = first_soft_ack;
|
||||||
call->ackr_prev_seq = prev_pkt;
|
call->acks_prev_seq = prev_pkt;
|
||||||
|
|
||||||
/* Parse rwind and mtu sizes if provided. */
|
/* Parse rwind and mtu sizes if provided. */
|
||||||
if (buf.info.rxMTU)
|
if (buf.info.rxMTU)
|
||||||
|
@ -74,11 +74,18 @@ static size_t rxrpc_fill_out_ack(struct rxrpc_connection *conn,
|
|||||||
u8 reason)
|
u8 reason)
|
||||||
{
|
{
|
||||||
rxrpc_serial_t serial;
|
rxrpc_serial_t serial;
|
||||||
|
unsigned int tmp;
|
||||||
rxrpc_seq_t hard_ack, top, seq;
|
rxrpc_seq_t hard_ack, top, seq;
|
||||||
int ix;
|
int ix;
|
||||||
u32 mtu, jmax;
|
u32 mtu, jmax;
|
||||||
u8 *ackp = pkt->acks;
|
u8 *ackp = pkt->acks;
|
||||||
|
|
||||||
|
tmp = atomic_xchg(&call->ackr_nr_unacked, 0);
|
||||||
|
tmp |= atomic_xchg(&call->ackr_nr_consumed, 0);
|
||||||
|
if (!tmp && (reason == RXRPC_ACK_DELAY ||
|
||||||
|
reason == RXRPC_ACK_IDLE))
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* Barrier against rxrpc_input_data(). */
|
/* Barrier against rxrpc_input_data(). */
|
||||||
serial = call->ackr_serial;
|
serial = call->ackr_serial;
|
||||||
hard_ack = READ_ONCE(call->rx_hard_ack);
|
hard_ack = READ_ONCE(call->rx_hard_ack);
|
||||||
@ -89,7 +96,7 @@ static size_t rxrpc_fill_out_ack(struct rxrpc_connection *conn,
|
|||||||
pkt->ack.bufferSpace = htons(8);
|
pkt->ack.bufferSpace = htons(8);
|
||||||
pkt->ack.maxSkew = htons(0);
|
pkt->ack.maxSkew = htons(0);
|
||||||
pkt->ack.firstPacket = htonl(hard_ack + 1);
|
pkt->ack.firstPacket = htonl(hard_ack + 1);
|
||||||
pkt->ack.previousPacket = htonl(call->ackr_prev_seq);
|
pkt->ack.previousPacket = htonl(call->ackr_highest_seq);
|
||||||
pkt->ack.serial = htonl(serial);
|
pkt->ack.serial = htonl(serial);
|
||||||
pkt->ack.reason = reason;
|
pkt->ack.reason = reason;
|
||||||
pkt->ack.nAcks = top - hard_ack;
|
pkt->ack.nAcks = top - hard_ack;
|
||||||
@ -223,6 +230,10 @@ int rxrpc_send_ack_packet(struct rxrpc_call *call, bool ping,
|
|||||||
n = rxrpc_fill_out_ack(conn, call, pkt, &hard_ack, &top, reason);
|
n = rxrpc_fill_out_ack(conn, call, pkt, &hard_ack, &top, reason);
|
||||||
|
|
||||||
spin_unlock_bh(&call->lock);
|
spin_unlock_bh(&call->lock);
|
||||||
|
if (n == 0) {
|
||||||
|
kfree(pkt);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
iov[0].iov_base = pkt;
|
iov[0].iov_base = pkt;
|
||||||
iov[0].iov_len = sizeof(pkt->whdr) + sizeof(pkt->ack) + n;
|
iov[0].iov_len = sizeof(pkt->whdr) + sizeof(pkt->ack) + n;
|
||||||
@ -259,13 +270,6 @@ int rxrpc_send_ack_packet(struct rxrpc_call *call, bool ping,
|
|||||||
ntohl(pkt->ack.serial),
|
ntohl(pkt->ack.serial),
|
||||||
false, true,
|
false, true,
|
||||||
rxrpc_propose_ack_retry_tx);
|
rxrpc_propose_ack_retry_tx);
|
||||||
} else {
|
|
||||||
spin_lock_bh(&call->lock);
|
|
||||||
if (after(hard_ack, call->ackr_consumed))
|
|
||||||
call->ackr_consumed = hard_ack;
|
|
||||||
if (after(top, call->ackr_seen))
|
|
||||||
call->ackr_seen = top;
|
|
||||||
spin_unlock_bh(&call->lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rxrpc_set_keepalive(call);
|
rxrpc_set_keepalive(call);
|
||||||
|
@ -260,11 +260,9 @@ static void rxrpc_rotate_rx_window(struct rxrpc_call *call)
|
|||||||
rxrpc_end_rx_phase(call, serial);
|
rxrpc_end_rx_phase(call, serial);
|
||||||
} else {
|
} else {
|
||||||
/* Check to see if there's an ACK that needs sending. */
|
/* Check to see if there's an ACK that needs sending. */
|
||||||
if (after_eq(hard_ack, call->ackr_consumed + 2) ||
|
if (atomic_inc_return(&call->ackr_nr_consumed) > 2)
|
||||||
after_eq(top, call->ackr_seen + 2) ||
|
rxrpc_propose_ACK(call, RXRPC_ACK_IDLE, serial,
|
||||||
(hard_ack == top && after(hard_ack, call->ackr_consumed)))
|
true, false,
|
||||||
rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, serial,
|
|
||||||
true, true,
|
|
||||||
rxrpc_propose_ack_rotate_rx);
|
rxrpc_propose_ack_rotate_rx);
|
||||||
if (call->ackr_reason && call->ackr_reason != RXRPC_ACK_DELAY)
|
if (call->ackr_reason && call->ackr_reason != RXRPC_ACK_DELAY)
|
||||||
rxrpc_send_ack_packet(call, false, NULL);
|
rxrpc_send_ack_packet(call, false, NULL);
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
static struct ctl_table_header *rxrpc_sysctl_reg_table;
|
static struct ctl_table_header *rxrpc_sysctl_reg_table;
|
||||||
static const unsigned int four = 4;
|
static const unsigned int four = 4;
|
||||||
static const unsigned int thirtytwo = 32;
|
static const unsigned int max_backlog = RXRPC_BACKLOG_MAX - 1;
|
||||||
static const unsigned int n_65535 = 65535;
|
static const unsigned int n_65535 = 65535;
|
||||||
static const unsigned int n_max_acks = RXRPC_RXTX_BUFF_SIZE - 1;
|
static const unsigned int n_max_acks = RXRPC_RXTX_BUFF_SIZE - 1;
|
||||||
static const unsigned long one_jiffy = 1;
|
static const unsigned long one_jiffy = 1;
|
||||||
@ -89,7 +89,7 @@ static struct ctl_table rxrpc_sysctl_table[] = {
|
|||||||
.mode = 0644,
|
.mode = 0644,
|
||||||
.proc_handler = proc_dointvec_minmax,
|
.proc_handler = proc_dointvec_minmax,
|
||||||
.extra1 = (void *)&four,
|
.extra1 = (void *)&four,
|
||||||
.extra2 = (void *)&thirtytwo,
|
.extra2 = (void *)&max_backlog,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.procname = "rx_window_size",
|
.procname = "rx_window_size",
|
||||||
|
@ -1584,11 +1584,11 @@ static int smc_connect(struct socket *sock, struct sockaddr *addr,
|
|||||||
if (rc && rc != -EINPROGRESS)
|
if (rc && rc != -EINPROGRESS)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
sock_hold(&smc->sk); /* sock put in passive closing */
|
|
||||||
if (smc->use_fallback) {
|
if (smc->use_fallback) {
|
||||||
sock->state = rc ? SS_CONNECTING : SS_CONNECTED;
|
sock->state = rc ? SS_CONNECTING : SS_CONNECTED;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
sock_hold(&smc->sk); /* sock put in passive closing */
|
||||||
if (flags & O_NONBLOCK) {
|
if (flags & O_NONBLOCK) {
|
||||||
if (queue_work(smc_hs_wq, &smc->connect_work))
|
if (queue_work(smc_hs_wq, &smc->connect_work))
|
||||||
smc->connect_nonblock = 1;
|
smc->connect_nonblock = 1;
|
||||||
@ -2118,13 +2118,13 @@ static int smc_listen_rdma_reg(struct smc_sock *new_smc, bool local_first)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void smc_find_rdma_v2_device_serv(struct smc_sock *new_smc,
|
static int smc_find_rdma_v2_device_serv(struct smc_sock *new_smc,
|
||||||
struct smc_clc_msg_proposal *pclc,
|
struct smc_clc_msg_proposal *pclc,
|
||||||
struct smc_init_info *ini)
|
struct smc_init_info *ini)
|
||||||
{
|
{
|
||||||
struct smc_clc_v2_extension *smc_v2_ext;
|
struct smc_clc_v2_extension *smc_v2_ext;
|
||||||
u8 smcr_version;
|
u8 smcr_version;
|
||||||
int rc;
|
int rc = 0;
|
||||||
|
|
||||||
if (!(ini->smcr_version & SMC_V2) || !smcr_indicated(ini->smc_type_v2))
|
if (!(ini->smcr_version & SMC_V2) || !smcr_indicated(ini->smc_type_v2))
|
||||||
goto not_found;
|
goto not_found;
|
||||||
@ -2142,26 +2142,31 @@ static void smc_find_rdma_v2_device_serv(struct smc_sock *new_smc,
|
|||||||
ini->smcrv2.saddr = new_smc->clcsock->sk->sk_rcv_saddr;
|
ini->smcrv2.saddr = new_smc->clcsock->sk->sk_rcv_saddr;
|
||||||
ini->smcrv2.daddr = smc_ib_gid_to_ipv4(smc_v2_ext->roce);
|
ini->smcrv2.daddr = smc_ib_gid_to_ipv4(smc_v2_ext->roce);
|
||||||
rc = smc_find_rdma_device(new_smc, ini);
|
rc = smc_find_rdma_device(new_smc, ini);
|
||||||
if (rc) {
|
if (rc)
|
||||||
smc_find_ism_store_rc(rc, ini);
|
|
||||||
goto not_found;
|
goto not_found;
|
||||||
}
|
|
||||||
if (!ini->smcrv2.uses_gateway)
|
if (!ini->smcrv2.uses_gateway)
|
||||||
memcpy(ini->smcrv2.nexthop_mac, pclc->lcl.mac, ETH_ALEN);
|
memcpy(ini->smcrv2.nexthop_mac, pclc->lcl.mac, ETH_ALEN);
|
||||||
|
|
||||||
smcr_version = ini->smcr_version;
|
smcr_version = ini->smcr_version;
|
||||||
ini->smcr_version = SMC_V2;
|
ini->smcr_version = SMC_V2;
|
||||||
rc = smc_listen_rdma_init(new_smc, ini);
|
rc = smc_listen_rdma_init(new_smc, ini);
|
||||||
if (!rc)
|
if (rc) {
|
||||||
rc = smc_listen_rdma_reg(new_smc, ini->first_contact_local);
|
ini->smcr_version = smcr_version;
|
||||||
if (!rc)
|
goto not_found;
|
||||||
return;
|
}
|
||||||
ini->smcr_version = smcr_version;
|
rc = smc_listen_rdma_reg(new_smc, ini->first_contact_local);
|
||||||
smc_find_ism_store_rc(rc, ini);
|
if (rc) {
|
||||||
|
ini->smcr_version = smcr_version;
|
||||||
|
goto not_found;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
not_found:
|
not_found:
|
||||||
|
rc = rc ?: SMC_CLC_DECL_NOSMCDEV;
|
||||||
ini->smcr_version &= ~SMC_V2;
|
ini->smcr_version &= ~SMC_V2;
|
||||||
ini->check_smcrv2 = false;
|
ini->check_smcrv2 = false;
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int smc_find_rdma_v1_device_serv(struct smc_sock *new_smc,
|
static int smc_find_rdma_v1_device_serv(struct smc_sock *new_smc,
|
||||||
@ -2194,6 +2199,7 @@ static int smc_listen_find_device(struct smc_sock *new_smc,
|
|||||||
struct smc_init_info *ini)
|
struct smc_init_info *ini)
|
||||||
{
|
{
|
||||||
int prfx_rc;
|
int prfx_rc;
|
||||||
|
int rc;
|
||||||
|
|
||||||
/* check for ISM device matching V2 proposed device */
|
/* check for ISM device matching V2 proposed device */
|
||||||
smc_find_ism_v2_device_serv(new_smc, pclc, ini);
|
smc_find_ism_v2_device_serv(new_smc, pclc, ini);
|
||||||
@ -2221,14 +2227,18 @@ static int smc_listen_find_device(struct smc_sock *new_smc,
|
|||||||
return ini->rc ?: SMC_CLC_DECL_NOSMCDDEV;
|
return ini->rc ?: SMC_CLC_DECL_NOSMCDDEV;
|
||||||
|
|
||||||
/* check if RDMA V2 is available */
|
/* check if RDMA V2 is available */
|
||||||
smc_find_rdma_v2_device_serv(new_smc, pclc, ini);
|
rc = smc_find_rdma_v2_device_serv(new_smc, pclc, ini);
|
||||||
if (ini->smcrv2.ib_dev_v2)
|
if (!rc)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/* skip V1 check if V2 is unavailable for non-Device reason */
|
||||||
|
if (rc != SMC_CLC_DECL_NOSMCDEV &&
|
||||||
|
rc != SMC_CLC_DECL_NOSMCRDEV &&
|
||||||
|
rc != SMC_CLC_DECL_NOSMCDDEV)
|
||||||
|
return rc;
|
||||||
|
|
||||||
/* check if RDMA V1 is available */
|
/* check if RDMA V1 is available */
|
||||||
if (!prfx_rc) {
|
if (!prfx_rc) {
|
||||||
int rc;
|
|
||||||
|
|
||||||
rc = smc_find_rdma_v1_device_serv(new_smc, pclc, ini);
|
rc = smc_find_rdma_v1_device_serv(new_smc, pclc, ini);
|
||||||
smc_find_ism_store_rc(rc, ini);
|
smc_find_ism_store_rc(rc, ini);
|
||||||
return (!rc) ? 0 : ini->rc;
|
return (!rc) ? 0 : ini->rc;
|
||||||
|
Loading…
Reference in New Issue
Block a user