mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 08:15:07 -04:00
Merge tag 'net-7.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Pull networking fixes from Jakub Kicinski:
"Including fixes from Bluetooth, IPSec and Netfilter.
Current release - fix to a fix:
- netfilter: ipset: remove need to allocate memory on delete operations
Current release - regressions:
- macb: drop CONFIG_OF #if block, fix build
Previous releases - always broken:
- stream of fixes for SCTP continues
- inet: frags: strip GSO state from fragments before reassembly
- virtio-net: ensure that TCP packets don't overflow gso_segs
- tcp-ao: fix use-after-free of current_key on reconnect to another
peer
- page_pool: remove zone/policy GFP flags when allocating XArray
entries
- Bluetooth: L2CAP: reject accept queue add unless BT_LISTEN
- tls: device: fix out-of-bounds write in tls_append_frag()
- eth: bnxt:
- ring the doorbell when SW USO exits early, avoid packets stuck
in Tx
- gate TPH enablement behind BNXT_SUPPORTS_QUEUE_API check, avoid
users of older NICs seeing non-actionable warning messages
- eth: qede: fix NULL pointer dereference in TPA fragment processing"
* tag 'net-7.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (216 commits)
inet: frags: strip GSO state from fragments before reassembly
net/sched: sch_htb: limit htb_classify inner-class filter hops
selftests/net: packetdrill: add tcp_urg_ptr_retransmit
tcp: fix corruption of urgent data on multi-segment retransmit
usb: atm: usbatm: fix invalid ci_range initialization
net: fec: only stop PTP if it was initialized
slip: remove slip_hangup() to fix use-after-free in slip_receive_buf()
net: bridge: mcast: fix use-after-free of a master VLAN's multicast context
net/sched: bound qdisc_pkt_len to prevent qdisc soft lockup
net: dsa: mxl862xx: enable assisted learning on CPU port
net: stmmac: restore NET_IP_ALIGN in the RX DMA offset
net: stmmac: drop gso_enabled_types and rely on netdev features
net: stmmac: selftests: Don't test flow control for small rx fifos
net: stmmac: selftests: Account for the UC filter list for filtering tests
net: stmmac: dwxgmac: Account for the primary MAC address for UC filtering
net: stmmac: dwmac4: Account for the primary MAC address for UC filtering
net: stmmac: dwmac1000: Account for the primary MAC address for UC filtering
net: stmmac: selftests: Check multiple MMC counters
selftests: net: Fix slow configurations in big_tcp_tunnels.sh
selftests: net: Lower threshold with csum offload off in big_tcp_tunnels.sh
...
This commit is contained in:
@@ -77,7 +77,7 @@ Reference
|
||||
|
||||
10BASE-T1x MAC-PHY Serial Interface Specification,
|
||||
|
||||
Link: https://opensig.org/download/document/OPEN_Alliance_10BASET1x_MAC-PHY_Serial_Interface_V1.1.pdf
|
||||
Link: https://opensig.org/wp-content/uploads/2023/12/OPEN_Alliance_10BASET1x_MAC-PHY_Serial_Interface_V1.1.pdf
|
||||
|
||||
Hardware Architecture
|
||||
---------------------
|
||||
|
||||
@@ -860,6 +860,7 @@ static u32 btmtk_usb_reset_done(struct hci_dev *hdev)
|
||||
|
||||
int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id)
|
||||
{
|
||||
int reset_err = 0;
|
||||
u32 val;
|
||||
int err;
|
||||
|
||||
@@ -958,8 +959,10 @@ int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id)
|
||||
|
||||
err = readx_poll_timeout(btmtk_usb_reset_done, hdev, val,
|
||||
val & MTK_BT_RST_DONE, 20000, 1000000);
|
||||
if (err < 0)
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Reset timeout");
|
||||
reset_err = err;
|
||||
}
|
||||
|
||||
if (dev_id == 0x7922) {
|
||||
err = btmtk_usb_uhw_reg_write(hdev, MTK_UDMA_INT_STA_BT, 0x000000FF);
|
||||
@@ -968,10 +971,12 @@ int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id)
|
||||
}
|
||||
|
||||
err = btmtk_usb_id_get(hdev, 0x70010200, &val);
|
||||
if (err || (!val && dev_id != 0x6639))
|
||||
if (err || (!val && dev_id != 0x6639)) {
|
||||
bt_dev_err(hdev, "Can't get device id, subsys reset fail.");
|
||||
return err ? err : -ENODEV;
|
||||
}
|
||||
|
||||
return err;
|
||||
return reset_err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btmtk_usb_subsys_reset);
|
||||
|
||||
|
||||
@@ -272,12 +272,24 @@ static int btmtksdio_tx_packet(struct btmtksdio_dev *bdev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct mtkbtsdio_hdr *sdio_hdr;
|
||||
unsigned int len, pad_len;
|
||||
int err;
|
||||
|
||||
/* Make sure that there are enough rooms for SDIO header */
|
||||
if (unlikely(skb_headroom(skb) < sizeof(*sdio_hdr))) {
|
||||
err = pskb_expand_head(skb, sizeof(*sdio_hdr), 0,
|
||||
GFP_ATOMIC);
|
||||
/* Make sure that the data buffer is not shared with anyone else and
|
||||
* that there is enough room for the SDIO header
|
||||
*/
|
||||
err = skb_cow_head(skb, sizeof(*sdio_hdr));
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* The transfer is rounded up to the SDIO block size, so the buffer
|
||||
* has to provide tailroom for the padding as well
|
||||
*/
|
||||
len = skb->len + sizeof(*sdio_hdr);
|
||||
pad_len = round_up(len, MTK_SDIO_BLOCK_SIZE) - len;
|
||||
|
||||
if (unlikely(skb_tailroom(skb) < pad_len)) {
|
||||
err = pskb_expand_head(skb, 0, pad_len, GFP_ATOMIC);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
@@ -290,19 +302,22 @@ static int btmtksdio_tx_packet(struct btmtksdio_dev *bdev,
|
||||
sdio_hdr->reserved = cpu_to_le16(0);
|
||||
sdio_hdr->bt_type = hci_skb_pkt_type(skb);
|
||||
|
||||
clear_bit(BTMTKSDIO_HW_TX_READY, &bdev->tx_state);
|
||||
err = sdio_writesb(bdev->func, MTK_REG_CTDR, skb->data,
|
||||
round_up(skb->len, MTK_SDIO_BLOCK_SIZE));
|
||||
if (err < 0)
|
||||
goto err_skb_pull;
|
||||
/* Zero the padding so that no uninitialised memory is sent out */
|
||||
skb_put_zero(skb, pad_len);
|
||||
|
||||
bdev->hdev->stat.byte_tx += skb->len;
|
||||
clear_bit(BTMTKSDIO_HW_TX_READY, &bdev->tx_state);
|
||||
err = sdio_writesb(bdev->func, MTK_REG_CTDR, skb->data, skb->len);
|
||||
if (err < 0)
|
||||
goto err_skb_restore;
|
||||
|
||||
bdev->hdev->stat.byte_tx += len;
|
||||
|
||||
kfree_skb(skb);
|
||||
|
||||
return 0;
|
||||
|
||||
err_skb_pull:
|
||||
err_skb_restore:
|
||||
skb_trim(skb, len);
|
||||
skb_pull(skb, sizeof(*sdio_hdr));
|
||||
|
||||
return err;
|
||||
|
||||
@@ -1359,12 +1359,21 @@ static int nxp_process_fw_dump(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
struct hci_acl_hdr *acl_hdr = (struct hci_acl_hdr *)skb_pull_data(skb,
|
||||
sizeof(*acl_hdr));
|
||||
struct nxp_fw_dump_hdr *fw_dump_hdr = (struct nxp_fw_dump_hdr *)skb->data;
|
||||
struct nxp_fw_dump_hdr *fw_dump_hdr;
|
||||
struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
|
||||
__u16 seq_num = __le16_to_cpu(fw_dump_hdr->seq_num);
|
||||
__u16 buf_len = __le16_to_cpu(fw_dump_hdr->buf_len);
|
||||
__u16 seq_num;
|
||||
__u16 buf_len;
|
||||
int err;
|
||||
|
||||
fw_dump_hdr = skb_pull_data(skb, sizeof(*fw_dump_hdr));
|
||||
if (!fw_dump_hdr) {
|
||||
bt_dev_warn(hdev, "FW dump: invalid or corrupt fw dump chunk");
|
||||
goto free_skb;
|
||||
}
|
||||
|
||||
seq_num = __le16_to_cpu(fw_dump_hdr->seq_num);
|
||||
buf_len = __le16_to_cpu(fw_dump_hdr->buf_len);
|
||||
|
||||
if (seq_num == 0x0001) {
|
||||
if (test_and_set_bit(BTNXPUART_FW_DUMP_IN_PROGRESS, &nxpdev->tx_state)) {
|
||||
bt_dev_err(hdev, "FW dump already in progress");
|
||||
@@ -1809,6 +1818,28 @@ static void nxp_coredump_notify(struct hci_dev *hdev, int state)
|
||||
kobject_uevent_env(&serdev->dev.kobj, KOBJ_CHANGE, envp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the remote M.2 connector device linked via OF graph is present
|
||||
* and available. This is used to determine whether the pwrseq path should
|
||||
* be taken. When the remote connector node is disabled (e.g., by a DT
|
||||
* overlay switching from PCIe WiFi to SDIO WiFi), the pwrseq path is
|
||||
* skipped, allowing the BT driver to use a direct bluetooth child node
|
||||
* instead.
|
||||
*/
|
||||
static bool nxp_m2_connector_is_available(struct device *dev)
|
||||
{
|
||||
struct device_node *ep __free(device_node) =
|
||||
of_graph_get_next_endpoint(dev_of_node(dev), NULL);
|
||||
|
||||
if (!ep)
|
||||
return false;
|
||||
|
||||
struct device_node *remote __free(device_node) =
|
||||
of_graph_get_remote_port_parent(ep);
|
||||
|
||||
return remote && of_device_is_available(remote);
|
||||
}
|
||||
|
||||
static int nxp_serdev_probe(struct serdev_device *serdev)
|
||||
{
|
||||
struct hci_dev *hdev;
|
||||
@@ -1863,7 +1894,7 @@ static int nxp_serdev_probe(struct serdev_device *serdev)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (of_graph_is_present(dev_of_node(&serdev->ctrl->dev))) {
|
||||
if (nxp_m2_connector_is_available(&serdev->ctrl->dev)) {
|
||||
struct pwrseq_desc *pwrseq;
|
||||
|
||||
pwrseq = pwrseq_get(&serdev->ctrl->dev, "uart");
|
||||
|
||||
@@ -1343,19 +1343,6 @@ void btrtl_set_quirks(struct hci_dev *hdev, struct btrtl_device_info *btrtl_dev)
|
||||
if (!btrtl_dev->ic_info)
|
||||
return;
|
||||
|
||||
switch (btrtl_dev->project_id) {
|
||||
case CHIP_ID_8761B:
|
||||
/* RTL8761B/BU reports HCI version 5.1 but does not support
|
||||
* the LE Extended Scan commands (Opcode 0x2042), causing
|
||||
* repeated -EBUSY failures when BlueZ attempts extended
|
||||
* scanning while a connection is active.
|
||||
*/
|
||||
hci_set_quirk(hdev, HCI_QUIRK_BROKEN_EXT_SCAN);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (btrtl_dev->ic_info->lmp_subver) {
|
||||
case RTL_ROM_LMP_8703B:
|
||||
/* 8723CS reports two pages for local ext features,
|
||||
|
||||
@@ -67,6 +67,7 @@ static struct usb_driver btusb_driver;
|
||||
#define BTUSB_INTEL_NO_WBS_SUPPORT BIT(26)
|
||||
#define BTUSB_ACTIONS_SEMI BIT(27)
|
||||
#define BTUSB_BARROT BIT(28)
|
||||
#define BTUSB_BROKEN_EXT_SCAN BIT(29)
|
||||
|
||||
static const struct usb_device_id btusb_table[] = {
|
||||
/* Generic Bluetooth USB device */
|
||||
@@ -617,6 +618,10 @@ static const struct usb_device_id quirks_table[] = {
|
||||
{ USB_DEVICE(0x0489, 0xe130), .driver_info = BTUSB_REALTEK |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
|
||||
/* Realtek 8761BU Bluetooth devices */
|
||||
{ USB_DEVICE(0x0bda, 0xa728), .driver_info = BTUSB_REALTEK |
|
||||
BTUSB_BROKEN_EXT_SCAN },
|
||||
|
||||
/* Realtek Bluetooth devices */
|
||||
{ USB_VENDOR_AND_INTERFACE_INFO(0x0bda, 0xe0, 0x01, 0x01),
|
||||
.driver_info = BTUSB_REALTEK },
|
||||
@@ -4401,6 +4406,9 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
if (id->driver_info & BTUSB_INVALID_LE_STATES)
|
||||
hci_set_quirk(hdev, HCI_QUIRK_BROKEN_LE_STATES);
|
||||
|
||||
if (id->driver_info & BTUSB_BROKEN_EXT_SCAN)
|
||||
hci_set_quirk(hdev, HCI_QUIRK_BROKEN_EXT_SCAN);
|
||||
|
||||
if (id->driver_info & BTUSB_DIGIANSWER) {
|
||||
data->cmdreq_type = USB_TYPE_VENDOR;
|
||||
hci_set_quirk(hdev, HCI_QUIRK_RESET_ON_CLOSE);
|
||||
|
||||
@@ -547,6 +547,7 @@ static int bcm_close(struct hci_uart *hu)
|
||||
if (IS_ENABLED(CONFIG_PM) && bdev->irq_acquired) {
|
||||
devm_free_irq(bdev->dev, bdev->irq, bdev);
|
||||
device_init_wakeup(bdev->dev, false);
|
||||
pm_runtime_dont_use_autosuspend(bdev->dev);
|
||||
pm_runtime_disable(bdev->dev);
|
||||
}
|
||||
|
||||
|
||||
@@ -2490,6 +2490,7 @@ static const struct bcm4377_hw bcm4377_hw_variants[] = {
|
||||
.has_bar0_core2_window2 = true,
|
||||
.broken_mws_transport_config = true,
|
||||
.broken_le_coded = true,
|
||||
.broken_le_ext_adv_report_phy = true,
|
||||
.send_calibration = bcm4378_send_calibration,
|
||||
.send_ptb = bcm4378_send_ptb,
|
||||
},
|
||||
|
||||
@@ -1023,8 +1023,10 @@ static void h5_btrtl_open(struct h5 *h5)
|
||||
|
||||
static void h5_btrtl_close(struct h5 *h5)
|
||||
{
|
||||
if (!test_bit(H5_WAKEUP_DISABLE, &h5->flags))
|
||||
if (!test_bit(H5_WAKEUP_DISABLE, &h5->flags)) {
|
||||
pm_runtime_dont_use_autosuspend(&h5->hu->serdev->dev);
|
||||
pm_runtime_disable(&h5->hu->serdev->dev);
|
||||
}
|
||||
|
||||
gpiod_set_value_cansleep(h5->device_wake_gpio, 0);
|
||||
gpiod_set_value_cansleep(h5->enable_gpio, 0);
|
||||
|
||||
@@ -345,6 +345,7 @@ static int intel_set_power(struct hci_uart *hu, bool powered)
|
||||
devm_free_irq(&idev->pdev->dev, idev->irq, idev);
|
||||
device_wakeup_disable(&idev->pdev->dev);
|
||||
|
||||
pm_runtime_dont_use_autosuspend(&idev->pdev->dev);
|
||||
pm_runtime_disable(&idev->pdev->dev);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -457,7 +457,7 @@ static int hci_uart_setup(struct hci_dev *hdev)
|
||||
if (IS_ERR(skb)) {
|
||||
BT_ERR("%s: Reading local version information failed (%ld)",
|
||||
hdev->name, PTR_ERR(skb));
|
||||
return 0;
|
||||
return PTR_ERR(skb);
|
||||
}
|
||||
|
||||
if (skb->len != sizeof(*ver)) {
|
||||
|
||||
@@ -221,7 +221,7 @@ static int hci_uart_setup(struct hci_dev *hdev)
|
||||
if (IS_ERR(skb)) {
|
||||
bt_dev_err(hdev, "Reading local version info failed (%ld)",
|
||||
PTR_ERR(skb));
|
||||
return 0;
|
||||
return PTR_ERR(skb);
|
||||
}
|
||||
|
||||
if (skb->len != sizeof(*ver))
|
||||
|
||||
@@ -1630,14 +1630,15 @@ static int mlx5_ib_query_port_speed_from_vport(struct mlx5_core_dev *mdev,
|
||||
u32 port_num)
|
||||
{
|
||||
u32 max_tx_speed;
|
||||
u8 vport_state;
|
||||
int err;
|
||||
|
||||
err = mlx5_query_vport_max_tx_speed(mdev, op_mod, vport, other_vport,
|
||||
&max_tx_speed);
|
||||
&max_tx_speed, &vport_state);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (max_tx_speed == 0)
|
||||
if (vport_state == VPORT_STATE_DOWN || max_tx_speed == 0)
|
||||
/* Value 0 indicates field not supported, fallback */
|
||||
return mlx5_ib_query_port_speed_from_port(dev, port_num,
|
||||
speed);
|
||||
|
||||
@@ -2111,6 +2111,7 @@ static int mxl862xx_probe(struct mdio_device *mdiodev)
|
||||
ds->ops = &mxl862xx_switch_ops;
|
||||
ds->phylink_mac_ops = &mxl862xx_phylink_mac_ops;
|
||||
ds->num_ports = MXL862XX_MAX_PORTS;
|
||||
ds->assisted_learning_on_cpu_port = true;
|
||||
ds->fdb_isolation = true;
|
||||
ds->max_num_bridges = MXL862XX_MAX_BRIDGES;
|
||||
|
||||
|
||||
@@ -768,7 +768,7 @@ static int airoha_npu_probe(struct platform_device *pdev)
|
||||
npu->irqs[i] = irq;
|
||||
}
|
||||
|
||||
err = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
|
||||
err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
||||
@@ -996,9 +996,9 @@ static int emac_probe(struct platform_device *pdev)
|
||||
/* fill in parameters for net-dev structure */
|
||||
ndev->base_addr = (unsigned long)db->membase;
|
||||
ndev->irq = irq_of_parse_and_map(np, 0);
|
||||
if (ndev->irq == -ENXIO) {
|
||||
if (!ndev->irq) {
|
||||
netdev_err(ndev, "No irq resource\n");
|
||||
ret = ndev->irq;
|
||||
ret = -ENXIO;
|
||||
goto out_iounmap;
|
||||
}
|
||||
|
||||
|
||||
@@ -13473,10 +13473,13 @@ static int bnx2x_init_firmware(struct bnx2x *bp)
|
||||
|
||||
iro_alloc_err:
|
||||
kfree(bp->init_ops_offsets);
|
||||
bp->init_ops_offsets = NULL;
|
||||
init_offsets_alloc_err:
|
||||
kfree(bp->init_ops);
|
||||
bp->init_ops = NULL;
|
||||
init_ops_alloc_err:
|
||||
kfree(bp->init_data);
|
||||
bp->init_data = NULL;
|
||||
request_firmware_exit:
|
||||
release_firmware(bp->firmware);
|
||||
bp->firmware = NULL;
|
||||
|
||||
@@ -485,6 +485,7 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
struct bnxt_sw_tx_bd *tx_buf;
|
||||
__le32 lflags = 0;
|
||||
skb_frag_t *frag;
|
||||
netdev_tx_t ret;
|
||||
|
||||
i = skb_get_queue_mapping(skb);
|
||||
if (unlikely(i >= bp->tx_nr_rings)) {
|
||||
@@ -501,17 +502,19 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
if (skb_shinfo(skb)->nr_frags > TX_MAX_FRAGS) {
|
||||
netdev_warn_once(dev, "SKB has too many (%d) fragments, max supported is %d. SKB will be linearized.\n",
|
||||
skb_shinfo(skb)->nr_frags, TX_MAX_FRAGS);
|
||||
if (skb_linearize(skb)) {
|
||||
dev_kfree_skb_any(skb);
|
||||
dev_core_stats_tx_dropped_inc(dev);
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
if (skb_linearize(skb))
|
||||
goto tx_free;
|
||||
}
|
||||
#endif
|
||||
if (skb_is_gso(skb) &&
|
||||
(skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) &&
|
||||
!(bp->flags & BNXT_FLAG_UDP_GSO_CAP))
|
||||
return bnxt_sw_udp_gso_xmit(bp, txr, txq, skb);
|
||||
!(bp->flags & BNXT_FLAG_UDP_GSO_CAP)) {
|
||||
ret = bnxt_sw_udp_gso_xmit(bp, txr, txq, skb);
|
||||
if (txr->kick_pending)
|
||||
bnxt_txr_db_kick(bp, txr, txr->tx_prod);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
free_size = bnxt_tx_avail(bp, txr);
|
||||
if (unlikely(free_size < skb_shinfo(skb)->nr_frags + 2)) {
|
||||
@@ -11946,9 +11949,11 @@ static int bnxt_request_irq(struct bnxt *bp)
|
||||
#endif
|
||||
|
||||
/* Enable TPH support as part of IRQ request */
|
||||
rc = pcie_enable_tph(bp->pdev, PCI_TPH_ST_IV_MODE);
|
||||
if (!rc)
|
||||
bp->tph_mode = PCI_TPH_ST_IV_MODE;
|
||||
if (BNXT_SUPPORTS_QUEUE_API(bp)) {
|
||||
rc = pcie_enable_tph(bp->pdev, PCI_TPH_ST_IV_MODE);
|
||||
if (!rc)
|
||||
bp->tph_mode = PCI_TPH_ST_IV_MODE;
|
||||
}
|
||||
|
||||
for (i = 0, j = 0; i < bp->cp_nr_rings; i++) {
|
||||
struct cpumask *cpu_mask = bp->ring_cpu_mask[i];
|
||||
|
||||
@@ -223,9 +223,7 @@ netdev_tx_t bnxt_sw_udp_gso_xmit(struct bnxt *bp,
|
||||
netdev_tx_sent_queue(txq, skb->len);
|
||||
|
||||
WRITE_ONCE(txr->tx_prod, prod);
|
||||
/* Sync BDs before doorbell */
|
||||
wmb();
|
||||
bnxt_db_write(bp, &txr->tx_db, prod);
|
||||
txr->kick_pending = 1;
|
||||
|
||||
if (unlikely(bnxt_tx_avail(bp, txr) <= bp->tx_wake_thresh))
|
||||
netif_txq_try_stop(txq, bnxt_tx_avail(bp, txr),
|
||||
|
||||
@@ -40,7 +40,7 @@ void bnxt_hwmon_notify_event(struct bnxt *bp)
|
||||
return;
|
||||
}
|
||||
|
||||
hwmon_notify_event(&bp->pdev->dev, hwmon_temp, attr, 0);
|
||||
hwmon_notify_event(bp->hwmon_dev, hwmon_temp, attr, 0);
|
||||
}
|
||||
|
||||
static int bnxt_hwrm_temp_query(struct bnxt *bp, u8 *temp)
|
||||
|
||||
@@ -4926,7 +4926,6 @@ static const struct macb_usrio_config at91_default_usrio = {
|
||||
.clken = MACB_BIT(CLKEN),
|
||||
};
|
||||
|
||||
#if defined(CONFIG_OF)
|
||||
/* 1518 rounded up */
|
||||
#define AT91ETHER_MAX_RBUFF_SZ 0x600
|
||||
/* max number of receive buffers */
|
||||
@@ -5754,7 +5753,6 @@ static const struct of_device_id macb_dt_ids[] = {
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, macb_dt_ids);
|
||||
#endif /* CONFIG_OF */
|
||||
|
||||
static const struct macb_config default_gem_config = {
|
||||
.caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE |
|
||||
@@ -6267,7 +6265,7 @@ static struct platform_driver macb_driver = {
|
||||
.remove = macb_remove,
|
||||
.driver = {
|
||||
.name = "macb",
|
||||
.of_match_table = of_match_ptr(macb_dt_ids),
|
||||
.of_match_table = macb_dt_ids,
|
||||
.pm = &macb_pm_ops,
|
||||
},
|
||||
.shutdown = macb_shutdown,
|
||||
|
||||
@@ -81,6 +81,33 @@ void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(enetc_reset_mac_addr_filter);
|
||||
|
||||
void enetc_set_congestion_mode(struct enetc_ndev_priv *priv, bool enable)
|
||||
{
|
||||
struct enetc_si *si = priv->si;
|
||||
struct enetc_hw *hw = &si->hw;
|
||||
|
||||
spin_lock(&si->gen_lock);
|
||||
|
||||
if (enable)
|
||||
set_bit(ENETC_RXBDR_CM, &priv->flags);
|
||||
else
|
||||
clear_bit(ENETC_RXBDR_CM, &priv->flags);
|
||||
|
||||
for (int i = 0; i < priv->num_rx_rings; i++) {
|
||||
u32 old_rbmr = enetc_rxbdr_rd(hw, i, ENETC_RBMR);
|
||||
u32 rbmr;
|
||||
|
||||
rbmr = u32_replace_bits(old_rbmr, enable, ENETC_RBMR_CM);
|
||||
if (rbmr == old_rbmr)
|
||||
continue;
|
||||
|
||||
enetc_rxbdr_wr(hw, i, ENETC_RBMR, rbmr);
|
||||
}
|
||||
|
||||
spin_unlock(&si->gen_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(enetc_set_congestion_mode);
|
||||
|
||||
static int enetc_num_stack_tx_queues(struct enetc_ndev_priv *priv)
|
||||
{
|
||||
int num_tx_rings = priv->num_tx_rings;
|
||||
@@ -2632,7 +2659,6 @@ static void enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring,
|
||||
bool extended)
|
||||
{
|
||||
int idx = rx_ring->index;
|
||||
u32 rbmr = 0;
|
||||
|
||||
enetc_rxbdr_wr(hw, idx, ENETC_RBBAR0,
|
||||
lower_32_bits(rx_ring->bd_dma_base));
|
||||
@@ -2660,12 +2686,6 @@ static void enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring,
|
||||
enetc_rxbdr_wr(hw, idx, ENETC_RBICR0, ENETC_RBICR0_ICEN | 0x1);
|
||||
|
||||
rx_ring->ext_en = extended;
|
||||
if (rx_ring->ext_en)
|
||||
rbmr |= ENETC_RBMR_BDS;
|
||||
|
||||
if (rx_ring->ndev->features & NETIF_F_HW_VLAN_CTAG_RX)
|
||||
rbmr |= ENETC_RBMR_VTE;
|
||||
|
||||
rx_ring->rcir = hw->reg + ENETC_BDR(RX, idx, ENETC_RBCIR);
|
||||
rx_ring->idr = hw->reg + ENETC_SIRXIDR;
|
||||
|
||||
@@ -2676,8 +2696,6 @@ static void enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring,
|
||||
enetc_lock_mdio();
|
||||
enetc_refill_rx_ring(rx_ring, enetc_bd_unused(rx_ring));
|
||||
enetc_unlock_mdio();
|
||||
|
||||
enetc_rxbdr_wr(hw, idx, ENETC_RBMR, rbmr);
|
||||
}
|
||||
|
||||
static void enetc_setup_bdrs(struct enetc_ndev_priv *priv, bool extended)
|
||||
@@ -2704,21 +2722,34 @@ static void enetc_enable_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring)
|
||||
|
||||
static void enetc_enable_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring)
|
||||
{
|
||||
struct enetc_ndev_priv *priv = netdev_priv(rx_ring->ndev);
|
||||
int idx = rx_ring->index;
|
||||
u32 rbmr;
|
||||
u32 rbmr = ENETC_RBMR_EN;
|
||||
|
||||
if (rx_ring->ext_en)
|
||||
rbmr |= ENETC_RBMR_BDS;
|
||||
|
||||
if (rx_ring->ndev->features & NETIF_F_HW_VLAN_CTAG_RX)
|
||||
rbmr |= ENETC_RBMR_VTE;
|
||||
|
||||
if (test_bit(ENETC_RXBDR_CM, &priv->flags))
|
||||
rbmr |= ENETC_RBMR_CM;
|
||||
|
||||
rbmr = enetc_rxbdr_rd(hw, idx, ENETC_RBMR);
|
||||
rbmr |= ENETC_RBMR_EN;
|
||||
enetc_rxbdr_wr(hw, idx, ENETC_RBMR, rbmr);
|
||||
}
|
||||
|
||||
static void enetc_enable_rx_bdrs(struct enetc_ndev_priv *priv)
|
||||
{
|
||||
struct enetc_hw *hw = &priv->si->hw;
|
||||
struct enetc_si *si = priv->si;
|
||||
struct enetc_hw *hw = &si->hw;
|
||||
int i;
|
||||
|
||||
spin_lock(&si->gen_lock);
|
||||
|
||||
for (i = 0; i < priv->num_rx_rings; i++)
|
||||
enetc_enable_rxbdr(hw, priv->rx_ring[i]);
|
||||
|
||||
spin_unlock(&si->gen_lock);
|
||||
}
|
||||
|
||||
static void enetc_enable_tx_bdrs(struct enetc_ndev_priv *priv)
|
||||
@@ -2748,11 +2779,16 @@ static void enetc_disable_txbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring)
|
||||
|
||||
static void enetc_disable_rx_bdrs(struct enetc_ndev_priv *priv)
|
||||
{
|
||||
struct enetc_hw *hw = &priv->si->hw;
|
||||
struct enetc_si *si = priv->si;
|
||||
struct enetc_hw *hw = &si->hw;
|
||||
int i;
|
||||
|
||||
spin_lock(&si->gen_lock);
|
||||
|
||||
for (i = 0; i < priv->num_rx_rings; i++)
|
||||
enetc_disable_rxbdr(hw, priv->rx_ring[i]);
|
||||
|
||||
spin_unlock(&si->gen_lock);
|
||||
}
|
||||
|
||||
static void enetc_disable_tx_bdrs(struct enetc_ndev_priv *priv)
|
||||
@@ -3344,11 +3380,16 @@ EXPORT_SYMBOL_GPL(enetc_get_stats);
|
||||
static void enetc_enable_rxvlan(struct net_device *ndev, bool en)
|
||||
{
|
||||
struct enetc_ndev_priv *priv = netdev_priv(ndev);
|
||||
struct enetc_hw *hw = &priv->si->hw;
|
||||
struct enetc_si *si = priv->si;
|
||||
struct enetc_hw *hw = &si->hw;
|
||||
int i;
|
||||
|
||||
spin_lock(&si->gen_lock);
|
||||
|
||||
for (i = 0; i < priv->num_rx_rings; i++)
|
||||
enetc_bdr_enable_rxvlan(hw, i, en);
|
||||
|
||||
spin_unlock(&si->gen_lock);
|
||||
}
|
||||
|
||||
static void enetc_enable_txvlan(struct net_device *ndev, bool en)
|
||||
@@ -3679,6 +3720,7 @@ int enetc_pci_probe(struct pci_dev *pdev, const char *name, int sizeof_priv)
|
||||
|
||||
si = PTR_ALIGN(p, ENETC_SI_ALIGN);
|
||||
si->pad = (char *)si - (char *)p;
|
||||
spin_lock_init(&si->gen_lock);
|
||||
|
||||
pci_set_drvdata(pdev, si);
|
||||
si->pdev = pdev;
|
||||
|
||||
@@ -309,6 +309,13 @@ struct enetc_si {
|
||||
|
||||
struct net_device *ndev; /* back ref. */
|
||||
|
||||
/* General-purpose lock serializing updates that must not race,
|
||||
* e.g. read-modify-write of shared hardware registers and of
|
||||
* selected priv->flags bits between the phylink link callbacks
|
||||
* and the ring (re)configuration path.
|
||||
*/
|
||||
spinlock_t gen_lock;
|
||||
|
||||
union {
|
||||
struct enetc_cbdr cbd_ring; /* Only ENETC 1.0 */
|
||||
struct ntmp_user ntmp_user; /* ENETC 4.1 and later */
|
||||
@@ -417,6 +424,7 @@ enum enetc_active_offloads {
|
||||
enum enetc_flags_bit {
|
||||
ENETC_TX_ONESTEP_TSTAMP_IN_PROGRESS = 0,
|
||||
ENETC_TX_DOWN,
|
||||
ENETC_RXBDR_CM,
|
||||
};
|
||||
|
||||
/* interrupt coalescing modes */
|
||||
@@ -505,6 +513,7 @@ int enetc_get_driver_data(struct enetc_si *si);
|
||||
void enetc_add_mac_addr_ht_filter(struct enetc_mac_filter *filter,
|
||||
const unsigned char *addr);
|
||||
void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter);
|
||||
void enetc_set_congestion_mode(struct enetc_ndev_priv *priv, bool enable);
|
||||
|
||||
int enetc_open(struct net_device *ndev);
|
||||
int enetc_close(struct net_device *ndev);
|
||||
|
||||
@@ -718,22 +718,14 @@ static void enetc4_set_rx_pause(struct enetc_pf *pf, bool rx_pause)
|
||||
enetc_port_mac_wr(si, ENETC4_PM_CMD_CFG(0), val);
|
||||
}
|
||||
|
||||
static void enetc4_set_tx_pause(struct enetc_pf *pf, int num_rxbdr, bool tx_pause)
|
||||
static void enetc4_set_tx_pause(struct enetc_pf *pf, bool tx_pause)
|
||||
{
|
||||
struct enetc_ndev_priv *priv = netdev_priv(pf->si->ndev);
|
||||
u32 pause_off_thresh = 0, pause_on_thresh = 0;
|
||||
u32 init_quanta = 0, refresh_quanta = 0;
|
||||
struct enetc_hw *hw = &pf->si->hw;
|
||||
u32 rbmr, old_rbmr;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_rxbdr; i++) {
|
||||
old_rbmr = enetc_rxbdr_rd(hw, i, ENETC_RBMR);
|
||||
rbmr = u32_replace_bits(old_rbmr, tx_pause ? 1 : 0, ENETC_RBMR_CM);
|
||||
if (rbmr == old_rbmr)
|
||||
continue;
|
||||
|
||||
enetc_rxbdr_wr(hw, i, ENETC_RBMR, rbmr);
|
||||
}
|
||||
enetc_set_congestion_mode(priv, tx_pause);
|
||||
|
||||
if (tx_pause) {
|
||||
/* When the port first enters congestion, send a PAUSE request
|
||||
@@ -898,7 +890,7 @@ static void enetc4_pl_mac_link_up(struct phylink_config *config,
|
||||
tx_pause = false;
|
||||
}
|
||||
|
||||
enetc4_set_tx_pause(pf, priv->num_rx_rings, tx_pause);
|
||||
enetc4_set_tx_pause(pf, tx_pause);
|
||||
enetc4_set_rx_pause(pf, rx_pause);
|
||||
enetc4_mac_tx_enable(pf);
|
||||
enetc4_mac_rx_enable(pf);
|
||||
|
||||
@@ -556,8 +556,7 @@ static void enetc_pl_mac_link_up(struct phylink_config *config,
|
||||
struct enetc_hw *hw = &pf->si->hw;
|
||||
struct enetc_si *si = pf->si;
|
||||
struct enetc_ndev_priv *priv;
|
||||
u32 rbmr, cmd_cfg;
|
||||
int idx;
|
||||
u32 cmd_cfg;
|
||||
|
||||
priv = netdev_priv(pf->si->ndev);
|
||||
|
||||
@@ -569,16 +568,7 @@ static void enetc_pl_mac_link_up(struct phylink_config *config,
|
||||
enetc_force_rgmii_mac(si, speed, duplex);
|
||||
|
||||
/* Flow control */
|
||||
for (idx = 0; idx < priv->num_rx_rings; idx++) {
|
||||
rbmr = enetc_rxbdr_rd(hw, idx, ENETC_RBMR);
|
||||
|
||||
if (tx_pause)
|
||||
rbmr |= ENETC_RBMR_CM;
|
||||
else
|
||||
rbmr &= ~ENETC_RBMR_CM;
|
||||
|
||||
enetc_rxbdr_wr(hw, idx, ENETC_RBMR, rbmr);
|
||||
}
|
||||
enetc_set_congestion_mode(priv, tx_pause);
|
||||
|
||||
if (tx_pause) {
|
||||
/* When the port first enters congestion, send a PAUSE request
|
||||
|
||||
@@ -5457,7 +5457,8 @@ fec_probe(struct platform_device *pdev)
|
||||
failed_irq:
|
||||
fec_enet_deinit(ndev);
|
||||
failed_init:
|
||||
fec_ptp_stop(pdev);
|
||||
if (fep->bufdesc_ex)
|
||||
fec_ptp_stop(pdev);
|
||||
failed_reset:
|
||||
pm_runtime_put_noidle(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
@@ -5499,7 +5500,8 @@ fec_drv_remove(struct platform_device *pdev)
|
||||
ERR_PTR(ret));
|
||||
|
||||
cancel_work_sync(&fep->tx_timeout_work);
|
||||
fec_ptp_stop(pdev);
|
||||
if (fep->bufdesc_ex)
|
||||
fec_ptp_stop(pdev);
|
||||
unregister_netdev(ndev);
|
||||
fec_enet_mii_remove(fep);
|
||||
if (fep->reg_phy)
|
||||
|
||||
@@ -554,7 +554,7 @@ static int hbg_ring_page_pool_init(struct hbg_priv *priv, struct hbg_ring *ring)
|
||||
.nid = dev_to_node(&priv->pdev->dev),
|
||||
.dev = &priv->pdev->dev,
|
||||
.napi = &ring->napi,
|
||||
.dma_dir = DMA_FROM_DEVICE,
|
||||
.dma_dir = DMA_BIDIRECTIONAL,
|
||||
.offset = 0,
|
||||
.max_len = hbg_get_page_size(ring),
|
||||
};
|
||||
|
||||
@@ -3071,7 +3071,8 @@ static void igc_xdp_xmit_zc(struct igc_ring *ring)
|
||||
olinfo_status = xdp_desc.len << IGC_ADVTXD_PAYLEN_SHIFT;
|
||||
|
||||
dma = xsk_buff_raw_get_dma(pool, xdp_desc.addr);
|
||||
meta = xsk_buff_get_metadata(pool, xdp_desc.addr);
|
||||
meta = xsk_buff_get_metadata(pool, xdp_desc.addr,
|
||||
xdp_desc.options);
|
||||
xsk_buff_raw_dma_sync_for_device(pool, dma, xdp_desc.len);
|
||||
bi = &ring->tx_buffer_info[ntu];
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ int cn20k_rvu_mbox_init(struct rvu *rvu, int type, int num);
|
||||
int cn20k_rvu_get_mbox_regions(struct rvu *rvu, void **mbox_addr,
|
||||
int num, int type, unsigned long *pf_bmap);
|
||||
void cn20k_free_mbox_memory(struct rvu *rvu);
|
||||
void cn20k_free_mbox_memory_type(struct rvu *rvu, int type);
|
||||
int cn20k_register_afpf_mbox_intr(struct rvu *rvu);
|
||||
int cn20k_register_afvf_mbox_intr(struct rvu *rvu, int pf_vec_start);
|
||||
void cn20k_rvu_enable_mbox_intr(struct rvu *rvu);
|
||||
|
||||
@@ -335,13 +335,30 @@ int cn20k_rvu_mbox_init(struct rvu *rvu, int type, int ndevs)
|
||||
return rvu_alloc_mbox_memory(rvu, type, ndevs, MBOX_SIZE);
|
||||
}
|
||||
|
||||
void cn20k_free_mbox_memory_type(struct rvu *rvu, int type)
|
||||
{
|
||||
if (!is_cn20k(rvu->pdev) || !rvu->ng_rvu)
|
||||
return;
|
||||
|
||||
switch (type) {
|
||||
case TYPE_AFPF:
|
||||
qmem_free(rvu->dev, rvu->ng_rvu->pf_mbox_addr);
|
||||
rvu->ng_rvu->pf_mbox_addr = NULL;
|
||||
break;
|
||||
case TYPE_AFVF:
|
||||
qmem_free(rvu->dev, rvu->ng_rvu->vf_mbox_addr);
|
||||
rvu->ng_rvu->vf_mbox_addr = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void cn20k_free_mbox_memory(struct rvu *rvu)
|
||||
{
|
||||
if (!is_cn20k(rvu->pdev))
|
||||
return;
|
||||
|
||||
qmem_free(rvu->dev, rvu->ng_rvu->pf_mbox_addr);
|
||||
qmem_free(rvu->dev, rvu->ng_rvu->vf_mbox_addr);
|
||||
cn20k_free_mbox_memory_type(rvu, TYPE_AFPF);
|
||||
cn20k_free_mbox_memory_type(rvu, TYPE_AFVF);
|
||||
}
|
||||
|
||||
void cn20k_rvu_disable_afvf_intr(struct rvu *rvu, int vfs)
|
||||
|
||||
@@ -2585,12 +2585,6 @@ static int rvu_mbox_init(struct rvu *rvu, struct mbox_wq_info *mw,
|
||||
if (!pf_bmap)
|
||||
return -ENOMEM;
|
||||
|
||||
ng_rvu_mbox = kzalloc_obj(*ng_rvu_mbox);
|
||||
if (!ng_rvu_mbox) {
|
||||
err = -ENOMEM;
|
||||
goto free_bitmap;
|
||||
}
|
||||
|
||||
/* RVU VFs */
|
||||
if (type == TYPE_AFVF)
|
||||
bitmap_set(pf_bmap, 0, num);
|
||||
@@ -2604,15 +2598,22 @@ static int rvu_mbox_init(struct rvu *rvu, struct mbox_wq_info *mw,
|
||||
}
|
||||
}
|
||||
|
||||
rvu->ng_rvu = ng_rvu_mbox;
|
||||
if (!rvu->ng_rvu) {
|
||||
ng_rvu_mbox = devm_kzalloc(rvu->dev, sizeof(*ng_rvu_mbox), GFP_KERNEL);
|
||||
if (!ng_rvu_mbox) {
|
||||
err = -ENOMEM;
|
||||
goto free_bitmap;
|
||||
}
|
||||
|
||||
rvu->ng_rvu->rvu_mbox_ops = &rvu_mbox_ops;
|
||||
rvu->ng_rvu = ng_rvu_mbox;
|
||||
|
||||
rvu->ng_rvu->rvu_mbox_ops = &rvu_mbox_ops;
|
||||
mutex_init(&rvu->mbox_lock);
|
||||
}
|
||||
|
||||
err = cn20k_rvu_mbox_init(rvu, type, num);
|
||||
if (err)
|
||||
goto free_mem;
|
||||
|
||||
mutex_init(&rvu->mbox_lock);
|
||||
goto free_bitmap;
|
||||
|
||||
mbox_regions = kcalloc(num, sizeof(void __iomem *), GFP_KERNEL);
|
||||
if (!mbox_regions) {
|
||||
@@ -2702,14 +2703,18 @@ static int rvu_mbox_init(struct rvu *rvu, struct mbox_wq_info *mw,
|
||||
free_regions:
|
||||
kfree(mbox_regions);
|
||||
free_qmem:
|
||||
cn20k_free_mbox_memory(rvu);
|
||||
free_mem:
|
||||
kfree(rvu->ng_rvu);
|
||||
cn20k_free_mbox_memory_type(rvu, type);
|
||||
free_bitmap:
|
||||
bitmap_free(pf_bmap);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void rvu_free_cn20k_mbox_memory(struct rvu *rvu)
|
||||
{
|
||||
if (is_cn20k(rvu->pdev))
|
||||
cn20k_free_mbox_memory(rvu);
|
||||
}
|
||||
|
||||
static void rvu_mbox_destroy(struct mbox_wq_info *mw)
|
||||
{
|
||||
struct otx2_mbox *mbox = &mw->mbox;
|
||||
@@ -3331,8 +3336,8 @@ static int rvu_register_interrupts(struct rvu *rvu)
|
||||
goto fail;
|
||||
|
||||
for (i = 0; i < rvu->num_vec; i++) {
|
||||
if (strstr(&rvu->irq_name[i * NAME_SIZE], "Mbox") ||
|
||||
strstr(&rvu->irq_name[i * NAME_SIZE], "FLR"))
|
||||
if (strnstr(&rvu->irq_name[i * NAME_SIZE], "Mbox", NAME_SIZE) ||
|
||||
strnstr(&rvu->irq_name[i * NAME_SIZE], "FLR", NAME_SIZE))
|
||||
irq_set_affinity(pci_irq_vector(rvu->pdev, i),
|
||||
cpumask_of(0));
|
||||
}
|
||||
@@ -3519,6 +3524,7 @@ static int rvu_enable_sriov(struct rvu *rvu)
|
||||
if (err) {
|
||||
rvu_disable_afvf_intr(rvu);
|
||||
rvu_mbox_destroy(&rvu->afvf_wq_info);
|
||||
cn20k_free_mbox_memory_type(rvu, TYPE_AFVF);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -3681,6 +3687,7 @@ static int rvu_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
err_mbox:
|
||||
rvu_mbox_destroy(&rvu->afpf_wq_info);
|
||||
err_hwsetup:
|
||||
rvu_free_cn20k_mbox_memory(rvu);
|
||||
rvu_cgx_exit(rvu);
|
||||
rvu_fwdata_exit(rvu);
|
||||
rvu_mcs_exit(rvu);
|
||||
@@ -3723,9 +3730,7 @@ static void rvu_remove(struct pci_dev *pdev)
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
|
||||
devm_kfree(&pdev->dev, rvu->hw);
|
||||
if (is_cn20k(rvu->pdev))
|
||||
cn20k_free_mbox_memory(rvu);
|
||||
kfree(rvu->ng_rvu);
|
||||
rvu_free_cn20k_mbox_memory(rvu);
|
||||
devm_kfree(&pdev->dev, rvu);
|
||||
atomic_set(&device_bound, 0);
|
||||
}
|
||||
|
||||
@@ -1697,6 +1697,12 @@ static int rvu_dbg_nix_tm_tree_display(struct seq_file *m, void *unused)
|
||||
return -EINVAL;
|
||||
|
||||
pfvf = rvu_get_pfvf(rvu, pcifunc);
|
||||
|
||||
if (!pfvf->sq_ctx) {
|
||||
seq_printf(m, "SQ context is not initialized for pcifunc 0x%x\n", pcifunc);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
max_id = pfvf->sq_ctx->qsize;
|
||||
|
||||
memset(&aq_req, 0, sizeof(struct nix_aq_enq_req));
|
||||
|
||||
@@ -2491,8 +2491,8 @@ static int nix_smq_flush(struct rvu *rvu, int blkaddr,
|
||||
int pf = rvu_get_pf(rvu->pdev, pcifunc);
|
||||
u8 cgx_id = 0, lmac_id = 0;
|
||||
u16 tl2_tl3_link_schq;
|
||||
u8 link, link_level;
|
||||
u64 cfg, bmap = 0;
|
||||
u8 link_level;
|
||||
|
||||
if (!is_rvu_otx2(rvu)) {
|
||||
/* Skip SMQ flush if pkt count is zero */
|
||||
@@ -2524,7 +2524,6 @@ static int nix_smq_flush(struct rvu *rvu, int blkaddr,
|
||||
link_level = rvu_read64(rvu, blkaddr, NIX_AF_PSE_CHANNEL_LEVEL) & 0x01 ?
|
||||
NIX_TXSCH_LVL_TL3 : NIX_TXSCH_LVL_TL2;
|
||||
tl2_tl3_link_schq = smq_flush_ctx->smq_tree_ctx[link_level].schq;
|
||||
link = smq_flush_ctx->smq_tree_ctx[NIX_TXSCH_LVL_TL1].schq;
|
||||
|
||||
/* SMQ set enqueue xoff */
|
||||
cfg = rvu_read64(rvu, blkaddr, NIX_AF_SMQX_CFG(smq));
|
||||
@@ -2534,13 +2533,13 @@ static int nix_smq_flush(struct rvu *rvu, int blkaddr,
|
||||
/* Clear all NIX_AF_TL3_TL2_LINK_CFG[ENA] for the TL3/TL2 queue */
|
||||
for (i = 0; i < (rvu->hw->cgx_links + rvu->hw->lbk_links); i++) {
|
||||
cfg = rvu_read64(rvu, blkaddr,
|
||||
NIX_AF_TL3_TL2X_LINKX_CFG(tl2_tl3_link_schq, link));
|
||||
NIX_AF_TL3_TL2X_LINKX_CFG(tl2_tl3_link_schq, i));
|
||||
if (!(cfg & BIT_ULL(12)))
|
||||
continue;
|
||||
bmap |= BIT_ULL(i);
|
||||
cfg &= ~BIT_ULL(12);
|
||||
rvu_write64(rvu, blkaddr,
|
||||
NIX_AF_TL3_TL2X_LINKX_CFG(tl2_tl3_link_schq, link), cfg);
|
||||
NIX_AF_TL3_TL2X_LINKX_CFG(tl2_tl3_link_schq, i), cfg);
|
||||
}
|
||||
|
||||
/* Do SMQ flush and set enqueue xoff */
|
||||
@@ -2561,10 +2560,10 @@ static int nix_smq_flush(struct rvu *rvu, int blkaddr,
|
||||
if (!(bmap & BIT_ULL(i)))
|
||||
continue;
|
||||
cfg = rvu_read64(rvu, blkaddr,
|
||||
NIX_AF_TL3_TL2X_LINKX_CFG(tl2_tl3_link_schq, link));
|
||||
NIX_AF_TL3_TL2X_LINKX_CFG(tl2_tl3_link_schq, i));
|
||||
cfg |= BIT_ULL(12);
|
||||
rvu_write64(rvu, blkaddr,
|
||||
NIX_AF_TL3_TL2X_LINKX_CFG(tl2_tl3_link_schq, link), cfg);
|
||||
NIX_AF_TL3_TL2X_LINKX_CFG(tl2_tl3_link_schq, i), cfg);
|
||||
}
|
||||
|
||||
/* clear XOFF on TL2s */
|
||||
|
||||
@@ -333,7 +333,8 @@ int otx2_set_rss_table(struct otx2_nic *pfvf, int ctx_id, const u32 *ind_tbl)
|
||||
/* Get memory to put this msg */
|
||||
for (idx = 0; idx < rss->rss_size; idx++) {
|
||||
/* Ignore the queue if AF_XDP zero copy is enabled */
|
||||
if (test_bit(ind_tbl[idx], pfvf->af_xdp_zc_qidx))
|
||||
if (pfvf->af_xdp_zc_qidx &&
|
||||
test_bit(ind_tbl[idx], pfvf->af_xdp_zc_qidx))
|
||||
continue;
|
||||
|
||||
aq = otx2_mbox_alloc_msg_nix_aq_enq(mbox);
|
||||
@@ -1509,7 +1510,8 @@ int otx2_pool_aq_init(struct otx2_nic *pfvf, u16 pool_id,
|
||||
if (type != AURA_NIX_RQ)
|
||||
return 0;
|
||||
|
||||
if (!test_bit(pool_id, pfvf->af_xdp_zc_qidx)) {
|
||||
if (!pfvf->af_xdp_zc_qidx ||
|
||||
!test_bit(pool_id, pfvf->af_xdp_zc_qidx)) {
|
||||
pp_params.order = get_order(buf_size);
|
||||
pp_params.flags = PP_FLAG_DMA_MAP;
|
||||
pp_params.pool_size = min(OTX2_PAGE_POOL_SZ, numptrs);
|
||||
|
||||
@@ -939,7 +939,8 @@ static int otx2_get_rxfh(struct net_device *dev,
|
||||
|
||||
for (idx = 0; idx < rss->rss_size; idx++) {
|
||||
/* Ignore if the rx queue is AF_XDP zero copy enabled */
|
||||
if (test_bit(rss->ind_tbl[idx], pfvf->af_xdp_zc_qidx))
|
||||
if (pfvf->af_xdp_zc_qidx &&
|
||||
test_bit(rss->ind_tbl[idx], pfvf->af_xdp_zc_qidx))
|
||||
continue;
|
||||
indir[idx] = rss->ind_tbl[idx];
|
||||
}
|
||||
|
||||
@@ -737,16 +737,16 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
if (err)
|
||||
goto err_ptp_destroy;
|
||||
|
||||
err = otx2_vf_wq_init(vf);
|
||||
if (err)
|
||||
goto err_ipsec_clean;
|
||||
|
||||
err = register_netdev(netdev);
|
||||
if (err) {
|
||||
dev_err(dev, "Failed to register netdevice\n");
|
||||
goto err_ipsec_clean;
|
||||
goto err_wq_destroy;
|
||||
}
|
||||
|
||||
err = otx2_vf_wq_init(vf);
|
||||
if (err)
|
||||
goto err_unreg_netdev;
|
||||
|
||||
otx2vf_set_ethtool_ops(netdev);
|
||||
|
||||
err = otx2vf_mcam_flow_init(vf);
|
||||
@@ -789,6 +789,10 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
otx2_shutdown_tc(vf);
|
||||
err_unreg_netdev:
|
||||
unregister_netdev(netdev);
|
||||
err_wq_destroy:
|
||||
cancel_work_sync(&vf->reset_task);
|
||||
cancel_work_sync(&vf->rx_mode_work);
|
||||
destroy_workqueue(vf->otx2_wq);
|
||||
err_ipsec_clean:
|
||||
cn10k_ipsec_clean(vf);
|
||||
err_ptp_destroy:
|
||||
@@ -836,11 +840,13 @@ static void otx2vf_remove(struct pci_dev *pdev)
|
||||
}
|
||||
#endif
|
||||
|
||||
cancel_work_sync(&vf->reset_task);
|
||||
otx2_unregister_dl(vf);
|
||||
unregister_netdev(netdev);
|
||||
if (vf->otx2_wq)
|
||||
if (vf->otx2_wq) {
|
||||
cancel_work_sync(&vf->reset_task);
|
||||
cancel_work_sync(&vf->rx_mode_work);
|
||||
destroy_workqueue(vf->otx2_wq);
|
||||
}
|
||||
cn10k_ipsec_clean(vf);
|
||||
otx2_ptp_destroy(vf);
|
||||
otx2_mcam_flow_del(vf);
|
||||
|
||||
@@ -193,7 +193,8 @@ int otx2_xsk_wakeup(struct net_device *dev, u32 queue_id, u32 flags)
|
||||
|
||||
void otx2_attach_xsk_buff(struct otx2_nic *pfvf, struct otx2_snd_queue *sq, int qidx)
|
||||
{
|
||||
if (test_bit(qidx, pfvf->af_xdp_zc_qidx))
|
||||
if (pfvf->af_xdp_zc_qidx &&
|
||||
test_bit(qidx, pfvf->af_xdp_zc_qidx))
|
||||
sq->xsk_pool = xsk_get_pool_from_qid(pfvf->netdev, qidx);
|
||||
}
|
||||
|
||||
|
||||
@@ -2071,6 +2071,11 @@ mtk_wed_dma_enable(struct mtk_wed_device *dev)
|
||||
wdma_set(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN);
|
||||
}
|
||||
|
||||
if (mtk_wed_is_v2(dev->hw))
|
||||
wdma_m32(dev, MTK_WDMA_GLO_CFG,
|
||||
MTK_WDMA_GLO_CFG_RESV_BUFF,
|
||||
FIELD_PREP(MTK_WDMA_GLO_CFG_RESV_BUFF, 0x80));
|
||||
|
||||
wed_set(dev, MTK_WED_GLO_CFG,
|
||||
MTK_WED_GLO_CFG_TX_DMA_EN |
|
||||
MTK_WED_GLO_CFG_RX_DMA_EN);
|
||||
|
||||
@@ -433,6 +433,7 @@ struct mtk_wdma_desc {
|
||||
#define MTK_WDMA_GLO_CFG_TX_DMA_BUSY BIT(1)
|
||||
#define MTK_WDMA_GLO_CFG_RX_DMA_EN BIT(2)
|
||||
#define MTK_WDMA_GLO_CFG_RX_DMA_BUSY BIT(3)
|
||||
#define MTK_WDMA_GLO_CFG_RESV_BUFF GENMASK(23, 16)
|
||||
#define MTK_WDMA_GLO_CFG_RX_INFO3_PRERES BIT(26)
|
||||
#define MTK_WDMA_GLO_CFG_RX_INFO2_PRERES BIT(27)
|
||||
#define MTK_WDMA_GLO_CFG_RX_INFO1_PRERES BIT(28)
|
||||
|
||||
@@ -99,7 +99,7 @@ bool mlx5e_xsk_tx(struct mlx5e_xdpsq *sq, unsigned int budget)
|
||||
xdptxd.dma_addr = xsk_buff_raw_get_dma(pool, desc.addr);
|
||||
xdptxd.data = xsk_buff_raw_get_data(pool, desc.addr);
|
||||
xdptxd.len = desc.len;
|
||||
meta = xsk_buff_get_metadata(pool, desc.addr);
|
||||
meta = xsk_buff_get_metadata(pool, desc.addr, desc.options);
|
||||
|
||||
xsk_buff_raw_dma_sync_for_device(pool, xdptxd.dma_addr, xdptxd.len);
|
||||
|
||||
|
||||
@@ -689,11 +689,13 @@ static int mlx5e_rep_open(struct net_device *dev)
|
||||
if (err)
|
||||
goto unlock;
|
||||
|
||||
mutex_lock(&rep->esw->state_lock);
|
||||
if (!mlx5_modify_vport_admin_state(priv->mdev,
|
||||
MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
|
||||
rep->vport, 1,
|
||||
MLX5_VPORT_ADMIN_STATE_UP))
|
||||
netif_carrier_on(dev);
|
||||
mutex_unlock(&rep->esw->state_lock);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&priv->state_lock);
|
||||
@@ -708,10 +710,12 @@ static int mlx5e_rep_close(struct net_device *dev)
|
||||
int ret;
|
||||
|
||||
mutex_lock(&priv->state_lock);
|
||||
mutex_lock(&rep->esw->state_lock);
|
||||
mlx5_modify_vport_admin_state(priv->mdev,
|
||||
MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
|
||||
rep->vport, 1,
|
||||
MLX5_VPORT_ADMIN_STATE_DOWN);
|
||||
mutex_unlock(&rep->esw->state_lock);
|
||||
ret = mlx5e_close_locked(dev);
|
||||
mutex_unlock(&priv->state_lock);
|
||||
return ret;
|
||||
@@ -783,22 +787,25 @@ static int mlx5e_rep_change_carrier(struct net_device *dev, bool new_carrier)
|
||||
struct mlx5e_priv *priv = netdev_priv(dev);
|
||||
struct mlx5e_rep_priv *rpriv = priv->ppriv;
|
||||
struct mlx5_eswitch_rep *rep = rpriv->rep;
|
||||
int err;
|
||||
int err = 0;
|
||||
|
||||
mutex_lock(&rep->esw->state_lock);
|
||||
if (new_carrier) {
|
||||
err = mlx5_modify_vport_admin_state(priv->mdev, MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
|
||||
rep->vport, 1, MLX5_VPORT_ADMIN_STATE_UP);
|
||||
if (err)
|
||||
return err;
|
||||
goto unlock;
|
||||
netif_carrier_on(dev);
|
||||
} else {
|
||||
err = mlx5_modify_vport_admin_state(priv->mdev, MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
|
||||
rep->vport, 1, MLX5_VPORT_ADMIN_STATE_DOWN);
|
||||
if (err)
|
||||
return err;
|
||||
goto unlock;
|
||||
netif_carrier_off(dev);
|
||||
}
|
||||
return 0;
|
||||
unlock:
|
||||
mutex_unlock(&rep->esw->state_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
static const struct net_device_ops mlx5e_netdev_ops_rep = {
|
||||
@@ -1339,9 +1346,12 @@ static int mlx5e_uplink_rep_enable(struct mlx5e_priv *priv)
|
||||
|
||||
mlx5e_rep_tc_enable(priv);
|
||||
|
||||
if (MLX5_CAP_GEN(mdev, uplink_follow))
|
||||
if (MLX5_CAP_GEN(mdev, uplink_follow)) {
|
||||
mutex_lock(&mdev->priv.eswitch->state_lock);
|
||||
mlx5_modify_vport_admin_state(mdev, MLX5_VPORT_STATE_OP_MOD_UPLINK,
|
||||
0, 0, MLX5_VPORT_ADMIN_STATE_AUTO);
|
||||
mutex_unlock(&mdev->priv.eswitch->state_lock);
|
||||
}
|
||||
mlx5_lag_add_netdev(mdev, netdev);
|
||||
priv->events_nb.notifier_call = uplink_rep_async_event;
|
||||
mlx5_notifier_register(mdev, &priv->events_nb);
|
||||
|
||||
@@ -9,6 +9,28 @@ int mlx5_esw_adj_vport_modify(struct mlx5_core_dev *dev, u16 vport,
|
||||
{
|
||||
u32 in[MLX5_ST_SZ_DW(modify_vport_state_in)] = {};
|
||||
|
||||
lockdep_assert_held(&dev->priv.eswitch->state_lock);
|
||||
|
||||
if (MLX5_CAP_ESW(dev, esw_vport_state_max_tx_speed)) {
|
||||
u8 op_mod = MLX5_VPORT_STATE_OP_MOD_ESW_VPORT;
|
||||
struct mlx5_vport *esw_vport;
|
||||
u32 speed = 0;
|
||||
int err;
|
||||
|
||||
err = mlx5_query_vport_max_tx_speed(dev, op_mod, vport,
|
||||
true, &speed, NULL);
|
||||
if (err) {
|
||||
esw_vport = mlx5_eswitch_get_vport(dev->priv.eswitch,
|
||||
vport);
|
||||
speed = IS_ERR(esw_vport) ? 0 :
|
||||
esw_vport->agg_max_tx_speed;
|
||||
mlx5_core_dbg(dev,
|
||||
"Failed to query vport %d max tx speed, err=%d, using cached %u\n",
|
||||
vport, err, speed);
|
||||
}
|
||||
MLX5_SET(modify_vport_state_in, in, max_tx_speed, speed);
|
||||
}
|
||||
|
||||
MLX5_SET(modify_vport_state_in, in, opcode,
|
||||
MLX5_CMD_OP_MODIFY_VPORT_STATE);
|
||||
MLX5_SET(modify_vport_state_in, in, op_mod,
|
||||
|
||||
@@ -2567,6 +2567,7 @@ static void mlx5_esw_fdb_active(struct mlx5_eswitch *esw)
|
||||
mlx5_esw_fdb_drop_destroy(esw);
|
||||
mlx5_mpfs_enable(esw->dev);
|
||||
|
||||
mutex_lock(&esw->state_lock);
|
||||
mlx5_esw_for_each_vf_vport(esw, i, vport, U16_MAX) {
|
||||
if (!vport->adjacent)
|
||||
continue;
|
||||
@@ -2574,6 +2575,7 @@ static void mlx5_esw_fdb_active(struct mlx5_eswitch *esw)
|
||||
vport->vport);
|
||||
mlx5_esw_adj_vport_modify(esw->dev, vport->vport, true);
|
||||
}
|
||||
mutex_unlock(&esw->state_lock);
|
||||
|
||||
esw->offloads_inactive = false;
|
||||
esw_warn(esw->dev, "MPFS/FDB active\n");
|
||||
@@ -2587,6 +2589,7 @@ static void mlx5_esw_fdb_inactive(struct mlx5_eswitch *esw)
|
||||
mlx5_mpfs_disable(esw->dev);
|
||||
mlx5_esw_fdb_drop_create(esw);
|
||||
|
||||
mutex_lock(&esw->state_lock);
|
||||
mlx5_esw_for_each_vf_vport(esw, i, vport, U16_MAX) {
|
||||
if (!vport->adjacent)
|
||||
continue;
|
||||
@@ -2595,6 +2598,7 @@ static void mlx5_esw_fdb_inactive(struct mlx5_eswitch *esw)
|
||||
|
||||
mlx5_esw_adj_vport_modify(esw->dev, vport->vport, false);
|
||||
}
|
||||
mutex_unlock(&esw->state_lock);
|
||||
|
||||
esw->offloads_inactive = true;
|
||||
esw_warn(esw->dev, "MPFS/FDB inactive\n");
|
||||
|
||||
@@ -1471,6 +1471,7 @@ static void mlx5_lag_modify_device_vports_speed(struct mlx5_core_dev *mdev,
|
||||
if (!MLX5_CAP_ESW(mdev, esw_vport_state_max_tx_speed))
|
||||
return;
|
||||
|
||||
mutex_lock(&esw->state_lock);
|
||||
mlx5_esw_for_each_vport(esw, i, vport) {
|
||||
if (!vport)
|
||||
continue;
|
||||
@@ -1490,6 +1491,7 @@ static void mlx5_lag_modify_device_vports_speed(struct mlx5_core_dev *mdev,
|
||||
"Failed to set vport %d speed %d, err=%d\n",
|
||||
vport->vport, speed, ret);
|
||||
}
|
||||
mutex_unlock(&esw->state_lock);
|
||||
}
|
||||
|
||||
void mlx5_lag_set_vports_agg_speed(struct mlx5_lag *ldev)
|
||||
|
||||
@@ -89,6 +89,34 @@ int mlx5_modify_vport_admin_state(struct mlx5_core_dev *mdev, u8 opmod,
|
||||
{
|
||||
u32 in[MLX5_ST_SZ_DW(modify_vport_state_in)] = {};
|
||||
|
||||
#ifdef CONFIG_MLX5_ESWITCH
|
||||
lockdep_assert_held(&mdev->priv.eswitch->state_lock);
|
||||
#endif
|
||||
|
||||
if (MLX5_CAP_ESW(mdev, esw_vport_state_max_tx_speed) &&
|
||||
opmod == MLX5_VPORT_STATE_OP_MOD_ESW_VPORT &&
|
||||
vport != MLX5_VPORT_UPLINK) {
|
||||
u32 speed = 0;
|
||||
int err;
|
||||
|
||||
err = mlx5_query_vport_max_tx_speed(mdev, opmod, vport,
|
||||
other_vport, &speed, NULL);
|
||||
if (err) {
|
||||
#ifdef CONFIG_MLX5_ESWITCH
|
||||
struct mlx5_vport *esw_vport;
|
||||
|
||||
esw_vport = mlx5_eswitch_get_vport(mdev->priv.eswitch,
|
||||
vport);
|
||||
speed = IS_ERR(esw_vport) ? 0 :
|
||||
esw_vport->agg_max_tx_speed;
|
||||
#endif
|
||||
mlx5_core_dbg(mdev,
|
||||
"Failed to query vport %d max tx speed, err=%d, using cached %u\n",
|
||||
vport, err, speed);
|
||||
}
|
||||
MLX5_SET(modify_vport_state_in, in, max_tx_speed, speed);
|
||||
}
|
||||
|
||||
MLX5_SET(modify_vport_state_in, in, opcode,
|
||||
MLX5_CMD_OP_MODIFY_VPORT_STATE);
|
||||
MLX5_SET(modify_vport_state_in, in, op_mod, opmod);
|
||||
@@ -106,6 +134,10 @@ int mlx5_modify_vport_max_tx_speed(struct mlx5_core_dev *mdev, u8 opmod,
|
||||
u8 admin_state;
|
||||
int err;
|
||||
|
||||
#ifdef CONFIG_MLX5_ESWITCH
|
||||
lockdep_assert_held(&mdev->priv.eswitch->state_lock);
|
||||
#endif
|
||||
|
||||
err = mlx5_query_vport_admin_state(mdev, opmod, vport, other_vport,
|
||||
&admin_state);
|
||||
if (err)
|
||||
@@ -123,11 +155,11 @@ int mlx5_modify_vport_max_tx_speed(struct mlx5_core_dev *mdev, u8 opmod,
|
||||
}
|
||||
|
||||
int mlx5_query_vport_max_tx_speed(struct mlx5_core_dev *mdev, u8 op_mod,
|
||||
u16 vport, u8 other_vport, u32 *max_tx_speed)
|
||||
u16 vport, u8 other_vport,
|
||||
u32 *max_tx_speed, u8 *state)
|
||||
{
|
||||
u32 out[MLX5_ST_SZ_DW(query_vport_state_out)] = {};
|
||||
u32 in[MLX5_ST_SZ_DW(query_vport_state_in)] = {};
|
||||
u32 state;
|
||||
int err;
|
||||
|
||||
MLX5_SET(query_vport_state_in, in, opcode,
|
||||
@@ -140,13 +172,9 @@ int mlx5_query_vport_max_tx_speed(struct mlx5_core_dev *mdev, u8 op_mod,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
state = MLX5_GET(query_vport_state_out, out, state);
|
||||
if (state == VPORT_STATE_DOWN) {
|
||||
*max_tx_speed = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*max_tx_speed = MLX5_GET(query_vport_state_out, out, max_tx_speed);
|
||||
if (state)
|
||||
*state = MLX5_GET(query_vport_state_out, out, state);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mlx5_query_vport_max_tx_speed);
|
||||
|
||||
@@ -162,13 +162,18 @@ static int sparx5_port_stop(struct net_device *ndev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sparx5_set_rx_mode(struct net_device *dev)
|
||||
static int sparx5_set_rx_mode(struct net_device *dev,
|
||||
struct netdev_hw_addr_list *uc,
|
||||
struct netdev_hw_addr_list *mc)
|
||||
{
|
||||
struct sparx5_port *port = netdev_priv(dev);
|
||||
struct sparx5 *sparx5 = port->sparx5;
|
||||
|
||||
if (!test_bit(port->portno, sparx5->bridge_mask))
|
||||
__dev_mc_sync(dev, sparx5_mc_sync, sparx5_mc_unsync);
|
||||
return __hw_addr_sync_dev(mc, dev, sparx5_mc_sync,
|
||||
sparx5_mc_unsync);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sparx5_port_get_phys_port_name(struct net_device *dev,
|
||||
@@ -249,7 +254,7 @@ static const struct net_device_ops sparx5_port_netdev_ops = {
|
||||
.ndo_open = sparx5_port_open,
|
||||
.ndo_stop = sparx5_port_stop,
|
||||
.ndo_start_xmit = sparx5_port_xmit_impl,
|
||||
.ndo_set_rx_mode = sparx5_set_rx_mode,
|
||||
.ndo_set_rx_mode_async = sparx5_set_rx_mode,
|
||||
.ndo_get_phys_port_name = sparx5_port_get_phys_port_name,
|
||||
.ndo_set_mac_address = sparx5_set_mac_address,
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
|
||||
@@ -2077,8 +2077,9 @@ int sparx5_vcap_init(struct sparx5 *sparx5)
|
||||
dir = vcap_debugfs(sparx5->dev, sparx5->debugfs_root, ctrl);
|
||||
for (idx = 0; idx < consts->n_ports; ++idx)
|
||||
if (sparx5->ports[idx])
|
||||
vcap_port_debugfs(sparx5->dev, dir, ctrl,
|
||||
sparx5->ports[idx]->ndev);
|
||||
vcap_port_debugfs_portno(sparx5->dev, dir, ctrl,
|
||||
sparx5->ports[idx]->ndev,
|
||||
sparx5->ports[idx]->portno);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -400,6 +400,27 @@ void vcap_port_debugfs(struct device *dev, struct dentry *parent,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vcap_port_debugfs);
|
||||
|
||||
void vcap_port_debugfs_portno(struct device *dev,
|
||||
struct dentry *parent,
|
||||
struct vcap_control *vctrl,
|
||||
struct net_device *ndev,
|
||||
unsigned int portno)
|
||||
{
|
||||
struct vcap_port_debugfs_info *info;
|
||||
char name[16];
|
||||
|
||||
info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
return;
|
||||
|
||||
info->vctrl = vctrl;
|
||||
info->ndev = ndev;
|
||||
|
||||
snprintf(name, sizeof(name), "p%u", portno);
|
||||
debugfs_create_file(name, 0444, parent, info, &vcap_port_debugfs_fops);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vcap_port_debugfs_portno);
|
||||
|
||||
/* Show the full VCAP instance data (rules with all fields) */
|
||||
static int vcap_debugfs_show(struct seq_file *m, void *unused)
|
||||
{
|
||||
|
||||
@@ -18,6 +18,12 @@ void vcap_port_debugfs(struct device *dev, struct dentry *parent,
|
||||
struct vcap_control *vctrl,
|
||||
struct net_device *ndev);
|
||||
|
||||
void vcap_port_debugfs_portno(struct device *dev,
|
||||
struct dentry *parent,
|
||||
struct vcap_control *vctrl,
|
||||
struct net_device *ndev,
|
||||
unsigned int portno);
|
||||
|
||||
/* Create a debugFS entry for a vcap instance */
|
||||
struct dentry *vcap_debugfs(struct device *dev, struct dentry *parent,
|
||||
struct vcap_control *vctrl);
|
||||
@@ -30,6 +36,14 @@ static inline void vcap_port_debugfs(struct device *dev, struct dentry *parent,
|
||||
{
|
||||
}
|
||||
|
||||
static inline void vcap_port_debugfs_portno(struct device *dev,
|
||||
struct dentry *parent,
|
||||
struct vcap_control *vctrl,
|
||||
struct net_device *ndev,
|
||||
unsigned int portno)
|
||||
{
|
||||
}
|
||||
|
||||
static inline struct dentry *vcap_debugfs(struct device *dev,
|
||||
struct dentry *parent,
|
||||
struct vcap_control *vctrl)
|
||||
|
||||
@@ -182,6 +182,7 @@ static int mana_gd_query_max_resources(struct pci_dev *pdev)
|
||||
struct gdma_query_max_resources_resp resp = {};
|
||||
struct gdma_general_req req = {};
|
||||
unsigned int max_num_queues;
|
||||
unsigned int msix_vec_count;
|
||||
u8 bm_hostmode;
|
||||
u16 num_ports;
|
||||
int err;
|
||||
@@ -218,6 +219,24 @@ static int mana_gd_query_max_resources(struct pci_dev *pdev)
|
||||
gc->num_msix_usable = min(resp.max_msix, num_online_cpus() + 1);
|
||||
}
|
||||
|
||||
/* MSI-X vectors are allocated by index into the device MSI-X table, so
|
||||
* never ask for more than the table holds. It can be smaller than both
|
||||
* resp.max_msix and the CPU count.
|
||||
*/
|
||||
err = pci_msix_vec_count(pdev);
|
||||
if (err <= 0) {
|
||||
dev_err(gc->dev, "Failed to query MSI-X table size: %d\n", err);
|
||||
return err < 0 ? err : -ENOSPC;
|
||||
}
|
||||
msix_vec_count = err;
|
||||
|
||||
if (gc->num_msix_usable > msix_vec_count) {
|
||||
dev_info(gc->dev,
|
||||
"Limiting MSI-X vectors from %u to table size %u\n",
|
||||
gc->num_msix_usable, msix_vec_count);
|
||||
gc->num_msix_usable = msix_vec_count;
|
||||
}
|
||||
|
||||
if (gc->num_msix_usable <= 1)
|
||||
return -ENOSPC;
|
||||
|
||||
|
||||
@@ -2740,7 +2740,7 @@ static void nv_tx_timeout(struct net_device *dev, unsigned int txqueue)
|
||||
|
||||
netdev_info(dev, "Ring at %lx\n", (unsigned long)np->ring_addr);
|
||||
netdev_info(dev, "Dumping tx registers\n");
|
||||
for (i = 0; i <= np->register_size; i += 32) {
|
||||
for (i = 0; i + 32 <= np->register_size; i += 32) {
|
||||
netdev_info(dev,
|
||||
"%3x: %08x %08x %08x %08x "
|
||||
"%08x %08x %08x %08x\n",
|
||||
@@ -6221,7 +6221,7 @@ static int nv_suspend(struct device *device)
|
||||
netif_device_detach(dev);
|
||||
|
||||
/* save non-pci configuration space */
|
||||
for (i = 0; i <= np->register_size/sizeof(u32); i++)
|
||||
for (i = 0; i < np->register_size/sizeof(u32); i++)
|
||||
np->saved_config_space[i] = readl(base + i*sizeof(u32));
|
||||
|
||||
return 0;
|
||||
@@ -6236,7 +6236,7 @@ static int nv_resume(struct device *device)
|
||||
int i, rc = 0;
|
||||
|
||||
/* restore non-pci configuration space */
|
||||
for (i = 0; i <= np->register_size/sizeof(u32); i++)
|
||||
for (i = 0; i < np->register_size/sizeof(u32); i++)
|
||||
writel(np->saved_config_space[i], base+i*sizeof(u32));
|
||||
|
||||
if (np->driver_data & DEV_NEED_MSI_FIX)
|
||||
|
||||
@@ -555,6 +555,8 @@ enum ionic_lif_rdma_cap_stats {
|
||||
* @rdma.eq_qtype: RDMA Event Qtype
|
||||
* @rdma.stats_type: Supported statistics type
|
||||
* (enum ionic_lif_rdma_cap_stats)
|
||||
* @rdma.rsvd: Reserved byte
|
||||
* @rdma.rcq_sign_bit: RCQ sign bit
|
||||
* @rdma.rsvd1: Reserved byte(s)
|
||||
* @words: word access to struct contents
|
||||
*/
|
||||
@@ -600,7 +602,9 @@ union ionic_lif_identity {
|
||||
struct ionic_lif_logical_qtype cq_qtype;
|
||||
struct ionic_lif_logical_qtype eq_qtype;
|
||||
__le16 stats_type;
|
||||
u8 rsvd1[162];
|
||||
u8 rsvd;
|
||||
u8 rcq_sign_bit;
|
||||
u8 rsvd1[160];
|
||||
} __packed rdma;
|
||||
} __packed;
|
||||
__le32 words[478];
|
||||
|
||||
@@ -303,10 +303,10 @@ enum qede_agg_state {
|
||||
};
|
||||
|
||||
struct qede_agg_info {
|
||||
/* rx_buf is a data buffer that can be placed / consumed from rx bd
|
||||
* chain. It has two purposes: We will preallocate the data buffer
|
||||
* for each aggregation when we open the interface and will place this
|
||||
* buffer on the rx-bd-ring when we receive TPA_START. We don't want
|
||||
/* buffer is used to retain the Rx consumer descriptor when a TPA
|
||||
* session starts. If the SKB allocation fails during TPA_START,
|
||||
* we use this saved buffer to safely recycle the physical page
|
||||
* back into the rx-bd-ring via qede_reuse_page(). We don't want
|
||||
* to be in a state where allocation fails, as we can't reuse the
|
||||
* consumer buffer in the rx-chain since FW may still be writing to it
|
||||
* (since header needs to be modified for TPA).
|
||||
|
||||
@@ -850,6 +850,7 @@ static void qede_tpa_start(struct qede_dev *edev,
|
||||
pad, false);
|
||||
tpa_info->buffer.page_offset = sw_rx_data_cons->page_offset;
|
||||
tpa_info->buffer.mapping = sw_rx_data_cons->mapping;
|
||||
tpa_info->buffer.data = sw_rx_data_cons->data;
|
||||
|
||||
if (unlikely(!tpa_info->skb)) {
|
||||
DP_NOTICE(edev, "Failed to allocate SKB for gro\n");
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "qlcnic.h"
|
||||
#include "qlcnic_hw.h"
|
||||
#include <linux/unaligned.h>
|
||||
|
||||
struct crb_addr_pair {
|
||||
u32 addr;
|
||||
@@ -740,159 +741,212 @@ qlcnic_has_mn(struct qlcnic_adapter *adapter)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
struct uni_table_desc *qlcnic_get_table_desc(const u8 *unirom, int section)
|
||||
#define FILEHEADER_SIZE (14 * 4)
|
||||
#define QLCNIC_UNI_DIR_TYPE_OFF (8 * sizeof(__le32))
|
||||
#define QLCNIC_UNI_DIR_ENTRY_MIN_SIZE (9 * sizeof(__le32))
|
||||
#define QLCNIC_UNI_PRODUCT_ENTRY_MIN_SIZE \
|
||||
((QLCNIC_UNI_FIRMWARE_IDX_OFF + 1) * sizeof(__le32))
|
||||
#define QLCNIC_UNI_VERSION_TAIL_SIZE 17
|
||||
#define QLCNIC_UNI_BOOTLD_SIZE \
|
||||
(QLCNIC_IMAGE_START - QLCNIC_BOOTLD_START)
|
||||
|
||||
struct qlcnic_uni_data {
|
||||
u32 offset;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
static bool qlcnic_rom_range_valid(size_t size, size_t offset, size_t len)
|
||||
{
|
||||
u32 i, entries;
|
||||
struct uni_table_desc *directory = (struct uni_table_desc *) &unirom[0];
|
||||
entries = le32_to_cpu(directory->num_entries);
|
||||
|
||||
for (i = 0; i < entries; i++) {
|
||||
|
||||
u32 offs = le32_to_cpu(directory->findex) +
|
||||
i * le32_to_cpu(directory->entry_size);
|
||||
u32 tab_type = le32_to_cpu(*((__le32 *)&unirom[offs] + 8));
|
||||
|
||||
if (tab_type == section)
|
||||
return (struct uni_table_desc *) &unirom[offs];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return offset <= size && len <= size - offset;
|
||||
}
|
||||
|
||||
#define FILEHEADER_SIZE (14 * 4)
|
||||
static bool qlcnic_rom_table_valid(size_t size, u32 offset, u32 entries,
|
||||
u32 entry_size, u32 min_entry_size)
|
||||
{
|
||||
if (entry_size < min_entry_size || offset > size)
|
||||
return false;
|
||||
|
||||
return entries <= (size - offset) / entry_size;
|
||||
}
|
||||
|
||||
static int qlcnic_get_directory(struct qlcnic_adapter *adapter,
|
||||
size_t *offset, u32 *entries, u32 *entry_size)
|
||||
{
|
||||
const struct firmware *fw = adapter->fw;
|
||||
const u8 *directory = fw->data;
|
||||
|
||||
if (fw->size < FILEHEADER_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
*offset = get_unaligned_le32(directory +
|
||||
offsetof(struct uni_table_desc, findex));
|
||||
*entries = get_unaligned_le32(directory +
|
||||
offsetof(struct uni_table_desc, num_entries));
|
||||
*entry_size = get_unaligned_le32(directory +
|
||||
offsetof(struct uni_table_desc, entry_size));
|
||||
|
||||
if (!qlcnic_rom_table_valid(fw->size, *offset, *entries, *entry_size,
|
||||
QLCNIC_UNI_DIR_ENTRY_MIN_SIZE))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qlcnic_get_table_desc(struct qlcnic_adapter *adapter, int section,
|
||||
size_t *desc_offset)
|
||||
{
|
||||
const u8 *unirom = adapter->fw->data;
|
||||
size_t directory_offset;
|
||||
u32 entries, entry_size;
|
||||
size_t i;
|
||||
int ret;
|
||||
|
||||
ret = qlcnic_get_directory(adapter, &directory_offset, &entries,
|
||||
&entry_size);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < entries; i++) {
|
||||
size_t offset = directory_offset + i * entry_size;
|
||||
u32 table_type;
|
||||
|
||||
table_type = get_unaligned_le32(unirom + offset +
|
||||
QLCNIC_UNI_DIR_TYPE_OFF);
|
||||
if (table_type == section) {
|
||||
*desc_offset = offset;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int
|
||||
qlcnic_validate_header(struct qlcnic_adapter *adapter)
|
||||
{
|
||||
const u8 *unirom = adapter->fw->data;
|
||||
struct uni_table_desc *directory = (struct uni_table_desc *) &unirom[0];
|
||||
u32 entries, entry_size, tab_size, fw_file_size;
|
||||
u32 entries, entry_size;
|
||||
size_t offset;
|
||||
|
||||
fw_file_size = adapter->fw->size;
|
||||
return qlcnic_get_directory(adapter, &offset, &entries, &entry_size);
|
||||
}
|
||||
|
||||
if (fw_file_size < FILEHEADER_SIZE)
|
||||
static int qlcnic_get_data_desc(struct qlcnic_adapter *adapter, u32 section,
|
||||
u32 index_offset, struct qlcnic_uni_data *data)
|
||||
{
|
||||
size_t table_desc_offset, table_offset, desc_offset;
|
||||
const struct firmware *fw = adapter->fw;
|
||||
const u8 *unirom = fw->data;
|
||||
size_t product_index_offset;
|
||||
u32 entries, entry_size, idx;
|
||||
int ret;
|
||||
|
||||
product_index_offset = adapter->file_prd_off +
|
||||
(size_t)index_offset * sizeof(__le32);
|
||||
if (!qlcnic_rom_range_valid(fw->size, product_index_offset,
|
||||
sizeof(__le32)))
|
||||
return -EINVAL;
|
||||
|
||||
entries = le32_to_cpu(directory->num_entries);
|
||||
entry_size = le32_to_cpu(directory->entry_size);
|
||||
tab_size = le32_to_cpu(directory->findex) + (entries * entry_size);
|
||||
idx = get_unaligned_le32(unirom + product_index_offset);
|
||||
ret = qlcnic_get_table_desc(adapter, section, &table_desc_offset);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (fw_file_size < tab_size)
|
||||
table_offset = get_unaligned_le32(unirom + table_desc_offset +
|
||||
offsetof(struct uni_table_desc, findex));
|
||||
entries = get_unaligned_le32(unirom + table_desc_offset +
|
||||
offsetof(struct uni_table_desc, num_entries));
|
||||
entry_size = get_unaligned_le32(unirom + table_desc_offset +
|
||||
offsetof(struct uni_table_desc, entry_size));
|
||||
if (!qlcnic_rom_table_valid(fw->size, table_offset, entries,
|
||||
entry_size, sizeof(struct uni_data_desc)) ||
|
||||
idx >= entries)
|
||||
return -EINVAL;
|
||||
|
||||
desc_offset = table_offset + (size_t)idx * entry_size;
|
||||
data->offset = get_unaligned_le32(unirom + desc_offset +
|
||||
offsetof(struct uni_data_desc, findex));
|
||||
data->size = get_unaligned_le32(unirom + desc_offset +
|
||||
offsetof(struct uni_data_desc, size));
|
||||
|
||||
if (!qlcnic_rom_range_valid(fw->size, data->offset, data->size))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
qlcnic_validate_bootld(struct qlcnic_adapter *adapter)
|
||||
static int qlcnic_validate_bootld(struct qlcnic_adapter *adapter)
|
||||
{
|
||||
struct uni_table_desc *tab_desc;
|
||||
struct uni_data_desc *descr;
|
||||
u32 offs, tab_size, data_size, idx;
|
||||
const u8 *unirom = adapter->fw->data;
|
||||
__le32 temp;
|
||||
struct qlcnic_uni_data data;
|
||||
int ret;
|
||||
|
||||
temp = *((__le32 *)&unirom[adapter->file_prd_off] +
|
||||
QLCNIC_UNI_BOOTLD_IDX_OFF);
|
||||
idx = le32_to_cpu(temp);
|
||||
tab_desc = qlcnic_get_table_desc(unirom, QLCNIC_UNI_DIR_SECT_BOOTLD);
|
||||
ret = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_BOOTLD,
|
||||
QLCNIC_UNI_BOOTLD_IDX_OFF, &data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!tab_desc)
|
||||
return -EINVAL;
|
||||
|
||||
tab_size = le32_to_cpu(tab_desc->findex) +
|
||||
le32_to_cpu(tab_desc->entry_size) * (idx + 1);
|
||||
|
||||
if (adapter->fw->size < tab_size)
|
||||
return -EINVAL;
|
||||
|
||||
offs = le32_to_cpu(tab_desc->findex) +
|
||||
le32_to_cpu(tab_desc->entry_size) * idx;
|
||||
descr = (struct uni_data_desc *)&unirom[offs];
|
||||
|
||||
data_size = le32_to_cpu(descr->findex) + le32_to_cpu(descr->size);
|
||||
|
||||
if (adapter->fw->size < data_size)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
return data.size < QLCNIC_UNI_BOOTLD_SIZE ? -EINVAL : 0;
|
||||
}
|
||||
|
||||
static int
|
||||
qlcnic_validate_fw(struct qlcnic_adapter *adapter)
|
||||
static int qlcnic_validate_fw(struct qlcnic_adapter *adapter)
|
||||
{
|
||||
struct uni_table_desc *tab_desc;
|
||||
struct uni_data_desc *descr;
|
||||
const u8 *unirom = adapter->fw->data;
|
||||
u32 offs, tab_size, data_size, idx;
|
||||
__le32 temp;
|
||||
struct qlcnic_uni_data data;
|
||||
int ret;
|
||||
|
||||
temp = *((__le32 *)&unirom[adapter->file_prd_off] +
|
||||
QLCNIC_UNI_FIRMWARE_IDX_OFF);
|
||||
idx = le32_to_cpu(temp);
|
||||
tab_desc = qlcnic_get_table_desc(unirom, QLCNIC_UNI_DIR_SECT_FW);
|
||||
ret = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_FW,
|
||||
QLCNIC_UNI_FIRMWARE_IDX_OFF, &data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!tab_desc)
|
||||
return -EINVAL;
|
||||
|
||||
tab_size = le32_to_cpu(tab_desc->findex) +
|
||||
le32_to_cpu(tab_desc->entry_size) * (idx + 1);
|
||||
|
||||
if (adapter->fw->size < tab_size)
|
||||
return -EINVAL;
|
||||
|
||||
offs = le32_to_cpu(tab_desc->findex) +
|
||||
le32_to_cpu(tab_desc->entry_size) * idx;
|
||||
descr = (struct uni_data_desc *)&unirom[offs];
|
||||
data_size = le32_to_cpu(descr->findex) + le32_to_cpu(descr->size);
|
||||
|
||||
if (adapter->fw->size < data_size)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
return data.size < QLCNIC_UNI_VERSION_TAIL_SIZE ? -EINVAL : 0;
|
||||
}
|
||||
|
||||
static int
|
||||
qlcnic_validate_product_offs(struct qlcnic_adapter *adapter)
|
||||
{
|
||||
struct uni_table_desc *ptab_descr;
|
||||
size_t table_desc_offset, table_offset;
|
||||
const u8 *unirom = adapter->fw->data;
|
||||
int mn_present = qlcnic_has_mn(adapter);
|
||||
u32 entries, entry_size, tab_size, i;
|
||||
__le32 temp;
|
||||
u32 entries, entry_size;
|
||||
size_t i;
|
||||
int ret;
|
||||
|
||||
ptab_descr = qlcnic_get_table_desc(unirom,
|
||||
QLCNIC_UNI_DIR_SECT_PRODUCT_TBL);
|
||||
if (!ptab_descr)
|
||||
return -EINVAL;
|
||||
ret = qlcnic_get_table_desc(adapter, QLCNIC_UNI_DIR_SECT_PRODUCT_TBL,
|
||||
&table_desc_offset);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
entries = le32_to_cpu(ptab_descr->num_entries);
|
||||
entry_size = le32_to_cpu(ptab_descr->entry_size);
|
||||
tab_size = le32_to_cpu(ptab_descr->findex) + (entries * entry_size);
|
||||
|
||||
if (adapter->fw->size < tab_size)
|
||||
table_offset = get_unaligned_le32(unirom + table_desc_offset +
|
||||
offsetof(struct uni_table_desc, findex));
|
||||
entries = get_unaligned_le32(unirom + table_desc_offset +
|
||||
offsetof(struct uni_table_desc, num_entries));
|
||||
entry_size = get_unaligned_le32(unirom + table_desc_offset +
|
||||
offsetof(struct uni_table_desc, entry_size));
|
||||
if (!qlcnic_rom_table_valid(adapter->fw->size, table_offset, entries,
|
||||
entry_size,
|
||||
QLCNIC_UNI_PRODUCT_ENTRY_MIN_SIZE))
|
||||
return -EINVAL;
|
||||
|
||||
nomn:
|
||||
for (i = 0; i < entries; i++) {
|
||||
|
||||
u32 flags, file_chiprev, offs;
|
||||
size_t offset = table_offset + i * entry_size;
|
||||
u8 chiprev = adapter->ahw->revision_id;
|
||||
u32 flags, file_chiprev;
|
||||
u32 flagbit;
|
||||
|
||||
offs = le32_to_cpu(ptab_descr->findex) +
|
||||
i * le32_to_cpu(ptab_descr->entry_size);
|
||||
temp = *((__le32 *)&unirom[offs] + QLCNIC_UNI_FLAGS_OFF);
|
||||
flags = le32_to_cpu(temp);
|
||||
temp = *((__le32 *)&unirom[offs] + QLCNIC_UNI_CHIP_REV_OFF);
|
||||
file_chiprev = le32_to_cpu(temp);
|
||||
flags = get_unaligned_le32(unirom + offset +
|
||||
QLCNIC_UNI_FLAGS_OFF * sizeof(__le32));
|
||||
file_chiprev = get_unaligned_le32(unirom + offset +
|
||||
QLCNIC_UNI_CHIP_REV_OFF *
|
||||
sizeof(__le32));
|
||||
|
||||
flagbit = mn_present ? 1 : 2;
|
||||
|
||||
if ((chiprev == file_chiprev) &&
|
||||
((1ULL << flagbit) & flags)) {
|
||||
adapter->file_prd_off = offs;
|
||||
if (offset > U32_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
adapter->file_prd_off = offset;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -933,93 +987,81 @@ qlcnic_validate_unified_romimage(struct qlcnic_adapter *adapter)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
struct uni_data_desc *qlcnic_get_data_desc(struct qlcnic_adapter *adapter,
|
||||
u32 section, u32 idx_offset)
|
||||
{
|
||||
const u8 *unirom = adapter->fw->data;
|
||||
struct uni_table_desc *tab_desc;
|
||||
u32 offs, idx;
|
||||
__le32 temp;
|
||||
|
||||
temp = *((__le32 *)&unirom[adapter->file_prd_off] + idx_offset);
|
||||
idx = le32_to_cpu(temp);
|
||||
|
||||
tab_desc = qlcnic_get_table_desc(unirom, section);
|
||||
|
||||
if (tab_desc == NULL)
|
||||
return NULL;
|
||||
|
||||
offs = le32_to_cpu(tab_desc->findex) +
|
||||
le32_to_cpu(tab_desc->entry_size) * idx;
|
||||
|
||||
return (struct uni_data_desc *)&unirom[offs];
|
||||
}
|
||||
|
||||
static u8 *
|
||||
qlcnic_get_bootld_offs(struct qlcnic_adapter *adapter)
|
||||
static int qlcnic_get_bootld_data(struct qlcnic_adapter *adapter,
|
||||
const u8 **bootld)
|
||||
{
|
||||
u32 offs = QLCNIC_BOOTLD_START;
|
||||
struct uni_data_desc *data_desc;
|
||||
struct qlcnic_uni_data data;
|
||||
int ret;
|
||||
|
||||
data_desc = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_BOOTLD,
|
||||
QLCNIC_UNI_BOOTLD_IDX_OFF);
|
||||
if (adapter->ahw->fw_type == QLCNIC_UNIFIED_ROMIMAGE) {
|
||||
ret = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_BOOTLD,
|
||||
QLCNIC_UNI_BOOTLD_IDX_OFF, &data);
|
||||
if (ret || data.size < QLCNIC_UNI_BOOTLD_SIZE)
|
||||
return -EINVAL;
|
||||
offs = data.offset;
|
||||
} else if (!qlcnic_rom_range_valid(adapter->fw->size, offs,
|
||||
QLCNIC_UNI_BOOTLD_SIZE)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (adapter->ahw->fw_type == QLCNIC_UNIFIED_ROMIMAGE)
|
||||
offs = le32_to_cpu(data_desc->findex);
|
||||
|
||||
return (u8 *)&adapter->fw->data[offs];
|
||||
*bootld = adapter->fw->data + offs;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 *
|
||||
qlcnic_get_fw_offs(struct qlcnic_adapter *adapter)
|
||||
static int qlcnic_get_fw_data(struct qlcnic_adapter *adapter,
|
||||
const u8 **image, u32 *image_size)
|
||||
{
|
||||
u32 offs = QLCNIC_IMAGE_START;
|
||||
struct uni_data_desc *data_desc;
|
||||
struct qlcnic_uni_data data;
|
||||
int ret;
|
||||
|
||||
data_desc = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_FW,
|
||||
QLCNIC_UNI_FIRMWARE_IDX_OFF);
|
||||
if (adapter->ahw->fw_type == QLCNIC_UNIFIED_ROMIMAGE)
|
||||
offs = le32_to_cpu(data_desc->findex);
|
||||
if (adapter->ahw->fw_type == QLCNIC_UNIFIED_ROMIMAGE) {
|
||||
ret = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_FW,
|
||||
QLCNIC_UNI_FIRMWARE_IDX_OFF, &data);
|
||||
if (ret)
|
||||
return ret;
|
||||
offs = data.offset;
|
||||
*image_size = data.size;
|
||||
} else {
|
||||
if (!qlcnic_rom_range_valid(adapter->fw->size,
|
||||
QLCNIC_FW_SIZE_OFFSET,
|
||||
sizeof(__le32)))
|
||||
return -EINVAL;
|
||||
*image_size = get_unaligned_le32(adapter->fw->data +
|
||||
QLCNIC_FW_SIZE_OFFSET);
|
||||
}
|
||||
|
||||
return (u8 *)&adapter->fw->data[offs];
|
||||
}
|
||||
if (!qlcnic_rom_range_valid(adapter->fw->size, offs, *image_size))
|
||||
return -EINVAL;
|
||||
|
||||
static u32 qlcnic_get_fw_size(struct qlcnic_adapter *adapter)
|
||||
{
|
||||
struct uni_data_desc *data_desc;
|
||||
const u8 *unirom = adapter->fw->data;
|
||||
|
||||
data_desc = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_FW,
|
||||
QLCNIC_UNI_FIRMWARE_IDX_OFF);
|
||||
|
||||
if (adapter->ahw->fw_type == QLCNIC_UNIFIED_ROMIMAGE)
|
||||
return le32_to_cpu(data_desc->size);
|
||||
else
|
||||
return le32_to_cpu(*(__le32 *)&unirom[QLCNIC_FW_SIZE_OFFSET]);
|
||||
*image = adapter->fw->data + offs;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 qlcnic_get_fw_version(struct qlcnic_adapter *adapter)
|
||||
{
|
||||
struct uni_data_desc *fw_data_desc;
|
||||
char ver_str[QLCNIC_UNI_VERSION_TAIL_SIZE + 1];
|
||||
const struct firmware *fw = adapter->fw;
|
||||
struct qlcnic_uni_data data;
|
||||
u32 major, minor, sub;
|
||||
__le32 version_offset;
|
||||
const u8 *ver_str;
|
||||
int i, ret;
|
||||
|
||||
if (adapter->ahw->fw_type != QLCNIC_UNIFIED_ROMIMAGE) {
|
||||
version_offset = *(__le32 *)&fw->data[QLCNIC_FW_VERSION_OFFSET];
|
||||
return le32_to_cpu(version_offset);
|
||||
}
|
||||
if (adapter->ahw->fw_type != QLCNIC_UNIFIED_ROMIMAGE)
|
||||
return get_unaligned_le32(fw->data + QLCNIC_FW_VERSION_OFFSET);
|
||||
|
||||
fw_data_desc = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_FW,
|
||||
QLCNIC_UNI_FIRMWARE_IDX_OFF);
|
||||
ver_str = fw->data + le32_to_cpu(fw_data_desc->findex) +
|
||||
le32_to_cpu(fw_data_desc->size) - 17;
|
||||
ret = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_FW,
|
||||
QLCNIC_UNI_FIRMWARE_IDX_OFF, &data);
|
||||
if (ret || data.size < QLCNIC_UNI_VERSION_TAIL_SIZE)
|
||||
return 0;
|
||||
|
||||
memcpy(ver_str, fw->data + data.offset + data.size -
|
||||
QLCNIC_UNI_VERSION_TAIL_SIZE,
|
||||
QLCNIC_UNI_VERSION_TAIL_SIZE);
|
||||
ver_str[QLCNIC_UNI_VERSION_TAIL_SIZE] = '\0';
|
||||
|
||||
for (i = 0; i < 12; i++) {
|
||||
if (!strncmp(&ver_str[i], "REV=", 4)) {
|
||||
if (!strncmp(ver_str + i, "REV=", 4)) {
|
||||
ret = sscanf(&ver_str[i+4], "%u.%u.%u ",
|
||||
&major, &minor, &sub);
|
||||
if (ret != 3)
|
||||
@@ -1034,18 +1076,15 @@ static u32 qlcnic_get_fw_version(struct qlcnic_adapter *adapter)
|
||||
|
||||
static u32 qlcnic_get_bios_version(struct qlcnic_adapter *adapter)
|
||||
{
|
||||
const struct firmware *fw = adapter->fw;
|
||||
u32 bios_ver, prd_off = adapter->file_prd_off;
|
||||
u8 *version_offset;
|
||||
__le32 temp;
|
||||
const struct firmware *fw = adapter->fw;
|
||||
|
||||
if (adapter->ahw->fw_type != QLCNIC_UNIFIED_ROMIMAGE) {
|
||||
version_offset = (u8 *)&fw->data[QLCNIC_BIOS_VERSION_OFFSET];
|
||||
return le32_to_cpu(*(__le32 *)version_offset);
|
||||
}
|
||||
if (adapter->ahw->fw_type != QLCNIC_UNIFIED_ROMIMAGE)
|
||||
return get_unaligned_le32(fw->data + QLCNIC_BIOS_VERSION_OFFSET);
|
||||
|
||||
temp = *((__le32 *)(&fw->data[prd_off]) + QLCNIC_UNI_BIOS_VERSION_OFF);
|
||||
bios_ver = le32_to_cpu(temp);
|
||||
bios_ver = get_unaligned_le32(fw->data + prd_off +
|
||||
QLCNIC_UNI_BIOS_VERSION_OFF *
|
||||
sizeof(__le32));
|
||||
|
||||
return (bios_ver << 16) + ((bios_ver >> 8) & 0xff00) + (bios_ver >> 24);
|
||||
}
|
||||
@@ -1106,24 +1145,26 @@ static const char *fw_name[] = {
|
||||
int
|
||||
qlcnic_load_firmware(struct qlcnic_adapter *adapter)
|
||||
{
|
||||
__le64 *ptr64;
|
||||
u32 i, flashaddr, size;
|
||||
const struct firmware *fw = adapter->fw;
|
||||
struct pci_dev *pdev = adapter->pdev;
|
||||
const u8 *bootld, *image;
|
||||
u32 i, flashaddr, image_size;
|
||||
int ret;
|
||||
|
||||
dev_info(&pdev->dev, "loading firmware from %s\n",
|
||||
fw_name[adapter->ahw->fw_type]);
|
||||
|
||||
if (fw) {
|
||||
u32 words, remainder;
|
||||
u64 data;
|
||||
|
||||
size = (QLCNIC_IMAGE_START - QLCNIC_BOOTLD_START) / 8;
|
||||
|
||||
ptr64 = (__le64 *)qlcnic_get_bootld_offs(adapter);
|
||||
ret = qlcnic_get_bootld_data(adapter, &bootld);
|
||||
if (ret)
|
||||
return ret;
|
||||
flashaddr = QLCNIC_BOOTLD_START;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
data = le64_to_cpu(ptr64[i]);
|
||||
for (i = 0; i < QLCNIC_UNI_BOOTLD_SIZE / sizeof(u64); i++) {
|
||||
data = get_unaligned_le64(bootld + i * sizeof(u64));
|
||||
|
||||
if (qlcnic_pci_mem_write_2M(adapter, flashaddr, data))
|
||||
return -EIO;
|
||||
@@ -1131,13 +1172,15 @@ qlcnic_load_firmware(struct qlcnic_adapter *adapter)
|
||||
flashaddr += 8;
|
||||
}
|
||||
|
||||
size = qlcnic_get_fw_size(adapter) / 8;
|
||||
|
||||
ptr64 = (__le64 *)qlcnic_get_fw_offs(adapter);
|
||||
ret = qlcnic_get_fw_data(adapter, &image, &image_size);
|
||||
if (ret)
|
||||
return ret;
|
||||
words = image_size / sizeof(u64);
|
||||
remainder = image_size % sizeof(u64);
|
||||
flashaddr = QLCNIC_IMAGE_START;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
data = le64_to_cpu(ptr64[i]);
|
||||
for (i = 0; i < words; i++) {
|
||||
data = get_unaligned_le64(image + i * sizeof(u64));
|
||||
|
||||
if (qlcnic_pci_mem_write_2M(adapter,
|
||||
flashaddr, data))
|
||||
@@ -1146,9 +1189,11 @@ qlcnic_load_firmware(struct qlcnic_adapter *adapter)
|
||||
flashaddr += 8;
|
||||
}
|
||||
|
||||
size = qlcnic_get_fw_size(adapter) % 8;
|
||||
if (size) {
|
||||
data = le64_to_cpu(ptr64[i]);
|
||||
if (remainder) {
|
||||
__le64 tail = 0;
|
||||
|
||||
memcpy(&tail, image + words * sizeof(u64), remainder);
|
||||
data = le64_to_cpu(tail);
|
||||
|
||||
if (qlcnic_pci_mem_write_2M(adapter,
|
||||
flashaddr, data))
|
||||
@@ -1156,10 +1201,9 @@ qlcnic_load_firmware(struct qlcnic_adapter *adapter)
|
||||
}
|
||||
|
||||
} else {
|
||||
u64 data;
|
||||
u32 hi, lo;
|
||||
int ret;
|
||||
struct qlcnic_flt_entry bootld_entry;
|
||||
u32 hi, lo, size;
|
||||
u64 data;
|
||||
|
||||
ret = qlcnic_get_flt_entry(adapter, QLCNIC_BOOTLD_REGION,
|
||||
&bootld_entry);
|
||||
@@ -1200,26 +1244,33 @@ qlcnic_load_firmware(struct qlcnic_adapter *adapter)
|
||||
static int
|
||||
qlcnic_validate_firmware(struct qlcnic_adapter *adapter)
|
||||
{
|
||||
u32 val;
|
||||
u32 ver, bios, min_size;
|
||||
struct pci_dev *pdev = adapter->pdev;
|
||||
const struct firmware *fw = adapter->fw;
|
||||
struct pci_dev *pdev = adapter->pdev;
|
||||
u8 fw_type = adapter->ahw->fw_type;
|
||||
u32 ver, bios, min_size;
|
||||
const u8 *data;
|
||||
u32 data_size;
|
||||
u32 val;
|
||||
|
||||
if (fw_type == QLCNIC_UNIFIED_ROMIMAGE)
|
||||
min_size = QLCNIC_UNI_FW_MIN_SIZE;
|
||||
else
|
||||
min_size = QLCNIC_FW_MIN_SIZE;
|
||||
|
||||
if (fw->size < min_size)
|
||||
return -EINVAL;
|
||||
|
||||
if (fw_type == QLCNIC_UNIFIED_ROMIMAGE) {
|
||||
if (qlcnic_validate_unified_romimage(adapter))
|
||||
return -EINVAL;
|
||||
|
||||
min_size = QLCNIC_UNI_FW_MIN_SIZE;
|
||||
} else {
|
||||
val = le32_to_cpu(*(__le32 *)&fw->data[QLCNIC_FW_MAGIC_OFFSET]);
|
||||
val = get_unaligned_le32(fw->data + QLCNIC_FW_MAGIC_OFFSET);
|
||||
if (val != QLCNIC_BDINFO_MAGIC)
|
||||
return -EINVAL;
|
||||
|
||||
min_size = QLCNIC_FW_MIN_SIZE;
|
||||
}
|
||||
|
||||
if (fw->size < min_size)
|
||||
if (qlcnic_get_bootld_data(adapter, &data) ||
|
||||
qlcnic_get_fw_data(adapter, &data, &data_size))
|
||||
return -EINVAL;
|
||||
|
||||
val = qlcnic_get_fw_version(adapter);
|
||||
|
||||
@@ -394,6 +394,7 @@ struct sk_buff *rmnet_map_deaggregate(struct sk_buff *skb,
|
||||
if (!skbn)
|
||||
return NULL;
|
||||
|
||||
skbn->dev = skb->dev;
|
||||
skb_reserve(skbn, RMNET_MAP_DEAGGR_HEADROOM);
|
||||
skb_put(skbn, packet_len);
|
||||
memcpy(skbn->data, skb->data, packet_len);
|
||||
|
||||
@@ -1303,7 +1303,8 @@ static int rswitch_etha_mii_write_c22(struct mii_bus *bus, int phyad,
|
||||
/* Call of_node_put(port) after done */
|
||||
static struct device_node *rswitch_get_port_node(struct rswitch_device *rdev)
|
||||
{
|
||||
struct device_node *ports, *port;
|
||||
struct device_node *port = NULL;
|
||||
struct device_node *ports;
|
||||
int err = 0;
|
||||
u32 index;
|
||||
|
||||
@@ -1312,17 +1313,16 @@ static struct device_node *rswitch_get_port_node(struct rswitch_device *rdev)
|
||||
if (!ports)
|
||||
return NULL;
|
||||
|
||||
for_each_available_child_of_node(ports, port) {
|
||||
err = of_property_read_u32(port, "reg", &index);
|
||||
if (err < 0) {
|
||||
port = NULL;
|
||||
goto out;
|
||||
}
|
||||
if (index == rdev->etha->index)
|
||||
for_each_available_child_of_node_scoped(ports, child) {
|
||||
err = of_property_read_u32(child, "reg", &index);
|
||||
if (err < 0)
|
||||
break;
|
||||
if (index == rdev->etha->index) {
|
||||
port = of_node_get(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
of_node_put(ports);
|
||||
|
||||
return port;
|
||||
|
||||
@@ -194,7 +194,7 @@ static void dwmac1000_set_filter(struct mac_device_info *hw,
|
||||
dwmac1000_set_mchash(ioaddr, mc_filter, mcbitslog2);
|
||||
|
||||
/* Handle multiple unicast addresses (perfect filtering) */
|
||||
if (netdev_uc_count(dev) > perfect_addr_number)
|
||||
if (netdev_uc_count(dev) + 1 > perfect_addr_number)
|
||||
/* Switch to promiscuous mode if more than unicast
|
||||
* addresses are requested than supported by hardware.
|
||||
*/
|
||||
|
||||
@@ -521,7 +521,7 @@ static void dwmac4_set_filter(struct mac_device_info *hw,
|
||||
value |= GMAC_PACKET_FILTER_HPF;
|
||||
|
||||
/* Handle multiple unicast addresses */
|
||||
if (netdev_uc_count(dev) > hw->unicast_filter_entries) {
|
||||
if (netdev_uc_count(dev) + 1 > hw->unicast_filter_entries) {
|
||||
/* Switch to promiscuous mode if more than 128 addrs
|
||||
* are required
|
||||
*/
|
||||
|
||||
@@ -532,7 +532,7 @@ static void dwxgmac2_set_filter(struct mac_device_info *hw,
|
||||
dwxgmac2_set_mchash(ioaddr, mc_filter, mcbitslog2);
|
||||
|
||||
/* Handle multiple unicast addresses */
|
||||
if (netdev_uc_count(dev) > hw->unicast_filter_entries) {
|
||||
if (netdev_uc_count(dev) + 1 > hw->unicast_filter_entries) {
|
||||
value |= XGMAC_FILTER_PR;
|
||||
} else {
|
||||
struct netdev_hw_addr *ha;
|
||||
|
||||
@@ -265,8 +265,6 @@ struct stmmac_priv {
|
||||
u32 rx_coal_frames[MTL_MAX_RX_QUEUES];
|
||||
|
||||
int hwts_tx_en;
|
||||
/* skb_shinfo(skb)->gso_type types that we handle */
|
||||
unsigned int gso_enabled_types;
|
||||
bool tx_path_in_lpi_mode;
|
||||
bool sph_active;
|
||||
bool sph_capable;
|
||||
|
||||
@@ -1531,9 +1531,9 @@ static void stmmac_display_rings(struct stmmac_priv *priv,
|
||||
static unsigned int stmmac_rx_offset(struct stmmac_priv *priv)
|
||||
{
|
||||
if (stmmac_xdp_is_enabled(priv))
|
||||
return XDP_PACKET_HEADROOM;
|
||||
return XDP_PACKET_HEADROOM + NET_IP_ALIGN;
|
||||
|
||||
return NET_SKB_PAD;
|
||||
return NET_SKB_PAD + NET_IP_ALIGN;
|
||||
}
|
||||
|
||||
static int stmmac_set_bfsize(int mtu)
|
||||
@@ -2723,7 +2723,8 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget)
|
||||
|
||||
tx_desc = stmmac_get_tx_desc(priv, tx_q, entry);
|
||||
dma_addr = xsk_buff_raw_get_dma(pool, xdp_desc.addr);
|
||||
meta = xsk_buff_get_metadata(pool, xdp_desc.addr);
|
||||
meta = xsk_buff_get_metadata(pool, xdp_desc.addr,
|
||||
xdp_desc.options);
|
||||
xsk_buff_raw_dma_sync_for_device(pool, dma_addr, xdp_desc.len);
|
||||
|
||||
/* To return XDP buffer to XSK pool, we simple call
|
||||
@@ -4375,18 +4376,6 @@ static void stmmac_flush_tx_descriptors(struct stmmac_priv *priv, int queue)
|
||||
stmmac_set_queue_tx_tail_ptr(priv, tx_q, queue, tx_q->cur_tx);
|
||||
}
|
||||
|
||||
static void stmmac_set_gso_types(struct stmmac_priv *priv, bool tso)
|
||||
{
|
||||
if (!tso) {
|
||||
priv->gso_enabled_types = 0;
|
||||
} else {
|
||||
/* Manage oversized TCP frames for GMAC4 device */
|
||||
priv->gso_enabled_types = SKB_GSO_TCPV4 | SKB_GSO_TCPV6;
|
||||
if (priv->plat->core_type == DWMAC_CORE_GMAC4)
|
||||
priv->gso_enabled_types |= SKB_GSO_UDP_L4;
|
||||
}
|
||||
}
|
||||
|
||||
static void stmmac_set_gso_features(struct net_device *ndev)
|
||||
{
|
||||
struct stmmac_priv *priv = netdev_priv(ndev);
|
||||
@@ -4420,8 +4409,6 @@ static void stmmac_set_gso_features(struct net_device *ndev)
|
||||
if (priv->plat->core_type == DWMAC_CORE_GMAC4)
|
||||
ndev->hw_features |= NETIF_F_GSO_UDP_L4;
|
||||
|
||||
stmmac_set_gso_types(priv, true);
|
||||
|
||||
dev_info(priv->device, "TSO feature enabled\n");
|
||||
}
|
||||
|
||||
@@ -4771,8 +4758,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
if (priv->tx_path_in_lpi_mode && priv->eee_sw_timer_en)
|
||||
stmmac_stop_sw_lpi(priv);
|
||||
|
||||
if (skb_is_gso(skb) &&
|
||||
skb_shinfo(skb)->gso_type & priv->gso_enabled_types)
|
||||
if (skb_is_gso(skb))
|
||||
return stmmac_tso_xmit(skb, dev);
|
||||
|
||||
if (priv->est && priv->est->enable &&
|
||||
@@ -6206,8 +6192,6 @@ static int stmmac_set_features(struct net_device *netdev,
|
||||
stmmac_enable_sph(priv, priv->ioaddr, sph_en, chan);
|
||||
}
|
||||
|
||||
stmmac_set_gso_types(priv, features & NETIF_F_TSO);
|
||||
|
||||
if (features & NETIF_F_HW_VLAN_CTAG_RX)
|
||||
priv->hw->hw_vlan_en = true;
|
||||
else
|
||||
|
||||
@@ -130,7 +130,6 @@ static struct stmmac_axi *stmmac_axi_setup(struct platform_device *pdev)
|
||||
static int stmmac_mtl_setup(struct platform_device *pdev,
|
||||
struct plat_stmmacenet_data *plat)
|
||||
{
|
||||
struct device_node *q_node;
|
||||
struct device_node *rx_node;
|
||||
struct device_node *tx_node;
|
||||
u8 queue = 0;
|
||||
@@ -169,7 +168,7 @@ static int stmmac_mtl_setup(struct platform_device *pdev,
|
||||
plat->rx_sched_algorithm = MTL_RX_ALGORITHM_SP;
|
||||
|
||||
/* Processing individual RX queue config */
|
||||
for_each_child_of_node(rx_node, q_node) {
|
||||
for_each_child_of_node_scoped(rx_node, q_node) {
|
||||
if (queue >= plat->rx_queues_to_use)
|
||||
break;
|
||||
|
||||
@@ -227,7 +226,7 @@ static int stmmac_mtl_setup(struct platform_device *pdev,
|
||||
queue = 0;
|
||||
|
||||
/* Processing individual TX queue config */
|
||||
for_each_child_of_node(tx_node, q_node) {
|
||||
for_each_child_of_node_scoped(tx_node, q_node) {
|
||||
if (queue >= plat->tx_queues_to_use)
|
||||
break;
|
||||
|
||||
@@ -276,7 +275,6 @@ static int stmmac_mtl_setup(struct platform_device *pdev,
|
||||
out:
|
||||
of_node_put(rx_node);
|
||||
of_node_put(tx_node);
|
||||
of_node_put(q_node);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -395,11 +395,17 @@ static int stmmac_test_mmc(struct stmmac_priv *priv)
|
||||
stmmac_mmc_read(priv, priv->mmcaddr, &final);
|
||||
|
||||
/*
|
||||
* The number of MMC counters available depends on HW configuration
|
||||
* so we just use this one to validate the feature. I hope there is
|
||||
* not a version without this counter.
|
||||
* The number of MMC counters available depends on HW configuration,
|
||||
* and there doesn't seem to be a way to enumerate the implemented
|
||||
* counters.
|
||||
*
|
||||
* Let's check a hand-picked set of counters, knowing that :
|
||||
* - Starfive JH7110 doesn't implement mmc_tx_framecount_g
|
||||
* - Amlogic SM1 doesn't implement any mmc_tx_*
|
||||
*
|
||||
*/
|
||||
if (final.mmc_tx_framecount_g <= initial.mmc_tx_framecount_g)
|
||||
if (final.mmc_tx_framecount_g <= initial.mmc_tx_framecount_g &&
|
||||
final.mmc_rx_framecount_gb <= initial.mmc_rx_framecount_gb)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
@@ -473,6 +479,21 @@ static int stmmac_filter_check(struct stmmac_priv *priv)
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int stmmac_uc_filter_check(struct stmmac_priv *priv)
|
||||
{
|
||||
/* For tests involving the UC filter, we need at least one empty
|
||||
* slot in the UC filter. The UC filters contains netdev_uc_count() + 1
|
||||
* entries: The dev->uc list + one entry for the HW address.
|
||||
*
|
||||
* Having an empty slot therefore means netdev_uc_count() + 2 entries
|
||||
* can fit in the filter
|
||||
*/
|
||||
if (netdev_uc_count(priv->dev) + 2 > priv->hw->unicast_filter_entries)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool stmmac_hash_check(struct stmmac_priv *priv, unsigned char *addr)
|
||||
{
|
||||
int mc_offset = 32 - priv->hw->mcast_bits_log2;
|
||||
@@ -564,7 +585,7 @@ static int stmmac_test_pfilt(struct stmmac_priv *priv)
|
||||
|
||||
if (stmmac_filter_check(priv))
|
||||
return -EOPNOTSUPP;
|
||||
if (netdev_uc_count(priv->dev) >= priv->hw->unicast_filter_entries)
|
||||
if (stmmac_uc_filter_check(priv))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
while (--tries) {
|
||||
@@ -608,7 +629,7 @@ static int stmmac_test_mcfilt(struct stmmac_priv *priv)
|
||||
|
||||
if (stmmac_filter_check(priv))
|
||||
return -EOPNOTSUPP;
|
||||
if (netdev_uc_count(priv->dev) >= priv->hw->unicast_filter_entries)
|
||||
if (stmmac_uc_filter_check(priv))
|
||||
return -EOPNOTSUPP;
|
||||
if (netdev_mc_count(priv->dev) >= priv->hw->multicast_filter_bins)
|
||||
return -EOPNOTSUPP;
|
||||
@@ -654,7 +675,7 @@ static int stmmac_test_ucfilt(struct stmmac_priv *priv)
|
||||
|
||||
if (stmmac_filter_check(priv))
|
||||
return -EOPNOTSUPP;
|
||||
if (netdev_uc_count(priv->dev) >= priv->hw->unicast_filter_entries)
|
||||
if (stmmac_uc_filter_check(priv))
|
||||
return -EOPNOTSUPP;
|
||||
if (netdev_mc_count(priv->dev) >= priv->hw->multicast_filter_bins)
|
||||
return -EOPNOTSUPP;
|
||||
@@ -718,12 +739,24 @@ static int stmmac_test_flowctrl(struct stmmac_priv *priv)
|
||||
u32 rx_cnt = priv->plat->rx_queues_to_use;
|
||||
struct mac_device_info *mac = priv->hw;
|
||||
struct stmmac_test_priv *tpriv;
|
||||
unsigned int rx_fifo_size;
|
||||
unsigned int pkt_count;
|
||||
int i, ret = 0;
|
||||
|
||||
if (!(mac->link.caps & MAC_SYM_PAUSE))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
rx_fifo_size = priv->plat->rx_fifo_size;
|
||||
if (!rx_fifo_size)
|
||||
rx_fifo_size = priv->dma_cap.rx_fifo_size;
|
||||
|
||||
/* No pause frame is emitted if we don't have at least 4096 bytes per
|
||||
* queue, except on dwmac100.
|
||||
*/
|
||||
if (priv->plat->core_type != DWMAC_CORE_MAC100 &&
|
||||
rx_fifo_size / priv->plat->rx_queues_to_use < 4096)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
tpriv = kzalloc_obj(*tpriv);
|
||||
if (!tpriv)
|
||||
return -ENOMEM;
|
||||
@@ -737,9 +770,7 @@ static int stmmac_test_flowctrl(struct stmmac_priv *priv)
|
||||
dev_add_pack(&tpriv->pt);
|
||||
|
||||
/* Compute minimum number of packets to make FIFO full */
|
||||
pkt_count = priv->plat->rx_fifo_size;
|
||||
if (!pkt_count)
|
||||
pkt_count = priv->dma_cap.rx_fifo_size;
|
||||
pkt_count = rx_fifo_size;
|
||||
pkt_count /= 1400;
|
||||
pkt_count *= 2;
|
||||
|
||||
@@ -1432,11 +1463,11 @@ static int __stmmac_test_l4filt(struct stmmac_priv *priv, u32 dst, u32 src,
|
||||
struct {
|
||||
struct flow_dissector_key_basic bkey;
|
||||
struct flow_dissector_key_ports key;
|
||||
} __aligned(BITS_PER_LONG / 8) keys;
|
||||
} __aligned(BITS_PER_LONG / 8) keys = { };
|
||||
struct {
|
||||
struct flow_dissector_key_basic bmask;
|
||||
struct flow_dissector_key_ports mask;
|
||||
} __aligned(BITS_PER_LONG / 8) masks;
|
||||
} __aligned(BITS_PER_LONG / 8) masks = { };
|
||||
unsigned long dummy_cookie = 0xdeadbeef;
|
||||
struct stmmac_packet_attrs attr = { };
|
||||
struct flow_dissector *dissector;
|
||||
@@ -1489,6 +1520,8 @@ static int __stmmac_test_l4filt(struct stmmac_priv *priv, u32 dst, u32 src,
|
||||
keys.bkey.ip_proto = udp ? IPPROTO_UDP : IPPROTO_TCP;
|
||||
keys.key.src = htons(src);
|
||||
keys.key.dst = htons(dst);
|
||||
/* Match the full IP proto field */
|
||||
masks.bmask.ip_proto = 0xff;
|
||||
masks.mask.src = src_mask;
|
||||
masks.mask.dst = dst_mask;
|
||||
|
||||
|
||||
@@ -558,13 +558,11 @@ static int wx_ptp_set_timestamp_mode(struct wx *wx,
|
||||
{
|
||||
u32 tsync_tx_ctl = WX_TSC_1588_CTL_ENABLED;
|
||||
u32 tsync_rx_ctl = WX_PSR_1588_CTL_ENABLED;
|
||||
DECLARE_BITMAP(flags, WX_PF_FLAGS_NBITS);
|
||||
u32 tsync_rx_mtrl = PTP_EV_PORT << 16;
|
||||
bool rx_tstamp = false;
|
||||
bool is_l2 = false;
|
||||
u32 regval;
|
||||
|
||||
memcpy(flags, wx->flags, sizeof(wx->flags));
|
||||
|
||||
switch (config->tx_type) {
|
||||
case HWTSTAMP_TX_OFF:
|
||||
tsync_tx_ctl = 0;
|
||||
@@ -579,20 +577,16 @@ static int wx_ptp_set_timestamp_mode(struct wx *wx,
|
||||
case HWTSTAMP_FILTER_NONE:
|
||||
tsync_rx_ctl = 0;
|
||||
tsync_rx_mtrl = 0;
|
||||
clear_bit(WX_FLAG_RX_HWTSTAMP_ENABLED, flags);
|
||||
clear_bit(WX_FLAG_RX_HWTSTAMP_IN_REGISTER, flags);
|
||||
break;
|
||||
case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
|
||||
tsync_rx_ctl |= WX_PSR_1588_CTL_TYPE_L4_V1;
|
||||
tsync_rx_mtrl |= WX_PSR_1588_MSG_V1_SYNC;
|
||||
set_bit(WX_FLAG_RX_HWTSTAMP_ENABLED, flags);
|
||||
set_bit(WX_FLAG_RX_HWTSTAMP_IN_REGISTER, flags);
|
||||
rx_tstamp = true;
|
||||
break;
|
||||
case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
|
||||
tsync_rx_ctl |= WX_PSR_1588_CTL_TYPE_L4_V1;
|
||||
tsync_rx_mtrl |= WX_PSR_1588_MSG_V1_DELAY_REQ;
|
||||
set_bit(WX_FLAG_RX_HWTSTAMP_ENABLED, flags);
|
||||
set_bit(WX_FLAG_RX_HWTSTAMP_IN_REGISTER, flags);
|
||||
rx_tstamp = true;
|
||||
break;
|
||||
case HWTSTAMP_FILTER_PTP_V2_EVENT:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
|
||||
@@ -605,9 +599,8 @@ static int wx_ptp_set_timestamp_mode(struct wx *wx,
|
||||
case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
|
||||
tsync_rx_ctl |= WX_PSR_1588_CTL_TYPE_EVENT_V2;
|
||||
is_l2 = true;
|
||||
rx_tstamp = true;
|
||||
config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
|
||||
set_bit(WX_FLAG_RX_HWTSTAMP_ENABLED, flags);
|
||||
set_bit(WX_FLAG_RX_HWTSTAMP_IN_REGISTER, flags);
|
||||
break;
|
||||
default:
|
||||
/* register PSR_1588_MSG must be set in order to do V1 packets,
|
||||
@@ -646,7 +639,8 @@ static int wx_ptp_set_timestamp_mode(struct wx *wx,
|
||||
WX_WRITE_FLUSH(wx);
|
||||
|
||||
/* configure adapter flags only when HW is actually configured */
|
||||
memcpy(wx->flags, flags, sizeof(wx->flags));
|
||||
assign_bit(WX_FLAG_RX_HWTSTAMP_ENABLED, wx->flags, rx_tstamp);
|
||||
assign_bit(WX_FLAG_RX_HWTSTAMP_IN_REGISTER, wx->flags, rx_tstamp);
|
||||
|
||||
/* clear TX/RX timestamp state, just to be sure */
|
||||
wx_ptp_clear_tx_timestamp(wx);
|
||||
|
||||
@@ -1446,7 +1446,7 @@ struct wx {
|
||||
};
|
||||
|
||||
#define WX_INTR_ALL (~0ULL)
|
||||
#define WX_INTR_Q(i) BIT((i))
|
||||
#define WX_INTR_Q(i) BIT_ULL((i))
|
||||
|
||||
/* register operations */
|
||||
#define wr32(a, reg, value) writel((value), ((a)->hw_addr + (reg)))
|
||||
|
||||
@@ -164,6 +164,7 @@ static irqreturn_t txgbe_misc_irq_thread_fn(int irq, void *data)
|
||||
struct wx *wx = txgbe->wx;
|
||||
unsigned int nhandled = 0;
|
||||
unsigned int sub_irq;
|
||||
u64 misc_mask;
|
||||
u32 eicr;
|
||||
|
||||
eicr = txgbe->eicr;
|
||||
@@ -183,7 +184,9 @@ static irqreturn_t txgbe_misc_irq_thread_fn(int irq, void *data)
|
||||
nhandled++;
|
||||
}
|
||||
|
||||
wx_intr_enable(wx, TXGBE_INTR_MISC(wx));
|
||||
misc_mask = wx->pdev->msix_enabled ? TXGBE_INTR_MISC(wx) : BIT(0);
|
||||
if (!test_bit(WX_STATE_DOWN, wx->state))
|
||||
wx_intr_enable(wx, misc_mask);
|
||||
return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
|
||||
}
|
||||
|
||||
|
||||
@@ -303,7 +303,7 @@ struct txgbe_fdir_filter {
|
||||
#define TXGBE_DEFAULT_RX_WORK 128
|
||||
#endif
|
||||
|
||||
#define TXGBE_INTR_MISC(A) BIT((A)->num_q_vectors)
|
||||
#define TXGBE_INTR_MISC(A) BIT_ULL((A)->num_q_vectors)
|
||||
#define TXGBE_INTR_QALL(A) (TXGBE_INTR_MISC(A) - 1)
|
||||
|
||||
#define TXGBE_MAX_EITR GENMASK(11, 3)
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/udp.h>
|
||||
#include <linux/rculist.h>
|
||||
@@ -108,6 +109,7 @@ struct gtp_net {
|
||||
};
|
||||
|
||||
static u32 gtp_h_initval;
|
||||
static DEFINE_MUTEX(gtp_pdp_lock);
|
||||
|
||||
static struct genl_family gtp_genl_family;
|
||||
|
||||
@@ -151,7 +153,8 @@ static struct pdp_ctx *gtp0_pdp_find(struct gtp_dev *gtp, u64 tid, u16 family)
|
||||
|
||||
head = >p->tid_hash[gtp0_hashfn(tid) % gtp->hash_size];
|
||||
|
||||
hlist_for_each_entry_rcu(pdp, head, hlist_tid) {
|
||||
hlist_for_each_entry_rcu(pdp, head, hlist_tid,
|
||||
lockdep_is_held(>p_pdp_lock)) {
|
||||
if (pdp->af == family &&
|
||||
pdp->gtp_version == GTP_V0 &&
|
||||
pdp->u.v0.tid == tid)
|
||||
@@ -168,7 +171,8 @@ static struct pdp_ctx *gtp1_pdp_find(struct gtp_dev *gtp, u32 tid, u16 family)
|
||||
|
||||
head = >p->tid_hash[gtp1u_hashfn(tid) % gtp->hash_size];
|
||||
|
||||
hlist_for_each_entry_rcu(pdp, head, hlist_tid) {
|
||||
hlist_for_each_entry_rcu(pdp, head, hlist_tid,
|
||||
lockdep_is_held(>p_pdp_lock)) {
|
||||
if (pdp->af == family &&
|
||||
pdp->gtp_version == GTP_V1 &&
|
||||
pdp->u.v1.i_tei == tid)
|
||||
@@ -185,7 +189,8 @@ static struct pdp_ctx *ipv4_pdp_find(struct gtp_dev *gtp, __be32 ms_addr)
|
||||
|
||||
head = >p->addr_hash[ipv4_hashfn(ms_addr) % gtp->hash_size];
|
||||
|
||||
hlist_for_each_entry_rcu(pdp, head, hlist_addr) {
|
||||
hlist_for_each_entry_rcu(pdp, head, hlist_addr,
|
||||
lockdep_is_held(>p_pdp_lock)) {
|
||||
if (pdp->af == AF_INET &&
|
||||
pdp->ms.addr.s_addr == ms_addr)
|
||||
return pdp;
|
||||
@@ -220,7 +225,8 @@ static struct pdp_ctx *ipv6_pdp_find(struct gtp_dev *gtp,
|
||||
|
||||
head = >p->addr_hash[ipv6_hashfn(ms_addr) % gtp->hash_size];
|
||||
|
||||
hlist_for_each_entry_rcu(pdp, head, hlist_addr) {
|
||||
hlist_for_each_entry_rcu(pdp, head, hlist_addr,
|
||||
lockdep_is_held(>p_pdp_lock)) {
|
||||
if (pdp->af == AF_INET6 &&
|
||||
ipv6_pdp_addr_equal(&pdp->ms.addr6, ms_addr))
|
||||
return pdp;
|
||||
@@ -1543,6 +1549,8 @@ static int gtp_newlink(struct net_device *dev,
|
||||
out_encap:
|
||||
gtp_encap_disable(gtp);
|
||||
out_hashtable:
|
||||
/* Wait for RCU readers that may still reference this gtp_dev. */
|
||||
synchronize_net();
|
||||
kfree(gtp->addr_hash);
|
||||
kfree(gtp->tid_hash);
|
||||
return err;
|
||||
@@ -1555,9 +1563,11 @@ static void gtp_dellink(struct net_device *dev, struct list_head *head)
|
||||
struct pdp_ctx *pctx;
|
||||
int i;
|
||||
|
||||
mutex_lock(>p_pdp_lock);
|
||||
for (i = 0; i < gtp->hash_size; i++)
|
||||
hlist_for_each_entry_safe(pctx, next, >p->tid_hash[i], hlist_tid)
|
||||
pdp_context_delete(pctx);
|
||||
mutex_unlock(>p_pdp_lock);
|
||||
|
||||
list_del(>p->list);
|
||||
unregister_netdevice_queue(dev, head);
|
||||
@@ -2053,6 +2063,7 @@ static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info)
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
mutex_lock(>p_pdp_lock);
|
||||
pctx = gtp_pdp_add(gtp, sk, info);
|
||||
if (IS_ERR(pctx)) {
|
||||
err = PTR_ERR(pctx);
|
||||
@@ -2060,6 +2071,7 @@ static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info)
|
||||
gtp_tunnel_notify(pctx, GTP_CMD_NEWPDP, GFP_KERNEL);
|
||||
err = 0;
|
||||
}
|
||||
mutex_unlock(>p_pdp_lock);
|
||||
|
||||
out_unlock:
|
||||
rtnl_unlock();
|
||||
@@ -2134,6 +2146,8 @@ static int gtp_genl_del_pdp(struct sk_buff *skb, struct genl_info *info)
|
||||
if (!info->attrs[GTPA_VERSION])
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(>p_pdp_lock);
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
pctx = gtp_find_pdp(sock_net(skb->sk), info->attrs);
|
||||
@@ -2154,6 +2168,7 @@ static int gtp_genl_del_pdp(struct sk_buff *skb, struct genl_info *info)
|
||||
|
||||
out_unlock:
|
||||
rcu_read_unlock();
|
||||
mutex_unlock(>p_pdp_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -972,12 +972,12 @@ static void ipa_remove(struct platform_device *pdev)
|
||||
}
|
||||
if (ret) {
|
||||
/*
|
||||
* Not cleaning up here properly might also yield a
|
||||
* crash later on. As the device is still unregistered
|
||||
* in this case, this might even yield a crash later on.
|
||||
* Continuing teardown after failing to stop the modem
|
||||
* could crash, so leave the remaining resources allocated.
|
||||
*/
|
||||
dev_err(dev, "Failed to stop modem (%pe), leaking resources\n",
|
||||
ERR_PTR(ret));
|
||||
pm_runtime_put_noidle(dev);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -266,13 +266,29 @@ void ipa_modem_suspend(struct net_device *netdev)
|
||||
* the modem. We can't enable the queue directly in ipa_modem_resume()
|
||||
* because transmits restart the instant the queue is awakened; but the
|
||||
* device power state won't be ACTIVE until *after* ipa_modem_resume()
|
||||
* returns.
|
||||
* returns. A transmit restarted before that would stop the queue
|
||||
* again and get -EINPROGRESS from pm_runtime_get(), and with this
|
||||
* work having already run, nothing would ever wake the queue again.
|
||||
* So wait for the resume to complete before waking the queue.
|
||||
*/
|
||||
static void ipa_modem_wake_queue_work(struct work_struct *work)
|
||||
{
|
||||
struct ipa_priv *priv = container_of(work, struct ipa_priv, work);
|
||||
struct device *dev = priv->ipa->dev;
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_get_sync(dev);
|
||||
|
||||
/* Wake the queue even if the device could not be resumed, so
|
||||
* that pending packets are dropped by the transmit path rather
|
||||
* than stranded behind a stopped queue.
|
||||
*/
|
||||
netif_wake_queue(priv->tx->netdev);
|
||||
|
||||
if (ret < 0)
|
||||
pm_runtime_put_noidle(dev);
|
||||
else
|
||||
(void)pm_runtime_put_autosuspend(dev);
|
||||
}
|
||||
|
||||
/** ipa_modem_resume() - resume callback for runtime_pm
|
||||
|
||||
@@ -529,6 +529,7 @@ static void nsim_del_napi(struct netdevsim *ns)
|
||||
for (i = 0; i < dev->num_rx_queues; i++) {
|
||||
struct nsim_rq *rq = ns->rq[i];
|
||||
|
||||
netif_queue_set_napi(dev, i, NETDEV_QUEUE_TYPE_RX, NULL);
|
||||
napi_disable_locked(&rq->napi);
|
||||
__netif_napi_del_locked(&rq->napi);
|
||||
}
|
||||
@@ -826,6 +827,7 @@ nsim_queue_start(struct net_device *dev, struct netdev_queue_config *qcfg,
|
||||
}
|
||||
|
||||
ns->rq[idx] = qmem->rq;
|
||||
netif_queue_set_napi(dev, idx, NETDEV_QUEUE_TYPE_RX, &ns->rq[idx]->napi);
|
||||
napi_enable_locked(&ns->rq[idx]->napi);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -144,6 +144,9 @@ static void ntb_netdev_rx_handler(struct ntb_transport_qp *qp, void *qp_data,
|
||||
goto enqueue_again;
|
||||
}
|
||||
|
||||
ndev->stats.rx_packets++;
|
||||
ndev->stats.rx_bytes += len;
|
||||
|
||||
new_skb = netdev_alloc_skb(ndev, ndev->mtu + ETH_HLEN);
|
||||
if (!new_skb) {
|
||||
ndev->stats.rx_dropped++;
|
||||
@@ -155,13 +158,7 @@ static void ntb_netdev_rx_handler(struct ntb_transport_qp *qp, void *qp_data,
|
||||
skb->ip_summed = CHECKSUM_NONE;
|
||||
skb_record_rx_queue(skb, q->qid);
|
||||
|
||||
if (netif_rx(skb) == NET_RX_DROP) {
|
||||
ndev->stats.rx_errors++;
|
||||
ndev->stats.rx_dropped++;
|
||||
} else {
|
||||
ndev->stats.rx_packets++;
|
||||
ndev->stats.rx_bytes += len;
|
||||
}
|
||||
netif_rx(skb);
|
||||
|
||||
skb = new_skb;
|
||||
|
||||
@@ -199,8 +196,10 @@ static int __ntb_netdev_maybe_stop_tx(struct net_device *netdev,
|
||||
static int ntb_netdev_maybe_stop_tx(struct net_device *ndev,
|
||||
struct ntb_netdev_queue *q, int size)
|
||||
{
|
||||
if (__netif_subqueue_stopped(ndev, q->qid) ||
|
||||
(ntb_transport_tx_free_entry(q->qp) >= size))
|
||||
if (__netif_subqueue_stopped(ndev, q->qid))
|
||||
return -EBUSY;
|
||||
|
||||
if (ntb_transport_tx_free_entry(q->qp) >= size)
|
||||
return 0;
|
||||
|
||||
return __ntb_netdev_maybe_stop_tx(ndev, q, size);
|
||||
@@ -256,21 +255,30 @@ static netdev_tx_t ntb_netdev_start_xmit(struct sk_buff *skb,
|
||||
|
||||
q = &dev->queues[qid];
|
||||
|
||||
ntb_netdev_maybe_stop_tx(ndev, q, tx_stop);
|
||||
if (unlikely(ntb_netdev_maybe_stop_tx(ndev, q, tx_stop)))
|
||||
return NETDEV_TX_BUSY;
|
||||
|
||||
rc = ntb_transport_tx_enqueue(q->qp, skb, skb->data, skb->len);
|
||||
if (rc)
|
||||
goto err;
|
||||
if (rc) {
|
||||
if (rc == -EAGAIN || rc == -EBUSY) {
|
||||
netif_stop_subqueue(ndev, q->qid);
|
||||
mod_timer(&q->tx_timer,
|
||||
jiffies + usecs_to_jiffies(tx_time));
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
|
||||
goto drop;
|
||||
}
|
||||
|
||||
/* check for next submit */
|
||||
ntb_netdev_maybe_stop_tx(ndev, q, tx_stop);
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
err:
|
||||
drop:
|
||||
dev_kfree_skb_any(skb);
|
||||
ndev->stats.tx_dropped++;
|
||||
ndev->stats.tx_errors++;
|
||||
return NETDEV_TX_BUSY;
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
static void ntb_netdev_tx_timer(struct timer_list *t)
|
||||
|
||||
@@ -1173,13 +1173,6 @@ static int en8811h_probe(struct phy_device *phydev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Configure led gpio pins as output */
|
||||
ret = air_phy_buckpbus_reg_modify(phydev, EN8811H_GPIO_OUTPUT,
|
||||
EN8811H_GPIO_OUTPUT_345,
|
||||
EN8811H_GPIO_OUTPUT_345);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1324,6 +1317,17 @@ static int en8811h_config_init(struct phy_device *phydev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Configure led gpio pins as output. Must be redone on every
|
||||
* .config_init(), not just once in .probe(): en8811h_restart_mcu()
|
||||
* resets buckpbus-mapped MCU state (incl. this register) on every
|
||||
* call after the first, e.g. on link renegotiation or ifup/ifdown.
|
||||
*/
|
||||
ret = air_phy_buckpbus_reg_modify(phydev, EN8811H_GPIO_OUTPUT,
|
||||
EN8811H_GPIO_OUTPUT_345,
|
||||
EN8811H_GPIO_OUTPUT_345);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -964,7 +964,7 @@ static unsigned int phylink_inband_caps(struct phylink *pl,
|
||||
return 0;
|
||||
|
||||
pcs = pl->mac_ops->mac_select_pcs(pl->config, interface);
|
||||
if (!pcs)
|
||||
if (IS_ERR_OR_NULL(pcs))
|
||||
return 0;
|
||||
|
||||
return phylink_pcs_inband_caps(pcs, interface);
|
||||
|
||||
@@ -628,9 +628,15 @@ static void sl_uninit(struct net_device *dev)
|
||||
struct slip *sl = netdev_priv(dev);
|
||||
|
||||
sl_free_bufs(sl);
|
||||
/* Drop the slip_devs[] entry here rather than from the destructor:
|
||||
* ndo_uninit runs under RTNL, so it cannot race sl_sync().
|
||||
*/
|
||||
slip_devs[dev->base_addr] = NULL;
|
||||
}
|
||||
|
||||
/* Hook the destructor so we can free slip devices at the right point in time */
|
||||
/* Only for the slip_open() error path: register_netdevice() can fail before
|
||||
* ndo_init, and then ndo_uninit is not called either.
|
||||
*/
|
||||
static void sl_free_netdev(struct net_device *dev)
|
||||
{
|
||||
int i = dev->base_addr;
|
||||
@@ -657,7 +663,6 @@ static void sl_setup(struct net_device *dev)
|
||||
{
|
||||
dev->netdev_ops = &sl_netdev_ops;
|
||||
dev->needs_free_netdev = true;
|
||||
dev->priv_destructor = sl_free_netdev;
|
||||
|
||||
dev->hard_header_len = 0;
|
||||
dev->addr_len = 0;
|
||||
@@ -881,8 +886,6 @@ static int slip_open(struct tty_struct *tty)
|
||||
* Close down a SLIP channel.
|
||||
* This means flushing out any pending queues, and then returning. This
|
||||
* call is serialized against other ldisc functions.
|
||||
*
|
||||
* We also use this method fo a hangup event
|
||||
*/
|
||||
|
||||
static void slip_close(struct tty_struct *tty)
|
||||
@@ -908,12 +911,7 @@ static void slip_close(struct tty_struct *tty)
|
||||
#endif
|
||||
/* Flush network side */
|
||||
unregister_netdev(sl->dev);
|
||||
/* This will complete via sl_free_netdev */
|
||||
}
|
||||
|
||||
static void slip_hangup(struct tty_struct *tty)
|
||||
{
|
||||
slip_close(tty);
|
||||
/* sl_uninit() has dropped the slip_devs[] entry by now */
|
||||
}
|
||||
/************************************************************************
|
||||
* STANDARD SLIP ENCAPSULATION *
|
||||
@@ -1275,7 +1273,6 @@ static struct tty_ldisc_ops sl_ldisc = {
|
||||
.name = "slip",
|
||||
.open = slip_open,
|
||||
.close = slip_close,
|
||||
.hangup = slip_hangup,
|
||||
.ioctl = slip_ioctl,
|
||||
.receive_buf = slip_receive_buf,
|
||||
.write_wakeup = slip_write_wakeup,
|
||||
|
||||
@@ -904,9 +904,11 @@ static int tbnet_poll(struct napi_struct *napi, int budget)
|
||||
le32_to_cpu(net->rx_hdr.frame_count) - 1;
|
||||
|
||||
rx_packets++;
|
||||
net->stats.rx_bytes += frame_size;
|
||||
|
||||
if (last) {
|
||||
/* Before eth_type_trans() pulls the Ethernet header. */
|
||||
net->stats.rx_packets++;
|
||||
net->stats.rx_bytes += skb->len;
|
||||
skb->protocol = eth_type_trans(skb, net->dev);
|
||||
trace_tbnet_rx_skb(skb);
|
||||
napi_gro_receive(&net->napi, skb);
|
||||
@@ -914,8 +916,6 @@ static int tbnet_poll(struct napi_struct *napi, int budget)
|
||||
}
|
||||
}
|
||||
|
||||
net->stats.rx_packets += rx_packets;
|
||||
|
||||
if (cleaned_count)
|
||||
tbnet_alloc_rx_buffers(net, cleaned_count);
|
||||
|
||||
|
||||
@@ -2013,6 +2013,12 @@ static const struct usb_device_id cdc_devs[] = {
|
||||
},
|
||||
|
||||
/* Mac */
|
||||
{ USB_DEVICE_INTERFACE_NUMBER(0x05ac, 0x1902, 0),
|
||||
.driver_info = (unsigned long)&apple_private_interface_info,
|
||||
},
|
||||
{ USB_DEVICE_INTERFACE_NUMBER(0x05ac, 0x1902, 2),
|
||||
.driver_info = (unsigned long)&apple_private_interface_info,
|
||||
},
|
||||
{ USB_DEVICE_INTERFACE_NUMBER(0x05ac, 0x1905, 0),
|
||||
.driver_info = (unsigned long)&apple_private_interface_info,
|
||||
},
|
||||
|
||||
@@ -1881,6 +1881,7 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
|
||||
|
||||
if (n) {
|
||||
struct vxlan_rdst *rdst = NULL;
|
||||
u8 ha[ETH_ALEN] __aligned(2);
|
||||
struct vxlan_fdb *f;
|
||||
struct sk_buff *reply;
|
||||
|
||||
@@ -1889,8 +1890,10 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
|
||||
goto out;
|
||||
}
|
||||
|
||||
neigh_ha_snapshot(ha, n, n->dev);
|
||||
|
||||
rcu_read_lock();
|
||||
f = vxlan_find_mac_tx(vxlan, n->ha, vni);
|
||||
f = vxlan_find_mac_tx(vxlan, ha, vni);
|
||||
if (f)
|
||||
rdst = first_remote_rcu(f);
|
||||
if (rdst && vxlan_addr_any(&rdst->remote_ip)) {
|
||||
@@ -1902,7 +1905,7 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
|
||||
rcu_read_unlock();
|
||||
|
||||
reply = arp_create(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip, sha,
|
||||
n->ha, sha);
|
||||
ha, sha);
|
||||
|
||||
neigh_release(n);
|
||||
|
||||
@@ -1935,7 +1938,8 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
static struct sk_buff *vxlan_na_create(struct sk_buff *request,
|
||||
struct neighbour *n, bool isrouter)
|
||||
struct neighbour *n, u8 *ha,
|
||||
bool isrouter)
|
||||
{
|
||||
struct net_device *dev = request->dev;
|
||||
struct sk_buff *reply;
|
||||
@@ -1981,7 +1985,7 @@ static struct sk_buff *vxlan_na_create(struct sk_buff *request,
|
||||
|
||||
/* Ethernet header */
|
||||
ether_addr_copy(eth_hdr(reply)->h_dest, daddr);
|
||||
ether_addr_copy(eth_hdr(reply)->h_source, n->ha);
|
||||
ether_addr_copy(eth_hdr(reply)->h_source, ha);
|
||||
eth_hdr(reply)->h_proto = htons(ETH_P_IPV6);
|
||||
reply->protocol = htons(ETH_P_IPV6);
|
||||
|
||||
@@ -2010,7 +2014,7 @@ static struct sk_buff *vxlan_na_create(struct sk_buff *request,
|
||||
na->icmph.icmp6_override = 1;
|
||||
na->icmph.icmp6_solicited = 1;
|
||||
na->target = ns->target;
|
||||
ether_addr_copy(&na->opt[2], n->ha);
|
||||
ether_addr_copy(&na->opt[2], ha);
|
||||
na->opt[0] = ND_OPT_TARGET_LL_ADDR;
|
||||
na->opt[1] = na_olen >> 3;
|
||||
|
||||
@@ -2051,6 +2055,7 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
|
||||
|
||||
if (n) {
|
||||
struct vxlan_rdst *rdst = NULL;
|
||||
u8 ha[ETH_ALEN] __aligned(2);
|
||||
struct vxlan_fdb *f;
|
||||
struct sk_buff *reply;
|
||||
|
||||
@@ -2059,7 +2064,8 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
|
||||
goto out;
|
||||
}
|
||||
|
||||
f = vxlan_find_mac_tx(vxlan, n->ha, vni);
|
||||
neigh_ha_snapshot(ha, n, n->dev);
|
||||
f = vxlan_find_mac_tx(vxlan, ha, vni);
|
||||
if (f)
|
||||
rdst = first_remote_rcu(f);
|
||||
if (rdst && vxlan_addr_any(&rdst->remote_ip)) {
|
||||
@@ -2068,7 +2074,7 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
|
||||
goto out;
|
||||
}
|
||||
|
||||
reply = vxlan_na_create(skb, n,
|
||||
reply = vxlan_na_create(skb, n, ha,
|
||||
!!(f ? f->flags & NTF_ROUTER : 0));
|
||||
|
||||
neigh_release(n);
|
||||
|
||||
@@ -1719,9 +1719,16 @@ static void ntb_transport_rxc_db(unsigned long data)
|
||||
static void ntb_tx_copy_callback(void *data,
|
||||
const struct dmaengine_result *res)
|
||||
{
|
||||
struct ntb_payload_header __iomem *hdr;
|
||||
struct ntb_queue_entry *entry = data;
|
||||
struct ntb_transport_qp *qp = entry->qp;
|
||||
struct ntb_payload_header __iomem *hdr = entry->tx_hdr;
|
||||
struct ntb_transport_qp *qp;
|
||||
unsigned int len;
|
||||
void *cb_data;
|
||||
|
||||
qp = entry->qp;
|
||||
hdr = entry->tx_hdr;
|
||||
cb_data = entry->cb_data;
|
||||
len = entry->len;
|
||||
|
||||
/* we need to check DMA results if we are using DMA */
|
||||
if (res) {
|
||||
@@ -1768,15 +1775,13 @@ static void ntb_tx_copy_callback(void *data,
|
||||
* "link down" or similar. Since no payload is being sent in these
|
||||
* cases, there is nothing to add to the completion queue.
|
||||
*/
|
||||
if (entry->len > 0) {
|
||||
qp->tx_bytes += entry->len;
|
||||
|
||||
if (qp->tx_handler)
|
||||
qp->tx_handler(qp, qp->cb_data, entry->cb_data,
|
||||
entry->len);
|
||||
}
|
||||
if (len > 0)
|
||||
qp->tx_bytes += len;
|
||||
|
||||
ntb_list_add(&qp->ntb_tx_free_q_lock, &entry->entry, &qp->tx_free_q);
|
||||
|
||||
if (len > 0 && qp->tx_handler)
|
||||
qp->tx_handler(qp, qp->cb_data, cb_data, len);
|
||||
}
|
||||
|
||||
static void ntb_memcpy_tx_on_stack(struct ntb_queue_entry *entry, void __iomem *offset)
|
||||
@@ -1950,15 +1955,6 @@ static int ntb_process_tx(struct ntb_transport_qp *qp,
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
if (entry->len > qp->tx_max_frame - sizeof(struct ntb_payload_header)) {
|
||||
if (qp->tx_handler)
|
||||
qp->tx_handler(qp, qp->cb_data, NULL, -EIO);
|
||||
|
||||
ntb_list_add(&qp->ntb_tx_free_q_lock, &entry->entry,
|
||||
&qp->tx_free_q);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ntb_async_tx(qp, entry);
|
||||
|
||||
qp->tx_pkts++;
|
||||
@@ -2348,9 +2344,11 @@ int ntb_transport_tx_enqueue(struct ntb_transport_qp *qp, void *cb, void *data,
|
||||
if (!qp || !len)
|
||||
return -EINVAL;
|
||||
|
||||
/* If the qp link is down already, just ignore. */
|
||||
if (!qp->link_is_up)
|
||||
return 0;
|
||||
return -ENOLINK;
|
||||
|
||||
if (len > qp->tx_max_frame - sizeof(struct ntb_payload_header))
|
||||
return -EMSGSIZE;
|
||||
|
||||
entry = ntb_list_rm(&qp->ntb_tx_free_q_lock, &qp->tx_free_q);
|
||||
if (!entry) {
|
||||
|
||||
@@ -440,7 +440,7 @@ static int net_timer_enable_perout(struct netc_timer *priv,
|
||||
}
|
||||
|
||||
if (on) {
|
||||
u64 period_ns, gclk_period, max_period, min_period;
|
||||
u64 period_ns, gclk_period, min_period;
|
||||
struct timespec64 period, stime;
|
||||
u32 integral_period;
|
||||
int alarm_id;
|
||||
@@ -450,12 +450,12 @@ static int net_timer_enable_perout(struct netc_timer *priv,
|
||||
period_ns = timespec64_to_ns(&period);
|
||||
|
||||
integral_period = netc_timer_get_integral_period(priv);
|
||||
max_period = (u64)NETC_TMR_DEFAULT_FIPER + integral_period;
|
||||
gclk_period = netc_timer_get_gclk_period(priv);
|
||||
min_period = gclk_period * 4 + integral_period;
|
||||
if (period_ns > max_period || period_ns < min_period) {
|
||||
dev_err(dev, "The period range is %llu ~ %llu\n",
|
||||
min_period, max_period);
|
||||
if (period_ns > NETC_TMR_DEFAULT_FIPER ||
|
||||
period_ns < min_period) {
|
||||
dev_err(dev, "The period range is %llu ~ %lu\n",
|
||||
min_period, NETC_TMR_DEFAULT_FIPER);
|
||||
err = -EINVAL;
|
||||
goto unlock_spinlock;
|
||||
}
|
||||
|
||||
@@ -917,8 +917,8 @@ static int usbatm_atm_init(struct usbatm_data *instance)
|
||||
|
||||
instance->atm_dev = atm_dev;
|
||||
|
||||
atm_dev->ci_range.vpi_bits = ATM_CI_MAX;
|
||||
atm_dev->ci_range.vci_bits = ATM_CI_MAX;
|
||||
atm_dev->ci_range.vpi_bits = 8;
|
||||
atm_dev->ci_range.vci_bits = 16;
|
||||
atm_dev->signal = ATM_PHY_SIG_UNKNOWN;
|
||||
|
||||
/* temp init ATM device, set to 128kbit */
|
||||
|
||||
@@ -7,9 +7,6 @@
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
#define __ETHTOOL_LINK_MODE_MASK_NWORDS \
|
||||
DIV_ROUND_UP(__ETHTOOL_LINK_MODE_MASK_NBITS, 32)
|
||||
|
||||
#define ETHTOOL_PAUSE_STAT_CNT (__ETHTOOL_A_PAUSE_STAT_CNT - \
|
||||
ETHTOOL_A_PAUSE_STAT_TX_FRAMES)
|
||||
|
||||
|
||||
@@ -61,7 +61,8 @@ u8 mlx5_query_vport_state(struct mlx5_core_dev *mdev, u8 opmod, u16 vport);
|
||||
int mlx5_modify_vport_admin_state(struct mlx5_core_dev *mdev, u8 opmod,
|
||||
u16 vport, u8 other_vport, u8 state);
|
||||
int mlx5_query_vport_max_tx_speed(struct mlx5_core_dev *mdev, u8 op_mod,
|
||||
u16 vport, u8 other_vport, u32 *max_tx_speed);
|
||||
u16 vport, u8 other_vport,
|
||||
u32 *max_tx_speed, u8 *state);
|
||||
int mlx5_modify_vport_max_tx_speed(struct mlx5_core_dev *mdev, u8 opmod,
|
||||
u16 vport, u8 other_vport, u16 max_tx_speed);
|
||||
int mlx5_query_nic_vport_mac_address(struct mlx5_core_dev *mdev,
|
||||
|
||||
@@ -3126,6 +3126,30 @@ static inline void skb_set_transport_header(struct sk_buff *skb,
|
||||
skb->transport_header += offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* skb_set_transport_header_careful - conditionally set transport header
|
||||
* @skb: buffer to alter
|
||||
* @offset: offset to add to skb->data
|
||||
*
|
||||
* Hardened version of skb_set_transport_header().
|
||||
*
|
||||
* Returns: true if the operation was a success.
|
||||
*/
|
||||
static inline bool __must_check
|
||||
skb_set_transport_header_careful(struct sk_buff *skb, const int offset)
|
||||
{
|
||||
long thoff = skb->data - skb->head + offset;
|
||||
|
||||
if (unlikely(thoff != (typeof(skb->transport_header))thoff))
|
||||
return false;
|
||||
|
||||
if (unlikely(thoff == (typeof(skb->transport_header))~0U))
|
||||
return false;
|
||||
|
||||
skb->transport_header = thoff;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline unsigned char *skb_network_header(const struct sk_buff *skb)
|
||||
{
|
||||
return skb->head + skb->network_header;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <linux/ip.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/udp.h>
|
||||
#include <net/tcp.h>
|
||||
#include <uapi/linux/tcp.h>
|
||||
#include <uapi/linux/virtio_net.h>
|
||||
|
||||
@@ -179,6 +180,9 @@ static inline int __virtio_net_hdr_to_skb(struct sk_buff *skb,
|
||||
if (skb->ip_summed == CHECKSUM_PARTIAL &&
|
||||
skb->csum_offset != offsetof(struct tcphdr, check))
|
||||
return -EINVAL;
|
||||
|
||||
BUILD_BUG_ON(TCP_MIN_GSO_SIZE * GSO_MAX_SEGS < GSO_MAX_SIZE);
|
||||
gso_size = max(gso_size, TCP_MIN_GSO_SIZE);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -935,9 +935,9 @@ static inline void hci_discovery_filter_clear(struct hci_dev *hdev)
|
||||
hdev->discovery.result_filtering = false;
|
||||
hdev->discovery.report_invalid_rssi = true;
|
||||
hdev->discovery.rssi = HCI_RSSI_INVALID;
|
||||
hdev->discovery.uuid_count = 0;
|
||||
|
||||
spin_lock(&hdev->discovery.lock);
|
||||
hdev->discovery.uuid_count = 0;
|
||||
kfree(hdev->discovery.uuids);
|
||||
hdev->discovery.uuids = NULL;
|
||||
spin_unlock(&hdev->discovery.lock);
|
||||
|
||||
@@ -699,7 +699,12 @@ struct l2cap_rx_busy {
|
||||
|
||||
struct l2cap_pinfo {
|
||||
struct bt_sock bt;
|
||||
|
||||
/* With owning sk_socket chan may be read without lock, other access
|
||||
* should hold lock_sock.
|
||||
*/
|
||||
struct l2cap_chan *chan;
|
||||
|
||||
struct list_head rx_busy;
|
||||
};
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ struct inetpeer_addr {
|
||||
|
||||
struct inet_peer {
|
||||
struct rb_node rb_node;
|
||||
u64 hash;
|
||||
struct inetpeer_addr daddr;
|
||||
|
||||
u32 metrics[RTAX_MAX];
|
||||
@@ -125,6 +126,9 @@ static inline int inetpeer_addr_cmp(const struct inetpeer_addr *a,
|
||||
{
|
||||
int i, n;
|
||||
|
||||
if (a->family != b->family)
|
||||
return a->family < b->family ? -1 : 1;
|
||||
|
||||
if (a->family == AF_INET)
|
||||
n = sizeof(a->a4) / sizeof(u32);
|
||||
else
|
||||
|
||||
@@ -506,6 +506,31 @@ static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst,
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Configured/administrative MTU of a route, for advertising the TCP MSS.
|
||||
*
|
||||
* Unlike ip_dst_mtu_maybe_forward(), this deliberately ignores the
|
||||
* ICMP-learned path MTU (rt->rt_pmtu). The advertised MSS bounds what the
|
||||
* peer may send to us and must reflect our receive capability (the device or
|
||||
* route-configured MTU), not a path MTU learned on the reverse (send)
|
||||
* direction, which may not apply to the peer->us path and outlives the fnhe
|
||||
* for the whole connection. See RFC 2923 section 2.3 and the comment above
|
||||
* tcp_advertise_mss().
|
||||
*/
|
||||
static inline unsigned int ip_dst_mtu_configured(const struct dst_entry *dst)
|
||||
{
|
||||
unsigned int mtu, res;
|
||||
|
||||
rcu_read_lock();
|
||||
mtu = dst_metric_raw(dst, RTAX_MTU);
|
||||
if (!mtu)
|
||||
mtu = READ_ONCE(dst_dev_rcu(dst)->mtu);
|
||||
mtu = min_t(unsigned int, mtu, IP_MAX_MTU);
|
||||
res = mtu - lwtunnel_headroom(dst->lwtstate, mtu);
|
||||
rcu_read_unlock();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline unsigned int ip_skb_dst_mtu(struct sock *sk,
|
||||
const struct sk_buff *skb)
|
||||
{
|
||||
|
||||
@@ -387,6 +387,43 @@ static inline unsigned int ip6_dst_mtu_maybe_forward(const struct dst_entry *dst
|
||||
return mtu - lwtunnel_headroom(dst->lwtstate, mtu);
|
||||
}
|
||||
|
||||
/* Configured/administrative MTU of a route, for advertising the TCP MSS.
|
||||
*
|
||||
* Unlike ip6_dst_mtu_maybe_forward(), this ignores any ICMPv6-learned path
|
||||
* MTU (which is kept on the RTF_CACHE exception route) and returns the MTU of
|
||||
* the underlying route (fib6_pmtu) or the egress device. The advertised MSS
|
||||
* bounds what the peer may send to us and must reflect our receive
|
||||
* capability, not a path MTU learned on the reverse (send) direction. See
|
||||
* RFC 2923 section 2.3 and the comment above tcp_advertise_mss().
|
||||
*/
|
||||
static inline unsigned int ip6_dst_mtu_configured(const struct dst_entry *dst)
|
||||
{
|
||||
const struct rt6_info *rt = dst_rt6_info(dst);
|
||||
const struct fib6_info *from;
|
||||
struct inet6_dev *idev;
|
||||
unsigned int mtu = 0;
|
||||
|
||||
rcu_read_lock();
|
||||
/* IPv6 keeps the learned PMTU and the configured MTU in the same
|
||||
* RTAX_MTU slot: the learned value sits on this (possibly RTF_CACHE)
|
||||
* dst, the configured one on the underlying route. Reach the latter
|
||||
* via ->from (fib6_pmtu), populated by ip6_route_info_create().
|
||||
*/
|
||||
from = rcu_dereference(rt->from);
|
||||
if (from)
|
||||
mtu = from->fib6_pmtu;
|
||||
if (!mtu) {
|
||||
mtu = IPV6_MIN_MTU;
|
||||
idev = __in6_dev_get(dst_dev_rcu(dst));
|
||||
if (idev)
|
||||
mtu = max_t(unsigned int, mtu, READ_ONCE(idev->cnf.mtu6));
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
mtu = min_t(unsigned int, mtu, IP6_MAX_MTU);
|
||||
return mtu - lwtunnel_headroom(dst->lwtstate, mtu);
|
||||
}
|
||||
|
||||
u32 ip6_mtu_from_fib6(const struct fib6_result *res,
|
||||
const struct in6_addr *daddr,
|
||||
const struct in6_addr *saddr);
|
||||
|
||||
@@ -196,7 +196,7 @@ __libeth_xsk_xmit_fill_buf_md(const struct xdp_desc *xdesc,
|
||||
struct libeth_xdp_tx_desc desc;
|
||||
struct xdp_desc_ctx ctx;
|
||||
|
||||
ctx = xsk_buff_raw_get_ctx(sq->pool, xdesc->addr);
|
||||
ctx = xsk_buff_raw_get_ctx(sq->pool, xdesc->addr, xdesc->options);
|
||||
desc = (typeof(desc)){
|
||||
.addr = ctx.dma,
|
||||
__libeth_xdp_tx_len(xdesc->len),
|
||||
|
||||
@@ -870,8 +870,6 @@ struct nft_elem_priv *nft_set_elem_init(const struct nft_set *set,
|
||||
const u32 *key, const u32 *key_end,
|
||||
const u32 *data,
|
||||
u64 timeout, u64 expiration, gfp_t gfp);
|
||||
int nft_set_elem_expr_clone(const struct nft_ctx *ctx, struct nft_set *set,
|
||||
struct nft_expr *expr_array[]);
|
||||
void nft_set_elem_expr_destroy(const struct nft_ctx *ctx,
|
||||
struct nft_set_elem_expr *elem_expr);
|
||||
void nft_set_elem_destroy(const struct nft_set *set,
|
||||
@@ -1949,6 +1947,7 @@ struct nftables_pernet {
|
||||
struct list_head binding_list;
|
||||
struct list_head module_list;
|
||||
struct list_head notify_list;
|
||||
struct list_head set_update_list;
|
||||
struct mutex commit_mutex;
|
||||
u64 table_handle;
|
||||
u64 tstamp;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#define DEFAULT_TX_QUEUE_LEN 1000
|
||||
#define STAB_SIZE_LOG_MAX 30
|
||||
#define QDISC_PKT_LEN_MAX (1 << 20) /* 1 MiB */
|
||||
|
||||
struct qdisc_walker {
|
||||
int stop;
|
||||
|
||||
@@ -2057,7 +2057,7 @@ struct sctp_association {
|
||||
force_delay:1;
|
||||
|
||||
__u8 strreset_enable;
|
||||
__u8 strreset_outstanding; /* request param count on the fly */
|
||||
__u8 strreset_outstanding; /* request param bitmask on the fly */
|
||||
|
||||
__u32 strreset_outseq; /* Update after receiving response */
|
||||
__u32 strreset_inseq; /* Update after receiving request */
|
||||
|
||||
@@ -1782,6 +1782,11 @@ static inline int tcp_full_space(const struct sock *sk)
|
||||
return tcp_win_from_space(sk, READ_ONCE(sk->sk_rcvbuf));
|
||||
}
|
||||
|
||||
static inline u32 tcp_dst_advmss(const struct dst_entry *dst)
|
||||
{
|
||||
return max_t(u32, dst_metric_advmss(dst), TCP_MIN_MSS);
|
||||
}
|
||||
|
||||
static inline void __tcp_adjust_rcv_ssthresh(struct sock *sk, u32 new_ssthresh)
|
||||
{
|
||||
int unused_mem = sk_unused_reserved_mem(sk);
|
||||
|
||||
@@ -240,6 +240,7 @@ static inline void *xsk_buff_raw_get_data(struct xsk_buff_pool *pool, u64 addr)
|
||||
* xsk_buff_raw_get_ctx - get &xdp_desc context
|
||||
* @pool: XSk buff pool desc address belongs to
|
||||
* @addr: desc address (from userspace)
|
||||
* @options: desc options (from userspace)
|
||||
*
|
||||
* Wrapper for xp_raw_get_ctx() to be used in drivers, see its kdoc for
|
||||
* details.
|
||||
@@ -248,9 +249,9 @@ static inline void *xsk_buff_raw_get_data(struct xsk_buff_pool *pool, u64 addr)
|
||||
* pointer, if it is present (initialized to %NULL otherwise).
|
||||
*/
|
||||
static inline struct xdp_desc_ctx
|
||||
xsk_buff_raw_get_ctx(const struct xsk_buff_pool *pool, u64 addr)
|
||||
xsk_buff_raw_get_ctx(const struct xsk_buff_pool *pool, u64 addr, u32 options)
|
||||
{
|
||||
return xp_raw_get_ctx(pool, addr);
|
||||
return xp_raw_get_ctx(pool, addr, options);
|
||||
}
|
||||
|
||||
#define XDP_TXMD_FLAGS_VALID ( \
|
||||
@@ -318,18 +319,20 @@ xsk_tx_metadata_request(const struct xsk_buff_pool *pool,
|
||||
}
|
||||
|
||||
static inline struct xsk_tx_metadata *
|
||||
__xsk_buff_get_metadata(const struct xsk_buff_pool *pool, void *data)
|
||||
__xsk_buff_get_metadata(const struct xsk_buff_pool *pool, void *data,
|
||||
unsigned int options)
|
||||
{
|
||||
if (!pool->tx_metadata_len)
|
||||
if (!pool->tx_metadata_len || !(options & XDP_TX_METADATA))
|
||||
return NULL;
|
||||
|
||||
return data - pool->tx_metadata_len;
|
||||
}
|
||||
|
||||
static inline struct xsk_tx_metadata *
|
||||
xsk_buff_get_metadata(struct xsk_buff_pool *pool, u64 addr)
|
||||
xsk_buff_get_metadata(struct xsk_buff_pool *pool, u64 addr, u32 options)
|
||||
{
|
||||
return __xsk_buff_get_metadata(pool, xp_raw_get_data(pool, addr));
|
||||
return __xsk_buff_get_metadata(pool, xp_raw_get_data(pool, addr),
|
||||
options);
|
||||
}
|
||||
|
||||
static inline void xsk_buff_dma_sync_for_cpu(struct xdp_buff *xdp)
|
||||
@@ -510,7 +513,7 @@ static inline void *xsk_buff_raw_get_data(struct xsk_buff_pool *pool, u64 addr)
|
||||
}
|
||||
|
||||
static inline struct xdp_desc_ctx
|
||||
xsk_buff_raw_get_ctx(const struct xsk_buff_pool *pool, u64 addr)
|
||||
xsk_buff_raw_get_ctx(const struct xsk_buff_pool *pool, u64 addr, u32 options)
|
||||
{
|
||||
return (struct xdp_desc_ctx){ };
|
||||
}
|
||||
@@ -530,13 +533,14 @@ xsk_tx_metadata_request(const struct xsk_buff_pool *pool,
|
||||
}
|
||||
|
||||
static inline struct xsk_tx_metadata *
|
||||
__xsk_buff_get_metadata(const struct xsk_buff_pool *pool, void *data)
|
||||
__xsk_buff_get_metadata(const struct xsk_buff_pool *pool, void *data,
|
||||
unsigned int options)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct xsk_tx_metadata *
|
||||
xsk_buff_get_metadata(struct xsk_buff_pool *pool, u64 addr)
|
||||
xsk_buff_get_metadata(struct xsk_buff_pool *pool, u64 addr, u32 options)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -154,7 +154,8 @@ struct xdp_desc_ctx {
|
||||
struct xsk_tx_metadata *meta;
|
||||
};
|
||||
|
||||
struct xdp_desc_ctx xp_raw_get_ctx(const struct xsk_buff_pool *pool, u64 addr);
|
||||
struct xdp_desc_ctx xp_raw_get_ctx(const struct xsk_buff_pool *pool, u64 addr,
|
||||
u32 options);
|
||||
|
||||
static inline dma_addr_t xp_get_dma(struct xdp_buff_xsk *xskb)
|
||||
{
|
||||
|
||||
@@ -149,6 +149,7 @@ struct xsk_tx_metadata {
|
||||
__u16 csum_start;
|
||||
/* Offset from csum_start where checksum should be stored. */
|
||||
__u16 csum_offset;
|
||||
__u32 reserved;
|
||||
|
||||
/* XDP_TXMD_FLAGS_LAUNCH_TIME */
|
||||
/* Launch time in nanosecond against the PTP HW Clock */
|
||||
|
||||
@@ -502,26 +502,6 @@ static const struct header_ops vlan_header_ops = {
|
||||
.parse_protocol = vlan_parse_protocol,
|
||||
};
|
||||
|
||||
static int vlan_passthru_hard_header(struct sk_buff *skb, struct net_device *dev,
|
||||
unsigned short type,
|
||||
const void *daddr, const void *saddr,
|
||||
unsigned int len)
|
||||
{
|
||||
struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
|
||||
struct net_device *real_dev = vlan->real_dev;
|
||||
|
||||
if (saddr == NULL)
|
||||
saddr = dev->dev_addr;
|
||||
|
||||
return dev_hard_header(skb, real_dev, type, daddr, saddr, len);
|
||||
}
|
||||
|
||||
static const struct header_ops vlan_passthru_header_ops = {
|
||||
.create = vlan_passthru_hard_header,
|
||||
.parse = eth_header_parse,
|
||||
.parse_protocol = vlan_parse_protocol,
|
||||
};
|
||||
|
||||
static const struct device_type vlan_type = {
|
||||
.name = "vlan",
|
||||
};
|
||||
@@ -580,14 +560,10 @@ static int vlan_dev_init(struct net_device *dev)
|
||||
dev->fcoe_ddp_xid = real_dev->fcoe_ddp_xid;
|
||||
#endif
|
||||
|
||||
dev->needed_headroom = real_dev->needed_headroom;
|
||||
if (vlan_hw_offload_capable(real_dev->features, vlan->vlan_proto)) {
|
||||
dev->header_ops = &vlan_passthru_header_ops;
|
||||
dev->hard_header_len = real_dev->hard_header_len;
|
||||
} else {
|
||||
dev->header_ops = &vlan_header_ops;
|
||||
dev->hard_header_len = real_dev->hard_header_len + VLAN_HLEN;
|
||||
}
|
||||
dev->needed_headroom = real_dev->needed_headroom + VLAN_HLEN;
|
||||
dev->needed_tailroom = real_dev->needed_tailroom;
|
||||
dev->header_ops = &vlan_header_ops;
|
||||
dev->hard_header_len = real_dev->hard_header_len;
|
||||
|
||||
dev->netdev_ops = &vlan_netdev_ops;
|
||||
|
||||
@@ -1029,10 +1005,9 @@ static void vlan_transfer_features(struct net_device *dev,
|
||||
|
||||
netif_inherit_tso_max(vlandev, dev);
|
||||
|
||||
if (vlan_hw_offload_capable(dev->features, vlan->vlan_proto))
|
||||
vlandev->hard_header_len = dev->hard_header_len;
|
||||
else
|
||||
vlandev->hard_header_len = dev->hard_header_len + VLAN_HLEN;
|
||||
vlandev->needed_headroom = dev->needed_headroom + VLAN_HLEN;
|
||||
vlandev->needed_tailroom = dev->needed_tailroom;
|
||||
vlandev->hard_header_len = dev->hard_header_len;
|
||||
|
||||
#if IS_ENABLED(CONFIG_FCOE)
|
||||
vlandev->fcoe_ddp_xid = dev->fcoe_ddp_xid;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user