mirror of
https://github.com/Dasharo/linux.git
synced 2026-03-06 15:25:10 -08:00
Merge tag 'net-6.13-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Pull networking fixes from Paolo Abeni:
"Including fixes from can and netfilter.
Current release - regressions:
- rtnetlink: fix double call of rtnl_link_get_net_ifla()
- tcp: populate XPS related fields of timewait sockets
- ethtool: fix access to uninitialized fields in set RXNFC command
- selinux: use sk_to_full_sk() in selinux_ip_output()
Current release - new code bugs:
- net: make napi_hash_lock irq safe
- eth:
- bnxt_en: support header page pool in queue API
- ice: fix NULL pointer dereference in switchdev
Previous releases - regressions:
- core: fix icmp host relookup triggering ip_rt_bug
- ipv6:
- avoid possible NULL deref in modify_prefix_route()
- release expired exception dst cached in socket
- smc: fix LGR and link use-after-free issue
- hsr: avoid potential out-of-bound access in fill_frame_info()
- can: hi311x: fix potential use-after-free
- eth: ice: fix VLAN pruning in switchdev mode
Previous releases - always broken:
- netfilter:
- ipset: hold module reference while requesting a module
- nft_inner: incorrect percpu area handling under softirq
- can: j1939: fix skb reference counting
- eth:
- mlxsw: use correct key block on Spectrum-4
- mlx5: fix memory leak in mlx5hws_definer_calc_layout"
* tag 'net-6.13-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (76 commits)
net :mana :Request a V2 response version for MANA_QUERY_GF_STAT
net: avoid potential UAF in default_operstate()
vsock/test: verify socket options after setting them
vsock/test: fix parameter types in SO_VM_SOCKETS_* calls
vsock/test: fix failures due to wrong SO_RCVLOWAT parameter
net/mlx5e: Remove workaround to avoid syndrome for internal port
net/mlx5e: SD, Use correct mdev to build channel param
net/mlx5: E-Switch, Fix switching to switchdev mode in MPV
net/mlx5: E-Switch, Fix switching to switchdev mode with IB device disabled
net/mlx5: HWS: Properly set bwc queue locks lock classes
net/mlx5: HWS: Fix memory leak in mlx5hws_definer_calc_layout
bnxt_en: handle tpa_info in queue API implementation
bnxt_en: refactor bnxt_alloc_rx_rings() to call bnxt_alloc_rx_agg_bmap()
bnxt_en: refactor tpa_info alloc/free into helpers
geneve: do not assume mac header is set in geneve_xmit_skb()
mlxsw: spectrum_acl_flex_keys: Use correct key block on Spectrum-4
ethtool: Fix wrong mod state in case of verbose and no_mask bitset
ipmr: tune the ipmr_can_free_table() checks.
netfilter: nft_set_hash: skip duplicated elements pending gc run
netfilter: ipset: Hold module reference while requesting a module
...
This commit is contained in:
@@ -6,16 +6,17 @@ Bare UDP Tunnelling Module Documentation
|
||||
|
||||
There are various L3 encapsulation standards using UDP being discussed to
|
||||
leverage the UDP based load balancing capability of different networks.
|
||||
MPLSoUDP (__ https://tools.ietf.org/html/rfc7510) is one among them.
|
||||
MPLSoUDP (https://tools.ietf.org/html/rfc7510) is one among them.
|
||||
|
||||
The Bareudp tunnel module provides a generic L3 encapsulation support for
|
||||
tunnelling different L3 protocols like MPLS, IP, NSH etc. inside a UDP tunnel.
|
||||
|
||||
Special Handling
|
||||
----------------
|
||||
|
||||
The bareudp device supports special handling for MPLS & IP as they can have
|
||||
multiple ethertypes.
|
||||
MPLS procotcol can have ethertypes ETH_P_MPLS_UC (unicast) & ETH_P_MPLS_MC (multicast).
|
||||
The MPLS protocol can have ethertypes ETH_P_MPLS_UC (unicast) & ETH_P_MPLS_MC (multicast).
|
||||
IP protocol can have ethertypes ETH_P_IP (v4) & ETH_P_IPV6 (v6).
|
||||
This special handling can be enabled only for ethertypes ETH_P_IP & ETH_P_MPLS_UC
|
||||
with a flag called multiproto mode.
|
||||
@@ -52,7 +53,7 @@ be enabled explicitly with the "multiproto" flag.
|
||||
3) Device Usage
|
||||
|
||||
The bareudp device could be used along with OVS or flower filter in TC.
|
||||
The OVS or TC flower layer must set the tunnel information in SKB dst field before
|
||||
sending packet buffer to the bareudp device for transmission. On reception the
|
||||
bareudp device extracts and stores the tunnel information in SKB dst field before
|
||||
The OVS or TC flower layer must set the tunnel information in the SKB dst field before
|
||||
sending the packet buffer to the bareudp device for transmission. On reception, the
|
||||
bareUDP device extracts and stores the tunnel information in the SKB dst field before
|
||||
passing the packet buffer to the network stack.
|
||||
|
||||
@@ -16267,6 +16267,7 @@ F: Documentation/devicetree/bindings/net/
|
||||
F: Documentation/networking/net_cachelines/net_device.rst
|
||||
F: drivers/connector/
|
||||
F: drivers/net/
|
||||
F: drivers/ptp/
|
||||
F: include/dt-bindings/net/
|
||||
F: include/linux/cn_proc.h
|
||||
F: include/linux/etherdevice.h
|
||||
|
||||
@@ -1014,49 +1014,57 @@ static int c_can_handle_bus_err(struct net_device *dev,
|
||||
|
||||
/* propagate the error condition to the CAN stack */
|
||||
skb = alloc_can_err_skb(dev, &cf);
|
||||
if (unlikely(!skb))
|
||||
return 0;
|
||||
|
||||
/* check for 'last error code' which tells us the
|
||||
* type of the last error to occur on the CAN bus
|
||||
*/
|
||||
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
|
||||
if (likely(skb))
|
||||
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
|
||||
|
||||
switch (lec_type) {
|
||||
case LEC_STUFF_ERROR:
|
||||
netdev_dbg(dev, "stuff error\n");
|
||||
cf->data[2] |= CAN_ERR_PROT_STUFF;
|
||||
if (likely(skb))
|
||||
cf->data[2] |= CAN_ERR_PROT_STUFF;
|
||||
stats->rx_errors++;
|
||||
break;
|
||||
case LEC_FORM_ERROR:
|
||||
netdev_dbg(dev, "form error\n");
|
||||
cf->data[2] |= CAN_ERR_PROT_FORM;
|
||||
if (likely(skb))
|
||||
cf->data[2] |= CAN_ERR_PROT_FORM;
|
||||
stats->rx_errors++;
|
||||
break;
|
||||
case LEC_ACK_ERROR:
|
||||
netdev_dbg(dev, "ack error\n");
|
||||
cf->data[3] = CAN_ERR_PROT_LOC_ACK;
|
||||
if (likely(skb))
|
||||
cf->data[3] = CAN_ERR_PROT_LOC_ACK;
|
||||
stats->tx_errors++;
|
||||
break;
|
||||
case LEC_BIT1_ERROR:
|
||||
netdev_dbg(dev, "bit1 error\n");
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT1;
|
||||
if (likely(skb))
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT1;
|
||||
stats->tx_errors++;
|
||||
break;
|
||||
case LEC_BIT0_ERROR:
|
||||
netdev_dbg(dev, "bit0 error\n");
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT0;
|
||||
if (likely(skb))
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT0;
|
||||
stats->tx_errors++;
|
||||
break;
|
||||
case LEC_CRC_ERROR:
|
||||
netdev_dbg(dev, "CRC error\n");
|
||||
cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
|
||||
if (likely(skb))
|
||||
cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
|
||||
stats->rx_errors++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (unlikely(!skb))
|
||||
return 0;
|
||||
|
||||
netif_receive_skb(skb);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -468,7 +468,7 @@ static int can_set_termination(struct net_device *ndev, u16 term)
|
||||
else
|
||||
set = 0;
|
||||
|
||||
gpiod_set_value(priv->termination_gpio, set);
|
||||
gpiod_set_value_cansleep(priv->termination_gpio, set);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -390,36 +390,55 @@ static int ifi_canfd_handle_lec_err(struct net_device *ndev)
|
||||
return 0;
|
||||
|
||||
priv->can.can_stats.bus_error++;
|
||||
stats->rx_errors++;
|
||||
|
||||
/* Propagate the error condition to the CAN stack. */
|
||||
skb = alloc_can_err_skb(ndev, &cf);
|
||||
if (unlikely(!skb))
|
||||
return 0;
|
||||
|
||||
/* Read the error counter register and check for new errors. */
|
||||
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
|
||||
if (likely(skb))
|
||||
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
|
||||
|
||||
if (errctr & IFI_CANFD_ERROR_CTR_OVERLOAD_FIRST)
|
||||
cf->data[2] |= CAN_ERR_PROT_OVERLOAD;
|
||||
if (errctr & IFI_CANFD_ERROR_CTR_OVERLOAD_FIRST) {
|
||||
stats->rx_errors++;
|
||||
if (likely(skb))
|
||||
cf->data[2] |= CAN_ERR_PROT_OVERLOAD;
|
||||
}
|
||||
|
||||
if (errctr & IFI_CANFD_ERROR_CTR_ACK_ERROR_FIRST)
|
||||
cf->data[3] = CAN_ERR_PROT_LOC_ACK;
|
||||
if (errctr & IFI_CANFD_ERROR_CTR_ACK_ERROR_FIRST) {
|
||||
stats->tx_errors++;
|
||||
if (likely(skb))
|
||||
cf->data[3] = CAN_ERR_PROT_LOC_ACK;
|
||||
}
|
||||
|
||||
if (errctr & IFI_CANFD_ERROR_CTR_BIT0_ERROR_FIRST)
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT0;
|
||||
if (errctr & IFI_CANFD_ERROR_CTR_BIT0_ERROR_FIRST) {
|
||||
stats->tx_errors++;
|
||||
if (likely(skb))
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT0;
|
||||
}
|
||||
|
||||
if (errctr & IFI_CANFD_ERROR_CTR_BIT1_ERROR_FIRST)
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT1;
|
||||
if (errctr & IFI_CANFD_ERROR_CTR_BIT1_ERROR_FIRST) {
|
||||
stats->tx_errors++;
|
||||
if (likely(skb))
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT1;
|
||||
}
|
||||
|
||||
if (errctr & IFI_CANFD_ERROR_CTR_STUFF_ERROR_FIRST)
|
||||
cf->data[2] |= CAN_ERR_PROT_STUFF;
|
||||
if (errctr & IFI_CANFD_ERROR_CTR_STUFF_ERROR_FIRST) {
|
||||
stats->rx_errors++;
|
||||
if (likely(skb))
|
||||
cf->data[2] |= CAN_ERR_PROT_STUFF;
|
||||
}
|
||||
|
||||
if (errctr & IFI_CANFD_ERROR_CTR_CRC_ERROR_FIRST)
|
||||
cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
|
||||
if (errctr & IFI_CANFD_ERROR_CTR_CRC_ERROR_FIRST) {
|
||||
stats->rx_errors++;
|
||||
if (likely(skb))
|
||||
cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
|
||||
}
|
||||
|
||||
if (errctr & IFI_CANFD_ERROR_CTR_FORM_ERROR_FIRST)
|
||||
cf->data[2] |= CAN_ERR_PROT_FORM;
|
||||
if (errctr & IFI_CANFD_ERROR_CTR_FORM_ERROR_FIRST) {
|
||||
stats->rx_errors++;
|
||||
if (likely(skb))
|
||||
cf->data[2] |= CAN_ERR_PROT_FORM;
|
||||
}
|
||||
|
||||
/* Reset the error counter, ack the IRQ and re-enable the counter. */
|
||||
writel(IFI_CANFD_ERROR_CTR_ER_RESET, priv->base + IFI_CANFD_ERROR_CTR);
|
||||
@@ -427,6 +446,9 @@ static int ifi_canfd_handle_lec_err(struct net_device *ndev)
|
||||
priv->base + IFI_CANFD_INTERRUPT);
|
||||
writel(IFI_CANFD_ERROR_CTR_ER_ENABLE, priv->base + IFI_CANFD_ERROR_CTR);
|
||||
|
||||
if (unlikely(!skb))
|
||||
return 0;
|
||||
|
||||
netif_receive_skb(skb);
|
||||
|
||||
return 1;
|
||||
|
||||
@@ -695,47 +695,60 @@ static int m_can_handle_lec_err(struct net_device *dev,
|
||||
u32 timestamp = 0;
|
||||
|
||||
cdev->can.can_stats.bus_error++;
|
||||
stats->rx_errors++;
|
||||
|
||||
/* propagate the error condition to the CAN stack */
|
||||
skb = alloc_can_err_skb(dev, &cf);
|
||||
if (unlikely(!skb))
|
||||
return 0;
|
||||
|
||||
/* check for 'last error code' which tells us the
|
||||
* type of the last error to occur on the CAN bus
|
||||
*/
|
||||
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
|
||||
if (likely(skb))
|
||||
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
|
||||
|
||||
switch (lec_type) {
|
||||
case LEC_STUFF_ERROR:
|
||||
netdev_dbg(dev, "stuff error\n");
|
||||
cf->data[2] |= CAN_ERR_PROT_STUFF;
|
||||
stats->rx_errors++;
|
||||
if (likely(skb))
|
||||
cf->data[2] |= CAN_ERR_PROT_STUFF;
|
||||
break;
|
||||
case LEC_FORM_ERROR:
|
||||
netdev_dbg(dev, "form error\n");
|
||||
cf->data[2] |= CAN_ERR_PROT_FORM;
|
||||
stats->rx_errors++;
|
||||
if (likely(skb))
|
||||
cf->data[2] |= CAN_ERR_PROT_FORM;
|
||||
break;
|
||||
case LEC_ACK_ERROR:
|
||||
netdev_dbg(dev, "ack error\n");
|
||||
cf->data[3] = CAN_ERR_PROT_LOC_ACK;
|
||||
stats->tx_errors++;
|
||||
if (likely(skb))
|
||||
cf->data[3] = CAN_ERR_PROT_LOC_ACK;
|
||||
break;
|
||||
case LEC_BIT1_ERROR:
|
||||
netdev_dbg(dev, "bit1 error\n");
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT1;
|
||||
stats->tx_errors++;
|
||||
if (likely(skb))
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT1;
|
||||
break;
|
||||
case LEC_BIT0_ERROR:
|
||||
netdev_dbg(dev, "bit0 error\n");
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT0;
|
||||
stats->tx_errors++;
|
||||
if (likely(skb))
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT0;
|
||||
break;
|
||||
case LEC_CRC_ERROR:
|
||||
netdev_dbg(dev, "CRC error\n");
|
||||
cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
|
||||
stats->rx_errors++;
|
||||
if (likely(skb))
|
||||
cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (unlikely(!skb))
|
||||
return 0;
|
||||
|
||||
if (cdev->is_peripheral)
|
||||
timestamp = m_can_get_timestamp(cdev);
|
||||
|
||||
|
||||
@@ -416,8 +416,6 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
|
||||
int ret = 0;
|
||||
|
||||
skb = alloc_can_err_skb(dev, &cf);
|
||||
if (skb == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
txerr = priv->read_reg(priv, SJA1000_TXERR);
|
||||
rxerr = priv->read_reg(priv, SJA1000_RXERR);
|
||||
@@ -425,8 +423,11 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
|
||||
if (isrc & IRQ_DOI) {
|
||||
/* data overrun interrupt */
|
||||
netdev_dbg(dev, "data overrun interrupt\n");
|
||||
cf->can_id |= CAN_ERR_CRTL;
|
||||
cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
|
||||
if (skb) {
|
||||
cf->can_id |= CAN_ERR_CRTL;
|
||||
cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
|
||||
}
|
||||
|
||||
stats->rx_over_errors++;
|
||||
stats->rx_errors++;
|
||||
sja1000_write_cmdreg(priv, CMD_CDO); /* clear bit */
|
||||
@@ -452,7 +453,7 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
|
||||
else
|
||||
state = CAN_STATE_ERROR_ACTIVE;
|
||||
}
|
||||
if (state != CAN_STATE_BUS_OFF) {
|
||||
if (state != CAN_STATE_BUS_OFF && skb) {
|
||||
cf->can_id |= CAN_ERR_CNT;
|
||||
cf->data[6] = txerr;
|
||||
cf->data[7] = rxerr;
|
||||
@@ -460,33 +461,38 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
|
||||
if (isrc & IRQ_BEI) {
|
||||
/* bus error interrupt */
|
||||
priv->can.can_stats.bus_error++;
|
||||
stats->rx_errors++;
|
||||
|
||||
ecc = priv->read_reg(priv, SJA1000_ECC);
|
||||
if (skb) {
|
||||
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
|
||||
|
||||
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
|
||||
/* set error type */
|
||||
switch (ecc & ECC_MASK) {
|
||||
case ECC_BIT:
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT;
|
||||
break;
|
||||
case ECC_FORM:
|
||||
cf->data[2] |= CAN_ERR_PROT_FORM;
|
||||
break;
|
||||
case ECC_STUFF:
|
||||
cf->data[2] |= CAN_ERR_PROT_STUFF;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* set error type */
|
||||
switch (ecc & ECC_MASK) {
|
||||
case ECC_BIT:
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT;
|
||||
break;
|
||||
case ECC_FORM:
|
||||
cf->data[2] |= CAN_ERR_PROT_FORM;
|
||||
break;
|
||||
case ECC_STUFF:
|
||||
cf->data[2] |= CAN_ERR_PROT_STUFF;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
/* set error location */
|
||||
cf->data[3] = ecc & ECC_SEG;
|
||||
}
|
||||
|
||||
/* set error location */
|
||||
cf->data[3] = ecc & ECC_SEG;
|
||||
|
||||
/* Error occurred during transmission? */
|
||||
if ((ecc & ECC_DIR) == 0)
|
||||
cf->data[2] |= CAN_ERR_PROT_TX;
|
||||
if ((ecc & ECC_DIR) == 0) {
|
||||
stats->tx_errors++;
|
||||
if (skb)
|
||||
cf->data[2] |= CAN_ERR_PROT_TX;
|
||||
} else {
|
||||
stats->rx_errors++;
|
||||
}
|
||||
}
|
||||
if (isrc & IRQ_EPI) {
|
||||
/* error passive interrupt */
|
||||
@@ -502,8 +508,10 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
|
||||
netdev_dbg(dev, "arbitration lost interrupt\n");
|
||||
alc = priv->read_reg(priv, SJA1000_ALC);
|
||||
priv->can.can_stats.arbitration_lost++;
|
||||
cf->can_id |= CAN_ERR_LOSTARB;
|
||||
cf->data[0] = alc & 0x1f;
|
||||
if (skb) {
|
||||
cf->can_id |= CAN_ERR_LOSTARB;
|
||||
cf->data[0] = alc & 0x1f;
|
||||
}
|
||||
}
|
||||
|
||||
if (state != priv->can.state) {
|
||||
@@ -516,6 +524,9 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
|
||||
can_bus_off(dev);
|
||||
}
|
||||
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
netif_rx(skb);
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -663,27 +663,27 @@ static irqreturn_t hi3110_can_ist(int irq, void *dev_id)
|
||||
u8 rxerr, txerr;
|
||||
|
||||
skb = alloc_can_err_skb(net, &cf);
|
||||
if (!skb)
|
||||
break;
|
||||
|
||||
txerr = hi3110_read(spi, HI3110_READ_TEC);
|
||||
rxerr = hi3110_read(spi, HI3110_READ_REC);
|
||||
tx_state = txerr >= rxerr ? new_state : 0;
|
||||
rx_state = txerr <= rxerr ? new_state : 0;
|
||||
can_change_state(net, cf, tx_state, rx_state);
|
||||
netif_rx(skb);
|
||||
|
||||
if (new_state == CAN_STATE_BUS_OFF) {
|
||||
if (skb)
|
||||
netif_rx(skb);
|
||||
can_bus_off(net);
|
||||
if (priv->can.restart_ms == 0) {
|
||||
priv->force_quit = 1;
|
||||
hi3110_hw_sleep(spi);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
} else if (skb) {
|
||||
cf->can_id |= CAN_ERR_CNT;
|
||||
cf->data[6] = txerr;
|
||||
cf->data[7] = rxerr;
|
||||
netif_rx(skb);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -696,27 +696,38 @@ static irqreturn_t hi3110_can_ist(int irq, void *dev_id)
|
||||
/* Check for protocol errors */
|
||||
if (eflag & HI3110_ERR_PROTOCOL_MASK) {
|
||||
skb = alloc_can_err_skb(net, &cf);
|
||||
if (!skb)
|
||||
break;
|
||||
if (skb)
|
||||
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
|
||||
|
||||
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
|
||||
priv->can.can_stats.bus_error++;
|
||||
priv->net->stats.rx_errors++;
|
||||
if (eflag & HI3110_ERR_BITERR)
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT;
|
||||
else if (eflag & HI3110_ERR_FRMERR)
|
||||
cf->data[2] |= CAN_ERR_PROT_FORM;
|
||||
else if (eflag & HI3110_ERR_STUFERR)
|
||||
cf->data[2] |= CAN_ERR_PROT_STUFF;
|
||||
else if (eflag & HI3110_ERR_CRCERR)
|
||||
cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ;
|
||||
else if (eflag & HI3110_ERR_ACKERR)
|
||||
cf->data[3] |= CAN_ERR_PROT_LOC_ACK;
|
||||
if (eflag & HI3110_ERR_BITERR) {
|
||||
priv->net->stats.tx_errors++;
|
||||
if (skb)
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT;
|
||||
} else if (eflag & HI3110_ERR_FRMERR) {
|
||||
priv->net->stats.rx_errors++;
|
||||
if (skb)
|
||||
cf->data[2] |= CAN_ERR_PROT_FORM;
|
||||
} else if (eflag & HI3110_ERR_STUFERR) {
|
||||
priv->net->stats.rx_errors++;
|
||||
if (skb)
|
||||
cf->data[2] |= CAN_ERR_PROT_STUFF;
|
||||
} else if (eflag & HI3110_ERR_CRCERR) {
|
||||
priv->net->stats.rx_errors++;
|
||||
if (skb)
|
||||
cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ;
|
||||
} else if (eflag & HI3110_ERR_ACKERR) {
|
||||
priv->net->stats.tx_errors++;
|
||||
if (skb)
|
||||
cf->data[3] |= CAN_ERR_PROT_LOC_ACK;
|
||||
}
|
||||
|
||||
cf->data[6] = hi3110_read(spi, HI3110_READ_TEC);
|
||||
cf->data[7] = hi3110_read(spi, HI3110_READ_REC);
|
||||
netdev_dbg(priv->net, "Bus Error\n");
|
||||
netif_rx(skb);
|
||||
if (skb) {
|
||||
cf->data[6] = hi3110_read(spi, HI3110_READ_TEC);
|
||||
cf->data[7] = hi3110_read(spi, HI3110_READ_REC);
|
||||
netif_rx(skb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,11 @@ static inline bool mcp251xfd_tx_fifo_sta_empty(u32 fifo_sta)
|
||||
return fifo_sta & MCP251XFD_REG_FIFOSTA_TFERFFIF;
|
||||
}
|
||||
|
||||
static inline bool mcp251xfd_tx_fifo_sta_less_than_half_full(u32 fifo_sta)
|
||||
{
|
||||
return fifo_sta & MCP251XFD_REG_FIFOSTA_TFHRFHIF;
|
||||
}
|
||||
|
||||
static inline int
|
||||
mcp251xfd_tef_tail_get_from_chip(const struct mcp251xfd_priv *priv,
|
||||
u8 *tef_tail)
|
||||
@@ -147,7 +152,29 @@ mcp251xfd_get_tef_len(struct mcp251xfd_priv *priv, u8 *len_p)
|
||||
BUILD_BUG_ON(sizeof(tx_ring->obj_num) != sizeof(len));
|
||||
|
||||
len = (chip_tx_tail << shift) - (tail << shift);
|
||||
*len_p = len >> shift;
|
||||
len >>= shift;
|
||||
|
||||
/* According to mcp2518fd erratum DS80000789E 6. the FIFOCI
|
||||
* bits of a FIFOSTA register, here the TX-FIFO tail index
|
||||
* might be corrupted.
|
||||
*
|
||||
* However here it seems the bit indicating that the TX-FIFO
|
||||
* is empty (MCP251XFD_REG_FIFOSTA_TFERFFIF) is not correct
|
||||
* while the TX-FIFO tail index is.
|
||||
*
|
||||
* We assume the TX-FIFO is empty, i.e. all pending CAN frames
|
||||
* haven been send, if:
|
||||
* - Chip's head and tail index are equal (len == 0).
|
||||
* - The TX-FIFO is less than half full.
|
||||
* (The TX-FIFO empty case has already been checked at the
|
||||
* beginning of this function.)
|
||||
* - No free buffers in the TX ring.
|
||||
*/
|
||||
if (len == 0 && mcp251xfd_tx_fifo_sta_less_than_half_full(fifo_sta) &&
|
||||
mcp251xfd_get_tx_free(tx_ring) == 0)
|
||||
len = tx_ring->obj_num;
|
||||
|
||||
*len_p = len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -579,11 +579,9 @@ static int sun4i_can_err(struct net_device *dev, u8 isrc, u8 status)
|
||||
/* bus error interrupt */
|
||||
netdev_dbg(dev, "bus error interrupt\n");
|
||||
priv->can.can_stats.bus_error++;
|
||||
stats->rx_errors++;
|
||||
ecc = readl(priv->base + SUN4I_REG_STA_ADDR);
|
||||
|
||||
if (likely(skb)) {
|
||||
ecc = readl(priv->base + SUN4I_REG_STA_ADDR);
|
||||
|
||||
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
|
||||
|
||||
switch (ecc & SUN4I_STA_MASK_ERR) {
|
||||
@@ -601,9 +599,15 @@ static int sun4i_can_err(struct net_device *dev, u8 isrc, u8 status)
|
||||
>> 16;
|
||||
break;
|
||||
}
|
||||
/* error occurred during transmission? */
|
||||
if ((ecc & SUN4I_STA_ERR_DIR) == 0)
|
||||
}
|
||||
|
||||
/* error occurred during transmission? */
|
||||
if ((ecc & SUN4I_STA_ERR_DIR) == 0) {
|
||||
if (likely(skb))
|
||||
cf->data[2] |= CAN_ERR_PROT_TX;
|
||||
stats->tx_errors++;
|
||||
} else {
|
||||
stats->rx_errors++;
|
||||
}
|
||||
}
|
||||
if (isrc & SUN4I_INT_ERR_PASSIVE) {
|
||||
@@ -629,10 +633,10 @@ static int sun4i_can_err(struct net_device *dev, u8 isrc, u8 status)
|
||||
tx_state = txerr >= rxerr ? state : 0;
|
||||
rx_state = txerr <= rxerr ? state : 0;
|
||||
|
||||
if (likely(skb))
|
||||
can_change_state(dev, cf, tx_state, rx_state);
|
||||
else
|
||||
priv->can.state = state;
|
||||
/* The skb allocation might fail, but can_change_state()
|
||||
* handles cf == NULL.
|
||||
*/
|
||||
can_change_state(dev, cf, tx_state, rx_state);
|
||||
if (state == CAN_STATE_BUS_OFF)
|
||||
can_bus_off(dev);
|
||||
}
|
||||
|
||||
@@ -335,15 +335,14 @@ static void ems_usb_rx_err(struct ems_usb *dev, struct ems_cpc_msg *msg)
|
||||
struct net_device_stats *stats = &dev->netdev->stats;
|
||||
|
||||
skb = alloc_can_err_skb(dev->netdev, &cf);
|
||||
if (skb == NULL)
|
||||
return;
|
||||
|
||||
if (msg->type == CPC_MSG_TYPE_CAN_STATE) {
|
||||
u8 state = msg->msg.can_state;
|
||||
|
||||
if (state & SJA1000_SR_BS) {
|
||||
dev->can.state = CAN_STATE_BUS_OFF;
|
||||
cf->can_id |= CAN_ERR_BUSOFF;
|
||||
if (skb)
|
||||
cf->can_id |= CAN_ERR_BUSOFF;
|
||||
|
||||
dev->can.can_stats.bus_off++;
|
||||
can_bus_off(dev->netdev);
|
||||
@@ -361,44 +360,53 @@ static void ems_usb_rx_err(struct ems_usb *dev, struct ems_cpc_msg *msg)
|
||||
|
||||
/* bus error interrupt */
|
||||
dev->can.can_stats.bus_error++;
|
||||
stats->rx_errors++;
|
||||
|
||||
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
|
||||
if (skb) {
|
||||
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
|
||||
|
||||
switch (ecc & SJA1000_ECC_MASK) {
|
||||
case SJA1000_ECC_BIT:
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT;
|
||||
break;
|
||||
case SJA1000_ECC_FORM:
|
||||
cf->data[2] |= CAN_ERR_PROT_FORM;
|
||||
break;
|
||||
case SJA1000_ECC_STUFF:
|
||||
cf->data[2] |= CAN_ERR_PROT_STUFF;
|
||||
break;
|
||||
default:
|
||||
cf->data[3] = ecc & SJA1000_ECC_SEG;
|
||||
break;
|
||||
switch (ecc & SJA1000_ECC_MASK) {
|
||||
case SJA1000_ECC_BIT:
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT;
|
||||
break;
|
||||
case SJA1000_ECC_FORM:
|
||||
cf->data[2] |= CAN_ERR_PROT_FORM;
|
||||
break;
|
||||
case SJA1000_ECC_STUFF:
|
||||
cf->data[2] |= CAN_ERR_PROT_STUFF;
|
||||
break;
|
||||
default:
|
||||
cf->data[3] = ecc & SJA1000_ECC_SEG;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Error occurred during transmission? */
|
||||
if ((ecc & SJA1000_ECC_DIR) == 0)
|
||||
cf->data[2] |= CAN_ERR_PROT_TX;
|
||||
if ((ecc & SJA1000_ECC_DIR) == 0) {
|
||||
stats->tx_errors++;
|
||||
if (skb)
|
||||
cf->data[2] |= CAN_ERR_PROT_TX;
|
||||
} else {
|
||||
stats->rx_errors++;
|
||||
}
|
||||
|
||||
if (dev->can.state == CAN_STATE_ERROR_WARNING ||
|
||||
dev->can.state == CAN_STATE_ERROR_PASSIVE) {
|
||||
if (skb && (dev->can.state == CAN_STATE_ERROR_WARNING ||
|
||||
dev->can.state == CAN_STATE_ERROR_PASSIVE)) {
|
||||
cf->can_id |= CAN_ERR_CRTL;
|
||||
cf->data[1] = (txerr > rxerr) ?
|
||||
CAN_ERR_CRTL_TX_PASSIVE : CAN_ERR_CRTL_RX_PASSIVE;
|
||||
}
|
||||
} else if (msg->type == CPC_MSG_TYPE_OVERRUN) {
|
||||
cf->can_id |= CAN_ERR_CRTL;
|
||||
cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
|
||||
if (skb) {
|
||||
cf->can_id |= CAN_ERR_CRTL;
|
||||
cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
|
||||
}
|
||||
|
||||
stats->rx_over_errors++;
|
||||
stats->rx_errors++;
|
||||
}
|
||||
|
||||
netif_rx(skb);
|
||||
if (skb)
|
||||
netif_rx(skb);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -526,7 +526,6 @@ static void f81604_handle_can_bus_errors(struct f81604_port_priv *priv,
|
||||
netdev_dbg(netdev, "bus error interrupt\n");
|
||||
|
||||
priv->can.can_stats.bus_error++;
|
||||
stats->rx_errors++;
|
||||
|
||||
if (skb) {
|
||||
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
|
||||
@@ -548,10 +547,15 @@ static void f81604_handle_can_bus_errors(struct f81604_port_priv *priv,
|
||||
|
||||
/* set error location */
|
||||
cf->data[3] = data->ecc & F81604_SJA1000_ECC_SEG;
|
||||
}
|
||||
|
||||
/* Error occurred during transmission? */
|
||||
if ((data->ecc & F81604_SJA1000_ECC_DIR) == 0)
|
||||
/* Error occurred during transmission? */
|
||||
if ((data->ecc & F81604_SJA1000_ECC_DIR) == 0) {
|
||||
stats->tx_errors++;
|
||||
if (skb)
|
||||
cf->data[2] |= CAN_ERR_PROT_TX;
|
||||
} else {
|
||||
stats->rx_errors++;
|
||||
}
|
||||
|
||||
set_bit(F81604_CLEAR_ECC, &priv->clear_flags);
|
||||
|
||||
@@ -43,9 +43,6 @@
|
||||
#define USB_XYLANTA_SAINT3_VENDOR_ID 0x16d0
|
||||
#define USB_XYLANTA_SAINT3_PRODUCT_ID 0x0f30
|
||||
|
||||
#define GS_USB_ENDPOINT_IN 1
|
||||
#define GS_USB_ENDPOINT_OUT 2
|
||||
|
||||
/* Timestamp 32 bit timer runs at 1 MHz (1 µs tick). Worker accounts
|
||||
* for timer overflow (will be after ~71 minutes)
|
||||
*/
|
||||
@@ -336,6 +333,9 @@ struct gs_usb {
|
||||
|
||||
unsigned int hf_size_rx;
|
||||
u8 active_channels;
|
||||
|
||||
unsigned int pipe_in;
|
||||
unsigned int pipe_out;
|
||||
};
|
||||
|
||||
/* 'allocate' a tx context.
|
||||
@@ -687,7 +687,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
|
||||
|
||||
resubmit_urb:
|
||||
usb_fill_bulk_urb(urb, parent->udev,
|
||||
usb_rcvbulkpipe(parent->udev, GS_USB_ENDPOINT_IN),
|
||||
parent->pipe_in,
|
||||
hf, dev->parent->hf_size_rx,
|
||||
gs_usb_receive_bulk_callback, parent);
|
||||
|
||||
@@ -819,7 +819,7 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb,
|
||||
}
|
||||
|
||||
usb_fill_bulk_urb(urb, dev->udev,
|
||||
usb_sndbulkpipe(dev->udev, GS_USB_ENDPOINT_OUT),
|
||||
dev->parent->pipe_out,
|
||||
hf, dev->hf_size_tx,
|
||||
gs_usb_xmit_callback, txc);
|
||||
|
||||
@@ -925,8 +925,7 @@ static int gs_can_open(struct net_device *netdev)
|
||||
/* fill, anchor, and submit rx urb */
|
||||
usb_fill_bulk_urb(urb,
|
||||
dev->udev,
|
||||
usb_rcvbulkpipe(dev->udev,
|
||||
GS_USB_ENDPOINT_IN),
|
||||
dev->parent->pipe_in,
|
||||
buf,
|
||||
dev->parent->hf_size_rx,
|
||||
gs_usb_receive_bulk_callback, parent);
|
||||
@@ -1413,6 +1412,7 @@ static int gs_usb_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
struct usb_device *udev = interface_to_usbdev(intf);
|
||||
struct usb_endpoint_descriptor *ep_in, *ep_out;
|
||||
struct gs_host_frame *hf;
|
||||
struct gs_usb *parent;
|
||||
struct gs_host_config hconf = {
|
||||
@@ -1422,6 +1422,13 @@ static int gs_usb_probe(struct usb_interface *intf,
|
||||
unsigned int icount, i;
|
||||
int rc;
|
||||
|
||||
rc = usb_find_common_endpoints(intf->cur_altsetting,
|
||||
&ep_in, &ep_out, NULL, NULL);
|
||||
if (rc) {
|
||||
dev_err(&intf->dev, "Required endpoints not found\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* send host config */
|
||||
rc = usb_control_msg_send(udev, 0,
|
||||
GS_USB_BREQ_HOST_FORMAT,
|
||||
@@ -1466,6 +1473,10 @@ static int gs_usb_probe(struct usb_interface *intf,
|
||||
usb_set_intfdata(intf, parent);
|
||||
parent->udev = udev;
|
||||
|
||||
/* store the detected endpoints */
|
||||
parent->pipe_in = usb_rcvbulkpipe(parent->udev, ep_in->bEndpointAddress);
|
||||
parent->pipe_out = usb_sndbulkpipe(parent->udev, ep_out->bEndpointAddress);
|
||||
|
||||
for (i = 0; i < icount; i++) {
|
||||
unsigned int hf_size_rx = 0;
|
||||
|
||||
|
||||
@@ -172,13 +172,12 @@ static void vxcan_setup(struct net_device *dev)
|
||||
/* forward declaration for rtnl_create_link() */
|
||||
static struct rtnl_link_ops vxcan_link_ops;
|
||||
|
||||
static int vxcan_newlink(struct net *net, struct net_device *dev,
|
||||
static int vxcan_newlink(struct net *peer_net, struct net_device *dev,
|
||||
struct nlattr *tb[], struct nlattr *data[],
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct vxcan_priv *priv;
|
||||
struct net_device *peer;
|
||||
struct net *peer_net;
|
||||
|
||||
struct nlattr *peer_tb[IFLA_MAX + 1], **tbp = tb;
|
||||
char ifname[IFNAMSIZ];
|
||||
@@ -203,20 +202,15 @@ static int vxcan_newlink(struct net *net, struct net_device *dev,
|
||||
name_assign_type = NET_NAME_ENUM;
|
||||
}
|
||||
|
||||
peer_net = rtnl_link_get_net(net, tbp);
|
||||
peer = rtnl_create_link(peer_net, ifname, name_assign_type,
|
||||
&vxcan_link_ops, tbp, extack);
|
||||
if (IS_ERR(peer)) {
|
||||
put_net(peer_net);
|
||||
if (IS_ERR(peer))
|
||||
return PTR_ERR(peer);
|
||||
}
|
||||
|
||||
if (ifmp && dev->ifindex)
|
||||
peer->ifindex = ifmp->ifi_index;
|
||||
|
||||
err = register_netdevice(peer);
|
||||
put_net(peer_net);
|
||||
peer_net = NULL;
|
||||
if (err < 0) {
|
||||
free_netdev(peer);
|
||||
return err;
|
||||
|
||||
@@ -3421,15 +3421,11 @@ static void bnxt_free_one_rx_agg_ring(struct bnxt *bp, struct bnxt_rx_ring_info
|
||||
}
|
||||
}
|
||||
|
||||
static void bnxt_free_one_rx_ring_skbs(struct bnxt *bp, int ring_nr)
|
||||
static void bnxt_free_one_tpa_info_data(struct bnxt *bp,
|
||||
struct bnxt_rx_ring_info *rxr)
|
||||
{
|
||||
struct bnxt_rx_ring_info *rxr = &bp->rx_ring[ring_nr];
|
||||
struct bnxt_tpa_idx_map *map;
|
||||
int i;
|
||||
|
||||
if (!rxr->rx_tpa)
|
||||
goto skip_rx_tpa_free;
|
||||
|
||||
for (i = 0; i < bp->max_tpa; i++) {
|
||||
struct bnxt_tpa_info *tpa_info = &rxr->rx_tpa[i];
|
||||
u8 *data = tpa_info->data;
|
||||
@@ -3440,6 +3436,17 @@ static void bnxt_free_one_rx_ring_skbs(struct bnxt *bp, int ring_nr)
|
||||
tpa_info->data = NULL;
|
||||
page_pool_free_va(rxr->head_pool, data, false);
|
||||
}
|
||||
}
|
||||
|
||||
static void bnxt_free_one_rx_ring_skbs(struct bnxt *bp,
|
||||
struct bnxt_rx_ring_info *rxr)
|
||||
{
|
||||
struct bnxt_tpa_idx_map *map;
|
||||
|
||||
if (!rxr->rx_tpa)
|
||||
goto skip_rx_tpa_free;
|
||||
|
||||
bnxt_free_one_tpa_info_data(bp, rxr);
|
||||
|
||||
skip_rx_tpa_free:
|
||||
if (!rxr->rx_buf_ring)
|
||||
@@ -3467,7 +3474,7 @@ static void bnxt_free_rx_skbs(struct bnxt *bp)
|
||||
return;
|
||||
|
||||
for (i = 0; i < bp->rx_nr_rings; i++)
|
||||
bnxt_free_one_rx_ring_skbs(bp, i);
|
||||
bnxt_free_one_rx_ring_skbs(bp, &bp->rx_ring[i]);
|
||||
}
|
||||
|
||||
static void bnxt_free_skbs(struct bnxt *bp)
|
||||
@@ -3608,29 +3615,64 @@ static int bnxt_alloc_ring(struct bnxt *bp, struct bnxt_ring_mem_info *rmem)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bnxt_free_one_tpa_info(struct bnxt *bp,
|
||||
struct bnxt_rx_ring_info *rxr)
|
||||
{
|
||||
int i;
|
||||
|
||||
kfree(rxr->rx_tpa_idx_map);
|
||||
rxr->rx_tpa_idx_map = NULL;
|
||||
if (rxr->rx_tpa) {
|
||||
for (i = 0; i < bp->max_tpa; i++) {
|
||||
kfree(rxr->rx_tpa[i].agg_arr);
|
||||
rxr->rx_tpa[i].agg_arr = NULL;
|
||||
}
|
||||
}
|
||||
kfree(rxr->rx_tpa);
|
||||
rxr->rx_tpa = NULL;
|
||||
}
|
||||
|
||||
static void bnxt_free_tpa_info(struct bnxt *bp)
|
||||
{
|
||||
int i, j;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < bp->rx_nr_rings; i++) {
|
||||
struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i];
|
||||
|
||||
kfree(rxr->rx_tpa_idx_map);
|
||||
rxr->rx_tpa_idx_map = NULL;
|
||||
if (rxr->rx_tpa) {
|
||||
for (j = 0; j < bp->max_tpa; j++) {
|
||||
kfree(rxr->rx_tpa[j].agg_arr);
|
||||
rxr->rx_tpa[j].agg_arr = NULL;
|
||||
}
|
||||
}
|
||||
kfree(rxr->rx_tpa);
|
||||
rxr->rx_tpa = NULL;
|
||||
bnxt_free_one_tpa_info(bp, rxr);
|
||||
}
|
||||
}
|
||||
|
||||
static int bnxt_alloc_one_tpa_info(struct bnxt *bp,
|
||||
struct bnxt_rx_ring_info *rxr)
|
||||
{
|
||||
struct rx_agg_cmp *agg;
|
||||
int i;
|
||||
|
||||
rxr->rx_tpa = kcalloc(bp->max_tpa, sizeof(struct bnxt_tpa_info),
|
||||
GFP_KERNEL);
|
||||
if (!rxr->rx_tpa)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!(bp->flags & BNXT_FLAG_CHIP_P5_PLUS))
|
||||
return 0;
|
||||
for (i = 0; i < bp->max_tpa; i++) {
|
||||
agg = kcalloc(MAX_SKB_FRAGS, sizeof(*agg), GFP_KERNEL);
|
||||
if (!agg)
|
||||
return -ENOMEM;
|
||||
rxr->rx_tpa[i].agg_arr = agg;
|
||||
}
|
||||
rxr->rx_tpa_idx_map = kzalloc(sizeof(*rxr->rx_tpa_idx_map),
|
||||
GFP_KERNEL);
|
||||
if (!rxr->rx_tpa_idx_map)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bnxt_alloc_tpa_info(struct bnxt *bp)
|
||||
{
|
||||
int i, j;
|
||||
int i, rc;
|
||||
|
||||
bp->max_tpa = MAX_TPA;
|
||||
if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) {
|
||||
@@ -3641,25 +3683,10 @@ static int bnxt_alloc_tpa_info(struct bnxt *bp)
|
||||
|
||||
for (i = 0; i < bp->rx_nr_rings; i++) {
|
||||
struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i];
|
||||
struct rx_agg_cmp *agg;
|
||||
|
||||
rxr->rx_tpa = kcalloc(bp->max_tpa, sizeof(struct bnxt_tpa_info),
|
||||
GFP_KERNEL);
|
||||
if (!rxr->rx_tpa)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!(bp->flags & BNXT_FLAG_CHIP_P5_PLUS))
|
||||
continue;
|
||||
for (j = 0; j < bp->max_tpa; j++) {
|
||||
agg = kcalloc(MAX_SKB_FRAGS, sizeof(*agg), GFP_KERNEL);
|
||||
if (!agg)
|
||||
return -ENOMEM;
|
||||
rxr->rx_tpa[j].agg_arr = agg;
|
||||
}
|
||||
rxr->rx_tpa_idx_map = kzalloc(sizeof(*rxr->rx_tpa_idx_map),
|
||||
GFP_KERNEL);
|
||||
if (!rxr->rx_tpa_idx_map)
|
||||
return -ENOMEM;
|
||||
rc = bnxt_alloc_one_tpa_info(bp, rxr);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -3683,7 +3710,7 @@ static void bnxt_free_rx_rings(struct bnxt *bp)
|
||||
xdp_rxq_info_unreg(&rxr->xdp_rxq);
|
||||
|
||||
page_pool_destroy(rxr->page_pool);
|
||||
if (rxr->page_pool != rxr->head_pool)
|
||||
if (bnxt_separate_head_pool())
|
||||
page_pool_destroy(rxr->head_pool);
|
||||
rxr->page_pool = rxr->head_pool = NULL;
|
||||
|
||||
@@ -3737,6 +3764,19 @@ err_destroy_pp:
|
||||
return PTR_ERR(pool);
|
||||
}
|
||||
|
||||
static int bnxt_alloc_rx_agg_bmap(struct bnxt *bp, struct bnxt_rx_ring_info *rxr)
|
||||
{
|
||||
u16 mem_size;
|
||||
|
||||
rxr->rx_agg_bmap_size = bp->rx_agg_ring_mask + 1;
|
||||
mem_size = rxr->rx_agg_bmap_size / 8;
|
||||
rxr->rx_agg_bmap = kzalloc(mem_size, GFP_KERNEL);
|
||||
if (!rxr->rx_agg_bmap)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bnxt_alloc_rx_rings(struct bnxt *bp)
|
||||
{
|
||||
int numa_node = dev_to_node(&bp->pdev->dev);
|
||||
@@ -3781,19 +3821,15 @@ static int bnxt_alloc_rx_rings(struct bnxt *bp)
|
||||
|
||||
ring->grp_idx = i;
|
||||
if (agg_rings) {
|
||||
u16 mem_size;
|
||||
|
||||
ring = &rxr->rx_agg_ring_struct;
|
||||
rc = bnxt_alloc_ring(bp, &ring->ring_mem);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
ring->grp_idx = i;
|
||||
rxr->rx_agg_bmap_size = bp->rx_agg_ring_mask + 1;
|
||||
mem_size = rxr->rx_agg_bmap_size / 8;
|
||||
rxr->rx_agg_bmap = kzalloc(mem_size, GFP_KERNEL);
|
||||
if (!rxr->rx_agg_bmap)
|
||||
return -ENOMEM;
|
||||
rc = bnxt_alloc_rx_agg_bmap(bp, rxr);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
if (bp->flags & BNXT_FLAG_TPA)
|
||||
@@ -4268,10 +4304,31 @@ static void bnxt_alloc_one_rx_ring_page(struct bnxt *bp,
|
||||
rxr->rx_agg_prod = prod;
|
||||
}
|
||||
|
||||
static int bnxt_alloc_one_tpa_info_data(struct bnxt *bp,
|
||||
struct bnxt_rx_ring_info *rxr)
|
||||
{
|
||||
dma_addr_t mapping;
|
||||
u8 *data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < bp->max_tpa; i++) {
|
||||
data = __bnxt_alloc_rx_frag(bp, &mapping, rxr,
|
||||
GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
rxr->rx_tpa[i].data = data;
|
||||
rxr->rx_tpa[i].data_ptr = data + bp->rx_offset;
|
||||
rxr->rx_tpa[i].mapping = mapping;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bnxt_alloc_one_rx_ring(struct bnxt *bp, int ring_nr)
|
||||
{
|
||||
struct bnxt_rx_ring_info *rxr = &bp->rx_ring[ring_nr];
|
||||
int i;
|
||||
int rc;
|
||||
|
||||
bnxt_alloc_one_rx_ring_skb(bp, rxr, ring_nr);
|
||||
|
||||
@@ -4281,19 +4338,9 @@ static int bnxt_alloc_one_rx_ring(struct bnxt *bp, int ring_nr)
|
||||
bnxt_alloc_one_rx_ring_page(bp, rxr, ring_nr);
|
||||
|
||||
if (rxr->rx_tpa) {
|
||||
dma_addr_t mapping;
|
||||
u8 *data;
|
||||
|
||||
for (i = 0; i < bp->max_tpa; i++) {
|
||||
data = __bnxt_alloc_rx_frag(bp, &mapping, rxr,
|
||||
GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
rxr->rx_tpa[i].data = data;
|
||||
rxr->rx_tpa[i].data_ptr = data + bp->rx_offset;
|
||||
rxr->rx_tpa[i].mapping = mapping;
|
||||
}
|
||||
rc = bnxt_alloc_one_tpa_info_data(bp, rxr);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -13663,7 +13710,7 @@ static void bnxt_rx_ring_reset(struct bnxt *bp)
|
||||
bnxt_reset_task(bp, true);
|
||||
break;
|
||||
}
|
||||
bnxt_free_one_rx_ring_skbs(bp, i);
|
||||
bnxt_free_one_rx_ring_skbs(bp, rxr);
|
||||
rxr->rx_prod = 0;
|
||||
rxr->rx_agg_prod = 0;
|
||||
rxr->rx_sw_agg_prod = 0;
|
||||
@@ -15293,19 +15340,6 @@ static const struct netdev_stat_ops bnxt_stat_ops = {
|
||||
.get_base_stats = bnxt_get_base_stats,
|
||||
};
|
||||
|
||||
static int bnxt_alloc_rx_agg_bmap(struct bnxt *bp, struct bnxt_rx_ring_info *rxr)
|
||||
{
|
||||
u16 mem_size;
|
||||
|
||||
rxr->rx_agg_bmap_size = bp->rx_agg_ring_mask + 1;
|
||||
mem_size = rxr->rx_agg_bmap_size / 8;
|
||||
rxr->rx_agg_bmap = kzalloc(mem_size, GFP_KERNEL);
|
||||
if (!rxr->rx_agg_bmap)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bnxt_queue_mem_alloc(struct net_device *dev, void *qmem, int idx)
|
||||
{
|
||||
struct bnxt_rx_ring_info *rxr, *clone;
|
||||
@@ -15354,15 +15388,25 @@ static int bnxt_queue_mem_alloc(struct net_device *dev, void *qmem, int idx)
|
||||
goto err_free_rx_agg_ring;
|
||||
}
|
||||
|
||||
if (bp->flags & BNXT_FLAG_TPA) {
|
||||
rc = bnxt_alloc_one_tpa_info(bp, clone);
|
||||
if (rc)
|
||||
goto err_free_tpa_info;
|
||||
}
|
||||
|
||||
bnxt_init_one_rx_ring_rxbd(bp, clone);
|
||||
bnxt_init_one_rx_agg_ring_rxbd(bp, clone);
|
||||
|
||||
bnxt_alloc_one_rx_ring_skb(bp, clone, idx);
|
||||
if (bp->flags & BNXT_FLAG_AGG_RINGS)
|
||||
bnxt_alloc_one_rx_ring_page(bp, clone, idx);
|
||||
if (bp->flags & BNXT_FLAG_TPA)
|
||||
bnxt_alloc_one_tpa_info_data(bp, clone);
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_tpa_info:
|
||||
bnxt_free_one_tpa_info(bp, clone);
|
||||
err_free_rx_agg_ring:
|
||||
bnxt_free_ring(bp, &clone->rx_agg_ring_struct.ring_mem);
|
||||
err_free_rx_ring:
|
||||
@@ -15370,9 +15414,11 @@ err_free_rx_ring:
|
||||
err_rxq_info_unreg:
|
||||
xdp_rxq_info_unreg(&clone->xdp_rxq);
|
||||
err_page_pool_destroy:
|
||||
clone->page_pool->p.napi = NULL;
|
||||
page_pool_destroy(clone->page_pool);
|
||||
if (bnxt_separate_head_pool())
|
||||
page_pool_destroy(clone->head_pool);
|
||||
clone->page_pool = NULL;
|
||||
clone->head_pool = NULL;
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -15382,13 +15428,15 @@ static void bnxt_queue_mem_free(struct net_device *dev, void *qmem)
|
||||
struct bnxt *bp = netdev_priv(dev);
|
||||
struct bnxt_ring_struct *ring;
|
||||
|
||||
bnxt_free_one_rx_ring(bp, rxr);
|
||||
bnxt_free_one_rx_agg_ring(bp, rxr);
|
||||
bnxt_free_one_rx_ring_skbs(bp, rxr);
|
||||
|
||||
xdp_rxq_info_unreg(&rxr->xdp_rxq);
|
||||
|
||||
page_pool_destroy(rxr->page_pool);
|
||||
if (bnxt_separate_head_pool())
|
||||
page_pool_destroy(rxr->head_pool);
|
||||
rxr->page_pool = NULL;
|
||||
rxr->head_pool = NULL;
|
||||
|
||||
ring = &rxr->rx_ring_struct;
|
||||
bnxt_free_ring(bp, &ring->ring_mem);
|
||||
@@ -15470,7 +15518,10 @@ static int bnxt_queue_start(struct net_device *dev, void *qmem, int idx)
|
||||
rxr->rx_agg_prod = clone->rx_agg_prod;
|
||||
rxr->rx_sw_agg_prod = clone->rx_sw_agg_prod;
|
||||
rxr->rx_next_cons = clone->rx_next_cons;
|
||||
rxr->rx_tpa = clone->rx_tpa;
|
||||
rxr->rx_tpa_idx_map = clone->rx_tpa_idx_map;
|
||||
rxr->page_pool = clone->page_pool;
|
||||
rxr->head_pool = clone->head_pool;
|
||||
rxr->xdp_rxq = clone->xdp_rxq;
|
||||
|
||||
bnxt_copy_rx_ring(bp, rxr, clone);
|
||||
@@ -15529,6 +15580,8 @@ static int bnxt_queue_stop(struct net_device *dev, void *qmem, int idx)
|
||||
bnxt_hwrm_rx_agg_ring_free(bp, rxr, false);
|
||||
rxr->rx_next_cons = 0;
|
||||
page_pool_disable_direct_recycling(rxr->page_pool);
|
||||
if (bnxt_separate_head_pool())
|
||||
page_pool_disable_direct_recycling(rxr->head_pool);
|
||||
|
||||
memcpy(qmem, rxr, sizeof(*rxr));
|
||||
bnxt_init_rx_ring_struct(bp, qmem);
|
||||
|
||||
@@ -1187,10 +1187,14 @@ static int bnxt_grxclsrule(struct bnxt *bp, struct ethtool_rxnfc *cmd)
|
||||
}
|
||||
}
|
||||
|
||||
if (fltr->base.flags & BNXT_ACT_DROP)
|
||||
if (fltr->base.flags & BNXT_ACT_DROP) {
|
||||
fs->ring_cookie = RX_CLS_FLOW_DISC;
|
||||
else
|
||||
} else if (fltr->base.flags & BNXT_ACT_RSS_CTX) {
|
||||
fs->flow_type |= FLOW_RSS;
|
||||
cmd->rss_context = fltr->base.fw_vnic_id;
|
||||
} else {
|
||||
fs->ring_cookie = fltr->base.rxq;
|
||||
}
|
||||
rc = 0;
|
||||
|
||||
fltr_err:
|
||||
|
||||
@@ -29,6 +29,9 @@ EXPORT_SYMBOL_GPL(enetc_port_mac_wr);
|
||||
static void enetc_change_preemptible_tcs(struct enetc_ndev_priv *priv,
|
||||
u8 preemptible_tcs)
|
||||
{
|
||||
if (!(priv->si->hw_features & ENETC_SI_F_QBU))
|
||||
return;
|
||||
|
||||
priv->preemptible_tcs = preemptible_tcs;
|
||||
enetc_mm_commit_preemptible_tcs(priv);
|
||||
}
|
||||
@@ -1756,15 +1759,6 @@ void enetc_get_si_caps(struct enetc_si *si)
|
||||
rss = enetc_rd(hw, ENETC_SIRSSCAPR);
|
||||
si->num_rss = ENETC_SIRSSCAPR_GET_NUM_RSS(rss);
|
||||
}
|
||||
|
||||
if (val & ENETC_SIPCAPR0_QBV)
|
||||
si->hw_features |= ENETC_SI_F_QBV;
|
||||
|
||||
if (val & ENETC_SIPCAPR0_QBU)
|
||||
si->hw_features |= ENETC_SI_F_QBU;
|
||||
|
||||
if (val & ENETC_SIPCAPR0_PSFP)
|
||||
si->hw_features |= ENETC_SI_F_PSFP;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(enetc_get_si_caps);
|
||||
|
||||
|
||||
@@ -23,10 +23,7 @@
|
||||
#define ENETC_SICTR0 0x18
|
||||
#define ENETC_SICTR1 0x1c
|
||||
#define ENETC_SIPCAPR0 0x20
|
||||
#define ENETC_SIPCAPR0_PSFP BIT(9)
|
||||
#define ENETC_SIPCAPR0_RSS BIT(8)
|
||||
#define ENETC_SIPCAPR0_QBV BIT(4)
|
||||
#define ENETC_SIPCAPR0_QBU BIT(3)
|
||||
#define ENETC_SIPCAPR0_RFS BIT(2)
|
||||
#define ENETC_SIPCAPR1 0x24
|
||||
#define ENETC_SITGTGR 0x30
|
||||
@@ -194,6 +191,9 @@ enum enetc_bdr_type {TX, RX};
|
||||
#define ENETC_PCAPR0 0x0900
|
||||
#define ENETC_PCAPR0_RXBDR(val) ((val) >> 24)
|
||||
#define ENETC_PCAPR0_TXBDR(val) (((val) >> 16) & 0xff)
|
||||
#define ENETC_PCAPR0_PSFP BIT(9)
|
||||
#define ENETC_PCAPR0_QBV BIT(4)
|
||||
#define ENETC_PCAPR0_QBU BIT(3)
|
||||
#define ENETC_PCAPR1 0x0904
|
||||
#define ENETC_PSICFGR0(n) (0x0940 + (n) * 0xc) /* n = SI index */
|
||||
#define ENETC_PSICFGR0_SET_TXBDR(val) ((val) & 0xff)
|
||||
|
||||
@@ -409,6 +409,23 @@ static void enetc_port_assign_rfs_entries(struct enetc_si *si)
|
||||
enetc_port_wr(hw, ENETC_PRFSMR, ENETC_PRFSMR_RFSE);
|
||||
}
|
||||
|
||||
static void enetc_port_get_caps(struct enetc_si *si)
|
||||
{
|
||||
struct enetc_hw *hw = &si->hw;
|
||||
u32 val;
|
||||
|
||||
val = enetc_port_rd(hw, ENETC_PCAPR0);
|
||||
|
||||
if (val & ENETC_PCAPR0_QBV)
|
||||
si->hw_features |= ENETC_SI_F_QBV;
|
||||
|
||||
if (val & ENETC_PCAPR0_QBU)
|
||||
si->hw_features |= ENETC_SI_F_QBU;
|
||||
|
||||
if (val & ENETC_PCAPR0_PSFP)
|
||||
si->hw_features |= ENETC_SI_F_PSFP;
|
||||
}
|
||||
|
||||
static void enetc_port_si_configure(struct enetc_si *si)
|
||||
{
|
||||
struct enetc_pf *pf = enetc_si_priv(si);
|
||||
@@ -416,6 +433,8 @@ static void enetc_port_si_configure(struct enetc_si *si)
|
||||
int num_rings, i;
|
||||
u32 val;
|
||||
|
||||
enetc_port_get_caps(si);
|
||||
|
||||
val = enetc_port_rd(hw, ENETC_PCAPR0);
|
||||
num_rings = min(ENETC_PCAPR0_RXBDR(val), ENETC_PCAPR0_TXBDR(val));
|
||||
|
||||
|
||||
@@ -542,7 +542,8 @@ ice_aq_get_netlist_node(struct ice_hw *hw, struct ice_aqc_get_link_topo *cmd,
|
||||
/**
|
||||
* ice_find_netlist_node
|
||||
* @hw: pointer to the hw struct
|
||||
* @node_type_ctx: type of netlist node to look for
|
||||
* @node_type: type of netlist node to look for
|
||||
* @ctx: context of the search
|
||||
* @node_part_number: node part number to look for
|
||||
* @node_handle: output parameter if node found - optional
|
||||
*
|
||||
@@ -552,10 +553,12 @@ ice_aq_get_netlist_node(struct ice_hw *hw, struct ice_aqc_get_link_topo *cmd,
|
||||
* valid if the function returns zero, and should be ignored on any non-zero
|
||||
* return value.
|
||||
*
|
||||
* Returns: 0 if the node is found, -ENOENT if no handle was found, and
|
||||
* a negative error code on failure to access the AQ.
|
||||
* Return:
|
||||
* * 0 if the node is found,
|
||||
* * -ENOENT if no handle was found,
|
||||
* * negative error code on failure to access the AQ.
|
||||
*/
|
||||
static int ice_find_netlist_node(struct ice_hw *hw, u8 node_type_ctx,
|
||||
static int ice_find_netlist_node(struct ice_hw *hw, u8 node_type, u8 ctx,
|
||||
u8 node_part_number, u16 *node_handle)
|
||||
{
|
||||
u8 idx;
|
||||
@@ -566,8 +569,8 @@ static int ice_find_netlist_node(struct ice_hw *hw, u8 node_type_ctx,
|
||||
int status;
|
||||
|
||||
cmd.addr.topo_params.node_type_ctx =
|
||||
FIELD_PREP(ICE_AQC_LINK_TOPO_NODE_TYPE_M,
|
||||
node_type_ctx);
|
||||
FIELD_PREP(ICE_AQC_LINK_TOPO_NODE_TYPE_M, node_type) |
|
||||
FIELD_PREP(ICE_AQC_LINK_TOPO_NODE_CTX_M, ctx);
|
||||
cmd.addr.topo_params.index = idx;
|
||||
|
||||
status = ice_aq_get_netlist_node(hw, &cmd,
|
||||
@@ -2747,9 +2750,11 @@ bool ice_is_pf_c827(struct ice_hw *hw)
|
||||
*/
|
||||
bool ice_is_phy_rclk_in_netlist(struct ice_hw *hw)
|
||||
{
|
||||
if (ice_find_netlist_node(hw, ICE_AQC_LINK_TOPO_NODE_TYPE_CLK_CTRL,
|
||||
if (ice_find_netlist_node(hw, ICE_AQC_LINK_TOPO_NODE_TYPE_PHY,
|
||||
ICE_AQC_LINK_TOPO_NODE_CTX_PORT,
|
||||
ICE_AQC_GET_LINK_TOPO_NODE_NR_C827, NULL) &&
|
||||
ice_find_netlist_node(hw, ICE_AQC_LINK_TOPO_NODE_TYPE_CLK_CTRL,
|
||||
ice_find_netlist_node(hw, ICE_AQC_LINK_TOPO_NODE_TYPE_PHY,
|
||||
ICE_AQC_LINK_TOPO_NODE_CTX_PORT,
|
||||
ICE_AQC_GET_LINK_TOPO_NODE_NR_E822_PHY, NULL))
|
||||
return false;
|
||||
|
||||
@@ -2765,6 +2770,7 @@ bool ice_is_phy_rclk_in_netlist(struct ice_hw *hw)
|
||||
bool ice_is_clock_mux_in_netlist(struct ice_hw *hw)
|
||||
{
|
||||
if (ice_find_netlist_node(hw, ICE_AQC_LINK_TOPO_NODE_TYPE_CLK_MUX,
|
||||
ICE_AQC_LINK_TOPO_NODE_CTX_GLOBAL,
|
||||
ICE_AQC_GET_LINK_TOPO_NODE_NR_GEN_CLK_MUX,
|
||||
NULL))
|
||||
return false;
|
||||
@@ -2785,12 +2791,14 @@ bool ice_is_clock_mux_in_netlist(struct ice_hw *hw)
|
||||
bool ice_is_cgu_in_netlist(struct ice_hw *hw)
|
||||
{
|
||||
if (!ice_find_netlist_node(hw, ICE_AQC_LINK_TOPO_NODE_TYPE_CLK_CTRL,
|
||||
ICE_AQC_LINK_TOPO_NODE_CTX_GLOBAL,
|
||||
ICE_AQC_GET_LINK_TOPO_NODE_NR_ZL30632_80032,
|
||||
NULL)) {
|
||||
hw->cgu_part_number = ICE_AQC_GET_LINK_TOPO_NODE_NR_ZL30632_80032;
|
||||
return true;
|
||||
} else if (!ice_find_netlist_node(hw,
|
||||
ICE_AQC_LINK_TOPO_NODE_TYPE_CLK_CTRL,
|
||||
ICE_AQC_LINK_TOPO_NODE_CTX_GLOBAL,
|
||||
ICE_AQC_GET_LINK_TOPO_NODE_NR_SI5383_5384,
|
||||
NULL)) {
|
||||
hw->cgu_part_number = ICE_AQC_GET_LINK_TOPO_NODE_NR_SI5383_5384;
|
||||
@@ -2809,6 +2817,7 @@ bool ice_is_cgu_in_netlist(struct ice_hw *hw)
|
||||
bool ice_is_gps_in_netlist(struct ice_hw *hw)
|
||||
{
|
||||
if (ice_find_netlist_node(hw, ICE_AQC_LINK_TOPO_NODE_TYPE_GPS,
|
||||
ICE_AQC_LINK_TOPO_NODE_CTX_GLOBAL,
|
||||
ICE_AQC_GET_LINK_TOPO_NODE_NR_GEN_GPS, NULL))
|
||||
return false;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user