diff options
Diffstat (limited to 'drivers')
107 files changed, 5192 insertions, 758 deletions
diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c index 79b718430cd1..b23d1e4bad33 100644 --- a/drivers/atm/eni.c +++ b/drivers/atm/eni.c @@ -1136,7 +1136,7 @@ DPRINTK("doing direct send\n"); /* @@@ well, this doesn't work anyway */ else put_dma(tx->index,eni_dev->dma,&j,(unsigned long) skb_frag_page(&skb_shinfo(skb)->frags[i]) + - skb_shinfo(skb)->frags[i].page_offset, + skb_frag_off(&skb_shinfo(skb)->frags[i]), skb_frag_size(&skb_shinfo(skb)->frags[i])); } if (skb->len & 3) { diff --git a/drivers/hsi/clients/ssi_protocol.c b/drivers/hsi/clients/ssi_protocol.c index c9e3f928b93d..0253e76f1df2 100644 --- a/drivers/hsi/clients/ssi_protocol.c +++ b/drivers/hsi/clients/ssi_protocol.c @@ -182,7 +182,7 @@ static void ssip_skb_to_msg(struct sk_buff *skb, struct hsi_msg *msg) BUG_ON(!sg); frag = &skb_shinfo(skb)->frags[i]; sg_set_page(sg, skb_frag_page(frag), skb_frag_size(frag), - frag->page_offset); + skb_frag_off(frag)); } } diff --git a/drivers/infiniband/hw/hfi1/vnic_sdma.c b/drivers/infiniband/hw/hfi1/vnic_sdma.c index 05a140504a99..7d90b900131b 100644 --- a/drivers/infiniband/hw/hfi1/vnic_sdma.c +++ b/drivers/infiniband/hw/hfi1/vnic_sdma.c @@ -108,7 +108,7 @@ static noinline int build_vnic_ulp_payload(struct sdma_engine *sde, ret = sdma_txadd_page(sde->dd, &tx->txreq, skb_frag_page(frag), - frag->page_offset, + skb_frag_off(frag), skb_frag_size(frag)); if (unlikely(ret)) goto bail_txadd; diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index 78fa777c87b1..c332b4761816 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -293,7 +293,8 @@ int ipoib_dma_map_tx(struct ib_device *ca, struct ipoib_tx_buf *tx_req) const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; mapping[i + off] = ib_dma_map_page(ca, skb_frag_page(frag), - frag->page_offset, skb_frag_size(frag), + skb_frag_off(frag), + skb_frag_size(frag), DMA_TO_DEVICE); if (unlikely(ib_dma_mapping_error(ca, mapping[i + off]))) goto partial_error; diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c index 19d4f52a8f90..a761092e6ac9 100644 --- a/drivers/net/can/janz-ican3.c +++ b/drivers/net/can/janz-ican3.c @@ -1936,7 +1936,6 @@ static int ican3_probe(struct platform_device *pdev) /* find our IRQ number */ mod->irq = platform_get_irq(pdev, 0); if (mod->irq < 0) { - dev_err(dev, "IRQ line not found\n"); ret = -ENODEV; goto out_free_ndev; } diff --git a/drivers/net/can/rcar/rcar_can.c b/drivers/net/can/rcar/rcar_can.c index 13e66297b65f..cf218949a8fb 100644 --- a/drivers/net/can/rcar/rcar_can.c +++ b/drivers/net/can/rcar/rcar_can.c @@ -759,7 +759,6 @@ static int rcar_can_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "No IRQ resource\n"); err = irq; goto fail; } diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c index 05410008aa6b..51eecc7cdcdd 100644 --- a/drivers/net/can/rcar/rcar_canfd.c +++ b/drivers/net/can/rcar/rcar_canfd.c @@ -1651,14 +1651,12 @@ static int rcar_canfd_probe(struct platform_device *pdev) ch_irq = platform_get_irq(pdev, 0); if (ch_irq < 0) { - dev_err(&pdev->dev, "no Channel IRQ resource\n"); err = ch_irq; goto fail_dev; } g_irq = platform_get_irq(pdev, 1); if (g_irq < 0) { - dev_err(&pdev->dev, "no Global IRQ resource\n"); err = g_irq; goto fail_dev; } diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c index 093fc9a529f0..f4cd88196404 100644 --- a/drivers/net/can/sun4i_can.c +++ b/drivers/net/can/sun4i_can.c @@ -787,7 +787,6 @@ static int sun4ican_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "could not get a valid irq\n"); err = -ENODEV; goto exit; } diff --git a/drivers/net/dsa/microchip/Kconfig b/drivers/net/dsa/microchip/Kconfig index fe0a13b79c4b..5e4f74286ea3 100644 --- a/drivers/net/dsa/microchip/Kconfig +++ b/drivers/net/dsa/microchip/Kconfig @@ -16,3 +16,20 @@ config NET_DSA_MICROCHIP_KSZ9477_SPI select REGMAP_SPI help Select to enable support for registering switches configured through SPI. + +menuconfig NET_DSA_MICROCHIP_KSZ8795 + tristate "Microchip KSZ8795 series switch support" + depends on NET_DSA + select NET_DSA_MICROCHIP_KSZ_COMMON + help + This driver adds support for Microchip KSZ8795 switch chips. + +config NET_DSA_MICROCHIP_KSZ8795_SPI + tristate "KSZ8795 series SPI connected switch driver" + depends on NET_DSA_MICROCHIP_KSZ8795 && SPI + select REGMAP_SPI + help + This driver accesses KSZ8795 chip through SPI. + + It is required to use the KSZ8795 switch driver as the only access + is through SPI. diff --git a/drivers/net/dsa/microchip/Makefile b/drivers/net/dsa/microchip/Makefile index 68451b02f775..e3d799b95d7d 100644 --- a/drivers/net/dsa/microchip/Makefile +++ b/drivers/net/dsa/microchip/Makefile @@ -2,3 +2,5 @@ obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ_COMMON) += ksz_common.o obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ9477) += ksz9477.o obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ9477_SPI) += ksz9477_spi.o +obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ8795) += ksz8795.o +obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ8795_SPI) += ksz8795_spi.o diff --git a/drivers/net/dsa/microchip/ksz8795.c b/drivers/net/dsa/microchip/ksz8795.c new file mode 100644 index 000000000000..ae80b3c6dea2 --- /dev/null +++ b/drivers/net/dsa/microchip/ksz8795.c @@ -0,0 +1,1311 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Microchip KSZ8795 switch driver + * + * Copyright (C) 2017 Microchip Technology Inc. + * Tristram Ha <Tristram.Ha@microchip.com> + */ + +#include <linux/delay.h> +#include <linux/export.h> +#include <linux/gpio.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_data/microchip-ksz.h> +#include <linux/phy.h> +#include <linux/etherdevice.h> +#include <linux/if_bridge.h> +#include <net/dsa.h> +#include <net/switchdev.h> + +#include "ksz_priv.h" +#include "ksz_common.h" +#include "ksz8795_reg.h" + +static const struct { + char string[ETH_GSTRING_LEN]; +} mib_names[TOTAL_SWITCH_COUNTER_NUM] = { + { "rx_hi" }, + { "rx_undersize" }, + { "rx_fragments" }, + { "rx_oversize" }, + { "rx_jabbers" }, + { "rx_symbol_err" }, + { "rx_crc_err" }, + { "rx_align_err" }, + { "rx_mac_ctrl" }, + { "rx_pause" }, + { "rx_bcast" }, + { "rx_mcast" }, + { "rx_ucast" }, + { "rx_64_or_less" }, + { "rx_65_127" }, + { "rx_128_255" }, + { "rx_256_511" }, + { "rx_512_1023" }, + { "rx_1024_1522" }, + { "rx_1523_2000" }, + { "rx_2001" }, + { "tx_hi" }, + { "tx_late_col" }, + { "tx_pause" }, + { "tx_bcast" }, + { "tx_mcast" }, + { "tx_ucast" }, + { "tx_deferred" }, + { "tx_total_col" }, + { "tx_exc_col" }, + { "tx_single_col" }, + { "tx_mult_col" }, + { "rx_total" }, + { "tx_total" }, + { "rx_discards" }, + { "tx_discards" }, +}; + +static void ksz_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set) +{ + regmap_update_bits(dev->regmap[0], addr, bits, set ? bits : 0); +} + +static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits, + bool set) +{ + regmap_update_bits(dev->regmap[0], PORT_CTRL_ADDR(port, offset), + bits, set ? bits : 0); +} + +static int ksz8795_reset_switch(struct ksz_device *dev) +{ + /* reset switch */ + ksz_write8(dev, REG_POWER_MANAGEMENT_1, + SW_SOFTWARE_POWER_DOWN << SW_POWER_MANAGEMENT_MODE_S); + ksz_write8(dev, REG_POWER_MANAGEMENT_1, 0); + + return 0; +} + +static void ksz8795_set_prio_queue(struct ksz_device *dev, int port, int queue) +{ + u8 hi, lo; + + /* Number of queues can only be 1, 2, or 4. */ + switch (queue) { + case 4: + case 3: + queue = PORT_QUEUE_SPLIT_4; + break; + case 2: + queue = PORT_QUEUE_SPLIT_2; + break; + default: + queue = PORT_QUEUE_SPLIT_1; + } + ksz_pread8(dev, port, REG_PORT_CTRL_0, &lo); + ksz_pread8(dev, port, P_DROP_TAG_CTRL, &hi); + lo &= ~PORT_QUEUE_SPLIT_L; + if (queue & PORT_QUEUE_SPLIT_2) + lo |= PORT_QUEUE_SPLIT_L; + hi &= ~PORT_QUEUE_SPLIT_H; + if (queue & PORT_QUEUE_SPLIT_4) + hi |= PORT_QUEUE_SPLIT_H; + ksz_pwrite8(dev, port, REG_PORT_CTRL_0, lo); + ksz_pwrite8(dev, port, P_DROP_TAG_CTRL, hi); + + /* Default is port based for egress rate limit. */ + if (queue != PORT_QUEUE_SPLIT_1) + ksz_cfg(dev, REG_SW_CTRL_19, SW_OUT_RATE_LIMIT_QUEUE_BASED, + true); +} + +static void ksz8795_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, + u64 *cnt) +{ + u16 ctrl_addr; + u32 data; + u8 check; + int loop; + + ctrl_addr = addr + SWITCH_COUNTER_NUM * port; + ctrl_addr |= IND_ACC_TABLE(TABLE_MIB | TABLE_READ); + + mutex_lock(&dev->alu_mutex); + ksz_write16(dev, REG_IND_CTRL_0, ctrl_addr); + + /* It is almost guaranteed to always read the valid bit because of + * slow SPI speed. + */ + for (loop = 2; loop > 0; loop--) { + ksz_read8(dev, REG_IND_MIB_CHECK, &check); + + if (check & MIB_COUNTER_VALID) { + ksz_read32(dev, REG_IND_DATA_LO, &data); + if (check & MIB_COUNTER_OVERFLOW) + *cnt += MIB_COUNTER_VALUE + 1; + *cnt += data & MIB_COUNTER_VALUE; + break; + } + } + mutex_unlock(&dev->alu_mutex); +} + +static void ksz8795_r_mib_pkt(struct ksz_device *dev, int port, u16 addr, + u64 *dropped, u64 *cnt) +{ + u16 ctrl_addr; + u32 data; + u8 check; + int loop; + + addr -= SWITCH_COUNTER_NUM; + ctrl_addr = (KS_MIB_TOTAL_RX_1 - KS_MIB_TOTAL_RX_0) * port; + ctrl_addr += addr + KS_MIB_TOTAL_RX_0; + ctrl_addr |= IND_ACC_TABLE(TABLE_MIB | TABLE_READ); + + mutex_lock(&dev->alu_mutex); + ksz_write16(dev, REG_IND_CTRL_0, ctrl_addr); + + /* It is almost guaranteed to always read the valid bit because of + * slow SPI speed. + */ + for (loop = 2; loop > 0; loop--) { + ksz_read8(dev, REG_IND_MIB_CHECK, &check); + + if (check & MIB_COUNTER_VALID) { + ksz_read32(dev, REG_IND_DATA_LO, &data); + if (addr < 2) { + u64 total; + + total = check & MIB_TOTAL_BYTES_H; + total <<= 32; + *cnt += total; + *cnt += data; + if (check & MIB_COUNTER_OVERFLOW) { + total = MIB_TOTAL_BYTES_H + 1; + total <<= 32; + *cnt += total; + } + } else { + if (check & MIB_COUNTER_OVERFLOW) + *cnt += MIB_PACKET_DROPPED + 1; + *cnt += data & MIB_PACKET_DROPPED; + } + break; + } + } + mutex_unlock(&dev->alu_mutex); +} + +static void ksz8795_freeze_mib(struct ksz_device *dev, int port, bool freeze) +{ + /* enable the port for flush/freeze function */ + if (freeze) + ksz_cfg(dev, REG_SW_CTRL_6, BIT(port), true); + ksz_cfg(dev, REG_SW_CTRL_6, SW_MIB_COUNTER_FREEZE, freeze); + + /* disable the port after freeze is done */ + if (!freeze) + ksz_cfg(dev, REG_SW_CTRL_6, BIT(port), false); +} + +static void ksz8795_port_init_cnt(struct ksz_device *dev, int port) +{ + struct ksz_port_mib *mib = &dev->ports[port].mib; + + /* flush all enabled port MIB counters */ + ksz_cfg(dev, REG_SW_CTRL_6, BIT(port), true); + ksz_cfg(dev, REG_SW_CTRL_6, SW_MIB_COUNTER_FLUSH, true); + ksz_cfg(dev, REG_SW_CTRL_6, BIT(port), false); + + mib->cnt_ptr = 0; + + /* Some ports may not have MIB counters before SWITCH_COUNTER_NUM. */ + while (mib->cnt_ptr < dev->reg_mib_cnt) { + dev->dev_ops->r_mib_cnt(dev, port, mib->cnt_ptr, + &mib->counters[mib->cnt_ptr]); + ++mib->cnt_ptr; + } + + /* Some ports may not have MIB counters after SWITCH_COUNTER_NUM. */ + while (mib->cnt_ptr < dev->mib_cnt) { + dev->dev_ops->r_mib_pkt(dev, port, mib->cnt_ptr, + NULL, &mib->counters[mib->cnt_ptr]); + ++mib->cnt_ptr; + } + mib->cnt_ptr = 0; + memset(mib->counters, 0, dev->mib_cnt * sizeof(u64)); +} + +static void ksz8795_r_table(struct ksz_device *dev, int table, u16 addr, + u64 *data) +{ + u16 ctrl_addr; + + ctrl_addr = IND_ACC_TABLE(table | TABLE_READ) | addr; + + mutex_lock(&dev->alu_mutex); + ksz_write16(dev, REG_IND_CTRL_0, ctrl_addr); + ksz_read64(dev, REG_IND_DATA_HI, data); + mutex_unlock(&dev->alu_mutex); +} + +static void ksz8795_w_table(struct ksz_device *dev, int table, u16 addr, + u64 data) +{ + u16 ctrl_addr; + + ctrl_addr = IND_ACC_TABLE(table) | addr; + + mutex_lock(&dev->alu_mutex); + ksz_write64(dev, REG_IND_DATA_HI, data); + ksz_write16(dev, REG_IND_CTRL_0, ctrl_addr); + mutex_unlock(&dev->alu_mutex); +} + +static int ksz8795_valid_dyn_entry(struct ksz_device *dev, u8 *data) +{ + int timeout = 100; + + do { + ksz_read8(dev, REG_IND_DATA_CHECK, data); + timeout--; + } while ((*data & DYNAMIC_MAC_TABLE_NOT_READY) && timeout); + + /* Entry is not ready for accessing. */ + if (*data & DYNAMIC_MAC_TABLE_NOT_READY) { + return -EAGAIN; + /* Entry is ready for accessing. */ + } else { + ksz_read8(dev, REG_IND_DATA_8, data); + + /* There is no valid entry in the table. */ + if (*data & DYNAMIC_MAC_TABLE_MAC_EMPTY) + return -ENXIO; + } + return 0; +} + +static int ksz8795_r_dyn_mac_table(struct ksz_device *dev, u16 addr, + u8 *mac_addr, u8 *fid, u8 *src_port, + u8 *timestamp, u16 *entries) +{ + u32 data_hi, data_lo; + u16 ctrl_addr; + u8 data; + int rc; + + ctrl_addr = IND_ACC_TABLE(TABLE_DYNAMIC_MAC | TABLE_READ) | addr; + + mutex_lock(&dev->alu_mutex); + ksz_write16(dev, REG_IND_CTRL_0, ctrl_addr); + + rc = ksz8795_valid_dyn_entry(dev, &data); + if (rc == -EAGAIN) { + if (addr == 0) + *entries = 0; + } else if (rc == -ENXIO) { + *entries = 0; + /* At least one valid entry in the table. */ + } else { + u64 buf = 0; + int cnt; + + ksz_read64(dev, REG_IND_DATA_HI, &buf); + data_hi = (u32)(buf >> 32); + data_lo = (u32)buf; + + /* Check out how many valid entry in the table. */ + cnt = data & DYNAMIC_MAC_TABLE_ENTRIES_H; + cnt <<= DYNAMIC_MAC_ENTRIES_H_S; + cnt |= (data_hi & DYNAMIC_MAC_TABLE_ENTRIES) >> + DYNAMIC_MAC_ENTRIES_S; + *entries = cnt + 1; + + *fid = (data_hi & DYNAMIC_MAC_TABLE_FID) >> + DYNAMIC_MAC_FID_S; + *src_port = (data_hi & DYNAMIC_MAC_TABLE_SRC_PORT) >> + DYNAMIC_MAC_SRC_PORT_S; + *timestamp = (data_hi & DYNAMIC_MAC_TABLE_TIMESTAMP) >> + DYNAMIC_MAC_TIMESTAMP_S; + + mac_addr[5] = (u8)data_lo; + mac_addr[4] = (u8)(data_lo >> 8); + mac_addr[3] = (u8)(data_lo >> 16); + mac_addr[2] = (u8)(data_lo >> 24); + + mac_addr[1] = (u8)data_hi; + mac_addr[0] = (u8)(data_hi >> 8); + rc = 0; + } + mutex_unlock(&dev->alu_mutex); + + return rc; +} + +static int ksz8795_r_sta_mac_table(struct ksz_device *dev, u16 addr, + struct alu_struct *alu) +{ + u32 data_hi, data_lo; + u64 data; + + ksz8795_r_table(dev, TABLE_STATIC_MAC, addr, &data); + data_hi = data >> 32; + data_lo = (u32)data; + if (data_hi & (STATIC_MAC_TABLE_VALID | STATIC_MAC_TABLE_OVERRIDE)) { + alu->mac[5] = (u8)data_lo; + alu->mac[4] = (u8)(data_lo >> 8); + alu->mac[3] = (u8)(data_lo >> 16); + alu->mac[2] = (u8)(data_lo >> 24); + alu->mac[1] = (u8)data_hi; + alu->mac[0] = (u8)(data_hi >> 8); + alu->port_forward = (data_hi & STATIC_MAC_TABLE_FWD_PORTS) >> + STATIC_MAC_FWD_PORTS_S; + alu->is_override = + (data_hi & STATIC_MAC_TABLE_OVERRIDE) ? 1 : 0; + data_hi >>= 1; + alu->is_use_fid = (data_hi & STATIC_MAC_TABLE_USE_FID) ? 1 : 0; + alu->fid = (data_hi & STATIC_MAC_TABLE_FID) >> + STATIC_MAC_FID_S; + return 0; + } + return -ENXIO; +} + +static void ksz8795_w_sta_mac_table(struct ksz_device *dev, u16 addr, + struct alu_struct *alu) +{ + u32 data_hi, data_lo; + u64 data; + + data_lo = ((u32)alu->mac[2] << 24) | + ((u32)alu->mac[3] << 16) | + ((u32)alu->mac[4] << 8) | alu->mac[5]; + data_hi = ((u32)alu->mac[0] << 8) | alu->mac[1]; + data_hi |= (u32)alu->port_forward << STATIC_MAC_FWD_PORTS_S; + + if (alu->is_override) + data_hi |= STATIC_MAC_TABLE_OVERRIDE; + if (alu->is_use_fid) { + data_hi |= STATIC_MAC_TABLE_USE_FID; + data_hi |= (u32)alu->fid << STATIC_MAC_FID_S; + } + if (alu->is_static) + data_hi |= STATIC_MAC_TABLE_VALID; + else + data_hi &= ~STATIC_MAC_TABLE_OVERRIDE; + + data = (u64)data_hi << 32 | data_lo; + ksz8795_w_table(dev, TABLE_STATIC_MAC, addr, data); +} + +static void ksz8795_from_vlan(u16 vlan, u8 *fid, u8 *member, u8 *valid) +{ + *fid = vlan & VLAN_TABLE_FID; + *member = (vlan & VLAN_TABLE_MEMBERSHIP) >> VLAN_TABLE_MEMBERSHIP_S; + *valid = !!(vlan & VLAN_TABLE_VALID); +} + +static void ksz8795_to_vlan(u8 fid, u8 member, u8 valid, u16 *vlan) +{ + *vlan = fid; + *vlan |= (u16)member << VLAN_TABLE_MEMBERSHIP_S; + if (valid) + *vlan |= VLAN_TABLE_VALID; +} + +static void ksz8795_r_vlan_entries(struct ksz_device *dev, u16 addr) +{ + u64 data; + int i; + + ksz8795_r_table(dev, TABLE_VLAN, addr, &data); + addr *= 4; + for (i = 0; i < 4; i++) { + dev->vlan_cache[addr + i].table[0] = (u16)data; + data >>= VLAN_TABLE_S; + } +} + +static void ksz8795_r_vlan_table(struct ksz_device *dev, u16 vid, u16 *vlan) +{ + int index; + u16 *data; + u16 addr; + u64 buf; + + data = (u16 *)&buf; + addr = vid / 4; + index = vid & 3; + ksz8795_r_table(dev, TABLE_VLAN, addr, &buf); + *vlan = data[index]; +} + +static void ksz8795_w_vlan_table(struct ksz_device *dev, u16 vid, u16 vlan) +{ + int index; + u16 *data; + u16 addr; + u64 buf; + + data = (u16 *)&buf; + addr = vid / 4; + index = vid & 3; + ksz8795_r_table(dev, TABLE_VLAN, addr, &buf); + data[index] = vlan; + dev->vlan_cache[vid].table[0] = vlan; + ksz8795_w_table(dev, TABLE_VLAN, addr, buf); +} + +static void ksz8795_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val) +{ + u8 restart, speed, ctrl, link; + int processed = true; + u16 data = 0; + u8 p = phy; + + switch (reg) { + case PHY_REG_CTRL: + ksz_pread8(dev, p, P_NEG_RESTART_CTRL, &restart); + ksz_pread8(dev, p, P_SPEED_STATUS, &speed); + ksz_pread8(dev, p, P_FORCE_CTRL, &ctrl); + if (restart & PORT_PHY_LOOPBACK) + data |= PHY_LOOPBACK; + if (ctrl & PORT_FORCE_100_MBIT) + data |= PHY_SPEED_100MBIT; + if (!(ctrl & PORT_AUTO_NEG_DISABLE)) + data |= PHY_AUTO_NEG_ENABLE; + if (restart & PORT_POWER_DOWN) + data |= PHY_POWER_DOWN; + if (restart & PORT_AUTO_NEG_RESTART) + data |= PHY_AUTO_NEG_RESTART; + if (ctrl & PORT_FORCE_FULL_DUPLEX) + data |= PHY_FULL_DUPLEX; + if (speed & PORT_HP_MDIX) + data |= PHY_HP_MDIX; + if (restart & PORT_FORCE_MDIX) + data |= PHY_FORCE_MDIX; + if (restart & PORT_AUTO_MDIX_DISABLE) + data |= PHY_AUTO_MDIX_DISABLE; + if (restart & PORT_TX_DISABLE) + data |= PHY_TRANSMIT_DISABLE; + if (restart & PORT_LED_OFF) + data |= PHY_LED_DISABLE; + break; + case PHY_REG_STATUS: + ksz_pread8(dev, p, P_LINK_STATUS, &link); + data = PHY_100BTX_FD_CAPABLE | + PHY_100BTX_CAPABLE | + PHY_10BT_FD_CAPABLE | + PHY_10BT_CAPABLE | + PHY_AUTO_NEG_CAPABLE; + if (link & PORT_AUTO_NEG_COMPLETE) + data |= PHY_AUTO_NEG_ACKNOWLEDGE; + if (link & PORT_STAT_LINK_GOOD) + data |= PHY_LINK_STATUS; + break; + case PHY_REG_ID_1: + data = KSZ8795_ID_HI; + break; + case PHY_REG_ID_2: + data = KSZ8795_ID_LO; + break; + case PHY_REG_AUTO_NEGOTIATION: + ksz_pread8(dev, p, P_LOCAL_CTRL, &ctrl); + data = PHY_AUTO_NEG_802_3; + if (ctrl & PORT_AUTO_NEG_SYM_PAUSE) + data |= PHY_AUTO_NEG_SYM_PAUSE; + if (ctrl & PORT_AUTO_NEG_100BTX_FD) + data |= PHY_AUTO_NEG_100BTX_FD; + if (ctrl & PORT_AUTO_NEG_100BTX) + data |= PHY_AUTO_NEG_100BTX; + if (ctrl & PORT_AUTO_NEG_10BT_FD) + data |= PHY_AUTO_NEG_10BT_FD; + if (ctrl & PORT_AUTO_NEG_10BT) + data |= PHY_AUTO_NEG_10BT; + break; + case PHY_REG_REMOTE_CAPABILITY: + ksz_pread8(dev, p, P_REMOTE_STATUS, &link); + data = PHY_AUTO_NEG_802_3; + if (link & PORT_REMOTE_SYM_PAUSE) + data |= PHY_AUTO_NEG_SYM_PAUSE; + if (link & PORT_REMOTE_100BTX_FD) + data |= PHY_AUTO_NEG_100BTX_FD; + if (link & PORT_REMOTE_100BTX) + data |= PHY_AUTO_NEG_100BTX; + if (link & PORT_REMOTE_10BT_FD) + data |= PHY_AUTO_NEG_10BT_FD; + if (link & PORT_REMOTE_10BT) + data |= PHY_AUTO_NEG_10BT; + if (data & ~PHY_AUTO_NEG_802_3) + data |= PHY_REMOTE_ACKNOWLEDGE_NOT; + break; + default: + processed = false; + break; + } + if (processed) + *val = data; +} + +static void ksz8795_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val) +{ + u8 p = phy; + u8 restart, speed, ctrl, data; + + switch (reg) { + case PHY_REG_CTRL: + + /* Do not support PHY reset function. */ + if (val & PHY_RESET) + break; + ksz_pread8(dev, p, P_SPEED_STATUS, &speed); + data = speed; + if (val & PHY_HP_MDIX) + data |= PORT_HP_MDIX; + else + data &= ~PORT_HP_MDIX; + if (data != speed) + ksz_pwrite8(dev, p, P_SPEED_STATUS, data); + ksz_pread8(dev, p, P_FORCE_CTRL, &ctrl); + data = ctrl; + if (!(val & PHY_AUTO_NEG_ENABLE)) + data |= PORT_AUTO_NEG_DISABLE; + else + data &= ~PORT_AUTO_NEG_DISABLE; + + /* Fiber port does not support auto-negotiation. */ + if (dev->ports[p].fiber) + data |= PORT_AUTO_NEG_DISABLE; + if (val & PHY_SPEED_100MBIT) + data |= PORT_FORCE_100_MBIT; + else + data &= ~PORT_FORCE_100_MBIT; + if (val & PHY_FULL_DUPLEX) + data |= PORT_FORCE_FULL_DUPLEX; + else + data &= ~PORT_FORCE_FULL_DUPLEX; + if (data != ctrl) + ksz_pwrite8(dev, p, P_FORCE_CTRL, data); + ksz_pread8(dev, p, P_NEG_RESTART_CTRL, &restart); + data = restart; + if (val & PHY_LED_DISABLE) + data |= PORT_LED_OFF; + else + data &= ~PORT_LED_OFF; + if (val & PHY_TRANSMIT_DISABLE) + data |= PORT_TX_DISABLE; + else + data &= ~PORT_TX_DISABLE; + if (val & PHY_AUTO_NEG_RESTART) + data |= PORT_AUTO_NEG_RESTART; + else + data &= ~(PORT_AUTO_NEG_RESTART); + if (val & PHY_POWER_DOWN) + data |= PORT_POWER_DOWN; + else + data &= ~PORT_POWER_DOWN; + if (val & PHY_AUTO_MDIX_DISABLE) + data |= PORT_AUTO_MDIX_DISABLE; + else + data &= ~PORT_AUTO_MDIX_DISABLE; + if (val & PHY_FORCE_MDIX) + data |= PORT_FORCE_MDIX; + else + data &= ~PORT_FORCE_MDIX; + if (val & PHY_LOOPBACK) + data |= PORT_PHY_LOOPBACK; + else + data &= ~PORT_PHY_LOOPBACK; + if (data != restart) + ksz_pwrite8(dev, p, P_NEG_RESTART_CTRL, data); + break; + case PHY_REG_AUTO_NEGOTIATION: + ksz_pread8(dev, p, P_LOCAL_CTRL, &ctrl); + data = ctrl; + data &= ~(PORT_AUTO_NEG_SYM_PAUSE | + PORT_AUTO_NEG_100BTX_FD | + PORT_AUTO_NEG_100BTX | + PORT_AUTO_NEG_10BT_FD | + PORT_AUTO_NEG_10BT); + if (val & PHY_AUTO_NEG_SYM_PAUSE) + data |= PORT_AUTO_NEG_SYM_PAUSE; + if (val & PHY_AUTO_NEG_100BTX_FD) + data |= PORT_AUTO_NEG_100BTX_FD; + if (val & PHY_AUTO_NEG_100BTX) + data |= PORT_AUTO_NEG_100BTX; + if (val & PHY_AUTO_NEG_10BT_FD) + data |= PORT_AUTO_NEG_10BT_FD; + if (val & PHY_AUTO_NEG_10BT) + data |= PORT_AUTO_NEG_10BT; + if (data != ctrl) + ksz_pwrite8(dev, p, P_LOCAL_CTRL, data); + break; + default: + break; + } +} + +static enum dsa_tag_protocol ksz8795_get_tag_protocol(struct dsa_switch *ds, + int port) +{ + return DSA_TAG_PROTO_KSZ8795; +} + +static void ksz8795_get_strings(struct dsa_switch *ds, int port, + u32 stringset, uint8_t *buf) +{ + int i; + + for (i = 0; i < TOTAL_SWITCH_COUNTER_NUM; i++) { + memcpy(buf + i * ETH_GSTRING_LEN, mib_names[i].string, + ETH_GSTRING_LEN); + } +} + +static void ksz8795_cfg_port_member(struct ksz_device *dev, int port, + u8 member) +{ + u8 data; + + ksz_pread8(dev, port, P_MIRROR_CTRL, &data); + data &= ~PORT_VLAN_MEMBERSHIP; + data |= (member & dev->port_mask); + ksz_pwrite8(dev, port, P_MIRROR_CTRL, data); + dev->ports[port].member = member; +} + +static void ksz8795_port_stp_state_set(struct dsa_switch *ds, int port, + u8 state) +{ + struct ksz_device *dev = ds->priv; + int forward = dev->member; + struct ksz_port *p; + int member = -1; + u8 data; + + p = &dev->ports[port]; + + ksz_pread8(dev, port, P_STP_CTRL, &data); + data &= ~(PORT_TX_ENABLE | PORT_RX_ENABLE | PORT_LEARN_DISABLE); + + switch (state) { + case BR_STATE_DISABLED: + data |= PORT_LEARN_DISABLE; + if (port < SWITCH_PORT_NUM) + member = 0; + break; + case BR_STATE_LISTENING: + data |= (PORT_RX_ENABLE | PORT_LEARN_DISABLE); + if (port < SWITCH_PORT_NUM && + p->stp_state == BR_STATE_DISABLED) + member = dev->host_mask | p->vid_member; + break; + case BR_STATE_LEARNING: + data |= PORT_RX_ENABLE; + break; + case BR_STATE_FORWARDING: + data |= (PORT_TX_ENABLE | PORT_RX_ENABLE); + + /* This function is also used internally. */ + if (port == dev->cpu_port) + break; + + /* Port is a member of a bridge. */ + if (dev->br_member & BIT(port)) { + dev->member |= BIT(port); + member = dev->member; + } else { + member = dev->host_mask | p->vid_member; + } + break; + case BR_STATE_BLOCKING: + data |= PORT_LEARN_DISABLE; + if (port < SWITCH_PORT_NUM && + p->stp_state == BR_STATE_DISABLED) + member = dev->host_mask | p->vid_member; + break; + default: + dev_err(ds->dev, "invalid STP state: %d\n", state); + return; + } + + ksz_pwrite8(dev, port, P_STP_CTRL, data); + p->stp_state = state; + if (data & PORT_RX_ENABLE) + dev->rx_ports |= BIT(port); + else + dev->rx_ports &= ~BIT(port); + if (data & PORT_TX_ENABLE) + dev->tx_ports |= BIT(port); + else + dev->tx_ports &= ~BIT(port); + + /* Port membership may share register with STP state. */ + if (member >= 0 && member != p->member) + ksz8795_cfg_port_member(dev, port, (u8)member); + + /* Check if forwarding needs to be updated. */ + if (state != BR_STATE_FORWARDING) { + if (dev->br_member & BIT(port)) + dev->member &= ~BIT(port); + } + + /* When topology has changed the function ksz_update_port_member + * should be called to modify port forwarding behavior. + */ + if (forward != dev->member) + ksz_update_port_member(dev, port); +} + +static void ksz8795_flush_dyn_mac_table(struct ksz_device *dev, int port) +{ + u8 learn[TOTAL_PORT_NUM]; + int first, index, cnt; + struct ksz_port *p; + + if ((uint)port < TOTAL_PORT_NUM) { + first = port; + cnt = port + 1; + } else { + /* Flush all ports. */ + first = 0; + cnt = dev->mib_port_cnt; + } + for (index = first; index < cnt; index++) { + p = &dev->ports[index]; + if (!p->on) + continue; + ksz_pread8(dev, index, P_STP_CTRL, &learn[index]); + if (!(learn[index] & PORT_LEARN_DISABLE)) + ksz_pwrite8(dev, index, P_STP_CTRL, + learn[index] | PORT_LEARN_DISABLE); + } + ksz_cfg(dev, S_FLUSH_TABLE_CTRL, SW_FLUSH_DYN_MAC_TABLE, true); + for (index = first; index < cnt; index++) { + p = &dev->ports[index]; + if (!p->on) + continue; + if (!(learn[index] & PORT_LEARN_DISABLE)) + ksz_pwrite8(dev, index, P_STP_CTRL, learn[index]); + } +} + +static int ksz8795_port_vlan_filtering(struct dsa_switch *ds, int port, + bool flag) +{ + struct ksz_device *dev = ds->priv; + + ksz_cfg(dev, S_MIRROR_CTRL, SW_VLAN_ENABLE, flag); + + return 0; +} + +static void ksz8795_port_vlan_add(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan) +{ + bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; + struct ksz_device *dev = ds->priv; + u16 data, vid, new_pvid = 0; + u8 fid, member, valid; + + ksz_port_cfg(dev, port, P_TAG_CTRL, PORT_REMOVE_TAG, untagged); + + for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) { + ksz8795_r_vlan_table(dev, vid, &data); + ksz8795_from_vlan(data, &fid, &member, &valid); + + /* First time to setup the VLAN entry. */ + if (!valid) { + /* Need to find a way to map VID to FID. */ + fid = 1; + valid = 1; + } + member |= BIT(port); + + ksz8795_to_vlan(fid, member, valid, &data); + ksz8795_w_vlan_table(dev, vid, data); + + /* change PVID */ + if (vlan->flags & BRIDGE_VLAN_INFO_PVID) + new_pvid = vid; + } + + if (new_pvid) { + ksz_pread16(dev, port, REG_PORT_CTRL_VID, &vid); + vid &= 0xfff; + vid |= new_pvid; + ksz_pwrite16(dev, port, REG_PORT_CTRL_VID, vid); + } +} + +static int ksz8795_port_vlan_del(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan) +{ + bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; + struct ksz_device *dev = ds->priv; + u16 data, vid, pvid, new_pvid = 0; + u8 fid, member, valid; + + ksz_pread16(dev, port, REG_PORT_CTRL_VID, &pvid); + pvid = pvid & 0xFFF; + + ksz_port_cfg(dev, port, P_TAG_CTRL, PORT_REMOVE_TAG, untagged); + + for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) { + ksz8795_r_vlan_table(dev, vid, &data); + ksz8795_from_vlan(data, &fid, &member, &valid); + + member &= ~BIT(port); + + /* Invalidate the entry if no more member. */ + if (!member) { + fid = 0; + valid = 0; + } + + if (pvid == vid) + new_pvid = 1; + + ksz8795_to_vlan(fid, member, valid, &data); + ksz8795_w_vlan_table(dev, vid, data); + } + + if (new_pvid != pvid) + ksz_pwrite16(dev, port, REG_PORT_CTRL_VID, pvid); + + return 0; +} + +static int ksz8795_port_mirror_add(struct dsa_switch *ds, int port, + struct dsa_mall_mirror_tc_entry *mirror, + bool ingress) +{ + struct ksz_device *dev = ds->priv; + + if (ingress) { + ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_RX, true); + dev->mirror_rx |= BIT(port); + } else { + ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_TX, true); + dev->mirror_tx |= BIT(port); + } + + ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_SNIFFER, false); + + /* configure mirror port */ + if (dev->mirror_rx || dev->mirror_tx) + ksz_port_cfg(dev, mirror->to_local_port, P_MIRROR_CTRL, + PORT_MIRROR_SNIFFER, true); + + return 0; +} + +static void ksz8795_port_mirror_del(struct dsa_switch *ds, int port, + struct dsa_mall_mirror_tc_entry *mirror) +{ + struct ksz_device *dev = ds->priv; + u8 data; + + if (mirror->ingress) { + ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_RX, false); + dev->mirror_rx &= ~BIT(port); + } else { + ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_TX, false); + dev->mirror_tx &= ~BIT(port); + } + + ksz_pread8(dev, port, P_MIRROR_CTRL, &data); + + if (!dev->mirror_rx && !dev->mirror_tx) + ksz_port_cfg(dev, mirror->to_local_port, P_MIRROR_CTRL, + PORT_MIRROR_SNIFFER, false); +} + +static void ksz8795_port_setup(struct ksz_device *dev, int port, bool cpu_port) +{ + struct ksz_port *p = &dev->ports[port]; + u8 data8, member; + + /* enable broadcast storm limit */ + ksz_port_cfg(dev, port, P_BCAST_STORM_CTRL, PORT_BROADCAST_STORM, true); + + ksz8795_set_prio_queue(dev, port, 4); + + /* disable DiffServ priority */ + ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_DIFFSERV_ENABLE, false); + + /* replace priority */ + ksz_port_cfg(dev, port, P_802_1P_CTRL, PORT_802_1P_REMAPPING, false); + + /* enable 802.1p priority */ + ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_802_1P_ENABLE, true); + + if (cpu_port) { + /* Configure MII interface for proper network communication. */ + ksz_read8(dev, REG_PORT_5_CTRL_6, &data8); + data8 &= ~PORT_INTERFACE_TYPE; + data8 &= ~PORT_GMII_1GPS_MODE; + switch (dev->interface) { + case PHY_INTERFACE_MODE_MII: + p->phydev.speed = SPEED_100; + break; + case PHY_INTERFACE_MODE_RMII: + data8 |= PORT_INTERFACE_RMII; + p->phydev.speed = SPEED_100; + break; + case PHY_INTERFACE_MODE_GMII: + data8 |= PORT_GMII_1GPS_MODE; + data8 |= PORT_INTERFACE_GMII; + p->phydev.speed = SPEED_1000; + break; + default: + data8 &= ~PORT_RGMII_ID_IN_ENABLE; + data8 &= ~PORT_RGMII_ID_OUT_ENABLE; + if (dev->interface == PHY_INTERFACE_MODE_RGMII_ID || + dev->interface == PHY_INTERFACE_MODE_RGMII_RXID) + data8 |= PORT_RGMII_ID_IN_ENABLE; + if (dev->interface == PHY_INTERFACE_MODE_RGMII_ID || + dev->interface == PHY_INTERFACE_MODE_RGMII_TXID) + data8 |= PORT_RGMII_ID_OUT_ENABLE; + data8 |= PORT_GMII_1GPS_MODE; + data8 |= PORT_INTERFACE_RGMII; + p->phydev.speed = SPEED_1000; + break; + } + ksz_write8(dev, REG_PORT_5_CTRL_6, data8); + p->phydev.duplex = 1; + + member = dev->port_mask; + dev->on_ports = dev->host_mask; + dev->live_ports = dev->host_mask; + } else { + member = dev->host_mask | p->vid_member; + dev->on_ports |= BIT(port); + + /* Link was detected before port is enabled. */ + if (p->phydev.link) + dev->live_ports |= BIT(port); + } + ksz8795_cfg_port_member(dev, port, member); +} + +static void ksz8795_config_cpu_port(struct dsa_switch *ds) +{ + struct ksz_device *dev = ds->priv; + struct ksz_port *p; + u8 remote; + int i; + + ds->num_ports = dev->port_cnt + 1; + + /* Switch marks the maximum frame with extra byte as oversize. */ + ksz_cfg(dev, REG_SW_CTRL_2, SW_LEGAL_PACKET_DISABLE, true); + ksz_cfg(dev, S_TAIL_TAG_CTRL, SW_TAIL_TAG_ENABLE, true); + + p = &dev->ports[dev->cpu_port]; + p->vid_member = dev->port_mask; + p->on = 1; + + ksz8795_port_setup(dev, dev->cpu_port, true); + dev->member = dev->host_mask; + + for (i = 0; i < SWITCH_PORT_NUM; i++) { + p = &dev->ports[i]; + + /* Initialize to non-zero so that ksz_cfg_port_member() will + * be called. + */ + p->vid_member = BIT(i); + p->member = dev->port_mask; + ksz8795_port_stp_state_set(ds, i, BR_STATE_DISABLED); + + /* Last port may be disabled. */ + if (i == dev->port_cnt) + break; + p->on = 1; + p->phy = 1; + } + for (i = 0; i < dev->phy_port_cnt; i++) { + p = &dev->ports[i]; + if (!p->on) + continue; + ksz_pread8(dev, i, P_REMOTE_STATUS, &remote); + if (remote & PORT_FIBER_MODE) + p->fiber = 1; + if (p->fiber) + ksz_port_cfg(dev, i, P_STP_CTRL, PORT_FORCE_FLOW_CTRL, + true); + else + ksz_port_cfg(dev, i, P_STP_CTRL, PORT_FORCE_FLOW_CTRL, + false); + } +} + +static int ksz8795_setup(struct dsa_switch *ds) +{ + struct ksz_device *dev = ds->priv; + struct alu_struct alu; + int i, ret = 0; + + dev->vlan_cache = devm_kcalloc(dev->dev, sizeof(struct vlan_table), + dev->num_vlans, GFP_KERNEL); + if (!dev->vlan_cache) + return -ENOMEM; + + ret = ksz8795_reset_switch(dev); + if (ret) { + dev_err(ds->dev, "failed to reset switch\n"); + return ret; + } + + ksz_cfg(dev, S_REPLACE_VID_CTRL, SW_FLOW_CTRL, true); + + /* Enable automatic fast aging when link changed detected. */ + ksz_cfg(dev, S_LINK_AGING_CTRL, SW_LINK_AUTO_AGING, true); + + /* Enable aggressive back off algorithm in half duplex mode. */ + regmap_update_bits(dev->regmap[0], REG_SW_CTRL_1, + SW_AGGR_BACKOFF, SW_AGGR_BACKOFF); + + /* + * Make sure unicast VLAN boundary is set as default and + * enable no excessive collision drop. + */ + regmap_update_bits(dev->regmap[0], REG_SW_CTRL_2, + UNICAST_VLAN_BOUNDARY | NO_EXC_COLLISION_DROP, + UNICAST_VLAN_BOUNDARY | NO_EXC_COLLISION_DROP); + + ksz8795_config_cpu_port(ds); + + ksz_cfg(dev, REG_SW_CTRL_2, MULTICAST_STORM_DISABLE, true); + + ksz_cfg(dev, S_REPLACE_VID_CTRL, SW_REPLACE_VID, false); + + ksz_cfg(dev, S_MIRROR_CTRL, SW_MIRROR_RX_TX, false); + + /* set broadcast storm protection 10% rate */ + regmap_update_bits(dev->regmap[1], S_REPLACE_VID_CTRL, + BROADCAST_STORM_RATE, + (BROADCAST_STORM_VALUE * + BROADCAST_STORM_PROT_RATE) / 100); + + for (i = 0; i < VLAN_TABLE_ENTRIES; i++) + ksz8795_r_vlan_entries(dev, i); + + /* Setup STP address for STP operation. */ + memset(&alu, 0, sizeof(alu)); + ether_addr_copy(alu.mac, eth_stp_addr); + alu.is_static = true; + alu.is_override = true; + alu.port_forward = dev->host_mask; + + ksz8795_w_sta_mac_table(dev, 0, &alu); + + ksz_init_mib_timer(dev); + + return 0; +} + +static const struct dsa_switch_ops ksz8795_switch_ops = { + .get_tag_protocol = ksz8795_get_tag_protocol, + .setup = ksz8795_setup, + .phy_read = ksz_phy_read16, + .phy_write = ksz_phy_write16, + .adjust_link = ksz_adjust_link, + .port_enable = ksz_enable_port, + .port_disable = ksz_disable_port, + .get_strings = ksz8795_get_strings, + .get_ethtool_stats = ksz_get_ethtool_stats, + .get_sset_count = ksz_sset_count, + .port_bridge_join = ksz_port_bridge_join, + .port_bridge_leave = ksz_port_bridge_leave, + .port_stp_state_set = ksz8795_port_stp_state_set, + .port_fast_age = ksz_port_fast_age, + .port_vlan_filtering = ksz8795_port_vlan_filtering, + .port_vlan_prepare = ksz_port_vlan_prepare, + .port_vlan_add = ksz8795_port_vlan_add, + .port_vlan_del = ksz8795_port_vlan_del, + .port_fdb_dump = ksz_port_fdb_dump, + .port_mdb_prepare = ksz_port_mdb_prepare, + .port_mdb_add = ksz_port_mdb_add, + .port_mdb_del = ksz_port_mdb_del, + .port_mirror_add = ksz8795_port_mirror_add, + .port_mirror_del = ksz8795_port_mirror_del, +}; + +static u32 ksz8795_get_port_addr(int port, int offset) +{ + return PORT_CTRL_ADDR(port, offset); +} + +static int ksz8795_switch_detect(struct ksz_device *dev) +{ + u8 id1, id2; + u16 id16; + int ret; + + /* read chip id */ + ret = ksz_read16(dev, REG_CHIP_ID0, &id16); + if (ret) + return ret; + + id1 = id16 >> 8; + id2 = id16 & SW_CHIP_ID_M; + if (id1 != FAMILY_ID || + (id2 != CHIP_ID_94 && id2 != CHIP_ID_95)) + return -ENODEV; + + dev->mib_port_cnt = TOTAL_PORT_NUM; + dev->phy_port_cnt = SWITCH_PORT_NUM; + dev->port_cnt = SWITCH_PORT_NUM; + + if (id2 == CHIP_ID_95) { + u8 val; + + id2 = 0x95; + ksz_read8(dev, REG_PORT_1_STATUS_0, &val); + if (val & PORT_FIBER_MODE) + id2 = 0x65; + } else if (id2 == CHIP_ID_94) { + dev->port_cnt--; + dev->last_port = dev->port_cnt; + id2 = 0x94; + } + id16 &= ~0xff; + id16 |= id2; + dev->chip_id = id16; + + dev->cpu_port = dev->mib_port_cnt - 1; + dev->host_mask = BIT(dev->cpu_port); + + return 0; +} + +struct ksz_chip_data { + u16 chip_id; + const char *dev_name; + int num_vlans; + int num_alus; + int num_statics; + int cpu_ports; + int port_cnt; +}; + +static const struct ksz_chip_data ksz8795_switch_chips[] = { + { + .chip_id = 0x8795, + .dev_name = "KSZ8795", + .num_vlans = 4096, + .num_alus = 0, + .num_statics = 8, + .cpu_ports = 0x10, /* can be configured as cpu port */ + .port_cnt = 4, /* total physical port count */ + }, + { + .chip_id = 0x8794, + .dev_name = "KSZ8794", + .num_vlans = 4096, + .num_alus = 0, + .num_statics = 8, + .cpu_ports = 0x10, /* can be configured as cpu port */ + .port_cnt = 3, /* total physical port count */ + }, + { + .chip_id = 0x8765, + .dev_name = "KSZ8765", + .num_vlans = 4096, + .num_alus = 0, + .num_statics = 8, + .cpu_ports = 0x10, /* can be configured as cpu port */ + .port_cnt = 4, /* total physical port count */ + }, +}; + +static int ksz8795_switch_init(struct ksz_device *dev) +{ + int i; + + mutex_init(&dev->stats_mutex); + mutex_init(&dev->alu_mutex); + mutex_init(&dev->vlan_mutex); + + dev->ds->ops = &ksz8795_switch_ops; + + for (i = 0; i < ARRAY_SIZE(ksz8795_switch_chips); i++) { + const struct ksz_chip_data *chip = &ksz8795_switch_chips[i]; + + if (dev->chip_id == chip->chip_id) { + dev->name = chip->dev_name; + dev->num_vlans = chip->num_vlans; + dev->num_alus = chip->num_alus; + dev->num_statics = chip->num_statics; + dev->port_cnt = chip->port_cnt; + dev->cpu_ports = chip->cpu_ports; + + break; + } + } + + /* no switch found */ + if (!dev->cpu_ports) + return -ENODEV; + + dev->port_mask = BIT(dev->port_cnt) - 1; + dev->port_mask |= dev->host_mask; + + dev->reg_mib_cnt = SWITCH_COUNTER_NUM; + dev->mib_cnt = TOTAL_SWITCH_COUNTER_NUM; + + i = dev->mib_port_cnt; + dev->ports = devm_kzalloc(dev->dev, sizeof(struct ksz_port) * i, + GFP_KERNEL); + if (!dev->ports) + return -ENOMEM; + for (i = 0; i < dev->mib_port_cnt; i++) { + mutex_init(&dev->ports[i].mib.cnt_mutex); + dev->ports[i].mib.counters = + devm_kzalloc(dev->dev, + sizeof(u64) * + (TOTAL_SWITCH_COUNTER_NUM + 1), + GFP_KERNEL); + if (!dev->ports[i].mib.counters) + return -ENOMEM; + } + + return 0; +} + +static void ksz8795_switch_exit(struct ksz_device *dev) +{ + ksz8795_reset_switch(dev); +} + +static const struct ksz_dev_ops ksz8795_dev_ops = { + .get_port_addr = ksz8795_get_port_addr, + .cfg_port_member = ksz8795_cfg_port_member, + .flush_dyn_mac_table = ksz8795_flush_dyn_mac_table, + .port_setup = ksz8795_port_setup, + .r_phy = ksz8795_r_phy, + .w_phy = ksz8795_w_phy, + .r_dyn_mac_table = ksz8795_r_dyn_mac_table, + .r_sta_mac_table = ksz8795_r_sta_mac_table, + .w_sta_mac_table = ksz8795_w_sta_mac_table, + .r_mib_cnt = ksz8795_r_mib_cnt, + .r_mib_pkt = ksz8795_r_mib_pkt, + .freeze_mib = ksz8795_freeze_mib, + .port_init_cnt = ksz8795_port_init_cnt, + .shutdown = ksz8795_reset_switch, + .detect = ksz8795_switch_detect, + .init = ksz8795_switch_init, + .exit = ksz8795_switch_exit, +}; + +int ksz8795_switch_register(struct ksz_device *dev) +{ + return ksz_switch_register(dev, &ksz8795_dev_ops); +} +EXPORT_SYMBOL(ksz8795_switch_register); + +MODULE_AUTHOR("Tristram Ha <Tristram.Ha@microchip.com>"); +MODULE_DESCRIPTION("Microchip KSZ8795 Series Switch DSA Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/dsa/microchip/ksz8795_reg.h b/drivers/net/dsa/microchip/ksz8795_reg.h new file mode 100644 index 000000000000..3a50462df8fa --- /dev/null +++ b/drivers/net/dsa/microchip/ksz8795_reg.h @@ -0,0 +1,1004 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Microchip KSZ8795 register definitions + * + * Copyright (c) 2017 Microchip Technology Inc. + * Tristram Ha <Tristram.Ha@microchip.com> + */ + +#ifndef __KSZ8795_REG_H +#define __KSZ8795_REG_H + +#define KS_PORT_M 0x1F + +#define KS_PRIO_M 0x3 +#define KS_PRIO_S 2 + +#define REG_CHIP_ID0 0x00 + +#define FAMILY_ID 0x87 + +#define REG_CHIP_ID1 0x01 + +#define SW_CHIP_ID_M 0xF0 +#define SW_CHIP_ID_S 4 +#define SW_REVISION_M 0x0E +#define SW_REVISION_S 1 +#define SW_START 0x01 + +#define CHIP_ID_94 0x60 +#define CHIP_ID_95 0x90 + +#define REG_SW_CTRL_0 0x02 + +#define SW_NEW_BACKOFF BIT(7) +#define SW_GLOBAL_RESET BIT(6) +#define SW_FLUSH_DYN_MAC_TABLE BIT(5) +#define SW_FLUSH_STA_MAC_TABLE BIT(4) +#define SW_LINK_AUTO_AGING BIT(0) + +#define REG_SW_CTRL_1 0x03 + +#define SW_HUGE_PACKET BIT(6) +#define SW_TX_FLOW_CTRL_DISABLE BIT(5) +#define SW_RX_FLOW_CTRL_DISABLE BIT(4) +#define SW_CHECK_LENGTH BIT(3) +#define SW_AGING_ENABLE BIT(2) +#define SW_FAST_AGING BIT(1) +#define SW_AGGR_BACKOFF BIT(0) + +#define REG_SW_CTRL_2 0x04 + +#define UNICAST_VLAN_BOUNDARY BIT(7) +#define MULTICAST_STORM_DISABLE BIT(6) +#define SW_BACK_PRESSURE BIT(5) +#define FAIR_FLOW_CTRL BIT(4) +#define NO_EXC_COLLISION_DROP BIT(3) +#define SW_LEGAL_PACKET_DISABLE BIT(1) + +#define REG_SW_CTRL_3 0x05 + #define WEIGHTED_FAIR_QUEUE_ENABLE BIT(3) + +#define SW_VLAN_ENABLE BIT(7) +#define SW_IGMP_SNOOP BIT(6) +#define SW_MIRROR_RX_TX BIT(0) + +#define REG_SW_CTRL_4 0x06 + +#define SW_HALF_DUPLEX_FLOW_CTRL BIT(7) +#define SW_HALF_DUPLEX BIT(6) +#define SW_FLOW_CTRL BIT(5) +#define SW_10_MBIT BIT(4) +#define SW_REPLACE_VID BIT(3) +#define BROADCAST_STORM_RATE_HI 0x07 + +#define REG_SW_CTRL_5 0x07 + +#define BROADCAST_STORM_RATE_LO 0xFF +#define BROADCAST_STORM_RATE 0x07FF + +#define REG_SW_CTRL_6 0x08 + +#define SW_MIB_COUNTER_FLUSH BIT(7) +#define SW_MIB_COUNTER_FREEZE BIT(6) +#define SW_MIB_COUNTER_CTRL_ENABLE KS_PORT_M + +#define REG_SW_CTRL_9 0x0B + +#define SPI_CLK_125_MHZ 0x80 +#define SPI_CLK_62_5_MHZ 0x40 +#define SPI_CLK_31_25_MHZ 0x00 + +#define SW_LED_MODE_M 0x3 +#define SW_LED_MODE_S 4 +#define SW_LED_LINK_ACT_SPEED 0 +#define SW_LED_LINK_ACT 1 +#define SW_LED_LINK_ACT_DUPLEX 2 +#define SW_LED_LINK_DUPLEX 3 + +#define REG_SW_CTRL_10 0x0C + +#define SW_TAIL_TAG_ENABLE BIT(1) +#define SW_PASS_PAUSE BIT(0) + +#define REG_SW_CTRL_11 0x0D + +#define REG_POWER_MANAGEMENT_1 0x0E + +#define SW_PLL_POWER_DOWN BIT(5) +#define SW_POWER_MANAGEMENT_MODE_M 0x3 +#define SW_POWER_MANAGEMENT_MODE_S 3 +#define SW_POWER_NORMAL 0 +#define SW_ENERGY_DETECTION 1 +#define SW_SOFTWARE_POWER_DOWN 2 + +#define REG_POWER_MANAGEMENT_2 0x0F + +#define REG_PORT_1_CTRL_0 0x10 +#define REG_PORT_2_CTRL_0 0x20 +#define REG_PORT_3_CTRL_0 0x30 +#define REG_PORT_4_CTRL_0 0x40 +#define REG_PORT_5_CTRL_0 0x50 + +#define PORT_BROADCAST_STORM BIT(7) +#define PORT_DIFFSERV_ENABLE BIT(6) +#define PORT_802_1P_ENABLE BIT(5) +#define PORT_BASED_PRIO_S 3 +#define PORT_BASED_PRIO_M KS_PRIO_M +#define PORT_BASED_PRIO_0 0 +#define PORT_BASED_PRIO_1 1 +#define PORT_BASED_PRIO_2 2 +#define PORT_BASED_PRIO_3 3 +#define PORT_INSERT_TAG BIT(2) +#define PORT_REMOVE_TAG BIT(1) +#define PORT_QUEUE_SPLIT_L BIT(0) + +#define REG_PORT_1_CTRL_1 0x11 +#define REG_PORT_2_CTRL_1 0x21 +#define REG_PORT_3_CTRL_1 0x31 +#define REG_PORT_4_CTRL_1 0x41 +#define REG_PORT_5_CTRL_1 0x51 + +#define PORT_MIRROR_SNIFFER BIT(7) +#define PORT_MIRROR_RX BIT(6) +#define PORT_MIRROR_TX BIT(5) +#define PORT_VLAN_MEMBERSHIP KS_PORT_M + +#define REG_PORT_1_CTRL_2 0x12 +#define REG_PORT_2_CTRL_2 0x22 +#define REG_PORT_3_CTRL_2 0x32 +#define REG_PORT_4_CTRL_2 0x42 +#define REG_PORT_5_CTRL_2 0x52 + +#define PORT_802_1P_REMAPPING BIT(7) +#define PORT_INGRESS_FILTER BIT(6) +#define PORT_DISCARD_NON_VID BIT(5) +#define PORT_FORCE_FLOW_CTRL BIT(4) +#define PORT_BACK_PRESSURE BIT(3) +#define PORT_TX_ENABLE BIT(2) +#define PORT_RX_ENABLE BIT(1) +#define PORT_LEARN_DISABLE BIT(0) + +#define REG_PORT_1_CTRL_3 0x13 +#define REG_PORT_2_CTRL_3 0x23 +#define REG_PORT_3_CTRL_3 0x33 +#define REG_PORT_4_CTRL_3 0x43 +#define REG_PORT_5_CTRL_3 0x53 +#define REG_PORT_1_CTRL_4 0x14 +#define REG_PORT_2_CTRL_4 0x24 +#define REG_PORT_3_CTRL_4 0x34 +#define REG_PORT_4_CTRL_4 0x44 +#define REG_PORT_5_CTRL_4 0x54 + +#define PORT_DEFAULT_VID 0x0001 + +#define REG_PORT_1_CTRL_5 0x15 +#define REG_PORT_2_CTRL_5 0x25 +#define REG_PORT_3_CTRL_5 0x35 +#define REG_PORT_4_CTRL_5 0x45 +#define REG_PORT_5_CTRL_5 0x55 + +#define PORT_ACL_ENABLE BIT(2) +#define PORT_AUTHEN_MODE 0x3 +#define PORT_AUTHEN_PASS 0 +#define PORT_AUTHEN_BLOCK 1 +#define PORT_AUTHEN_TRAP 2 + +#define REG_PORT_5_CTRL_6 0x56 + +#define PORT_MII_INTERNAL_CLOCK BIT(7) +#define PORT_GMII_1GPS_MODE BIT(6) +#define PORT_RGMII_ID_IN_ENABLE BIT(4) +#define PORT_RGMII_ID_OUT_ENABLE BIT(3) +#define PORT_GMII_MAC_MODE BIT(2) +#define PORT_INTERFACE_TYPE 0x3 +#define PORT_INTERFACE_MII 0 +#define PORT_INTERFACE_RMII 1 +#define PORT_INTERFACE_GMII 2 +#define PORT_INTERFACE_RGMII 3 + +#define REG_PORT_1_CTRL_7 0x17 +#define REG_PORT_2_CTRL_7 0x27 +#define REG_PORT_3_CTRL_7 0x37 +#define REG_PORT_4_CTRL_7 0x47 + +#define PORT_AUTO_NEG_ASYM_PAUSE BIT(5) +#define PORT_AUTO_NEG_SYM_PAUSE BIT(4) +#define PORT_AUTO_NEG_100BTX_FD BIT(3) +#define PORT_AUTO_NEG_100BTX BIT(2) +#define PORT_AUTO_NEG_10BT_FD BIT(1) +#define PORT_AUTO_NEG_10BT BIT(0) + +#define REG_PORT_1_STATUS_0 0x18 +#define REG_PORT_2_STATUS_0 0x28 +#define REG_PORT_3_STATUS_0 0x38 +#define REG_PORT_4_STATUS_0 0x48 + +/* For KSZ8765. */ +#define PORT_FIBER_MODE BIT(7) + +#define PORT_REMOTE_ASYM_PAUSE BIT(5) +#define PORT_REMOTE_SYM_PAUSE BIT(4) +#define PORT_REMOTE_100BTX_FD BIT(3) +#define PORT_REMOTE_100BTX BIT(2) +#define PORT_REMOTE_10BT_FD BIT(1) +#define PORT_REMOTE_10BT BIT(0) + +#define REG_PORT_1_STATUS_1 0x19 +#define REG_PORT_2_STATUS_1 0x29 +#define REG_PORT_3_STATUS_1 0x39 +#define REG_PORT_4_STATUS_1 0x49 + +#define PORT_HP_MDIX BIT(7) +#define PORT_REVERSED_POLARITY BIT(5) +#define PORT_TX_FLOW_CTRL BIT(4) +#define PORT_RX_FLOW_CTRL BIT(3) +#define PORT_STAT_SPEED_100MBIT BIT(2) +#define PORT_STAT_FULL_DUPLEX BIT(1) + +#define PORT_REMOTE_FAULT BIT(0) + +#define REG_PORT_1_LINK_MD_CTRL 0x1A +#define REG_PORT_2_LINK_MD_CTRL 0x2A +#define REG_PORT_3_LINK_MD_CTRL 0x3A +#define REG_PORT_4_LINK_MD_CTRL 0x4A + +#define PORT_CABLE_10M_SHORT BIT(7) +#define PORT_CABLE_DIAG_RESULT_M 0x3 +#define PORT_CABLE_DIAG_RESULT_S 5 +#define PORT_CABLE_STAT_NORMAL 0 +#define PORT_CABLE_STAT_OPEN 1 +#define PORT_CABLE_STAT_SHORT 2 +#define PORT_CABLE_STAT_FAILED 3 +#define PORT_START_CABLE_DIAG BIT(4) +#define PORT_FORCE_LINK BIT(3) +#define PORT_POWER_SAVING BIT(2) +#define PORT_PHY_REMOTE_LOOPBACK BIT(1) +#define PORT_CABLE_FAULT_COUNTER_H 0x01 + +#define REG_PORT_1_LINK_MD_RESULT 0x1B +#define REG_PORT_2_LINK_MD_RESULT 0x2B +#define REG_PORT_3_LINK_MD_RESULT 0x3B +#define REG_PORT_4_LINK_MD_RESULT 0x4B + +#define PORT_CABLE_FAULT_COUNTER_L 0xFF +#define PORT_CABLE_FAULT_COUNTER 0x1FF + +#define REG_PORT_1_CTRL_9 0x1C +#define REG_PORT_2_CTRL_9 0x2C +#define REG_PORT_3_CTRL_9 0x3C +#define REG_PORT_4_CTRL_9 0x4C + +#define PORT_AUTO_NEG_DISABLE BIT(7) +#define PORT_FORCE_100_MBIT BIT(6) +#define PORT_FORCE_FULL_DUPLEX BIT(5) + +#define REG_PORT_1_CTRL_10 0x1D +#define REG_PORT_2_CTRL_10 0x2D +#define REG_PORT_3_CTRL_10 0x3D +#define REG_PORT_4_CTRL_10 0x4D + +#define PORT_LED_OFF BIT(7) +#define PORT_TX_DISABLE BIT(6) +#define PORT_AUTO_NEG_RESTART BIT(5) +#define PORT_POWER_DOWN BIT(3) +#define PORT_AUTO_MDIX_DISABLE BIT(2) +#define PORT_FORCE_MDIX BIT(1) +#define PORT_MAC_LOOPBACK BIT(0) + +#define REG_PORT_1_STATUS_2 0x1E +#define REG_PORT_2_STATUS_2 0x2E +#define REG_PORT_3_STATUS_2 0x3E +#define REG_PORT_4_STATUS_2 0x4E + +#define PORT_MDIX_STATUS BIT(7) +#define PORT_AUTO_NEG_COMPLETE BIT(6) +#define PORT_STAT_LINK_GOOD BIT(5) + +#define REG_PORT_1_STATUS_3 0x1F +#define REG_PORT_2_STATUS_3 0x2F +#define REG_PORT_3_STATUS_3 0x3F +#define REG_PORT_4_STATUS_3 0x4F + +#define PORT_PHY_LOOPBACK BIT(7) +#define PORT_PHY_ISOLATE BIT(5) +#define PORT_PHY_SOFT_RESET BIT(4) +#define PORT_PHY_FORCE_LINK BIT(3) +#define PORT_PHY_MODE_M 0x7 +#define PHY_MODE_IN_AUTO_NEG 1 +#define PHY_MODE_10BT_HALF 2 +#define PHY_MODE_100BT_HALF 3 +#define PHY_MODE_10BT_FULL 5 +#define PHY_MODE_100BT_FULL 6 +#define PHY_MODE_ISOLDATE 7 + +#define REG_PORT_CTRL_0 0x00 +#define REG_PORT_CTRL_1 0x01 +#define REG_PORT_CTRL_2 0x02 +#define REG_PORT_CTRL_VID 0x03 + +#define REG_PORT_CTRL_5 0x05 + +#define REG_PORT_CTRL_7 0x07 +#define REG_PORT_STATUS_0 0x08 +#define REG_PORT_STATUS_1 0x09 +#define REG_PORT_LINK_MD_CTRL 0x0A +#define REG_PORT_LINK_MD_RESULT 0x0B +#define REG_PORT_CTRL_9 0x0C +#define REG_PORT_CTRL_10 0x0D +#define REG_PORT_STATUS_2 0x0E +#define REG_PORT_STATUS_3 0x0F + +#define REG_PORT_CTRL_12 0xA0 +#define REG_PORT_CTRL_13 0xA1 +#define REG_PORT_RATE_CTRL_3 0xA2 +#define REG_PORT_RATE_CTRL_2 0xA3 +#define REG_PORT_RATE_CTRL_1 0xA4 +#define REG_PORT_RATE_CTRL_0 0xA5 +#define REG_PORT_RATE_LIMIT 0xA6 +#define REG_PORT_IN_RATE_0 0xA7 +#define REG_PORT_IN_RATE_1 0xA8 +#define REG_PORT_IN_RATE_2 0xA9 +#define REG_PORT_IN_RATE_3 0xAA +#define REG_PORT_OUT_RATE_0 0xAB +#define REG_PORT_OUT_RATE_1 0xAC +#define REG_PORT_OUT_RATE_2 0xAD +#define REG_PORT_OUT_RATE_3 0xAE + +#define PORT_CTRL_ADDR(port, addr) \ + ((addr) + REG_PORT_1_CTRL_0 + (port) * \ + (REG_PORT_2_CTRL_0 - REG_PORT_1_CTRL_0)) + +#define REG_SW_MAC_ADDR_0 0x68 +#define REG_SW_MAC_ADDR_1 0x69 +#define REG_SW_MAC_ADDR_2 0x6A +#define REG_SW_MAC_ADDR_3 0x6B +#define REG_SW_MAC_ADDR_4 0x6C +#define REG_SW_MAC_ADDR_5 0x6D + +#define REG_IND_CTRL_0 0x6E + +#define TABLE_EXT_SELECT_S 5 +#define TABLE_EEE_V 1 +#define TABLE_ACL_V 2 +#define TABLE_PME_V 4 +#define TABLE_LINK_MD_V 5 +#define TABLE_EEE (TABLE_EEE_V << TABLE_EXT_SELECT_S) +#define TABLE_ACL (TABLE_ACL_V << TABLE_EXT_SELECT_S) +#define TABLE_PME (TABLE_PME_V << TABLE_EXT_SELECT_S) +#define TABLE_LINK_MD (TABLE_LINK_MD << TABLE_EXT_SELECT_S) +#define TABLE_READ BIT(4) +#define TABLE_SELECT_S 2 +#define TABLE_STATIC_MAC_V 0 +#define TABLE_VLAN_V 1 +#define TABLE_DYNAMIC_MAC_V 2 +#define TABLE_MIB_V 3 +#define TABLE_STATIC_MAC (TABLE_STATIC_MAC_V << TABLE_SELECT_S) +#define TABLE_VLAN (TABLE_VLAN_V << TABLE_SELECT_S) +#define TABLE_DYNAMIC_MAC (TABLE_DYNAMIC_MAC_V << TABLE_SELECT_S) +#define TABLE_MIB (TABLE_MIB_V << TABLE_SELECT_S) + +#define REG_IND_CTRL_1 0x6F + +#define TABLE_ENTRY_MASK 0x03FF +#define TABLE_EXT_ENTRY_MASK 0x0FFF + +#define REG_IND_DATA_8 0x70 +#define REG_IND_DATA_7 0x71 +#define REG_IND_DATA_6 0x72 +#define REG_IND_DATA_5 0x73 +#define REG_IND_DATA_4 0x74 +#define REG_IND_DATA_3 0x75 +#define REG_IND_DATA_2 0x76 +#define REG_IND_DATA_1 0x77 +#define REG_IND_DATA_0 0x78 + +#define REG_IND_DATA_PME_EEE_ACL 0xA0 + +#define REG_IND_DATA_CHECK REG_IND_DATA_6 +#define REG_IND_MIB_CHECK REG_IND_DATA_4 +#define REG_IND_DATA_HI REG_IND_DATA_7 +#define REG_IND_DATA_LO REG_IND_DATA_3 + +#define REG_INT_STATUS 0x7C +#define REG_INT_ENABLE 0x7D + +#define INT_PME BIT(4) + +#define REG_ACL_INT_STATUS 0x7E +#define REG_ACL_INT_ENABLE 0x7F + +#define INT_PORT_5 BIT(4) +#define INT_PORT_4 BIT(3) +#define INT_PORT_3 BIT(2) +#define INT_PORT_2 BIT(1) +#define INT_PORT_1 BIT(0) + +#define INT_PORT_ALL \ + (INT_PORT_5 | INT_PORT_4 | INT_PORT_3 | INT_PORT_2 | INT_PORT_1) + +#define REG_SW_CTRL_12 0x80 +#define REG_SW_CTRL_13 0x81 + +#define SWITCH_802_1P_MASK 3 +#define SWITCH_802_1P_BASE 3 +#define SWITCH_802_1P_SHIFT 2 + +#define SW_802_1P_MAP_M KS_PRIO_M +#define SW_802_1P_MAP_S KS_PRIO_S + +#define REG_SWITCH_CTRL_14 0x82 + +#define SW_PRIO_MAPPING_M KS_PRIO_M +#define SW_PRIO_MAPPING_S 6 +#define SW_PRIO_MAP_3_HI 0 +#define SW_PRIO_MAP_2_HI 2 +#define SW_PRIO_MAP_0_LO 3 + +#define REG_SW_CTRL_15 0x83 +#define REG_SW_CTRL_16 0x84 +#define REG_SW_CTRL_17 0x85 +#define REG_SW_CTRL_18 0x86 + +#define SW_SELF_ADDR_FILTER_ENABLE BIT(6) + +#define REG_SW_UNK_UCAST_CTRL 0x83 +#define REG_SW_UNK_MCAST_CTRL 0x84 +#define REG_SW_UNK_VID_CTRL 0x85 +#define REG_SW_UNK_IP_MCAST_CTRL 0x86 + +#define SW_UNK_FWD_ENABLE BIT(5) +#define SW_UNK_FWD_MAP KS_PORT_M + +#define REG_SW_CTRL_19 0x87 + +#define SW_IN_RATE_LIMIT_PERIOD_M 0x3 +#define SW_IN_RATE_LIMIT_PERIOD_S 4 +#define SW_IN_RATE_LIMIT_16_MS 0 +#define SW_IN_RATE_LIMIT_64_MS 1 +#define SW_IN_RATE_LIMIT_256_MS 2 +#define SW_OUT_RATE_LIMIT_QUEUE_BASED BIT(3) +#define SW_INS_TAG_ENABLE BIT(2) + +#define REG_TOS_PRIO_CTRL_0 0x90 +#define REG_TOS_PRIO_CTRL_1 0x91 +#define REG_TOS_PRIO_CTRL_2 0x92 +#define REG_TOS_PRIO_CTRL_3 0x93 +#define REG_TOS_PRIO_CTRL_4 0x94 +#define REG_TOS_PRIO_CTRL_5 0x95 +#define REG_TOS_PRIO_CTRL_6 0x96 +#define REG_TOS_PRIO_CTRL_7 0x97 +#define REG_TOS_PRIO_CTRL_8 0x98 +#define REG_TOS_PRIO_CTRL_9 0x99 +#define REG_TOS_PRIO_CTRL_10 0x9A +#define REG_TOS_PRIO_CTRL_11 0x9B +#define REG_TOS_PRIO_CTRL_12 0x9C +#define REG_TOS_PRIO_CTRL_13 0x9D +#define REG_TOS_PRIO_CTRL_14 0x9E +#define REG_TOS_PRIO_CTRL_15 0x9F + +#define TOS_PRIO_M KS_PRIO_M +#define TOS_PRIO_S KS_PRIO_S + +#define REG_SW_CTRL_20 0xA3 + +#define SW_GMII_DRIVE_STRENGTH_S 4 +#define SW_DRIVE_STRENGTH_M 0x7 +#define SW_DRIVE_STRENGTH_2MA 0 +#define SW_DRIVE_STRENGTH_4MA 1 +#define SW_DRIVE_STRENGTH_8MA 2 +#define SW_DRIVE_STRENGTH_12MA 3 +#define SW_DRIVE_STRENGTH_16MA 4 +#define SW_DRIVE_STRENGTH_20MA 5 +#define SW_DRIVE_STRENGTH_24MA 6 +#define SW_DRIVE_STRENGTH_28MA 7 +#define SW_MII_DRIVE_STRENGTH_S 0 + +#define REG_SW_CTRL_21 0xA4 + +#define SW_IPV6_MLD_OPTION BIT(3) +#define SW_IPV6_MLD_SNOOP BIT(2) + +#define REG_PORT_1_CTRL_12 0xB0 +#define REG_PORT_2_CTRL_12 0xC0 +#define REG_PORT_3_CTRL_12 0xD0 +#define REG_PORT_4_CTRL_12 0xE0 +#define REG_PORT_5_CTRL_12 0xF0 + +#define PORT_PASS_ALL BIT(6) +#define PORT_INS_TAG_FOR_PORT_5_S 3 +#define PORT_INS_TAG_FOR_PORT_5 BIT(3) +#define PORT_INS_TAG_FOR_PORT_4 BIT(2) +#define PORT_INS_TAG_FOR_PORT_3 BIT(1) +#define PORT_INS_TAG_FOR_PORT_2 BIT(0) + +#define REG_PORT_1_CTRL_13 0xB1 +#define REG_PORT_2_CTRL_13 0xC1 +#define REG_PORT_3_CTRL_13 0xD1 +#define REG_PORT_4_CTRL_13 0xE1 +#define REG_PORT_5_CTRL_13 0xF1 + +#define PORT_QUEUE_SPLIT_H BIT(1) +#define PORT_QUEUE_SPLIT_1 0 +#define PORT_QUEUE_SPLIT_2 1 +#define PORT_QUEUE_SPLIT_4 2 +#define PORT_DROP_TAG BIT(0) + +#define REG_PORT_1_CTRL_14 0xB2 +#define REG_PORT_2_CTRL_14 0xC2 +#define REG_PORT_3_CTRL_14 0xD2 +#define REG_PORT_4_CTRL_14 0xE2 +#define REG_PORT_5_CTRL_14 0xF2 +#define REG_PORT_1_CTRL_15 0xB3 +#define REG_PORT_2_CTRL_15 0xC3 +#define REG_PORT_3_CTRL_15 0xD3 +#define REG_PORT_4_CTRL_15 0xE3 +#define REG_PORT_5_CTRL_15 0xF3 +#define REG_PORT_1_CTRL_16 0xB4 +#define REG_PORT_2_CTRL_16 0xC4 +#define REG_PORT_3_CTRL_16 0xD4 +#define REG_PORT_4_CTRL_16 0xE4 +#define REG_PORT_5_CTRL_16 0xF4 +#define REG_PORT_1_CTRL_17 0xB5 +#define REG_PORT_2_CTRL_17 0xC5 +#define REG_PORT_3_CTRL_17 0xD5 +#define REG_PORT_4_CTRL_17 0xE5 +#define REG_PORT_5_CTRL_17 0xF5 + +#define REG_PORT_1_RATE_CTRL_3 0xB2 +#define REG_PORT_1_RATE_CTRL_2 0xB3 +#define REG_PORT_1_RATE_CTRL_1 0xB4 +#define REG_PORT_1_RATE_CTRL_0 0xB5 +#define REG_PORT_2_RATE_CTRL_3 0xC2 +#define REG_PORT_2_RATE_CTRL_2 0xC3 +#define REG_PORT_2_RATE_CTRL_1 0xC4 +#define REG_PORT_2_RATE_CTRL_0 0xC5 +#define REG_PORT_3_RATE_CTRL_3 0xD2 +#define REG_PORT_3_RATE_CTRL_2 0xD3 +#define REG_PORT_3_RATE_CTRL_1 0xD4 +#define REG_PORT_3_RATE_CTRL_0 0xD5 +#define REG_PORT_4_RATE_CTRL_3 0xE2 +#define REG_PORT_4_RATE_CTRL_2 0xE3 +#define REG_PORT_4_RATE_CTRL_1 0xE4 +#define REG_PORT_4_RATE_CTRL_0 0xE5 +#define REG_PORT_5_RATE_CTRL_3 0xF2 +#define REG_PORT_5_RATE_CTRL_2 0xF3 +#define REG_PORT_5_RATE_CTRL_1 0xF4 +#define REG_PORT_5_RATE_CTRL_0 0xF5 + +#define RATE_CTRL_ENABLE BIT(7) +#define RATE_RATIO_M (BIT(7) - 1) + +#define PORT_OUT_RATE_ENABLE BIT(7) + +#define REG_PORT_1_RATE_LIMIT 0xB6 +#define REG_PORT_2_RATE_LIMIT 0xC6 +#define REG_PORT_3_RATE_LIMIT 0xD6 +#define REG_PORT_4_RATE_LIMIT 0xE6 +#define REG_PORT_5_RATE_LIMIT 0xF6 + +#define PORT_IN_PORT_BASED_S 6 +#define PORT_RATE_PACKET_BASED_S 5 +#define PORT_IN_FLOW_CTRL_S 4 +#define PORT_IN_LIMIT_MODE_M 0x3 +#define PORT_IN_LIMIT_MODE_S 2 +#define PORT_COUNT_IFG_S 1 +#define PORT_COUNT_PREAMBLE_S 0 +#define PORT_IN_PORT_BASED BIT(PORT_IN_PORT_BASED_S) +#define PORT_RATE_PACKET_BASED BIT(PORT_RATE_PACKET_BASED_S) +#define PORT_IN_FLOW_CTRL BIT(PORT_IN_FLOW_CTRL_S) +#define PORT_IN_ALL 0 +#define PORT_IN_UNICAST 1 +#define PORT_IN_MULTICAST 2 +#define PORT_IN_BROADCAST 3 +#define PORT_COUNT_IFG BIT(PORT_COUNT_IFG_S) +#define PORT_COUNT_PREAMBLE BIT(PORT_COUNT_PREAMBLE_S) + +#define REG_PORT_1_IN_RATE_0 0xB7 +#define REG_PORT_2_IN_RATE_0 0xC7 +#define REG_PORT_3_IN_RATE_0 0xD7 +#define REG_PORT_4_IN_RATE_0 0xE7 +#define REG_PORT_5_IN_RATE_0 0xF7 +#define REG_PORT_1_IN_RATE_1 0xB8 +#define REG_PORT_2_IN_RATE_1 0xC8 +#define REG_PORT_3_IN_RATE_1 0xD8 +#define REG_PORT_4_IN_RATE_1 0xE8 +#define REG_PORT_5_IN_RATE_1 0xF8 +#define REG_PORT_1_IN_RATE_2 0xB9 +#define REG_PORT_2_IN_RATE_2 0xC9 +#define REG_PORT_3_IN_RATE_2 0xD9 +#define REG_PORT_4_IN_RATE_2 0xE9 +#define REG_PORT_5_IN_RATE_2 0xF9 +#define REG_PORT_1_IN_RATE_3 0xBA +#define REG_PORT_2_IN_RATE_3 0xCA +#define REG_PORT_3_IN_RATE_3 0xDA +#define REG_PORT_4_IN_RATE_3 0xEA +#define REG_PORT_5_IN_RATE_3 0xFA + +#define PORT_IN_RATE_ENABLE BIT(7) +#define PORT_RATE_LIMIT_M (BIT(7) - 1) + +#define REG_PORT_1_OUT_RATE_0 0xBB +#define REG_PORT_2_OUT_RATE_0 0xCB +#define REG_PORT_3_OUT_RATE_0 0xDB +#define REG_PORT_4_OUT_RATE_0 0xEB +#define REG_PORT_5_OUT_RATE_0 0xFB +#define REG_PORT_1_OUT_RATE_1 0xBC +#define REG_PORT_2_OUT_RATE_1 0xCC +#define REG_PORT_3_OUT_RATE_1 0xDC +#define REG_PORT_4_OUT_RATE_1 0xEC +#define REG_PORT_5_OUT_RATE_1 0xFC +#define REG_PORT_1_OUT_RATE_2 0xBD +#define REG_PORT_2_OUT_RATE_2 0xCD +#define REG_PORT_3_OUT_RATE_2 0xDD +#define REG_PORT_4_OUT_RATE_2 0xED +#define REG_PORT_5_OUT_RATE_2 0xFD +#define REG_PORT_1_OUT_RATE_3 0xBE +#define REG_PORT_2_OUT_RATE_3 0xCE +#define REG_PORT_3_OUT_RATE_3 0xDE +#define REG_PORT_4_OUT_RATE_3 0xEE +#define REG_PORT_5_OUT_RATE_3 0xFE + +/* PME */ + +#define SW_PME_OUTPUT_ENABLE BIT(1) +#define SW_PME_ACTIVE_HIGH BIT(0) + +#define PORT_MAGIC_PACKET_DETECT BIT(2) +#define PORT_LINK_UP_DETECT BIT(1) +#define PORT_ENERGY_DETECT BIT(0) + +/* ACL */ + +#define ACL_FIRST_RULE_M 0xF + +#define ACL_MODE_M 0x3 +#define ACL_MODE_S 4 +#define ACL_MODE_DISABLE 0 +#define ACL_MODE_LAYER_2 1 +#define ACL_MODE_LAYER_3 2 +#define ACL_MODE_LAYER_4 3 +#define ACL_ENABLE_M 0x3 +#define ACL_ENABLE_S 2 +#define ACL_ENABLE_2_COUNT 0 +#define ACL_ENABLE_2_TYPE 1 +#define ACL_ENABLE_2_MAC 2 +#define ACL_ENABLE_2_BOTH 3 +#define ACL_ENABLE_3_IP 1 +#define ACL_ENABLE_3_SRC_DST_COMP 2 +#define ACL_ENABLE_4_PROTOCOL 0 +#define ACL_ENABLE_4_TCP_PORT_COMP 1 +#define ACL_ENABLE_4_UDP_PORT_COMP 2 +#define ACL_ENABLE_4_TCP_SEQN_COMP 3 +#define ACL_SRC BIT(1) +#define ACL_EQUAL BIT(0) + +#define ACL_MAX_PORT 0xFFFF + +#define ACL_MIN_PORT 0xFFFF +#define ACL_IP_ADDR 0xFFFFFFFF +#define ACL_TCP_SEQNUM 0xFFFFFFFF + +#define ACL_RESERVED 0xF8 +#define ACL_PORT_MODE_M 0x3 +#define ACL_PORT_MODE_S 1 +#define ACL_PORT_MODE_DISABLE 0 +#define ACL_PORT_MODE_EITHER 1 +#define ACL_PORT_MODE_IN_RANGE 2 +#define ACL_PORT_MODE_OUT_OF_RANGE 3 + +#define ACL_TCP_FLAG_ENABLE BIT(0) + +#define ACL_TCP_FLAG_M 0xFF + +#define ACL_TCP_FLAG 0xFF +#define ACL_ETH_TYPE 0xFFFF +#define ACL_IP_M 0xFFFFFFFF + +#define ACL_PRIO_MODE_M 0x3 +#define ACL_PRIO_MODE_S 6 +#define ACL_PRIO_MODE_DISABLE 0 +#define ACL_PRIO_MODE_HIGHER 1 +#define ACL_PRIO_MODE_LOWER 2 +#define ACL_PRIO_MODE_REPLACE 3 +#define ACL_PRIO_M 0x7 +#define ACL_PRIO_S 3 +#define ACL_VLAN_PRIO_REPLACE BIT(2) +#define ACL_VLAN_PRIO_M 0x7 +#define ACL_VLAN_PRIO_HI_M 0x3 + +#define ACL_VLAN_PRIO_LO_M 0x8 +#define ACL_VLAN_PRIO_S 7 +#define ACL_MAP_MODE_M 0x3 +#define ACL_MAP_MODE_S 5 +#define ACL_MAP_MODE_DISABLE 0 +#define ACL_MAP_MODE_OR 1 +#define ACL_MAP_MODE_AND 2 +#define ACL_MAP_MODE_REPLACE 3 +#define ACL_MAP_PORT_M 0x1F + +#define ACL_CNT_M (BIT(11) - 1) +#define ACL_CNT_S 5 +#define ACL_MSEC_UNIT BIT(4) +#define ACL_INTR_MODE BIT(3) + +#define REG_PORT_ACL_BYTE_EN_MSB 0x10 + +#define ACL_BYTE_EN_MSB_M 0x3F + +#define REG_PORT_ACL_BYTE_EN_LSB 0x11 + +#define ACL_ACTION_START 0xA +#define ACL_ACTION_LEN 2 +#define ACL_INTR_CNT_START 0xB +#define ACL_RULESET_START 0xC +#define ACL_RULESET_LEN 2 +#define ACL_TABLE_LEN 14 + +#define ACL_ACTION_ENABLE 0x000C +#define ACL_MATCH_ENABLE 0x1FF0 +#define ACL_RULESET_ENABLE 0x2003 +#define ACL_BYTE_ENABLE ((ACL_BYTE_EN_MSB_M << 8) | 0xFF) +#define ACL_MODE_ENABLE (0x10 << 8) + +#define REG_PORT_ACL_CTRL_0 0x12 + +#define PORT_ACL_WRITE_DONE BIT(6) +#define PORT_ACL_READ_DONE BIT(5) +#define PORT_ACL_WRITE BIT(4) +#define PORT_ACL_INDEX_M 0xF + +#define REG_PORT_ACL_CTRL_1 0x13 + +#define PORT_ACL_FORCE_DLR_MISS BIT(0) + +#ifndef PHY_REG_CTRL +#define PHY_REG_CTRL 0 + +#define PHY_RESET BIT(15) +#define PHY_LOOPBACK BIT(14) +#define PHY_SPEED_100MBIT BIT(13) +#define PHY_AUTO_NEG_ENABLE BIT(12) +#define PHY_POWER_DOWN BIT(11) +#define PHY_MII_DISABLE BIT(10) +#define PHY_AUTO_NEG_RESTART BIT(9) +#define PHY_FULL_DUPLEX BIT(8) +#define PHY_COLLISION_TEST_NOT BIT(7) +#define PHY_HP_MDIX BIT(5) +#define PHY_FORCE_MDIX BIT(4) +#define PHY_AUTO_MDIX_DISABLE BIT(3) +#define PHY_REMOTE_FAULT_DISABLE BIT(2) +#define PHY_TRANSMIT_DISABLE BIT(1) +#define PHY_LED_DISABLE BIT(0) + +#define PHY_REG_STATUS 1 + +#define PHY_100BT4_CAPABLE BIT(15) +#define PHY_100BTX_FD_CAPABLE BIT(14) +#define PHY_100BTX_CAPABLE BIT(13) +#define PHY_10BT_FD_CAPABLE BIT(12) +#define PHY_10BT_CAPABLE BIT(11) +#define PHY_MII_SUPPRESS_CAPABLE_NOT BIT(6) +#define PHY_AUTO_NEG_ACKNOWLEDGE BIT(5) +#define PHY_REMOTE_FAULT BIT(4) +#define PHY_AUTO_NEG_CAPABLE BIT(3) +#define PHY_LINK_STATUS BIT(2) +#define PHY_JABBER_DETECT_NOT BIT(1) +#define PHY_EXTENDED_CAPABILITY BIT(0) + +#define PHY_REG_ID_1 2 +#define PHY_REG_ID_2 3 + +#define PHY_REG_AUTO_NEGOTIATION 4 + +#define PHY_AUTO_NEG_NEXT_PAGE_NOT BIT(15) +#define PHY_AUTO_NEG_REMOTE_FAULT_NOT BIT(13) +#define PHY_AUTO_NEG_SYM_PAUSE BIT(10) +#define PHY_AUTO_NEG_100BT4 BIT(9) +#define PHY_AUTO_NEG_100BTX_FD BIT(8) +#define PHY_AUTO_NEG_100BTX BIT(7) +#define PHY_AUTO_NEG_10BT_FD BIT(6) +#define PHY_AUTO_NEG_10BT BIT(5) +#define PHY_AUTO_NEG_SELECTOR 0x001F +#define PHY_AUTO_NEG_802_3 0x0001 + +#define PHY_REG_REMOTE_CAPABILITY 5 + +#define PHY_REMOTE_NEXT_PAGE_NOT BIT(15) +#define PHY_REMOTE_ACKNOWLEDGE_NOT BIT(14) +#define PHY_REMOTE_REMOTE_FAULT_NOT BIT(13) +#define PHY_REMOTE_SYM_PAUSE BIT(10) +#define PHY_REMOTE_100BTX_FD BIT(8) +#define PHY_REMOTE_100BTX BIT(7) +#define PHY_REMOTE_10BT_FD BIT(6) +#define PHY_REMOTE_10BT BIT(5) +#endif + +#define KSZ8795_ID_HI 0x0022 +#define KSZ8795_ID_LO 0x1550 + +#define KSZ8795_SW_ID 0x8795 + +#define PHY_REG_LINK_MD 0x1D + +#define PHY_START_CABLE_DIAG BIT(15) +#define PHY_CABLE_DIAG_RESULT 0x6000 +#define PHY_CABLE_STAT_NORMAL 0x0000 +#define PHY_CABLE_STAT_OPEN 0x2000 +#define PHY_CABLE_STAT_SHORT 0x4000 +#define PHY_CABLE_STAT_FAILED 0x6000 +#define PHY_CABLE_10M_SHORT BIT(12) +#define PHY_CABLE_FAULT_COUNTER 0x01FF + +#define PHY_REG_PHY_CTRL 0x1F + +#define PHY_MODE_M 0x7 +#define PHY_MODE_S 8 +#define PHY_STAT_REVERSED_POLARITY BIT(5) +#define PHY_STAT_MDIX BIT(4) +#define PHY_FORCE_LINK BIT(3) +#define PHY_POWER_SAVING_ENABLE BIT(2) +#define PHY_REMOTE_LOOPBACK BIT(1) + +/* Chip resource */ + +#define PRIO_QUEUES 4 + +#define KS_PRIO_IN_REG 4 + +#define TOTAL_PORT_NUM 5 + +/* Host port can only be last of them. */ +#define SWITCH_PORT_NUM (TOTAL_PORT_NUM - 1) + +#define KSZ8795_COUNTER_NUM 0x20 +#define TOTAL_KSZ8795_COUNTER_NUM (KSZ8795_COUNTER_NUM + 4) + +#define SWITCH_COUNTER_NUM KSZ8795_COUNTER_NUM +#define TOTAL_SWITCH_COUNTER_NUM TOTAL_KSZ8795_COUNTER_NUM + +/* Common names used by other drivers */ + +#define P_BCAST_STORM_CTRL REG_PORT_CTRL_0 +#define P_PRIO_CTRL REG_PORT_CTRL_0 +#define P_TAG_CTRL REG_PORT_CTRL_0 +#define P_MIRROR_CTRL REG_PORT_CTRL_1 +#define P_802_1P_CTRL REG_PORT_CTRL_2 +#define P_STP_CTRL REG_PORT_CTRL_2 +#define P_LOCAL_CTRL REG_PORT_CTRL_7 +#define P_REMOTE_STATUS REG_PORT_STATUS_0 +#define P_FORCE_CTRL REG_PORT_CTRL_9 +#define P_NEG_RESTART_CTRL REG_PORT_CTRL_10 +#define P_SPEED_STATUS REG_PORT_STATUS_1 +#define P_LINK_STATUS REG_PORT_STATUS_2 +#define P_PASS_ALL_CTRL REG_PORT_CTRL_12 +#define P_INS_SRC_PVID_CTRL REG_PORT_CTRL_12 +#define P_DROP_TAG_CTRL REG_PORT_CTRL_13 +#define P_RATE_LIMIT_CTRL REG_PORT_RATE_LIMIT + +#define S_UNKNOWN_DA_CTRL REG_SWITCH_CTRL_12 +#define S_FORWARD_INVALID_VID_CTRL REG_FORWARD_INVALID_VID + +#define S_FLUSH_TABLE_CTRL REG_SW_CTRL_0 +#define S_LINK_AGING_CTRL REG_SW_CTRL_0 +#define S_HUGE_PACKET_CTRL REG_SW_CTRL_1 +#define S_MIRROR_CTRL REG_SW_CTRL_3 +#define S_REPLACE_VID_CTRL REG_SW_CTRL_4 +#define S_PASS_PAUSE_CTRL REG_SW_CTRL_10 +#define S_TAIL_TAG_CTRL REG_SW_CTRL_10 +#define S_802_1P_PRIO_CTRL REG_SW_CTRL_12 +#define S_TOS_PRIO_CTRL REG_TOS_PRIO_CTRL_0 +#define S_IPV6_MLD_CTRL REG_SW_CTRL_21 + +#define IND_ACC_TABLE(table) ((table) << 8) + +/* Driver set switch broadcast storm protection at 10% rate. */ +#define BROADCAST_STORM_PROT_RATE 10 + +/* 148,800 frames * 67 ms / 100 */ +#define BROADCAST_STORM_VALUE 9969 + +/** + * STATIC_MAC_TABLE_ADDR 00-0000FFFF-FFFFFFFF + * STATIC_MAC_TABLE_FWD_PORTS 00-001F0000-00000000 + * STATIC_MAC_TABLE_VALID 00-00200000-00000000 + * STATIC_MAC_TABLE_OVERRIDE 00-00400000-00000000 + * STATIC_MAC_TABLE_USE_FID 00-00800000-00000000 + * STATIC_MAC_TABLE_FID 00-7F000000-00000000 + */ + +#define STATIC_MAC_TABLE_ADDR 0x0000FFFF +#define STATIC_MAC_TABLE_FWD_PORTS 0x001F0000 +#define STATIC_MAC_TABLE_VALID 0x00200000 +#define STATIC_MAC_TABLE_OVERRIDE 0x00400000 +#define STATIC_MAC_TABLE_USE_FID 0x00800000 +#define STATIC_MAC_TABLE_FID 0x7F000000 + +#define STATIC_MAC_FWD_PORTS_S 16 +#define STATIC_MAC_FID_S 24 + +/** + * VLAN_TABLE_FID 00-007F007F-007F007F + * VLAN_TABLE_MEMBERSHIP 00-0F800F80-0F800F80 + * VLAN_TABLE_VALID 00-10001000-10001000 + */ + +#define VLAN_TABLE_FID 0x007F +#define VLAN_TABLE_MEMBERSHIP 0x0F80 +#define VLAN_TABLE_VALID 0x1000 + +#define VLAN_TABLE_MEMBERSHIP_S 7 +#define VLAN_TABLE_S 16 + +/** + * DYNAMIC_MAC_TABLE_ADDR 00-0000FFFF-FFFFFFFF + * DYNAMIC_MAC_TABLE_FID 00-007F0000-00000000 + * DYNAMIC_MAC_TABLE_NOT_READY 00-00800000-00000000 + * DYNAMIC_MAC_TABLE_SRC_PORT 00-07000000-00000000 + * DYNAMIC_MAC_TABLE_TIMESTAMP 00-18000000-00000000 + * DYNAMIC_MAC_TABLE_ENTRIES 7F-E0000000-00000000 + * DYNAMIC_MAC_TABLE_MAC_EMPTY 80-00000000-00000000 + */ + +#define DYNAMIC_MAC_TABLE_ADDR 0x0000FFFF +#define DYNAMIC_MAC_TABLE_FID 0x007F0000 +#define DYNAMIC_MAC_TABLE_SRC_PORT 0x07000000 +#define DYNAMIC_MAC_TABLE_TIMESTAMP 0x18000000 +#define DYNAMIC_MAC_TABLE_ENTRIES 0xE0000000 + +#define DYNAMIC_MAC_TABLE_NOT_READY 0x80 + +#define DYNAMIC_MAC_TABLE_ENTRIES_H 0x7F +#define DYNAMIC_MAC_TABLE_MAC_EMPTY 0x80 + +#define DYNAMIC_MAC_FID_S 16 +#define DYNAMIC_MAC_SRC_PORT_S 24 +#define DYNAMIC_MAC_TIMESTAMP_S 27 +#define DYNAMIC_MAC_ENTRIES_S 29 +#define DYNAMIC_MAC_ENTRIES_H_S 3 + +/** + * MIB_COUNTER_VALUE 00-00000000-3FFFFFFF + * MIB_TOTAL_BYTES 00-0000000F-FFFFFFFF + * MIB_PACKET_DROPPED 00-00000000-0000FFFF + * MIB_COUNTER_VALID 00-00000020-00000000 + * MIB_COUNTER_OVERFLOW 00-00000040-00000000 + */ + +#define MIB_COUNTER_OVERFLOW BIT(6) +#define MIB_COUNTER_VALID BIT(5) + +#define MIB_COUNTER_VALUE 0x3FFFFFFF + +#define KS_MIB_TOTAL_RX_0 0x100 +#define KS_MIB_TOTAL_TX_0 0x101 +#define KS_MIB_PACKET_DROPPED_RX_0 0x102 +#define KS_MIB_PACKET_DROPPED_TX_0 0x103 +#define KS_MIB_TOTAL_RX_1 0x104 +#define KS_MIB_TOTAL_TX_1 0x105 +#define KS_MIB_PACKET_DROPPED_TX_1 0x106 +#define KS_MIB_PACKET_DROPPED_RX_1 0x107 +#define KS_MIB_TOTAL_RX_2 0x108 +#define KS_MIB_TOTAL_TX_2 0x109 +#define KS_MIB_PACKET_DROPPED_TX_2 0x10A +#define KS_MIB_PACKET_DROPPED_RX_2 0x10B +#define KS_MIB_TOTAL_RX_3 0x10C +#define KS_MIB_TOTAL_TX_3 0x10D +#define KS_MIB_PACKET_DROPPED_TX_3 0x10E +#define KS_MIB_PACKET_DROPPED_RX_3 0x10F +#define KS_MIB_TOTAL_RX_4 0x110 +#define KS_MIB_TOTAL_TX_4 0x111 +#define KS_MIB_PACKET_DROPPED_TX_4 0x112 +#define KS_MIB_PACKET_DROPPED_RX_4 0x113 + +#define MIB_PACKET_DROPPED 0x0000FFFF + +#define MIB_TOTAL_BYTES_H 0x0000000F + +#define TAIL_TAG_OVERRIDE BIT(6) +#define TAIL_TAG_LOOKUP BIT(7) + +#define VLAN_TABLE_ENTRIES (4096 / 4) +#define FID_ENTRIES 128 + +#endif diff --git a/drivers/net/dsa/microchip/ksz8795_spi.c b/drivers/net/dsa/microchip/ksz8795_spi.c new file mode 100644 index 000000000000..50aa0d24effb --- /dev/null +++ b/drivers/net/dsa/microchip/ksz8795_spi.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Microchip KSZ8795 series register access through SPI + * + * Copyright (C) 2017 Microchip Technology Inc. + * Tristram Ha <Tristram.Ha@microchip.com> + */ + +#include <asm/unaligned.h> + +#include <linux/delay.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/regmap.h> +#include <linux/spi/spi.h> + +#include "ksz_priv.h" +#include "ksz_common.h" + +#define SPI_ADDR_SHIFT 12 +#define SPI_ADDR_ALIGN 3 +#define SPI_TURNAROUND_SHIFT 1 + +KSZ_REGMAP_TABLE(ksz8795, 16, SPI_ADDR_SHIFT, + SPI_TURNAROUND_SHIFT, SPI_ADDR_ALIGN); + +static int ksz8795_spi_probe(struct spi_device *spi) +{ + struct ksz_device *dev; + int i, ret; + + dev = ksz_switch_alloc(&spi->dev, spi); + if (!dev) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(ksz8795_regmap_config); i++) { + dev->regmap[i] = devm_regmap_init_spi(spi, + &ksz8795_regmap_config + [i]); + if (IS_ERR(dev->regmap[i])) { + ret = PTR_ERR(dev->regmap[i]); + dev_err(&spi->dev, + "Failed to initialize regmap%i: %d\n", + ksz8795_regmap_config[i].val_bits, ret); + return ret; + } + } + + if (spi->dev.platform_data) + dev->pdata = spi->dev.platform_data; + + ret = ksz8795_switch_register(dev); + + /* Main DSA driver may not be started yet. */ + if (ret) + return ret; + + spi_set_drvdata(spi, dev); + + return 0; +} + +static int ksz8795_spi_remove(struct spi_device *spi) +{ + struct ksz_device *dev = spi_get_drvdata(spi); + + if (dev) + ksz_switch_remove(dev); + + return 0; +} + +static void ksz8795_spi_shutdown(struct spi_device *spi) +{ + struct ksz_device *dev = spi_get_drvdata(spi); + + if (dev && dev->dev_ops->shutdown) + dev->dev_ops->shutdown(dev); +} + +static const struct of_device_id ksz8795_dt_ids[] = { + { .compatible = "microchip,ksz8765" }, + { .compatible = "microchip,ksz8794" }, + { .compatible = "microchip,ksz8795" }, + {}, +}; +MODULE_DEVICE_TABLE(of, ksz8795_dt_ids); + +static struct spi_driver ksz8795_spi_driver = { + .driver = { + .name = "ksz8795-switch", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(ksz8795_dt_ids), + }, + .probe = ksz8795_spi_probe, + .remove = ksz8795_spi_remove, + .shutdown = ksz8795_spi_shutdown, +}; + +module_spi_driver(ksz8795_spi_driver); + +MODULE_AUTHOR("Tristram Ha <Tristram.Ha@microchip.com>"); +MODULE_DESCRIPTION("Microchip KSZ8795 Series Switch SPI Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index a3d2d67894bd..ce20cc90f9ef 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -373,7 +373,8 @@ int ksz_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy) /* setup slave port */ dev->dev_ops->port_setup(dev, port, false); - dev->dev_ops->phy_setup(dev, port, phy); + if (dev->dev_ops->phy_setup) + dev->dev_ops->phy_setup(dev, port, phy); /* port_stp_state_set() will be called after to enable the port so * there is no need to do anything. diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h index ee7096d8af07..84fed4a2578b 100644 --- a/drivers/net/dsa/microchip/ksz_common.h +++ b/drivers/net/dsa/microchip/ksz_common.h @@ -68,6 +68,22 @@ static inline int ksz_read32(struct ksz_device *dev, u32 reg, u32 *val) return ret; } +static inline int ksz_read64(struct ksz_device *dev, u32 reg, u64 *val) +{ + u32 value[2]; + int ret; + + ret = regmap_bulk_read(dev->regmap[2], reg, value, 2); + if (!ret) { + /* Ick! ToDo: Add 64bit R/W to regmap on 32bit systems */ + value[0] = swab32(value[0]); + value[1] = swab32(value[1]); + *val = swab64((u64)*value); + } + + return ret; +} + static inline int ksz_write8(struct ksz_device *dev, u32 reg, u8 value) { return regmap_write(dev->regmap[0], reg, value); @@ -83,6 +99,18 @@ static inline int ksz_write32(struct ksz_device *dev, u32 reg, u32 value) return regmap_write(dev->regmap[2], reg, value); } +static inline int ksz_write64(struct ksz_device *dev, u32 reg, u64 value) +{ + u32 val[2]; + + /* Ick! ToDo: Add 64bit R/W to regmap on 32bit systems */ + value = swab64(value); + val[0] = swab32(value & 0xffffffffULL); + val[1] = swab32(value >> 32ULL); + + return regmap_bulk_write(dev->regmap[2], reg, val, 2); +} + static inline void ksz_pread8(struct ksz_device *dev, int port, int offset, u8 *data) { diff --git a/drivers/net/dsa/microchip/ksz_priv.h b/drivers/net/dsa/microchip/ksz_priv.h index beacf0e40f42..44c16aaf775c 100644 --- a/drivers/net/dsa/microchip/ksz_priv.h +++ b/drivers/net/dsa/microchip/ksz_priv.h @@ -150,6 +150,7 @@ int ksz_switch_register(struct ksz_device *dev, const struct ksz_dev_ops *ops); void ksz_switch_remove(struct ksz_device *dev); +int ksz8795_switch_register(struct ksz_device *dev); int ksz9477_switch_register(struct ksz_device *dev); #endif diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 6b17cd961d06..2e500428670c 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1423,7 +1423,6 @@ static int mv88e6xxx_vtu_get(struct mv88e6xxx_chip *chip, u16 vid, /* Initialize a fresh VLAN entry */ memset(entry, 0, sizeof(*entry)); - entry->valid = true; entry->vid = vid; /* Exclude all ports */ @@ -1618,6 +1617,9 @@ static int _mv88e6xxx_port_vlan_add(struct mv88e6xxx_chip *chip, int port, if (err) return err; + if (vlan.valid && vlan.member[port] == member) + return 0; + vlan.valid = true; vlan.member[port] = member; err = mv88e6xxx_vtu_loadpurge(chip, &vlan); diff --git a/drivers/net/ethernet/amd/au1000_eth.c b/drivers/net/ethernet/amd/au1000_eth.c index 650d1bae5f56..1793950f0582 100644 --- a/drivers/net/ethernet/amd/au1000_eth.c +++ b/drivers/net/ethernet/amd/au1000_eth.c @@ -1100,7 +1100,6 @@ static int au1000_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "failed to retrieve IRQ\n"); err = -ENODEV; goto out; } diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-platform.c b/drivers/net/ethernet/amd/xgbe/xgbe-platform.c index d0f3dfb88202..dce9e59e8881 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-platform.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-platform.c @@ -467,10 +467,8 @@ static int xgbe_platform_probe(struct platform_device *pdev) /* Get the device interrupt */ ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err(dev, "platform_get_irq 0 failed\n"); + if (ret < 0) goto err_io; - } pdata->dev_irq = ret; /* Get the per channel DMA interrupts */ @@ -479,12 +477,8 @@ static int xgbe_platform_probe(struct platform_device *pdev) for (i = 0; (i < max) && (dma_irqnum < dma_irqend); i++) { ret = platform_get_irq(pdata->platdev, dma_irqnum++); - if (ret < 0) { - netdev_err(pdata->netdev, - "platform_get_irq %u failed\n", - dma_irqnum - 1); + if (ret < 0) goto err_io; - } pdata->channel_irq[i] = ret; } @@ -496,10 +490,8 @@ static int xgbe_platform_probe(struct platform_device *pdev) /* Get the auto-negotiation interrupt */ ret = platform_get_irq(phy_pdev, phy_irqnum++); - if (ret < 0) { - dev_err(dev, "platform_get_irq phy 0 failed\n"); + if (ret < 0) goto err_io; - } pdata->an_irq = ret; /* Configure the netdev resource */ diff --git a/drivers/net/ethernet/apm/xgene-v2/main.c b/drivers/net/ethernet/apm/xgene-v2/main.c index 79048cc46703..02b4f3af02b5 100644 --- a/drivers/net/ethernet/apm/xgene-v2/main.c +++ b/drivers/net/ethernet/apm/xgene-v2/main.c @@ -54,10 +54,8 @@ static int xge_get_resources(struct xge_pdata *pdata) } ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err(dev, "Unable to get irq\n"); + if (ret < 0) return ret; - } pdata->resources.irq = ret; return 0; diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c index 79924efd4ab7..5f657879134e 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c @@ -694,7 +694,6 @@ bool xgene_ring_mgr_init(struct xgene_enet_pdata *p) static int xgene_enet_reset(struct xgene_enet_pdata *pdata) { struct device *dev = &pdata->pdev->dev; - acpi_status status; if (!xgene_ring_mgr_init(pdata)) return -ENODEV; @@ -713,6 +712,8 @@ static int xgene_enet_reset(struct xgene_enet_pdata *pdata) udelay(5); } else { #ifdef CONFIG_ACPI + acpi_status status; + status = acpi_evaluate_object(ACPI_HANDLE(&pdata->pdev->dev), "_RST", NULL, NULL); if (ACPI_FAILURE(status)) { diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c index 949bff4d2921..d8612131c55e 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c @@ -1617,7 +1617,6 @@ static int xgene_get_rx_delay(struct xgene_enet_pdata *pdata) static int xgene_enet_get_irqs(struct xgene_enet_pdata *pdata) { struct platform_device *pdev = pdata->pdev; - struct device *dev = &pdev->dev; int i, ret, max_irqs; if (phy_interface_mode_is_rgmii(pdata->phy_mode)) @@ -1637,9 +1636,7 @@ static int xgene_enet_get_irqs(struct xgene_enet_pdata *pdata) pdata->cq_cnt = max_irqs / 2; break; } - dev_err(dev, "Unable to get ENET IRQ\n"); - ret = ret ? : -ENXIO; - return ret; + return ret ? : -ENXIO; } pdata->irqs[i] = ret; } diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c index 3b3dc5b25b29..f482ced2cadd 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c @@ -437,7 +437,6 @@ static void xgene_sgmac_tx_disable(struct xgene_enet_pdata *p) static int xgene_enet_reset(struct xgene_enet_pdata *p) { struct device *dev = &p->pdev->dev; - acpi_status status; if (!xgene_ring_mgr_init(p)) return -ENODEV; @@ -461,6 +460,8 @@ static int xgene_enet_reset(struct xgene_enet_pdata *p) } } else { #ifdef CONFIG_ACPI + acpi_status status; + status = acpi_evaluate_object(ACPI_HANDLE(&p->pdev->dev), "_RST", NULL, NULL); if (ACPI_FAILURE(status)) { diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c index 78584089d76d..304b5d43f236 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c @@ -380,7 +380,6 @@ static void xgene_xgmac_tx_disable(struct xgene_enet_pdata *pdata) static int xgene_enet_reset(struct xgene_enet_pdata *pdata) { struct device *dev = &pdata->pdev->dev; - acpi_status status; if (!xgene_ring_mgr_init(pdata)) return -ENODEV; @@ -394,6 +393,8 @@ static int xgene_enet_reset(struct xgene_enet_pdata *pdata) udelay(5); } else { #ifdef CONFIG_ACPI + acpi_status status; + status = acpi_evaluate_object(ACPI_HANDLE(&pdata->pdev->dev), "_RST", NULL, NULL); if (ACPI_FAILURE(status)) { diff --git a/drivers/net/ethernet/atheros/ag71xx.c b/drivers/net/ethernet/atheros/ag71xx.c index 8b69d0d7e726..40a8717f51b1 100644 --- a/drivers/net/ethernet/atheros/ag71xx.c +++ b/drivers/net/ethernet/atheros/ag71xx.c @@ -1148,7 +1148,7 @@ static int ag71xx_rings_init(struct ag71xx *ag) return -ENOMEM; } - rx->buf = &tx->buf[BIT(tx->order)]; + rx->buf = &tx->buf[tx_size]; rx->descs_cpu = ((void *)tx->descs_cpu) + tx_size * AG71XX_DESC_SIZE; rx->descs_dma = tx->descs_dma + tx_size * AG71XX_DESC_SIZE; @@ -1686,7 +1686,7 @@ static int ag71xx_probe(struct platform_device *pdev) } ag->mac_base = devm_ioremap_nocache(&pdev->dev, res->start, - res->end - res->start + 1); + resource_size(res)); if (!ag->mac_base) { err = -ENOMEM; goto err_free; diff --git a/drivers/net/ethernet/aurora/nb8800.c b/drivers/net/ethernet/aurora/nb8800.c index 3b3370a94a9c..37752d9514e7 100644 --- a/drivers/net/ethernet/aurora/nb8800.c +++ b/drivers/net/ethernet/aurora/nb8800.c @@ -1351,10 +1351,8 @@ static int nb8800_probe(struct platform_device *pdev) ops = match->data; irq = platform_get_irq(pdev, 0); - if (irq <= 0) { - dev_err(&pdev->dev, "No IRQ\n"); + if (irq <= 0) return -EINVAL; - } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_ioremap_resource(&pdev->dev, res); diff --git a/drivers/net/ethernet/broadcom/bgmac-platform.c b/drivers/net/ethernet/broadcom/bgmac-platform.c index 6dc0dd91ad11..c46c1b1416f7 100644 --- a/drivers/net/ethernet/broadcom/bgmac-platform.c +++ b/drivers/net/ethernet/broadcom/bgmac-platform.c @@ -199,10 +199,8 @@ static int bgmac_probe(struct platform_device *pdev) dev_warn(&pdev->dev, "MAC address not present in device tree\n"); bgmac->irq = platform_get_irq(pdev, 0); - if (bgmac->irq < 0) { - dev_err(&pdev->dev, "Unable to obtain IRQ\n"); + if (bgmac->irq < 0) return bgmac->irq; - } regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "amac_base"); if (!regs) { diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 1fedefd499ac..c23fbb34f0e9 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -116,6 +116,9 @@ enum board_idx { BCM57508, BCM57504, BCM57502, + BCM57508_NPAR, + BCM57504_NPAR, + BCM57502_NPAR, BCM58802, BCM58804, BCM58808, @@ -161,6 +164,9 @@ static const struct { [BCM57508] = { "Broadcom BCM57508 NetXtreme-E 10Gb/25Gb/50Gb/100Gb/200Gb Ethernet" }, [BCM57504] = { "Broadcom BCM57504 NetXtreme-E 10Gb/25Gb/50Gb/100Gb/200Gb Ethernet" }, [BCM57502] = { "Broadcom BCM57502 NetXtreme-E 10Gb/25Gb/50Gb Ethernet" }, + [BCM57508_NPAR] = { "Broadcom BCM57508 NetXtreme-E Ethernet Partition" }, + [BCM57504_NPAR] = { "Broadcom BCM57504 NetXtreme-E Ethernet Partition" }, + [BCM57502_NPAR] = { "Broadcom BCM57502 NetXtreme-E Ethernet Partition" }, [BCM58802] = { "Broadcom BCM58802 NetXtreme-S 10Gb/25Gb/40Gb/50Gb Ethernet" }, [BCM58804] = { "Broadcom BCM58804 NetXtreme-S 10Gb/25Gb/40Gb/50Gb/100Gb Ethernet" }, [BCM58808] = { "Broadcom BCM58808 NetXtreme-S 10Gb/25Gb/40Gb/50Gb/100Gb Ethernet" }, @@ -209,6 +215,12 @@ static const struct pci_device_id bnxt_pci_tbl[] = { { PCI_VDEVICE(BROADCOM, 0x1750), .driver_data = BCM57508 }, { PCI_VDEVICE(BROADCOM, 0x1751), .driver_data = BCM57504 }, { PCI_VDEVICE(BROADCOM, 0x1752), .driver_data = BCM57502 }, + { PCI_VDEVICE(BROADCOM, 0x1800), .driver_data = BCM57508_NPAR }, + { PCI_VDEVICE(BROADCOM, 0x1801), .driver_data = BCM57504_NPAR }, + { PCI_VDEVICE(BROADCOM, 0x1802), .driver_data = BCM57502_NPAR }, + { PCI_VDEVICE(BROADCOM, 0x1803), .driver_data = BCM57508_NPAR }, + { PCI_VDEVICE(BROADCOM, 0x1804), .driver_data = BCM57504_NPAR }, + { PCI_VDEVICE(BROADCOM, 0x1805), .driver_data = BCM57502_NPAR }, { PCI_VDEVICE(BROADCOM, 0xd802), .driver_data = BCM58802 }, { PCI_VDEVICE(BROADCOM, 0xd804), .driver_data = BCM58804 }, #ifdef CONFIG_BNXT_SRIOV @@ -828,16 +840,41 @@ static inline int bnxt_alloc_rx_page(struct bnxt *bp, return 0; } -static void bnxt_reuse_rx_agg_bufs(struct bnxt_cp_ring_info *cpr, u16 cp_cons, - u32 agg_bufs) +static struct rx_agg_cmp *bnxt_get_agg(struct bnxt *bp, + struct bnxt_cp_ring_info *cpr, + u16 cp_cons, u16 curr) +{ + struct rx_agg_cmp *agg; + + cp_cons = RING_CMP(ADV_RAW_CMP(cp_cons, curr)); + agg = (struct rx_agg_cmp *) + &cpr->cp_desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)]; + return agg; +} + +static struct rx_agg_cmp *bnxt_get_tpa_agg_p5(struct bnxt *bp, + struct bnxt_rx_ring_info *rxr, + u16 agg_id, u16 curr) +{ + struct bnxt_tpa_info *tpa_info = &rxr->rx_tpa[agg_id]; + + return &tpa_info->agg_arr[curr]; +} + +static void bnxt_reuse_rx_agg_bufs(struct bnxt_cp_ring_info *cpr, u16 idx, + u16 start, u32 agg_bufs, bool tpa) { struct bnxt_napi *bnapi = cpr->bnapi; struct bnxt *bp = bnapi->bp; struct bnxt_rx_ring_info *rxr = bnapi->rx_ring; u16 prod = rxr->rx_agg_prod; u16 sw_prod = rxr->rx_sw_agg_prod; + bool p5_tpa = false; u32 i; + if ((bp->flags & BNXT_FLAG_CHIP_P5) && tpa) + p5_tpa = true; + for (i = 0; i < agg_bufs; i++) { u16 cons; struct rx_agg_cmp *agg; @@ -845,8 +882,10 @@ static void bnxt_reuse_rx_agg_bufs(struct bnxt_cp_ring_info *cpr, u16 cp_cons, struct rx_bd *prod_bd; struct page *page; - agg = (struct rx_agg_cmp *) - &cpr->cp_desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)]; + if (p5_tpa) + agg = bnxt_get_tpa_agg_p5(bp, rxr, idx, start + i); + else + agg = bnxt_get_agg(bp, cpr, idx, start + i); cons = agg->rx_agg_cmp_opaque; __clear_bit(cons, rxr->rx_agg_bmap); @@ -874,7 +913,6 @@ static void bnxt_reuse_rx_agg_bufs(struct bnxt_cp_ring_info *cpr, u16 cp_cons, prod = NEXT_RX_AGG(prod); sw_prod = NEXT_RX_AGG(sw_prod); - cp_cons = NEXT_CMP(cp_cons); } rxr->rx_agg_prod = prod; rxr->rx_sw_agg_prod = sw_prod; @@ -919,7 +957,7 @@ static struct sk_buff *bnxt_rx_page_skb(struct bnxt *bp, frag = &skb_shinfo(skb)->frags[0]; skb_frag_size_sub(frag, payload); - frag->page_offset += payload; + skb_frag_off_add(frag, payload); skb->data_len -= payload; skb->tail += payload; @@ -957,15 +995,19 @@ static struct sk_buff *bnxt_rx_skb(struct bnxt *bp, static struct sk_buff *bnxt_rx_pages(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, - struct sk_buff *skb, u16 cp_cons, - u32 agg_bufs) + struct sk_buff *skb, u16 idx, + u32 agg_bufs, bool tpa) { struct bnxt_napi *bnapi = cpr->bnapi; struct pci_dev *pdev = bp->pdev; struct bnxt_rx_ring_info *rxr = bnapi->rx_ring; u16 prod = rxr->rx_agg_prod; + bool p5_tpa = false; u32 i; + if ((bp->flags & BNXT_FLAG_CHIP_P5) && tpa) + p5_tpa = true; + for (i = 0; i < agg_bufs; i++) { u16 cons, frag_len; struct rx_agg_cmp *agg; @@ -973,8 +1015,10 @@ static struct sk_buff *bnxt_rx_pages(struct bnxt *bp, struct page *page; dma_addr_t mapping; - agg = (struct rx_agg_cmp *) - &cpr->cp_desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)]; + if (p5_tpa) + agg = bnxt_get_tpa_agg_p5(bp, rxr, idx, i); + else + agg = bnxt_get_agg(bp, cpr, idx, i); cons = agg->rx_agg_cmp_opaque; frag_len = (le32_to_cpu(agg->rx_agg_cmp_len_flags_type) & RX_AGG_CMP_LEN) >> RX_AGG_CMP_LEN_SHIFT; @@ -1008,7 +1052,7 @@ static struct sk_buff *bnxt_rx_pages(struct bnxt *bp, * allocated already. */ rxr->rx_agg_prod = prod; - bnxt_reuse_rx_agg_bufs(cpr, cp_cons, agg_bufs - i); + bnxt_reuse_rx_agg_bufs(cpr, idx, i, agg_bufs - i, tpa); return NULL; } @@ -1021,7 +1065,6 @@ static struct sk_buff *bnxt_rx_pages(struct bnxt *bp, skb->truesize += PAGE_SIZE; prod = NEXT_RX_AGG(prod); - cp_cons = NEXT_CMP(cp_cons); } rxr->rx_agg_prod = prod; return skb; @@ -1081,9 +1124,10 @@ static int bnxt_discard_rx(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, } else if (cmp_type == CMP_TYPE_RX_L2_TPA_END_CMP) { struct rx_tpa_end_cmp *tpa_end = cmp; - agg_bufs = (le32_to_cpu(tpa_end->rx_tpa_end_cmp_misc_v1) & - RX_TPA_END_CMP_AGG_BUFS) >> - RX_TPA_END_CMP_AGG_BUFS_SHIFT; + if (bp->flags & BNXT_FLAG_CHIP_P5) + return 0; + + agg_bufs = TPA_END_AGG_BUFS(tpa_end); } if (agg_bufs) { @@ -1120,26 +1164,60 @@ static void bnxt_sched_reset(struct bnxt *bp, struct bnxt_rx_ring_info *rxr) rxr->rx_next_cons = 0xffff; } +static u16 bnxt_alloc_agg_idx(struct bnxt_rx_ring_info *rxr, u16 agg_id) +{ + struct bnxt_tpa_idx_map *map = rxr->rx_tpa_idx_map; + u16 idx = agg_id & MAX_TPA_P5_MASK; + + if (test_bit(idx, map->agg_idx_bmap)) + idx = find_first_zero_bit(map->agg_idx_bmap, + BNXT_AGG_IDX_BMAP_SIZE); + __set_bit(idx, map->agg_idx_bmap); + map->agg_id_tbl[agg_id] = idx; + return idx; +} + +static void bnxt_free_agg_idx(struct bnxt_rx_ring_info *rxr, u16 idx) +{ + struct bnxt_tpa_idx_map *map = rxr->rx_tpa_idx_map; + + __clear_bit(idx, map->agg_idx_bmap); +} + +static u16 bnxt_lookup_agg_idx(struct bnxt_rx_ring_info *rxr, u16 agg_id) +{ + struct bnxt_tpa_idx_map *map = rxr->rx_tpa_idx_map; + + return map->agg_id_tbl[agg_id]; +} + static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, struct rx_tpa_start_cmp *tpa_start, struct rx_tpa_start_cmp_ext *tpa_start1) { - u8 agg_id = TPA_START_AGG_ID(tpa_start); - u16 cons, prod; - struct bnxt_tpa_info *tpa_info; struct bnxt_sw_rx_bd *cons_rx_buf, *prod_rx_buf; + struct bnxt_tpa_info *tpa_info; + u16 cons, prod, agg_id; struct rx_bd *prod_bd; dma_addr_t mapping; + if (bp->flags & BNXT_FLAG_CHIP_P5) { + agg_id = TPA_START_AGG_ID_P5(tpa_start); + agg_id = bnxt_alloc_agg_idx(rxr, agg_id); + } else { + agg_id = TPA_START_AGG_ID(tpa_start); + } cons = tpa_start->rx_tpa_start_cmp_opaque; prod = rxr->rx_prod; cons_rx_buf = &rxr->rx_buf_ring[cons]; prod_rx_buf = &rxr->rx_buf_ring[prod]; tpa_info = &rxr->rx_tpa[agg_id]; - if (unlikely(cons != rxr->rx_next_cons)) { - netdev_warn(bp->dev, "TPA cons %x != expected cons %x\n", - cons, rxr->rx_next_cons); + if (unlikely(cons != rxr->rx_next_cons || + TPA_START_ERROR(tpa_start))) { + netdev_warn(bp->dev, "TPA cons %x, expected cons %x, error code %x\n", + cons, rxr->rx_next_cons, + TPA_START_ERROR_CODE(tpa_start1)); bnxt_sched_reset(bp, rxr); return; } @@ -1184,6 +1262,7 @@ static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, tpa_info->flags2 = le32_to_cpu(tpa_start1->rx_tpa_start_cmp_flags2); tpa_info->metadata = le32_to_cpu(tpa_start1->rx_tpa_start_cmp_metadata); tpa_info->hdr_info = le32_to_cpu(tpa_start1->rx_tpa_start_cmp_hdr_info); + tpa_info->agg_count = 0; rxr->rx_prod = NEXT_RX(prod); cons = NEXT_RX(cons); @@ -1195,13 +1274,37 @@ static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, cons_rx_buf->data = NULL; } -static void bnxt_abort_tpa(struct bnxt_cp_ring_info *cpr, u16 cp_cons, - u32 agg_bufs) +static void bnxt_abort_tpa(struct bnxt_cp_ring_info *cpr, u16 idx, u32 agg_bufs) { if (agg_bufs) - bnxt_reuse_rx_agg_bufs(cpr, cp_cons, agg_bufs); + bnxt_reuse_rx_agg_bufs(cpr, idx, 0, agg_bufs, true); } +#ifdef CONFIG_INET +static void bnxt_gro_tunnel(struct sk_buff *skb, __be16 ip_proto) +{ + struct udphdr *uh = NULL; + + if (ip_proto == htons(ETH_P_IP)) { + struct iphdr *iph = (struct iphdr *)skb->data; + + if (iph->protocol == IPPROTO_UDP) + uh = (struct udphdr *)(iph + 1); + } else { + struct ipv6hdr *iph = (struct ipv6hdr *)skb->data; + + if (iph->nexthdr == IPPROTO_UDP) + uh = (struct udphdr *)(iph + 1); + } + if (uh) { + if (uh->check) + skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL_CSUM; + else + skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL; + } +} +#endif + static struct sk_buff *bnxt_gro_func_5731x(struct bnxt_tpa_info *tpa_info, int payload_off, int tcp_ts, struct sk_buff *skb) @@ -1259,28 +1362,39 @@ static struct sk_buff *bnxt_gro_func_5731x(struct bnxt_tpa_info *tpa_info, } if (inner_mac_off) { /* tunnel */ - struct udphdr *uh = NULL; __be16 proto = *((__be16 *)(skb->data + outer_ip_off - ETH_HLEN - 2)); - if (proto == htons(ETH_P_IP)) { - struct iphdr *iph = (struct iphdr *)skb->data; + bnxt_gro_tunnel(skb, proto); + } +#endif + return skb; +} - if (iph->protocol == IPPROTO_UDP) - uh = (struct udphdr *)(iph + 1); - } else { - struct ipv6hdr *iph = (struct ipv6hdr *)skb->data; +static struct sk_buff *bnxt_gro_func_5750x(struct bnxt_tpa_info *tpa_info, + int payload_off, int tcp_ts, + struct sk_buff *skb) +{ +#ifdef CONFIG_INET + u16 outer_ip_off, inner_ip_off, inner_mac_off; + u32 hdr_info = tpa_info->hdr_info; + int iphdr_len, nw_off; - if (iph->nexthdr == IPPROTO_UDP) - uh = (struct udphdr *)(iph + 1); - } - if (uh) { - if (uh->check) - skb_shinfo(skb)->gso_type |= - SKB_GSO_UDP_TUNNEL_CSUM; - else - skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL; - } + inner_ip_off = BNXT_TPA_INNER_L3_OFF(hdr_info); + inner_mac_off = BNXT_TPA_INNER_L2_OFF(hdr_info); + outer_ip_off = BNXT_TPA_OUTER_L3_OFF(hdr_info); + + nw_off = inner_ip_off - ETH_HLEN; + skb_set_network_header(skb, nw_off); + iphdr_len = (tpa_info->flags2 & RX_TPA_START_CMP_FLAGS2_IP_TYPE) ? + sizeof(struct ipv6hdr) : sizeof(struct iphdr); + skb_set_transport_header(skb, nw_off + iphdr_len); + + if (inner_mac_off) { /* tunnel */ + __be16 proto = *((__be16 *)(skb->data + outer_ip_off - + ETH_HLEN - 2)); + + bnxt_gro_tunnel(skb, proto); } #endif return skb; @@ -1327,28 +1441,8 @@ static struct sk_buff *bnxt_gro_func_5730x(struct bnxt_tpa_info *tpa_info, return NULL; } - if (nw_off) { /* tunnel */ - struct udphdr *uh = NULL; - - if (skb->protocol == htons(ETH_P_IP)) { - struct iphdr *iph = (struct iphdr *)skb->data; - - if (iph->protocol == IPPROTO_UDP) - uh = (struct udphdr *)(iph + 1); - } else { - struct ipv6hdr *iph = (struct ipv6hdr *)skb->data; - - if (iph->nexthdr == IPPROTO_UDP) - uh = (struct udphdr *)(iph + 1); - } - if (uh) { - if (uh->check) - skb_shinfo(skb)->gso_type |= - SKB_GSO_UDP_TUNNEL_CSUM; - else - skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL; - } - } + if (nw_off) /* tunnel */ + bnxt_gro_tunnel(skb, skb->protocol); #endif return skb; } @@ -1371,9 +1465,10 @@ static inline struct sk_buff *bnxt_gro_skb(struct bnxt *bp, skb_shinfo(skb)->gso_size = le32_to_cpu(tpa_end1->rx_tpa_end_cmp_seg_len); skb_shinfo(skb)->gso_type = tpa_info->gso_type; - payload_off = (le32_to_cpu(tpa_end->rx_tpa_end_cmp_misc_v1) & - RX_TPA_END_CMP_PAYLOAD_OFFSET) >> - RX_TPA_END_CMP_PAYLOAD_OFFSET_SHIFT; + if (bp->flags & BNXT_FLAG_CHIP_P5) + payload_off = TPA_END_PAYLOAD_OFF_P5(tpa_end1); + else + payload_off = TPA_END_PAYLOAD_OFF(tpa_end); skb = bp->gro_func(tpa_info, payload_off, TPA_END_GRO_TS(tpa_end), skb); if (likely(skb)) tcp_gro_complete(skb); @@ -1401,14 +1496,14 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp, { struct bnxt_napi *bnapi = cpr->bnapi; struct bnxt_rx_ring_info *rxr = bnapi->rx_ring; - u8 agg_id = TPA_END_AGG_ID(tpa_end); u8 *data_ptr, agg_bufs; - u16 cp_cons = RING_CMP(*raw_cons); unsigned int len; struct bnxt_tpa_info *tpa_info; dma_addr_t mapping; struct sk_buff *skb; + u16 idx = 0, agg_id; void *data; + bool gro; if (unlikely(bnapi->in_reset)) { int rc = bnxt_discard_rx(bp, cpr, raw_cons, tpa_end); @@ -1418,26 +1513,43 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp, return NULL; } - tpa_info = &rxr->rx_tpa[agg_id]; + if (bp->flags & BNXT_FLAG_CHIP_P5) { + agg_id = TPA_END_AGG_ID_P5(tpa_end); + agg_id = bnxt_lookup_agg_idx(rxr, agg_id); + agg_bufs = TPA_END_AGG_BUFS_P5(tpa_end1); + tpa_info = &rxr->rx_tpa[agg_id]; + if (unlikely(agg_bufs != tpa_info->agg_count)) { + netdev_warn(bp->dev, "TPA end agg_buf %d != expected agg_bufs %d\n", + agg_bufs, tpa_info->agg_count); + agg_bufs = tpa_info->agg_count; + } + tpa_info->agg_count = 0; + *event |= BNXT_AGG_EVENT; + bnxt_free_agg_idx(rxr, agg_id); + idx = agg_id; + gro = !!(bp->flags & BNXT_FLAG_GRO); + } else { + agg_id = TPA_END_AGG_ID(tpa_end); + agg_bufs = TPA_END_AGG_BUFS(tpa_end); + tpa_info = &rxr->rx_tpa[agg_id]; + idx = RING_CMP(*raw_cons); + if (agg_bufs) { + if (!bnxt_agg_bufs_valid(bp, cpr, agg_bufs, raw_cons)) + return ERR_PTR(-EBUSY); + + *event |= BNXT_AGG_EVENT; + idx = NEXT_CMP(idx); + } + gro = !!TPA_END_GRO(tpa_end); + } data = tpa_info->data; data_ptr = tpa_info->data_ptr; prefetch(data_ptr); len = tpa_info->len; mapping = tpa_info->mapping; - agg_bufs = (le32_to_cpu(tpa_end->rx_tpa_end_cmp_misc_v1) & - RX_TPA_END_CMP_AGG_BUFS) >> RX_TPA_END_CMP_AGG_BUFS_SHIFT; - - if (agg_bufs) { - if (!bnxt_agg_bufs_valid(bp, cpr, agg_bufs, raw_cons)) - return ERR_PTR(-EBUSY); - - *event |= BNXT_AGG_EVENT; - cp_cons = NEXT_CMP(cp_cons); - } - if (unlikely(agg_bufs > MAX_SKB_FRAGS || TPA_END_ERRORS(tpa_end1))) { - bnxt_abort_tpa(cpr, cp_cons, agg_bufs); + bnxt_abort_tpa(cpr, idx, agg_bufs); if (agg_bufs > MAX_SKB_FRAGS) netdev_warn(bp->dev, "TPA frags %d exceeded MAX_SKB_FRAGS %d\n", agg_bufs, (int)MAX_SKB_FRAGS); @@ -1447,7 +1559,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp, if (len <= bp->rx_copy_thresh) { skb = bnxt_copy_skb(bnapi, data_ptr, len, mapping); if (!skb) { - bnxt_abort_tpa(cpr, cp_cons, agg_bufs); + bnxt_abort_tpa(cpr, idx, agg_bufs); return NULL; } } else { @@ -1456,7 +1568,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp, new_data = __bnxt_alloc_rx_data(bp, &new_mapping, GFP_ATOMIC); if (!new_data) { - bnxt_abort_tpa(cpr, cp_cons, agg_bufs); + bnxt_abort_tpa(cpr, idx, agg_bufs); return NULL; } @@ -1471,7 +1583,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp, if (!skb) { kfree(data); - bnxt_abort_tpa(cpr, cp_cons, agg_bufs); + bnxt_abort_tpa(cpr, idx, agg_bufs); return NULL; } skb_reserve(skb, bp->rx_offset); @@ -1479,7 +1591,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp, } if (agg_bufs) { - skb = bnxt_rx_pages(bp, cpr, skb, cp_cons, agg_bufs); + skb = bnxt_rx_pages(bp, cpr, skb, idx, agg_bufs, true); if (!skb) { /* Page reuse already handled by bnxt_rx_pages(). */ return NULL; @@ -1508,12 +1620,24 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp, (tpa_info->flags2 & RX_CMP_FLAGS2_T_L4_CS_CALC) >> 3; } - if (TPA_END_GRO(tpa_end)) + if (gro) skb = bnxt_gro_skb(bp, tpa_info, tpa_end, tpa_end1, skb); return skb; } +static void bnxt_tpa_agg(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, + struct rx_agg_cmp *rx_agg) +{ + u16 agg_id = TPA_AGG_AGG_ID(rx_agg); + struct bnxt_tpa_info *tpa_info; + + agg_id = bnxt_lookup_agg_idx(rxr, agg_id); + tpa_info = &rxr->rx_tpa[agg_id]; + BUG_ON(tpa_info->agg_count >= MAX_SKB_FRAGS); + tpa_info->agg_arr[tpa_info->agg_count++] = *rx_agg; +} + static void bnxt_deliver_skb(struct bnxt *bp, struct bnxt_napi *bnapi, struct sk_buff *skb) { @@ -1555,6 +1679,13 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, rxcmp = (struct rx_cmp *) &cpr->cp_desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)]; + cmp_type = RX_CMP_TYPE(rxcmp); + + if (cmp_type == CMP_TYPE_RX_TPA_AGG_CMP) { + bnxt_tpa_agg(bp, rxr, (struct rx_agg_cmp *)rxcmp); + goto next_rx_no_prod_no_len; + } + tmp_raw_cons = NEXT_RAW_CMP(tmp_raw_cons); cp_cons = RING_CMP(tmp_raw_cons); rxcmp1 = (struct rx_cmp_ext *) @@ -1563,8 +1694,6 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, if (!RX_CMP_VALID(rxcmp1, tmp_raw_cons)) return -EBUSY; - cmp_type = RX_CMP_TYPE(rxcmp); - prod = rxr->rx_prod; if (cmp_type == CMP_TYPE_RX_L2_TPA_START_CMP) { @@ -1623,7 +1752,8 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, bnxt_reuse_rx_data(rxr, cons, data); if (agg_bufs) - bnxt_reuse_rx_agg_bufs(cpr, cp_cons, agg_bufs); + bnxt_reuse_rx_agg_bufs(cpr, cp_cons, 0, agg_bufs, + false); rc = -EIO; if (rx_err & RX_CMPL_ERRORS_BUFFER_ERROR_MASK) { @@ -1646,7 +1776,8 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, bnxt_reuse_rx_data(rxr, cons, data); if (!skb) { if (agg_bufs) - bnxt_reuse_rx_agg_bufs(cpr, cp_cons, agg_bufs); + bnxt_reuse_rx_agg_bufs(cpr, cp_cons, 0, + agg_bufs, false); rc = -ENOMEM; goto next_rx; } @@ -1666,7 +1797,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, } if (agg_bufs) { - skb = bnxt_rx_pages(bp, cpr, skb, cp_cons, agg_bufs); + skb = bnxt_rx_pages(bp, cpr, skb, cp_cons, agg_bufs, false); if (!skb) { rc = -ENOMEM; goto next_rx; @@ -2325,10 +2456,11 @@ static void bnxt_free_rx_skbs(struct bnxt *bp) max_agg_idx = bp->rx_agg_nr_pages * RX_DESC_CNT; for (i = 0; i < bp->rx_nr_rings; i++) { struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i]; + struct bnxt_tpa_idx_map *map; int j; if (rxr->rx_tpa) { - for (j = 0; j < MAX_TPA; j++) { + for (j = 0; j < bp->max_tpa; j++) { struct bnxt_tpa_info *tpa_info = &rxr->rx_tpa[j]; u8 *data = tpa_info->data; @@ -2395,6 +2527,9 @@ static void bnxt_free_rx_skbs(struct bnxt *bp) __free_page(rxr->rx_page); rxr->rx_page = NULL; } + map = rxr->rx_tpa_idx_map; + if (map) + memset(map->agg_idx_bmap, 0, sizeof(map->agg_idx_bmap)); } } @@ -2483,6 +2618,61 @@ static int bnxt_alloc_ring(struct bnxt *bp, struct bnxt_ring_mem_info *rmem) return 0; } +static void bnxt_free_tpa_info(struct bnxt *bp) +{ + int i; + + for (i = 0; i < bp->rx_nr_rings; i++) { + struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i]; + + kfree(rxr->rx_tpa_idx_map); + rxr->rx_tpa_idx_map = NULL; + if (rxr->rx_tpa) { + kfree(rxr->rx_tpa[0].agg_arr); + rxr->rx_tpa[0].agg_arr = NULL; + } + kfree(rxr->rx_tpa); + rxr->rx_tpa = NULL; + } +} + +static int bnxt_alloc_tpa_info(struct bnxt *bp) +{ + int i, j, total_aggs = 0; + + bp->max_tpa = MAX_TPA; + if (bp->flags & BNXT_FLAG_CHIP_P5) { + if (!bp->max_tpa_v2) + return 0; + bp->max_tpa = max_t(u16, bp->max_tpa_v2, MAX_TPA_P5); + total_aggs = bp->max_tpa * MAX_SKB_FRAGS; + } + + for (i = 0; i < bp->rx_nr_rings; i++) { + struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i]; + struct rx_agg_cmp *agg; + + rxr->rx_tpa = kcalloc(bp->max_tpa, sizeof(struct bnxt_tpa_info), + GFP_KERNEL); + if (!rxr->rx_tpa) + return -ENOMEM; + + if (!(bp->flags & BNXT_FLAG_CHIP_P5)) + continue; + agg = kcalloc(total_aggs, sizeof(*agg), GFP_KERNEL); + rxr->rx_tpa[0].agg_arr = agg; + if (!agg) + return -ENOMEM; + for (j = 1; j < bp->max_tpa; j++) + rxr->rx_tpa[j].agg_arr = agg + j * MAX_SKB_FRAGS; + rxr->rx_tpa_idx_map = kzalloc(sizeof(*rxr->rx_tpa_idx_map), + GFP_KERNEL); + if (!rxr->rx_tpa_idx_map) + return -ENOMEM; + } + return 0; +} + static void bnxt_free_rx_rings(struct bnxt *bp) { int i; @@ -2490,6 +2680,7 @@ static void bnxt_free_rx_rings(struct bnxt *bp) if (!bp->rx_ring) return; + bnxt_free_tpa_info(bp); for (i = 0; i < bp->rx_nr_rings; i++) { struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i]; struct bnxt_ring_struct *ring; @@ -2503,9 +2694,6 @@ static void bnxt_free_rx_rings(struct bnxt *bp) page_pool_destroy(rxr->page_pool); rxr->page_pool = NULL; - kfree(rxr->rx_tpa); - rxr->rx_tpa = NULL; - kfree(rxr->rx_agg_bmap); rxr->rx_agg_bmap = NULL; @@ -2539,7 +2727,7 @@ static int bnxt_alloc_rx_page_pool(struct bnxt *bp, static int bnxt_alloc_rx_rings(struct bnxt *bp) { - int i, rc, agg_rings = 0, tpa_rings = 0; + int i, rc = 0, agg_rings = 0; if (!bp->rx_ring) return -ENOMEM; @@ -2547,9 +2735,6 @@ static int bnxt_alloc_rx_rings(struct bnxt *bp) if (bp->flags & BNXT_FLAG_AGG_RINGS) agg_rings = 1; - if (bp->flags & BNXT_FLAG_TPA) - tpa_rings = 1; - for (i = 0; i < bp->rx_nr_rings; i++) { struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i]; struct bnxt_ring_struct *ring; @@ -2591,17 +2776,11 @@ static int bnxt_alloc_rx_rings(struct bnxt *bp) rxr->rx_agg_bmap = kzalloc(mem_size, GFP_KERNEL); if (!rxr->rx_agg_bmap) return -ENOMEM; - - if (tpa_rings) { - rxr->rx_tpa = kcalloc(MAX_TPA, - sizeof(struct bnxt_tpa_info), - GFP_KERNEL); - if (!rxr->rx_tpa) - return -ENOMEM; - } } } - return 0; + if (bp->flags & BNXT_FLAG_TPA) + rc = bnxt_alloc_tpa_info(bp); + return rc; } static void bnxt_free_tx_rings(struct bnxt *bp) @@ -2953,7 +3132,7 @@ static int bnxt_init_one_rx_ring(struct bnxt *bp, int ring_nr) u8 *data; dma_addr_t mapping; - for (i = 0; i < MAX_TPA; i++) { + for (i = 0; i < bp->max_tpa; i++) { data = __bnxt_alloc_rx_data(bp, &mapping, GFP_KERNEL); if (!data) @@ -3468,7 +3647,7 @@ static void bnxt_free_ring_stats(struct bnxt *bp) if (!bp->bnapi) return; - size = sizeof(struct ctx_hw_stats); + size = bp->hw_ring_stats_size; for (i = 0; i < bp->cp_nr_rings; i++) { struct bnxt_napi *bnapi = bp->bnapi[i]; @@ -3487,7 +3666,7 @@ static int bnxt_alloc_stats(struct bnxt *bp) u32 size, i; struct pci_dev *pdev = bp->pdev; - size = sizeof(struct ctx_hw_stats); + size = bp->hw_ring_stats_size; for (i = 0; i < bp->cp_nr_rings; i++) { struct bnxt_napi *bnapi = bp->bnapi[i]; @@ -4414,6 +4593,7 @@ static int bnxt_hwrm_clear_vnic_filter(struct bnxt *bp) static int bnxt_hwrm_vnic_set_tpa(struct bnxt *bp, u16 vnic_id, u32 tpa_flags) { struct bnxt_vnic_info *vnic = &bp->vnic_info[vnic_id]; + u16 max_aggs = VNIC_TPA_CFG_REQ_MAX_AGGS_MAX; struct hwrm_vnic_tpa_cfg_input req = {0}; if (vnic->fw_vnic_id == INVALID_HW_RING_ID) @@ -4453,9 +4633,14 @@ static int bnxt_hwrm_vnic_set_tpa(struct bnxt *bp, u16 vnic_id, u32 tpa_flags) nsegs = (MAX_SKB_FRAGS - n) / n; } - segs = ilog2(nsegs); + if (bp->flags & BNXT_FLAG_CHIP_P5) { + segs = MAX_TPA_SEGS_P5; + max_aggs = bp->max_tpa; + } else { + segs = ilog2(nsegs); + } req.max_agg_segs = cpu_to_le16(segs); - req.max_aggs = cpu_to_le16(VNIC_TPA_CFG_REQ_MAX_AGGS_MAX); + req.max_aggs = cpu_to_le16(max_aggs); req.min_agg_len = cpu_to_le32(512); } @@ -4815,6 +5000,12 @@ static int bnxt_hwrm_vnic_qcaps(struct bnxt *bp) if (flags & VNIC_QCAPS_RESP_FLAGS_ROCE_MIRRORING_CAPABLE_VNIC_CAP) bp->flags |= BNXT_FLAG_ROCE_MIRROR_CAP; + bp->max_tpa_v2 = le16_to_cpu(resp->max_aggs_supported); + if (bp->max_tpa_v2) + bp->hw_ring_stats_size = + sizeof(struct ctx_hw_stats_ext); + else + bp->hw_ring_stats_size = sizeof(struct ctx_hw_stats); } mutex_unlock(&bp->hwrm_cmd_lock); return rc; @@ -6012,6 +6203,7 @@ static int bnxt_hwrm_stat_ctx_alloc(struct bnxt *bp) bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_STAT_CTX_ALLOC, -1, -1); + req.stats_dma_length = cpu_to_le16(bp->hw_ring_stats_size); req.update_period_ms = cpu_to_le32(bp->stats_coal_ticks / 1000); mutex_lock(&bp->hwrm_cmd_lock); @@ -9292,7 +9484,8 @@ static int bnxt_set_features(struct net_device *dev, netdev_features_t features) if (changes & BNXT_FLAG_TPA) { update_tpa = true; if ((bp->flags & BNXT_FLAG_TPA) == 0 || - (flags & BNXT_FLAG_TPA) == 0) + (flags & BNXT_FLAG_TPA) == 0 || + (bp->flags & BNXT_FLAG_CHIP_P5)) re_init = true; } @@ -9302,9 +9495,8 @@ static int bnxt_set_features(struct net_device *dev, netdev_features_t features) if (flags != bp->flags) { u32 old_flags = bp->flags; - bp->flags = flags; - if (!test_bit(BNXT_STATE_OPEN, &bp->state)) { + bp->flags = flags; if (update_tpa) bnxt_set_ring_params(bp); return rc; @@ -9312,12 +9504,14 @@ static int bnxt_set_features(struct net_device *dev, netdev_features_t features) if (re_init) { bnxt_close_nic(bp, false, false); + bp->flags = flags; if (update_tpa) bnxt_set_ring_params(bp); return bnxt_open_nic(bp, false, false); } if (update_tpa) { + bp->flags = flags; rc = bnxt_set_tpa(bp, (flags & BNXT_FLAG_TPA) ? true : false); @@ -9714,6 +9908,68 @@ static void bnxt_init_dflt_coal(struct bnxt *bp) bp->stats_coal_ticks = BNXT_DEF_STATS_COAL_TICKS; } +static int bnxt_fw_init_one_p1(struct bnxt *bp) +{ + int rc; + + bp->fw_cap = 0; + rc = bnxt_hwrm_ver_get(bp); + if (rc) + return rc; + + if (bp->fw_cap & BNXT_FW_CAP_KONG_MB_CHNL) { + rc = bnxt_alloc_kong_hwrm_resources(bp); + if (rc) + bp->fw_cap &= ~BNXT_FW_CAP_KONG_MB_CHNL; + } + + if ((bp->fw_cap & BNXT_FW_CAP_SHORT_CMD) || + bp->hwrm_max_ext_req_len > BNXT_HWRM_MAX_REQ_LEN) { + rc = bnxt_alloc_hwrm_short_cmd_req(bp); + if (rc) + return rc; + } + rc = bnxt_hwrm_func_reset(bp); + if (rc) + return -ENODEV; + + bnxt_hwrm_fw_set_time(bp); + return 0; +} + +static int bnxt_fw_init_one_p2(struct bnxt *bp) +{ + int rc; + + /* Get the MAX capabilities for this function */ + rc = bnxt_hwrm_func_qcaps(bp); + if (rc) { + netdev_err(bp->dev, "hwrm query capability failure rc: %x\n", + rc); + return -ENODEV; + } + + rc = bnxt_hwrm_cfa_adv_flow_mgnt_qcaps(bp); + if (rc) + netdev_warn(bp->dev, "hwrm query adv flow mgnt failure rc: %d\n", + rc); + + rc = bnxt_hwrm_func_drv_rgtr(bp); + if (rc) + return -ENODEV; + + rc = bnxt_hwrm_func_rgtr_async_events(bp, NULL, 0); + if (rc) + return -ENODEV; + + bnxt_hwrm_func_qcfg(bp); + bnxt_hwrm_vnic_qcaps(bp); + bnxt_hwrm_port_led_qcaps(bp); + bnxt_ethtool_init(bp); + bnxt_dcb_init(bp); + return 0; +} + static int bnxt_init_board(struct pci_dev *pdev, struct net_device *dev) { int rc; @@ -10669,32 +10925,18 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) goto init_err_pci_clean; mutex_init(&bp->hwrm_cmd_lock); - rc = bnxt_hwrm_ver_get(bp); + + rc = bnxt_fw_init_one_p1(bp); if (rc) goto init_err_pci_clean; - if (bp->fw_cap & BNXT_FW_CAP_KONG_MB_CHNL) { - rc = bnxt_alloc_kong_hwrm_resources(bp); - if (rc) - bp->fw_cap &= ~BNXT_FW_CAP_KONG_MB_CHNL; - } - - if ((bp->fw_cap & BNXT_FW_CAP_SHORT_CMD) || - bp->hwrm_max_ext_req_len > BNXT_HWRM_MAX_REQ_LEN) { - rc = bnxt_alloc_hwrm_short_cmd_req(bp); - if (rc) - goto init_err_pci_clean; - } - if (BNXT_CHIP_P5(bp)) bp->flags |= BNXT_FLAG_CHIP_P5; - rc = bnxt_hwrm_func_reset(bp); + rc = bnxt_fw_init_one_p2(bp); if (rc) goto init_err_pci_clean; - bnxt_hwrm_fw_set_time(bp); - dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_GRE | @@ -10732,41 +10974,14 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) bp->gro_func = bnxt_gro_func_5730x; if (BNXT_CHIP_P4(bp)) bp->gro_func = bnxt_gro_func_5731x; + else if (BNXT_CHIP_P5(bp)) + bp->gro_func = bnxt_gro_func_5750x; } if (!BNXT_CHIP_P4_PLUS(bp)) bp->flags |= BNXT_FLAG_DOUBLE_DB; - rc = bnxt_hwrm_func_drv_rgtr(bp); - if (rc) - goto init_err_pci_clean; - - rc = bnxt_hwrm_func_rgtr_async_events(bp, NULL, 0); - if (rc) - goto init_err_pci_clean; - bp->ulp_probe = bnxt_ulp_probe; - rc = bnxt_hwrm_queue_qportcfg(bp); - if (rc) { - netdev_err(bp->dev, "hwrm query qportcfg failure rc: %x\n", - rc); - rc = -1; - goto init_err_pci_clean; - } - /* Get the MAX capabilities for this function */ - rc = bnxt_hwrm_func_qcaps(bp); - if (rc) { - netdev_err(bp->dev, "hwrm query capability failure rc: %x\n", - rc); - rc = -1; - goto init_err_pci_clean; - } - - rc = bnxt_hwrm_cfa_adv_flow_mgnt_qcaps(bp); - if (rc) - netdev_warn(bp->dev, "hwrm query adv flow mgnt failure rc: %d\n", - rc); - rc = bnxt_init_mac_addr(bp); if (rc) { dev_err(&pdev->dev, "Unable to initialize mac address.\n"); @@ -10780,11 +10995,6 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (rc) goto init_err_pci_clean; } - bnxt_hwrm_func_qcfg(bp); - bnxt_hwrm_vnic_qcaps(bp); - bnxt_hwrm_port_led_qcaps(bp); - bnxt_ethtool_init(bp); - bnxt_dcb_init(bp); /* MTU range: 60 - FW defined max */ dev->min_mtu = ETH_ZLEN; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index 16694b704d15..e3262089b751 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -113,6 +113,7 @@ struct tx_cmp { #define CMP_TYPE_RX_AGG_CMP 18 #define CMP_TYPE_RX_L2_TPA_START_CMP 19 #define CMP_TYPE_RX_L2_TPA_END_CMP 21 + #define CMP_TYPE_RX_TPA_AGG_CMP 22 #define CMP_TYPE_STATUS_CMP 32 #define CMP_TYPE_REMOTE_DRIVER_REQ 34 #define CMP_TYPE_REMOTE_DRIVER_RESP 36 @@ -263,14 +264,21 @@ struct rx_agg_cmp { u32 rx_agg_cmp_opaque; __le32 rx_agg_cmp_v; #define RX_AGG_CMP_V (1 << 0) + #define RX_AGG_CMP_AGG_ID (0xffff << 16) + #define RX_AGG_CMP_AGG_ID_SHIFT 16 __le32 rx_agg_cmp_unused; }; +#define TPA_AGG_AGG_ID(rx_agg) \ + ((le32_to_cpu((rx_agg)->rx_agg_cmp_v) & \ + RX_AGG_CMP_AGG_ID) >> RX_AGG_CMP_AGG_ID_SHIFT) + struct rx_tpa_start_cmp { __le32 rx_tpa_start_cmp_len_flags_type; #define RX_TPA_START_CMP_TYPE (0x3f << 0) #define RX_TPA_START_CMP_FLAGS (0x3ff << 6) #define RX_TPA_START_CMP_FLAGS_SHIFT 6 + #define RX_TPA_START_CMP_FLAGS_ERROR (0x1 << 6) #define RX_TPA_START_CMP_FLAGS_PLACEMENT (0x7 << 7) #define RX_TPA_START_CMP_FLAGS_PLACEMENT_SHIFT 7 #define RX_TPA_START_CMP_FLAGS_PLACEMENT_JUMBO (0x1 << 7) @@ -278,6 +286,7 @@ struct rx_tpa_start_cmp { #define RX_TPA_START_CMP_FLAGS_PLACEMENT_GRO_JUMBO (0x5 << 7) #define RX_TPA_START_CMP_FLAGS_PLACEMENT_GRO_HDS (0x6 << 7) #define RX_TPA_START_CMP_FLAGS_RSS_VALID (0x1 << 10) + #define RX_TPA_START_CMP_FLAGS_TIMESTAMP (0x1 << 11) #define RX_TPA_START_CMP_FLAGS_ITYPES (0xf << 12) #define RX_TPA_START_CMP_FLAGS_ITYPES_SHIFT 12 #define RX_TPA_START_CMP_FLAGS_ITYPE_TCP (0x2 << 12) @@ -291,6 +300,8 @@ struct rx_tpa_start_cmp { #define RX_TPA_START_CMP_RSS_HASH_TYPE_SHIFT 9 #define RX_TPA_START_CMP_AGG_ID (0x7f << 25) #define RX_TPA_START_CMP_AGG_ID_SHIFT 25 + #define RX_TPA_START_CMP_AGG_ID_P5 (0xffff << 16) + #define RX_TPA_START_CMP_AGG_ID_SHIFT_P5 16 __le32 rx_tpa_start_cmp_rss_hash; }; @@ -308,6 +319,14 @@ struct rx_tpa_start_cmp { ((le32_to_cpu((rx_tpa_start)->rx_tpa_start_cmp_misc_v1) & \ RX_TPA_START_CMP_AGG_ID) >> RX_TPA_START_CMP_AGG_ID_SHIFT) +#define TPA_START_AGG_ID_P5(rx_tpa_start) \ + ((le32_to_cpu((rx_tpa_start)->rx_tpa_start_cmp_misc_v1) & \ + RX_TPA_START_CMP_AGG_ID_P5) >> RX_TPA_START_CMP_AGG_ID_SHIFT_P5) + +#define TPA_START_ERROR(rx_tpa_start) \ + ((rx_tpa_start)->rx_tpa_start_cmp_len_flags_type & \ + cpu_to_le32(RX_TPA_START_CMP_FLAGS_ERROR)) + struct rx_tpa_start_cmp_ext { __le32 rx_tpa_start_cmp_flags2; #define RX_TPA_START_CMP_FLAGS2_IP_CS_CALC (0x1 << 0) @@ -315,10 +334,20 @@ struct rx_tpa_start_cmp_ext { #define RX_TPA_START_CMP_FLAGS2_T_IP_CS_CALC (0x1 << 2) #define RX_TPA_START_CMP_FLAGS2_T_L4_CS_CALC (0x1 << 3) #define RX_TPA_START_CMP_FLAGS2_IP_TYPE (0x1 << 8) + #define RX_TPA_START_CMP_FLAGS2_CSUM_CMPL_VALID (0x1 << 9) + #define RX_TPA_START_CMP_FLAGS2_EXT_META_FORMAT (0x3 << 10) + #define RX_TPA_START_CMP_FLAGS2_EXT_META_FORMAT_SHIFT 10 + #define RX_TPA_START_CMP_FLAGS2_CSUM_CMPL (0xffff << 16) + #define RX_TPA_START_CMP_FLAGS2_CSUM_CMPL_SHIFT 16 __le32 rx_tpa_start_cmp_metadata; __le32 rx_tpa_start_cmp_cfa_code_v2; #define RX_TPA_START_CMP_V2 (0x1 << 0) + #define RX_TPA_START_CMP_ERRORS_BUFFER_ERROR_MASK (0x7 << 1) + #define RX_TPA_START_CMP_ERRORS_BUFFER_ERROR_SHIFT 1 + #define RX_TPA_START_CMP_ERRORS_BUFFER_ERROR_NO_BUFFER (0x0 << 1) + #define RX_TPA_START_CMP_ERRORS_BUFFER_ERROR_BAD_FORMAT (0x3 << 1) + #define RX_TPA_START_CMP_ERRORS_BUFFER_ERROR_FLUSH (0x5 << 1) #define RX_TPA_START_CMP_CFA_CODE (0xffff << 16) #define RX_TPA_START_CMPL_CFA_CODE_SHIFT 16 __le32 rx_tpa_start_cmp_hdr_info; @@ -332,6 +361,11 @@ struct rx_tpa_start_cmp_ext { (!!((rx_tpa_start)->rx_tpa_start_cmp_flags2 & \ cpu_to_le32(RX_TPA_START_CMP_FLAGS2_IP_TYPE))) +#define TPA_START_ERROR_CODE(rx_tpa_start) \ + ((le32_to_cpu((rx_tpa_start)->rx_tpa_start_cmp_cfa_code_v2) & \ + RX_TPA_START_CMP_ERRORS_BUFFER_ERROR_MASK) >> \ + RX_TPA_START_CMP_ERRORS_BUFFER_ERROR_SHIFT) + struct rx_tpa_end_cmp { __le32 rx_tpa_end_cmp_len_flags_type; #define RX_TPA_END_CMP_TYPE (0x3f << 0) @@ -361,6 +395,8 @@ struct rx_tpa_end_cmp { #define RX_TPA_END_CMP_PAYLOAD_OFFSET_SHIFT 16 #define RX_TPA_END_CMP_AGG_ID (0x7f << 25) #define RX_TPA_END_CMP_AGG_ID_SHIFT 25 + #define RX_TPA_END_CMP_AGG_ID_P5 (0xffff << 16) + #define RX_TPA_END_CMP_AGG_ID_SHIFT_P5 16 __le32 rx_tpa_end_cmp_tsdelta; #define RX_TPA_END_GRO_TS (0x1 << 31) @@ -370,6 +406,18 @@ struct rx_tpa_end_cmp { ((le32_to_cpu((rx_tpa_end)->rx_tpa_end_cmp_misc_v1) & \ RX_TPA_END_CMP_AGG_ID) >> RX_TPA_END_CMP_AGG_ID_SHIFT) +#define TPA_END_AGG_ID_P5(rx_tpa_end) \ + ((le32_to_cpu((rx_tpa_end)->rx_tpa_end_cmp_misc_v1) & \ + RX_TPA_END_CMP_AGG_ID_P5) >> RX_TPA_END_CMP_AGG_ID_SHIFT_P5) + +#define TPA_END_PAYLOAD_OFF(rx_tpa_end) \ + ((le32_to_cpu((rx_tpa_end)->rx_tpa_end_cmp_misc_v1) & \ + RX_TPA_END_CMP_PAYLOAD_OFFSET) >> RX_TPA_END_CMP_PAYLOAD_OFFSET_SHIFT) + +#define TPA_END_AGG_BUFS(rx_tpa_end) \ + ((le32_to_cpu((rx_tpa_end)->rx_tpa_end_cmp_misc_v1) & \ + RX_TPA_END_CMP_AGG_BUFS) >> RX_TPA_END_CMP_AGG_BUFS_SHIFT) + #define TPA_END_TPA_SEGS(rx_tpa_end) \ ((le32_to_cpu((rx_tpa_end)->rx_tpa_end_cmp_misc_v1) & \ RX_TPA_END_CMP_TPA_SEGS) >> RX_TPA_END_CMP_TPA_SEGS_SHIFT) @@ -389,6 +437,10 @@ struct rx_tpa_end_cmp { struct rx_tpa_end_cmp_ext { __le32 rx_tpa_end_cmp_dup_acks; #define RX_TPA_END_CMP_TPA_DUP_ACKS (0xf << 0) + #define RX_TPA_END_CMP_PAYLOAD_OFFSET_P5 (0xff << 16) + #define RX_TPA_END_CMP_PAYLOAD_OFFSET_SHIFT_P5 16 + #define RX_TPA_END_CMP_AGG_BUFS_P5 (0xff << 24) + #define RX_TPA_END_CMP_AGG_BUFS_SHIFT_P5 24 __le32 rx_tpa_end_cmp_seg_len; #define RX_TPA_END_CMP_TPA_SEG_LEN (0xffff << 0) @@ -396,7 +448,13 @@ struct rx_tpa_end_cmp_ext { __le32 rx_tpa_end_cmp_errors_v2; #define RX_TPA_END_CMP_V2 (0x1 << 0) #define RX_TPA_END_CMP_ERRORS (0x3 << 1) + #define RX_TPA_END_CMP_ERRORS_P5 (0x7 << 1) #define RX_TPA_END_CMPL_ERRORS_SHIFT 1 + #define RX_TPA_END_CMP_ERRORS_BUFFER_ERROR_NO_BUFFER (0x0 << 1) + #define RX_TPA_END_CMP_ERRORS_BUFFER_ERROR_NOT_ON_CHIP (0x2 << 1) + #define RX_TPA_END_CMP_ERRORS_BUFFER_ERROR_BAD_FORMAT (0x3 << 1) + #define RX_TPA_END_CMP_ERRORS_BUFFER_ERROR_RSV_ERROR (0x4 << 1) + #define RX_TPA_END_CMP_ERRORS_BUFFER_ERROR_FLUSH (0x5 << 1) u32 rx_tpa_end_cmp_start_opaque; }; @@ -405,6 +463,15 @@ struct rx_tpa_end_cmp_ext { ((rx_tpa_end_ext)->rx_tpa_end_cmp_errors_v2 & \ cpu_to_le32(RX_TPA_END_CMP_ERRORS)) +#define TPA_END_PAYLOAD_OFF_P5(rx_tpa_end_ext) \ + ((le32_to_cpu((rx_tpa_end_ext)->rx_tpa_end_cmp_dup_acks) & \ + RX_TPA_END_CMP_PAYLOAD_OFFSET_P5) >> \ + RX_TPA_END_CMP_PAYLOAD_OFFSET_SHIFT_P5) + +#define TPA_END_AGG_BUFS_P5(rx_tpa_end_ext) \ + ((le32_to_cpu((rx_tpa_end_ext)->rx_tpa_end_cmp_dup_acks) & \ + RX_TPA_END_CMP_AGG_BUFS_P5) >> RX_TPA_END_CMP_AGG_BUFS_SHIFT_P5) + struct nqe_cn { __le16 type; #define NQ_CN_TYPE_MASK 0x3fUL @@ -487,6 +554,9 @@ struct nqe_cn { #define BNXT_DEFAULT_TX_RING_SIZE 511 #define MAX_TPA 64 +#define MAX_TPA_P5 256 +#define MAX_TPA_P5_MASK (MAX_TPA_P5 - 1) +#define MAX_TPA_SEGS_P5 0x3f #if (BNXT_PAGE_SHIFT == 16) #define MAX_RX_PAGES 1 @@ -768,6 +838,15 @@ struct bnxt_tpa_info { ((hdr_info) & 0x1ff) u16 cfa_code; /* cfa_code in TPA start compl */ + u8 agg_count; + struct rx_agg_cmp *agg_arr; +}; + +#define BNXT_AGG_IDX_BMAP_SIZE (MAX_TPA_P5 / BITS_PER_LONG) + +struct bnxt_tpa_idx_map { + u16 agg_id_tbl[1024]; + unsigned long agg_idx_bmap[BNXT_AGG_IDX_BMAP_SIZE]; }; struct bnxt_rx_ring_info { @@ -797,6 +876,7 @@ struct bnxt_rx_ring_info { dma_addr_t rx_agg_desc_mapping[MAX_RX_AGG_PAGES]; struct bnxt_tpa_info *rx_tpa; + struct bnxt_tpa_idx_map *rx_tpa_idx_map; struct bnxt_ring_struct rx_ring_struct; struct bnxt_ring_struct rx_agg_ring_struct; @@ -1282,7 +1362,9 @@ struct bnxt { #define CHIP_NUM_5745X 0xd730 -#define CHIP_NUM_57500 0x1750 +#define CHIP_NUM_57508 0x1750 +#define CHIP_NUM_57504 0x1751 +#define CHIP_NUM_57502 0x1752 #define CHIP_NUM_58802 0xd802 #define CHIP_NUM_58804 0xd804 @@ -1379,12 +1461,14 @@ struct bnxt { #define BNXT_CHIP_TYPE_NITRO_A0(bp) ((bp)->flags & BNXT_FLAG_CHIP_NITRO_A0) #define BNXT_RX_PAGE_MODE(bp) ((bp)->flags & BNXT_FLAG_RX_PAGE_MODE) #define BNXT_SUPPORTS_TPA(bp) (!BNXT_CHIP_TYPE_NITRO_A0(bp) && \ - !(bp->flags & BNXT_FLAG_CHIP_P5) && \ - !is_kdump_kernel()) + (!((bp)->flags & BNXT_FLAG_CHIP_P5) || \ + (bp)->max_tpa_v2) && !is_kdump_kernel()) /* Chip class phase 5 */ #define BNXT_CHIP_P5(bp) \ - ((bp)->chip_num == CHIP_NUM_57500) + ((bp)->chip_num == CHIP_NUM_57508 || \ + (bp)->chip_num == CHIP_NUM_57504 || \ + (bp)->chip_num == CHIP_NUM_57502) /* Chip class phase 4.x */ #define BNXT_CHIP_P4(bp) \ @@ -1414,6 +1498,8 @@ struct bnxt { u16, void *, u8 *, dma_addr_t, unsigned int); + u16 max_tpa_v2; + u16 max_tpa; u32 rx_buf_size; u32 rx_buf_use_size; /* useable size */ u16 rx_offset; @@ -1525,6 +1611,7 @@ struct bnxt { int hw_port_stats_size; u16 fw_rx_stats_ext_size; u16 fw_tx_stats_ext_size; + u16 hw_ring_stats_size; u8 pri2cos[8]; u8 pri2cos_valid; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index c7ee63d69679..3a3d8a9be5ed 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@ -137,7 +137,44 @@ reset_coalesce: return rc; } -#define BNXT_NUM_STATS 22 +static const char * const bnxt_ring_stats_str[] = { + "rx_ucast_packets", + "rx_mcast_packets", + "rx_bcast_packets", + "rx_discards", + "rx_drops", + "rx_ucast_bytes", + "rx_mcast_bytes", + "rx_bcast_bytes", + "tx_ucast_packets", + "tx_mcast_packets", + "tx_bcast_packets", + "tx_discards", + "tx_drops", + "tx_ucast_bytes", + "tx_mcast_bytes", + "tx_bcast_bytes", +}; + +static const char * const bnxt_ring_tpa_stats_str[] = { + "tpa_packets", + "tpa_bytes", + "tpa_events", + "tpa_aborts", +}; + +static const char * const bnxt_ring_tpa2_stats_str[] = { + "rx_tpa_eligible_pkt", + "rx_tpa_eligible_bytes", + "rx_tpa_pkt", + "rx_tpa_bytes", + "rx_tpa_errors", +}; + +static const char * const bnxt_ring_sw_stats_str[] = { + "rx_l4_csum_errors", + "missed_irqs", +}; #define BNXT_RX_STATS_ENTRY(counter) \ { BNXT_RX_STATS_OFFSET(counter), __stringify(counter) } @@ -207,6 +244,20 @@ reset_coalesce: BNXT_TX_STATS_EXT_COS_ENTRY(6), \ BNXT_TX_STATS_EXT_COS_ENTRY(7) \ +#define BNXT_RX_STATS_EXT_DISCARD_COS_ENTRY(n) \ + BNXT_RX_STATS_EXT_ENTRY(rx_discard_bytes_cos##n), \ + BNXT_RX_STATS_EXT_ENTRY(rx_discard_packets_cos##n) + +#define BNXT_RX_STATS_EXT_DISCARD_COS_ENTRIES \ + BNXT_RX_STATS_EXT_DISCARD_COS_ENTRY(0), \ + BNXT_RX_STATS_EXT_DISCARD_COS_ENTRY(1), \ + BNXT_RX_STATS_EXT_DISCARD_COS_ENTRY(2), \ + BNXT_RX_STATS_EXT_DISCARD_COS_ENTRY(3), \ + BNXT_RX_STATS_EXT_DISCARD_COS_ENTRY(4), \ + BNXT_RX_STATS_EXT_DISCARD_COS_ENTRY(5), \ + BNXT_RX_STATS_EXT_DISCARD_COS_ENTRY(6), \ + BNXT_RX_STATS_EXT_DISCARD_COS_ENTRY(7) + #define BNXT_RX_STATS_PRI_ENTRY(counter, n) \ { BNXT_RX_STATS_EXT_OFFSET(counter##_cos0), \ __stringify(counter##_pri##n) } @@ -352,6 +403,7 @@ static const struct { BNXT_RX_STATS_EXT_ENTRY(rx_buffer_passed_threshold), BNXT_RX_STATS_EXT_ENTRY(rx_pcs_symbol_err), BNXT_RX_STATS_EXT_ENTRY(rx_corrected_bits), + BNXT_RX_STATS_EXT_DISCARD_COS_ENTRIES, }; static const struct { @@ -417,9 +469,29 @@ static const struct { ARRAY_SIZE(bnxt_tx_pkts_pri_arr)) #define BNXT_NUM_PCIE_STATS ARRAY_SIZE(bnxt_pcie_stats_arr) +static int bnxt_get_num_tpa_ring_stats(struct bnxt *bp) +{ + if (BNXT_SUPPORTS_TPA(bp)) { + if (bp->max_tpa_v2) + return ARRAY_SIZE(bnxt_ring_tpa2_stats_str); + return ARRAY_SIZE(bnxt_ring_tpa_stats_str); + } + return 0; +} + +static int bnxt_get_num_ring_stats(struct bnxt *bp) +{ + int num_stats; + + num_stats = ARRAY_SIZE(bnxt_ring_stats_str) + + ARRAY_SIZE(bnxt_ring_sw_stats_str) + + bnxt_get_num_tpa_ring_stats(bp); + return num_stats * bp->cp_nr_rings; +} + static int bnxt_get_num_stats(struct bnxt *bp) { - int num_stats = BNXT_NUM_STATS * bp->cp_nr_rings; + int num_stats = bnxt_get_num_ring_stats(bp); num_stats += BNXT_NUM_SW_FUNC_STATS; @@ -460,10 +532,11 @@ static void bnxt_get_ethtool_stats(struct net_device *dev, { u32 i, j = 0; struct bnxt *bp = netdev_priv(dev); - u32 stat_fields = sizeof(struct ctx_hw_stats) / 8; + u32 stat_fields = ARRAY_SIZE(bnxt_ring_stats_str) + + bnxt_get_num_tpa_ring_stats(bp); if (!bp->bnapi) { - j += BNXT_NUM_STATS * bp->cp_nr_rings + BNXT_NUM_SW_FUNC_STATS; + j += bnxt_get_num_ring_stats(bp) + BNXT_NUM_SW_FUNC_STATS; goto skip_ring_stats; } @@ -551,56 +624,39 @@ skip_ring_stats: static void bnxt_get_strings(struct net_device *dev, u32 stringset, u8 *buf) { struct bnxt *bp = netdev_priv(dev); - u32 i; + static const char * const *str; + u32 i, j, num_str; switch (stringset) { - /* The number of strings must match BNXT_NUM_STATS defined above. */ case ETH_SS_STATS: for (i = 0; i < bp->cp_nr_rings; i++) { - sprintf(buf, "[%d]: rx_ucast_packets", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: rx_mcast_packets", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: rx_bcast_packets", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: rx_discards", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: rx_drops", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: rx_ucast_bytes", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: rx_mcast_bytes", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: rx_bcast_bytes", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: tx_ucast_packets", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: tx_mcast_packets", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: tx_bcast_packets", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: tx_discards", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: tx_drops", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: tx_ucast_bytes", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: tx_mcast_bytes", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: tx_bcast_bytes", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: tpa_packets", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: tpa_bytes", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: tpa_events", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: tpa_aborts", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: rx_l4_csum_errors", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: missed_irqs", i); - buf += ETH_GSTRING_LEN; + num_str = ARRAY_SIZE(bnxt_ring_stats_str); + for (j = 0; j < num_str; j++) { + sprintf(buf, "[%d]: %s", i, + bnxt_ring_stats_str[j]); + buf += ETH_GSTRING_LEN; + } + if (!BNXT_SUPPORTS_TPA(bp)) + goto skip_tpa_stats; + + if (bp->max_tpa_v2) { + num_str = ARRAY_SIZE(bnxt_ring_tpa2_stats_str); + str = bnxt_ring_tpa2_stats_str; + } else { + num_str = ARRAY_SIZE(bnxt_ring_tpa_stats_str); + str = bnxt_ring_tpa_stats_str; + } + for (j = 0; j < num_str; j++) { + sprintf(buf, "[%d]: %s", i, str[j]); + buf += ETH_GSTRING_LEN; + } +skip_tpa_stats: + num_str = ARRAY_SIZE(bnxt_ring_sw_stats_str); + for (j = 0; j < num_str; j++) { + sprintf(buf, "[%d]: %s", i, + bnxt_ring_sw_stats_str[j]); + buf += ETH_GSTRING_LEN; + } } for (i = 0; i < BNXT_NUM_SW_FUNC_STATS; i++) { strcpy(buf, bnxt_sw_func_stats[i].string); diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h index 12bbb2a207d0..2cdef753a1bc 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h @@ -1,7 +1,8 @@ /* Broadcom NetXtreme-C/E network driver. * * Copyright (c) 2014-2016 Broadcom Corporation - * Copyright (c) 2016-2019 Broadcom Limited + * Copyright (c) 2014-2018 Broadcom Limited + * Copyright (c) 2018-2019 Broadcom Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -39,15 +40,15 @@ struct hwrm_resp_hdr { #define TLV_TYPE_ROCE_SP_COMMAND 0x3UL #define TLV_TYPE_QUERY_ROCE_CC_GEN1 0x4UL #define TLV_TYPE_MODIFY_ROCE_CC_GEN1 0x5UL -#define TLV_TYPE_ENGINE_CKV_DEVICE_SERIAL_NUMBER 0x8001UL -#define TLV_TYPE_ENGINE_CKV_NONCE 0x8002UL +#define TLV_TYPE_ENGINE_CKV_ALIAS_ECC_PUBLIC_KEY 0x8001UL #define TLV_TYPE_ENGINE_CKV_IV 0x8003UL #define TLV_TYPE_ENGINE_CKV_AUTH_TAG 0x8004UL #define TLV_TYPE_ENGINE_CKV_CIPHERTEXT 0x8005UL #define TLV_TYPE_ENGINE_CKV_ALGORITHMS 0x8006UL -#define TLV_TYPE_ENGINE_CKV_ECC_PUBLIC_KEY 0x8007UL +#define TLV_TYPE_ENGINE_CKV_HOST_ECC_PUBLIC_KEY 0x8007UL #define TLV_TYPE_ENGINE_CKV_ECDSA_SIGNATURE 0x8008UL -#define TLV_TYPE_LAST TLV_TYPE_ENGINE_CKV_ECDSA_SIGNATURE +#define TLV_TYPE_ENGINE_CKV_SRT_ECC_PUBLIC_KEY 0x8009UL +#define TLV_TYPE_LAST TLV_TYPE_ENGINE_CKV_SRT_ECC_PUBLIC_KEY /* tlv (size:64b/8B) */ @@ -267,7 +268,6 @@ struct cmd_nums { #define HWRM_CFA_EEM_OP 0x123UL #define HWRM_CFA_ADV_FLOW_MGNT_QCAPS 0x124UL #define HWRM_CFA_TFLIB 0x125UL - #define HWRM_ENGINE_CKV_HELLO 0x12dUL #define HWRM_ENGINE_CKV_STATUS 0x12eUL #define HWRM_ENGINE_CKV_CKEK_ADD 0x12fUL #define HWRM_ENGINE_CKV_CKEK_DELETE 0x130UL @@ -313,6 +313,7 @@ struct cmd_nums { #define HWRM_FUNC_BACKING_STORE_QCFG 0x194UL #define HWRM_FUNC_VF_BW_CFG 0x195UL #define HWRM_FUNC_VF_BW_QCFG 0x196UL + #define HWRM_FUNC_HOST_PF_IDS_QUERY 0x197UL #define HWRM_SELFTEST_QLIST 0x200UL #define HWRM_SELFTEST_EXEC 0x201UL #define HWRM_SELFTEST_IRQ 0x202UL @@ -410,8 +411,8 @@ struct hwrm_err_output { #define HWRM_VERSION_MAJOR 1 #define HWRM_VERSION_MINOR 10 #define HWRM_VERSION_UPDATE 0 -#define HWRM_VERSION_RSVD 69 -#define HWRM_VERSION_STR "1.10.0.69" +#define HWRM_VERSION_RSVD 89 +#define HWRM_VERSION_STR "1.10.0.89" /* hwrm_ver_get_input (size:192b/24B) */ struct hwrm_ver_get_input { @@ -624,6 +625,8 @@ struct hwrm_async_event_cmpl { #define ASYNC_EVENT_CMPL_EVENT_ID_TCP_FLAG_ACTION_CHANGE 0x3aUL #define ASYNC_EVENT_CMPL_EVENT_ID_EEM_FLOW_ACTIVE 0x3bUL #define ASYNC_EVENT_CMPL_EVENT_ID_EEM_CFG_CHANGE 0x3cUL + #define ASYNC_EVENT_CMPL_EVENT_ID_TFLIB_DEFAULT_VNIC_CHANGE 0x3dUL + #define ASYNC_EVENT_CMPL_EVENT_ID_TFLIB_LINK_STATUS_CHANGE 0x3eUL #define ASYNC_EVENT_CMPL_EVENT_ID_FW_TRACE_MSG 0xfeUL #define ASYNC_EVENT_CMPL_EVENT_ID_HWRM_ERROR 0xffUL #define ASYNC_EVENT_CMPL_EVENT_ID_LAST ASYNC_EVENT_CMPL_EVENT_ID_HWRM_ERROR @@ -1122,6 +1125,7 @@ struct hwrm_func_qcfg_output { #define FUNC_QCFG_RESP_FLAGS_MULTI_HOST 0x20UL #define FUNC_QCFG_RESP_FLAGS_TRUSTED_VF 0x40UL #define FUNC_QCFG_RESP_FLAGS_SECURE_MODE_ENABLED 0x80UL + #define FUNC_QCFG_RESP_FLAGS_PREBOOT_LEGACY_L2_RINGS 0x100UL u8 mac_address[6]; __le16 pci_id; __le16 alloc_rsscos_ctx; @@ -1241,6 +1245,7 @@ struct hwrm_func_cfg_input { #define FUNC_CFG_REQ_FLAGS_DYNAMIC_TX_RING_ALLOC 0x400000UL #define FUNC_CFG_REQ_FLAGS_NQ_ASSETS_TEST 0x800000UL #define FUNC_CFG_REQ_FLAGS_TRUSTED_VF_DISABLE 0x1000000UL + #define FUNC_CFG_REQ_FLAGS_PREBOOT_LEGACY_L2_RINGS 0x2000000UL __le32 enables; #define FUNC_CFG_REQ_ENABLES_MTU 0x1UL #define FUNC_CFG_REQ_ENABLES_MRU 0x2UL @@ -2916,7 +2921,7 @@ struct tx_port_stats_ext { __le64 pfc_pri7_tx_transitions; }; -/* rx_port_stats_ext (size:2624b/328B) */ +/* rx_port_stats_ext (size:3648b/456B) */ struct rx_port_stats_ext { __le64 link_down_events; __le64 continuous_pause_events; @@ -2959,6 +2964,22 @@ struct rx_port_stats_ext { __le64 rx_buffer_passed_threshold; __le64 rx_pcs_symbol_err; __le64 rx_corrected_bits; + __le64 rx_discard_bytes_cos0; + __le64 rx_discard_bytes_cos1; + __le64 rx_discard_bytes_cos2; + __le64 rx_discard_bytes_cos3; + __le64 rx_discard_bytes_cos4; + __le64 rx_discard_bytes_cos5; + __le64 rx_discard_bytes_cos6; + __le64 rx_discard_bytes_cos7; + __le64 rx_discard_packets_cos0; + __le64 rx_discard_packets_cos1; + __le64 rx_discard_packets_cos2; + __le64 rx_discard_packets_cos3; + __le64 rx_discard_packets_cos4; + __le64 rx_discard_packets_cos5; + __le64 rx_discard_packets_cos6; + __le64 rx_discard_packets_cos7; }; /* hwrm_port_qstats_ext_input (size:320b/40B) */ @@ -6115,6 +6136,21 @@ struct hwrm_cfa_flow_alloc_output { u8 valid; }; +/* hwrm_cfa_flow_alloc_cmd_err (size:64b/8B) */ +struct hwrm_cfa_flow_alloc_cmd_err { + u8 code; + #define CFA_FLOW_ALLOC_CMD_ERR_CODE_UNKNOWN 0x0UL + #define CFA_FLOW_ALLOC_CMD_ERR_CODE_L2_CONTEXT_TCAM 0x1UL + #define CFA_FLOW_ALLOC_CMD_ERR_CODE_ACTION_RECORD 0x2UL + #define CFA_FLOW_ALLOC_CMD_ERR_CODE_FLOW_COUNTER 0x3UL + #define CFA_FLOW_ALLOC_CMD_ERR_CODE_WILD_CARD_TCAM 0x4UL + #define CFA_FLOW_ALLOC_CMD_ERR_CODE_HASH_COLLISION 0x5UL + #define CFA_FLOW_ALLOC_CMD_ERR_CODE_KEY_EXISTS 0x6UL + #define CFA_FLOW_ALLOC_CMD_ERR_CODE_FLOW_CTXT_DB 0x7UL + #define CFA_FLOW_ALLOC_CMD_ERR_CODE_LAST CFA_FLOW_ALLOC_CMD_ERR_CODE_FLOW_CTXT_DB + u8 unused_0[7]; +}; + /* hwrm_cfa_flow_free_input (size:256b/32B) */ struct hwrm_cfa_flow_free_input { __le16 req_type; @@ -6305,7 +6341,7 @@ struct hwrm_cfa_eem_qcaps_input { __le32 unused_0; }; -/* hwrm_cfa_eem_qcaps_output (size:256b/32B) */ +/* hwrm_cfa_eem_qcaps_output (size:320b/40B) */ struct hwrm_cfa_eem_qcaps_output { __le16 error_code; __le16 req_type; @@ -6322,15 +6358,17 @@ struct hwrm_cfa_eem_qcaps_output { #define CFA_EEM_QCAPS_RESP_SUPPORTED_KEY1_TABLE 0x2UL #define CFA_EEM_QCAPS_RESP_SUPPORTED_EXTERNAL_RECORD_TABLE 0x4UL #define CFA_EEM_QCAPS_RESP_SUPPORTED_EXTERNAL_FLOW_COUNTERS_TABLE 0x8UL + #define CFA_EEM_QCAPS_RESP_SUPPORTED_FID_TABLE 0x10UL __le32 max_entries_supported; __le16 key_entry_size; __le16 record_entry_size; __le16 efc_entry_size; - u8 unused_1; + __le16 fid_entry_size; + u8 unused_1[7]; u8 valid; }; -/* hwrm_cfa_eem_cfg_input (size:320b/40B) */ +/* hwrm_cfa_eem_cfg_input (size:384b/48B) */ struct hwrm_cfa_eem_cfg_input { __le16 req_type; __le16 cmpl_ring; @@ -6350,6 +6388,9 @@ struct hwrm_cfa_eem_cfg_input { __le16 key1_ctx_id; __le16 record_ctx_id; __le16 efc_ctx_id; + __le16 fid_ctx_id; + __le16 unused_2; + __le32 unused_3; }; /* hwrm_cfa_eem_cfg_output (size:128b/16B) */ @@ -6375,7 +6416,7 @@ struct hwrm_cfa_eem_qcfg_input { __le32 unused_0; }; -/* hwrm_cfa_eem_qcfg_output (size:192b/24B) */ +/* hwrm_cfa_eem_qcfg_output (size:256b/32B) */ struct hwrm_cfa_eem_qcfg_output { __le16 error_code; __le16 req_type; @@ -6386,7 +6427,12 @@ struct hwrm_cfa_eem_qcfg_output { #define CFA_EEM_QCFG_RESP_FLAGS_PATH_RX 0x2UL #define CFA_EEM_QCFG_RESP_FLAGS_PREFERRED_OFFLOAD 0x4UL __le32 num_entries; - u8 unused_0[7]; + __le16 key0_ctx_id; + __le16 key1_ctx_id; + __le16 record_ctx_id; + __le16 efc_ctx_id; + __le16 fid_ctx_id; + u8 unused_2[5]; u8 valid; }; @@ -6567,6 +6613,31 @@ struct ctx_hw_stats { __le64 tpa_aborts; }; +/* ctx_hw_stats_ext (size:1344b/168B) */ +struct ctx_hw_stats_ext { + __le64 rx_ucast_pkts; + __le64 rx_mcast_pkts; + __le64 rx_bcast_pkts; + __le64 rx_discard_pkts; + __le64 rx_drop_pkts; + __le64 rx_ucast_bytes; + __le64 rx_mcast_bytes; + __le64 rx_bcast_bytes; + __le64 tx_ucast_pkts; + __le64 tx_mcast_pkts; + __le64 tx_bcast_pkts; + __le64 tx_discard_pkts; + __le64 tx_drop_pkts; + __le64 tx_ucast_bytes; + __le64 tx_mcast_bytes; + __le64 tx_bcast_bytes; + __le64 rx_tpa_eligible_pkt; + __le64 rx_tpa_eligible_bytes; + __le64 rx_tpa_pkt; + __le64 rx_tpa_bytes; + __le64 rx_tpa_errors; +}; + /* hwrm_stat_ctx_alloc_input (size:256b/32B) */ struct hwrm_stat_ctx_alloc_input { __le16 req_type; @@ -6578,7 +6649,8 @@ struct hwrm_stat_ctx_alloc_input { __le32 update_period_ms; u8 stat_ctx_flags; #define STAT_CTX_ALLOC_REQ_STAT_CTX_FLAGS_ROCE 0x1UL - u8 unused_0[3]; + u8 unused_0; + __le16 stats_dma_length; }; /* hwrm_stat_ctx_alloc_output (size:128b/16B) */ @@ -7204,7 +7276,9 @@ struct coredump_segment_record { u8 version_hi; u8 version_low; u8 seg_flags; - u8 unused_0[7]; + u8 compress_flags; + #define SFLAG_COMPRESSED_ZLIB 0x1UL + u8 unused_0[6]; }; /* hwrm_dbg_coredump_list_input (size:256b/32B) */ @@ -7729,6 +7803,9 @@ struct hwrm_nvm_set_variable_input { #define NVM_SET_VARIABLE_REQ_FLAGS_ENCRYPT_MODE_AES256 (0x2UL << 1) #define NVM_SET_VARIABLE_REQ_FLAGS_ENCRYPT_MODE_HMAC_SHA1_AUTH (0x3UL << 1) #define NVM_SET_VARIABLE_REQ_FLAGS_ENCRYPT_MODE_LAST NVM_SET_VARIABLE_REQ_FLAGS_ENCRYPT_MODE_HMAC_SHA1_AUTH + #define NVM_SET_VARIABLE_REQ_FLAGS_FLAGS_UNUSED_0_MASK 0x70UL + #define NVM_SET_VARIABLE_REQ_FLAGS_FLAGS_UNUSED_0_SFT 4 + #define NVM_SET_VARIABLE_REQ_FLAGS_FACTORY_DEFAULT 0x80UL u8 unused_0; }; diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c index c0266a87794c..4ab57d33a87e 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c @@ -1594,7 +1594,7 @@ int nicvf_sq_append_skb(struct nicvf *nic, struct snd_queue *sq, size = skb_frag_size(frag); dma_addr = dma_map_page_attrs(&nic->pdev->dev, skb_frag_page(frag), - frag->page_offset, size, + skb_frag_off(frag), size, DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); if (dma_mapping_error(&nic->pdev->dev, dma_addr)) { diff --git a/drivers/net/ethernet/chelsio/cxgb3/sge.c b/drivers/net/ethernet/chelsio/cxgb3/sge.c index 310a232e00f0..6dabbf1502c7 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c @@ -2182,7 +2182,7 @@ static void lro_add_page(struct adapter *adap, struct sge_qset *qs, rx_frag += nr_frags; __skb_frag_set_page(rx_frag, sd->pg_chunk.page); - rx_frag->page_offset = sd->pg_chunk.offset + offset; + skb_frag_off_set(rx_frag, sd->pg_chunk.offset + offset); skb_frag_size_set(rx_frag, len); skb->len += len; diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c index 46dd6b4886b6..e736ce2c58ca 100644 --- a/drivers/net/ethernet/cortina/gemini.c +++ b/drivers/net/ethernet/cortina/gemini.c @@ -2422,10 +2422,8 @@ static int gemini_ethernet_port_probe(struct platform_device *pdev) /* Interrupt */ irq = platform_get_irq(pdev, 0); - if (irq <= 0) { - dev_err(dev, "no IRQ\n"); + if (irq <= 0) return irq ? irq : -ENODEV; - } port->irq = irq; /* Clock the port */ diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c index 386bdc1378d1..cce90b5925d9 100644 --- a/drivers/net/ethernet/davicom/dm9000.c +++ b/drivers/net/ethernet/davicom/dm9000.c @@ -1500,8 +1500,6 @@ dm9000_probe(struct platform_device *pdev) ndev->irq = platform_get_irq(pdev, 0); if (ndev->irq < 0) { - dev_err(db->dev, "interrupt resource unavailable: %d\n", - ndev->irq); ret = ndev->irq; goto out; } diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index e00a94a03879..1c9883019767 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -2346,8 +2346,8 @@ static void skb_fill_rx_data(struct be_rx_obj *rxo, struct sk_buff *skb, memcpy(skb->data, start, hdr_len); skb_shinfo(skb)->nr_frags = 1; skb_frag_set_page(skb, 0, page_info->page); - skb_shinfo(skb)->frags[0].page_offset = - page_info->page_offset + hdr_len; + skb_frag_off_set(&skb_shinfo(skb)->frags[0], + page_info->page_offset + hdr_len); skb_frag_size_set(&skb_shinfo(skb)->frags[0], curr_frag_len - hdr_len); skb->data_len = curr_frag_len - hdr_len; @@ -2372,8 +2372,8 @@ static void skb_fill_rx_data(struct be_rx_obj *rxo, struct sk_buff *skb, /* Fresh page */ j++; skb_frag_set_page(skb, j, page_info->page); - skb_shinfo(skb)->frags[j].page_offset = - page_info->page_offset; + skb_frag_off_set(&skb_shinfo(skb)->frags[j], + page_info->page_offset); skb_frag_size_set(&skb_shinfo(skb)->frags[j], 0); skb_shinfo(skb)->nr_frags++; } else { @@ -2454,8 +2454,8 @@ static void be_rx_compl_process_gro(struct be_rx_obj *rxo, /* First frag or Fresh page */ j++; skb_frag_set_page(skb, j, page_info->page); - skb_shinfo(skb)->frags[j].page_offset = - page_info->page_offset; + skb_frag_off_set(&skb_shinfo(skb)->frags[j], + page_info->page_offset); skb_frag_size_set(&skb_shinfo(skb)->frags[j], 0); } else { put_page(page_info->page); diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c index 5fad73b2e123..3981c06f082f 100644 --- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c +++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c @@ -501,7 +501,7 @@ fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) nr_frags = skb_shinfo(skb)->nr_frags; frag = skb_shinfo(skb)->frags; for (i = 0; i < nr_frags; i++, frag++) { - if (!IS_ALIGNED(frag->page_offset, 4)) { + if (!IS_ALIGNED(skb_frag_off(frag), 4)) { is_aligned = 0; break; } diff --git a/drivers/net/ethernet/hisilicon/hisi_femac.c b/drivers/net/ethernet/hisilicon/hisi_femac.c index 689f18e3100f..90ab7ade44c4 100644 --- a/drivers/net/ethernet/hisilicon/hisi_femac.c +++ b/drivers/net/ethernet/hisilicon/hisi_femac.c @@ -877,7 +877,6 @@ static int hisi_femac_drv_probe(struct platform_device *pdev) ndev->irq = platform_get_irq(pdev, 0); if (ndev->irq <= 0) { - dev_err(dev, "No irq resource\n"); ret = -ENODEV; goto out_disconnect_phy; } diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 48c7b70fc2c4..a4624db3b5d5 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -179,6 +179,15 @@ struct hnae3_vector_info { #define HNAE3_RING_GL_RX 0 #define HNAE3_RING_GL_TX 1 +#define HNAE3_FW_VERSION_BYTE3_SHIFT 24 +#define HNAE3_FW_VERSION_BYTE3_MASK GENMASK(31, 24) +#define HNAE3_FW_VERSION_BYTE2_SHIFT 16 +#define HNAE3_FW_VERSION_BYTE2_MASK GENMASK(23, 16) +#define HNAE3_FW_VERSION_BYTE1_SHIFT 8 +#define HNAE3_FW_VERSION_BYTE1_MASK GENMASK(15, 8) +#define HNAE3_FW_VERSION_BYTE0_SHIFT 0 +#define HNAE3_FW_VERSION_BYTE0_MASK GENMASK(7, 0) + struct hnae3_ring_chain_node { struct hnae3_ring_chain_node *next; u32 tqp_index; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 69f7ef810654..d2df42d30d88 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -459,6 +459,9 @@ static int hns3_nic_net_open(struct net_device *netdev) h->ae_algo->ops->set_timer_task(priv->ae_handle, true); hns3_config_xps(priv); + + netif_dbg(h, drv, netdev, "net open\n"); + return 0; } @@ -519,6 +522,8 @@ static int hns3_nic_net_stop(struct net_device *netdev) if (test_and_set_bit(HNS3_NIC_STATE_DOWN, &priv->state)) return 0; + netif_dbg(h, drv, netdev, "net stop\n"); + if (h->ae_algo->ops->set_timer_task) h->ae_algo->ops->set_timer_task(priv->ae_handle, false); @@ -1550,6 +1555,8 @@ static int hns3_setup_tc(struct net_device *netdev, void *type_data) h = hns3_get_handle(netdev); kinfo = &h->kinfo; + netif_dbg(h, drv, netdev, "setup tc: num_tc=%u\n", tc); + return (kinfo->dcb_ops && kinfo->dcb_ops->setup_tc) ? kinfo->dcb_ops->setup_tc(h, tc, prio_tc) : -EOPNOTSUPP; } @@ -1593,6 +1600,10 @@ static int hns3_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, struct hnae3_handle *h = hns3_get_handle(netdev); int ret = -EIO; + netif_dbg(h, drv, netdev, + "set vf vlan: vf=%d, vlan=%u, qos=%u, vlan_proto=%u\n", + vf, vlan, qos, vlan_proto); + if (h->ae_algo->ops->set_vf_vlan_filter) ret = h->ae_algo->ops->set_vf_vlan_filter(h, vf, vlan, qos, vlan_proto); @@ -1611,6 +1622,9 @@ static int hns3_nic_change_mtu(struct net_device *netdev, int new_mtu) if (!h->ae_algo->ops->set_mtu) return -EOPNOTSUPP; + netif_dbg(h, drv, netdev, + "change mtu from %u to %d\n", netdev->mtu, new_mtu); + ret = h->ae_algo->ops->set_mtu(h, new_mtu); if (ret) netdev_err(netdev, "failed to change MTU in hardware %d\n", @@ -1963,7 +1977,7 @@ static pci_ers_result_t hns3_slot_reset(struct pci_dev *pdev) ops = ae_dev->ops; /* request the reset */ - if (ops->reset_event) { + if (ops->reset_event && ops->get_reset_level) { if (ae_dev->hw_err_reset_req) { reset_type = ops->get_reset_level(ae_dev, &ae_dev->hw_err_reset_req); @@ -2067,7 +2081,7 @@ static void hns3_set_default_feature(struct net_device *netdev) static int hns3_alloc_buffer(struct hns3_enet_ring *ring, struct hns3_desc_cb *cb) { - unsigned int order = hnae3_page_order(ring); + unsigned int order = hns3_page_order(ring); struct page *p; p = dev_alloc_pages(order); @@ -2078,7 +2092,7 @@ static int hns3_alloc_buffer(struct hns3_enet_ring *ring, cb->page_offset = 0; cb->reuse_flag = 0; cb->buf = page_address(p); - cb->length = hnae3_page_size(ring); + cb->length = hns3_page_size(ring); cb->type = DESC_TYPE_PAGE; return 0; @@ -2381,7 +2395,7 @@ static void hns3_nic_reuse_page(struct sk_buff *skb, int i, { struct hns3_desc *desc = &ring->desc[ring->next_to_clean]; int size = le16_to_cpu(desc->rx.size); - u32 truesize = hnae3_buf_size(ring); + u32 truesize = hns3_buf_size(ring); skb_add_rx_frag(skb, i, desc_cb->priv, desc_cb->page_offset + pull_len, size - pull_len, truesize); @@ -2396,7 +2410,7 @@ static void hns3_nic_reuse_page(struct sk_buff *skb, int i, /* Move offset up to the next cache line */ desc_cb->page_offset += truesize; - if (desc_cb->page_offset + truesize <= hnae3_page_size(ring)) { + if (desc_cb->page_offset + truesize <= hns3_page_size(ring)) { desc_cb->reuse_flag = 1; /* Bump ref count on page before it is given */ get_page(desc_cb->priv); @@ -2678,7 +2692,7 @@ static int hns3_add_frag(struct hns3_enet_ring *ring, struct hns3_desc *desc, } if (ring->tail_skb) { - head_skb->truesize += hnae3_buf_size(ring); + head_skb->truesize += hns3_buf_size(ring); head_skb->data_len += le16_to_cpu(desc->rx.size); head_skb->len += le16_to_cpu(desc->rx.size); skb = ring->tail_skb; @@ -4378,6 +4392,9 @@ int hns3_set_channels(struct net_device *netdev, u16 org_tqp_num; int ret; + if (hns3_nic_resetting(netdev)) + return -EBUSY; + if (ch->rx_count || ch->tx_count) return -EINVAL; @@ -4392,6 +4409,10 @@ int hns3_set_channels(struct net_device *netdev, if (kinfo->rss_size == new_tqp_num) return 0; + netif_dbg(h, drv, netdev, + "set channels: tqp_num=%u, rxfh=%d\n", + new_tqp_num, rxfh_configured); + ret = hns3_reset_notify(h, HNAE3_DOWN_CLIENT); if (ret) return ret; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index 848b866761df..1a17856f9a3b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -608,9 +608,18 @@ static inline bool hns3_nic_resetting(struct net_device *netdev) #define tx_ring_data(priv, idx) ((priv)->ring_data[idx]) -#define hnae3_buf_size(_ring) ((_ring)->buf_size) -#define hnae3_page_order(_ring) (get_order(hnae3_buf_size(_ring))) -#define hnae3_page_size(_ring) (PAGE_SIZE << (u32)hnae3_page_order(_ring)) +#define hns3_buf_size(_ring) ((_ring)->buf_size) + +static inline unsigned int hns3_page_order(struct hns3_enet_ring *ring) +{ +#if (PAGE_SIZE < 8192) + if (ring->buf_size > (PAGE_SIZE / 2)) + return 1; +#endif + return 0; +} + +#define hns3_page_size(_ring) (PAGE_SIZE << hns3_page_order(_ring)) /* iterator for handling rings in ring group */ #define hns3_for_each_ring(pos, head) \ diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index 5bff98a9b0dc..fe0f82a97234 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -311,6 +311,8 @@ static void hns3_self_test(struct net_device *ndev, if (eth_test->flags != ETH_TEST_FL_OFFLINE) return; + netif_dbg(h, drv, ndev, "self test start"); + st_param[HNAE3_LOOP_APP][0] = HNAE3_LOOP_APP; st_param[HNAE3_LOOP_APP][1] = h->flags & HNAE3_SUPPORT_APP_LOOPBACK; @@ -374,6 +376,8 @@ static void hns3_self_test(struct net_device *ndev, if (if_running) ndev->netdev_ops->ndo_open(ndev); + + netif_dbg(h, drv, ndev, "self test end\n"); } static int hns3_get_sset_count(struct net_device *netdev, int stringset) @@ -527,6 +531,7 @@ static void hns3_get_drvinfo(struct net_device *netdev, { struct hns3_nic_priv *priv = netdev_priv(netdev); struct hnae3_handle *h = priv->ae_handle; + u32 fw_version; if (!h->ae_algo->ops->get_fw_version) { netdev_err(netdev, "could not get fw version!\n"); @@ -545,8 +550,18 @@ static void hns3_get_drvinfo(struct net_device *netdev, sizeof(drvinfo->bus_info)); drvinfo->bus_info[ETHTOOL_BUSINFO_LEN - 1] = '\0'; - snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), "0x%08x", - priv->ae_handle->ae_algo->ops->get_fw_version(h)); + fw_version = priv->ae_handle->ae_algo->ops->get_fw_version(h); + + snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), + "%lu.%lu.%lu.%lu", + hnae3_get_field(fw_version, HNAE3_FW_VERSION_BYTE3_MASK, + HNAE3_FW_VERSION_BYTE3_SHIFT), + hnae3_get_field(fw_version, HNAE3_FW_VERSION_BYTE2_MASK, + HNAE3_FW_VERSION_BYTE2_SHIFT), + hnae3_get_field(fw_version, HNAE3_FW_VERSION_BYTE1_MASK, + HNAE3_FW_VERSION_BYTE1_SHIFT), + hnae3_get_field(fw_version, HNAE3_FW_VERSION_BYTE0_MASK, + HNAE3_FW_VERSION_BYTE0_SHIFT)); } static u32 hns3_get_link(struct net_device *netdev) @@ -593,6 +608,10 @@ static int hns3_set_pauseparam(struct net_device *netdev, { struct hnae3_handle *h = hns3_get_handle(netdev); + netif_dbg(h, drv, netdev, + "set pauseparam: autoneg=%u, rx:%u, tx:%u\n", + param->autoneg, param->rx_pause, param->tx_pause); + if (h->ae_algo->ops->set_pauseparam) return h->ae_algo->ops->set_pauseparam(h, param->autoneg, param->rx_pause, @@ -732,6 +751,11 @@ static int hns3_set_link_ksettings(struct net_device *netdev, if (cmd->base.speed == SPEED_1000 && cmd->base.duplex == DUPLEX_HALF) return -EINVAL; + netif_dbg(handle, drv, netdev, + "set link(%s): autoneg=%u, speed=%u, duplex=%u\n", + netdev->phydev ? "phy" : "mac", + cmd->base.autoneg, cmd->base.speed, cmd->base.duplex); + /* Only support ksettings_set for netdev with phy attached for now */ if (netdev->phydev) return phy_ethtool_ksettings_set(netdev->phydev, cmd); @@ -973,6 +997,9 @@ static int hns3_nway_reset(struct net_device *netdev) return -EINVAL; } + netif_dbg(handle, drv, netdev, + "nway reset (using %s)\n", phy ? "phy" : "mac"); + if (phy) return genphy_restart_aneg(phy); @@ -1297,6 +1324,9 @@ static int hns3_set_fecparam(struct net_device *netdev, if (!ops->set_fec) return -EOPNOTSUPP; fec_mode = eth_to_loc_fec(fec->fec); + + netif_dbg(handle, drv, netdev, "set fecparam: mode=%u\n", fec_mode); + return ops->set_fec(handle, fec_mode); } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c index 22f6acd45d9a..d9858f285460 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c @@ -419,7 +419,15 @@ int hclge_cmd_init(struct hclge_dev *hdev) } hdev->fw_version = version; - dev_info(&hdev->pdev->dev, "The firmware version is %08x\n", version); + dev_info(&hdev->pdev->dev, "The firmware version is %lu.%lu.%lu.%lu\n", + hnae3_get_field(version, HNAE3_FW_VERSION_BYTE3_MASK, + HNAE3_FW_VERSION_BYTE3_SHIFT), + hnae3_get_field(version, HNAE3_FW_VERSION_BYTE2_MASK, + HNAE3_FW_VERSION_BYTE2_SHIFT), + hnae3_get_field(version, HNAE3_FW_VERSION_BYTE1_MASK, + HNAE3_FW_VERSION_BYTE1_SHIFT), + hnae3_get_field(version, HNAE3_FW_VERSION_BYTE0_MASK, + HNAE3_FW_VERSION_BYTE0_SHIFT)); return 0; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c index bac4ce13f6ae..814e0f076e32 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c @@ -201,6 +201,7 @@ static int hclge_client_setup_tc(struct hclge_dev *hdev) static int hclge_ieee_setets(struct hnae3_handle *h, struct ieee_ets *ets) { struct hclge_vport *vport = hclge_get_vport(h); + struct net_device *netdev = h->kinfo.netdev; struct hclge_dev *hdev = vport->back; bool map_changed = false; u8 num_tc = 0; @@ -215,6 +216,8 @@ static int hclge_ieee_setets(struct hnae3_handle *h, struct ieee_ets *ets) return ret; if (map_changed) { + netif_dbg(h, drv, netdev, "set ets\n"); + ret = hclge_notify_client(hdev, HNAE3_DOWN_CLIENT); if (ret) return ret; @@ -300,6 +303,7 @@ static int hclge_ieee_getpfc(struct hnae3_handle *h, struct ieee_pfc *pfc) static int hclge_ieee_setpfc(struct hnae3_handle *h, struct ieee_pfc *pfc) { struct hclge_vport *vport = hclge_get_vport(h); + struct net_device *netdev = h->kinfo.netdev; struct hclge_dev *hdev = vport->back; u8 i, j, pfc_map, *prio_tc; @@ -325,6 +329,10 @@ static int hclge_ieee_setpfc(struct hnae3_handle *h, struct ieee_pfc *pfc) hdev->tm_info.hw_pfc_map = pfc_map; hdev->tm_info.pfc_en = pfc->pfc_en; + netif_dbg(h, drv, netdev, + "set pfc: pfc_en=%u, pfc_map=%u, num_tc=%u\n", + pfc->pfc_en, pfc_map, hdev->tm_info.num_tc); + hclge_tm_pfc_info_update(hdev); return hclge_pause_setup_hw(hdev, false); @@ -345,8 +353,11 @@ static u8 hclge_getdcbx(struct hnae3_handle *h) static u8 hclge_setdcbx(struct hnae3_handle *h, u8 mode) { struct hclge_vport *vport = hclge_get_vport(h); + struct net_device *netdev = h->kinfo.netdev; struct hclge_dev *hdev = vport->back; + netif_dbg(h, drv, netdev, "set dcbx: mode=%u\n", mode); + /* No support for LLD_MANAGED modes or CEE */ if ((mode & DCB_CAP_DCBX_LLD_MANAGED) || (mode & DCB_CAP_DCBX_VER_CEE) || diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 3fde5471e1c0..4138780fca39 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -1270,6 +1270,12 @@ static int hclge_configure(struct hclge_dev *hdev) hclge_init_kdump_kernel_config(hdev); + /* Set the init affinity based on pci func number */ + i = cpumask_weight(cpumask_of_node(dev_to_node(&hdev->pdev->dev))); + i = i ? PCI_FUNC(hdev->pdev->devfn) % i : 0; + cpumask_set_cpu(cpumask_local_spread(i, dev_to_node(&hdev->pdev->dev)), + &hdev->affinity_mask); + return ret; } @@ -2499,22 +2505,29 @@ static void hclge_mbx_task_schedule(struct hclge_dev *hdev) { if (!test_bit(HCLGE_STATE_CMD_DISABLE, &hdev->state) && !test_and_set_bit(HCLGE_STATE_MBX_SERVICE_SCHED, &hdev->state)) - schedule_work(&hdev->mbx_service_task); + queue_work_on(cpumask_first(&hdev->affinity_mask), system_wq, + &hdev->mbx_service_task); } static void hclge_reset_task_schedule(struct hclge_dev *hdev) { if (!test_bit(HCLGE_STATE_REMOVING, &hdev->state) && !test_and_set_bit(HCLGE_STATE_RST_SERVICE_SCHED, &hdev->state)) - schedule_work(&hdev->rst_service_task); + queue_work_on(cpumask_first(&hdev->affinity_mask), system_wq, + &hdev->rst_service_task); } static void hclge_task_schedule(struct hclge_dev *hdev) { if (!test_bit(HCLGE_STATE_DOWN, &hdev->state) && !test_bit(HCLGE_STATE_REMOVING, &hdev->state) && - !test_and_set_bit(HCLGE_STATE_SERVICE_SCHED, &hdev->state)) - (void)schedule_work(&hdev->service_task); + !test_and_set_bit(HCLGE_STATE_SERVICE_SCHED, &hdev->state)) { + hdev->hw_stats.stats_timer++; + hdev->fd_arfs_expire_timer++; + mod_delayed_work_on(cpumask_first(&hdev->affinity_mask), + system_wq, &hdev->service_task, + round_jiffies_relative(HZ)); + } } static int hclge_get_mac_link_status(struct hclge_dev *hdev) @@ -2729,25 +2742,6 @@ static int hclge_get_status(struct hnae3_handle *handle) return hdev->hw.mac.link; } -static void hclge_service_timer(struct timer_list *t) -{ - struct hclge_dev *hdev = from_timer(hdev, t, service_timer); - - mod_timer(&hdev->service_timer, jiffies + HZ); - hdev->hw_stats.stats_timer++; - hdev->fd_arfs_expire_timer++; - hclge_task_schedule(hdev); -} - -static void hclge_service_complete(struct hclge_dev *hdev) -{ - WARN_ON(!test_bit(HCLGE_STATE_SERVICE_SCHED, &hdev->state)); - - /* Flush memory before next watchdog */ - smp_mb__before_atomic(); - clear_bit(HCLGE_STATE_SERVICE_SCHED, &hdev->state); -} - static u32 hclge_check_event_cause(struct hclge_dev *hdev, u32 *clearval) { u32 rst_src_reg, cmdq_src_reg, msix_src_reg; @@ -2918,6 +2912,36 @@ static void hclge_get_misc_vector(struct hclge_dev *hdev) hdev->num_msi_used += 1; } +static void hclge_irq_affinity_notify(struct irq_affinity_notify *notify, + const cpumask_t *mask) +{ + struct hclge_dev *hdev = container_of(notify, struct hclge_dev, + affinity_notify); + + cpumask_copy(&hdev->affinity_mask, mask); +} + +static void hclge_irq_affinity_release(struct kref *ref) +{ +} + +static void hclge_misc_affinity_setup(struct hclge_dev *hdev) +{ + irq_set_affinity_hint(hdev->misc_vector.vector_irq, + &hdev->affinity_mask); + + hdev->affinity_notify.notify = hclge_irq_affinity_notify; + hdev->affinity_notify.release = hclge_irq_affinity_release; + irq_set_affinity_notifier(hdev->misc_vector.vector_irq, + &hdev->affinity_notify); +} + +static void hclge_misc_affinity_teardown(struct hclge_dev *hdev) +{ + irq_set_affinity_notifier(hdev->misc_vector.vector_irq, NULL); + irq_set_affinity_hint(hdev->misc_vector.vector_irq, NULL); +} + static int hclge_misc_irq_init(struct hclge_dev *hdev) { int ret; @@ -3305,7 +3329,7 @@ static int hclge_reset_prepare_wait(struct hclge_dev *hdev) return ret; } -static bool hclge_reset_err_handle(struct hclge_dev *hdev, bool is_timeout) +static bool hclge_reset_err_handle(struct hclge_dev *hdev) { #define MAX_RESET_FAIL_CNT 5 @@ -3322,20 +3346,11 @@ static bool hclge_reset_err_handle(struct hclge_dev *hdev, bool is_timeout) return false; } else if (hdev->reset_fail_cnt < MAX_RESET_FAIL_CNT) { hdev->reset_fail_cnt++; - if (is_timeout) { - set_bit(hdev->reset_type, &hdev->reset_pending); - dev_info(&hdev->pdev->dev, - "re-schedule to wait for hw reset done\n"); - return true; - } - - dev_info(&hdev->pdev->dev, "Upgrade reset level\n"); - hclge_clear_reset_cause(hdev); - set_bit(HNAE3_GLOBAL_RESET, &hdev->default_reset_request); - mod_timer(&hdev->reset_timer, - jiffies + HCLGE_RESET_INTERVAL); - - return false; + set_bit(hdev->reset_type, &hdev->reset_pending); + dev_info(&hdev->pdev->dev, + "re-schedule reset task(%d)\n", + hdev->reset_fail_cnt); + return true; } hclge_clear_reset_cause(hdev); @@ -3382,7 +3397,6 @@ static int hclge_reset_stack(struct hclge_dev *hdev) static void hclge_reset(struct hclge_dev *hdev) { struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev); - bool is_timeout = false; int ret; /* Initialize ae_dev reset status as well, in case enet layer wants to @@ -3410,10 +3424,8 @@ static void hclge_reset(struct hclge_dev *hdev) if (ret) goto err_reset; - if (hclge_reset_wait(hdev)) { - is_timeout = true; + if (hclge_reset_wait(hdev)) goto err_reset; - } hdev->rst_stats.hw_reset_done_cnt++; @@ -3465,7 +3477,7 @@ static void hclge_reset(struct hclge_dev *hdev) err_reset_lock: rtnl_unlock(); err_reset: - if (hclge_reset_err_handle(hdev, is_timeout)) + if (hclge_reset_err_handle(hdev)) hclge_reset_task_schedule(hdev); } @@ -3606,7 +3618,9 @@ static void hclge_update_vport_alive(struct hclge_dev *hdev) static void hclge_service_task(struct work_struct *work) { struct hclge_dev *hdev = - container_of(work, struct hclge_dev, service_task); + container_of(work, struct hclge_dev, service_task.work); + + clear_bit(HCLGE_STATE_SERVICE_SCHED, &hdev->state); if (hdev->hw_stats.stats_timer >= HCLGE_STATS_TIMER_INTERVAL) { hclge_update_stats_for_all(hdev); @@ -3621,7 +3635,8 @@ static void hclge_service_task(struct work_struct *work) hclge_rfs_filter_expire(hdev); hdev->fd_arfs_expire_timer = 0; } - hclge_service_complete(hdev); + + hclge_task_schedule(hdev); } struct hclge_vport *hclge_get_vport(struct hnae3_handle *handle) @@ -5808,7 +5823,7 @@ static int hclge_add_fd_entry_by_arfs(struct hnae3_handle *handle, u16 queue_id, return -ENOSPC; } - rule = kzalloc(sizeof(*rule), GFP_KERNEL); + rule = kzalloc(sizeof(*rule), GFP_ATOMIC); if (!rule) { spin_unlock_bh(&hdev->fd_rule_lock); @@ -6160,10 +6175,13 @@ static void hclge_set_timer_task(struct hnae3_handle *handle, bool enable) struct hclge_dev *hdev = vport->back; if (enable) { - mod_timer(&hdev->service_timer, jiffies + HZ); + hclge_task_schedule(hdev); } else { - del_timer_sync(&hdev->service_timer); - cancel_work_sync(&hdev->service_task); + /* Set the DOWN flag here to disable the service to be + * scheduled again + */ + set_bit(HCLGE_STATE_DOWN, &hdev->state); + cancel_delayed_work_sync(&hdev->service_task); clear_bit(HCLGE_STATE_SERVICE_SCHED, &hdev->state); } } @@ -8602,12 +8620,10 @@ static void hclge_state_uninit(struct hclge_dev *hdev) set_bit(HCLGE_STATE_DOWN, &hdev->state); set_bit(HCLGE_STATE_REMOVING, &hdev->state); - if (hdev->service_timer.function) - del_timer_sync(&hdev->service_timer); if (hdev->reset_timer.function) del_timer_sync(&hdev->reset_timer); - if (hdev->service_task.func) - cancel_work_sync(&hdev->service_task); + if (hdev->service_task.work.func) + cancel_delayed_work_sync(&hdev->service_task); if (hdev->rst_service_task.func) cancel_work_sync(&hdev->rst_service_task); if (hdev->mbx_service_task.func) @@ -8812,12 +8828,16 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev) hclge_dcb_ops_set(hdev); - timer_setup(&hdev->service_timer, hclge_service_timer, 0); timer_setup(&hdev->reset_timer, hclge_reset_timer, 0); - INIT_WORK(&hdev->service_task, hclge_service_task); + INIT_DELAYED_WORK(&hdev->service_task, hclge_service_task); INIT_WORK(&hdev->rst_service_task, hclge_reset_service_task); INIT_WORK(&hdev->mbx_service_task, hclge_mailbox_service_task); + /* Setup affinity after service timer setup because add_timer_on + * is called in affinity notify. + */ + hclge_misc_affinity_setup(hdev); + hclge_clear_all_event_cause(hdev); hclge_clear_resetting_state(hdev); @@ -8842,7 +8862,9 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev) hclge_state_init(hdev); hdev->last_reset_time = jiffies; - pr_info("%s driver initialization finished.\n", HCLGE_DRIVER_NAME); + dev_info(&hdev->pdev->dev, "%s driver initialization finished.\n", + HCLGE_DRIVER_NAME); + return 0; err_mdiobus_unreg: @@ -8979,6 +9001,7 @@ static void hclge_uninit_ae_dev(struct hnae3_ae_dev *ae_dev) struct hclge_dev *hdev = ae_dev->priv; struct hclge_mac *mac = &hdev->hw.mac; + hclge_misc_affinity_teardown(hdev); hclge_state_uninit(hdev); if (mac->phydev) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 6a12285f4c76..688e4250491d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -806,9 +806,8 @@ struct hclge_dev { u16 adminq_work_limit; /* Num of admin receive queue desc to process */ unsigned long service_timer_period; unsigned long service_timer_previous; - struct timer_list service_timer; struct timer_list reset_timer; - struct work_struct service_task; + struct delayed_work service_task; struct work_struct rst_service_task; struct work_struct mbx_service_task; @@ -864,6 +863,10 @@ struct hclge_dev { DECLARE_KFIFO(mac_tnl_log, struct hclge_mac_tnl_stats, HCLGE_MAC_TNL_LOG_SIZE); + + /* affinity mask and notify for misc interrupt */ + cpumask_t affinity_mask; + struct irq_affinity_notify affinity_notify; }; /* VPort level vlan tag configuration for TX direction */ diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c index 652b796044e3..8f21eb3d9bd2 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c @@ -405,7 +405,15 @@ int hclgevf_cmd_init(struct hclgevf_dev *hdev) } hdev->fw_version = version; - dev_info(&hdev->pdev->dev, "The firmware version is %08x\n", version); + dev_info(&hdev->pdev->dev, "The firmware version is %lu.%lu.%lu.%lu\n", + hnae3_get_field(version, HNAE3_FW_VERSION_BYTE3_MASK, + HNAE3_FW_VERSION_BYTE3_SHIFT), + hnae3_get_field(version, HNAE3_FW_VERSION_BYTE2_MASK, + HNAE3_FW_VERSION_BYTE2_SHIFT), + hnae3_get_field(version, HNAE3_FW_VERSION_BYTE1_MASK, + HNAE3_FW_VERSION_BYTE1_SHIFT), + hnae3_get_field(version, HNAE3_FW_VERSION_BYTE0_MASK, + HNAE3_FW_VERSION_BYTE0_SHIFT)); return 0; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index a13a0e101c3b..ae0e6a69d54b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -2695,7 +2695,8 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev) } hdev->last_reset_time = jiffies; - pr_info("finished initializing %s driver\n", HCLGEVF_DRIVER_NAME); + dev_info(&hdev->pdev->dev, "finished initializing %s driver\n", + HCLGEVF_DRIVER_NAME); return 0; diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 3da680073265..81a05ea38237 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -1485,7 +1485,7 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev) memcpy(dst + cur, page_address(skb_frag_page(frag)) + - frag->page_offset, skb_frag_size(frag)); + skb_frag_off(frag), skb_frag_size(frag)); cur += skb_frag_size(frag); } } else { diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index f162252f01b5..e3f29dc8b290 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -3306,7 +3306,7 @@ bool __i40e_chk_linearize(struct sk_buff *skb) * descriptor associated with the fragment. */ if (stale_size > I40E_MAX_DATA_PER_TXD) { - int align_pad = -(stale->page_offset) & + int align_pad = -(skb_frag_off(stale)) & (I40E_MAX_READ_REQ_SIZE - 1); sum -= align_pad; diff --git a/drivers/net/ethernet/intel/iavf/iavf_txrx.c b/drivers/net/ethernet/intel/iavf/iavf_txrx.c index fae7cd1c618a..7a30d5d5ef53 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_txrx.c +++ b/drivers/net/ethernet/intel/iavf/iavf_txrx.c @@ -2205,7 +2205,7 @@ bool __iavf_chk_linearize(struct sk_buff *skb) * descriptor associated with the fragment. */ if (stale_size > IAVF_MAX_DATA_PER_TXD) { - int align_pad = -(stale->page_offset) & + int align_pad = -(skb_frag_off(stale)) & (IAVF_MAX_READ_REQ_SIZE - 1); sum -= align_pad; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index e12d23d1fa64..dc7b128c780e 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -1807,7 +1807,7 @@ static void ixgbe_pull_tail(struct ixgbe_ring *rx_ring, /* update all of the pointers */ skb_frag_size_sub(frag, pull_len); - frag->page_offset += pull_len; + skb_frag_off_add(frag, pull_len); skb->data_len -= pull_len; skb->tail += pull_len; } @@ -1844,7 +1844,7 @@ static void ixgbe_dma_sync_frag(struct ixgbe_ring *rx_ring, dma_sync_single_range_for_cpu(rx_ring->dev, IXGBE_CB(skb)->dma, - frag->page_offset, + skb_frag_off(frag), skb_frag_size(frag), DMA_FROM_DEVICE); } diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c index 9c3ab00643bd..6d52cf5ce20e 100644 --- a/drivers/net/ethernet/jme.c +++ b/drivers/net/ethernet/jme.c @@ -2040,8 +2040,8 @@ jme_map_tx_skb(struct jme_adapter *jme, struct sk_buff *skb, int idx) ctxbi = txbi + ((idx + i + 2) & (mask)); ret = jme_fill_tx_map(jme->pdev, ctxdesc, ctxbi, - skb_frag_page(frag), - frag->page_offset, skb_frag_size(frag), hidma); + skb_frag_page(frag), skb_frag_off(frag), + skb_frag_size(frag), hidma); if (ret) { jme_drop_tx_map(jme, idx, i); goto out; diff --git a/drivers/net/ethernet/lantiq_xrx200.c b/drivers/net/ethernet/lantiq_xrx200.c index cda641ef89af..900affbdcc0e 100644 --- a/drivers/net/ethernet/lantiq_xrx200.c +++ b/drivers/net/ethernet/lantiq_xrx200.c @@ -458,17 +458,11 @@ static int xrx200_probe(struct platform_device *pdev) } priv->chan_rx.dma.irq = platform_get_irq_byname(pdev, "rx"); - if (priv->chan_rx.dma.irq < 0) { - dev_err(dev, "failed to get RX IRQ, %i\n", - priv->chan_rx.dma.irq); + if (priv->chan_rx.dma.irq < 0) return -ENOENT; - } priv->chan_tx.dma.irq = platform_get_irq_byname(pdev, "tx"); - if (priv->chan_tx.dma.irq < 0) { - dev_err(dev, "failed to get TX IRQ, %i\n", - priv->chan_tx.dma.irq); + if (priv->chan_tx.dma.irq < 0) return -ENOENT; - } /* get the clock */ priv->clk = devm_clk_get(dev, NULL); diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index 88ea5ac83c93..82ea55ae5053 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -659,7 +659,7 @@ static inline unsigned int has_tiny_unaligned_frags(struct sk_buff *skb) for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) { const skb_frag_t *fragp = &skb_shinfo(skb)->frags[frag]; - if (skb_frag_size(fragp) <= 8 && fragp->page_offset & 7) + if (skb_frag_size(fragp) <= 8 && skb_frag_off(fragp) & 7) return 1; } diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index c1438ae52a11..40ec5acf79c0 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -2645,14 +2645,6 @@ out: en_err(priv, "failed setting L2 tunnel configuration ret %d\n", ret); return; } - - /* set offloads */ - priv->dev->hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_RXCSUM | - NETIF_F_TSO | NETIF_F_TSO6 | - NETIF_F_GSO_UDP_TUNNEL | - NETIF_F_GSO_UDP_TUNNEL_CSUM | - NETIF_F_GSO_PARTIAL; } static void mlx4_en_del_vxlan_offloads(struct work_struct *work) @@ -2660,14 +2652,6 @@ static void mlx4_en_del_vxlan_offloads(struct work_struct *work) int ret; struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv, vxlan_del_task); - /* unset offloads */ - priv->dev->hw_enc_features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_RXCSUM | - NETIF_F_TSO | NETIF_F_TSO6 | - NETIF_F_GSO_UDP_TUNNEL | - NETIF_F_GSO_UDP_TUNNEL_CSUM | - NETIF_F_GSO_PARTIAL); - ret = mlx4_SET_PORT_VXLAN(priv->mdev->dev, priv->port, VXLAN_STEER_BY_OUTER_MAC, 0); if (ret) @@ -3415,6 +3399,23 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, if (mdev->LSO_support) dev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6; + if (mdev->dev->caps.tunnel_offload_mode == + MLX4_TUNNEL_OFFLOAD_MODE_VXLAN) { + dev->hw_features |= NETIF_F_GSO_UDP_TUNNEL | + NETIF_F_GSO_UDP_TUNNEL_CSUM | + NETIF_F_GSO_PARTIAL; + dev->features |= NETIF_F_GSO_UDP_TUNNEL | + NETIF_F_GSO_UDP_TUNNEL_CSUM | + NETIF_F_GSO_PARTIAL; + dev->gso_partial_features = NETIF_F_GSO_UDP_TUNNEL_CSUM; + dev->hw_enc_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | + NETIF_F_RXCSUM | + NETIF_F_TSO | NETIF_F_TSO6 | + NETIF_F_GSO_UDP_TUNNEL | + NETIF_F_GSO_UDP_TUNNEL_CSUM | + NETIF_F_GSO_PARTIAL; + } + dev->vlan_features = dev->hw_features; dev->hw_features |= NETIF_F_RXCSUM | NETIF_F_RXHASH; @@ -3483,16 +3484,6 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, priv->rss_hash_fn = ETH_RSS_HASH_TOP; } - if (mdev->dev->caps.tunnel_offload_mode == MLX4_TUNNEL_OFFLOAD_MODE_VXLAN) { - dev->hw_features |= NETIF_F_GSO_UDP_TUNNEL | - NETIF_F_GSO_UDP_TUNNEL_CSUM | - NETIF_F_GSO_PARTIAL; - dev->features |= NETIF_F_GSO_UDP_TUNNEL | - NETIF_F_GSO_UDP_TUNNEL_CSUM | - NETIF_F_GSO_PARTIAL; - dev->gso_partial_features = NETIF_F_GSO_UDP_TUNNEL_CSUM; - } - /* MTU range: 68 - hw-specific max */ dev->min_mtu = ETH_MIN_MTU; dev->max_mtu = priv->max_mtu; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 7e8a54068d92..9277b3f125e8 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -1625,7 +1625,7 @@ mlxsw_sp_setup_tc_block_flower_bind(struct mlxsw_sp_port *mlxsw_sp_port, } flow_block_cb_incref(block_cb); err = mlxsw_sp_acl_block_bind(mlxsw_sp, acl_block, - mlxsw_sp_port, ingress); + mlxsw_sp_port, ingress, f->extack); if (err) goto err_block_bind; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 131f62ce9297..c78d93afbb9d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -623,7 +623,8 @@ struct mlxsw_sp_acl_rule_info { unsigned int priority; struct mlxsw_afk_element_values values; struct mlxsw_afa_block *act_block; - u8 action_created:1; + u8 action_created:1, + egress_bind_blocker:1; unsigned int counter_index; }; @@ -642,6 +643,7 @@ struct mlxsw_sp_acl_block { struct mlxsw_sp *mlxsw_sp; unsigned int rule_count; unsigned int disable_count; + unsigned int egress_blocker_rule_count; struct net *net; }; @@ -657,7 +659,8 @@ void mlxsw_sp_acl_block_destroy(struct mlxsw_sp_acl_block *block); int mlxsw_sp_acl_block_bind(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_block *block, struct mlxsw_sp_port *mlxsw_sp_port, - bool ingress); + bool ingress, + struct netlink_ext_ack *extack); int mlxsw_sp_acl_block_unbind(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_block *block, struct mlxsw_sp_port *mlxsw_sp_port, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c index e8ac90564dbe..1aaab8446270 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c @@ -239,7 +239,8 @@ mlxsw_sp_acl_block_lookup(struct mlxsw_sp_acl_block *block, int mlxsw_sp_acl_block_bind(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_block *block, struct mlxsw_sp_port *mlxsw_sp_port, - bool ingress) + bool ingress, + struct netlink_ext_ack *extack) { struct mlxsw_sp_acl_block_binding *binding; int err; @@ -247,6 +248,11 @@ int mlxsw_sp_acl_block_bind(struct mlxsw_sp *mlxsw_sp, if (WARN_ON(mlxsw_sp_acl_block_lookup(block, mlxsw_sp_port, ingress))) return -EEXIST; + if (!ingress && block->egress_blocker_rule_count) { + NL_SET_ERR_MSG_MOD(extack, "Block cannot be bound to egress because it contains unsupported rules"); + return -EOPNOTSUPP; + } + binding = kzalloc(sizeof(*binding), GFP_KERNEL); if (!binding) return -ENOMEM; @@ -672,6 +678,7 @@ int mlxsw_sp_acl_rule_add(struct mlxsw_sp *mlxsw_sp, { struct mlxsw_sp_acl_ruleset *ruleset = rule->ruleset; const struct mlxsw_sp_acl_profile_ops *ops = ruleset->ht_key.ops; + struct mlxsw_sp_acl_block *block = ruleset->ht_key.block; int err; err = ops->rule_add(mlxsw_sp, ruleset->priv, rule->priv, rule->rulei); @@ -689,14 +696,14 @@ int mlxsw_sp_acl_rule_add(struct mlxsw_sp *mlxsw_sp, * one, to be directly bound to device. The rest of the * rulesets are bound by "Goto action set". */ - err = mlxsw_sp_acl_ruleset_block_bind(mlxsw_sp, ruleset, - ruleset->ht_key.block); + err = mlxsw_sp_acl_ruleset_block_bind(mlxsw_sp, ruleset, block); if (err) goto err_ruleset_block_bind; } list_add_tail(&rule->list, &mlxsw_sp->acl->rules); - ruleset->ht_key.block->rule_count++; + block->rule_count++; + block->egress_blocker_rule_count += rule->rulei->egress_bind_blocker; return 0; err_ruleset_block_bind: @@ -712,7 +719,9 @@ void mlxsw_sp_acl_rule_del(struct mlxsw_sp *mlxsw_sp, { struct mlxsw_sp_acl_ruleset *ruleset = rule->ruleset; const struct mlxsw_sp_acl_profile_ops *ops = ruleset->ht_key.ops; + struct mlxsw_sp_acl_block *block = ruleset->ht_key.block; + block->egress_blocker_rule_count -= rule->rulei->egress_bind_blocker; ruleset->ht_key.block->rule_count--; list_del(&rule->list); if (!ruleset->ht_key.chain_index && diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c index 202e9a246019..0ad1a24abfc6 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c @@ -78,6 +78,16 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_fid *fid; u16 fid_index; + if (mlxsw_sp_acl_block_is_egress_bound(block)) { + NL_SET_ERR_MSG_MOD(extack, "Redirect action is not supported on egress"); + return -EOPNOTSUPP; + } + + /* Forbid block with this rulei to be bound + * to egress in future. + */ + rulei->egress_bind_blocker = 1; + fid = mlxsw_sp_acl_dummy_fid(mlxsw_sp); fid_index = mlxsw_sp_fid_index(fid); err = mlxsw_sp_acl_rulei_act_fid_set(mlxsw_sp, rulei, @@ -257,6 +267,12 @@ static int mlxsw_sp_flower_parse_tcp(struct mlxsw_sp *mlxsw_sp, flow_rule_match_tcp(rule, &match); + if (match.mask->flags & htons(0x0E00)) { + NL_SET_ERR_MSG_MOD(f->common.extack, "TCP flags match not supported on reserved bits"); + dev_err(mlxsw_sp->bus_info->dev, "TCP flags match not supported on reserved bits\n"); + return -EINVAL; + } + mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_TCP_FLAGS, ntohs(match.key->flags), ntohs(match.mask->flags)); @@ -390,6 +406,12 @@ static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp, NL_SET_ERR_MSG_MOD(f->common.extack, "vlan_id key is not supported on egress"); return -EOPNOTSUPP; } + + /* Forbid block with this rulei to be bound + * to egress in future. + */ + rulei->egress_bind_blocker = 1; + if (match.mask->vlan_id != 0) mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_VID, diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c index 9ead6ecb7586..61fe92719982 100644 --- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c +++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c @@ -1306,8 +1306,8 @@ myri10ge_vlan_rx(struct net_device *dev, void *addr, struct sk_buff *skb) skb->len -= VLAN_HLEN; skb->data_len -= VLAN_HLEN; frag = skb_shinfo(skb)->frags; - frag->page_offset += VLAN_HLEN; - skb_frag_size_set(frag, skb_frag_size(frag) - VLAN_HLEN); + skb_frag_off_add(frag, VLAN_HLEN); + skb_frag_size_sub(frag, VLAN_HLEN); } } @@ -1364,7 +1364,7 @@ myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum) } /* remove padding */ - rx_frags[0].page_offset += MXGEFW_PAD; + skb_frag_off_add(&rx_frags[0], MXGEFW_PAD); skb_frag_size_sub(&rx_frags[0], MXGEFW_PAD); len -= MXGEFW_PAD; @@ -3037,7 +3037,6 @@ static int myri10ge_set_mac_address(struct net_device *dev, void *addr) static int myri10ge_change_mtu(struct net_device *dev, int new_mtu) { struct myri10ge_priv *mgp = netdev_priv(dev); - int error = 0; netdev_info(dev, "changing mtu from %d to %d\n", dev->mtu, new_mtu); if (mgp->running) { @@ -3049,7 +3048,7 @@ static int myri10ge_change_mtu(struct net_device *dev, int new_mtu) } else dev->mtu = new_mtu; - return error; + return 0; } /* diff --git a/drivers/net/ethernet/nuvoton/w90p910_ether.c b/drivers/net/ethernet/nuvoton/w90p910_ether.c index 3d73970b3a2e..219b0b863c89 100644 --- a/drivers/net/ethernet/nuvoton/w90p910_ether.c +++ b/drivers/net/ethernet/nuvoton/w90p910_ether.c @@ -993,14 +993,12 @@ static int w90p910_ether_probe(struct platform_device *pdev) ether->txirq = platform_get_irq(pdev, 0); if (ether->txirq < 0) { - dev_err(&pdev->dev, "failed to get ether tx irq\n"); error = -ENXIO; goto failed_free_io; } ether->rxirq = platform_get_irq(pdev, 1); if (ether->rxirq < 0) { - dev_err(&pdev->dev, "failed to get ether rx irq\n"); error = -ENXIO; goto failed_free_io; } diff --git a/drivers/net/ethernet/qualcomm/emac/emac.c b/drivers/net/ethernet/qualcomm/emac/emac.c index 59c2349b59df..bfe10464c81f 100644 --- a/drivers/net/ethernet/qualcomm/emac/emac.c +++ b/drivers/net/ethernet/qualcomm/emac/emac.c @@ -556,11 +556,8 @@ static int emac_probe_resources(struct platform_device *pdev, /* Core 0 interrupt */ ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err(&pdev->dev, - "error: missing core0 irq resource (error=%i)\n", ret); + if (ret < 0) return ret; - } adpt->irq.irq = ret; /* base register address */ diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index e1e1c89fbe3d..109779e449cd 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -539,11 +539,11 @@ enum rtl_tx_desc_bit_1 { TD1_GTSENV4 = (1 << 26), /* Giant Send for IPv4 */ TD1_GTSENV6 = (1 << 25), /* Giant Send for IPv6 */ #define GTTCPHO_SHIFT 18 -#define GTTCPHO_MAX 0x7fU +#define GTTCPHO_MAX 0x7f /* Second doubleword. */ #define TCPHO_SHIFT 18 -#define TCPHO_MAX 0x3ffU +#define TCPHO_MAX 0x3ff #define TD1_MSS_SHIFT 18 /* MSS position (11 bits) */ TD1_IPv6_CS = (1 << 28), /* Calculate IPv6 checksum */ TD1_IPv4_CS = (1 << 29), /* Calculate IPv4 checksum */ @@ -569,6 +569,11 @@ enum rtl_rx_desc_bit { #define RsvdMask 0x3fffc000 +#define RTL_GSO_MAX_SIZE_V1 32000 +#define RTL_GSO_MAX_SEGS_V1 24 +#define RTL_GSO_MAX_SIZE_V2 64000 +#define RTL_GSO_MAX_SEGS_V2 64 + struct TxDesc { __le32 opts1; __le32 opts2; @@ -1414,18 +1419,22 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts) } switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_17: + case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06: options = RTL_R8(tp, Config1) & ~PMEnable; if (wolopts) options |= PMEnable; RTL_W8(tp, Config1, options); break; - default: + case RTL_GIGA_MAC_VER_34: + case RTL_GIGA_MAC_VER_37: + case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_51: options = RTL_R8(tp, Config2) & ~PME_SIGNAL; if (wolopts) options |= PME_SIGNAL; RTL_W8(tp, Config2, options); break; + default: + break; } rtl_lock_config_regs(tp); @@ -5499,44 +5508,6 @@ static bool rtl_test_hw_pad_bug(struct rtl8169_private *tp, struct sk_buff *skb) return skb->len < ETH_ZLEN && tp->mac_version == RTL_GIGA_MAC_VER_34; } -static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, - struct net_device *dev); -/* r8169_csum_workaround() - * The hw limites the value the transport offset. When the offset is out of the - * range, calculate the checksum by sw. - */ -static void r8169_csum_workaround(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - if (skb_is_gso(skb)) { - netdev_features_t features = tp->dev->features; - struct sk_buff *segs, *nskb; - - features &= ~(NETIF_F_SG | NETIF_F_IPV6_CSUM | NETIF_F_TSO6); - segs = skb_gso_segment(skb, features); - if (IS_ERR(segs) || !segs) - goto drop; - - do { - nskb = segs; - segs = segs->next; - nskb->next = NULL; - rtl8169_start_xmit(nskb, tp->dev); - } while (segs); - - dev_consume_skb_any(skb); - } else if (skb->ip_summed == CHECKSUM_PARTIAL) { - if (skb_checksum_help(skb) < 0) - goto drop; - - rtl8169_start_xmit(skb, tp->dev); - } else { -drop: - tp->dev->stats.tx_dropped++; - dev_kfree_skb_any(skb); - } -} - /* msdn_giant_send_check() * According to the document of microsoft, the TCP Pseudo Header excludes the * packet length for IPv6 TCP large packets. @@ -5586,13 +5557,6 @@ static bool rtl8169_tso_csum_v2(struct rtl8169_private *tp, u32 mss = skb_shinfo(skb)->gso_size; if (mss) { - if (transport_offset > GTTCPHO_MAX) { - netif_warn(tp, tx_err, tp->dev, - "Invalid transport offset 0x%x for TSO\n", - transport_offset); - return false; - } - switch (vlan_get_protocol(skb)) { case htons(ETH_P_IP): opts[0] |= TD1_GTSENV4; @@ -5615,16 +5579,6 @@ static bool rtl8169_tso_csum_v2(struct rtl8169_private *tp, } else if (skb->ip_summed == CHECKSUM_PARTIAL) { u8 ip_protocol; - if (unlikely(rtl_test_hw_pad_bug(tp, skb))) - return !(skb_checksum_help(skb) || eth_skb_pad(skb)); - - if (transport_offset > TCPHO_MAX) { - netif_warn(tp, tx_err, tp->dev, - "Invalid transport offset 0x%x\n", - transport_offset); - return false; - } - switch (vlan_get_protocol(skb)) { case htons(ETH_P_IP): opts[1] |= TD1_IPv4_CS; @@ -5687,6 +5641,8 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, struct device *d = tp_to_dev(tp); dma_addr_t mapping; u32 opts[2], len; + bool stop_queue; + bool door_bell; int frags; if (unlikely(!rtl_tx_slots_avail(tp, skb_shinfo(skb)->nr_frags))) { @@ -5701,10 +5657,8 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, opts[0] = DescOwn; if (rtl_chip_supports_csum_v2(tp)) { - if (!rtl8169_tso_csum_v2(tp, skb, opts)) { - r8169_csum_workaround(tp, skb); - return NETDEV_TX_OK; - } + if (!rtl8169_tso_csum_v2(tp, skb, opts)) + goto err_dma_0; } else { rtl8169_tso_csum_v1(skb, opts); } @@ -5732,13 +5686,13 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, txd->opts2 = cpu_to_le32(opts[1]); - netdev_sent_queue(dev, skb->len); - skb_tx_timestamp(skb); /* Force memory writes to complete before releasing descriptor */ dma_wmb(); + door_bell = __netdev_sent_queue(dev, skb->len, netdev_xmit_more()); + txd->opts1 = rtl8169_get_txd_opts1(opts[0], len, entry); /* Force all memory writes to complete before notifying device */ @@ -5746,14 +5700,19 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, tp->cur_tx += frags + 1; - RTL_W8(tp, TxPoll, NPQ); - - if (!rtl_tx_slots_avail(tp, MAX_SKB_FRAGS)) { + stop_queue = !rtl_tx_slots_avail(tp, MAX_SKB_FRAGS); + if (unlikely(stop_queue)) { /* Avoid wrongly optimistic queue wake-up: rtl_tx thread must * not miss a ring update when it notices a stopped queue. */ smp_wmb(); netif_stop_queue(dev); + } + + if (door_bell) + RTL_W8(tp, TxPoll, NPQ); + + if (unlikely(stop_queue)) { /* Sync with rtl_tx: * - publish queue status and cur_tx ring index (write barrier) * - refresh dirty_tx ring index (read barrier). @@ -5781,6 +5740,39 @@ err_stop_0: return NETDEV_TX_BUSY; } +static netdev_features_t rtl8169_features_check(struct sk_buff *skb, + struct net_device *dev, + netdev_features_t features) +{ + int transport_offset = skb_transport_offset(skb); + struct rtl8169_private *tp = netdev_priv(dev); + + if (skb_is_gso(skb)) { + if (transport_offset > GTTCPHO_MAX && + rtl_chip_supports_csum_v2(tp)) + features &= ~NETIF_F_ALL_TSO; + } else if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (skb->len < ETH_ZLEN) { + switch (tp->mac_version) { + case RTL_GIGA_MAC_VER_11: + case RTL_GIGA_MAC_VER_12: + case RTL_GIGA_MAC_VER_17: + case RTL_GIGA_MAC_VER_34: + features &= ~NETIF_F_CSUM_MASK; + break; + default: + break; + } + } + + if (transport_offset > TCPHO_MAX && + rtl_chip_supports_csum_v2(tp)) + features &= ~NETIF_F_CSUM_MASK; + } + + return vlan_features_check(skb, features); +} + static void rtl8169_pcierr_interrupt(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); @@ -6537,6 +6529,7 @@ static const struct net_device_ops rtl_netdev_ops = { .ndo_stop = rtl8169_close, .ndo_get_stats64 = rtl8169_get_stats64, .ndo_start_xmit = rtl8169_start_xmit, + .ndo_features_check = rtl8169_features_check, .ndo_tx_timeout = rtl8169_tx_timeout, .ndo_validate_addr = eth_validate_addr, .ndo_change_mtu = rtl8169_change_mtu, @@ -6893,11 +6886,9 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) netif_napi_add(dev, &tp->napi, rtl8169_poll, NAPI_POLL_WEIGHT); - /* don't enable SG, IP_CSUM and TSO by default - it might not work - * properly for all devices */ - dev->features |= NETIF_F_RXCSUM | - NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX; - + dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | + NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_TX | + NETIF_F_HW_VLAN_CTAG_RX; dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX; @@ -6915,8 +6906,22 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) /* Disallow toggling */ dev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_RX; - if (rtl_chip_supports_csum_v2(tp)) + if (rtl_chip_supports_csum_v2(tp)) { dev->hw_features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6; + dev->features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6; + dev->gso_max_size = RTL_GSO_MAX_SIZE_V2; + dev->gso_max_segs = RTL_GSO_MAX_SEGS_V2; + } else { + dev->gso_max_size = RTL_GSO_MAX_SIZE_V1; + dev->gso_max_segs = RTL_GSO_MAX_SEGS_V1; + } + + /* RTL8168e-vl has a HW issue with TSO */ + if (tp->mac_version == RTL_GIGA_MAC_VER_34) { + dev->vlan_features &= ~NETIF_F_ALL_TSO; + dev->hw_features &= ~NETIF_F_ALL_TSO; + dev->features &= ~NETIF_F_ALL_TSO; + } dev->hw_features |= NETIF_F_RXALL; dev->hw_features |= NETIF_F_RXFCS; diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c index 31ec56091a5d..65e81ec1b314 100644 --- a/drivers/net/ethernet/sfc/tx.c +++ b/drivers/net/ethernet/sfc/tx.c @@ -274,7 +274,7 @@ static void efx_skb_copy_bits_to_pio(struct efx_nic *efx, struct sk_buff *skb, vaddr = kmap_atomic(skb_frag_page(f)); - efx_memcpy_toio_aligned_cb(efx, piobuf, vaddr + f->page_offset, + efx_memcpy_toio_aligned_cb(efx, piobuf, vaddr + skb_frag_off(f), skb_frag_size(f), copy_buf); kunmap_atomic(vaddr); } diff --git a/drivers/net/ethernet/sis/sis900.c b/drivers/net/ethernet/sis/sis900.c index 6e07f5ebacfc..85eaccbbbac1 100644 --- a/drivers/net/ethernet/sis/sis900.c +++ b/drivers/net/ethernet/sis/sis900.c @@ -191,6 +191,8 @@ struct sis900_private { unsigned int tx_full; /* The Tx queue is full. */ u8 host_bridge_rev; u8 chipset_rev; + /* EEPROM data */ + int eeprom_size; }; MODULE_AUTHOR("Jim Huang <cmhuang@sis.com.tw>, Ollie Lho <ollie@sis.com.tw>"); @@ -475,6 +477,8 @@ static int sis900_probe(struct pci_dev *pci_dev, sis_priv->pci_dev = pci_dev; spin_lock_init(&sis_priv->lock); + sis_priv->eeprom_size = 24; + pci_set_drvdata(pci_dev, net_dev); ring_space = pci_alloc_consistent(pci_dev, TX_TOTAL_SIZE, &ring_dma); @@ -2122,6 +2126,68 @@ static void sis900_get_wol(struct net_device *net_dev, struct ethtool_wolinfo *w wol->supported = (WAKE_PHY | WAKE_MAGIC); } +static int sis900_get_eeprom_len(struct net_device *dev) +{ + struct sis900_private *sis_priv = netdev_priv(dev); + + return sis_priv->eeprom_size; +} + +static int sis900_read_eeprom(struct net_device *net_dev, u8 *buf) +{ + struct sis900_private *sis_priv = netdev_priv(net_dev); + void __iomem *ioaddr = sis_priv->ioaddr; + int wait, ret = -EAGAIN; + u16 signature; + u16 *ebuf = (u16 *)buf; + int i; + + if (sis_priv->chipset_rev == SIS96x_900_REV) { + sw32(mear, EEREQ); + for (wait = 0; wait < 2000; wait++) { + if (sr32(mear) & EEGNT) { + /* read 16 bits, and index by 16 bits */ + for (i = 0; i < sis_priv->eeprom_size / 2; i++) + ebuf[i] = (u16)read_eeprom(ioaddr, i); + ret = 0; + break; + } + udelay(1); + } + sw32(mear, EEDONE); + } else { + signature = (u16)read_eeprom(ioaddr, EEPROMSignature); + if (signature != 0xffff && signature != 0x0000) { + /* read 16 bits, and index by 16 bits */ + for (i = 0; i < sis_priv->eeprom_size / 2; i++) + ebuf[i] = (u16)read_eeprom(ioaddr, i); + ret = 0; + } + } + return ret; +} + +#define SIS900_EEPROM_MAGIC 0xBABE +static int sis900_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data) +{ + struct sis900_private *sis_priv = netdev_priv(dev); + u8 *eebuf; + int res; + + eebuf = kmalloc(sis_priv->eeprom_size, GFP_KERNEL); + if (!eebuf) + return -ENOMEM; + + eeprom->magic = SIS900_EEPROM_MAGIC; + spin_lock_irq(&sis_priv->lock); + res = sis900_read_eeprom(dev, eebuf); + spin_unlock_irq(&sis_priv->lock); + if (!res) + memcpy(data, eebuf + eeprom->offset, eeprom->len); + kfree(eebuf); + return res; +} + static const struct ethtool_ops sis900_ethtool_ops = { .get_drvinfo = sis900_get_drvinfo, .get_msglevel = sis900_get_msglevel, @@ -2132,6 +2198,8 @@ static const struct ethtool_ops sis900_ethtool_ops = { .set_wol = sis900_set_wol, .get_link_ksettings = sis900_get_link_ksettings, .set_link_ksettings = sis900_set_link_ksettings, + .get_eeprom_len = sis900_get_eeprom_len, + .get_eeprom = sis900_get_eeprom, }; /** diff --git a/drivers/net/ethernet/socionext/sni_ave.c b/drivers/net/ethernet/socionext/sni_ave.c index 51a7b48db4bc..87ab0b5da91e 100644 --- a/drivers/net/ethernet/socionext/sni_ave.c +++ b/drivers/net/ethernet/socionext/sni_ave.c @@ -1573,10 +1573,8 @@ static int ave_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(dev, "IRQ not found\n"); + if (irq < 0) return irq; - } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_ioremap_resource(dev, res); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c index 3a14cdd01f5f..f2197b066ed1 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c @@ -333,6 +333,9 @@ static void *tegra_eqos_probe(struct platform_device *pdev, usleep_range(2000, 4000); gpiod_set_value(eqos->reset, 0); + /* MDIO bus was already reset just above */ + data->mdio_bus_data->needs_reset = false; + eqos->rst = devm_reset_control_get(&pdev->dev, "eqos"); if (IS_ERR(eqos->rst)) { err = PTR_ERR(eqos->rst); @@ -428,13 +431,8 @@ static int dwc_eth_dwmac_probe(struct platform_device *pdev) * resource initialization is done in the glue logic. */ stmmac_res.irq = platform_get_irq(pdev, 0); - if (stmmac_res.irq < 0) { - if (stmmac_res.irq != -EPROBE_DEFER) - dev_err(&pdev->dev, - "IRQ configuration information not found\n"); - + if (stmmac_res.irq < 0) return stmmac_res.irq; - } stmmac_res.wol_irq = stmmac_res.irq; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index 4304c1abc5d1..40c42637ad75 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -348,7 +348,9 @@ int stmmac_mdio_register(struct net_device *ndev) max_addr = PHY_MAX_ADDR; } - new_bus->reset = &stmmac_mdio_reset; + if (mdio_bus_data->needs_reset) + new_bus->reset = &stmmac_mdio_reset; + snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s-%x", new_bus->name, priv->plat->bus_id); new_bus->priv = ndev; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c index 86f9c07a38cf..d5d08e11c353 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c @@ -63,6 +63,7 @@ static void common_default_data(struct plat_stmmacenet_data *plat) plat->has_gmac = 1; plat->force_sf_dma_mode = 1; + plat->mdio_bus_data->needs_reset = true; plat->mdio_bus_data->phy_mask = 0; /* Set default value for multicast hash bins */ diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index 73fc2524372e..0f3e6ce7f6ec 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -342,10 +342,16 @@ static int stmmac_dt_phy(struct plat_stmmacenet_data *plat, mdio = true; } - if (mdio) + if (mdio) { plat->mdio_bus_data = devm_kzalloc(dev, sizeof(struct stmmac_mdio_bus_data), GFP_KERNEL); + if (!plat->mdio_bus_data) + return -ENOMEM; + + plat->mdio_bus_data->needs_reset = true; + } + return 0; } @@ -515,13 +521,15 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) } /* clock setup */ - plat->stmmac_clk = devm_clk_get(&pdev->dev, - STMMAC_RESOURCE_NAME); - if (IS_ERR(plat->stmmac_clk)) { - dev_warn(&pdev->dev, "Cannot get CSR clock\n"); - plat->stmmac_clk = NULL; + if (!of_device_is_compatible(np, "snps,dwc-qos-ethernet-4.10")) { + plat->stmmac_clk = devm_clk_get(&pdev->dev, + STMMAC_RESOURCE_NAME); + if (IS_ERR(plat->stmmac_clk)) { + dev_warn(&pdev->dev, "Cannot get CSR clock\n"); + plat->stmmac_clk = NULL; + } + clk_prepare_enable(plat->stmmac_clk); } - clk_prepare_enable(plat->stmmac_clk); plat->pclk = devm_clk_get(&pdev->dev, "pclk"); if (IS_ERR(plat->pclk)) { @@ -602,13 +610,8 @@ int stmmac_get_platform_resources(struct platform_device *pdev, * probe if needed before we went too far with resource allocation. */ stmmac_res->irq = platform_get_irq_byname(pdev, "macirq"); - if (stmmac_res->irq < 0) { - if (stmmac_res->irq != -EPROBE_DEFER) { - dev_err(&pdev->dev, - "MAC IRQ configuration information not found\n"); - } + if (stmmac_res->irq < 0) return stmmac_res->irq; - } /* On some platforms e.g. SPEAr the wake up irq differs from the mac irq * The external wake up irq can be passed through the platform code diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c index 6fc05c106afc..c91876f8c536 100644 --- a/drivers/net/ethernet/sun/cassini.c +++ b/drivers/net/ethernet/sun/cassini.c @@ -2034,7 +2034,7 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc, __skb_frag_set_page(frag, page->buffer); __skb_frag_ref(frag); - frag->page_offset = off; + skb_frag_off_set(frag, off); skb_frag_size_set(frag, hlen - swivel); /* any more data? */ @@ -2058,7 +2058,7 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc, __skb_frag_set_page(frag, page->buffer); __skb_frag_ref(frag); - frag->page_offset = 0; + skb_frag_off_set(frag, 0); skb_frag_size_set(frag, hlen); RX_USED_ADD(page, hlen + cp->crc_size); } @@ -2816,7 +2816,7 @@ static inline int cas_xmit_tx_ringN(struct cas *cp, int ring, mapping = skb_frag_dma_map(&cp->pdev->dev, fragp, 0, len, DMA_TO_DEVICE); - tabort = cas_calc_tabort(cp, fragp->page_offset, len); + tabort = cas_calc_tabort(cp, skb_frag_off(fragp), len); if (unlikely(tabort)) { void *addr; @@ -2827,7 +2827,7 @@ static inline int cas_xmit_tx_ringN(struct cas *cp, int ring, addr = cas_page_map(skb_frag_page(fragp)); memcpy(tx_tiny_buf(cp, ring, entry), - addr + fragp->page_offset + len - tabort, + addr + skb_frag_off(fragp) + len - tabort, tabort); cas_page_unmap(addr); mapping = tx_tiny_map(cp, ring, entry, tentry); diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c index 0bc5863bffeb..f5fd1f3c07cc 100644 --- a/drivers/net/ethernet/sun/niu.c +++ b/drivers/net/ethernet/sun/niu.c @@ -6695,7 +6695,7 @@ static netdev_tx_t niu_start_xmit(struct sk_buff *skb, len = skb_frag_size(frag); mapping = np->ops->map_page(np->device, skb_frag_page(frag), - frag->page_offset, len, + skb_frag_off(frag), len, DMA_TO_DEVICE); rp->tx_buffs[prod].skb = NULL; diff --git a/drivers/net/ethernet/sun/sunvnet_common.c b/drivers/net/ethernet/sun/sunvnet_common.c index baa3088b475c..646e67236b65 100644 --- a/drivers/net/ethernet/sun/sunvnet_common.c +++ b/drivers/net/ethernet/sun/sunvnet_common.c @@ -1088,7 +1088,7 @@ static inline int vnet_skb_map(struct ldc_channel *lp, struct sk_buff *skb, vaddr = kmap_atomic(skb_frag_page(f)); blen = skb_frag_size(f); blen += 8 - (blen & 7); - err = ldc_map_single(lp, vaddr + f->page_offset, + err = ldc_map_single(lp, vaddr + skb_frag_off(f), blen, cookies + nc, ncookies - nc, map_perm); kunmap_atomic(vaddr); @@ -1124,7 +1124,7 @@ static inline struct sk_buff *vnet_skb_shape(struct sk_buff *skb, int ncookies) for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { skb_frag_t *f = &skb_shinfo(skb)->frags[i]; - docopy |= f->page_offset & 7; + docopy |= skb_frag_off(f) & 7; } if (((unsigned long)skb->data & 7) != VNET_PACKET_SKIP || skb_tailroom(skb) < pad || diff --git a/drivers/net/ethernet/ti/netcp_core.c b/drivers/net/ethernet/ti/netcp_core.c index 642843945031..1b2702f74455 100644 --- a/drivers/net/ethernet/ti/netcp_core.c +++ b/drivers/net/ethernet/ti/netcp_core.c @@ -1116,7 +1116,7 @@ netcp_tx_map_skb(struct sk_buff *skb, struct netcp_intf *netcp) for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; struct page *page = skb_frag_page(frag); - u32 page_offset = frag->page_offset; + u32 page_offset = skb_frag_off(frag); u32 buf_len = skb_frag_size(frag); dma_addr_t desc_dma; u32 desc_dma_32; diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 3544e1991579..86884c863013 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -435,7 +435,7 @@ static u32 init_page_array(void *hdr, u32 len, struct sk_buff *skb, skb_frag_t *frag = skb_shinfo(skb)->frags + i; slots_used += fill_pg_buf(skb_frag_page(frag), - frag->page_offset, + skb_frag_off(frag), skb_frag_size(frag), &pb[slots_used]); } return slots_used; @@ -449,7 +449,7 @@ static int count_skb_frag_slots(struct sk_buff *skb) for (i = 0; i < frags; i++) { skb_frag_t *frag = skb_shinfo(skb)->frags + i; unsigned long size = skb_frag_size(frag); - unsigned long offset = frag->page_offset; + unsigned long offset = skb_frag_off(frag); /* Skip unused frames from start of page */ offset &= ~PAGE_MASK; diff --git a/drivers/net/thunderbolt.c b/drivers/net/thunderbolt.c index fcf31335a8b6..dacb4f680fd4 100644 --- a/drivers/net/thunderbolt.c +++ b/drivers/net/thunderbolt.c @@ -1005,7 +1005,7 @@ static void *tbnet_kmap_frag(struct sk_buff *skb, unsigned int frag_num, const skb_frag_t *frag = &skb_shinfo(skb)->frags[frag_num]; *len = skb_frag_size(frag); - return kmap_atomic(skb_frag_page(frag)) + frag->page_offset; + return kmap_atomic(skb_frag_page(frag)) + skb_frag_off(frag); } static netdev_tx_t tbnet_start_xmit(struct sk_buff *skb, diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index ace7ffaf3913..58952a79b05f 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -1328,7 +1328,7 @@ static int build_dma_sg(const struct sk_buff *skb, struct urb *urb) total_len += skb_frag_size(f); sg_set_page(&urb->sg[i + s], skb_frag_page(f), skb_frag_size(f), - f->page_offset); + skb_frag_off(f)); } urb->transfer_buffer_length = total_len; diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 03feaeae89cd..216acf37ca7c 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -662,7 +662,7 @@ vmxnet3_append_frag(struct sk_buff *skb, struct Vmxnet3_RxCompDesc *rcd, BUG_ON(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS); __skb_frag_set_page(frag, rbi->page); - frag->page_offset = 0; + skb_frag_off_set(frag, 0); skb_frag_size_set(frag, rcd->len); skb->data_len += rcd->len; skb->truesize += PAGE_SIZE; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/soc.c b/drivers/net/wireless/mediatek/mt76/mt7603/soc.c index b920be1f5718..c6c1ce69bcbc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/soc.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/soc.c @@ -17,10 +17,8 @@ mt76_wmac_probe(struct platform_device *pdev) int ret; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "Failed to get device IRQ\n"); + if (irq < 0) return irq; - } mem_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(mem_base)) { diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index a96c5c2a2c5a..3ef07b63613e 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -136,12 +136,12 @@ static inline struct xenvif_queue *ubuf_to_queue(const struct ubuf_info *ubuf) static u16 frag_get_pending_idx(skb_frag_t *frag) { - return (u16)frag->page_offset; + return (u16)skb_frag_off(frag); } static void frag_set_pending_idx(skb_frag_t *frag, u16 pending_idx) { - frag->page_offset = pending_idx; + skb_frag_off_set(frag, pending_idx); } static inline pending_ring_idx_t pending_index(unsigned i) @@ -1068,7 +1068,7 @@ static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *s offset += len; __skb_frag_set_page(&frags[i], page); - frags[i].page_offset = 0; + skb_frag_off_set(&frags[i], 0); skb_frag_size_set(&frags[i], len); } diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 8d33970a2950..b930d5f95222 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -531,7 +531,7 @@ static int xennet_count_skb_slots(struct sk_buff *skb) for (i = 0; i < frags; i++) { skb_frag_t *frag = skb_shinfo(skb)->frags + i; unsigned long size = skb_frag_size(frag); - unsigned long offset = frag->page_offset; + unsigned long offset = skb_frag_off(frag); /* Skip unused frames from start of page */ offset &= ~PAGE_MASK; @@ -674,8 +674,8 @@ static netdev_tx_t xennet_start_xmit(struct sk_buff *skb, struct net_device *dev /* Requests for all the frags. */ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - tx = xennet_make_txreqs(queue, tx, skb, - skb_frag_page(frag), frag->page_offset, + tx = xennet_make_txreqs(queue, tx, skb, skb_frag_page(frag), + skb_frag_off(frag), skb_frag_size(frag)); } @@ -1040,7 +1040,7 @@ err: if (NETFRONT_SKB_CB(skb)->pull_to > RX_COPY_THRESHOLD) NETFRONT_SKB_CB(skb)->pull_to = RX_COPY_THRESHOLD; - skb_shinfo(skb)->frags[0].page_offset = rx->offset; + skb_frag_off_set(&skb_shinfo(skb)->frags[0], rx->offset); skb_frag_size_set(&skb_shinfo(skb)->frags[0], rx->status); skb->data_len = rx->status; skb->len += rx->status; diff --git a/drivers/nfc/nxp-nci/Kconfig b/drivers/nfc/nxp-nci/Kconfig index 12df2c8cc51d..e1f71deab6fc 100644 --- a/drivers/nfc/nxp-nci/Kconfig +++ b/drivers/nfc/nxp-nci/Kconfig @@ -2,10 +2,9 @@ config NFC_NXP_NCI tristate "NXP-NCI NFC driver" depends on NFC_NCI - default n ---help--- - Generic core driver for NXP NCI chips such as the NPC100 - or PN7150 families. + Generic core driver for NXP NCI chips such as the NPC100 (PN547), + NPC300 (PN548) or PN7150 families. This is a driver based on the NCI NFC kernel layers and will thus not work with NXP libnfc library. @@ -23,4 +22,4 @@ config NFC_NXP_NCI_I2C To compile this driver as a module, choose m here. The module will be called nxp_nci_i2c. - Say Y if unsure. + Say N if unsure. diff --git a/drivers/nfc/nxp-nci/core.c b/drivers/nfc/nxp-nci/core.c index 8dafc696719f..a0ce95a287c5 100644 --- a/drivers/nfc/nxp-nci/core.c +++ b/drivers/nfc/nxp-nci/core.c @@ -11,10 +11,8 @@ */ #include <linux/delay.h> -#include <linux/gpio.h> #include <linux/module.h> #include <linux/nfc.h> -#include <linux/platform_data/nxp-nci.h> #include <net/nfc/nci_core.h> diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c index 4aeb3861b409..307bd2afbe05 100644 --- a/drivers/nfc/nxp-nci/i2c.c +++ b/drivers/nfc/nxp-nci/i2c.c @@ -12,8 +12,6 @@ * Copyright (C) 2012 Intel Corporation. All rights reserved. */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include <linux/acpi.h> #include <linux/delay.h> #include <linux/i2c.h> @@ -21,9 +19,6 @@ #include <linux/module.h> #include <linux/nfc.h> #include <linux/gpio/consumer.h> -#include <linux/of_gpio.h> -#include <linux/of_irq.h> -#include <linux/platform_data/nxp-nci.h> #include <asm/unaligned.h> #include <net/nfc/nfc.h> @@ -38,8 +33,8 @@ struct nxp_nci_i2c_phy { struct i2c_client *i2c_dev; struct nci_dev *ndev; - unsigned int gpio_en; - unsigned int gpio_fw; + struct gpio_desc *gpiod_en; + struct gpio_desc *gpiod_fw; int hard_fault; /* * < 0 if hardware error occurred (e.g. i2c err) @@ -52,8 +47,8 @@ static int nxp_nci_i2c_set_mode(void *phy_id, { struct nxp_nci_i2c_phy *phy = (struct nxp_nci_i2c_phy *) phy_id; - gpio_set_value(phy->gpio_fw, (mode == NXP_NCI_MODE_FW) ? 1 : 0); - gpio_set_value(phy->gpio_en, (mode != NXP_NCI_MODE_COLD) ? 1 : 0); + gpiod_set_value(phy->gpiod_fw, (mode == NXP_NCI_MODE_FW) ? 1 : 0); + gpiod_set_value(phy->gpiod_en, (mode != NXP_NCI_MODE_COLD) ? 1 : 0); usleep_range(10000, 15000); if (mode == NXP_NCI_MODE_COLD) @@ -250,116 +245,55 @@ exit_irq_none: return IRQ_NONE; } -static int nxp_nci_i2c_parse_devtree(struct i2c_client *client) -{ - struct nxp_nci_i2c_phy *phy = i2c_get_clientdata(client); - struct device_node *pp; - int r; - - pp = client->dev.of_node; - if (!pp) - return -ENODEV; - - r = of_get_named_gpio(pp, "enable-gpios", 0); - if (r == -EPROBE_DEFER) - r = of_get_named_gpio(pp, "enable-gpios", 0); - if (r < 0) { - nfc_err(&client->dev, "Failed to get EN gpio, error: %d\n", r); - return r; - } - phy->gpio_en = r; - - r = of_get_named_gpio(pp, "firmware-gpios", 0); - if (r == -EPROBE_DEFER) - r = of_get_named_gpio(pp, "firmware-gpios", 0); - if (r < 0) { - nfc_err(&client->dev, "Failed to get FW gpio, error: %d\n", r); - return r; - } - phy->gpio_fw = r; - - return 0; -} - -static int nxp_nci_i2c_acpi_config(struct nxp_nci_i2c_phy *phy) -{ - struct i2c_client *client = phy->i2c_dev; - struct gpio_desc *gpiod_en, *gpiod_fw; +static const struct acpi_gpio_params firmware_gpios = { 1, 0, false }; +static const struct acpi_gpio_params enable_gpios = { 2, 0, false }; - gpiod_en = devm_gpiod_get_index(&client->dev, NULL, 2, GPIOD_OUT_LOW); - gpiod_fw = devm_gpiod_get_index(&client->dev, NULL, 1, GPIOD_OUT_LOW); - - if (IS_ERR(gpiod_en) || IS_ERR(gpiod_fw)) { - nfc_err(&client->dev, "No GPIOs\n"); - return -EINVAL; - } - - phy->gpio_en = desc_to_gpio(gpiod_en); - phy->gpio_fw = desc_to_gpio(gpiod_fw); - - return 0; -} +static const struct acpi_gpio_mapping acpi_nxp_nci_gpios[] = { + { "enable-gpios", &enable_gpios, 1 }, + { "firmware-gpios", &firmware_gpios, 1 }, + { } +}; static int nxp_nci_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct device *dev = &client->dev; struct nxp_nci_i2c_phy *phy; - struct nxp_nci_nfc_platform_data *pdata; int r; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { nfc_err(&client->dev, "Need I2C_FUNC_I2C\n"); - r = -ENODEV; - goto probe_exit; + return -ENODEV; } phy = devm_kzalloc(&client->dev, sizeof(struct nxp_nci_i2c_phy), GFP_KERNEL); - if (!phy) { - r = -ENOMEM; - goto probe_exit; - } + if (!phy) + return -ENOMEM; phy->i2c_dev = client; i2c_set_clientdata(client, phy); - pdata = client->dev.platform_data; - - if (!pdata && client->dev.of_node) { - r = nxp_nci_i2c_parse_devtree(client); - if (r < 0) { - nfc_err(&client->dev, "Failed to get DT data\n"); - goto probe_exit; - } - } else if (pdata) { - phy->gpio_en = pdata->gpio_en; - phy->gpio_fw = pdata->gpio_fw; - } else if (ACPI_HANDLE(&client->dev)) { - r = nxp_nci_i2c_acpi_config(phy); - if (r < 0) - goto probe_exit; - goto nci_probe; - } else { - nfc_err(&client->dev, "No platform data\n"); - r = -EINVAL; - goto probe_exit; - } + r = devm_acpi_dev_add_driver_gpios(dev, acpi_nxp_nci_gpios); + if (r) + return r; - r = devm_gpio_request_one(&phy->i2c_dev->dev, phy->gpio_en, - GPIOF_OUT_INIT_LOW, "nxp_nci_en"); - if (r < 0) - goto probe_exit; + phy->gpiod_en = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW); + if (IS_ERR(phy->gpiod_en)) { + nfc_err(dev, "Failed to get EN gpio\n"); + return PTR_ERR(phy->gpiod_en); + } - r = devm_gpio_request_one(&phy->i2c_dev->dev, phy->gpio_fw, - GPIOF_OUT_INIT_LOW, "nxp_nci_fw"); - if (r < 0) - goto probe_exit; + phy->gpiod_fw = devm_gpiod_get(dev, "firmware", GPIOD_OUT_LOW); + if (IS_ERR(phy->gpiod_fw)) { + nfc_err(dev, "Failed to get FW gpio\n"); + return PTR_ERR(phy->gpiod_fw); + } -nci_probe: r = nxp_nci_probe(phy, &client->dev, &i2c_phy_ops, NXP_NCI_I2C_MAX_PAYLOAD, &phy->ndev); if (r < 0) - goto probe_exit; + return r; r = request_threaded_irq(client->irq, NULL, nxp_nci_i2c_irq_thread_fn, @@ -368,7 +302,6 @@ nci_probe: if (r < 0) nfc_err(&client->dev, "Unable to register IRQ handler\n"); -probe_exit: return r; } @@ -390,14 +323,15 @@ MODULE_DEVICE_TABLE(i2c, nxp_nci_i2c_id_table); static const struct of_device_id of_nxp_nci_i2c_match[] = { { .compatible = "nxp,nxp-nci-i2c", }, - {}, + {} }; MODULE_DEVICE_TABLE(of, of_nxp_nci_i2c_match); #ifdef CONFIG_ACPI -static struct acpi_device_id acpi_id[] = { +static const struct acpi_device_id acpi_id[] = { + { "NXP1001" }, { "NXP7471" }, - { }, + { } }; MODULE_DEVICE_TABLE(acpi, acpi_id); #endif @@ -406,7 +340,7 @@ static struct i2c_driver nxp_nci_i2c_driver = { .driver = { .name = NXP_NCI_I2C_DRIVER_NAME, .acpi_match_table = ACPI_PTR(acpi_id), - .of_match_table = of_match_ptr(of_nxp_nci_i2c_match), + .of_match_table = of_nxp_nci_i2c_match, }, .probe = nxp_nci_i2c_probe, .id_table = nxp_nci_i2c_id_table, diff --git a/drivers/nfc/nxp-nci/nxp-nci.h b/drivers/nfc/nxp-nci/nxp-nci.h index 6fe7c45544bf..ae3fb2735a4e 100644 --- a/drivers/nfc/nxp-nci/nxp-nci.h +++ b/drivers/nfc/nxp-nci/nxp-nci.h @@ -14,7 +14,6 @@ #include <linux/completion.h> #include <linux/firmware.h> #include <linux/nfc.h> -#include <linux/platform_data/nxp-nci.h> #include <net/nfc/nci_core.h> diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index 7796799bf04a..9ff9429395eb 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -346,7 +346,7 @@ static int bnx2fc_xmit(struct fc_lport *lport, struct fc_frame *fp) return -ENOMEM; } frag = &skb_shinfo(skb)->frags[skb_shinfo(skb)->nr_frags - 1]; - cp = kmap_atomic(skb_frag_page(frag)) + frag->page_offset; + cp = kmap_atomic(skb_frag_page(frag)) + skb_frag_off(frag); } else { cp = skb_put(skb, tlen); } diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 00dd47bcbb1e..587d4bbb7d22 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -1522,8 +1522,7 @@ static int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp) return -ENOMEM; } frag = &skb_shinfo(skb)->frags[skb_shinfo(skb)->nr_frags - 1]; - cp = kmap_atomic(skb_frag_page(frag)) - + frag->page_offset; + cp = kmap_atomic(skb_frag_page(frag)) + skb_frag_off(frag); } else { cp = skb_put(skb, tlen); } diff --git a/drivers/scsi/fcoe/fcoe_transport.c b/drivers/scsi/fcoe/fcoe_transport.c index d0550384cc38..a20ddc301c89 100644 --- a/drivers/scsi/fcoe/fcoe_transport.c +++ b/drivers/scsi/fcoe/fcoe_transport.c @@ -318,7 +318,7 @@ u32 fcoe_fc_crc(struct fc_frame *fp) for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { frag = &skb_shinfo(skb)->frags[i]; - off = frag->page_offset; + off = skb_frag_off(frag); len = skb_frag_size(frag); while (len > 0) { clen = min(len, PAGE_SIZE - (off & ~PAGE_MASK)); diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c index a42babde036d..42542720962f 100644 --- a/drivers/scsi/qedf/qedf_main.c +++ b/drivers/scsi/qedf/qedf_main.c @@ -1077,7 +1077,7 @@ static int qedf_xmit(struct fc_lport *lport, struct fc_frame *fp) return -ENOMEM; } frag = &skb_shinfo(skb)->frags[skb_shinfo(skb)->nr_frags - 1]; - cp = kmap_atomic(skb_frag_page(frag)) + frag->page_offset; + cp = kmap_atomic(skb_frag_page(frag)) + skb_frag_off(frag); } else { cp = skb_put(skb, tlen); } diff --git a/drivers/staging/octeon/Kconfig b/drivers/staging/octeon/Kconfig index 1e3012b9991c..5b3994649d99 100644 --- a/drivers/staging/octeon/Kconfig +++ b/drivers/staging/octeon/Kconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 config OCTEON_ETHERNET tristate "Cavium Networks Octeon Ethernet support" - depends on CAVIUM_OCTEON_SOC && NETDEVICES + depends on CAVIUM_OCTEON_SOC && NETDEVICES || COMPILE_TEST select PHYLIB select MDIO_OCTEON help diff --git a/drivers/staging/octeon/ethernet-defines.h b/drivers/staging/octeon/ethernet-defines.h index 1e114422993a..ef9e767b0e2e 100644 --- a/drivers/staging/octeon/ethernet-defines.h +++ b/drivers/staging/octeon/ethernet-defines.h @@ -21,8 +21,6 @@ #ifndef __ETHERNET_DEFINES_H__ #define __ETHERNET_DEFINES_H__ -#include <asm/octeon/cvmx-config.h> - #ifdef CONFIG_NETFILTER #define REUSE_SKBUFFS_WITHOUT_FREE 0 #else diff --git a/drivers/staging/octeon/ethernet-mdio.c b/drivers/staging/octeon/ethernet-mdio.c index 2aee64fdaec5..ffac0c4b3f5c 100644 --- a/drivers/staging/octeon/ethernet-mdio.c +++ b/drivers/staging/octeon/ethernet-mdio.c @@ -13,15 +13,11 @@ #include <generated/utsrelease.h> #include <net/dst.h> -#include <asm/octeon/octeon.h> - -#include "ethernet-defines.h" #include "octeon-ethernet.h" +#include "ethernet-defines.h" #include "ethernet-mdio.h" #include "ethernet-util.h" -#include <asm/octeon/cvmx-gmxx-defs.h> - static void cvm_oct_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { diff --git a/drivers/staging/octeon/ethernet-mem.c b/drivers/staging/octeon/ethernet-mem.c index 0d26c4a93ec1..532594957ebc 100644 --- a/drivers/staging/octeon/ethernet-mem.c +++ b/drivers/staging/octeon/ethernet-mem.c @@ -9,13 +9,10 @@ #include <linux/netdevice.h> #include <linux/slab.h> -#include <asm/octeon/octeon.h> - +#include "octeon-ethernet.h" #include "ethernet-mem.h" #include "ethernet-defines.h" -#include <asm/octeon/cvmx-fpa.h> - /** * cvm_oct_fill_hw_skbuff - fill the supplied hardware pool with skbuffs * @pool: Pool to allocate an skbuff for diff --git a/drivers/staging/octeon/ethernet-rgmii.c b/drivers/staging/octeon/ethernet-rgmii.c index c15376d33891..d91fd5ce9e68 100644 --- a/drivers/staging/octeon/ethernet-rgmii.c +++ b/drivers/staging/octeon/ethernet-rgmii.c @@ -12,19 +12,11 @@ #include <linux/ratelimit.h> #include <net/dst.h> -#include <asm/octeon/octeon.h> - -#include "ethernet-defines.h" #include "octeon-ethernet.h" +#include "ethernet-defines.h" #include "ethernet-util.h" #include "ethernet-mdio.h" -#include <asm/octeon/cvmx-helper.h> - -#include <asm/octeon/cvmx-ipd-defs.h> -#include <asm/octeon/cvmx-npi-defs.h> -#include <asm/octeon/cvmx-gmxx-defs.h> - static DEFINE_SPINLOCK(global_register_lock); static void cvm_oct_set_hw_preamble(struct octeon_ethernet *priv, bool enable) diff --git a/drivers/staging/octeon/ethernet-rx.c b/drivers/staging/octeon/ethernet-rx.c index 5e271245273c..0e65955c746b 100644 --- a/drivers/staging/octeon/ethernet-rx.c +++ b/drivers/staging/octeon/ethernet-rx.c @@ -23,23 +23,12 @@ #include <net/xfrm.h> #endif /* CONFIG_XFRM */ -#include <asm/octeon/octeon.h> - +#include "octeon-ethernet.h" #include "ethernet-defines.h" #include "ethernet-mem.h" #include "ethernet-rx.h" -#include "octeon-ethernet.h" #include "ethernet-util.h" -#include <asm/octeon/cvmx-helper.h> -#include <asm/octeon/cvmx-wqe.h> -#include <asm/octeon/cvmx-fau.h> -#include <asm/octeon/cvmx-pow.h> -#include <asm/octeon/cvmx-pip.h> -#include <asm/octeon/cvmx-scratch.h> - -#include <asm/octeon/cvmx-gmxx-defs.h> - static atomic_t oct_rx_ready = ATOMIC_INIT(0); static struct oct_rx_group { diff --git a/drivers/staging/octeon/ethernet-rx.h b/drivers/staging/octeon/ethernet-rx.h index 096553d8fc99..ff6482fa20d6 100644 --- a/drivers/staging/octeon/ethernet-rx.h +++ b/drivers/staging/octeon/ethernet-rx.h @@ -5,8 +5,6 @@ * Copyright (c) 2003-2007 Cavium Networks */ -#include <asm/octeon/cvmx-fau.h> - void cvm_oct_poll_controller(struct net_device *dev); void cvm_oct_rx_initialize(void); void cvm_oct_rx_shutdown(void); diff --git a/drivers/staging/octeon/ethernet-sgmii.c b/drivers/staging/octeon/ethernet-sgmii.c index a4a8f094e2b4..d7fbd9159302 100644 --- a/drivers/staging/octeon/ethernet-sgmii.c +++ b/drivers/staging/octeon/ethernet-sgmii.c @@ -11,17 +11,11 @@ #include <linux/ratelimit.h> #include <net/dst.h> -#include <asm/octeon/octeon.h> - -#include "ethernet-defines.h" #include "octeon-ethernet.h" +#include "ethernet-defines.h" #include "ethernet-util.h" #include "ethernet-mdio.h" -#include <asm/octeon/cvmx-helper.h> - -#include <asm/octeon/cvmx-gmxx-defs.h> - int cvm_oct_sgmii_open(struct net_device *dev) { return cvm_oct_common_open(dev, cvm_oct_link_poll); diff --git a/drivers/staging/octeon/ethernet-spi.c b/drivers/staging/octeon/ethernet-spi.c index 01efdf2a2c20..c582403e6a1f 100644 --- a/drivers/staging/octeon/ethernet-spi.c +++ b/drivers/staging/octeon/ethernet-spi.c @@ -10,18 +10,10 @@ #include <linux/interrupt.h> #include <net/dst.h> -#include <asm/octeon/octeon.h> - -#include "ethernet-defines.h" #include "octeon-ethernet.h" +#include "ethernet-defines.h" #include "ethernet-util.h" -#include <asm/octeon/cvmx-spi.h> - -#include <asm/octeon/cvmx-npi-defs.h> -#include <asm/octeon/cvmx-spxx-defs.h> -#include <asm/octeon/cvmx-stxx-defs.h> - static int number_spi_ports; static int need_retrain[2] = { 0, 0 }; diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c index 46a6fcf1414d..c64728fc21f2 100644 --- a/drivers/staging/octeon/ethernet-tx.c +++ b/drivers/staging/octeon/ethernet-tx.c @@ -22,21 +22,11 @@ #include <linux/atomic.h> #include <net/sch_generic.h> -#include <asm/octeon/octeon.h> - -#include "ethernet-defines.h" #include "octeon-ethernet.h" +#include "ethernet-defines.h" #include "ethernet-tx.h" #include "ethernet-util.h" -#include <asm/octeon/cvmx-wqe.h> -#include <asm/octeon/cvmx-fau.h> -#include <asm/octeon/cvmx-pip.h> -#include <asm/octeon/cvmx-pko.h> -#include <asm/octeon/cvmx-helper.h> - -#include <asm/octeon/cvmx-gmxx-defs.h> - #define CVM_OCT_SKB_CB(skb) ((u64 *)((skb)->cb)) /* @@ -284,7 +274,7 @@ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev) hw_buffer.s.addr = XKPHYS_TO_PHYS((u64)skb_frag_address(fs)); - hw_buffer.s.size = skb_drag_size(fs); + hw_buffer.s.size = skb_frag_size(fs); CVM_OCT_SKB_CB(skb)[i + 1] = hw_buffer.u64; } hw_buffer.s.addr = XKPHYS_TO_PHYS((u64)CVM_OCT_SKB_CB(skb)); diff --git a/drivers/staging/octeon/ethernet-util.h b/drivers/staging/octeon/ethernet-util.h index 31a82873e15c..2af83a12ca78 100644 --- a/drivers/staging/octeon/ethernet-util.h +++ b/drivers/staging/octeon/ethernet-util.h @@ -5,10 +5,6 @@ * Copyright (c) 2003-2007 Cavium Networks */ -#include <asm/octeon/cvmx-pip.h> -#include <asm/octeon/cvmx-helper.h> -#include <asm/octeon/cvmx-helper-util.h> - /** * cvm_oct_get_buffer_ptr - convert packet data address to pointer * @packet_ptr: Packet data hardware address diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index 8847a11c212f..8889494adf1f 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -19,24 +19,14 @@ #include <net/dst.h> -#include <asm/octeon/octeon.h> - -#include "ethernet-defines.h" #include "octeon-ethernet.h" +#include "ethernet-defines.h" #include "ethernet-mem.h" #include "ethernet-rx.h" #include "ethernet-tx.h" #include "ethernet-mdio.h" #include "ethernet-util.h" -#include <asm/octeon/cvmx-pip.h> -#include <asm/octeon/cvmx-pko.h> -#include <asm/octeon/cvmx-fau.h> -#include <asm/octeon/cvmx-ipd.h> -#include <asm/octeon/cvmx-helper.h> -#include <asm/octeon/cvmx-asxx-defs.h> -#include <asm/octeon/cvmx-gmxx-defs.h> - #define OCTEON_MAX_MTU 65392 static int num_packet_buffers = 1024; diff --git a/drivers/staging/octeon/octeon-ethernet.h b/drivers/staging/octeon/octeon-ethernet.h index be570d33685a..a8a864b40913 100644 --- a/drivers/staging/octeon/octeon-ethernet.h +++ b/drivers/staging/octeon/octeon-ethernet.h @@ -13,7 +13,34 @@ #include <linux/of.h> #include <linux/phy.h> -#include <asm/octeon/cvmx-helper-board.h> + +#ifdef CONFIG_MIPS + +#include <asm/octeon/octeon.h> + +#include <asm/octeon/cvmx-asxx-defs.h> +#include <asm/octeon/cvmx-config.h> +#include <asm/octeon/cvmx-fau.h> +#include <asm/octeon/cvmx-gmxx-defs.h> +#include <asm/octeon/cvmx-helper.h> +#include <asm/octeon/cvmx-helper-util.h> +#include <asm/octeon/cvmx-ipd.h> +#include <asm/octeon/cvmx-ipd-defs.h> +#include <asm/octeon/cvmx-npi-defs.h> +#include <asm/octeon/cvmx-pip.h> +#include <asm/octeon/cvmx-pko.h> +#include <asm/octeon/cvmx-pow.h> +#include <asm/octeon/cvmx-scratch.h> +#include <asm/octeon/cvmx-spi.h> +#include <asm/octeon/cvmx-spxx-defs.h> +#include <asm/octeon/cvmx-stxx-defs.h> +#include <asm/octeon/cvmx-wqe.h> + +#else + +#include "octeon-stubs.h" + +#endif /** * This is the definition of the Ethernet driver's private diff --git a/drivers/staging/octeon/octeon-stubs.h b/drivers/staging/octeon/octeon-stubs.h new file mode 100644 index 000000000000..a4ac3bfb62a8 --- /dev/null +++ b/drivers/staging/octeon/octeon-stubs.h @@ -0,0 +1,1429 @@ +#define CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE 512 +#define XKPHYS_TO_PHYS(p) (p) + +#define OCTEON_IRQ_WORKQ0 0 +#define OCTEON_IRQ_RML 0 +#define OCTEON_IRQ_TIMER1 0 +#define OCTEON_IS_MODEL(x) 0 +#define octeon_has_feature(x) 0 +#define octeon_get_clock_rate() 0 + +#define CVMX_SYNCIOBDMA do { } while(0) + +#define CVMX_HELPER_INPUT_TAG_TYPE 0 +#define CVMX_HELPER_FIRST_MBUFF_SKIP 7 +#define CVMX_FAU_REG_END (2048) +#define CVMX_FPA_OUTPUT_BUFFER_POOL (2) +#define CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE 16 +#define CVMX_FPA_PACKET_POOL (0) +#define CVMX_FPA_PACKET_POOL_SIZE 16 +#define CVMX_FPA_WQE_POOL (1) +#define CVMX_FPA_WQE_POOL_SIZE 16 +#define CVMX_GMXX_RXX_ADR_CAM_EN(a, b) ((a)+(b)) +#define CVMX_GMXX_RXX_ADR_CTL(a, b) ((a)+(b)) +#define CVMX_GMXX_PRTX_CFG(a, b) ((a)+(b)) +#define CVMX_GMXX_RXX_FRM_MAX(a, b) ((a)+(b)) +#define CVMX_GMXX_RXX_JABBER(a, b) ((a)+(b)) +#define CVMX_IPD_CTL_STATUS 0 +#define CVMX_PIP_FRM_LEN_CHKX(a) (a) +#define CVMX_PIP_NUM_INPUT_PORTS 1 +#define CVMX_SCR_SCRATCH 0 +#define CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 2 +#define CVMX_PKO_QUEUES_PER_PORT_INTERFACE1 2 +#define CVMX_IPD_SUB_PORT_FCS 0 +#define CVMX_SSO_WQ_IQ_DIS 0 +#define CVMX_SSO_WQ_INT 0 +#define CVMX_POW_WQ_INT 0 +#define CVMX_SSO_WQ_INT_PC 0 +#define CVMX_NPI_RSL_INT_BLOCKS 0 +#define CVMX_POW_WQ_INT_PC 0 + +typedef union { + uint64_t u64; + struct { + uint64_t bufs:8; + uint64_t ip_offset:8; + uint64_t vlan_valid:1; + uint64_t vlan_stacked:1; + uint64_t unassigned:1; + uint64_t vlan_cfi:1; + uint64_t vlan_id:12; + uint64_t pr:4; + uint64_t unassigned2:8; + uint64_t dec_ipcomp:1; + uint64_t tcp_or_udp:1; + uint64_t dec_ipsec:1; + uint64_t is_v6:1; + uint64_t software:1; + uint64_t L4_error:1; + uint64_t is_frag:1; + uint64_t IP_exc:1; + uint64_t is_bcast:1; + uint64_t is_mcast:1; + uint64_t not_IP:1; + uint64_t rcv_error:1; + uint64_t err_code:8; + } s; + struct { + uint64_t bufs:8; + uint64_t ip_offset:8; + uint64_t vlan_valid:1; + uint64_t vlan_stacked:1; + uint64_t unassigned:1; + uint64_t vlan_cfi:1; + uint64_t vlan_id:12; + uint64_t port:12; + uint64_t dec_ipcomp:1; + uint64_t tcp_or_udp:1; + uint64_t dec_ipsec:1; + uint64_t is_v6:1; + uint64_t software:1; + uint64_t L4_error:1; + uint64_t is_frag:1; + uint64_t IP_exc:1; + uint64_t is_bcast:1; + uint64_t is_mcast:1; + uint64_t not_IP:1; + uint64_t rcv_error:1; + uint64_t err_code:8; + } s_cn68xx; + + struct { + uint64_t unused1:16; + uint64_t vlan:16; + uint64_t unused2:32; + } svlan; + struct { + uint64_t bufs:8; + uint64_t unused:8; + uint64_t vlan_valid:1; + uint64_t vlan_stacked:1; + uint64_t unassigned:1; + uint64_t vlan_cfi:1; + uint64_t vlan_id:12; + uint64_t pr:4; + uint64_t unassigned2:12; + uint64_t software:1; + uint64_t unassigned3:1; + uint64_t is_rarp:1; + uint64_t is_arp:1; + uint64_t is_bcast:1; + uint64_t is_mcast:1; + uint64_t not_IP:1; + uint64_t rcv_error:1; + uint64_t err_code:8; + } snoip; + +} cvmx_pip_wqe_word2; + +union cvmx_pip_wqe_word0 { + struct { + uint64_t next_ptr:40; + uint8_t unused; + uint16_t hw_chksum; + } cn38xx; + struct { + uint64_t pknd:6; /* 0..5 */ + uint64_t unused2:2; /* 6..7 */ + uint64_t bpid:6; /* 8..13 */ + uint64_t unused1:18; /* 14..31 */ + uint64_t l2ptr:8; /* 32..39 */ + uint64_t l3ptr:8; /* 40..47 */ + uint64_t unused0:8; /* 48..55 */ + uint64_t l4ptr:8; /* 56..63 */ + } cn68xx; +}; + +union cvmx_wqe_word0 { + uint64_t u64; + union cvmx_pip_wqe_word0 pip; +}; + +union cvmx_wqe_word1 { + uint64_t u64; + struct { + uint64_t tag:32; + uint64_t tag_type:2; + uint64_t varies:14; + uint64_t len:16; + }; + struct { + uint64_t tag:32; + uint64_t tag_type:2; + uint64_t zero_2:3; + uint64_t grp:6; + uint64_t zero_1:1; + uint64_t qos:3; + uint64_t zero_0:1; + uint64_t len:16; + } cn68xx; + struct { + uint64_t tag:32; + uint64_t tag_type:2; + uint64_t zero_2:1; + uint64_t grp:4; + uint64_t qos:3; + uint64_t ipprt:6; + uint64_t len:16; + } cn38xx; +}; + +union cvmx_buf_ptr { + void *ptr; + uint64_t u64; + struct { + uint64_t i:1; + uint64_t back:4; + uint64_t pool:3; + uint64_t size:16; + uint64_t addr:40; + } s; +}; + +typedef struct { + union cvmx_wqe_word0 word0; + union cvmx_wqe_word1 word1; + cvmx_pip_wqe_word2 word2; + union cvmx_buf_ptr packet_ptr; + uint8_t packet_data[96]; +} cvmx_wqe_t; + +typedef union { + uint64_t u64; + struct { + uint64_t reserved_20_63:44; + uint64_t link_up:1; /**< Is the physical link up? */ + uint64_t full_duplex:1; /**< 1 if the link is full duplex */ + uint64_t speed:18; /**< Speed of the link in Mbps */ + } s; +} cvmx_helper_link_info_t; + +typedef enum { + CVMX_FAU_REG_32_START = 0, +} cvmx_fau_reg_32_t; + +typedef enum { + CVMX_FAU_OP_SIZE_8 = 0, + CVMX_FAU_OP_SIZE_16 = 1, + CVMX_FAU_OP_SIZE_32 = 2, + CVMX_FAU_OP_SIZE_64 = 3 +} cvmx_fau_op_size_t; + +typedef enum { + CVMX_SPI_MODE_UNKNOWN = 0, + CVMX_SPI_MODE_TX_HALFPLEX = 1, + CVMX_SPI_MODE_RX_HALFPLEX = 2, + CVMX_SPI_MODE_DUPLEX = 3 +} cvmx_spi_mode_t; + +typedef enum { + CVMX_HELPER_INTERFACE_MODE_DISABLED, + CVMX_HELPER_INTERFACE_MODE_RGMII, + CVMX_HELPER_INTERFACE_MODE_GMII, + CVMX_HELPER_INTERFACE_MODE_SPI, + CVMX_HELPER_INTERFACE_MODE_PCIE, + CVMX_HELPER_INTERFACE_MODE_XAUI, + CVMX_HELPER_INTERFACE_MODE_SGMII, + CVMX_HELPER_INTERFACE_MODE_PICMG, + CVMX_HELPER_INTERFACE_MODE_NPI, + CVMX_HELPER_INTERFACE_MODE_LOOP, +} cvmx_helper_interface_mode_t; + +typedef enum { + CVMX_POW_WAIT = 1, + CVMX_POW_NO_WAIT = 0, +} cvmx_pow_wait_t; + +typedef enum { + CVMX_PKO_LOCK_NONE = 0, + CVMX_PKO_LOCK_ATOMIC_TAG = 1, + CVMX_PKO_LOCK_CMD_QUEUE = 2, +} cvmx_pko_lock_t; + +typedef enum { + CVMX_PKO_SUCCESS, + CVMX_PKO_INVALID_PORT, + CVMX_PKO_INVALID_QUEUE, + CVMX_PKO_INVALID_PRIORITY, + CVMX_PKO_NO_MEMORY, + CVMX_PKO_PORT_ALREADY_SETUP, + CVMX_PKO_CMD_QUEUE_INIT_ERROR +} cvmx_pko_status_t; + +enum cvmx_pow_tag_type { + CVMX_POW_TAG_TYPE_ORDERED = 0L, + CVMX_POW_TAG_TYPE_ATOMIC = 1L, + CVMX_POW_TAG_TYPE_NULL = 2L, + CVMX_POW_TAG_TYPE_NULL_NULL = 3L +}; + +union cvmx_ipd_ctl_status { + uint64_t u64; + struct cvmx_ipd_ctl_status_s { + uint64_t reserved_18_63:46; + uint64_t use_sop:1; + uint64_t rst_done:1; + uint64_t clken:1; + uint64_t no_wptr:1; + uint64_t pq_apkt:1; + uint64_t pq_nabuf:1; + uint64_t ipd_full:1; + uint64_t pkt_off:1; + uint64_t len_m8:1; + uint64_t reset:1; + uint64_t addpkt:1; + uint64_t naddbuf:1; + uint64_t pkt_lend:1; + uint64_t wqe_lend:1; + uint64_t pbp_en:1; + uint64_t opc_mode:2; + uint64_t ipd_en:1; + } s; + struct cvmx_ipd_ctl_status_cn30xx { + uint64_t reserved_10_63:54; + uint64_t len_m8:1; + uint64_t reset:1; + uint64_t addpkt:1; + uint64_t naddbuf:1; + uint64_t pkt_lend:1; + uint64_t wqe_lend:1; + uint64_t pbp_en:1; + uint64_t opc_mode:2; + uint64_t ipd_en:1; + } cn30xx; + struct cvmx_ipd_ctl_status_cn38xxp2 { + uint64_t reserved_9_63:55; + uint64_t reset:1; + uint64_t addpkt:1; + uint64_t naddbuf:1; + uint64_t pkt_lend:1; + uint64_t wqe_lend:1; + uint64_t pbp_en:1; + uint64_t opc_mode:2; + uint64_t ipd_en:1; + } cn38xxp2; + struct cvmx_ipd_ctl_status_cn50xx { + uint64_t reserved_15_63:49; + uint64_t no_wptr:1; + uint64_t pq_apkt:1; + uint64_t pq_nabuf:1; + uint64_t ipd_full:1; + uint64_t pkt_off:1; + uint64_t len_m8:1; + uint64_t reset:1; + uint64_t addpkt:1; + uint64_t naddbuf:1; + uint64_t pkt_lend:1; + uint64_t wqe_lend:1; + uint64_t pbp_en:1; + uint64_t opc_mode:2; + uint64_t ipd_en:1; + } cn50xx; + struct cvmx_ipd_ctl_status_cn58xx { + uint64_t reserved_12_63:52; + uint64_t ipd_full:1; + uint64_t pkt_off:1; + uint64_t len_m8:1; + uint64_t reset:1; + uint64_t addpkt:1; + uint64_t naddbuf:1; + uint64_t pkt_lend:1; + uint64_t wqe_lend:1; + uint64_t pbp_en:1; + uint64_t opc_mode:2; + uint64_t ipd_en:1; + } cn58xx; + struct cvmx_ipd_ctl_status_cn63xxp1 { + uint64_t reserved_16_63:48; + uint64_t clken:1; + uint64_t no_wptr:1; + uint64_t pq_apkt:1; + uint64_t pq_nabuf:1; + uint64_t ipd_full:1; + uint64_t pkt_off:1; + uint64_t len_m8:1; + uint64_t reset:1; + uint64_t addpkt:1; + uint64_t naddbuf:1; + uint64_t pkt_lend:1; + uint64_t wqe_lend:1; + uint64_t pbp_en:1; + uint64_t opc_mode:2; + uint64_t ipd_en:1; + } cn63xxp1; +}; + +union cvmx_ipd_sub_port_fcs { + uint64_t u64; + struct cvmx_ipd_sub_port_fcs_s { + uint64_t port_bit:32; + uint64_t reserved_32_35:4; + uint64_t port_bit2:4; + uint64_t reserved_40_63:24; + } s; + struct cvmx_ipd_sub_port_fcs_cn30xx { + uint64_t port_bit:3; + uint64_t reserved_3_63:61; + } cn30xx; + struct cvmx_ipd_sub_port_fcs_cn38xx { + uint64_t port_bit:32; + uint64_t reserved_32_63:32; + } cn38xx; +}; + +union cvmx_ipd_sub_port_qos_cnt { + uint64_t u64; + struct cvmx_ipd_sub_port_qos_cnt_s { + uint64_t cnt:32; + uint64_t port_qos:9; + uint64_t reserved_41_63:23; + } s; +}; +typedef struct { + uint32_t dropped_octets; + uint32_t dropped_packets; + uint32_t pci_raw_packets; + uint32_t octets; + uint32_t packets; + uint32_t multicast_packets; + uint32_t broadcast_packets; + uint32_t len_64_packets; + uint32_t len_65_127_packets; + uint32_t len_128_255_packets; + uint32_t len_256_511_packets; + uint32_t len_512_1023_packets; + uint32_t len_1024_1518_packets; + uint32_t len_1519_max_packets; + uint32_t fcs_align_err_packets; + uint32_t runt_packets; + uint32_t runt_crc_packets; + uint32_t oversize_packets; + uint32_t oversize_crc_packets; + uint32_t inb_packets; + uint64_t inb_octets; + uint16_t inb_errors; +} cvmx_pip_port_status_t; + +typedef struct { + uint32_t packets; + uint64_t octets; + uint64_t doorbell; +} cvmx_pko_port_status_t; + +union cvmx_pip_frm_len_chkx { + uint64_t u64; + struct cvmx_pip_frm_len_chkx_s { + uint64_t reserved_32_63:32; + uint64_t maxlen:16; + uint64_t minlen:16; + } s; +}; + +union cvmx_gmxx_rxx_frm_ctl { + uint64_t u64; + struct cvmx_gmxx_rxx_frm_ctl_s { + uint64_t pre_chk:1; + uint64_t pre_strp:1; + uint64_t ctl_drp:1; + uint64_t ctl_bck:1; + uint64_t ctl_mcst:1; + uint64_t ctl_smac:1; + uint64_t pre_free:1; + uint64_t vlan_len:1; + uint64_t pad_len:1; + uint64_t pre_align:1; + uint64_t null_dis:1; + uint64_t reserved_11_11:1; + uint64_t ptp_mode:1; + uint64_t reserved_13_63:51; + } s; + struct cvmx_gmxx_rxx_frm_ctl_cn30xx { + uint64_t pre_chk:1; + uint64_t pre_strp:1; + uint64_t ctl_drp:1; + uint64_t ctl_bck:1; + uint64_t ctl_mcst:1; + uint64_t ctl_smac:1; + uint64_t pre_free:1; + uint64_t vlan_len:1; + uint64_t pad_len:1; + uint64_t reserved_9_63:55; + } cn30xx; + struct cvmx_gmxx_rxx_frm_ctl_cn31xx { + uint64_t pre_chk:1; + uint64_t pre_strp:1; + uint64_t ctl_drp:1; + uint64_t ctl_bck:1; + uint64_t ctl_mcst:1; + uint64_t ctl_smac:1; + uint64_t pre_free:1; + uint64_t vlan_len:1; + uint64_t reserved_8_63:56; + } cn31xx; + struct cvmx_gmxx_rxx_frm_ctl_cn50xx { + uint64_t pre_chk:1; + uint64_t pre_strp:1; + uint64_t ctl_drp:1; + uint64_t ctl_bck:1; + uint64_t ctl_mcst:1; + uint64_t ctl_smac:1; + uint64_t pre_free:1; + uint64_t reserved_7_8:2; + uint64_t pre_align:1; + uint64_t null_dis:1; + uint64_t reserved_11_63:53; + } cn50xx; + struct cvmx_gmxx_rxx_frm_ctl_cn56xxp1 { + uint64_t pre_chk:1; + uint64_t pre_strp:1; + uint64_t ctl_drp:1; + uint64_t ctl_bck:1; + uint64_t ctl_mcst:1; + uint64_t ctl_smac:1; + uint64_t pre_free:1; + uint64_t reserved_7_8:2; + uint64_t pre_align:1; + uint64_t reserved_10_63:54; + } cn56xxp1; + struct cvmx_gmxx_rxx_frm_ctl_cn58xx { + uint64_t pre_chk:1; + uint64_t pre_strp:1; + uint64_t ctl_drp:1; + uint64_t ctl_bck:1; + uint64_t ctl_mcst:1; + uint64_t ctl_smac:1; + uint64_t pre_free:1; + uint64_t vlan_len:1; + uint64_t pad_len:1; + uint64_t pre_align:1; + uint64_t null_dis:1; + uint64_t reserved_11_63:53; + } cn58xx; + struct cvmx_gmxx_rxx_frm_ctl_cn61xx { + uint64_t pre_chk:1; + uint64_t pre_strp:1; + uint64_t ctl_drp:1; + uint64_t ctl_bck:1; + uint64_t ctl_mcst:1; + uint64_t ctl_smac:1; + uint64_t pre_free:1; + uint64_t reserved_7_8:2; + uint64_t pre_align:1; + uint64_t null_dis:1; + uint64_t reserved_11_11:1; + uint64_t ptp_mode:1; + uint64_t reserved_13_63:51; + } cn61xx; +}; + +union cvmx_gmxx_rxx_int_reg { + uint64_t u64; + struct cvmx_gmxx_rxx_int_reg_s { + uint64_t minerr:1; + uint64_t carext:1; + uint64_t maxerr:1; + uint64_t jabber:1; + uint64_t fcserr:1; + uint64_t alnerr:1; + uint64_t lenerr:1; + uint64_t rcverr:1; + uint64_t skperr:1; + uint64_t niberr:1; + uint64_t ovrerr:1; + uint64_t pcterr:1; + uint64_t rsverr:1; + uint64_t falerr:1; + uint64_t coldet:1; + uint64_t ifgerr:1; + uint64_t phy_link:1; + uint64_t phy_spd:1; + uint64_t phy_dupx:1; + uint64_t pause_drp:1; + uint64_t loc_fault:1; + uint64_t rem_fault:1; + uint64_t bad_seq:1; + uint64_t bad_term:1; + uint64_t unsop:1; + uint64_t uneop:1; + uint64_t undat:1; + uint64_t hg2fld:1; + uint64_t hg2cc:1; + uint64_t reserved_29_63:35; + } s; + struct cvmx_gmxx_rxx_int_reg_cn30xx { + uint64_t minerr:1; + uint64_t carext:1; + uint64_t maxerr:1; + uint64_t jabber:1; + uint64_t fcserr:1; + uint64_t alnerr:1; + uint64_t lenerr:1; + uint64_t rcverr:1; + uint64_t skperr:1; + uint64_t niberr:1; + uint64_t ovrerr:1; + uint64_t pcterr:1; + uint64_t rsverr:1; + uint64_t falerr:1; + uint64_t coldet:1; + uint64_t ifgerr:1; + uint64_t phy_link:1; + uint64_t phy_spd:1; + uint64_t phy_dupx:1; + uint64_t reserved_19_63:45; + } cn30xx; + struct cvmx_gmxx_rxx_int_reg_cn50xx { + uint64_t reserved_0_0:1; + uint64_t carext:1; + uint64_t reserved_2_2:1; + uint64_t jabber:1; + uint64_t fcserr:1; + uint64_t alnerr:1; + uint64_t reserved_6_6:1; + uint64_t rcverr:1; + uint64_t skperr:1; + uint64_t niberr:1; + uint64_t ovrerr:1; + uint64_t pcterr:1; + uint64_t rsverr:1; + uint64_t falerr:1; + uint64_t coldet:1; + uint64_t ifgerr:1; + uint64_t phy_link:1; + uint64_t phy_spd:1; + uint64_t phy_dupx:1; + uint64_t pause_drp:1; + uint64_t reserved_20_63:44; + } cn50xx; + struct cvmx_gmxx_rxx_int_reg_cn52xx { + uint64_t reserved_0_0:1; + uint64_t carext:1; + uint64_t reserved_2_2:1; + uint64_t jabber:1; + uint64_t fcserr:1; + uint64_t reserved_5_6:2; + uint64_t rcverr:1; + uint64_t skperr:1; + uint64_t reserved_9_9:1; + uint64_t ovrerr:1; + uint64_t pcterr:1; + uint64_t rsverr:1; + uint64_t falerr:1; + uint64_t coldet:1; + uint64_t ifgerr:1; + uint64_t reserved_16_18:3; + uint64_t pause_drp:1; + uint64_t loc_fault:1; + uint64_t rem_fault:1; + uint64_t bad_seq:1; + uint64_t bad_term:1; + uint64_t unsop:1; + uint64_t uneop:1; + uint64_t undat:1; + uint64_t hg2fld:1; + uint64_t hg2cc:1; + uint64_t reserved_29_63:35; + } cn52xx; + struct cvmx_gmxx_rxx_int_reg_cn56xxp1 { + uint64_t reserved_0_0:1; + uint64_t carext:1; + uint64_t reserved_2_2:1; + uint64_t jabber:1; + uint64_t fcserr:1; + uint64_t reserved_5_6:2; + uint64_t rcverr:1; + uint64_t skperr:1; + uint64_t reserved_9_9:1; + uint64_t ovrerr:1; + uint64_t pcterr:1; + uint64_t rsverr:1; + uint64_t falerr:1; + uint64_t coldet:1; + uint64_t ifgerr:1; + uint64_t reserved_16_18:3; + uint64_t pause_drp:1; + uint64_t loc_fault:1; + uint64_t rem_fault:1; + uint64_t bad_seq:1; + uint64_t bad_term:1; + uint64_t unsop:1; + uint64_t uneop:1; + uint64_t undat:1; + uint64_t reserved_27_63:37; + } cn56xxp1; + struct cvmx_gmxx_rxx_int_reg_cn58xx { + uint64_t minerr:1; + uint64_t carext:1; + uint64_t maxerr:1; + uint64_t jabber:1; + uint64_t fcserr:1; + uint64_t alnerr:1; + uint64_t lenerr:1; + uint64_t rcverr:1; + uint64_t skperr:1; + uint64_t niberr:1; + uint64_t ovrerr:1; + uint64_t pcterr:1; + uint64_t rsverr:1; + uint64_t falerr:1; + uint64_t coldet:1; + uint64_t ifgerr:1; + uint64_t phy_link:1; + uint64_t phy_spd:1; + uint64_t phy_dupx:1; + uint64_t pause_drp:1; + uint64_t reserved_20_63:44; + } cn58xx; + struct cvmx_gmxx_rxx_int_reg_cn61xx { + uint64_t minerr:1; + uint64_t carext:1; + uint64_t reserved_2_2:1; + uint64_t jabber:1; + uint64_t fcserr:1; + uint64_t reserved_5_6:2; + uint64_t rcverr:1; + uint64_t skperr:1; + uint64_t reserved_9_9:1; + uint64_t ovrerr:1; + uint64_t pcterr:1; + uint64_t rsverr:1; + uint64_t falerr:1; + uint64_t coldet:1; + uint64_t ifgerr:1; + uint64_t reserved_16_18:3; + uint64_t pause_drp:1; + uint64_t loc_fault:1; + uint64_t rem_fault:1; + uint64_t bad_seq:1; + uint64_t bad_term:1; + uint64_t unsop:1; + uint64_t uneop:1; + uint64_t undat:1; + uint64_t hg2fld:1; + uint64_t hg2cc:1; + uint64_t reserved_29_63:35; + } cn61xx; +}; + +union cvmx_gmxx_prtx_cfg { + uint64_t u64; + struct cvmx_gmxx_prtx_cfg_s { + uint64_t reserved_22_63:42; + uint64_t pknd:6; + uint64_t reserved_14_15:2; + uint64_t tx_idle:1; + uint64_t rx_idle:1; + uint64_t reserved_9_11:3; + uint64_t speed_msb:1; + uint64_t reserved_4_7:4; + uint64_t slottime:1; + uint64_t duplex:1; + uint64_t speed:1; + uint64_t en:1; + } s; + struct cvmx_gmxx_prtx_cfg_cn30xx { + uint64_t reserved_4_63:60; + uint64_t slottime:1; + uint64_t duplex:1; + uint64_t speed:1; + uint64_t en:1; + } cn30xx; + struct cvmx_gmxx_prtx_cfg_cn52xx { + uint64_t reserved_14_63:50; + uint64_t tx_idle:1; + uint64_t rx_idle:1; + uint64_t reserved_9_11:3; + uint64_t speed_msb:1; + uint64_t reserved_4_7:4; + uint64_t slottime:1; + uint64_t duplex:1; + uint64_t speed:1; + uint64_t en:1; + } cn52xx; +}; + +union cvmx_gmxx_rxx_adr_ctl { + uint64_t u64; + struct cvmx_gmxx_rxx_adr_ctl_s { + uint64_t reserved_4_63:60; + uint64_t cam_mode:1; + uint64_t mcst:2; + uint64_t bcst:1; + } s; +}; + +union cvmx_pip_prt_tagx { + uint64_t u64; + struct cvmx_pip_prt_tagx_s { + uint64_t reserved_54_63:10; + uint64_t portadd_en:1; + uint64_t inc_hwchk:1; + uint64_t reserved_50_51:2; + uint64_t grptagbase_msb:2; + uint64_t reserved_46_47:2; + uint64_t grptagmask_msb:2; + uint64_t reserved_42_43:2; + uint64_t grp_msb:2; + uint64_t grptagbase:4; + uint64_t grptagmask:4; + uint64_t grptag:1; + uint64_t grptag_mskip:1; + uint64_t tag_mode:2; + uint64_t inc_vs:2; + uint64_t inc_vlan:1; + uint64_t inc_prt_flag:1; + uint64_t ip6_dprt_flag:1; + uint64_t ip4_dprt_flag:1; + uint64_t ip6_sprt_flag:1; + uint64_t ip4_sprt_flag:1; + uint64_t ip6_nxth_flag:1; + uint64_t ip4_pctl_flag:1; + uint64_t ip6_dst_flag:1; + uint64_t ip4_dst_flag:1; + uint64_t ip6_src_flag:1; + uint64_t ip4_src_flag:1; + uint64_t tcp6_tag_type:2; + uint64_t tcp4_tag_type:2; + uint64_t ip6_tag_type:2; + uint64_t ip4_tag_type:2; + uint64_t non_tag_type:2; + uint64_t grp:4; + } s; + struct cvmx_pip_prt_tagx_cn30xx { + uint64_t reserved_40_63:24; + uint64_t grptagbase:4; + uint64_t grptagmask:4; + uint64_t grptag:1; + uint64_t reserved_30_30:1; + uint64_t tag_mode:2; + uint64_t inc_vs:2; + uint64_t inc_vlan:1; + uint64_t inc_prt_flag:1; + uint64_t ip6_dprt_flag:1; + uint64_t ip4_dprt_flag:1; + uint64_t ip6_sprt_flag:1; + uint64_t ip4_sprt_flag:1; + uint64_t ip6_nxth_flag:1; + uint64_t ip4_pctl_flag:1; + uint64_t ip6_dst_flag:1; + uint64_t ip4_dst_flag:1; + uint64_t ip6_src_flag:1; + uint64_t ip4_src_flag:1; + uint64_t tcp6_tag_type:2; + uint64_t tcp4_tag_type:2; + uint64_t ip6_tag_type:2; + uint64_t ip4_tag_type:2; + uint64_t non_tag_type:2; + uint64_t grp:4; + } cn30xx; + struct cvmx_pip_prt_tagx_cn50xx { + uint64_t reserved_40_63:24; + uint64_t grptagbase:4; + uint64_t grptagmask:4; + uint64_t grptag:1; + uint64_t grptag_mskip:1; + uint64_t tag_mode:2; + uint64_t inc_vs:2; + uint64_t inc_vlan:1; + uint64_t inc_prt_flag:1; + uint64_t ip6_dprt_flag:1; + uint64_t ip4_dprt_flag:1; + uint64_t ip6_sprt_flag:1; + uint64_t ip4_sprt_flag:1; + uint64_t ip6_nxth_flag:1; + uint64_t ip4_pctl_flag:1; + uint64_t ip6_dst_flag:1; + uint64_t ip4_dst_flag:1; + uint64_t ip6_src_flag:1; + uint64_t ip4_src_flag:1; + uint64_t tcp6_tag_type:2; + uint64_t tcp4_tag_type:2; + uint64_t ip6_tag_type:2; + uint64_t ip4_tag_type:2; + uint64_t non_tag_type:2; + uint64_t grp:4; + } cn50xx; +}; + +union cvmx_spxx_int_reg { + uint64_t u64; + struct cvmx_spxx_int_reg_s { + uint64_t reserved_32_63:32; + uint64_t spf:1; + uint64_t reserved_12_30:19; + uint64_t calerr:1; + uint64_t syncerr:1; + uint64_t diperr:1; + uint64_t tpaovr:1; + uint64_t rsverr:1; + uint64_t drwnng:1; + uint64_t clserr:1; + uint64_t spiovr:1; + uint64_t reserved_2_3:2; + uint64_t abnorm:1; + uint64_t prtnxa:1; + } s; +}; + +union cvmx_spxx_int_msk { + uint64_t u64; + struct cvmx_spxx_int_msk_s { + uint64_t reserved_12_63:52; + uint64_t calerr:1; + uint64_t syncerr:1; + uint64_t diperr:1; + uint64_t tpaovr:1; + uint64_t rsverr:1; + uint64_t drwnng:1; + uint64_t clserr:1; + uint64_t spiovr:1; + uint64_t reserved_2_3:2; + uint64_t abnorm:1; + uint64_t prtnxa:1; + } s; +}; + +union cvmx_pow_wq_int { + uint64_t u64; + struct cvmx_pow_wq_int_s { + uint64_t wq_int:16; + uint64_t iq_dis:16; + uint64_t reserved_32_63:32; + } s; +}; + +union cvmx_sso_wq_int_thrx { + uint64_t u64; + struct { + uint64_t iq_thr:12; + uint64_t reserved_12_13:2; + uint64_t ds_thr:12; + uint64_t reserved_26_27:2; + uint64_t tc_thr:4; + uint64_t tc_en:1; + uint64_t reserved_33_63:31; + } s; +}; + +union cvmx_stxx_int_reg { + uint64_t u64; + struct cvmx_stxx_int_reg_s { + uint64_t reserved_9_63:55; + uint64_t syncerr:1; + uint64_t frmerr:1; + uint64_t unxfrm:1; + uint64_t nosync:1; + uint64_t diperr:1; + uint64_t datovr:1; + uint64_t ovrbst:1; + uint64_t calpar1:1; + uint64_t calpar0:1; + } s; +}; + +union cvmx_stxx_int_msk { + uint64_t u64; + struct cvmx_stxx_int_msk_s { + uint64_t reserved_8_63:56; + uint64_t frmerr:1; + uint64_t unxfrm:1; + uint64_t nosync:1; + uint64_t diperr:1; + uint64_t datovr:1; + uint64_t ovrbst:1; + uint64_t calpar1:1; + uint64_t calpar0:1; + } s; +}; + +union cvmx_pow_wq_int_pc { + uint64_t u64; + struct cvmx_pow_wq_int_pc_s { + uint64_t reserved_0_7:8; + uint64_t pc_thr:20; + uint64_t reserved_28_31:4; + uint64_t pc:28; + uint64_t reserved_60_63:4; + } s; +}; + +union cvmx_pow_wq_int_thrx { + uint64_t u64; + struct cvmx_pow_wq_int_thrx_s { + uint64_t reserved_29_63:35; + uint64_t tc_en:1; + uint64_t tc_thr:4; + uint64_t reserved_23_23:1; + uint64_t ds_thr:11; + uint64_t reserved_11_11:1; + uint64_t iq_thr:11; + } s; + struct cvmx_pow_wq_int_thrx_cn30xx { + uint64_t reserved_29_63:35; + uint64_t tc_en:1; + uint64_t tc_thr:4; + uint64_t reserved_18_23:6; + uint64_t ds_thr:6; + uint64_t reserved_6_11:6; + uint64_t iq_thr:6; + } cn30xx; + struct cvmx_pow_wq_int_thrx_cn31xx { + uint64_t reserved_29_63:35; + uint64_t tc_en:1; + uint64_t tc_thr:4; + uint64_t reserved_20_23:4; + uint64_t ds_thr:8; + uint64_t reserved_8_11:4; + uint64_t iq_thr:8; + } cn31xx; + struct cvmx_pow_wq_int_thrx_cn52xx { + uint64_t reserved_29_63:35; + uint64_t tc_en:1; + uint64_t tc_thr:4; + uint64_t reserved_21_23:3; + uint64_t ds_thr:9; + uint64_t reserved_9_11:3; + uint64_t iq_thr:9; + } cn52xx; + struct cvmx_pow_wq_int_thrx_cn63xx { + uint64_t reserved_29_63:35; + uint64_t tc_en:1; + uint64_t tc_thr:4; + uint64_t reserved_22_23:2; + uint64_t ds_thr:10; + uint64_t reserved_10_11:2; + uint64_t iq_thr:10; + } cn63xx; +}; + +union cvmx_npi_rsl_int_blocks { + uint64_t u64; + struct cvmx_npi_rsl_int_blocks_s { + uint64_t reserved_32_63:32; + uint64_t rint_31:1; + uint64_t iob:1; + uint64_t reserved_28_29:2; + uint64_t rint_27:1; + uint64_t rint_26:1; + uint64_t rint_25:1; + uint64_t rint_24:1; + uint64_t asx1:1; + uint64_t asx0:1; + uint64_t rint_21:1; + uint64_t pip:1; + uint64_t spx1:1; + uint64_t spx0:1; + uint64_t lmc:1; + uint64_t l2c:1; + uint64_t rint_15:1; + uint64_t reserved_13_14:2; + uint64_t pow:1; + uint64_t tim:1; + uint64_t pko:1; + uint64_t ipd:1; + uint64_t rint_8:1; + uint64_t zip:1; + uint64_t dfa:1; + uint64_t fpa:1; + uint64_t key:1; + uint64_t npi:1; + uint64_t gmx1:1; + uint64_t gmx0:1; + uint64_t mio:1; + } s; + struct cvmx_npi_rsl_int_blocks_cn30xx { + uint64_t reserved_32_63:32; + uint64_t rint_31:1; + uint64_t iob:1; + uint64_t rint_29:1; + uint64_t rint_28:1; + uint64_t rint_27:1; + uint64_t rint_26:1; + uint64_t rint_25:1; + uint64_t rint_24:1; + uint64_t asx1:1; + uint64_t asx0:1; + uint64_t rint_21:1; + uint64_t pip:1; + uint64_t spx1:1; + uint64_t spx0:1; + uint64_t lmc:1; + uint64_t l2c:1; + uint64_t rint_15:1; + uint64_t rint_14:1; + uint64_t usb:1; + uint64_t pow:1; + uint64_t tim:1; + uint64_t pko:1; + uint64_t ipd:1; + uint64_t rint_8:1; + uint64_t zip:1; + uint64_t dfa:1; + uint64_t fpa:1; + uint64_t key:1; + uint64_t npi:1; + uint64_t gmx1:1; + uint64_t gmx0:1; + uint64_t mio:1; + } cn30xx; + struct cvmx_npi_rsl_int_blocks_cn38xx { + uint64_t reserved_32_63:32; + uint64_t rint_31:1; + uint64_t iob:1; + uint64_t rint_29:1; + uint64_t rint_28:1; + uint64_t rint_27:1; + uint64_t rint_26:1; + uint64_t rint_25:1; + uint64_t rint_24:1; + uint64_t asx1:1; + uint64_t asx0:1; + uint64_t rint_21:1; + uint64_t pip:1; + uint64_t spx1:1; + uint64_t spx0:1; + uint64_t lmc:1; + uint64_t l2c:1; + uint64_t rint_15:1; + uint64_t rint_14:1; + uint64_t rint_13:1; + uint64_t pow:1; + uint64_t tim:1; + uint64_t pko:1; + uint64_t ipd:1; + uint64_t rint_8:1; + uint64_t zip:1; + uint64_t dfa:1; + uint64_t fpa:1; + uint64_t key:1; + uint64_t npi:1; + uint64_t gmx1:1; + uint64_t gmx0:1; + uint64_t mio:1; + } cn38xx; + struct cvmx_npi_rsl_int_blocks_cn50xx { + uint64_t reserved_31_63:33; + uint64_t iob:1; + uint64_t lmc1:1; + uint64_t agl:1; + uint64_t reserved_24_27:4; + uint64_t asx1:1; + uint64_t asx0:1; + uint64_t reserved_21_21:1; + uint64_t pip:1; + uint64_t spx1:1; + uint64_t spx0:1; + uint64_t lmc:1; + uint64_t l2c:1; + uint64_t reserved_15_15:1; + uint64_t rad:1; + uint64_t usb:1; + uint64_t pow:1; + uint64_t tim:1; + uint64_t pko:1; + uint64_t ipd:1; + uint64_t reserved_8_8:1; + uint64_t zip:1; + uint64_t dfa:1; + uint64_t fpa:1; + uint64_t key:1; + uint64_t npi:1; + uint64_t gmx1:1; + uint64_t gmx0:1; + uint64_t mio:1; + } cn50xx; +}; + +typedef union { + uint64_t u64; + struct { + uint64_t total_bytes:16; + uint64_t segs:6; + uint64_t dontfree:1; + uint64_t ignore_i:1; + uint64_t ipoffp1:7; + uint64_t gather:1; + uint64_t rsp:1; + uint64_t wqp:1; + uint64_t n2:1; + uint64_t le:1; + uint64_t reg0:11; + uint64_t subone0:1; + uint64_t reg1:11; + uint64_t subone1:1; + uint64_t size0:2; + uint64_t size1:2; + } s; +} cvmx_pko_command_word0_t; + +union cvmx_ciu_timx { + uint64_t u64; + struct cvmx_ciu_timx_s { + uint64_t reserved_37_63:27; + uint64_t one_shot:1; + uint64_t len:36; + } s; +}; + +union cvmx_gmxx_rxx_rx_inbnd { + uint64_t u64; + struct cvmx_gmxx_rxx_rx_inbnd_s { + uint64_t status:1; + uint64_t speed:2; + uint64_t duplex:1; + uint64_t reserved_4_63:60; + } s; +}; + +static inline int32_t cvmx_fau_fetch_and_add32(cvmx_fau_reg_32_t reg, + int32_t value) +{ + return value; +} + +static inline void cvmx_fau_atomic_add32(cvmx_fau_reg_32_t reg, int32_t value) +{ } + +static inline void cvmx_fau_atomic_write32(cvmx_fau_reg_32_t reg, int32_t value) +{ } + +static inline uint64_t cvmx_scratch_read64(uint64_t address) +{ + return 0; +} + +static inline void cvmx_scratch_write64(uint64_t address, uint64_t value) +{ } + +static inline int cvmx_wqe_get_grp(cvmx_wqe_t *work) +{ + return 0; +} + +static inline void *cvmx_phys_to_ptr(uint64_t physical_address) +{ + return (void *)(physical_address); +} + +static inline uint64_t cvmx_ptr_to_phys(void *ptr) +{ + return (unsigned long)ptr; +} + +static inline int cvmx_helper_get_interface_num(int ipd_port) +{ + return ipd_port; +} + +static inline int cvmx_helper_get_interface_index_num(int ipd_port) +{ + return ipd_port; +} + +static inline void cvmx_fpa_enable(void) +{ } + +static inline uint64_t cvmx_read_csr(uint64_t csr_addr) +{ + return 0; +} + +static inline void cvmx_write_csr(uint64_t csr_addr, uint64_t val) +{ } + +static inline int cvmx_helper_setup_red(int pass_thresh, int drop_thresh) +{ + return 0; +} + +static inline void *cvmx_fpa_alloc(uint64_t pool) +{ + return NULL; +} + +static inline void cvmx_fpa_free(void *ptr, uint64_t pool, + uint64_t num_cache_lines) +{ } + +static inline int octeon_is_simulation(void) +{ + return 1; +} + +static inline void cvmx_pip_get_port_status(uint64_t port_num, uint64_t clear, + cvmx_pip_port_status_t *status) +{ } + +static inline void cvmx_pko_get_port_status(uint64_t port_num, uint64_t clear, + cvmx_pko_port_status_t *status) +{ } + +static inline cvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int + interface) +{ + return 0; +} + +static inline cvmx_helper_link_info_t cvmx_helper_link_get(int ipd_port) +{ + cvmx_helper_link_info_t ret = { .u64 = 0 }; + + return ret; +} + +static inline int cvmx_helper_link_set(int ipd_port, + cvmx_helper_link_info_t link_info) +{ + return 0; +} + +static inline int cvmx_helper_initialize_packet_io_global(void) +{ + return 0; +} + +static inline int cvmx_helper_get_number_of_interfaces(void) +{ + return 2; +} + +static inline int cvmx_helper_ports_on_interface(int interface) +{ + return 1; +} + +static inline int cvmx_helper_get_ipd_port(int interface, int port) +{ + return 0; +} + +static inline int cvmx_helper_ipd_and_packet_input_enable(void) +{ + return 0; +} + +static inline void cvmx_ipd_disable(void) +{ } + +static inline void cvmx_ipd_free_ptr(void) +{ } + +static inline void cvmx_pko_disable(void) +{ } + +static inline void cvmx_pko_shutdown(void) +{ } + +static inline int cvmx_pko_get_base_queue_per_core(int port, int core) +{ + return port; +} + +static inline int cvmx_pko_get_base_queue(int port) +{ + return port; +} + +static inline int cvmx_pko_get_num_queues(int port) +{ + return port; +} + +static inline unsigned int cvmx_get_core_num(void) +{ + return 0; +} + +static inline void cvmx_pow_work_request_async_nocheck(int scr_addr, + cvmx_pow_wait_t wait) +{ } + +static inline void cvmx_pow_work_request_async(int scr_addr, + cvmx_pow_wait_t wait) +{ } + +static inline cvmx_wqe_t *cvmx_pow_work_response_async(int scr_addr) +{ + cvmx_wqe_t *wqe = (void *)(unsigned long)scr_addr; + + return wqe; +} + +static inline cvmx_wqe_t *cvmx_pow_work_request_sync(cvmx_pow_wait_t wait) +{ + return (void *)(unsigned long)wait; +} + +static inline int cvmx_spi_restart_interface(int interface, + cvmx_spi_mode_t mode, int timeout) +{ + return 0; +} + +static inline void cvmx_fau_async_fetch_and_add32(uint64_t scraddr, + cvmx_fau_reg_32_t reg, + int32_t value) +{ } + +static inline union cvmx_gmxx_rxx_rx_inbnd cvmx_spi4000_check_speed( + int interface, + int port) +{ + union cvmx_gmxx_rxx_rx_inbnd r; + r.u64 = 0; + return r; +} + +static inline void cvmx_pko_send_packet_prepare(uint64_t port, uint64_t queue, + cvmx_pko_lock_t use_locking) +{ } + +static inline cvmx_pko_status_t cvmx_pko_send_packet_finish(uint64_t port, + uint64_t queue, cvmx_pko_command_word0_t pko_command, + union cvmx_buf_ptr packet, cvmx_pko_lock_t use_locking) +{ + cvmx_pko_status_t ret = 0; + + return ret; +} + +static inline void cvmx_wqe_set_port(cvmx_wqe_t *work, int port) +{ } + +static inline void cvmx_wqe_set_qos(cvmx_wqe_t *work, int qos) +{ } + +static inline int cvmx_wqe_get_qos(cvmx_wqe_t *work) +{ + return 0; +} + +static inline void cvmx_wqe_set_grp(cvmx_wqe_t *work, int grp) +{ } + +static inline void cvmx_pow_work_submit(cvmx_wqe_t *wqp, uint32_t tag, + enum cvmx_pow_tag_type tag_type, + uint64_t qos, uint64_t grp) +{ } + +#define CVMX_ASXX_RX_CLK_SETX(a, b) ((a)+(b)) +#define CVMX_ASXX_TX_CLK_SETX(a, b) ((a)+(b)) +#define CVMX_CIU_TIMX(a) (a) +#define CVMX_GMXX_RXX_ADR_CAM0(a, b) ((a)+(b)) +#define CVMX_GMXX_RXX_ADR_CAM1(a, b) ((a)+(b)) +#define CVMX_GMXX_RXX_ADR_CAM2(a, b) ((a)+(b)) +#define CVMX_GMXX_RXX_ADR_CAM3(a, b) ((a)+(b)) +#define CVMX_GMXX_RXX_ADR_CAM4(a, b) ((a)+(b)) +#define CVMX_GMXX_RXX_ADR_CAM5(a, b) ((a)+(b)) +#define CVMX_GMXX_RXX_FRM_CTL(a, b) ((a)+(b)) +#define CVMX_GMXX_RXX_INT_REG(a, b) ((a)+(b)) +#define CVMX_GMXX_SMACX(a, b) ((a)+(b)) +#define CVMX_PIP_PRT_TAGX(a) (a) +#define CVMX_POW_PP_GRP_MSKX(a) (a) +#define CVMX_POW_WQ_INT_THRX(a) (a) +#define CVMX_SPXX_INT_MSK(a) (a) +#define CVMX_SPXX_INT_REG(a) (a) +#define CVMX_SSO_PPX_GRP_MSK(a) (a) +#define CVMX_SSO_WQ_INT_THRX(a) (a) +#define CVMX_STXX_INT_MSK(a) (a) +#define CVMX_STXX_INT_REG(a) (a) diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c index b889b04a6e25..6fa7726185de 100644 --- a/drivers/staging/unisys/visornic/visornic_main.c +++ b/drivers/staging/unisys/visornic/visornic_main.c @@ -284,7 +284,7 @@ static int visor_copy_fragsinfo_from_skb(struct sk_buff *skb, for (frag = 0; frag < numfrags; frag++) { count = add_physinfo_entries(page_to_pfn( skb_frag_page(&skb_shinfo(skb)->frags[frag])), - skb_shinfo(skb)->frags[frag].page_offset, + skb_frag_off(&skb_shinfo(skb)->frags[frag]), skb_frag_size(&skb_shinfo(skb)->frags[frag]), count, frags_max, frags); /* add_physinfo_entries only returns diff --git a/drivers/target/iscsi/cxgbit/cxgbit_target.c b/drivers/target/iscsi/cxgbit/cxgbit_target.c index c25315431ad0..fcdc4211e3c2 100644 --- a/drivers/target/iscsi/cxgbit/cxgbit_target.c +++ b/drivers/target/iscsi/cxgbit/cxgbit_target.c @@ -900,7 +900,7 @@ cxgbit_handle_immediate_data(struct iscsi_cmd *cmd, struct iscsi_scsi_req *hdr, sg_init_table(&ccmd->sg, 1); sg_set_page(&ccmd->sg, skb_frag_page(dfrag), - skb_frag_size(dfrag), dfrag->page_offset); + skb_frag_size(dfrag), skb_frag_off(dfrag)); get_page(skb_frag_page(dfrag)); cmd->se_cmd.t_data_sg = &ccmd->sg; @@ -1403,7 +1403,7 @@ static void cxgbit_lro_skb_dump(struct sk_buff *skb) pdu_cb->ddigest, pdu_cb->frags); for (i = 0; i < ssi->nr_frags; i++) pr_info("skb 0x%p, frag %d, off %u, sz %u.\n", - skb, i, ssi->frags[i].page_offset, + skb, i, skb_frag_off(&ssi->frags[i]), skb_frag_size(&ssi->frags[i])); } diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c index 6a50e1d0529c..9f57736fe15e 100644 --- a/drivers/vhost/vsock.c +++ b/drivers/vhost/vsock.c @@ -102,7 +102,7 @@ vhost_transport_do_send_pkt(struct vhost_vsock *vsock, struct iov_iter iov_iter; unsigned out, in; size_t nbytes; - size_t len; + size_t iov_len, payload_len; int head; spin_lock_bh(&vsock->send_pkt_list_lock); @@ -147,8 +147,24 @@ vhost_transport_do_send_pkt(struct vhost_vsock *vsock, break; } - len = iov_length(&vq->iov[out], in); - iov_iter_init(&iov_iter, READ, &vq->iov[out], in, len); + iov_len = iov_length(&vq->iov[out], in); + if (iov_len < sizeof(pkt->hdr)) { + virtio_transport_free_pkt(pkt); + vq_err(vq, "Buffer len [%zu] too small\n", iov_len); + break; + } + + iov_iter_init(&iov_iter, READ, &vq->iov[out], in, iov_len); + payload_len = pkt->len - pkt->off; + + /* If the packet is greater than the space available in the + * buffer, we split it using multiple buffers. + */ + if (payload_len > iov_len - sizeof(pkt->hdr)) + payload_len = iov_len - sizeof(pkt->hdr); + + /* Set the correct length in the header */ + pkt->hdr.len = cpu_to_le32(payload_len); nbytes = copy_to_iter(&pkt->hdr, sizeof(pkt->hdr), &iov_iter); if (nbytes != sizeof(pkt->hdr)) { @@ -157,33 +173,47 @@ vhost_transport_do_send_pkt(struct vhost_vsock *vsock, break; } - nbytes = copy_to_iter(pkt->buf, pkt->len, &iov_iter); - if (nbytes != pkt->len) { + nbytes = copy_to_iter(pkt->buf + pkt->off, payload_len, + &iov_iter); + if (nbytes != payload_len) { virtio_transport_free_pkt(pkt); vq_err(vq, "Faulted on copying pkt buf\n"); break; } - vhost_add_used(vq, head, sizeof(pkt->hdr) + pkt->len); + vhost_add_used(vq, head, sizeof(pkt->hdr) + payload_len); added = true; - if (pkt->reply) { - int val; - - val = atomic_dec_return(&vsock->queued_replies); - - /* Do we have resources to resume tx processing? */ - if (val + 1 == tx_vq->num) - restart_tx = true; - } - /* Deliver to monitoring devices all correctly transmitted * packets. */ virtio_transport_deliver_tap_pkt(pkt); - total_len += pkt->len; - virtio_transport_free_pkt(pkt); + pkt->off += payload_len; + total_len += payload_len; + + /* If we didn't send all the payload we can requeue the packet + * to send it with the next available buffer. + */ + if (pkt->off < pkt->len) { + spin_lock_bh(&vsock->send_pkt_list_lock); + list_add(&pkt->list, &vsock->send_pkt_list); + spin_unlock_bh(&vsock->send_pkt_list_lock); + } else { + if (pkt->reply) { + int val; + + val = atomic_dec_return(&vsock->queued_replies); + + /* Do we have resources to resume tx + * processing? + */ + if (val + 1 == tx_vq->num) + restart_tx = true; + } + + virtio_transport_free_pkt(pkt); + } } while(likely(!vhost_exceeds_weight(vq, ++pkts, total_len))); if (added) vhost_signal(&vsock->dev, vq); @@ -329,6 +359,8 @@ vhost_vsock_alloc_pkt(struct vhost_virtqueue *vq, return NULL; } + pkt->buf_len = pkt->len; + nbytes = copy_from_iter(pkt->buf, pkt->len, &iov_iter); if (nbytes != pkt->len) { vq_err(vq, "Expected %u byte payload, got %zu bytes\n", |