mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 11:11:45 -04:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking updates from David Miller:
"Another merge window, another set of networking changes. I've heard
rumblings that the lightweight tunnels infrastructure has been voted
networking change of the year. But what do I know?
1) Add conntrack support to openvswitch, from Joe Stringer.
2) Initial support for VRF (Virtual Routing and Forwarding), which
allows the segmentation of routing paths without using multiple
devices. There are some semantic kinks to work out still, but
this is a reasonably strong foundation. From David Ahern.
3) Remove spinlock fro act_bpf fast path, from Alexei Starovoitov.
4) Ignore route nexthops with a link down state in ipv6, just like
ipv4. From Andy Gospodarek.
5) Remove spinlock from fast path of act_gact and act_mirred, from
Eric Dumazet.
6) Document the DSA layer, from Florian Fainelli.
7) Add netconsole support to bcmgenet, systemport, and DSA. Also
from Florian Fainelli.
8) Add Mellanox Switch Driver and core infrastructure, from Jiri
Pirko.
9) Add support for "light weight tunnels", which allow for
encapsulation and decapsulation without bearing the overhead of a
full blown netdevice. From Thomas Graf, Jiri Benc, and a cast of
others.
10) Add Identifier Locator Addressing support for ipv6, from Tom
Herbert.
11) Support fragmented SKBs in iwlwifi, from Johannes Berg.
12) Allow perf PMUs to be accessed from eBPF programs, from Kaixu Xia.
13) Add BQL support to 3c59x driver, from Loganaden Velvindron.
14) Stop using a zero TX queue length to mean that a device shouldn't
have a qdisc attached, use an explicit flag instead. From Phil
Sutter.
15) Use generic geneve netdevice infrastructure in openvswitch, from
Pravin B Shelar.
16) Add infrastructure to avoid re-forwarding a packet in software
that was already forwarded by a hardware switch. From Scott
Feldman.
17) Allow AF_PACKET fanout function to be implemented in a bpf
program, from Willem de Bruijn"
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1458 commits)
netfilter: nf_conntrack: make nf_ct_zone_dflt built-in
netfilter: nf_dup{4, 6}: fix build error when nf_conntrack disabled
net: fec: clear receive interrupts before processing a packet
ipv6: fix exthdrs offload registration in out_rt path
xen-netback: add support for multicast control
bgmac: Update fixed_phy_register()
sock, diag: fix panic in sock_diag_put_filterinfo
flow_dissector: Use 'const' where possible.
flow_dissector: Fix function argument ordering dependency
ixgbe: Resolve "initialized field overwritten" warnings
ixgbe: Remove bimodal SR-IOV disabling
ixgbe: Add support for reporting 2.5G link speed
ixgbe: fix bounds checking in ixgbe_setup_tc for 82598
ixgbe: support for ethtool set_rxfh
ixgbe: Avoid needless PHY access on copper phys
ixgbe: cleanup to use cached mask value
ixgbe: Remove second instance of lan_id variable
ixgbe: use kzalloc for allocating one thing
flow: Move __get_hash_from_flowi{4,6} into flow_dissector.c
ixgbe: Remove unused PCI bus types
...
This commit is contained in:
commit
dd5cdb48ed
1229 changed files with 78632 additions and 21995 deletions
|
|
@ -180,8 +180,8 @@ config VXLAN
|
|||
will be called vxlan.
|
||||
|
||||
config GENEVE
|
||||
tristate "Generic Network Virtualization Encapsulation netdev"
|
||||
depends on INET && GENEVE_CORE
|
||||
tristate "Generic Network Virtualization Encapsulation"
|
||||
depends on INET && NET_UDP_TUNNEL
|
||||
select NET_IP_TUNNEL
|
||||
---help---
|
||||
This allows one to create geneve virtual interfaces that provide
|
||||
|
|
@ -282,7 +282,6 @@ config VETH
|
|||
config VIRTIO_NET
|
||||
tristate "Virtio network driver"
|
||||
depends on VIRTIO
|
||||
select AVERAGE
|
||||
---help---
|
||||
This is the virtual network driver for virtio. It can be used with
|
||||
lguest or QEMU based VMMs (like KVM or Xen). Say Y or M.
|
||||
|
|
@ -297,6 +296,13 @@ config NLMON
|
|||
diagnostics, etc. This is mostly intended for developers or support
|
||||
to debug netlink issues. If unsure, say N.
|
||||
|
||||
config NET_VRF
|
||||
tristate "Virtual Routing and Forwarding (Lite)"
|
||||
depends on IP_MULTIPLE_TABLES && IPV6_MULTIPLE_TABLES
|
||||
---help---
|
||||
This option enables the support for mapping interfaces into VRF's. The
|
||||
support enables VRF devices.
|
||||
|
||||
endif # NET_CORE
|
||||
|
||||
config SUNGEM_PHY
|
||||
|
|
@ -407,6 +413,13 @@ config VMXNET3
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called vmxnet3.
|
||||
|
||||
config FUJITSU_ES
|
||||
tristate "FUJITSU Extended Socket Network Device driver"
|
||||
depends on ACPI
|
||||
help
|
||||
This driver provides support for Extended Socket network device
|
||||
on Extended Partitioning of FUJITSU PRIMEQUEST 2000 E2 series.
|
||||
|
||||
source "drivers/net/hyperv/Kconfig"
|
||||
|
||||
endif # NETDEVICES
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ obj-$(CONFIG_VIRTIO_NET) += virtio_net.o
|
|||
obj-$(CONFIG_VXLAN) += vxlan.o
|
||||
obj-$(CONFIG_GENEVE) += geneve.o
|
||||
obj-$(CONFIG_NLMON) += nlmon.o
|
||||
obj-$(CONFIG_NET_VRF) += vrf.o
|
||||
|
||||
#
|
||||
# Networking Drivers
|
||||
|
|
@ -67,3 +68,5 @@ obj-$(CONFIG_USB_NET_DRIVERS) += usb/
|
|||
|
||||
obj-$(CONFIG_HYPERV_NET) += hyperv/
|
||||
obj-$(CONFIG_NTB_NETDEV) += ntb_netdev.o
|
||||
|
||||
obj-$(CONFIG_FUJITSU_ES) += fjes/
|
||||
|
|
|
|||
|
|
@ -1870,8 +1870,6 @@ static void ad_marker_info_received(struct bond_marker *marker_info,
|
|||
static void ad_marker_response_received(struct bond_marker *marker,
|
||||
struct port *port)
|
||||
{
|
||||
marker = NULL;
|
||||
port = NULL;
|
||||
/* DO NOTHING, SINCE WE DECIDED NOT TO IMPLEMENT THIS FEATURE FOR NOW */
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -979,7 +979,6 @@ static void bond_poll_controller(struct net_device *bond_dev)
|
|||
if (bond_3ad_get_active_agg_info(bond, &ad_info))
|
||||
return;
|
||||
|
||||
rcu_read_lock_bh();
|
||||
bond_for_each_slave_rcu(bond, slave, iter) {
|
||||
ops = slave->dev->netdev_ops;
|
||||
if (!bond_slave_is_up(slave) || !ops->ndo_poll_controller)
|
||||
|
|
@ -1000,7 +999,6 @@ static void bond_poll_controller(struct net_device *bond_dev)
|
|||
ops->ndo_poll_controller(slave->dev);
|
||||
up(&ni->dev_lock);
|
||||
}
|
||||
rcu_read_unlock_bh();
|
||||
}
|
||||
|
||||
static void bond_netpoll_cleanup(struct net_device *bond_dev)
|
||||
|
|
@ -3097,7 +3095,7 @@ static bool bond_flow_dissect(struct bonding *bond, struct sk_buff *skb,
|
|||
int noff, proto = -1;
|
||||
|
||||
if (bond->params.xmit_policy > BOND_XMIT_POLICY_LAYER23)
|
||||
return skb_flow_dissect_flow_keys(skb, fk);
|
||||
return skb_flow_dissect_flow_keys(skb, fk, 0);
|
||||
|
||||
fk->ports.ports = 0;
|
||||
noff = skb_network_offset(skb);
|
||||
|
|
@ -3780,7 +3778,6 @@ int bond_update_slave_arr(struct bonding *bond, struct slave *skipslave)
|
|||
struct slave *slave;
|
||||
struct list_head *iter;
|
||||
struct bond_up_slave *new_arr, *old_arr;
|
||||
int slaves_in_agg;
|
||||
int agg_id = 0;
|
||||
int ret = 0;
|
||||
|
||||
|
|
@ -3811,7 +3808,6 @@ int bond_update_slave_arr(struct bonding *bond, struct slave *skipslave)
|
|||
}
|
||||
goto out;
|
||||
}
|
||||
slaves_in_agg = ad_info.ports;
|
||||
agg_id = ad_info.aggregator_id;
|
||||
}
|
||||
bond_for_each_slave(bond, slave, iter) {
|
||||
|
|
@ -4122,9 +4118,8 @@ void bond_setup(struct net_device *bond_dev)
|
|||
SET_NETDEV_DEVTYPE(bond_dev, &bond_type);
|
||||
|
||||
/* Initialize the device options */
|
||||
bond_dev->tx_queue_len = 0;
|
||||
bond_dev->flags |= IFF_MASTER|IFF_MULTICAST;
|
||||
bond_dev->priv_flags |= IFF_BONDING | IFF_UNICAST_FLT;
|
||||
bond_dev->priv_flags |= IFF_BONDING | IFF_UNICAST_FLT | IFF_NO_QUEUE;
|
||||
bond_dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING);
|
||||
|
||||
/* don't acquire bond device's netif_tx_lock when transmitting */
|
||||
|
|
|
|||
|
|
@ -111,6 +111,7 @@ static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = {
|
|||
[IFLA_BOND_AD_USER_PORT_KEY] = { .type = NLA_U16 },
|
||||
[IFLA_BOND_AD_ACTOR_SYSTEM] = { .type = NLA_BINARY,
|
||||
.len = ETH_ALEN },
|
||||
[IFLA_BOND_TLB_DYNAMIC_LB] = { .type = NLA_U8 },
|
||||
};
|
||||
|
||||
static const struct nla_policy bond_slave_policy[IFLA_BOND_SLAVE_MAX + 1] = {
|
||||
|
|
@ -405,7 +406,6 @@ static int bond_changelink(struct net_device *bond_dev,
|
|||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (data[IFLA_BOND_AD_USER_PORT_KEY]) {
|
||||
int port_key =
|
||||
nla_get_u16(data[IFLA_BOND_AD_USER_PORT_KEY]);
|
||||
|
|
@ -415,7 +415,6 @@ static int bond_changelink(struct net_device *bond_dev,
|
|||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (data[IFLA_BOND_AD_ACTOR_SYSTEM]) {
|
||||
if (nla_len(data[IFLA_BOND_AD_ACTOR_SYSTEM]) != ETH_ALEN)
|
||||
return -EINVAL;
|
||||
|
|
@ -426,6 +425,15 @@ static int bond_changelink(struct net_device *bond_dev,
|
|||
if (err)
|
||||
return err;
|
||||
}
|
||||
if (data[IFLA_BOND_TLB_DYNAMIC_LB]) {
|
||||
int dynamic_lb = nla_get_u8(data[IFLA_BOND_TLB_DYNAMIC_LB]);
|
||||
|
||||
bond_opt_initval(&newval, dynamic_lb);
|
||||
err = __bond_opt_set(bond, BOND_OPT_TLB_DYNAMIC_LB, &newval);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -476,6 +484,7 @@ static size_t bond_get_size(const struct net_device *bond_dev)
|
|||
nla_total_size(sizeof(u16)) + /* IFLA_BOND_AD_ACTOR_SYS_PRIO */
|
||||
nla_total_size(sizeof(u16)) + /* IFLA_BOND_AD_USER_PORT_KEY */
|
||||
nla_total_size(ETH_ALEN) + /* IFLA_BOND_AD_ACTOR_SYSTEM */
|
||||
nla_total_size(sizeof(u8)) + /* IFLA_BOND_TLB_DYNAMIC_LB */
|
||||
0;
|
||||
}
|
||||
|
||||
|
|
@ -598,6 +607,10 @@ static int bond_fill_info(struct sk_buff *skb,
|
|||
bond->params.ad_select))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (nla_put_u8(skb, IFLA_BOND_TLB_DYNAMIC_LB,
|
||||
bond->params.tlb_dynamic_lb))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (BOND_MODE(bond) == BOND_MODE_8023AD) {
|
||||
struct ad_info info;
|
||||
|
||||
|
|
|
|||
|
|
@ -420,6 +420,13 @@ static const struct bond_option bond_opts[BOND_OPT_LAST] = {
|
|||
.flags = BOND_OPTFLAG_IFDOWN,
|
||||
.values = bond_ad_user_port_key_tbl,
|
||||
.set = bond_option_ad_user_port_key_set,
|
||||
},
|
||||
[BOND_OPT_NUM_PEER_NOTIF_ALIAS] = {
|
||||
.id = BOND_OPT_NUM_PEER_NOTIF_ALIAS,
|
||||
.name = "num_grat_arp",
|
||||
.desc = "Number of peer notifications to send on failover event",
|
||||
.values = bond_num_peer_notif_tbl,
|
||||
.set = bond_option_num_peer_notif_set
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -380,7 +380,7 @@ static ssize_t bonding_show_ad_select(struct device *d,
|
|||
static DEVICE_ATTR(ad_select, S_IRUGO | S_IWUSR,
|
||||
bonding_show_ad_select, bonding_sysfs_store_option);
|
||||
|
||||
/* Show and set the number of peer notifications to send after a failover event. */
|
||||
/* Show the number of peer notifications to send after a failover event. */
|
||||
static ssize_t bonding_show_num_peer_notif(struct device *d,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
|
|
@ -388,24 +388,10 @@ static ssize_t bonding_show_num_peer_notif(struct device *d,
|
|||
struct bonding *bond = to_bond(d);
|
||||
return sprintf(buf, "%d\n", bond->params.num_peer_notif);
|
||||
}
|
||||
|
||||
static ssize_t bonding_store_num_peer_notif(struct device *d,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct bonding *bond = to_bond(d);
|
||||
int ret;
|
||||
|
||||
ret = bond_opt_tryset_rtnl(bond, BOND_OPT_NUM_PEER_NOTIF, (char *)buf);
|
||||
if (!ret)
|
||||
ret = count;
|
||||
|
||||
return ret;
|
||||
}
|
||||
static DEVICE_ATTR(num_grat_arp, S_IRUGO | S_IWUSR,
|
||||
bonding_show_num_peer_notif, bonding_store_num_peer_notif);
|
||||
bonding_show_num_peer_notif, bonding_sysfs_store_option);
|
||||
static DEVICE_ATTR(num_unsol_na, S_IRUGO | S_IWUSR,
|
||||
bonding_show_num_peer_notif, bonding_store_num_peer_notif);
|
||||
bonding_show_num_peer_notif, bonding_sysfs_store_option);
|
||||
|
||||
/* Show the MII monitor interval. */
|
||||
static ssize_t bonding_show_miimon(struct device *d,
|
||||
|
|
|
|||
|
|
@ -1120,7 +1120,7 @@ static void cfhsi_setup(struct net_device *dev)
|
|||
dev->type = ARPHRD_CAIF;
|
||||
dev->flags = IFF_POINTOPOINT | IFF_NOARP;
|
||||
dev->mtu = CFHSI_MAX_CAIF_FRAME_SZ;
|
||||
dev->tx_queue_len = 0;
|
||||
dev->priv_flags |= IFF_NO_QUEUE;
|
||||
dev->destructor = free_netdev;
|
||||
dev->netdev_ops = &cfhsi_netdevops;
|
||||
for (i = 0; i < CFHSI_PRIO_LAST; ++i)
|
||||
|
|
|
|||
|
|
@ -427,7 +427,7 @@ static void caifdev_setup(struct net_device *dev)
|
|||
dev->type = ARPHRD_CAIF;
|
||||
dev->flags = IFF_POINTOPOINT | IFF_NOARP;
|
||||
dev->mtu = CAIF_MAX_MTU;
|
||||
dev->tx_queue_len = 0;
|
||||
dev->priv_flags |= IFF_NO_QUEUE;
|
||||
dev->destructor = free_netdev;
|
||||
skb_queue_head_init(&serdev->head);
|
||||
serdev->common.link_select = CAIF_LINK_LOW_LATENCY;
|
||||
|
|
|
|||
|
|
@ -710,7 +710,7 @@ static void cfspi_setup(struct net_device *dev)
|
|||
dev->netdev_ops = &cfspi_ops;
|
||||
dev->type = ARPHRD_CAIF;
|
||||
dev->flags = IFF_NOARP | IFF_POINTOPOINT;
|
||||
dev->tx_queue_len = 0;
|
||||
dev->priv_flags |= IFF_NO_QUEUE;
|
||||
dev->mtu = SPI_MAX_PAYLOAD_SIZE;
|
||||
dev->destructor = free_netdev;
|
||||
skb_queue_head_init(&cfspi->qhead);
|
||||
|
|
|
|||
|
|
@ -805,7 +805,7 @@ static void flexcan_set_bittiming(struct net_device *dev)
|
|||
if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
|
||||
reg |= FLEXCAN_CTRL_SMP;
|
||||
|
||||
netdev_info(dev, "writing ctrl=0x%08x\n", reg);
|
||||
netdev_dbg(dev, "writing ctrl=0x%08x\n", reg);
|
||||
flexcan_write(reg, ®s->ctrl);
|
||||
|
||||
/* print chip status */
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ struct gs_can {
|
|||
struct can_bittiming_const bt_const;
|
||||
unsigned int channel; /* channel number */
|
||||
|
||||
/* This lock prevents a race condition between xmit and recieve. */
|
||||
/* This lock prevents a race condition between xmit and receive. */
|
||||
spinlock_t tx_ctx_lock;
|
||||
struct gs_tx_context tx_context[GS_MAX_TX_URBS];
|
||||
|
||||
|
|
@ -274,7 +274,7 @@ static void gs_update_state(struct gs_can *dev, struct can_frame *cf)
|
|||
}
|
||||
}
|
||||
|
||||
static void gs_usb_recieve_bulk_callback(struct urb *urb)
|
||||
static void gs_usb_receive_bulk_callback(struct urb *urb)
|
||||
{
|
||||
struct gs_usb *usbcan = urb->context;
|
||||
struct gs_can *dev;
|
||||
|
|
@ -376,7 +376,7 @@ static void gs_usb_recieve_bulk_callback(struct urb *urb)
|
|||
usb_rcvbulkpipe(usbcan->udev, GSUSB_ENDPOINT_IN),
|
||||
hf,
|
||||
sizeof(struct gs_host_frame),
|
||||
gs_usb_recieve_bulk_callback,
|
||||
gs_usb_receive_bulk_callback,
|
||||
usbcan
|
||||
);
|
||||
|
||||
|
|
@ -605,7 +605,7 @@ static int gs_can_open(struct net_device *netdev)
|
|||
GSUSB_ENDPOINT_IN),
|
||||
buf,
|
||||
sizeof(struct gs_host_frame),
|
||||
gs_usb_recieve_bulk_callback,
|
||||
gs_usb_receive_bulk_callback,
|
||||
parent);
|
||||
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
|
||||
|
||||
|
|
|
|||
|
|
@ -46,13 +46,13 @@ config NET_DSA_MV88E6171
|
|||
ethernet switches chips.
|
||||
|
||||
config NET_DSA_MV88E6352
|
||||
tristate "Marvell 88E6172/88E6176/88E6352 ethernet switch chip support"
|
||||
tristate "Marvell 88E6172/6176/6320/6321/6352 ethernet switch chip support"
|
||||
depends on NET_DSA
|
||||
select NET_DSA_MV88E6XXX
|
||||
select NET_DSA_TAG_EDSA
|
||||
---help---
|
||||
This enables support for the Marvell 88E6172, 88E6176 and 88E6352
|
||||
ethernet switch chips.
|
||||
This enables support for the Marvell 88E6172, 88E6176, 88E6320,
|
||||
88E6321 and 88E6352 ethernet switch chips.
|
||||
|
||||
config NET_DSA_BCM_SF2
|
||||
tristate "Broadcom Starfighter 2 Ethernet switch support"
|
||||
|
|
|
|||
|
|
@ -901,15 +901,11 @@ static void bcm_sf2_sw_fixed_link_update(struct dsa_switch *ds, int port,
|
|||
struct fixed_phy_status *status)
|
||||
{
|
||||
struct bcm_sf2_priv *priv = ds_to_priv(ds);
|
||||
u32 duplex, pause, speed;
|
||||
u32 duplex, pause;
|
||||
u32 reg;
|
||||
|
||||
duplex = core_readl(priv, CORE_DUPSTS);
|
||||
pause = core_readl(priv, CORE_PAUSESTS);
|
||||
speed = core_readl(priv, CORE_SPDSTS);
|
||||
|
||||
speed >>= (port * SPDSTS_SHIFT);
|
||||
speed &= SPDSTS_MASK;
|
||||
|
||||
status->link = 0;
|
||||
|
||||
|
|
@ -944,18 +940,6 @@ static void bcm_sf2_sw_fixed_link_update(struct dsa_switch *ds, int port,
|
|||
reg &= ~LINK_STS;
|
||||
core_writel(priv, reg, CORE_STS_OVERRIDE_GMIIP_PORT(port));
|
||||
|
||||
switch (speed) {
|
||||
case SPDSTS_10:
|
||||
status->speed = SPEED_10;
|
||||
break;
|
||||
case SPDSTS_100:
|
||||
status->speed = SPEED_100;
|
||||
break;
|
||||
case SPDSTS_1000:
|
||||
status->speed = SPEED_1000;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((pause & (1 << port)) &&
|
||||
(pause & (1 << (port + PAUSESTS_TX_PAUSE_SHIFT)))) {
|
||||
status->asym_pause = 1;
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ struct dsa_switch_driver mv88e6123_61_65_switch_driver = {
|
|||
.get_strings = mv88e6xxx_get_strings,
|
||||
.get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
|
||||
.get_sset_count = mv88e6xxx_get_sset_count,
|
||||
.adjust_link = mv88e6xxx_adjust_link,
|
||||
#ifdef CONFIG_NET_DSA_HWMON
|
||||
.get_temp = mv88e6xxx_get_temp,
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -182,6 +182,7 @@ struct dsa_switch_driver mv88e6131_switch_driver = {
|
|||
.get_strings = mv88e6xxx_get_strings,
|
||||
.get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
|
||||
.get_sset_count = mv88e6xxx_get_sset_count,
|
||||
.adjust_link = mv88e6xxx_adjust_link,
|
||||
};
|
||||
|
||||
MODULE_ALIAS("platform:mv88e6085");
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ struct dsa_switch_driver mv88e6171_switch_driver = {
|
|||
.get_strings = mv88e6xxx_get_strings,
|
||||
.get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
|
||||
.get_sset_count = mv88e6xxx_get_sset_count,
|
||||
.adjust_link = mv88e6xxx_adjust_link,
|
||||
#ifdef CONFIG_NET_DSA_HWMON
|
||||
.get_temp = mv88e6xxx_get_temp,
|
||||
#endif
|
||||
|
|
@ -116,9 +117,9 @@ struct dsa_switch_driver mv88e6171_switch_driver = {
|
|||
.port_join_bridge = mv88e6xxx_join_bridge,
|
||||
.port_leave_bridge = mv88e6xxx_leave_bridge,
|
||||
.port_stp_update = mv88e6xxx_port_stp_update,
|
||||
.fdb_add = mv88e6xxx_port_fdb_add,
|
||||
.fdb_del = mv88e6xxx_port_fdb_del,
|
||||
.fdb_getnext = mv88e6xxx_port_fdb_getnext,
|
||||
.port_fdb_add = mv88e6xxx_port_fdb_add,
|
||||
.port_fdb_del = mv88e6xxx_port_fdb_del,
|
||||
.port_fdb_getnext = mv88e6xxx_port_fdb_getnext,
|
||||
};
|
||||
|
||||
MODULE_ALIAS("platform:mv88e6171");
|
||||
|
|
|
|||
|
|
@ -36,6 +36,18 @@ static char *mv88e6352_probe(struct device *host_dev, int sw_addr)
|
|||
return "Marvell 88E6172";
|
||||
if ((ret & 0xfff0) == PORT_SWITCH_ID_6176)
|
||||
return "Marvell 88E6176";
|
||||
if (ret == PORT_SWITCH_ID_6320_A1)
|
||||
return "Marvell 88E6320 (A1)";
|
||||
if (ret == PORT_SWITCH_ID_6320_A2)
|
||||
return "Marvell 88e6320 (A2)";
|
||||
if ((ret & 0xfff0) == PORT_SWITCH_ID_6320)
|
||||
return "Marvell 88E6320";
|
||||
if (ret == PORT_SWITCH_ID_6321_A1)
|
||||
return "Marvell 88E6321 (A1)";
|
||||
if (ret == PORT_SWITCH_ID_6321_A2)
|
||||
return "Marvell 88e6321 (A2)";
|
||||
if ((ret & 0xfff0) == PORT_SWITCH_ID_6321)
|
||||
return "Marvell 88E6321";
|
||||
if (ret == PORT_SWITCH_ID_6352_A0)
|
||||
return "Marvell 88E6352 (A0)";
|
||||
if (ret == PORT_SWITCH_ID_6352_A1)
|
||||
|
|
@ -80,66 +92,6 @@ static int mv88e6352_setup_global(struct dsa_switch *ds)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_DSA_HWMON
|
||||
|
||||
static int mv88e6352_get_temp(struct dsa_switch *ds, int *temp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
*temp = 0;
|
||||
|
||||
ret = mv88e6xxx_phy_page_read(ds, 0, 6, 27);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
*temp = (ret & 0xff) - 25;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mv88e6352_get_temp_limit(struct dsa_switch *ds, int *temp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
*temp = 0;
|
||||
|
||||
ret = mv88e6xxx_phy_page_read(ds, 0, 6, 26);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
*temp = (((ret >> 8) & 0x1f) * 5) - 25;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mv88e6352_set_temp_limit(struct dsa_switch *ds, int temp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = mv88e6xxx_phy_page_read(ds, 0, 6, 26);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
temp = clamp_val(DIV_ROUND_CLOSEST(temp, 5) + 5, 0, 0x1f);
|
||||
return mv88e6xxx_phy_page_write(ds, 0, 6, 26,
|
||||
(ret & 0xe0ff) | (temp << 8));
|
||||
}
|
||||
|
||||
static int mv88e6352_get_temp_alarm(struct dsa_switch *ds, bool *alarm)
|
||||
{
|
||||
int ret;
|
||||
|
||||
*alarm = false;
|
||||
|
||||
ret = mv88e6xxx_phy_page_read(ds, 0, 6, 26);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
*alarm = !!(ret & 0x40);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_NET_DSA_HWMON */
|
||||
|
||||
static int mv88e6352_setup(struct dsa_switch *ds)
|
||||
{
|
||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||
|
|
@ -171,8 +123,9 @@ static int mv88e6352_read_eeprom_word(struct dsa_switch *ds, int addr)
|
|||
|
||||
mutex_lock(&ps->eeprom_mutex);
|
||||
|
||||
ret = mv88e6xxx_reg_write(ds, REG_GLOBAL2, 0x14,
|
||||
0xc000 | (addr & 0xff));
|
||||
ret = mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_EEPROM_OP,
|
||||
GLOBAL2_EEPROM_OP_READ |
|
||||
(addr & GLOBAL2_EEPROM_OP_ADDR_MASK));
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
|
|
@ -180,7 +133,7 @@ static int mv88e6352_read_eeprom_word(struct dsa_switch *ds, int addr)
|
|||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
ret = mv88e6xxx_reg_read(ds, REG_GLOBAL2, 0x15);
|
||||
ret = mv88e6xxx_reg_read(ds, REG_GLOBAL2, GLOBAL2_EEPROM_DATA);
|
||||
error:
|
||||
mutex_unlock(&ps->eeprom_mutex);
|
||||
return ret;
|
||||
|
|
@ -253,11 +206,11 @@ static int mv88e6352_eeprom_is_readonly(struct dsa_switch *ds)
|
|||
{
|
||||
int ret;
|
||||
|
||||
ret = mv88e6xxx_reg_read(ds, REG_GLOBAL2, 0x14);
|
||||
ret = mv88e6xxx_reg_read(ds, REG_GLOBAL2, GLOBAL2_EEPROM_OP);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (!(ret & 0x0400))
|
||||
if (!(ret & GLOBAL2_EEPROM_OP_WRITE_EN))
|
||||
return -EROFS;
|
||||
|
||||
return 0;
|
||||
|
|
@ -271,12 +224,13 @@ static int mv88e6352_write_eeprom_word(struct dsa_switch *ds, int addr,
|
|||
|
||||
mutex_lock(&ps->eeprom_mutex);
|
||||
|
||||
ret = mv88e6xxx_reg_write(ds, REG_GLOBAL2, 0x15, data);
|
||||
ret = mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_EEPROM_DATA, data);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
ret = mv88e6xxx_reg_write(ds, REG_GLOBAL2, 0x14,
|
||||
0xb000 | (addr & 0xff));
|
||||
ret = mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_EEPROM_OP,
|
||||
GLOBAL2_EEPROM_OP_WRITE |
|
||||
(addr & GLOBAL2_EEPROM_OP_ADDR_MASK));
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
|
|
@ -374,13 +328,14 @@ struct dsa_switch_driver mv88e6352_switch_driver = {
|
|||
.get_strings = mv88e6xxx_get_strings,
|
||||
.get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
|
||||
.get_sset_count = mv88e6xxx_get_sset_count,
|
||||
.adjust_link = mv88e6xxx_adjust_link,
|
||||
.set_eee = mv88e6xxx_set_eee,
|
||||
.get_eee = mv88e6xxx_get_eee,
|
||||
#ifdef CONFIG_NET_DSA_HWMON
|
||||
.get_temp = mv88e6352_get_temp,
|
||||
.get_temp_limit = mv88e6352_get_temp_limit,
|
||||
.set_temp_limit = mv88e6352_set_temp_limit,
|
||||
.get_temp_alarm = mv88e6352_get_temp_alarm,
|
||||
.get_temp = mv88e6xxx_get_temp,
|
||||
.get_temp_limit = mv88e6xxx_get_temp_limit,
|
||||
.set_temp_limit = mv88e6xxx_set_temp_limit,
|
||||
.get_temp_alarm = mv88e6xxx_get_temp_alarm,
|
||||
#endif
|
||||
.get_eeprom = mv88e6352_get_eeprom,
|
||||
.set_eeprom = mv88e6352_set_eeprom,
|
||||
|
|
@ -389,10 +344,18 @@ struct dsa_switch_driver mv88e6352_switch_driver = {
|
|||
.port_join_bridge = mv88e6xxx_join_bridge,
|
||||
.port_leave_bridge = mv88e6xxx_leave_bridge,
|
||||
.port_stp_update = mv88e6xxx_port_stp_update,
|
||||
.fdb_add = mv88e6xxx_port_fdb_add,
|
||||
.fdb_del = mv88e6xxx_port_fdb_del,
|
||||
.fdb_getnext = mv88e6xxx_port_fdb_getnext,
|
||||
.port_pvid_get = mv88e6xxx_port_pvid_get,
|
||||
.port_pvid_set = mv88e6xxx_port_pvid_set,
|
||||
.port_vlan_add = mv88e6xxx_port_vlan_add,
|
||||
.port_vlan_del = mv88e6xxx_port_vlan_del,
|
||||
.vlan_getnext = mv88e6xxx_vlan_getnext,
|
||||
.port_fdb_add = mv88e6xxx_port_fdb_add,
|
||||
.port_fdb_del = mv88e6xxx_port_fdb_del,
|
||||
.port_fdb_getnext = mv88e6xxx_port_fdb_getnext,
|
||||
};
|
||||
|
||||
MODULE_ALIAS("platform:mv88e6352");
|
||||
MODULE_ALIAS("platform:mv88e6172");
|
||||
MODULE_ALIAS("platform:mv88e6176");
|
||||
MODULE_ALIAS("platform:mv88e6320");
|
||||
MODULE_ALIAS("platform:mv88e6321");
|
||||
MODULE_ALIAS("platform:mv88e6352");
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -11,6 +11,8 @@
|
|||
#ifndef __MV88E6XXX_H
|
||||
#define __MV88E6XXX_H
|
||||
|
||||
#include <linux/if_vlan.h>
|
||||
|
||||
#ifndef UINT64_MAX
|
||||
#define UINT64_MAX (u64)(~((u64)0))
|
||||
#endif
|
||||
|
|
@ -44,6 +46,8 @@
|
|||
#define PORT_STATUS_TX_PAUSED BIT(5)
|
||||
#define PORT_STATUS_FLOW_CTRL BIT(4)
|
||||
#define PORT_PCS_CTRL 0x01
|
||||
#define PORT_PCS_CTRL_RGMII_DELAY_RXCLK BIT(15)
|
||||
#define PORT_PCS_CTRL_RGMII_DELAY_TXCLK BIT(14)
|
||||
#define PORT_PCS_CTRL_FC BIT(7)
|
||||
#define PORT_PCS_CTRL_FORCE_FC BIT(6)
|
||||
#define PORT_PCS_CTRL_LINK_UP BIT(5)
|
||||
|
|
@ -89,7 +93,12 @@
|
|||
#define PORT_SWITCH_ID_6182 0x1a60
|
||||
#define PORT_SWITCH_ID_6185 0x1a70
|
||||
#define PORT_SWITCH_ID_6240 0x2400
|
||||
#define PORT_SWITCH_ID_6320 0x1250
|
||||
#define PORT_SWITCH_ID_6320 0x1150
|
||||
#define PORT_SWITCH_ID_6320_A1 0x1151
|
||||
#define PORT_SWITCH_ID_6320_A2 0x1152
|
||||
#define PORT_SWITCH_ID_6321 0x3100
|
||||
#define PORT_SWITCH_ID_6321_A1 0x3101
|
||||
#define PORT_SWITCH_ID_6321_A2 0x3102
|
||||
#define PORT_SWITCH_ID_6350 0x3710
|
||||
#define PORT_SWITCH_ID_6351 0x3750
|
||||
#define PORT_SWITCH_ID_6352 0x3520
|
||||
|
|
@ -124,6 +133,7 @@
|
|||
#define PORT_CONTROL_1 0x05
|
||||
#define PORT_BASE_VLAN 0x06
|
||||
#define PORT_DEFAULT_VLAN 0x07
|
||||
#define PORT_DEFAULT_VLAN_MASK 0xfff
|
||||
#define PORT_CONTROL_2 0x08
|
||||
#define PORT_CONTROL_2_IGNORE_FCS BIT(15)
|
||||
#define PORT_CONTROL_2_VTU_PRI_OVERRIDE BIT(14)
|
||||
|
|
@ -132,6 +142,11 @@
|
|||
#define PORT_CONTROL_2_JUMBO_1522 (0x00 << 12)
|
||||
#define PORT_CONTROL_2_JUMBO_2048 (0x01 << 12)
|
||||
#define PORT_CONTROL_2_JUMBO_10240 (0x02 << 12)
|
||||
#define PORT_CONTROL_2_8021Q_MASK (0x03 << 10)
|
||||
#define PORT_CONTROL_2_8021Q_DISABLED (0x00 << 10)
|
||||
#define PORT_CONTROL_2_8021Q_FALLBACK (0x01 << 10)
|
||||
#define PORT_CONTROL_2_8021Q_CHECK (0x02 << 10)
|
||||
#define PORT_CONTROL_2_8021Q_SECURE (0x03 << 10)
|
||||
#define PORT_CONTROL_2_DISCARD_TAGGED BIT(9)
|
||||
#define PORT_CONTROL_2_DISCARD_UNTAGGED BIT(8)
|
||||
#define PORT_CONTROL_2_MAP_DA BIT(7)
|
||||
|
|
@ -164,6 +179,11 @@
|
|||
#define GLOBAL_MAC_01 0x01
|
||||
#define GLOBAL_MAC_23 0x02
|
||||
#define GLOBAL_MAC_45 0x03
|
||||
#define GLOBAL_ATU_FID 0x01 /* 6097 6165 6351 6352 */
|
||||
#define GLOBAL_VTU_FID 0x02 /* 6097 6165 6351 6352 */
|
||||
#define GLOBAL_VTU_FID_MASK 0xfff
|
||||
#define GLOBAL_VTU_SID 0x03 /* 6097 6165 6351 6352 */
|
||||
#define GLOBAL_VTU_SID_MASK 0x3f
|
||||
#define GLOBAL_CONTROL 0x04
|
||||
#define GLOBAL_CONTROL_SW_RESET BIT(15)
|
||||
#define GLOBAL_CONTROL_PPU_ENABLE BIT(14)
|
||||
|
|
@ -180,10 +200,27 @@
|
|||
#define GLOBAL_CONTROL_TCAM_EN BIT(1)
|
||||
#define GLOBAL_CONTROL_EEPROM_DONE_EN BIT(0)
|
||||
#define GLOBAL_VTU_OP 0x05
|
||||
#define GLOBAL_VTU_OP_BUSY BIT(15)
|
||||
#define GLOBAL_VTU_OP_FLUSH_ALL ((0x01 << 12) | GLOBAL_VTU_OP_BUSY)
|
||||
#define GLOBAL_VTU_OP_VTU_LOAD_PURGE ((0x03 << 12) | GLOBAL_VTU_OP_BUSY)
|
||||
#define GLOBAL_VTU_OP_VTU_GET_NEXT ((0x04 << 12) | GLOBAL_VTU_OP_BUSY)
|
||||
#define GLOBAL_VTU_OP_STU_LOAD_PURGE ((0x05 << 12) | GLOBAL_VTU_OP_BUSY)
|
||||
#define GLOBAL_VTU_OP_STU_GET_NEXT ((0x06 << 12) | GLOBAL_VTU_OP_BUSY)
|
||||
#define GLOBAL_VTU_VID 0x06
|
||||
#define GLOBAL_VTU_VID_MASK 0xfff
|
||||
#define GLOBAL_VTU_VID_VALID BIT(12)
|
||||
#define GLOBAL_VTU_DATA_0_3 0x07
|
||||
#define GLOBAL_VTU_DATA_4_7 0x08
|
||||
#define GLOBAL_VTU_DATA_8_11 0x09
|
||||
#define GLOBAL_VTU_STU_DATA_MASK 0x03
|
||||
#define GLOBAL_VTU_DATA_MEMBER_TAG_UNMODIFIED 0x00
|
||||
#define GLOBAL_VTU_DATA_MEMBER_TAG_UNTAGGED 0x01
|
||||
#define GLOBAL_VTU_DATA_MEMBER_TAG_TAGGED 0x02
|
||||
#define GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER 0x03
|
||||
#define GLOBAL_STU_DATA_PORT_STATE_DISABLED 0x00
|
||||
#define GLOBAL_STU_DATA_PORT_STATE_BLOCKING 0x01
|
||||
#define GLOBAL_STU_DATA_PORT_STATE_LEARNING 0x02
|
||||
#define GLOBAL_STU_DATA_PORT_STATE_FORWARDING 0x03
|
||||
#define GLOBAL_ATU_CONTROL 0x0a
|
||||
#define GLOBAL_ATU_CONTROL_LEARN2ALL BIT(3)
|
||||
#define GLOBAL_ATU_OP 0x0b
|
||||
|
|
@ -198,6 +235,8 @@
|
|||
#define GLOBAL_ATU_OP_GET_CLR_VIOLATION ((7 << 12) | GLOBAL_ATU_OP_BUSY)
|
||||
#define GLOBAL_ATU_DATA 0x0c
|
||||
#define GLOBAL_ATU_DATA_TRUNK BIT(15)
|
||||
#define GLOBAL_ATU_DATA_TRUNK_ID_MASK 0x00f0
|
||||
#define GLOBAL_ATU_DATA_TRUNK_ID_SHIFT 4
|
||||
#define GLOBAL_ATU_DATA_PORT_VECTOR_MASK 0x3ff0
|
||||
#define GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT 4
|
||||
#define GLOBAL_ATU_DATA_STATE_MASK 0x0f
|
||||
|
|
@ -280,8 +319,12 @@
|
|||
#define GLOBAL2_PRIO_OVERRIDE_FORCE_ARP BIT(3)
|
||||
#define GLOBAL2_PRIO_OVERRIDE_ARP_SHIFT 0
|
||||
#define GLOBAL2_EEPROM_OP 0x14
|
||||
#define GLOBAL2_EEPROM_OP_BUSY BIT(15)
|
||||
#define GLOBAL2_EEPROM_OP_LOAD BIT(11)
|
||||
#define GLOBAL2_EEPROM_OP_BUSY BIT(15)
|
||||
#define GLOBAL2_EEPROM_OP_WRITE ((3 << 12) | GLOBAL2_EEPROM_OP_BUSY)
|
||||
#define GLOBAL2_EEPROM_OP_READ ((4 << 12) | GLOBAL2_EEPROM_OP_BUSY)
|
||||
#define GLOBAL2_EEPROM_OP_LOAD BIT(11)
|
||||
#define GLOBAL2_EEPROM_OP_WRITE_EN BIT(10)
|
||||
#define GLOBAL2_EEPROM_OP_ADDR_MASK 0xff
|
||||
#define GLOBAL2_EEPROM_DATA 0x15
|
||||
#define GLOBAL2_PTP_AVB_OP 0x16
|
||||
#define GLOBAL2_PTP_AVB_DATA 0x17
|
||||
|
|
@ -304,6 +347,25 @@
|
|||
#define GLOBAL2_QOS_WEIGHT 0x1c
|
||||
#define GLOBAL2_MISC 0x1d
|
||||
|
||||
struct mv88e6xxx_atu_entry {
|
||||
u16 fid;
|
||||
u8 state;
|
||||
bool trunk;
|
||||
u16 portv_trunkid;
|
||||
u8 mac[ETH_ALEN];
|
||||
};
|
||||
|
||||
struct mv88e6xxx_vtu_stu_entry {
|
||||
/* VTU only */
|
||||
u16 vid;
|
||||
u16 fid;
|
||||
|
||||
/* VTU and STU */
|
||||
u8 sid;
|
||||
bool valid;
|
||||
u8 data[DSA_MAX_PORTS];
|
||||
};
|
||||
|
||||
struct mv88e6xxx_priv_state {
|
||||
/* When using multi-chip addressing, this mutex protects
|
||||
* access to the indirect access registers. (In single-chip
|
||||
|
|
@ -342,9 +404,9 @@ struct mv88e6xxx_priv_state {
|
|||
|
||||
/* hw bridging */
|
||||
|
||||
u32 fid_mask;
|
||||
u8 fid[DSA_MAX_PORTS];
|
||||
u16 bridge_mask[DSA_MAX_PORTS];
|
||||
DECLARE_BITMAP(fid_bitmap, VLAN_N_VID); /* FIDs 1 to 4095 available */
|
||||
u16 fid[DSA_MAX_PORTS]; /* per (non-bridged) port FID */
|
||||
u16 bridge_mask[DSA_MAX_PORTS]; /* br groups (indexed by FID) */
|
||||
|
||||
unsigned long port_state_update_mask;
|
||||
u8 port_state[DSA_MAX_PORTS];
|
||||
|
|
@ -386,10 +448,15 @@ void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port,
|
|||
uint64_t *data);
|
||||
int mv88e6xxx_get_sset_count(struct dsa_switch *ds);
|
||||
int mv88e6xxx_get_sset_count_basic(struct dsa_switch *ds);
|
||||
void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
|
||||
struct phy_device *phydev);
|
||||
int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port);
|
||||
void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
|
||||
struct ethtool_regs *regs, void *_p);
|
||||
int mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp);
|
||||
int mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp);
|
||||
int mv88e6xxx_get_temp_limit(struct dsa_switch *ds, int *temp);
|
||||
int mv88e6xxx_set_temp_limit(struct dsa_switch *ds, int temp);
|
||||
int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm);
|
||||
int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds);
|
||||
int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds);
|
||||
int mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int addr, int regnum);
|
||||
|
|
@ -401,15 +468,23 @@ int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
|
|||
int mv88e6xxx_join_bridge(struct dsa_switch *ds, int port, u32 br_port_mask);
|
||||
int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask);
|
||||
int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state);
|
||||
int mv88e6xxx_port_pvid_get(struct dsa_switch *ds, int port, u16 *vid);
|
||||
int mv88e6xxx_port_pvid_set(struct dsa_switch *ds, int port, u16 vid);
|
||||
int mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, u16 vid,
|
||||
bool untagged);
|
||||
int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, u16 vid);
|
||||
int mv88e6xxx_vlan_getnext(struct dsa_switch *ds, u16 *vid,
|
||||
unsigned long *ports, unsigned long *untagged);
|
||||
int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
|
||||
const unsigned char *addr, u16 vid);
|
||||
int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
|
||||
const unsigned char *addr, u16 vid);
|
||||
int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port,
|
||||
unsigned char *addr, bool *is_static);
|
||||
unsigned char *addr, u16 *vid, bool *is_static);
|
||||
int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg);
|
||||
int mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page,
|
||||
int reg, int val);
|
||||
|
||||
extern struct dsa_switch_driver mv88e6131_switch_driver;
|
||||
extern struct dsa_switch_driver mv88e6123_61_65_switch_driver;
|
||||
extern struct dsa_switch_driver mv88e6352_switch_driver;
|
||||
|
|
|
|||
|
|
@ -144,10 +144,9 @@ static void dummy_setup(struct net_device *dev)
|
|||
dev->destructor = free_netdev;
|
||||
|
||||
/* Fill in device structure with ethernet-generic values. */
|
||||
dev->tx_queue_len = 0;
|
||||
dev->flags |= IFF_NOARP;
|
||||
dev->flags &= ~IFF_MULTICAST;
|
||||
dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
|
||||
dev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_NO_QUEUE;
|
||||
dev->features |= NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO;
|
||||
dev->features |= NETIF_F_HW_CSUM | NETIF_F_HIGHDMA | NETIF_F_LLTX;
|
||||
eth_hw_addr_random(dev);
|
||||
|
|
|
|||
|
|
@ -1726,6 +1726,7 @@ vortex_up(struct net_device *dev)
|
|||
if (vp->cb_fn_base) /* The PCMCIA people are idiots. */
|
||||
iowrite32(0x8000, vp->cb_fn_base + 4);
|
||||
netif_start_queue (dev);
|
||||
netdev_reset_queue(dev);
|
||||
err_out:
|
||||
return err;
|
||||
}
|
||||
|
|
@ -1935,16 +1936,18 @@ static void vortex_tx_timeout(struct net_device *dev)
|
|||
if (vp->cur_tx - vp->dirty_tx > 0 && ioread32(ioaddr + DownListPtr) == 0)
|
||||
iowrite32(vp->tx_ring_dma + (vp->dirty_tx % TX_RING_SIZE) * sizeof(struct boom_tx_desc),
|
||||
ioaddr + DownListPtr);
|
||||
if (vp->cur_tx - vp->dirty_tx < TX_RING_SIZE)
|
||||
if (vp->cur_tx - vp->dirty_tx < TX_RING_SIZE) {
|
||||
netif_wake_queue (dev);
|
||||
netdev_reset_queue (dev);
|
||||
}
|
||||
if (vp->drv_flags & IS_BOOMERANG)
|
||||
iowrite8(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold);
|
||||
iowrite16(DownUnstall, ioaddr + EL3_CMD);
|
||||
} else {
|
||||
dev->stats.tx_dropped++;
|
||||
netif_wake_queue(dev);
|
||||
netdev_reset_queue(dev);
|
||||
}
|
||||
|
||||
/* Issue Tx Enable */
|
||||
iowrite16(TxEnable, ioaddr + EL3_CMD);
|
||||
dev->trans_start = jiffies; /* prevent tx timeout */
|
||||
|
|
@ -2063,6 +2066,7 @@ vortex_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
{
|
||||
struct vortex_private *vp = netdev_priv(dev);
|
||||
void __iomem *ioaddr = vp->ioaddr;
|
||||
int skblen = skb->len;
|
||||
|
||||
/* Put out the doubleword header... */
|
||||
iowrite32(skb->len, ioaddr + TX_FIFO);
|
||||
|
|
@ -2094,6 +2098,7 @@ vortex_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
}
|
||||
}
|
||||
|
||||
netdev_sent_queue(dev, skblen);
|
||||
|
||||
/* Clear the Tx status stack. */
|
||||
{
|
||||
|
|
@ -2125,6 +2130,7 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
void __iomem *ioaddr = vp->ioaddr;
|
||||
/* Calculate the next Tx descriptor entry. */
|
||||
int entry = vp->cur_tx % TX_RING_SIZE;
|
||||
int skblen = skb->len;
|
||||
struct boom_tx_desc *prev_entry = &vp->tx_ring[(vp->cur_tx-1) % TX_RING_SIZE];
|
||||
unsigned long flags;
|
||||
dma_addr_t dma_addr;
|
||||
|
|
@ -2230,6 +2236,8 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
}
|
||||
|
||||
vp->cur_tx++;
|
||||
netdev_sent_queue(dev, skblen);
|
||||
|
||||
if (vp->cur_tx - vp->dirty_tx > TX_RING_SIZE - 1) {
|
||||
netif_stop_queue (dev);
|
||||
} else { /* Clear previous interrupt enable. */
|
||||
|
|
@ -2267,6 +2275,7 @@ vortex_interrupt(int irq, void *dev_id)
|
|||
int status;
|
||||
int work_done = max_interrupt_work;
|
||||
int handled = 0;
|
||||
unsigned int bytes_compl = 0, pkts_compl = 0;
|
||||
|
||||
ioaddr = vp->ioaddr;
|
||||
spin_lock(&vp->lock);
|
||||
|
|
@ -2314,6 +2323,8 @@ vortex_interrupt(int irq, void *dev_id)
|
|||
if (ioread16(ioaddr + Wn7_MasterStatus) & 0x1000) {
|
||||
iowrite16(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */
|
||||
pci_unmap_single(VORTEX_PCI(vp), vp->tx_skb_dma, (vp->tx_skb->len + 3) & ~3, PCI_DMA_TODEVICE);
|
||||
pkts_compl++;
|
||||
bytes_compl += vp->tx_skb->len;
|
||||
dev_kfree_skb_irq(vp->tx_skb); /* Release the transferred buffer */
|
||||
if (ioread16(ioaddr + TxFree) > 1536) {
|
||||
/*
|
||||
|
|
@ -2358,6 +2369,7 @@ vortex_interrupt(int irq, void *dev_id)
|
|||
iowrite16(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
|
||||
} while ((status = ioread16(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete));
|
||||
|
||||
netdev_completed_queue(dev, pkts_compl, bytes_compl);
|
||||
spin_unlock(&vp->window_lock);
|
||||
|
||||
if (vortex_debug > 4)
|
||||
|
|
@ -2382,6 +2394,7 @@ boomerang_interrupt(int irq, void *dev_id)
|
|||
int status;
|
||||
int work_done = max_interrupt_work;
|
||||
int handled = 0;
|
||||
unsigned int bytes_compl = 0, pkts_compl = 0;
|
||||
|
||||
ioaddr = vp->ioaddr;
|
||||
|
||||
|
|
@ -2455,6 +2468,8 @@ boomerang_interrupt(int irq, void *dev_id)
|
|||
pci_unmap_single(VORTEX_PCI(vp),
|
||||
le32_to_cpu(vp->tx_ring[entry].addr), skb->len, PCI_DMA_TODEVICE);
|
||||
#endif
|
||||
pkts_compl++;
|
||||
bytes_compl += skb->len;
|
||||
dev_kfree_skb_irq(skb);
|
||||
vp->tx_skbuff[entry] = NULL;
|
||||
} else {
|
||||
|
|
@ -2495,6 +2510,7 @@ boomerang_interrupt(int irq, void *dev_id)
|
|||
iowrite32(0x8000, vp->cb_fn_base + 4);
|
||||
|
||||
} while ((status = ioread16(ioaddr + EL3_STATUS)) & IntLatch);
|
||||
netdev_completed_queue(dev, pkts_compl, bytes_compl);
|
||||
|
||||
if (vortex_debug > 4)
|
||||
pr_debug("%s: exiting interrupt, status %4.4x.\n",
|
||||
|
|
@ -2696,7 +2712,8 @@ vortex_down(struct net_device *dev, int final_down)
|
|||
struct vortex_private *vp = netdev_priv(dev);
|
||||
void __iomem *ioaddr = vp->ioaddr;
|
||||
|
||||
netif_stop_queue (dev);
|
||||
netdev_reset_queue(dev);
|
||||
netif_stop_queue(dev);
|
||||
|
||||
del_timer_sync(&vp->rx_oom_timer);
|
||||
del_timer_sync(&vp->timer);
|
||||
|
|
|
|||
|
|
@ -167,6 +167,7 @@ source "drivers/net/ethernet/sgi/Kconfig"
|
|||
source "drivers/net/ethernet/smsc/Kconfig"
|
||||
source "drivers/net/ethernet/stmicro/Kconfig"
|
||||
source "drivers/net/ethernet/sun/Kconfig"
|
||||
source "drivers/net/ethernet/synopsys/Kconfig"
|
||||
source "drivers/net/ethernet/tehuti/Kconfig"
|
||||
source "drivers/net/ethernet/ti/Kconfig"
|
||||
source "drivers/net/ethernet/tile/Kconfig"
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ obj-$(CONFIG_NET_VENDOR_SGI) += sgi/
|
|||
obj-$(CONFIG_NET_VENDOR_SMSC) += smsc/
|
||||
obj-$(CONFIG_NET_VENDOR_STMICRO) += stmicro/
|
||||
obj-$(CONFIG_NET_VENDOR_SUN) += sun/
|
||||
obj-$(CONFIG_NET_VENDOR_SYNOPSYS) += synopsys/
|
||||
obj-$(CONFIG_NET_VENDOR_TEHUTI) += tehuti/
|
||||
obj-$(CONFIG_NET_VENDOR_TI) += ti/
|
||||
obj-$(CONFIG_TILE_NET) += tile/
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/soc/sunxi/sunxi_sram.h>
|
||||
|
||||
#include "sun4i-emac.h"
|
||||
|
||||
|
|
@ -857,11 +858,17 @@ static int emac_probe(struct platform_device *pdev)
|
|||
|
||||
clk_prepare_enable(db->clk);
|
||||
|
||||
ret = sunxi_sram_claim(&pdev->dev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Error couldn't map SRAM to device\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
db->phy_node = of_parse_phandle(np, "phy", 0);
|
||||
if (!db->phy_node) {
|
||||
dev_err(&pdev->dev, "no associated PHY\n");
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
goto out_release_sram;
|
||||
}
|
||||
|
||||
/* Read MAC-address from DT */
|
||||
|
|
@ -893,7 +900,7 @@ static int emac_probe(struct platform_device *pdev)
|
|||
if (ret) {
|
||||
dev_err(&pdev->dev, "Registering netdev failed!\n");
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
goto out_release_sram;
|
||||
}
|
||||
|
||||
dev_info(&pdev->dev, "%s: at %p, IRQ %d MAC: %pM\n",
|
||||
|
|
@ -901,6 +908,8 @@ static int emac_probe(struct platform_device *pdev)
|
|||
|
||||
return 0;
|
||||
|
||||
out_release_sram:
|
||||
sunxi_sram_release(&pdev->dev);
|
||||
out:
|
||||
dev_err(db->dev, "not found (%d).\n", ret);
|
||||
|
||||
|
|
|
|||
|
|
@ -71,8 +71,6 @@ int sgdma_initialize(struct altera_tse_private *priv)
|
|||
SGDMA_CTRLREG_INTEN |
|
||||
SGDMA_CTRLREG_ILASTD;
|
||||
|
||||
priv->sgdmadesclen = sizeof(struct sgdma_descrip);
|
||||
|
||||
INIT_LIST_HEAD(&priv->txlisthd);
|
||||
INIT_LIST_HEAD(&priv->rxlisthd);
|
||||
|
||||
|
|
@ -254,7 +252,7 @@ u32 sgdma_rx_status(struct altera_tse_private *priv)
|
|||
unsigned int pktstatus = 0;
|
||||
dma_sync_single_for_cpu(priv->device,
|
||||
priv->rxdescphys,
|
||||
priv->sgdmadesclen,
|
||||
SGDMA_DESC_LEN,
|
||||
DMA_FROM_DEVICE);
|
||||
|
||||
pktlength = csrrd16(desc, sgdma_descroffs(bytes_xferred));
|
||||
|
|
@ -374,7 +372,7 @@ static int sgdma_async_read(struct altera_tse_private *priv)
|
|||
|
||||
dma_sync_single_for_device(priv->device,
|
||||
priv->rxdescphys,
|
||||
priv->sgdmadesclen,
|
||||
SGDMA_DESC_LEN,
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
csrwr32(lower_32_bits(sgdma_rxphysaddr(priv, cdesc)),
|
||||
|
|
@ -402,7 +400,7 @@ static int sgdma_async_write(struct altera_tse_private *priv,
|
|||
csrwr32(0x1f, priv->tx_dma_csr, sgdma_csroffs(status));
|
||||
|
||||
dma_sync_single_for_device(priv->device, priv->txdescphys,
|
||||
priv->sgdmadesclen, DMA_TO_DEVICE);
|
||||
SGDMA_DESC_LEN, DMA_TO_DEVICE);
|
||||
|
||||
csrwr32(lower_32_bits(sgdma_txphysaddr(priv, desc)),
|
||||
priv->tx_dma_csr,
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ struct sgdma_descrip {
|
|||
u8 control;
|
||||
} __packed;
|
||||
|
||||
#define SGDMA_DESC_LEN sizeof(struct sgdma_descrip)
|
||||
|
||||
#define SGDMA_STATUS_ERR BIT(0)
|
||||
#define SGDMA_STATUS_LENGTH_ERR BIT(1)
|
||||
|
|
|
|||
|
|
@ -458,7 +458,6 @@ struct altera_tse_private {
|
|||
u32 rxctrlreg;
|
||||
dma_addr_t rxdescphys;
|
||||
dma_addr_t txdescphys;
|
||||
size_t sgdmadesclen;
|
||||
|
||||
struct list_head txlisthd;
|
||||
struct list_head rxlisthd;
|
||||
|
|
|
|||
|
|
@ -193,12 +193,16 @@ enum xgene_enet_rm {
|
|||
#define USERINFO_LEN 32
|
||||
#define FPQNUM_POS 32
|
||||
#define FPQNUM_LEN 12
|
||||
#define NV_POS 50
|
||||
#define NV_LEN 1
|
||||
#define LL_POS 51
|
||||
#define LL_LEN 1
|
||||
#define LERR_POS 60
|
||||
#define LERR_LEN 3
|
||||
#define STASH_POS 52
|
||||
#define STASH_LEN 2
|
||||
#define BUFDATALEN_POS 48
|
||||
#define BUFDATALEN_LEN 12
|
||||
#define BUFDATALEN_LEN 15
|
||||
#define DATAADDR_POS 0
|
||||
#define DATAADDR_LEN 42
|
||||
#define COHERENT_POS 63
|
||||
|
|
@ -215,9 +219,19 @@ enum xgene_enet_rm {
|
|||
#define IPHDR_LEN 6
|
||||
#define EC_POS 22 /* Enable checksum */
|
||||
#define EC_LEN 1
|
||||
#define ET_POS 23 /* Enable TSO */
|
||||
#define IS_POS 24 /* IP protocol select */
|
||||
#define IS_LEN 1
|
||||
#define TYPE_ETH_WORK_MESSAGE_POS 44
|
||||
#define LL_BYTES_MSB_POS 56
|
||||
#define LL_BYTES_MSB_LEN 8
|
||||
#define LL_BYTES_LSB_POS 48
|
||||
#define LL_BYTES_LSB_LEN 12
|
||||
#define LL_LEN_POS 48
|
||||
#define LL_LEN_LEN 8
|
||||
#define DATALEN_MASK GENMASK(11, 0)
|
||||
|
||||
#define LAST_BUFFER (0x7800ULL << BUFDATALEN_POS)
|
||||
|
||||
struct xgene_enet_raw_desc {
|
||||
__le64 m0;
|
||||
|
|
|
|||
|
|
@ -147,18 +147,27 @@ static int xgene_enet_tx_completion(struct xgene_enet_desc_ring *cp_ring,
|
|||
{
|
||||
struct sk_buff *skb;
|
||||
struct device *dev;
|
||||
skb_frag_t *frag;
|
||||
dma_addr_t *frag_dma_addr;
|
||||
u16 skb_index;
|
||||
u8 status;
|
||||
int ret = 0;
|
||||
int i, ret = 0;
|
||||
|
||||
skb_index = GET_VAL(USERINFO, le64_to_cpu(raw_desc->m0));
|
||||
skb = cp_ring->cp_skb[skb_index];
|
||||
frag_dma_addr = &cp_ring->frag_dma_addr[skb_index * MAX_SKB_FRAGS];
|
||||
|
||||
dev = ndev_to_dev(cp_ring->ndev);
|
||||
dma_unmap_single(dev, GET_VAL(DATAADDR, le64_to_cpu(raw_desc->m1)),
|
||||
GET_VAL(BUFDATALEN, le64_to_cpu(raw_desc->m1)),
|
||||
skb_headlen(skb),
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
|
||||
frag = &skb_shinfo(skb)->frags[i];
|
||||
dma_unmap_page(dev, frag_dma_addr[i], skb_frag_size(frag),
|
||||
DMA_TO_DEVICE);
|
||||
}
|
||||
|
||||
/* Checking for error */
|
||||
status = GET_VAL(LERR, le64_to_cpu(raw_desc->m0));
|
||||
if (unlikely(status > 2)) {
|
||||
|
|
@ -179,12 +188,16 @@ static int xgene_enet_tx_completion(struct xgene_enet_desc_ring *cp_ring,
|
|||
|
||||
static u64 xgene_enet_work_msg(struct sk_buff *skb)
|
||||
{
|
||||
struct net_device *ndev = skb->dev;
|
||||
struct xgene_enet_pdata *pdata = netdev_priv(ndev);
|
||||
struct iphdr *iph;
|
||||
u8 l3hlen, l4hlen = 0;
|
||||
u8 csum_enable = 0;
|
||||
u8 proto = 0;
|
||||
u8 ethhdr;
|
||||
u64 hopinfo;
|
||||
u8 l3hlen = 0, l4hlen = 0;
|
||||
u8 ethhdr, proto = 0, csum_enable = 0;
|
||||
u64 hopinfo = 0;
|
||||
u32 hdr_len, mss = 0;
|
||||
u32 i, len, nr_frags;
|
||||
|
||||
ethhdr = xgene_enet_hdr_len(skb->data);
|
||||
|
||||
if (unlikely(skb->protocol != htons(ETH_P_IP)) &&
|
||||
unlikely(skb->protocol != htons(ETH_P_8021Q)))
|
||||
|
|
@ -201,14 +214,40 @@ static u64 xgene_enet_work_msg(struct sk_buff *skb)
|
|||
l4hlen = tcp_hdrlen(skb) >> 2;
|
||||
csum_enable = 1;
|
||||
proto = TSO_IPPROTO_TCP;
|
||||
if (ndev->features & NETIF_F_TSO) {
|
||||
hdr_len = ethhdr + ip_hdrlen(skb) + tcp_hdrlen(skb);
|
||||
mss = skb_shinfo(skb)->gso_size;
|
||||
|
||||
if (skb_is_nonlinear(skb)) {
|
||||
len = skb_headlen(skb);
|
||||
nr_frags = skb_shinfo(skb)->nr_frags;
|
||||
|
||||
for (i = 0; i < 2 && i < nr_frags; i++)
|
||||
len += skb_shinfo(skb)->frags[i].size;
|
||||
|
||||
/* HW requires header must reside in 3 buffer */
|
||||
if (unlikely(hdr_len > len)) {
|
||||
if (skb_linearize(skb))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mss || ((skb->len - hdr_len) <= mss))
|
||||
goto out;
|
||||
|
||||
if (mss != pdata->mss) {
|
||||
pdata->mss = mss;
|
||||
pdata->mac_ops->set_mss(pdata);
|
||||
}
|
||||
hopinfo |= SET_BIT(ET);
|
||||
}
|
||||
} else if (iph->protocol == IPPROTO_UDP) {
|
||||
l4hlen = UDP_HDR_SIZE;
|
||||
csum_enable = 1;
|
||||
}
|
||||
out:
|
||||
l3hlen = ip_hdrlen(skb) >> 2;
|
||||
ethhdr = xgene_enet_hdr_len(skb->data);
|
||||
hopinfo = SET_VAL(TCPHDR, l4hlen) |
|
||||
hopinfo |= SET_VAL(TCPHDR, l4hlen) |
|
||||
SET_VAL(IPHDR, l3hlen) |
|
||||
SET_VAL(ETHHDR, ethhdr) |
|
||||
SET_VAL(EC, csum_enable) |
|
||||
|
|
@ -219,35 +258,170 @@ out:
|
|||
return hopinfo;
|
||||
}
|
||||
|
||||
static u16 xgene_enet_encode_len(u16 len)
|
||||
{
|
||||
return (len == BUFLEN_16K) ? 0 : len;
|
||||
}
|
||||
|
||||
static void xgene_set_addr_len(__le64 *desc, u32 idx, dma_addr_t addr, u32 len)
|
||||
{
|
||||
desc[idx ^ 1] = cpu_to_le64(SET_VAL(DATAADDR, addr) |
|
||||
SET_VAL(BUFDATALEN, len));
|
||||
}
|
||||
|
||||
static __le64 *xgene_enet_get_exp_bufs(struct xgene_enet_desc_ring *ring)
|
||||
{
|
||||
__le64 *exp_bufs;
|
||||
|
||||
exp_bufs = &ring->exp_bufs[ring->exp_buf_tail * MAX_EXP_BUFFS];
|
||||
memset(exp_bufs, 0, sizeof(__le64) * MAX_EXP_BUFFS);
|
||||
ring->exp_buf_tail = (ring->exp_buf_tail + 1) & ((ring->slots / 2) - 1);
|
||||
|
||||
return exp_bufs;
|
||||
}
|
||||
|
||||
static dma_addr_t *xgene_get_frag_dma_array(struct xgene_enet_desc_ring *ring)
|
||||
{
|
||||
return &ring->cp_ring->frag_dma_addr[ring->tail * MAX_SKB_FRAGS];
|
||||
}
|
||||
|
||||
static int xgene_enet_setup_tx_desc(struct xgene_enet_desc_ring *tx_ring,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct device *dev = ndev_to_dev(tx_ring->ndev);
|
||||
struct xgene_enet_raw_desc *raw_desc;
|
||||
dma_addr_t dma_addr;
|
||||
__le64 *exp_desc = NULL, *exp_bufs = NULL;
|
||||
dma_addr_t dma_addr, pbuf_addr, *frag_dma_addr;
|
||||
skb_frag_t *frag;
|
||||
u16 tail = tx_ring->tail;
|
||||
u64 hopinfo;
|
||||
u32 len, hw_len;
|
||||
u8 ll = 0, nv = 0, idx = 0;
|
||||
bool split = false;
|
||||
u32 size, offset, ell_bytes = 0;
|
||||
u32 i, fidx, nr_frags, count = 1;
|
||||
|
||||
raw_desc = &tx_ring->raw_desc[tail];
|
||||
tail = (tail + 1) & (tx_ring->slots - 1);
|
||||
memset(raw_desc, 0, sizeof(struct xgene_enet_raw_desc));
|
||||
|
||||
dma_addr = dma_map_single(dev, skb->data, skb->len, DMA_TO_DEVICE);
|
||||
hopinfo = xgene_enet_work_msg(skb);
|
||||
if (!hopinfo)
|
||||
return -EINVAL;
|
||||
raw_desc->m3 = cpu_to_le64(SET_VAL(HENQNUM, tx_ring->dst_ring_num) |
|
||||
hopinfo);
|
||||
|
||||
len = skb_headlen(skb);
|
||||
hw_len = xgene_enet_encode_len(len);
|
||||
|
||||
dma_addr = dma_map_single(dev, skb->data, len, DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(dev, dma_addr)) {
|
||||
netdev_err(tx_ring->ndev, "DMA mapping error\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Hardware expects descriptor in little endian format */
|
||||
raw_desc->m0 = cpu_to_le64(tail);
|
||||
raw_desc->m1 = cpu_to_le64(SET_VAL(DATAADDR, dma_addr) |
|
||||
SET_VAL(BUFDATALEN, skb->len) |
|
||||
SET_VAL(BUFDATALEN, hw_len) |
|
||||
SET_BIT(COHERENT));
|
||||
hopinfo = xgene_enet_work_msg(skb);
|
||||
raw_desc->m3 = cpu_to_le64(SET_VAL(HENQNUM, tx_ring->dst_ring_num) |
|
||||
hopinfo);
|
||||
tx_ring->cp_ring->cp_skb[tail] = skb;
|
||||
|
||||
return 0;
|
||||
if (!skb_is_nonlinear(skb))
|
||||
goto out;
|
||||
|
||||
/* scatter gather */
|
||||
nv = 1;
|
||||
exp_desc = (void *)&tx_ring->raw_desc[tail];
|
||||
tail = (tail + 1) & (tx_ring->slots - 1);
|
||||
memset(exp_desc, 0, sizeof(struct xgene_enet_raw_desc));
|
||||
|
||||
nr_frags = skb_shinfo(skb)->nr_frags;
|
||||
for (i = nr_frags; i < 4 ; i++)
|
||||
exp_desc[i ^ 1] = cpu_to_le64(LAST_BUFFER);
|
||||
|
||||
frag_dma_addr = xgene_get_frag_dma_array(tx_ring);
|
||||
|
||||
for (i = 0, fidx = 0; split || (fidx < nr_frags); i++) {
|
||||
if (!split) {
|
||||
frag = &skb_shinfo(skb)->frags[fidx];
|
||||
size = skb_frag_size(frag);
|
||||
offset = 0;
|
||||
|
||||
pbuf_addr = skb_frag_dma_map(dev, frag, 0, size,
|
||||
DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(dev, pbuf_addr))
|
||||
return -EINVAL;
|
||||
|
||||
frag_dma_addr[fidx] = pbuf_addr;
|
||||
fidx++;
|
||||
|
||||
if (size > BUFLEN_16K)
|
||||
split = true;
|
||||
}
|
||||
|
||||
if (size > BUFLEN_16K) {
|
||||
len = BUFLEN_16K;
|
||||
size -= BUFLEN_16K;
|
||||
} else {
|
||||
len = size;
|
||||
split = false;
|
||||
}
|
||||
|
||||
dma_addr = pbuf_addr + offset;
|
||||
hw_len = xgene_enet_encode_len(len);
|
||||
|
||||
switch (i) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
xgene_set_addr_len(exp_desc, i, dma_addr, hw_len);
|
||||
break;
|
||||
case 3:
|
||||
if (split || (fidx != nr_frags)) {
|
||||
exp_bufs = xgene_enet_get_exp_bufs(tx_ring);
|
||||
xgene_set_addr_len(exp_bufs, idx, dma_addr,
|
||||
hw_len);
|
||||
idx++;
|
||||
ell_bytes += len;
|
||||
} else {
|
||||
xgene_set_addr_len(exp_desc, i, dma_addr,
|
||||
hw_len);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
xgene_set_addr_len(exp_bufs, idx, dma_addr, hw_len);
|
||||
idx++;
|
||||
ell_bytes += len;
|
||||
break;
|
||||
}
|
||||
|
||||
if (split)
|
||||
offset += BUFLEN_16K;
|
||||
}
|
||||
count++;
|
||||
|
||||
if (idx) {
|
||||
ll = 1;
|
||||
dma_addr = dma_map_single(dev, exp_bufs,
|
||||
sizeof(u64) * MAX_EXP_BUFFS,
|
||||
DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(dev, dma_addr)) {
|
||||
dev_kfree_skb_any(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
i = ell_bytes >> LL_BYTES_LSB_LEN;
|
||||
exp_desc[2] = cpu_to_le64(SET_VAL(DATAADDR, dma_addr) |
|
||||
SET_VAL(LL_BYTES_MSB, i) |
|
||||
SET_VAL(LL_LEN, idx));
|
||||
raw_desc->m2 = cpu_to_le64(SET_VAL(LL_BYTES_LSB, ell_bytes));
|
||||
}
|
||||
|
||||
out:
|
||||
raw_desc->m0 = cpu_to_le64(SET_VAL(LL, ll) | SET_VAL(NV, nv) |
|
||||
SET_VAL(USERINFO, tx_ring->tail));
|
||||
tx_ring->cp_ring->cp_skb[tx_ring->tail] = skb;
|
||||
tx_ring->tail = tail;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static netdev_tx_t xgene_enet_start_xmit(struct sk_buff *skb,
|
||||
|
|
@ -257,6 +431,7 @@ static netdev_tx_t xgene_enet_start_xmit(struct sk_buff *skb,
|
|||
struct xgene_enet_desc_ring *tx_ring = pdata->tx_ring;
|
||||
struct xgene_enet_desc_ring *cp_ring = tx_ring->cp_ring;
|
||||
u32 tx_level, cq_level;
|
||||
int count;
|
||||
|
||||
tx_level = pdata->ring_ops->len(tx_ring);
|
||||
cq_level = pdata->ring_ops->len(cp_ring);
|
||||
|
|
@ -266,14 +441,17 @@ static netdev_tx_t xgene_enet_start_xmit(struct sk_buff *skb,
|
|||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
|
||||
if (xgene_enet_setup_tx_desc(tx_ring, skb)) {
|
||||
if (skb_padto(skb, XGENE_MIN_ENET_FRAME_SIZE))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
count = xgene_enet_setup_tx_desc(tx_ring, skb);
|
||||
if (count <= 0) {
|
||||
dev_kfree_skb_any(skb);
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
pdata->ring_ops->wr_cmd(tx_ring, 1);
|
||||
pdata->ring_ops->wr_cmd(tx_ring, count);
|
||||
skb_tx_timestamp(skb);
|
||||
tx_ring->tail = (tx_ring->tail + 1) & (tx_ring->slots - 1);
|
||||
|
||||
pdata->stats.tx_packets++;
|
||||
pdata->stats.tx_bytes += skb->len;
|
||||
|
|
@ -326,7 +504,7 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring,
|
|||
|
||||
/* strip off CRC as HW isn't doing this */
|
||||
datalen = GET_VAL(BUFDATALEN, le64_to_cpu(raw_desc->m1));
|
||||
datalen -= 4;
|
||||
datalen = (datalen & DATALEN_MASK) - 4;
|
||||
prefetch(skb->data - NET_IP_ALIGN);
|
||||
skb_put(skb, datalen);
|
||||
|
||||
|
|
@ -358,26 +536,41 @@ static int xgene_enet_process_ring(struct xgene_enet_desc_ring *ring,
|
|||
int budget)
|
||||
{
|
||||
struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev);
|
||||
struct xgene_enet_raw_desc *raw_desc;
|
||||
struct xgene_enet_raw_desc *raw_desc, *exp_desc;
|
||||
u16 head = ring->head;
|
||||
u16 slots = ring->slots - 1;
|
||||
int ret, count = 0;
|
||||
int ret, count = 0, processed = 0;
|
||||
|
||||
do {
|
||||
raw_desc = &ring->raw_desc[head];
|
||||
exp_desc = NULL;
|
||||
if (unlikely(xgene_enet_is_desc_slot_empty(raw_desc)))
|
||||
break;
|
||||
|
||||
/* read fpqnum field after dataaddr field */
|
||||
dma_rmb();
|
||||
if (GET_BIT(NV, le64_to_cpu(raw_desc->m0))) {
|
||||
head = (head + 1) & slots;
|
||||
exp_desc = &ring->raw_desc[head];
|
||||
|
||||
if (unlikely(xgene_enet_is_desc_slot_empty(exp_desc))) {
|
||||
head = (head - 1) & slots;
|
||||
break;
|
||||
}
|
||||
dma_rmb();
|
||||
count++;
|
||||
}
|
||||
if (is_rx_desc(raw_desc))
|
||||
ret = xgene_enet_rx_frame(ring, raw_desc);
|
||||
else
|
||||
ret = xgene_enet_tx_completion(ring, raw_desc);
|
||||
xgene_enet_mark_desc_slot_empty(raw_desc);
|
||||
if (exp_desc)
|
||||
xgene_enet_mark_desc_slot_empty(exp_desc);
|
||||
|
||||
head = (head + 1) & slots;
|
||||
count++;
|
||||
processed++;
|
||||
|
||||
if (ret)
|
||||
break;
|
||||
|
|
@ -393,7 +586,7 @@ static int xgene_enet_process_ring(struct xgene_enet_desc_ring *ring,
|
|||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
return processed;
|
||||
}
|
||||
|
||||
static int xgene_enet_napi(struct napi_struct *napi, const int budget)
|
||||
|
|
@ -738,12 +931,13 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev)
|
|||
struct xgene_enet_desc_ring *rx_ring, *tx_ring, *cp_ring;
|
||||
struct xgene_enet_desc_ring *buf_pool = NULL;
|
||||
enum xgene_ring_owner owner;
|
||||
dma_addr_t dma_exp_bufs;
|
||||
u8 cpu_bufnum = pdata->cpu_bufnum;
|
||||
u8 eth_bufnum = pdata->eth_bufnum;
|
||||
u8 bp_bufnum = pdata->bp_bufnum;
|
||||
u16 ring_num = pdata->ring_num;
|
||||
u16 ring_id;
|
||||
int ret;
|
||||
int ret, size;
|
||||
|
||||
/* allocate rx descriptor ring */
|
||||
owner = xgene_derive_ring_owner(pdata);
|
||||
|
|
@ -794,6 +988,15 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev)
|
|||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
size = (tx_ring->slots / 2) * sizeof(__le64) * MAX_EXP_BUFFS;
|
||||
tx_ring->exp_bufs = dma_zalloc_coherent(dev, size, &dma_exp_bufs,
|
||||
GFP_KERNEL);
|
||||
if (!tx_ring->exp_bufs) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
pdata->tx_ring = tx_ring;
|
||||
|
||||
if (!pdata->cq_cnt) {
|
||||
|
|
@ -818,6 +1021,16 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev)
|
|||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
size = sizeof(dma_addr_t) * MAX_SKB_FRAGS;
|
||||
cp_ring->frag_dma_addr = devm_kcalloc(dev, tx_ring->slots,
|
||||
size, GFP_KERNEL);
|
||||
if (!cp_ring->frag_dma_addr) {
|
||||
devm_kfree(dev, cp_ring->cp_skb);
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
pdata->tx_ring->cp_ring = cp_ring;
|
||||
pdata->tx_ring->dst_ring_num = xgene_enet_dst_ring_num(cp_ring);
|
||||
|
||||
|
|
@ -905,40 +1118,6 @@ static int xgene_get_port_id_dt(struct device *dev, struct xgene_enet_pdata *pda
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int xgene_get_mac_address(struct device *dev,
|
||||
unsigned char *addr)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = device_property_read_u8_array(dev, "local-mac-address", addr, 6);
|
||||
if (ret)
|
||||
ret = device_property_read_u8_array(dev, "mac-address",
|
||||
addr, 6);
|
||||
if (ret)
|
||||
return -ENODEV;
|
||||
|
||||
return ETH_ALEN;
|
||||
}
|
||||
|
||||
static int xgene_get_phy_mode(struct device *dev)
|
||||
{
|
||||
int i, ret;
|
||||
char *modestr;
|
||||
|
||||
ret = device_property_read_string(dev, "phy-connection-type",
|
||||
(const char **)&modestr);
|
||||
if (ret)
|
||||
ret = device_property_read_string(dev, "phy-mode",
|
||||
(const char **)&modestr);
|
||||
if (ret)
|
||||
return -ENODEV;
|
||||
|
||||
for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++) {
|
||||
if (!strcasecmp(modestr, phy_modes(i)))
|
||||
return i;
|
||||
}
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
|
||||
{
|
||||
|
|
@ -998,12 +1177,12 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (xgene_get_mac_address(dev, ndev->dev_addr) != ETH_ALEN)
|
||||
if (!device_get_mac_address(dev, ndev->dev_addr, ETH_ALEN))
|
||||
eth_hw_addr_random(ndev);
|
||||
|
||||
memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len);
|
||||
|
||||
pdata->phy_mode = xgene_get_phy_mode(dev);
|
||||
pdata->phy_mode = device_get_phy_mode(dev);
|
||||
if (pdata->phy_mode < 0) {
|
||||
dev_err(dev, "Unable to get phy-connection-type\n");
|
||||
return pdata->phy_mode;
|
||||
|
|
@ -1207,7 +1386,8 @@ static int xgene_enet_probe(struct platform_device *pdev)
|
|||
xgene_enet_set_ethtool_ops(ndev);
|
||||
ndev->features |= NETIF_F_IP_CSUM |
|
||||
NETIF_F_GSO |
|
||||
NETIF_F_GRO;
|
||||
NETIF_F_GRO |
|
||||
NETIF_F_SG;
|
||||
|
||||
of_id = of_match_device(xgene_enet_of_match, &pdev->dev);
|
||||
if (of_id) {
|
||||
|
|
@ -1233,6 +1413,12 @@ static int xgene_enet_probe(struct platform_device *pdev)
|
|||
|
||||
xgene_enet_setup_ops(pdata);
|
||||
|
||||
if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
|
||||
ndev->features |= NETIF_F_TSO;
|
||||
pdata->mss = XGENE_ENET_MSS;
|
||||
}
|
||||
ndev->hw_features = ndev->features;
|
||||
|
||||
ret = register_netdev(ndev);
|
||||
if (ret) {
|
||||
netdev_err(ndev, "Failed to register netdev\n");
|
||||
|
|
|
|||
|
|
@ -40,8 +40,12 @@
|
|||
#define XGENE_DRV_VERSION "v1.0"
|
||||
#define XGENE_ENET_MAX_MTU 1536
|
||||
#define SKB_BUFFER_SIZE (XGENE_ENET_MAX_MTU - NET_IP_ALIGN)
|
||||
#define BUFLEN_16K (16 * 1024)
|
||||
#define NUM_PKT_BUF 64
|
||||
#define NUM_BUFPOOL 32
|
||||
#define MAX_EXP_BUFFS 256
|
||||
#define XGENE_ENET_MSS 1448
|
||||
#define XGENE_MIN_ENET_FRAME_SIZE 60
|
||||
|
||||
#define START_CPU_BUFNUM_0 0
|
||||
#define START_ETH_BUFNUM_0 2
|
||||
|
|
@ -79,6 +83,7 @@ struct xgene_enet_desc_ring {
|
|||
u16 num;
|
||||
u16 head;
|
||||
u16 tail;
|
||||
u16 exp_buf_tail;
|
||||
u16 slots;
|
||||
u16 irq;
|
||||
char irq_name[IRQ_ID_SIZE];
|
||||
|
|
@ -93,6 +98,7 @@ struct xgene_enet_desc_ring {
|
|||
u8 nbufpool;
|
||||
struct sk_buff *(*rx_skb);
|
||||
struct sk_buff *(*cp_skb);
|
||||
dma_addr_t *frag_dma_addr;
|
||||
enum xgene_enet_ring_cfgsize cfgsize;
|
||||
struct xgene_enet_desc_ring *cp_ring;
|
||||
struct xgene_enet_desc_ring *buf_pool;
|
||||
|
|
@ -102,6 +108,7 @@ struct xgene_enet_desc_ring {
|
|||
struct xgene_enet_raw_desc *raw_desc;
|
||||
struct xgene_enet_raw_desc16 *raw_desc16;
|
||||
};
|
||||
__le64 *exp_bufs;
|
||||
};
|
||||
|
||||
struct xgene_mac_ops {
|
||||
|
|
@ -112,6 +119,7 @@ struct xgene_mac_ops {
|
|||
void (*tx_disable)(struct xgene_enet_pdata *pdata);
|
||||
void (*rx_disable)(struct xgene_enet_pdata *pdata);
|
||||
void (*set_mac_addr)(struct xgene_enet_pdata *pdata);
|
||||
void (*set_mss)(struct xgene_enet_pdata *pdata);
|
||||
void (*link_state)(struct work_struct *work);
|
||||
};
|
||||
|
||||
|
|
@ -170,6 +178,7 @@ struct xgene_enet_pdata {
|
|||
u8 eth_bufnum;
|
||||
u8 bp_bufnum;
|
||||
u16 ring_num;
|
||||
u32 mss;
|
||||
};
|
||||
|
||||
struct xgene_indirect_ctl {
|
||||
|
|
@ -204,6 +213,9 @@ static inline u64 xgene_enet_get_field_value(int pos, int len, u64 src)
|
|||
#define GET_VAL(field, src) \
|
||||
xgene_enet_get_field_value(field ## _POS, field ## _LEN, src)
|
||||
|
||||
#define GET_BIT(field, src) \
|
||||
xgene_enet_get_field_value(field ## _POS, 1, src)
|
||||
|
||||
static inline struct device *ndev_to_dev(struct net_device *ndev)
|
||||
{
|
||||
return ndev->dev.parent;
|
||||
|
|
|
|||
|
|
@ -184,6 +184,11 @@ static void xgene_xgmac_set_mac_addr(struct xgene_enet_pdata *pdata)
|
|||
xgene_enet_wr_mac(pdata, HSTMACADR_MSW_ADDR, addr1);
|
||||
}
|
||||
|
||||
static void xgene_xgmac_set_mss(struct xgene_enet_pdata *pdata)
|
||||
{
|
||||
xgene_enet_wr_csr(pdata, XG_TSIF_MSS_REG0_ADDR, pdata->mss);
|
||||
}
|
||||
|
||||
static u32 xgene_enet_link_status(struct xgene_enet_pdata *pdata)
|
||||
{
|
||||
u32 data;
|
||||
|
|
@ -204,8 +209,8 @@ static void xgene_xgmac_init(struct xgene_enet_pdata *pdata)
|
|||
data &= ~HSTLENCHK;
|
||||
xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data);
|
||||
|
||||
xgene_enet_wr_mac(pdata, HSTMAXFRAME_LENGTH_ADDR, 0x06000600);
|
||||
xgene_xgmac_set_mac_addr(pdata);
|
||||
xgene_xgmac_set_mss(pdata);
|
||||
|
||||
xgene_enet_rd_csr(pdata, XG_RSIF_CONFIG_REG_ADDR, &data);
|
||||
data |= CFG_RSIF_FPBUFF_TIMEOUT_EN;
|
||||
|
|
@ -329,6 +334,7 @@ struct xgene_mac_ops xgene_xgmac_ops = {
|
|||
.rx_disable = xgene_xgmac_rx_disable,
|
||||
.tx_disable = xgene_xgmac_tx_disable,
|
||||
.set_mac_addr = xgene_xgmac_set_mac_addr,
|
||||
.set_mss = xgene_xgmac_set_mss,
|
||||
.link_state = xgene_enet_link_state
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -62,7 +62,9 @@
|
|||
#define XCLE_BYPASS_REG0_ADDR 0x0160
|
||||
#define XCLE_BYPASS_REG1_ADDR 0x0164
|
||||
#define XG_CFG_BYPASS_ADDR 0x0204
|
||||
#define XG_CFG_LINK_AGGR_RESUME_0_ADDR 0x0214
|
||||
#define XG_LINK_STATUS_ADDR 0x0228
|
||||
#define XG_TSIF_MSS_REG0_ADDR 0x02a4
|
||||
#define XG_ENET_SPARE_CFG_REG_ADDR 0x040c
|
||||
#define XG_ENET_SPARE_CFG_REG_1_ADDR 0x0410
|
||||
#define XGENET_RX_DV_GATE_REG_0_ADDR 0x0804
|
||||
|
|
|
|||
|
|
@ -874,6 +874,8 @@ static void atl1c_clean_tx_ring(struct atl1c_adapter *adapter,
|
|||
atl1c_clean_buffer(pdev, buffer_info);
|
||||
}
|
||||
|
||||
netdev_reset_queue(adapter->netdev);
|
||||
|
||||
/* Zero out Tx-buffers */
|
||||
memset(tpd_ring->desc, 0, sizeof(struct atl1c_tpd_desc) *
|
||||
ring_count);
|
||||
|
|
@ -1551,6 +1553,7 @@ static bool atl1c_clean_tx_irq(struct atl1c_adapter *adapter,
|
|||
u16 next_to_clean = atomic_read(&tpd_ring->next_to_clean);
|
||||
u16 hw_next_to_clean;
|
||||
u16 reg;
|
||||
unsigned int total_bytes = 0, total_packets = 0;
|
||||
|
||||
reg = type == atl1c_trans_high ? REG_TPD_PRI1_CIDX : REG_TPD_PRI0_CIDX;
|
||||
|
||||
|
|
@ -1558,12 +1561,18 @@ static bool atl1c_clean_tx_irq(struct atl1c_adapter *adapter,
|
|||
|
||||
while (next_to_clean != hw_next_to_clean) {
|
||||
buffer_info = &tpd_ring->buffer_info[next_to_clean];
|
||||
if (buffer_info->skb) {
|
||||
total_bytes += buffer_info->skb->len;
|
||||
total_packets++;
|
||||
}
|
||||
atl1c_clean_buffer(pdev, buffer_info);
|
||||
if (++next_to_clean == tpd_ring->count)
|
||||
next_to_clean = 0;
|
||||
atomic_set(&tpd_ring->next_to_clean, next_to_clean);
|
||||
}
|
||||
|
||||
netdev_completed_queue(adapter->netdev, total_packets, total_bytes);
|
||||
|
||||
if (netif_queue_stopped(adapter->netdev) &&
|
||||
netif_carrier_ok(adapter->netdev)) {
|
||||
netif_wake_queue(adapter->netdev);
|
||||
|
|
@ -2256,6 +2265,7 @@ static netdev_tx_t atl1c_xmit_frame(struct sk_buff *skb,
|
|||
spin_unlock_irqrestore(&adapter->tx_lock, flags);
|
||||
dev_kfree_skb_any(skb);
|
||||
} else {
|
||||
netdev_sent_queue(adapter->netdev, skb->len);
|
||||
atl1c_tx_queue(adapter, skb, tpd, type);
|
||||
spin_unlock_irqrestore(&adapter->tx_lock, flags);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -139,6 +139,16 @@ config BNX2X_SRIOV
|
|||
Virtualization support in the 578xx and 57712 products. This
|
||||
allows for virtual function acceleration in virtual environments.
|
||||
|
||||
config BNX2X_VXLAN
|
||||
bool "Virtual eXtensible Local Area Network support"
|
||||
default n
|
||||
depends on BNX2X && VXLAN && !(BNX2X=y && VXLAN=m)
|
||||
---help---
|
||||
This enables hardward offload support for VXLAN protocol over the
|
||||
NetXtremeII series adapters.
|
||||
Say Y here if you want to enable hardware offload support for
|
||||
Virtual eXtensible Local Area Network (VXLAN) in the driver.
|
||||
|
||||
config BGMAC
|
||||
tristate "BCMA bus GBit core support"
|
||||
depends on BCMA_HOST_SOC && HAS_DMA && (BCM47XX || ARCH_BCM_5301X)
|
||||
|
|
|
|||
|
|
@ -933,6 +933,21 @@ static irqreturn_t bcm_sysport_wol_isr(int irq, void *dev_id)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
static void bcm_sysport_poll_controller(struct net_device *dev)
|
||||
{
|
||||
struct bcm_sysport_priv *priv = netdev_priv(dev);
|
||||
|
||||
disable_irq(priv->irq0);
|
||||
bcm_sysport_rx_isr(priv->irq0, priv);
|
||||
enable_irq(priv->irq0);
|
||||
|
||||
disable_irq(priv->irq1);
|
||||
bcm_sysport_tx_isr(priv->irq1, priv);
|
||||
enable_irq(priv->irq1);
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct sk_buff *bcm_sysport_insert_tsb(struct sk_buff *skb,
|
||||
struct net_device *dev)
|
||||
{
|
||||
|
|
@ -1723,6 +1738,9 @@ static const struct net_device_ops bcm_sysport_netdev_ops = {
|
|||
.ndo_set_features = bcm_sysport_set_features,
|
||||
.ndo_set_rx_mode = bcm_sysport_set_rx_mode,
|
||||
.ndo_set_mac_address = bcm_sysport_change_mac,
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
.ndo_poll_controller = bcm_sysport_poll_controller,
|
||||
#endif
|
||||
};
|
||||
|
||||
#define REV_FMT "v%2x.%02x"
|
||||
|
|
|
|||
|
|
@ -1447,7 +1447,7 @@ static int bgmac_fixed_phy_register(struct bgmac *bgmac)
|
|||
struct phy_device *phy_dev;
|
||||
int err;
|
||||
|
||||
phy_dev = fixed_phy_register(PHY_POLL, &fphy_status, NULL);
|
||||
phy_dev = fixed_phy_register(PHY_POLL, &fphy_status, -1, NULL);
|
||||
if (!phy_dev || IS_ERR(phy_dev)) {
|
||||
bgmac_err(bgmac, "Failed to register fixed PHY device\n");
|
||||
return -ENODEV;
|
||||
|
|
@ -1549,11 +1549,20 @@ static int bgmac_probe(struct bcma_device *core)
|
|||
struct net_device *net_dev;
|
||||
struct bgmac *bgmac;
|
||||
struct ssb_sprom *sprom = &core->bus->sprom;
|
||||
u8 *mac = core->core_unit ? sprom->et1mac : sprom->et0mac;
|
||||
u8 *mac;
|
||||
int err;
|
||||
|
||||
/* We don't support 2nd, 3rd, ... units, SPROM has to be adjusted */
|
||||
if (core->core_unit > 1) {
|
||||
switch (core->core_unit) {
|
||||
case 0:
|
||||
mac = sprom->et0mac;
|
||||
break;
|
||||
case 1:
|
||||
mac = sprom->et1mac;
|
||||
break;
|
||||
case 2:
|
||||
mac = sprom->et2mac;
|
||||
break;
|
||||
default:
|
||||
pr_err("Unsupported core_unit %d\n", core->core_unit);
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
|
@ -1588,8 +1597,17 @@ static int bgmac_probe(struct bcma_device *core)
|
|||
}
|
||||
bgmac->cmn = core->bus->drv_gmac_cmn.core;
|
||||
|
||||
bgmac->phyaddr = core->core_unit ? sprom->et1phyaddr :
|
||||
sprom->et0phyaddr;
|
||||
switch (core->core_unit) {
|
||||
case 0:
|
||||
bgmac->phyaddr = sprom->et0phyaddr;
|
||||
break;
|
||||
case 1:
|
||||
bgmac->phyaddr = sprom->et1phyaddr;
|
||||
break;
|
||||
case 2:
|
||||
bgmac->phyaddr = sprom->et2phyaddr;
|
||||
break;
|
||||
}
|
||||
bgmac->phyaddr &= BGMAC_PHY_MASK;
|
||||
if (bgmac->phyaddr == BGMAC_PHY_MASK) {
|
||||
bgmac_err(bgmac, "No PHY found\n");
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
/* bnx2x.h: Broadcom Everest network driver.
|
||||
/* bnx2x.h: QLogic Everest network driver.
|
||||
*
|
||||
* Copyright (c) 2007-2013 Broadcom Corporation
|
||||
* Copyright (c) 2014 QLogic Corporation
|
||||
* All rights reserved
|
||||
*
|
||||
* 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
|
||||
|
|
@ -30,7 +32,7 @@
|
|||
* (you will need to reboot afterwards) */
|
||||
/* #define BNX2X_STOP_ON_ERROR */
|
||||
|
||||
#define DRV_MODULE_VERSION "1.710.51-0"
|
||||
#define DRV_MODULE_VERSION "1.712.30-0"
|
||||
#define DRV_MODULE_RELDATE "2014/02/10"
|
||||
#define BNX2X_BC_VER 0x040200
|
||||
|
||||
|
|
@ -1226,6 +1228,10 @@ struct bnx2x_slowpath {
|
|||
struct eth_classify_rules_ramrod_data e2;
|
||||
} mac_rdata;
|
||||
|
||||
union {
|
||||
struct eth_classify_rules_ramrod_data e2;
|
||||
} vlan_rdata;
|
||||
|
||||
union {
|
||||
struct tstorm_eth_mac_filter_config e1x;
|
||||
struct eth_filter_rules_ramrod_data e2;
|
||||
|
|
@ -1386,6 +1392,8 @@ enum sp_rtnl_flag {
|
|||
BNX2X_SP_RTNL_HYPERVISOR_VLAN,
|
||||
BNX2X_SP_RTNL_TX_STOP,
|
||||
BNX2X_SP_RTNL_GET_DRV_VERSION,
|
||||
BNX2X_SP_RTNL_ADD_VXLAN_PORT,
|
||||
BNX2X_SP_RTNL_DEL_VXLAN_PORT,
|
||||
};
|
||||
|
||||
enum bnx2x_iov_flag {
|
||||
|
|
@ -1408,6 +1416,9 @@ struct bnx2x_sp_objs {
|
|||
|
||||
/* Queue State object */
|
||||
struct bnx2x_queue_sp_obj q_obj;
|
||||
|
||||
/* VLANs object */
|
||||
struct bnx2x_vlan_mac_obj vlan_obj;
|
||||
};
|
||||
|
||||
struct bnx2x_fp_stats {
|
||||
|
|
@ -1422,6 +1433,13 @@ enum {
|
|||
SUB_MF_MODE_UNKNOWN = 0,
|
||||
SUB_MF_MODE_UFP,
|
||||
SUB_MF_MODE_NPAR1_DOT_5,
|
||||
SUB_MF_MODE_BD,
|
||||
};
|
||||
|
||||
struct bnx2x_vlan_entry {
|
||||
struct list_head link;
|
||||
u16 vid;
|
||||
bool hw;
|
||||
};
|
||||
|
||||
struct bnx2x {
|
||||
|
|
@ -1636,6 +1654,8 @@ struct bnx2x {
|
|||
u8 mf_sub_mode;
|
||||
#define IS_MF_UFP(bp) (IS_MF_SD(bp) && \
|
||||
bp->mf_sub_mode == SUB_MF_MODE_UFP)
|
||||
#define IS_MF_BD(bp) (IS_MF_SD(bp) && \
|
||||
bp->mf_sub_mode == SUB_MF_MODE_BD)
|
||||
|
||||
u8 wol;
|
||||
|
||||
|
|
@ -1860,8 +1880,6 @@ struct bnx2x {
|
|||
int dcb_version;
|
||||
|
||||
/* CAM credit pools */
|
||||
|
||||
/* used only in sriov */
|
||||
struct bnx2x_credit_pool_obj vlans_pool;
|
||||
|
||||
struct bnx2x_credit_pool_obj macs_pool;
|
||||
|
|
@ -1924,6 +1942,11 @@ struct bnx2x {
|
|||
u16 rx_filter;
|
||||
|
||||
struct bnx2x_link_report_data vf_link_vars;
|
||||
struct list_head vlan_reg;
|
||||
u16 vlan_cnt;
|
||||
u16 vlan_credit;
|
||||
u16 vxlan_dst_port;
|
||||
bool accept_any_vlan;
|
||||
};
|
||||
|
||||
/* Tx queues may be less or equal to Rx queues */
|
||||
|
|
@ -1951,23 +1974,14 @@ extern int num_queues;
|
|||
#define RSS_IPV6_TCP_CAP_MASK \
|
||||
TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY
|
||||
|
||||
/* func init flags */
|
||||
#define FUNC_FLG_RSS 0x0001
|
||||
#define FUNC_FLG_STATS 0x0002
|
||||
/* removed FUNC_FLG_UNMATCHED 0x0004 */
|
||||
#define FUNC_FLG_TPA 0x0008
|
||||
#define FUNC_FLG_SPQ 0x0010
|
||||
#define FUNC_FLG_LEADING 0x0020 /* PF only */
|
||||
#define FUNC_FLG_LEADING_STATS 0x0040
|
||||
struct bnx2x_func_init_params {
|
||||
/* dma */
|
||||
dma_addr_t fw_stat_map; /* valid iff FUNC_FLG_STATS */
|
||||
dma_addr_t spq_map; /* valid iff FUNC_FLG_SPQ */
|
||||
bool spq_active;
|
||||
dma_addr_t spq_map;
|
||||
u16 spq_prod;
|
||||
|
||||
u16 func_flgs;
|
||||
u16 func_id; /* abs fid */
|
||||
u16 pf_id;
|
||||
u16 spq_prod; /* valid iff FUNC_FLG_SPQ */
|
||||
};
|
||||
|
||||
#define for_each_cnic_queue(bp, var) \
|
||||
|
|
@ -2077,6 +2091,11 @@ struct bnx2x_func_init_params {
|
|||
int bnx2x_set_mac_one(struct bnx2x *bp, u8 *mac,
|
||||
struct bnx2x_vlan_mac_obj *obj, bool set,
|
||||
int mac_type, unsigned long *ramrod_flags);
|
||||
|
||||
int bnx2x_set_vlan_one(struct bnx2x *bp, u16 vlan,
|
||||
struct bnx2x_vlan_mac_obj *obj, bool set,
|
||||
unsigned long *ramrod_flags);
|
||||
|
||||
/**
|
||||
* bnx2x_del_all_macs - delete all MACs configured for the specific MAC object
|
||||
*
|
||||
|
|
@ -2481,6 +2500,7 @@ void bnx2x_igu_clear_sb_gen(struct bnx2x *bp, u8 func, u8 idu_sb_id,
|
|||
#define VF_ACQUIRE_THRESH 3
|
||||
#define VF_ACQUIRE_MAC_FILTERS 1
|
||||
#define VF_ACQUIRE_MC_FILTERS 10
|
||||
#define VF_ACQUIRE_VLAN_FILTERS 2 /* VLAN0 + 'real' VLAN */
|
||||
|
||||
#define GOOD_ME_REG(me_reg) (((me_reg) & ME_REG_VF_VALID) && \
|
||||
(!((me_reg) & ME_REG_VF_ERR)))
|
||||
|
|
@ -2553,6 +2573,10 @@ void bnx2x_notify_link_changed(struct bnx2x *bp);
|
|||
(IS_MF_SD_STORAGE_PERSONALITY_ONLY(bp) || \
|
||||
IS_MF_SI_STORAGE_PERSONALITY_ONLY(bp))
|
||||
|
||||
/* Determines whether BW configuration arrives in 100Mb units or in
|
||||
* percentages from actual physical link speed.
|
||||
*/
|
||||
#define IS_MF_PERCENT_BW(bp) (IS_MF_SI(bp) || IS_MF_UFP(bp) || IS_MF_BD(bp))
|
||||
|
||||
#define SET_FLAG(value, mask, flag) \
|
||||
do {\
|
||||
|
|
@ -2577,6 +2601,8 @@ void bnx2x_set_local_cmng(struct bnx2x *bp);
|
|||
|
||||
void bnx2x_update_mng_version(struct bnx2x *bp);
|
||||
|
||||
void bnx2x_update_mfw_dump(struct bnx2x *bp);
|
||||
|
||||
#define MCPR_SCRATCH_BASE(bp) \
|
||||
(CHIP_IS_E1x(bp) ? MCP_REG_MCPR_SCRATCH : MCP_A_REG_MCPR_SCRATCH)
|
||||
|
||||
|
|
@ -2589,4 +2615,9 @@ void bnx2x_set_rx_ts(struct bnx2x *bp, struct sk_buff *skb);
|
|||
#define BNX2X_MAX_PHC_DRIFT 31000000
|
||||
#define BNX2X_PTP_TX_TIMEOUT
|
||||
|
||||
/* Re-configure all previously configured vlan filters.
|
||||
* Meant for implicit re-load flows.
|
||||
*/
|
||||
int bnx2x_vlan_reconfigure_vid(struct bnx2x *bp);
|
||||
|
||||
#endif /* bnx2x.h */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
/* bnx2x_cmn.c: Broadcom Everest network driver.
|
||||
/* bnx2x_cmn.c: QLogic Everest network driver.
|
||||
*
|
||||
* Copyright (c) 2007-2013 Broadcom Corporation
|
||||
* Copyright (c) 2014 QLogic Corporation
|
||||
* All rights reserved
|
||||
*
|
||||
* 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
|
||||
|
|
@ -1188,7 +1190,7 @@ u16 bnx2x_get_mf_speed(struct bnx2x *bp)
|
|||
/* Calculate the current MAX line speed limit for the MF
|
||||
* devices
|
||||
*/
|
||||
if (IS_MF_SI(bp))
|
||||
if (IS_MF_PERCENT_BW(bp))
|
||||
line_speed = (line_speed * maxCfg) / 100;
|
||||
else { /* SD mode */
|
||||
u16 vn_max_rate = maxCfg * 100;
|
||||
|
|
@ -2103,9 +2105,14 @@ int bnx2x_rss(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj,
|
|||
if (rss_obj->udp_rss_v6)
|
||||
__set_bit(BNX2X_RSS_IPV6_UDP, ¶ms.rss_flags);
|
||||
|
||||
if (!CHIP_IS_E1x(bp))
|
||||
if (!CHIP_IS_E1x(bp)) {
|
||||
/* valid only for TUNN_MODE_VXLAN tunnel mode */
|
||||
__set_bit(BNX2X_RSS_IPV4_VXLAN, ¶ms.rss_flags);
|
||||
__set_bit(BNX2X_RSS_IPV6_VXLAN, ¶ms.rss_flags);
|
||||
|
||||
/* valid only for TUNN_MODE_GRE tunnel mode */
|
||||
__set_bit(BNX2X_RSS_GRE_INNER_HDRS, ¶ms.rss_flags);
|
||||
__set_bit(BNX2X_RSS_TUNN_INNER_HDRS, ¶ms.rss_flags);
|
||||
}
|
||||
} else {
|
||||
__set_bit(BNX2X_RSS_MODE_DISABLED, ¶ms.rss_flags);
|
||||
}
|
||||
|
|
@ -2510,6 +2517,20 @@ static void bnx2x_bz_fp(struct bnx2x *bp, int index)
|
|||
fp->mode = TPA_MODE_DISABLED;
|
||||
}
|
||||
|
||||
void bnx2x_set_os_driver_state(struct bnx2x *bp, u32 state)
|
||||
{
|
||||
u32 cur;
|
||||
|
||||
if (!IS_MF_BD(bp) || !SHMEM2_HAS(bp, os_driver_state) || IS_VF(bp))
|
||||
return;
|
||||
|
||||
cur = SHMEM2_RD(bp, os_driver_state[BP_FW_MB_IDX(bp)]);
|
||||
DP(NETIF_MSG_IFUP, "Driver state %08x-->%08x\n",
|
||||
cur, state);
|
||||
|
||||
SHMEM2_WR(bp, os_driver_state[BP_FW_MB_IDX(bp)], state);
|
||||
}
|
||||
|
||||
int bnx2x_load_cnic(struct bnx2x *bp)
|
||||
{
|
||||
int i, rc, port = BP_PORT(bp);
|
||||
|
|
@ -2827,6 +2848,11 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
|
|||
|
||||
/* Start fast path */
|
||||
|
||||
/* Re-configure vlan filters */
|
||||
rc = bnx2x_vlan_reconfigure_vid(bp);
|
||||
if (rc)
|
||||
LOAD_ERROR_EXIT(bp, load_error3);
|
||||
|
||||
/* Initialize Rx filter. */
|
||||
bnx2x_set_rx_mode_inner(bp);
|
||||
|
||||
|
|
@ -2873,6 +2899,8 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
|
|||
/* mark driver is loaded in shmem2 */
|
||||
u32 val;
|
||||
val = SHMEM2_RD(bp, drv_capabilities_flag[BP_FW_MB_IDX(bp)]);
|
||||
val &= ~DRV_FLAGS_MTU_MASK;
|
||||
val |= (bp->dev->mtu << DRV_FLAGS_MTU_SHIFT);
|
||||
SHMEM2_WR(bp, drv_capabilities_flag[BP_FW_MB_IDX(bp)],
|
||||
val | DRV_FLAGS_CAPABILITIES_LOADED_SUPPORTED |
|
||||
DRV_FLAGS_CAPABILITIES_LOADED_L2);
|
||||
|
|
@ -2885,10 +2913,17 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* Update driver data for On-Chip MFW dump. */
|
||||
if (IS_PF(bp))
|
||||
bnx2x_update_mfw_dump(bp);
|
||||
|
||||
/* If PMF - send ADMIN DCBX msg to MFW to initiate DCBX FSM */
|
||||
if (bp->port.pmf && (bp->state != BNX2X_STATE_DIAG))
|
||||
bnx2x_dcbx_init(bp, false);
|
||||
|
||||
if (!IS_MF_SD_STORAGE_PERSONALITY_ONLY(bp))
|
||||
bnx2x_set_os_driver_state(bp, OS_DRIVER_STATE_ACTIVE);
|
||||
|
||||
DP(NETIF_MSG_IFUP, "Ending successfully NIC load\n");
|
||||
|
||||
return 0;
|
||||
|
|
@ -2956,6 +2991,9 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link)
|
|||
|
||||
DP(NETIF_MSG_IFUP, "Starting NIC unload\n");
|
||||
|
||||
if (!IS_MF_SD_STORAGE_PERSONALITY_ONLY(bp))
|
||||
bnx2x_set_os_driver_state(bp, OS_DRIVER_STATE_DISABLED);
|
||||
|
||||
/* mark driver is unloaded in shmem2 */
|
||||
if (IS_PF(bp) && SHMEM2_HAS(bp, drv_capabilities_flag)) {
|
||||
u32 val;
|
||||
|
|
@ -3677,7 +3715,7 @@ static void bnx2x_update_pbds_gso_enc(struct sk_buff *skb,
|
|||
pbd2->fw_ip_hdr_to_payload_w =
|
||||
hlen_w - ((sizeof(struct ipv6hdr)) >> 1);
|
||||
pbd_e2->data.tunnel_data.flags |=
|
||||
ETH_TUNNEL_DATA_IP_HDR_TYPE_OUTER;
|
||||
ETH_TUNNEL_DATA_IPV6_OUTER;
|
||||
}
|
||||
|
||||
pbd2->tcp_send_seq = bswab32(inner_tcp_hdr(skb)->seq);
|
||||
|
|
@ -4184,6 +4222,41 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
void bnx2x_get_c2s_mapping(struct bnx2x *bp, u8 *c2s_map, u8 *c2s_default)
|
||||
{
|
||||
int mfw_vn = BP_FW_MB_IDX(bp);
|
||||
u32 tmp;
|
||||
|
||||
/* If the shmem shouldn't affect configuration, reflect */
|
||||
if (!IS_MF_BD(bp)) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < BNX2X_MAX_PRIORITY; i++)
|
||||
c2s_map[i] = i;
|
||||
*c2s_default = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
tmp = SHMEM2_RD(bp, c2s_pcp_map_lower[mfw_vn]);
|
||||
tmp = (__force u32)be32_to_cpu((__force __be32)tmp);
|
||||
c2s_map[0] = tmp & 0xff;
|
||||
c2s_map[1] = (tmp >> 8) & 0xff;
|
||||
c2s_map[2] = (tmp >> 16) & 0xff;
|
||||
c2s_map[3] = (tmp >> 24) & 0xff;
|
||||
|
||||
tmp = SHMEM2_RD(bp, c2s_pcp_map_upper[mfw_vn]);
|
||||
tmp = (__force u32)be32_to_cpu((__force __be32)tmp);
|
||||
c2s_map[4] = tmp & 0xff;
|
||||
c2s_map[5] = (tmp >> 8) & 0xff;
|
||||
c2s_map[6] = (tmp >> 16) & 0xff;
|
||||
c2s_map[7] = (tmp >> 24) & 0xff;
|
||||
|
||||
tmp = SHMEM2_RD(bp, c2s_pcp_map_default[mfw_vn]);
|
||||
tmp = (__force u32)be32_to_cpu((__force __be32)tmp);
|
||||
*c2s_default = (tmp >> (8 * mfw_vn)) & 0xff;
|
||||
}
|
||||
|
||||
/**
|
||||
* bnx2x_setup_tc - routine to configure net_device for multi tc
|
||||
*
|
||||
|
|
@ -4194,8 +4267,9 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
*/
|
||||
int bnx2x_setup_tc(struct net_device *dev, u8 num_tc)
|
||||
{
|
||||
int cos, prio, count, offset;
|
||||
struct bnx2x *bp = netdev_priv(dev);
|
||||
u8 c2s_map[BNX2X_MAX_PRIORITY], c2s_def;
|
||||
int cos, prio, count, offset;
|
||||
|
||||
/* setup tc must be called under rtnl lock */
|
||||
ASSERT_RTNL();
|
||||
|
|
@ -4219,12 +4293,16 @@ int bnx2x_setup_tc(struct net_device *dev, u8 num_tc)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
bnx2x_get_c2s_mapping(bp, c2s_map, &c2s_def);
|
||||
|
||||
/* configure priority to traffic class mapping */
|
||||
for (prio = 0; prio < BNX2X_MAX_PRIORITY; prio++) {
|
||||
netdev_set_prio_tc_map(dev, prio, bp->prio_to_cos[prio]);
|
||||
int outer_prio = c2s_map[prio];
|
||||
|
||||
netdev_set_prio_tc_map(dev, prio, bp->prio_to_cos[outer_prio]);
|
||||
DP(BNX2X_MSG_SP | NETIF_MSG_IFUP,
|
||||
"mapping priority %d to tc %d\n",
|
||||
prio, bp->prio_to_cos[prio]);
|
||||
outer_prio, bp->prio_to_cos[outer_prio]);
|
||||
}
|
||||
|
||||
/* Use this configuration to differentiate tc0 from other COSes
|
||||
|
|
@ -4278,6 +4356,9 @@ int bnx2x_change_mac_addr(struct net_device *dev, void *p)
|
|||
if (netif_running(dev))
|
||||
rc = bnx2x_set_eth_mac(bp, true);
|
||||
|
||||
if (IS_PF(bp) && SHMEM2_HAS(bp, curr_cfg))
|
||||
SHMEM2_WR(bp, curr_cfg, CURR_CFG_MET_OS);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
@ -4831,6 +4912,9 @@ int bnx2x_change_mtu(struct net_device *dev, int new_mtu)
|
|||
*/
|
||||
dev->mtu = new_mtu;
|
||||
|
||||
if (IS_PF(bp) && SHMEM2_HAS(bp, curr_cfg))
|
||||
SHMEM2_WR(bp, curr_cfg, CURR_CFG_MET_OS);
|
||||
|
||||
return bnx2x_reload_if_running(dev);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
/* bnx2x_cmn.h: Broadcom Everest network driver.
|
||||
/* bnx2x_cmn.h: QLogic Everest network driver.
|
||||
*
|
||||
* Copyright (c) 2007-2013 Broadcom Corporation
|
||||
* Copyright (c) 2014 QLogic Corporation
|
||||
* All rights reserved
|
||||
*
|
||||
* 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
|
||||
|
|
@ -620,6 +622,14 @@ int bnx2x_set_features(struct net_device *dev, netdev_features_t features);
|
|||
*/
|
||||
void bnx2x_tx_timeout(struct net_device *dev);
|
||||
|
||||
/** bnx2x_get_c2s_mapping - read inner-to-outer vlan configuration
|
||||
* c2s_map should have BNX2X_MAX_PRIORITY entries.
|
||||
* @bp: driver handle
|
||||
* @c2s_map: should have BNX2X_MAX_PRIORITY entries for mapping
|
||||
* @c2s_default: entry for non-tagged configuration
|
||||
*/
|
||||
void bnx2x_get_c2s_mapping(struct bnx2x *bp, u8 *c2s_map, u8 *c2s_default);
|
||||
|
||||
/*********************** Inlines **********************************/
|
||||
/*********************** Fast path ********************************/
|
||||
static inline void bnx2x_update_fpsb_idx(struct bnx2x_fastpath *fp)
|
||||
|
|
@ -931,14 +941,35 @@ static inline int bnx2x_func_start(struct bnx2x *bp)
|
|||
start_params->mf_mode = bp->mf_mode;
|
||||
start_params->sd_vlan_tag = bp->mf_ov;
|
||||
|
||||
/* Configure Ethertype for BD mode */
|
||||
if (IS_MF_BD(bp)) {
|
||||
DP(NETIF_MSG_IFUP, "Configuring ethertype 0x88a8 for BD\n");
|
||||
start_params->sd_vlan_eth_type = ETH_P_8021AD;
|
||||
REG_WR(bp, PRS_REG_VLAN_TYPE_0, ETH_P_8021AD);
|
||||
REG_WR(bp, PBF_REG_VLAN_TYPE_0, ETH_P_8021AD);
|
||||
REG_WR(bp, NIG_REG_LLH_E1HOV_TYPE_1, ETH_P_8021AD);
|
||||
|
||||
bnx2x_get_c2s_mapping(bp, start_params->c2s_pri,
|
||||
&start_params->c2s_pri_default);
|
||||
start_params->c2s_pri_valid = 1;
|
||||
|
||||
DP(NETIF_MSG_IFUP,
|
||||
"Inner-to-Outer priority: %02x %02x %02x %02x %02x %02x %02x %02x [Default %02x]\n",
|
||||
start_params->c2s_pri[0], start_params->c2s_pri[1],
|
||||
start_params->c2s_pri[2], start_params->c2s_pri[3],
|
||||
start_params->c2s_pri[4], start_params->c2s_pri[5],
|
||||
start_params->c2s_pri[6], start_params->c2s_pri[7],
|
||||
start_params->c2s_pri_default);
|
||||
}
|
||||
|
||||
if (CHIP_IS_E2(bp) || CHIP_IS_E3(bp))
|
||||
start_params->network_cos_mode = STATIC_COS;
|
||||
else /* CHIP_IS_E1X */
|
||||
start_params->network_cos_mode = FW_WRR;
|
||||
|
||||
start_params->tunnel_mode = TUNN_MODE_GRE;
|
||||
start_params->gre_tunnel_type = IPGRE_TUNNEL;
|
||||
start_params->inner_gre_rss_en = 1;
|
||||
start_params->vxlan_dst_port = bp->vxlan_dst_port;
|
||||
|
||||
start_params->inner_rss = 1;
|
||||
|
||||
if (IS_MF_UFP(bp) && BNX2X_IS_MF_SD_PROTOCOL_FCOE(bp)) {
|
||||
start_params->class_fail_ethtype = ETH_P_FIP;
|
||||
|
|
@ -1037,6 +1068,15 @@ static inline void bnx2x_init_vlan_mac_fp_objs(struct bnx2x_fastpath *fp,
|
|||
BNX2X_FILTER_MAC_PENDING,
|
||||
&bp->sp_state, obj_type,
|
||||
&bp->macs_pool);
|
||||
|
||||
if (!CHIP_IS_E1x(bp))
|
||||
bnx2x_init_vlan_obj(bp, &bnx2x_sp_obj(bp, fp).vlan_obj,
|
||||
fp->cl_id, fp->cid, BP_FUNC(bp),
|
||||
bnx2x_sp(bp, vlan_rdata),
|
||||
bnx2x_sp_mapping(bp, vlan_rdata),
|
||||
BNX2X_FILTER_VLAN_PENDING,
|
||||
&bp->sp_state, obj_type,
|
||||
&bp->vlans_pool);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1096,7 +1136,7 @@ static inline void bnx2x_init_bp_objs(struct bnx2x *bp)
|
|||
bnx2x_init_mac_credit_pool(bp, &bp->macs_pool, BP_FUNC(bp),
|
||||
bnx2x_get_path_func_num(bp));
|
||||
|
||||
bnx2x_init_vlan_credit_pool(bp, &bp->vlans_pool, BP_ABS_FUNC(bp)>>1,
|
||||
bnx2x_init_vlan_credit_pool(bp, &bp->vlans_pool, BP_FUNC(bp),
|
||||
bnx2x_get_path_func_num(bp));
|
||||
|
||||
/* RSS configuration object */
|
||||
|
|
@ -1106,6 +1146,8 @@ static inline void bnx2x_init_bp_objs(struct bnx2x *bp)
|
|||
bnx2x_sp_mapping(bp, rss_rdata),
|
||||
BNX2X_FILTER_RSS_CONF_PENDING, &bp->sp_state,
|
||||
BNX2X_OBJ_TYPE_RX);
|
||||
|
||||
bp->vlan_credit = PF_VLAN_CREDIT_E2(bp, bnx2x_get_path_func_num(bp));
|
||||
}
|
||||
|
||||
static inline u8 bnx2x_fp_qzone_id(struct bnx2x_fastpath *fp)
|
||||
|
|
@ -1339,4 +1381,23 @@ void bnx2x_squeeze_objects(struct bnx2x *bp);
|
|||
void bnx2x_schedule_sp_rtnl(struct bnx2x*, enum sp_rtnl_flag,
|
||||
u32 verbose);
|
||||
|
||||
/**
|
||||
* bnx2x_set_os_driver_state - write driver state for management FW usage
|
||||
*
|
||||
* @bp: driver handle
|
||||
* @state: OS_DRIVER_STATE_* value reflecting current driver state
|
||||
*/
|
||||
void bnx2x_set_os_driver_state(struct bnx2x *bp, u32 state);
|
||||
|
||||
/**
|
||||
* bnx2x_nvram_read - reads data from nvram [might sleep]
|
||||
*
|
||||
* @bp: driver handle
|
||||
* @offset: byte offset in nvram
|
||||
* @ret_buf: pointer to buffer where data is to be stored
|
||||
* @buf_size: Length of 'ret_buf' in bytes
|
||||
*/
|
||||
int bnx2x_nvram_read(struct bnx2x *bp, u32 offset, u8 *ret_buf,
|
||||
int buf_size);
|
||||
|
||||
#endif /* BNX2X_CMN_H */
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
/* bnx2x_dcb.c: Broadcom Everest network driver.
|
||||
/* bnx2x_dcb.c: QLogic Everest network driver.
|
||||
*
|
||||
* Copyright 2009-2013 Broadcom Corporation
|
||||
* Copyright 2014 QLogic Corporation
|
||||
* All rights reserved
|
||||
*
|
||||
* Unless you and Broadcom execute a separate written software license
|
||||
* Unless you and QLogic execute a separate written software license
|
||||
* agreement governing use of this software, this software is licensed to you
|
||||
* under the terms of the GNU General Public License version 2, available
|
||||
* at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL").
|
||||
*
|
||||
* Notwithstanding the above, under no circumstances may you combine this
|
||||
* software in any way with any other Broadcom software provided under a
|
||||
* license other than the GPL, without Broadcom's express prior written
|
||||
* software in any way with any other QLogic software provided under a
|
||||
* license other than the GPL, without QLogic's express prior written
|
||||
* consent.
|
||||
*
|
||||
* Maintained by: Ariel Elior <ariel.elior@qlogic.com>
|
||||
|
|
@ -1850,6 +1852,8 @@ static void bnx2x_dcbx_fw_struct(struct bnx2x *bp,
|
|||
if (bp->dcbx_port_params.ets.cos_params[cos].
|
||||
pri_bitmask & pri_bit)
|
||||
tt2cos[pri].cos = cos;
|
||||
|
||||
pfc_fw_cfg->dcb_outer_pri[pri] = ttp[pri];
|
||||
}
|
||||
|
||||
/* we never want the FW to add a 0 vlan tag */
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
/* bnx2x_dcb.h: Broadcom Everest network driver.
|
||||
/* bnx2x_dcb.h: QLogic Everest network driver.
|
||||
*
|
||||
* Copyright 2009-2013 Broadcom Corporation
|
||||
* Copyright 2014 QLogic Corporation
|
||||
* All rights reserved
|
||||
*
|
||||
* Unless you and Broadcom execute a separate written software license
|
||||
* Unless you and QLogic execute a separate written software license
|
||||
* agreement governing use of this software, this software is licensed to you
|
||||
* under the terms of the GNU General Public License version 2, available
|
||||
* at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL").
|
||||
*
|
||||
* Notwithstanding the above, under no circumstances may you combine this
|
||||
* software in any way with any other Broadcom software provided under a
|
||||
* license other than the GPL, without Broadcom's express prior written
|
||||
* software in any way with any other QLogic software provided under a
|
||||
* license other than the GPL, without QLogic's express prior written
|
||||
* consent.
|
||||
*
|
||||
* Maintained by: Ariel Elior <ariel.elior@qlogic.com>
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
/* bnx2x_dump.h: Broadcom Everest network driver.
|
||||
/* bnx2x_dump.h: QLogic Everest network driver.
|
||||
*
|
||||
* Copyright (c) 2012-2013 Broadcom Corporation
|
||||
* Copyright (c) 2014 QLogic Corporation
|
||||
* All rights reserved
|
||||
*
|
||||
* Unless you and Broadcom execute a separate written software license
|
||||
* Unless you and QLogic execute a separate written software license
|
||||
* agreement governing use of this software, this software is licensed to you
|
||||
* under the terms of the GNU General Public License version 2, available
|
||||
* at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL").
|
||||
*
|
||||
* Notwithstanding the above, under no circumstances may you combine this
|
||||
* software in any way with any other Broadcom software provided under a
|
||||
* license other than the GPL, without Broadcom's express prior written
|
||||
* software in any way with any other QLogic software provided under a
|
||||
* license other than the GPL, without QLogic's express prior written
|
||||
* consent.
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
/* bnx2x_ethtool.c: Broadcom Everest network driver.
|
||||
/* bnx2x_ethtool.c: QLogic Everest network driver.
|
||||
*
|
||||
* Copyright (c) 2007-2013 Broadcom Corporation
|
||||
* Copyright (c) 2014 QLogic Corporation
|
||||
* All rights reserved
|
||||
*
|
||||
* 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
|
||||
|
|
@ -1129,6 +1131,9 @@ static int bnx2x_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
|
|||
} else
|
||||
bp->wol = 0;
|
||||
|
||||
if (SHMEM2_HAS(bp, curr_cfg))
|
||||
SHMEM2_WR(bp, curr_cfg, CURR_CFG_MET_OS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1343,8 +1348,8 @@ static int bnx2x_nvram_read_dword(struct bnx2x *bp, u32 offset, __be32 *ret_val,
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int bnx2x_nvram_read(struct bnx2x *bp, u32 offset, u8 *ret_buf,
|
||||
int buf_size)
|
||||
int bnx2x_nvram_read(struct bnx2x *bp, u32 offset, u8 *ret_buf,
|
||||
int buf_size)
|
||||
{
|
||||
int rc;
|
||||
u32 cmd_flags;
|
||||
|
|
@ -3578,17 +3583,8 @@ static int bnx2x_get_ts_info(struct net_device *dev,
|
|||
|
||||
info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V1_L4_EVENT) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V1_L4_SYNC) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ);
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_EVENT);
|
||||
|
||||
info->tx_types = (1 << HWTSTAMP_TX_OFF)|(1 << HWTSTAMP_TX_ON);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
/* bnx2x_fw_defs.h: Broadcom Everest network driver.
|
||||
/* bnx2x_fw_defs.h: Qlogic Everest network driver.
|
||||
*
|
||||
* Copyright (c) 2007-2013 Broadcom Corporation
|
||||
* Copyright (c) 2014 QLogic Corporation
|
||||
* All rights reserved
|
||||
*
|
||||
* 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
|
||||
|
|
@ -372,7 +374,7 @@
|
|||
#define MAX_COS_NUMBER 4
|
||||
#define MAX_TRAFFIC_TYPES 8
|
||||
#define MAX_PFC_PRIORITIES 8
|
||||
|
||||
#define MAX_VLAN_PRIORITIES 8
|
||||
/* used by array traffic_type_to_priority[] to mark traffic type \
|
||||
that is not mapped to priority*/
|
||||
#define LLFC_TRAFFIC_TYPE_TO_PRIORITY_UNMAPPED 0xFF
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
/* bnx2x_fw_file_hdr.h: FW binary file header structure.
|
||||
*
|
||||
* Copyright (c) 2007-2013 Broadcom Corporation
|
||||
* Copyright (c) 2014 QLogic Corporation
|
||||
* All rights reserved
|
||||
*
|
||||
* 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
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
/* bnx2x_hsi.h: Broadcom Everest network driver.
|
||||
/* bnx2x_hsi.h: Qlogic Everest network driver.
|
||||
*
|
||||
* Copyright (c) 2007-2013 Broadcom Corporation
|
||||
* Copyright (c) 2014 QLogic Corporation
|
||||
* All rights reserved
|
||||
*
|
||||
* 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
|
||||
|
|
@ -729,6 +731,7 @@ struct port_hw_cfg { /* port 0: 0x12c port 1: 0x2bc */
|
|||
#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8722 0x00000f00
|
||||
#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM54616 0x00001000
|
||||
#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM84834 0x00001100
|
||||
#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM84858 0x00001200
|
||||
#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_FAILURE 0x0000fd00
|
||||
#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_NOT_CONN 0x0000ff00
|
||||
|
||||
|
|
@ -786,6 +789,7 @@ struct port_hw_cfg { /* port 0: 0x12c port 1: 0x2bc */
|
|||
#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722 0x00000f00
|
||||
#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54616 0x00001000
|
||||
#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834 0x00001100
|
||||
#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84858 0x00001200
|
||||
#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT_WC 0x0000fc00
|
||||
#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE 0x0000fd00
|
||||
#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN 0x0000ff00
|
||||
|
|
@ -864,6 +868,7 @@ struct shared_feat_cfg { /* NVRAM Offset */
|
|||
#define SHARED_FEAT_CFG_FORCE_SF_MODE_SPIO4 0x00000200
|
||||
#define SHARED_FEAT_CFG_FORCE_SF_MODE_SWITCH_INDEPT 0x00000300
|
||||
#define SHARED_FEAT_CFG_FORCE_SF_MODE_AFEX_MODE 0x00000400
|
||||
#define SHARED_FEAT_CFG_FORCE_SF_MODE_BD_MODE 0x00000500
|
||||
#define SHARED_FEAT_CFG_FORCE_SF_MODE_UFP_MODE 0x00000600
|
||||
#define SHARED_FEAT_CFG_FORCE_SF_MODE_EXTENDED_MODE 0x00000700
|
||||
|
||||
|
|
@ -2064,6 +2069,45 @@ struct ncsi_oem_fcoe_features {
|
|||
#define FCOE_FEATURES4_FEATURE_SETTINGS_OFFSET 0
|
||||
};
|
||||
|
||||
enum curr_cfg_method_e {
|
||||
CURR_CFG_MET_NONE = 0, /* default config */
|
||||
CURR_CFG_MET_OS = 1,
|
||||
CURR_CFG_MET_VENDOR_SPEC = 2,/* e.g. Option ROM, NPAR, O/S Cfg Utils */
|
||||
};
|
||||
|
||||
#define FC_NPIV_WWPN_SIZE 8
|
||||
#define FC_NPIV_WWNN_SIZE 8
|
||||
struct bdn_npiv_settings {
|
||||
u8 npiv_wwpn[FC_NPIV_WWPN_SIZE];
|
||||
u8 npiv_wwnn[FC_NPIV_WWNN_SIZE];
|
||||
};
|
||||
|
||||
struct bdn_fc_npiv_cfg {
|
||||
/* hdr used internally by the MFW */
|
||||
u32 hdr;
|
||||
u32 num_of_npiv;
|
||||
};
|
||||
|
||||
#define MAX_NUMBER_NPIV 64
|
||||
struct bdn_fc_npiv_tbl {
|
||||
struct bdn_fc_npiv_cfg fc_npiv_cfg;
|
||||
struct bdn_npiv_settings settings[MAX_NUMBER_NPIV];
|
||||
};
|
||||
|
||||
struct mdump_driver_info {
|
||||
u32 epoc;
|
||||
u32 drv_ver;
|
||||
u32 fw_ver;
|
||||
|
||||
u32 valid_dump;
|
||||
#define FIRST_DUMP_VALID (1 << 0)
|
||||
#define SECOND_DUMP_VALID (1 << 1)
|
||||
|
||||
u32 flags;
|
||||
#define ENABLE_ALL_TRIGGERS (0x7fffffff)
|
||||
#define TRIGGER_MDUMP_ONCE (1 << 31)
|
||||
};
|
||||
|
||||
struct ncsi_oem_data {
|
||||
u32 driver_version[4];
|
||||
struct ncsi_oem_fcoe_features ncsi_oem_fcoe_features;
|
||||
|
|
@ -2187,6 +2231,8 @@ struct shmem2_region {
|
|||
#define DRV_FLAGS_CAPABILITIES_LOADED_L2 0x00000002
|
||||
#define DRV_FLAGS_CAPABILITIES_LOADED_FCOE 0x00000004
|
||||
#define DRV_FLAGS_CAPABILITIES_LOADED_ISCSI 0x00000008
|
||||
#define DRV_FLAGS_MTU_MASK 0xffff0000
|
||||
#define DRV_FLAGS_MTU_SHIFT 16
|
||||
|
||||
u32 extended_dev_info_shared_cfg_size;
|
||||
|
||||
|
|
@ -2251,6 +2297,7 @@ struct shmem2_region {
|
|||
u32 reserved4; /* Offset 0x150 */
|
||||
u32 link_attr_sync[PORT_MAX]; /* Offset 0x154 */
|
||||
#define LINK_ATTR_SYNC_KR2_ENABLE 0x00000001
|
||||
#define LINK_ATTR_84858 0x00000002
|
||||
#define LINK_SFP_EEPROM_COMP_CODE_MASK 0x0000ff00
|
||||
#define LINK_SFP_EEPROM_COMP_CODE_SHIFT 8
|
||||
#define LINK_SFP_EEPROM_COMP_CODE_SR 0x00001000
|
||||
|
|
@ -2268,6 +2315,74 @@ struct shmem2_region {
|
|||
|
||||
/* We use indication for each PF (0..3) */
|
||||
#define MFW_DRV_IND_READ_DONE_OFFSET(_pf_) (1 << (_pf_))
|
||||
union { /* For various OEMs */ /* Offset 0x1a0 */
|
||||
u8 storage_boot_prog[E2_FUNC_MAX];
|
||||
#define STORAGE_BOOT_PROG_MASK 0x000000FF
|
||||
#define STORAGE_BOOT_PROG_NONE 0x00000000
|
||||
#define STORAGE_BOOT_PROG_ISCSI_IP_ACQUIRED 0x00000002
|
||||
#define STORAGE_BOOT_PROG_FCOE_FABRIC_LOGIN_SUCCESS 0x00000002
|
||||
#define STORAGE_BOOT_PROG_TARGET_FOUND 0x00000004
|
||||
#define STORAGE_BOOT_PROG_ISCSI_CHAP_SUCCESS 0x00000008
|
||||
#define STORAGE_BOOT_PROG_FCOE_LUN_FOUND 0x00000008
|
||||
#define STORAGE_BOOT_PROG_LOGGED_INTO_TGT 0x00000010
|
||||
#define STORAGE_BOOT_PROG_IMG_DOWNLOADED 0x00000020
|
||||
#define STORAGE_BOOT_PROG_OS_HANDOFF 0x00000040
|
||||
#define STORAGE_BOOT_PROG_COMPLETED 0x00000080
|
||||
|
||||
u32 oem_i2c_data_addr;
|
||||
};
|
||||
|
||||
/* 9 entires for the C2S PCP map for each inner VLAN PCP + 1 default */
|
||||
/* For PCP values 0-3 use the map lower */
|
||||
/* 0xFF000000 - PCP 0, 0x00FF0000 - PCP 1,
|
||||
* 0x0000FF00 - PCP 2, 0x000000FF PCP 3
|
||||
*/
|
||||
u32 c2s_pcp_map_lower[E2_FUNC_MAX]; /* 0x1a4 */
|
||||
|
||||
/* For PCP values 4-7 use the map upper */
|
||||
/* 0xFF000000 - PCP 4, 0x00FF0000 - PCP 5,
|
||||
* 0x0000FF00 - PCP 6, 0x000000FF PCP 7
|
||||
*/
|
||||
u32 c2s_pcp_map_upper[E2_FUNC_MAX]; /* 0x1b4 */
|
||||
|
||||
/* For PCP default value get the MSB byte of the map default */
|
||||
u32 c2s_pcp_map_default[E2_FUNC_MAX]; /* 0x1c4 */
|
||||
|
||||
/* FC_NPIV table offset in NVRAM */
|
||||
u32 fc_npiv_nvram_tbl_addr[PORT_MAX]; /* 0x1d4 */
|
||||
|
||||
/* Shows last method that changed configuration of this device */
|
||||
enum curr_cfg_method_e curr_cfg; /* 0x1dc */
|
||||
|
||||
/* Storm FW version, shold be kept in the format 0xMMmmbbdd:
|
||||
* MM - Major, mm - Minor, bb - Build ,dd - Drop
|
||||
*/
|
||||
u32 netproc_fw_ver; /* 0x1e0 */
|
||||
|
||||
/* Option ROM SMASH CLP version */
|
||||
u32 clp_ver; /* 0x1e4 */
|
||||
|
||||
u32 pcie_bus_num; /* 0x1e8 */
|
||||
|
||||
u32 sriov_switch_mode; /* 0x1ec */
|
||||
#define SRIOV_SWITCH_MODE_NONE 0x0
|
||||
#define SRIOV_SWITCH_MODE_VEB 0x1
|
||||
#define SRIOV_SWITCH_MODE_VEPA 0x2
|
||||
|
||||
u8 rsrv2[E2_FUNC_MAX]; /* 0x1f0 */
|
||||
|
||||
u32 img_inv_table_addr; /* Address to INV_TABLE_P */ /* 0x1f4 */
|
||||
|
||||
u32 mtu_size[E2_FUNC_MAX]; /* 0x1f8 */
|
||||
|
||||
u32 os_driver_state[E2_FUNC_MAX]; /* 0x208 */
|
||||
#define OS_DRIVER_STATE_NOT_LOADED 0 /* not installed */
|
||||
#define OS_DRIVER_STATE_LOADING 1 /* transition state */
|
||||
#define OS_DRIVER_STATE_DISABLED 2 /* installed but disabled */
|
||||
#define OS_DRIVER_STATE_ACTIVE 3 /* installed and active */
|
||||
|
||||
/* mini dump driver info */
|
||||
struct mdump_driver_info drv_info; /* 0x218 */
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -2898,8 +3013,8 @@ struct afex_stats {
|
|||
};
|
||||
|
||||
#define BCM_5710_FW_MAJOR_VERSION 7
|
||||
#define BCM_5710_FW_MINOR_VERSION 10
|
||||
#define BCM_5710_FW_REVISION_VERSION 51
|
||||
#define BCM_5710_FW_MINOR_VERSION 12
|
||||
#define BCM_5710_FW_REVISION_VERSION 30
|
||||
#define BCM_5710_FW_ENGINEERING_VERSION 0
|
||||
#define BCM_5710_FW_COMPILE_FLAGS 1
|
||||
|
||||
|
|
@ -3901,7 +4016,11 @@ struct eth_fast_path_rx_cqe {
|
|||
__le16 len_on_bd;
|
||||
struct parsing_flags pars_flags;
|
||||
union eth_sgl_or_raw_data sgl_or_raw_data;
|
||||
__le32 reserved1[7];
|
||||
u8 tunn_type;
|
||||
u8 tunn_inner_hdrs_offset;
|
||||
__le16 reserved1;
|
||||
__le32 tunn_tenant_id;
|
||||
__le32 padding[5];
|
||||
u32 marker;
|
||||
};
|
||||
|
||||
|
|
@ -4012,8 +4131,8 @@ struct eth_tunnel_data {
|
|||
__le16 pseudo_csum;
|
||||
u8 ip_hdr_start_inner_w;
|
||||
u8 flags;
|
||||
#define ETH_TUNNEL_DATA_IP_HDR_TYPE_OUTER (0x1<<0)
|
||||
#define ETH_TUNNEL_DATA_IP_HDR_TYPE_OUTER_SHIFT 0
|
||||
#define ETH_TUNNEL_DATA_IPV6_OUTER (0x1<<0)
|
||||
#define ETH_TUNNEL_DATA_IPV6_OUTER_SHIFT 0
|
||||
#define ETH_TUNNEL_DATA_RESERVED (0x7F<<1)
|
||||
#define ETH_TUNNEL_DATA_RESERVED_SHIFT 1
|
||||
};
|
||||
|
|
@ -4120,16 +4239,12 @@ struct eth_rss_update_ramrod_data {
|
|||
#define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_UDP_CAPABILITY_SHIFT 6
|
||||
#define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_VXLAN_CAPABILITY (0x1<<7)
|
||||
#define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_VXLAN_CAPABILITY_SHIFT 7
|
||||
#define ETH_RSS_UPDATE_RAMROD_DATA_EN_5_TUPLE_CAPABILITY (0x1<<8)
|
||||
#define ETH_RSS_UPDATE_RAMROD_DATA_EN_5_TUPLE_CAPABILITY_SHIFT 8
|
||||
#define ETH_RSS_UPDATE_RAMROD_DATA_NVGRE_KEY_ENTROPY_CAPABILITY (0x1<<9)
|
||||
#define ETH_RSS_UPDATE_RAMROD_DATA_NVGRE_KEY_ENTROPY_CAPABILITY_SHIFT 9
|
||||
#define ETH_RSS_UPDATE_RAMROD_DATA_GRE_INNER_HDRS_CAPABILITY (0x1<<10)
|
||||
#define ETH_RSS_UPDATE_RAMROD_DATA_GRE_INNER_HDRS_CAPABILITY_SHIFT 10
|
||||
#define ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY (0x1<<11)
|
||||
#define ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY_SHIFT 11
|
||||
#define ETH_RSS_UPDATE_RAMROD_DATA_RESERVED (0xF<<12)
|
||||
#define ETH_RSS_UPDATE_RAMROD_DATA_RESERVED_SHIFT 12
|
||||
#define ETH_RSS_UPDATE_RAMROD_DATA_TUNN_INNER_HDRS_CAPABILITY (0x1<<8)
|
||||
#define ETH_RSS_UPDATE_RAMROD_DATA_TUNN_INNER_HDRS_CAPABILITY_SHIFT 8
|
||||
#define ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY (0x1<<9)
|
||||
#define ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY_SHIFT 9
|
||||
#define ETH_RSS_UPDATE_RAMROD_DATA_RESERVED (0x3F<<10)
|
||||
#define ETH_RSS_UPDATE_RAMROD_DATA_RESERVED_SHIFT 10
|
||||
u8 rss_result_mask;
|
||||
u8 reserved3;
|
||||
__le16 reserved4;
|
||||
|
|
@ -4314,6 +4429,18 @@ enum eth_tunnel_non_lso_csum_location {
|
|||
MAX_ETH_TUNNEL_NON_LSO_CSUM_LOCATION
|
||||
};
|
||||
|
||||
enum eth_tunn_type {
|
||||
TUNN_TYPE_NONE,
|
||||
TUNN_TYPE_VXLAN,
|
||||
TUNN_TYPE_L2_GRE,
|
||||
TUNN_TYPE_IPV4_GRE,
|
||||
TUNN_TYPE_IPV6_GRE,
|
||||
TUNN_TYPE_L2_GENEVE,
|
||||
TUNN_TYPE_IPV4_GENEVE,
|
||||
TUNN_TYPE_IPV6_GENEVE,
|
||||
MAX_ETH_TUNN_TYPE
|
||||
};
|
||||
|
||||
/*
|
||||
* Tx regular BD structure
|
||||
*/
|
||||
|
|
@ -4758,6 +4885,9 @@ struct afex_vif_list_ramrod_data {
|
|||
__le16 reserved1;
|
||||
};
|
||||
|
||||
struct c2s_pri_trans_table_entry {
|
||||
u8 val[MAX_VLAN_PRIORITIES];
|
||||
};
|
||||
|
||||
/*
|
||||
* cfc delete event data
|
||||
|
|
@ -5246,6 +5376,7 @@ struct flow_control_configuration {
|
|||
u8 dont_add_pri_0_en;
|
||||
u8 reserved1;
|
||||
__le32 reserved2;
|
||||
u8 dcb_outer_pri[MAX_TRAFFIC_TYPES];
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -5260,18 +5391,25 @@ struct function_start_data {
|
|||
u8 path_id;
|
||||
u8 network_cos_mode;
|
||||
u8 dmae_cmd_id;
|
||||
u8 tunnel_mode;
|
||||
u8 gre_tunnel_type;
|
||||
u8 tunn_clss_en;
|
||||
u8 inner_gre_rss_en;
|
||||
u8 sd_accept_mf_clss_fail;
|
||||
u8 no_added_tags;
|
||||
__le16 reserved0;
|
||||
__le32 reserved1;
|
||||
u8 inner_clss_vxlan;
|
||||
u8 inner_clss_l2gre;
|
||||
u8 inner_clss_l2geneve;
|
||||
u8 inner_rss;
|
||||
__le16 vxlan_dst_port;
|
||||
__le16 geneve_dst_port;
|
||||
u8 sd_accept_mf_clss_fail;
|
||||
u8 sd_accept_mf_clss_fail_match_ethtype;
|
||||
__le16 sd_accept_mf_clss_fail_ethtype;
|
||||
__le16 sd_vlan_eth_type;
|
||||
u8 sd_vlan_force_pri_flg;
|
||||
u8 sd_vlan_force_pri_val;
|
||||
u8 sd_accept_mf_clss_fail_match_ethtype;
|
||||
u8 no_added_tags;
|
||||
u8 c2s_pri_tt_valid;
|
||||
u8 c2s_pri_default;
|
||||
u8 reserved2[6];
|
||||
struct c2s_pri_trans_table_entry c2s_pri_trans_table;
|
||||
};
|
||||
|
||||
struct function_update_data {
|
||||
|
|
@ -5289,11 +5427,12 @@ struct function_update_data {
|
|||
u8 tx_switch_suspend;
|
||||
u8 echo;
|
||||
u8 update_tunn_cfg_flg;
|
||||
u8 tunnel_mode;
|
||||
u8 gre_tunnel_type;
|
||||
u8 tunn_clss_en;
|
||||
u8 inner_gre_rss_en;
|
||||
u8 inner_clss_vxlan;
|
||||
u8 inner_clss_l2gre;
|
||||
u8 inner_clss_l2geneve;
|
||||
u8 inner_rss;
|
||||
__le16 vxlan_dst_port;
|
||||
__le16 geneve_dst_port;
|
||||
u8 sd_vlan_force_pri_change_flg;
|
||||
u8 sd_vlan_force_pri_flg;
|
||||
u8 sd_vlan_force_pri_val;
|
||||
|
|
@ -5302,6 +5441,8 @@ struct function_update_data {
|
|||
u8 reserved1;
|
||||
__le16 sd_vlan_tag;
|
||||
__le16 sd_vlan_eth_type;
|
||||
__le16 reserved0;
|
||||
__le32 reserved2;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -5330,15 +5471,6 @@ struct fw_version {
|
|||
#define __FW_VERSION_RESERVED_SHIFT 4
|
||||
};
|
||||
|
||||
|
||||
/* GRE Tunnel Mode */
|
||||
enum gre_tunnel_type {
|
||||
NVGRE_TUNNEL,
|
||||
L2GRE_TUNNEL,
|
||||
IPGRE_TUNNEL,
|
||||
MAX_GRE_TUNNEL_TYPE
|
||||
};
|
||||
|
||||
/*
|
||||
* Dynamic Host-Coalescing - Driver(host) counters
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
/* bnx2x_init.h: Broadcom Everest network driver.
|
||||
/* bnx2x_init.h: Qlogic Everest network driver.
|
||||
* Structures and macroes needed during the initialization.
|
||||
*
|
||||
* Copyright (c) 2007-2013 Broadcom Corporation
|
||||
* Copyright (c) 2014 QLogic Corporation
|
||||
All rights reserved
|
||||
*
|
||||
* 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
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
/* bnx2x_init_ops.h: Broadcom Everest network driver.
|
||||
/* bnx2x_init_ops.h: Qlogic Everest network driver.
|
||||
* Static functions needed during the initialization.
|
||||
* This file is "included" in bnx2x_main.c.
|
||||
*
|
||||
* Copyright (c) 2007-2013 Broadcom Corporation
|
||||
* Copyright (c) 2014 QLogic Corporation
|
||||
All rights reserved
|
||||
*
|
||||
* 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
|
||||
|
|
|
|||
|
|
@ -1,13 +1,15 @@
|
|||
/* Copyright 2008-2013 Broadcom Corporation
|
||||
* Copyright (c) 2014 QLogic Corporation
|
||||
* All rights reserved
|
||||
*
|
||||
* Unless you and Broadcom execute a separate written software license
|
||||
* Unless you and QLogic execute a separate written software license
|
||||
* agreement governing use of this software, this software is licensed to you
|
||||
* under the terms of the GNU General Public License version 2, available
|
||||
* at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL").
|
||||
* at http://www.gnu.org/licenses/gpl-2.0.html (the "GPL").
|
||||
*
|
||||
* Notwithstanding the above, under no circumstances may you combine this
|
||||
* software in any way with any other Broadcom software provided under a
|
||||
* license other than the GPL, without Broadcom's express prior written
|
||||
* software in any way with any other Qlogic software provided under a
|
||||
* license other than the GPL, without Qlogic's express prior written
|
||||
* consent.
|
||||
*
|
||||
* Written by Yaniv Rosner
|
||||
|
|
@ -9652,6 +9654,13 @@ static void bnx2x_8727_link_reset(struct bnx2x_phy *phy,
|
|||
/******************************************************************/
|
||||
/* BCM8481/BCM84823/BCM84833 PHY SECTION */
|
||||
/******************************************************************/
|
||||
static int bnx2x_is_8483x_8485x(struct bnx2x_phy *phy)
|
||||
{
|
||||
return ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
|
||||
(phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834) ||
|
||||
(phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84858));
|
||||
}
|
||||
|
||||
static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy,
|
||||
struct bnx2x *bp,
|
||||
u8 port)
|
||||
|
|
@ -9666,8 +9675,7 @@ static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy,
|
|||
};
|
||||
u16 fw_ver1;
|
||||
|
||||
if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
|
||||
(phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) {
|
||||
if (bnx2x_is_8483x_8485x(phy)) {
|
||||
bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD, 0x400f, &fw_ver1);
|
||||
bnx2x_save_spirom_version(bp, port, fw_ver1 & 0xfff,
|
||||
phy->ver_addr);
|
||||
|
|
@ -9749,8 +9757,7 @@ static void bnx2x_848xx_set_led(struct bnx2x *bp,
|
|||
bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
|
||||
reg_set[i].val);
|
||||
|
||||
if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
|
||||
(phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834))
|
||||
if (bnx2x_is_8483x_8485x(phy))
|
||||
offset = MDIO_PMA_REG_84833_CTL_LED_CTL_1;
|
||||
else
|
||||
offset = MDIO_PMA_REG_84823_CTL_LED_CTL_1;
|
||||
|
|
@ -9768,8 +9775,7 @@ static void bnx2x_848xx_specific_func(struct bnx2x_phy *phy,
|
|||
struct bnx2x *bp = params->bp;
|
||||
switch (action) {
|
||||
case PHY_INIT:
|
||||
if ((phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) &&
|
||||
(phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) {
|
||||
if (!bnx2x_is_8483x_8485x(phy)) {
|
||||
/* Save spirom version */
|
||||
bnx2x_save_848xx_spirom_version(phy, bp, params->port);
|
||||
}
|
||||
|
|
@ -9901,8 +9907,7 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
|
|||
/* Always write this if this is not 84833/4.
|
||||
* For 84833/4, write it only when it's a forced speed.
|
||||
*/
|
||||
if (((phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) &&
|
||||
(phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) ||
|
||||
if (!bnx2x_is_8483x_8485x(phy) ||
|
||||
((autoneg_val & (1<<12)) == 0))
|
||||
bnx2x_cl45_write(bp, phy,
|
||||
MDIO_AN_DEVAD,
|
||||
|
|
@ -9949,8 +9954,86 @@ static int bnx2x_8481_config_init(struct bnx2x_phy *phy,
|
|||
return bnx2x_848xx_cmn_config_init(phy, params, vars);
|
||||
}
|
||||
|
||||
#define PHY84833_CMDHDLR_WAIT 300
|
||||
#define PHY84833_CMDHDLR_MAX_ARGS 5
|
||||
#define PHY848xx_CMDHDLR_WAIT 300
|
||||
#define PHY848xx_CMDHDLR_MAX_ARGS 5
|
||||
|
||||
static int bnx2x_84858_cmd_hdlr(struct bnx2x_phy *phy,
|
||||
struct link_params *params,
|
||||
u16 fw_cmd,
|
||||
u16 cmd_args[], int argc)
|
||||
{
|
||||
int idx;
|
||||
u16 val;
|
||||
struct bnx2x *bp = params->bp;
|
||||
|
||||
/* Step 1: Poll the STATUS register to see whether the previous command
|
||||
* is in progress or the system is busy (CMD_IN_PROGRESS or
|
||||
* SYSTEM_BUSY). If previous command is in progress or system is busy,
|
||||
* check again until the previous command finishes execution and the
|
||||
* system is available for taking command
|
||||
*/
|
||||
|
||||
for (idx = 0; idx < PHY848xx_CMDHDLR_WAIT; idx++) {
|
||||
bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
|
||||
MDIO_848xx_CMD_HDLR_STATUS, &val);
|
||||
if ((val != PHY84858_STATUS_CMD_IN_PROGRESS) &&
|
||||
(val != PHY84858_STATUS_CMD_SYSTEM_BUSY))
|
||||
break;
|
||||
usleep_range(1000, 2000);
|
||||
}
|
||||
if (idx >= PHY848xx_CMDHDLR_WAIT) {
|
||||
DP(NETIF_MSG_LINK, "FW cmd: FW not ready.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Step2: If any parameters are required for the function, write them
|
||||
* to the required DATA registers
|
||||
*/
|
||||
|
||||
for (idx = 0; idx < argc; idx++) {
|
||||
bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
|
||||
MDIO_848xx_CMD_HDLR_DATA1 + idx,
|
||||
cmd_args[idx]);
|
||||
}
|
||||
|
||||
/* Step3: When the firmware is ready for commands, write the 'Command
|
||||
* code' to the CMD register
|
||||
*/
|
||||
bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
|
||||
MDIO_848xx_CMD_HDLR_COMMAND, fw_cmd);
|
||||
|
||||
/* Step4: Once the command has been written, poll the STATUS register
|
||||
* to check whether the command has completed (CMD_COMPLETED_PASS/
|
||||
* CMD_FOR_CMDS or CMD_COMPLETED_ERROR).
|
||||
*/
|
||||
|
||||
for (idx = 0; idx < PHY848xx_CMDHDLR_WAIT; idx++) {
|
||||
bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
|
||||
MDIO_848xx_CMD_HDLR_STATUS, &val);
|
||||
if ((val == PHY84858_STATUS_CMD_COMPLETE_PASS) ||
|
||||
(val == PHY84858_STATUS_CMD_COMPLETE_ERROR))
|
||||
break;
|
||||
usleep_range(1000, 2000);
|
||||
}
|
||||
if ((idx >= PHY848xx_CMDHDLR_WAIT) ||
|
||||
(val == PHY84858_STATUS_CMD_COMPLETE_ERROR)) {
|
||||
DP(NETIF_MSG_LINK, "FW cmd failed.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
/* Step5: Once the command has completed, read the specficied DATA
|
||||
* registers for any saved results for the command, if applicable
|
||||
*/
|
||||
|
||||
/* Gather returning data */
|
||||
for (idx = 0; idx < argc; idx++) {
|
||||
bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
|
||||
MDIO_848xx_CMD_HDLR_DATA1 + idx,
|
||||
&cmd_args[idx]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bnx2x_84833_cmd_hdlr(struct bnx2x_phy *phy,
|
||||
struct link_params *params, u16 fw_cmd,
|
||||
u16 cmd_args[], int argc)
|
||||
|
|
@ -9960,16 +10043,16 @@ static int bnx2x_84833_cmd_hdlr(struct bnx2x_phy *phy,
|
|||
struct bnx2x *bp = params->bp;
|
||||
/* Write CMD_OPEN_OVERRIDE to STATUS reg */
|
||||
bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
|
||||
MDIO_84833_CMD_HDLR_STATUS,
|
||||
MDIO_848xx_CMD_HDLR_STATUS,
|
||||
PHY84833_STATUS_CMD_OPEN_OVERRIDE);
|
||||
for (idx = 0; idx < PHY84833_CMDHDLR_WAIT; idx++) {
|
||||
for (idx = 0; idx < PHY848xx_CMDHDLR_WAIT; idx++) {
|
||||
bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
|
||||
MDIO_84833_CMD_HDLR_STATUS, &val);
|
||||
MDIO_848xx_CMD_HDLR_STATUS, &val);
|
||||
if (val == PHY84833_STATUS_CMD_OPEN_FOR_CMDS)
|
||||
break;
|
||||
usleep_range(1000, 2000);
|
||||
}
|
||||
if (idx >= PHY84833_CMDHDLR_WAIT) {
|
||||
if (idx >= PHY848xx_CMDHDLR_WAIT) {
|
||||
DP(NETIF_MSG_LINK, "FW cmd: FW not ready.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -9977,42 +10060,62 @@ static int bnx2x_84833_cmd_hdlr(struct bnx2x_phy *phy,
|
|||
/* Prepare argument(s) and issue command */
|
||||
for (idx = 0; idx < argc; idx++) {
|
||||
bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
|
||||
MDIO_84833_CMD_HDLR_DATA1 + idx,
|
||||
MDIO_848xx_CMD_HDLR_DATA1 + idx,
|
||||
cmd_args[idx]);
|
||||
}
|
||||
bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
|
||||
MDIO_84833_CMD_HDLR_COMMAND, fw_cmd);
|
||||
for (idx = 0; idx < PHY84833_CMDHDLR_WAIT; idx++) {
|
||||
MDIO_848xx_CMD_HDLR_COMMAND, fw_cmd);
|
||||
for (idx = 0; idx < PHY848xx_CMDHDLR_WAIT; idx++) {
|
||||
bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
|
||||
MDIO_84833_CMD_HDLR_STATUS, &val);
|
||||
MDIO_848xx_CMD_HDLR_STATUS, &val);
|
||||
if ((val == PHY84833_STATUS_CMD_COMPLETE_PASS) ||
|
||||
(val == PHY84833_STATUS_CMD_COMPLETE_ERROR))
|
||||
(val == PHY84833_STATUS_CMD_COMPLETE_ERROR))
|
||||
break;
|
||||
usleep_range(1000, 2000);
|
||||
}
|
||||
if ((idx >= PHY84833_CMDHDLR_WAIT) ||
|
||||
(val == PHY84833_STATUS_CMD_COMPLETE_ERROR)) {
|
||||
if ((idx >= PHY848xx_CMDHDLR_WAIT) ||
|
||||
(val == PHY84833_STATUS_CMD_COMPLETE_ERROR)) {
|
||||
DP(NETIF_MSG_LINK, "FW cmd failed.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
/* Gather returning data */
|
||||
for (idx = 0; idx < argc; idx++) {
|
||||
bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
|
||||
MDIO_84833_CMD_HDLR_DATA1 + idx,
|
||||
MDIO_848xx_CMD_HDLR_DATA1 + idx,
|
||||
&cmd_args[idx]);
|
||||
}
|
||||
bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
|
||||
MDIO_84833_CMD_HDLR_STATUS,
|
||||
MDIO_848xx_CMD_HDLR_STATUS,
|
||||
PHY84833_STATUS_CMD_CLEAR_COMPLETE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bnx2x_84833_pair_swap_cfg(struct bnx2x_phy *phy,
|
||||
struct link_params *params,
|
||||
struct link_vars *vars)
|
||||
static int bnx2x_848xx_cmd_hdlr(struct bnx2x_phy *phy,
|
||||
struct link_params *params,
|
||||
u16 fw_cmd,
|
||||
u16 cmd_args[], int argc)
|
||||
{
|
||||
struct bnx2x *bp = params->bp;
|
||||
|
||||
if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84858) ||
|
||||
(REG_RD(bp, params->shmem2_base +
|
||||
offsetof(struct shmem2_region,
|
||||
link_attr_sync[params->port])) &
|
||||
LINK_ATTR_84858)) {
|
||||
return bnx2x_84858_cmd_hdlr(phy, params, fw_cmd, cmd_args,
|
||||
argc);
|
||||
} else {
|
||||
return bnx2x_84833_cmd_hdlr(phy, params, fw_cmd, cmd_args,
|
||||
argc);
|
||||
}
|
||||
}
|
||||
|
||||
static int bnx2x_848xx_pair_swap_cfg(struct bnx2x_phy *phy,
|
||||
struct link_params *params,
|
||||
struct link_vars *vars)
|
||||
{
|
||||
u32 pair_swap;
|
||||
u16 data[PHY84833_CMDHDLR_MAX_ARGS];
|
||||
u16 data[PHY848xx_CMDHDLR_MAX_ARGS];
|
||||
int status;
|
||||
struct bnx2x *bp = params->bp;
|
||||
|
||||
|
|
@ -10028,8 +10131,9 @@ static int bnx2x_84833_pair_swap_cfg(struct bnx2x_phy *phy,
|
|||
/* Only the second argument is used for this command */
|
||||
data[1] = (u16)pair_swap;
|
||||
|
||||
status = bnx2x_84833_cmd_hdlr(phy, params,
|
||||
PHY84833_CMD_SET_PAIR_SWAP, data, PHY84833_CMDHDLR_MAX_ARGS);
|
||||
status = bnx2x_848xx_cmd_hdlr(phy, params,
|
||||
PHY848xx_CMD_SET_PAIR_SWAP, data,
|
||||
PHY848xx_CMDHDLR_MAX_ARGS);
|
||||
if (status == 0)
|
||||
DP(NETIF_MSG_LINK, "Pairswap OK, val=0x%x\n", data[1]);
|
||||
|
||||
|
|
@ -10118,8 +10222,8 @@ static int bnx2x_8483x_disable_eee(struct bnx2x_phy *phy,
|
|||
DP(NETIF_MSG_LINK, "Don't Advertise 10GBase-T EEE\n");
|
||||
|
||||
/* Prevent Phy from working in EEE and advertising it */
|
||||
rc = bnx2x_84833_cmd_hdlr(phy, params,
|
||||
PHY84833_CMD_SET_EEE_MODE, &cmd_args, 1);
|
||||
rc = bnx2x_848xx_cmd_hdlr(phy, params,
|
||||
PHY848xx_CMD_SET_EEE_MODE, &cmd_args, 1);
|
||||
if (rc) {
|
||||
DP(NETIF_MSG_LINK, "EEE disable failed.\n");
|
||||
return rc;
|
||||
|
|
@ -10136,8 +10240,8 @@ static int bnx2x_8483x_enable_eee(struct bnx2x_phy *phy,
|
|||
struct bnx2x *bp = params->bp;
|
||||
u16 cmd_args = 1;
|
||||
|
||||
rc = bnx2x_84833_cmd_hdlr(phy, params,
|
||||
PHY84833_CMD_SET_EEE_MODE, &cmd_args, 1);
|
||||
rc = bnx2x_848xx_cmd_hdlr(phy, params,
|
||||
PHY848xx_CMD_SET_EEE_MODE, &cmd_args, 1);
|
||||
if (rc) {
|
||||
DP(NETIF_MSG_LINK, "EEE enable failed.\n");
|
||||
return rc;
|
||||
|
|
@ -10155,7 +10259,7 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
|
|||
u8 port, initialize = 1;
|
||||
u16 val;
|
||||
u32 actual_phy_selection;
|
||||
u16 cmd_args[PHY84833_CMDHDLR_MAX_ARGS];
|
||||
u16 cmd_args[PHY848xx_CMDHDLR_MAX_ARGS];
|
||||
int rc = 0;
|
||||
|
||||
usleep_range(1000, 2000);
|
||||
|
|
@ -10180,8 +10284,7 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
|
|||
|
||||
/* Wait for GPHY to come out of reset */
|
||||
msleep(50);
|
||||
if ((phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) &&
|
||||
(phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) {
|
||||
if (!bnx2x_is_8483x_8485x(phy)) {
|
||||
/* BCM84823 requires that XGXS links up first @ 10G for normal
|
||||
* behavior.
|
||||
*/
|
||||
|
|
@ -10192,7 +10295,19 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
|
|||
bnx2x_program_serdes(¶ms->phy[INT_PHY], params, vars);
|
||||
vars->line_speed = temp;
|
||||
}
|
||||
/* Check if this is actually BCM84858 */
|
||||
if (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84858) {
|
||||
u16 hw_rev;
|
||||
|
||||
bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
|
||||
MDIO_AN_REG_848xx_ID_MSB, &hw_rev);
|
||||
if (hw_rev == BCM84858_PHY_ID) {
|
||||
params->link_attr_sync |= LINK_ATTR_84858;
|
||||
bnx2x_update_link_attr(params, params->link_attr_sync);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set dual-media configuration according to configuration */
|
||||
bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
|
||||
MDIO_CTL_REG_84823_MEDIA, &val);
|
||||
val &= ~(MDIO_CTL_REG_84823_MEDIA_MAC_MASK |
|
||||
|
|
@ -10237,18 +10352,17 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
|
|||
DP(NETIF_MSG_LINK, "Multi_phy config = 0x%x, Media control = 0x%x\n",
|
||||
params->multi_phy_config, val);
|
||||
|
||||
if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
|
||||
(phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) {
|
||||
bnx2x_84833_pair_swap_cfg(phy, params, vars);
|
||||
if (bnx2x_is_8483x_8485x(phy)) {
|
||||
bnx2x_848xx_pair_swap_cfg(phy, params, vars);
|
||||
|
||||
/* Keep AutogrEEEn disabled. */
|
||||
cmd_args[0] = 0x0;
|
||||
cmd_args[1] = 0x0;
|
||||
cmd_args[2] = PHY84833_CONSTANT_LATENCY + 1;
|
||||
cmd_args[3] = PHY84833_CONSTANT_LATENCY;
|
||||
rc = bnx2x_84833_cmd_hdlr(phy, params,
|
||||
PHY84833_CMD_SET_EEE_MODE, cmd_args,
|
||||
PHY84833_CMDHDLR_MAX_ARGS);
|
||||
rc = bnx2x_848xx_cmd_hdlr(phy, params,
|
||||
PHY848xx_CMD_SET_EEE_MODE, cmd_args,
|
||||
PHY848xx_CMDHDLR_MAX_ARGS);
|
||||
if (rc)
|
||||
DP(NETIF_MSG_LINK, "Cfg AutogrEEEn failed.\n");
|
||||
}
|
||||
|
|
@ -10302,8 +10416,7 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
|
|||
vars->eee_status &= ~SHMEM_EEE_SUPPORTED_MASK;
|
||||
}
|
||||
|
||||
if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
|
||||
(phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) {
|
||||
if (bnx2x_is_8483x_8485x(phy)) {
|
||||
/* Bring PHY out of super isolate mode as the final step. */
|
||||
bnx2x_cl45_read_and_write(bp, phy,
|
||||
MDIO_CTL_DEVAD,
|
||||
|
|
@ -10435,8 +10548,7 @@ static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy,
|
|||
LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE;
|
||||
|
||||
/* Determine if EEE was negotiated */
|
||||
if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
|
||||
(phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834))
|
||||
if (bnx2x_is_8483x_8485x(phy))
|
||||
bnx2x_eee_an_resolve(phy, params, vars);
|
||||
}
|
||||
|
||||
|
|
@ -11842,6 +11954,40 @@ static const struct bnx2x_phy phy_84834 = {
|
|||
.phy_specific_func = (phy_specific_func_t)bnx2x_848xx_specific_func
|
||||
};
|
||||
|
||||
static const struct bnx2x_phy phy_84858 = {
|
||||
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84858,
|
||||
.addr = 0xff,
|
||||
.def_md_devad = 0,
|
||||
.flags = FLAGS_FAN_FAILURE_DET_REQ |
|
||||
FLAGS_REARM_LATCH_SIGNAL,
|
||||
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
|
||||
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
|
||||
.mdio_ctrl = 0,
|
||||
.supported = (SUPPORTED_100baseT_Half |
|
||||
SUPPORTED_100baseT_Full |
|
||||
SUPPORTED_1000baseT_Full |
|
||||
SUPPORTED_10000baseT_Full |
|
||||
SUPPORTED_TP |
|
||||
SUPPORTED_Autoneg |
|
||||
SUPPORTED_Pause |
|
||||
SUPPORTED_Asym_Pause),
|
||||
.media_type = ETH_PHY_BASE_T,
|
||||
.ver_addr = 0,
|
||||
.req_flow_ctrl = 0,
|
||||
.req_line_speed = 0,
|
||||
.speed_cap_mask = 0,
|
||||
.req_duplex = 0,
|
||||
.rsrv = 0,
|
||||
.config_init = (config_init_t)bnx2x_848x3_config_init,
|
||||
.read_status = (read_status_t)bnx2x_848xx_read_status,
|
||||
.link_reset = (link_reset_t)bnx2x_848x3_link_reset,
|
||||
.config_loopback = (config_loopback_t)NULL,
|
||||
.format_fw_ver = (format_fw_ver_t)bnx2x_848xx_format_ver,
|
||||
.hw_reset = (hw_reset_t)bnx2x_84833_hw_reset_phy,
|
||||
.set_link_led = (set_link_led_t)bnx2x_848xx_set_link_led,
|
||||
.phy_specific_func = (phy_specific_func_t)bnx2x_848xx_specific_func
|
||||
};
|
||||
|
||||
static const struct bnx2x_phy phy_54618se = {
|
||||
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE,
|
||||
.addr = 0xff,
|
||||
|
|
@ -12128,6 +12274,9 @@ static int bnx2x_populate_ext_phy(struct bnx2x *bp,
|
|||
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834:
|
||||
*phy = phy_84834;
|
||||
break;
|
||||
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84858:
|
||||
*phy = phy_84858;
|
||||
break;
|
||||
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54616:
|
||||
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE:
|
||||
*phy = phy_54618se;
|
||||
|
|
@ -12184,9 +12333,7 @@ static int bnx2x_populate_ext_phy(struct bnx2x *bp,
|
|||
}
|
||||
phy->mdio_ctrl = bnx2x_get_emac_base(bp, mdc_mdio_access, port);
|
||||
|
||||
if (((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
|
||||
(phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) &&
|
||||
(phy->ver_addr)) {
|
||||
if (bnx2x_is_8483x_8485x(phy) && (phy->ver_addr)) {
|
||||
/* Remove 100Mb link supported for BCM84833/4 when phy fw
|
||||
* version lower than or equal to 1.39
|
||||
*/
|
||||
|
|
@ -13281,6 +13428,7 @@ static int bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base_path[],
|
|||
break;
|
||||
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833:
|
||||
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834:
|
||||
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84858:
|
||||
/* GPIO3's are linked, and so both need to be toggled
|
||||
* to obtain required 2us pulse.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,13 +1,15 @@
|
|||
/* Copyright 2008-2013 Broadcom Corporation
|
||||
* Copyright (c) 2014 QLogic Corporation
|
||||
* All rights reserved
|
||||
*
|
||||
* Unless you and Broadcom execute a separate written software license
|
||||
* Unless you and QLogic execute a separate written software license
|
||||
* agreement governing use of this software, this software is licensed to you
|
||||
* under the terms of the GNU General Public License version 2, available
|
||||
* at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL").
|
||||
* at http://www.gnu.org/licenses/gpl-2.0.html (the "GPL").
|
||||
*
|
||||
* Notwithstanding the above, under no circumstances may you combine this
|
||||
* software in any way with any other Broadcom software provided under a
|
||||
* license other than the GPL, without Broadcom's express prior written
|
||||
* software in any way with any other Qlogic software provided under a
|
||||
* license other than the GPL, without Qlogic's express prior written
|
||||
* consent.
|
||||
*
|
||||
* Written by Yaniv Rosner
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
/* bnx2x_main.c: Broadcom Everest network driver.
|
||||
/* bnx2x_main.c: QLogic Everest network driver.
|
||||
*
|
||||
* Copyright (c) 2007-2013 Broadcom Corporation
|
||||
* Copyright (c) 2014 QLogic Corporation
|
||||
* All rights reserved
|
||||
*
|
||||
* 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
|
||||
|
|
@ -81,11 +83,11 @@
|
|||
#define TX_TIMEOUT (5*HZ)
|
||||
|
||||
static char version[] =
|
||||
"Broadcom NetXtreme II 5771x/578xx 10/20-Gigabit Ethernet Driver "
|
||||
"QLogic 5771x/578xx 10/20-Gigabit Ethernet Driver "
|
||||
DRV_MODULE_NAME " " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
|
||||
|
||||
MODULE_AUTHOR("Eliezer Tamir");
|
||||
MODULE_DESCRIPTION("Broadcom NetXtreme II "
|
||||
MODULE_DESCRIPTION("QLogic "
|
||||
"BCM57710/57711/57711E/"
|
||||
"57712/57712_MF/57800/57800_MF/57810/57810_MF/"
|
||||
"57840/57840_MF Driver");
|
||||
|
|
@ -163,27 +165,27 @@ enum bnx2x_board_type {
|
|||
static struct {
|
||||
char *name;
|
||||
} board_info[] = {
|
||||
[BCM57710] = { "Broadcom NetXtreme II BCM57710 10 Gigabit PCIe [Everest]" },
|
||||
[BCM57711] = { "Broadcom NetXtreme II BCM57711 10 Gigabit PCIe" },
|
||||
[BCM57711E] = { "Broadcom NetXtreme II BCM57711E 10 Gigabit PCIe" },
|
||||
[BCM57712] = { "Broadcom NetXtreme II BCM57712 10 Gigabit Ethernet" },
|
||||
[BCM57712_MF] = { "Broadcom NetXtreme II BCM57712 10 Gigabit Ethernet Multi Function" },
|
||||
[BCM57712_VF] = { "Broadcom NetXtreme II BCM57712 10 Gigabit Ethernet Virtual Function" },
|
||||
[BCM57800] = { "Broadcom NetXtreme II BCM57800 10 Gigabit Ethernet" },
|
||||
[BCM57800_MF] = { "Broadcom NetXtreme II BCM57800 10 Gigabit Ethernet Multi Function" },
|
||||
[BCM57800_VF] = { "Broadcom NetXtreme II BCM57800 10 Gigabit Ethernet Virtual Function" },
|
||||
[BCM57810] = { "Broadcom NetXtreme II BCM57810 10 Gigabit Ethernet" },
|
||||
[BCM57810_MF] = { "Broadcom NetXtreme II BCM57810 10 Gigabit Ethernet Multi Function" },
|
||||
[BCM57810_VF] = { "Broadcom NetXtreme II BCM57810 10 Gigabit Ethernet Virtual Function" },
|
||||
[BCM57840_4_10] = { "Broadcom NetXtreme II BCM57840 10 Gigabit Ethernet" },
|
||||
[BCM57840_2_20] = { "Broadcom NetXtreme II BCM57840 20 Gigabit Ethernet" },
|
||||
[BCM57840_MF] = { "Broadcom NetXtreme II BCM57840 10/20 Gigabit Ethernet Multi Function" },
|
||||
[BCM57840_VF] = { "Broadcom NetXtreme II BCM57840 10/20 Gigabit Ethernet Virtual Function" },
|
||||
[BCM57811] = { "Broadcom NetXtreme II BCM57811 10 Gigabit Ethernet" },
|
||||
[BCM57811_MF] = { "Broadcom NetXtreme II BCM57811 10 Gigabit Ethernet Multi Function" },
|
||||
[BCM57840_O] = { "Broadcom NetXtreme II BCM57840 10/20 Gigabit Ethernet" },
|
||||
[BCM57840_MFO] = { "Broadcom NetXtreme II BCM57840 10/20 Gigabit Ethernet Multi Function" },
|
||||
[BCM57811_VF] = { "Broadcom NetXtreme II BCM57840 10/20 Gigabit Ethernet Virtual Function" }
|
||||
[BCM57710] = { "QLogic BCM57710 10 Gigabit PCIe [Everest]" },
|
||||
[BCM57711] = { "QLogic BCM57711 10 Gigabit PCIe" },
|
||||
[BCM57711E] = { "QLogic BCM57711E 10 Gigabit PCIe" },
|
||||
[BCM57712] = { "QLogic BCM57712 10 Gigabit Ethernet" },
|
||||
[BCM57712_MF] = { "QLogic BCM57712 10 Gigabit Ethernet Multi Function" },
|
||||
[BCM57712_VF] = { "QLogic BCM57712 10 Gigabit Ethernet Virtual Function" },
|
||||
[BCM57800] = { "QLogic BCM57800 10 Gigabit Ethernet" },
|
||||
[BCM57800_MF] = { "QLogic BCM57800 10 Gigabit Ethernet Multi Function" },
|
||||
[BCM57800_VF] = { "QLogic BCM57800 10 Gigabit Ethernet Virtual Function" },
|
||||
[BCM57810] = { "QLogic BCM57810 10 Gigabit Ethernet" },
|
||||
[BCM57810_MF] = { "QLogic BCM57810 10 Gigabit Ethernet Multi Function" },
|
||||
[BCM57810_VF] = { "QLogic BCM57810 10 Gigabit Ethernet Virtual Function" },
|
||||
[BCM57840_4_10] = { "QLogic BCM57840 10 Gigabit Ethernet" },
|
||||
[BCM57840_2_20] = { "QLogic BCM57840 20 Gigabit Ethernet" },
|
||||
[BCM57840_MF] = { "QLogic BCM57840 10/20 Gigabit Ethernet Multi Function" },
|
||||
[BCM57840_VF] = { "QLogic BCM57840 10/20 Gigabit Ethernet Virtual Function" },
|
||||
[BCM57811] = { "QLogic BCM57811 10 Gigabit Ethernet" },
|
||||
[BCM57811_MF] = { "QLogic BCM57811 10 Gigabit Ethernet Multi Function" },
|
||||
[BCM57840_O] = { "QLogic BCM57840 10/20 Gigabit Ethernet" },
|
||||
[BCM57840_MFO] = { "QLogic BCM57840 10/20 Gigabit Ethernet Multi Function" },
|
||||
[BCM57811_VF] = { "QLogic BCM57840 10/20 Gigabit Ethernet Virtual Function" }
|
||||
};
|
||||
|
||||
#ifndef PCI_DEVICE_ID_NX2_57710
|
||||
|
|
@ -264,11 +266,14 @@ static const struct pci_device_id bnx2x_pci_tbl[] = {
|
|||
{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57810_MF), BCM57810_MF },
|
||||
{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57840_O), BCM57840_O },
|
||||
{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57840_4_10), BCM57840_4_10 },
|
||||
{ PCI_VDEVICE(QLOGIC, PCI_DEVICE_ID_NX2_57840_4_10), BCM57840_4_10 },
|
||||
{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57840_2_20), BCM57840_2_20 },
|
||||
{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57810_VF), BCM57810_VF },
|
||||
{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57840_MFO), BCM57840_MFO },
|
||||
{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57840_MF), BCM57840_MF },
|
||||
{ PCI_VDEVICE(QLOGIC, PCI_DEVICE_ID_NX2_57840_MF), BCM57840_MF },
|
||||
{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57840_VF), BCM57840_VF },
|
||||
{ PCI_VDEVICE(QLOGIC, PCI_DEVICE_ID_NX2_57840_VF), BCM57840_VF },
|
||||
{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57811), BCM57811 },
|
||||
{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57811_MF), BCM57811_MF },
|
||||
{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57811_VF), BCM57811_VF },
|
||||
|
|
@ -2492,7 +2497,7 @@ static void bnx2x_calc_vn_max(struct bnx2x *bp, int vn,
|
|||
else {
|
||||
u32 maxCfg = bnx2x_extract_max_cfg(bp, vn_cfg);
|
||||
|
||||
if (IS_MF_SI(bp)) {
|
||||
if (IS_MF_PERCENT_BW(bp)) {
|
||||
/* maxCfg in percents of linkspeed */
|
||||
vn_max_rate = (bp->link_vars.line_speed * maxCfg) / 100;
|
||||
} else /* SD modes */
|
||||
|
|
@ -2916,7 +2921,7 @@ static void bnx2x_handle_update_svid_cmd(struct bnx2x *bp)
|
|||
func_params.f_obj = &bp->func_obj;
|
||||
func_params.cmd = BNX2X_F_CMD_SWITCH_UPDATE;
|
||||
|
||||
if (IS_MF_UFP(bp)) {
|
||||
if (IS_MF_UFP(bp) || IS_MF_BD(bp)) {
|
||||
int func = BP_ABS_FUNC(bp);
|
||||
u32 val;
|
||||
|
||||
|
|
@ -2943,16 +2948,16 @@ static void bnx2x_handle_update_svid_cmd(struct bnx2x *bp)
|
|||
BNX2X_ERR("Failed to configure FW of S-tag Change to %02x\n",
|
||||
bp->mf_ov);
|
||||
goto fail;
|
||||
} else {
|
||||
DP(BNX2X_MSG_MCP, "Configured S-tag %02x\n",
|
||||
bp->mf_ov);
|
||||
}
|
||||
|
||||
DP(BNX2X_MSG_MCP, "Configured S-tag %02x\n", bp->mf_ov);
|
||||
|
||||
bnx2x_fw_command(bp, DRV_MSG_CODE_OEM_UPDATE_SVID_OK, 0);
|
||||
|
||||
return;
|
||||
} else {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* not supported by SW yet */
|
||||
bnx2x_fw_command(bp, DRV_MSG_CODE_OEM_UPDATE_SVID_OK, 0);
|
||||
return;
|
||||
fail:
|
||||
bnx2x_fw_command(bp, DRV_MSG_CODE_OEM_UPDATE_SVID_FAILURE, 0);
|
||||
}
|
||||
|
|
@ -3065,7 +3070,7 @@ void bnx2x_func_init(struct bnx2x *bp, struct bnx2x_func_init_params *p)
|
|||
storm_memset_func_en(bp, p->func_id, 1);
|
||||
|
||||
/* spq */
|
||||
if (p->func_flgs & FUNC_FLG_SPQ) {
|
||||
if (p->spq_active) {
|
||||
storm_memset_spq_addr(bp, p->spq_map, p->func_id);
|
||||
REG_WR(bp, XSEM_REG_FAST_MEMORY +
|
||||
XSTORM_SPQ_PROD_OFFSET(p->func_id), p->spq_prod);
|
||||
|
|
@ -3281,7 +3286,6 @@ static void bnx2x_pf_init(struct bnx2x *bp)
|
|||
{
|
||||
struct bnx2x_func_init_params func_init = {0};
|
||||
struct event_ring_data eq_data = { {0} };
|
||||
u16 flags;
|
||||
|
||||
if (!CHIP_IS_E1x(bp)) {
|
||||
/* reset IGU PF statistics: MSIX + ATTN */
|
||||
|
|
@ -3298,15 +3302,7 @@ static void bnx2x_pf_init(struct bnx2x *bp)
|
|||
BP_FUNC(bp) : BP_VN(bp))*4, 0);
|
||||
}
|
||||
|
||||
/* function setup flags */
|
||||
flags = (FUNC_FLG_STATS | FUNC_FLG_LEADING | FUNC_FLG_SPQ);
|
||||
|
||||
/* This flag is relevant for E1x only.
|
||||
* E2 doesn't have a TPA configuration in a function level.
|
||||
*/
|
||||
flags |= (bp->dev->features & NETIF_F_LRO) ? FUNC_FLG_TPA : 0;
|
||||
|
||||
func_init.func_flgs = flags;
|
||||
func_init.spq_active = true;
|
||||
func_init.pf_id = BP_FUNC(bp);
|
||||
func_init.func_id = BP_FUNC(bp);
|
||||
func_init.spq_map = bp->spq_mapping;
|
||||
|
|
@ -3707,6 +3703,34 @@ out:
|
|||
ethver, iscsiver, fcoever);
|
||||
}
|
||||
|
||||
void bnx2x_update_mfw_dump(struct bnx2x *bp)
|
||||
{
|
||||
struct timeval epoc;
|
||||
u32 drv_ver;
|
||||
u32 valid_dump;
|
||||
|
||||
if (!SHMEM2_HAS(bp, drv_info))
|
||||
return;
|
||||
|
||||
/* Update Driver load time */
|
||||
do_gettimeofday(&epoc);
|
||||
SHMEM2_WR(bp, drv_info.epoc, epoc.tv_sec);
|
||||
|
||||
drv_ver = bnx2x_update_mng_version_utility(DRV_MODULE_VERSION, true);
|
||||
SHMEM2_WR(bp, drv_info.drv_ver, drv_ver);
|
||||
|
||||
SHMEM2_WR(bp, drv_info.fw_ver, REG_RD(bp, XSEM_REG_PRAM));
|
||||
|
||||
/* Check & notify On-Chip dump. */
|
||||
valid_dump = SHMEM2_RD(bp, drv_info.valid_dump);
|
||||
|
||||
if (valid_dump & FIRST_DUMP_VALID)
|
||||
DP(NETIF_MSG_IFUP, "A valid On-Chip MFW dump found on 1st partition\n");
|
||||
|
||||
if (valid_dump & SECOND_DUMP_VALID)
|
||||
DP(NETIF_MSG_IFUP, "A valid On-Chip MFW dump found on 2nd partition\n");
|
||||
}
|
||||
|
||||
static void bnx2x_oem_event(struct bnx2x *bp, u32 event)
|
||||
{
|
||||
u32 cmd_ok, cmd_fail;
|
||||
|
|
@ -5273,6 +5297,10 @@ static void bnx2x_handle_classification_eqe(struct bnx2x *bp,
|
|||
else
|
||||
vlan_mac_obj = &bp->sp_objs[cid].mac_obj;
|
||||
|
||||
break;
|
||||
case BNX2X_FILTER_VLAN_PENDING:
|
||||
DP(BNX2X_MSG_SP, "Got SETUP_VLAN completions\n");
|
||||
vlan_mac_obj = &bp->sp_objs[cid].vlan_obj;
|
||||
break;
|
||||
case BNX2X_FILTER_MCAST_PENDING:
|
||||
DP(BNX2X_MSG_SP, "Got SETUP_MCAST completions\n");
|
||||
|
|
@ -5568,6 +5596,8 @@ static void bnx2x_eq_int(struct bnx2x *bp)
|
|||
BNX2X_STATE_OPEN):
|
||||
case (EVENT_RING_OPCODE_RSS_UPDATE_RULES |
|
||||
BNX2X_STATE_OPENING_WAIT4_PORT):
|
||||
case (EVENT_RING_OPCODE_RSS_UPDATE_RULES |
|
||||
BNX2X_STATE_CLOSING_WAIT4_HALT):
|
||||
cid = elem->message.data.eth_event.echo &
|
||||
BNX2X_SWCID_MASK;
|
||||
DP(BNX2X_MSG_SP, "got RSS_UPDATE ramrod. CID %d\n",
|
||||
|
|
@ -5585,7 +5615,7 @@ static void bnx2x_eq_int(struct bnx2x *bp)
|
|||
BNX2X_STATE_DIAG):
|
||||
case (EVENT_RING_OPCODE_CLASSIFICATION_RULES |
|
||||
BNX2X_STATE_CLOSING_WAIT4_HALT):
|
||||
DP(BNX2X_MSG_SP, "got (un)set mac ramrod\n");
|
||||
DP(BNX2X_MSG_SP, "got (un)set vlan/mac ramrod\n");
|
||||
bnx2x_handle_classification_eqe(bp, elem);
|
||||
break;
|
||||
|
||||
|
|
@ -6173,6 +6203,11 @@ static int bnx2x_fill_accept_flags(struct bnx2x *bp, u32 rx_mode,
|
|||
__set_bit(BNX2X_ACCEPT_MULTICAST, tx_accept_flags);
|
||||
__set_bit(BNX2X_ACCEPT_BROADCAST, tx_accept_flags);
|
||||
|
||||
if (bp->accept_any_vlan) {
|
||||
__set_bit(BNX2X_ACCEPT_ANY_VLAN, rx_accept_flags);
|
||||
__set_bit(BNX2X_ACCEPT_ANY_VLAN, tx_accept_flags);
|
||||
}
|
||||
|
||||
break;
|
||||
case BNX2X_RX_MODE_ALLMULTI:
|
||||
__set_bit(BNX2X_ACCEPT_UNICAST, rx_accept_flags);
|
||||
|
|
@ -6184,6 +6219,11 @@ static int bnx2x_fill_accept_flags(struct bnx2x *bp, u32 rx_mode,
|
|||
__set_bit(BNX2X_ACCEPT_ALL_MULTICAST, tx_accept_flags);
|
||||
__set_bit(BNX2X_ACCEPT_BROADCAST, tx_accept_flags);
|
||||
|
||||
if (bp->accept_any_vlan) {
|
||||
__set_bit(BNX2X_ACCEPT_ANY_VLAN, rx_accept_flags);
|
||||
__set_bit(BNX2X_ACCEPT_ANY_VLAN, tx_accept_flags);
|
||||
}
|
||||
|
||||
break;
|
||||
case BNX2X_RX_MODE_PROMISC:
|
||||
/* According to definition of SI mode, iface in promisc mode
|
||||
|
|
@ -6204,18 +6244,15 @@ static int bnx2x_fill_accept_flags(struct bnx2x *bp, u32 rx_mode,
|
|||
else
|
||||
__set_bit(BNX2X_ACCEPT_UNICAST, tx_accept_flags);
|
||||
|
||||
__set_bit(BNX2X_ACCEPT_ANY_VLAN, rx_accept_flags);
|
||||
__set_bit(BNX2X_ACCEPT_ANY_VLAN, tx_accept_flags);
|
||||
|
||||
break;
|
||||
default:
|
||||
BNX2X_ERR("Unknown rx_mode: %d\n", rx_mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Set ACCEPT_ANY_VLAN as we do not enable filtering by VLAN */
|
||||
if (rx_mode != BNX2X_RX_MODE_NONE) {
|
||||
__set_bit(BNX2X_ACCEPT_ANY_VLAN, rx_accept_flags);
|
||||
__set_bit(BNX2X_ACCEPT_ANY_VLAN, tx_accept_flags);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -7429,6 +7466,9 @@ static int bnx2x_init_hw_common(struct bnx2x *bp)
|
|||
} else
|
||||
BNX2X_ERR("Bootcode is missing - can not initialize link\n");
|
||||
|
||||
if (SHMEM2_HAS(bp, netproc_fw_ver))
|
||||
SHMEM2_WR(bp, netproc_fw_ver, REG_RD(bp, XSEM_REG_PRAM));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -8406,6 +8446,42 @@ int bnx2x_set_mac_one(struct bnx2x *bp, u8 *mac,
|
|||
return rc;
|
||||
}
|
||||
|
||||
int bnx2x_set_vlan_one(struct bnx2x *bp, u16 vlan,
|
||||
struct bnx2x_vlan_mac_obj *obj, bool set,
|
||||
unsigned long *ramrod_flags)
|
||||
{
|
||||
int rc;
|
||||
struct bnx2x_vlan_mac_ramrod_params ramrod_param;
|
||||
|
||||
memset(&ramrod_param, 0, sizeof(ramrod_param));
|
||||
|
||||
/* Fill general parameters */
|
||||
ramrod_param.vlan_mac_obj = obj;
|
||||
ramrod_param.ramrod_flags = *ramrod_flags;
|
||||
|
||||
/* Fill a user request section if needed */
|
||||
if (!test_bit(RAMROD_CONT, ramrod_flags)) {
|
||||
ramrod_param.user_req.u.vlan.vlan = vlan;
|
||||
/* Set the command: ADD or DEL */
|
||||
if (set)
|
||||
ramrod_param.user_req.cmd = BNX2X_VLAN_MAC_ADD;
|
||||
else
|
||||
ramrod_param.user_req.cmd = BNX2X_VLAN_MAC_DEL;
|
||||
}
|
||||
|
||||
rc = bnx2x_config_vlan_mac(bp, &ramrod_param);
|
||||
|
||||
if (rc == -EEXIST) {
|
||||
/* Do not treat adding same vlan as error. */
|
||||
DP(BNX2X_MSG_SP, "Failed to schedule ADD operations: %d\n", rc);
|
||||
rc = 0;
|
||||
} else if (rc < 0) {
|
||||
BNX2X_ERR("%s VLAN failed\n", (set ? "Set" : "Del"));
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int bnx2x_del_all_macs(struct bnx2x *bp,
|
||||
struct bnx2x_vlan_mac_obj *mac_obj,
|
||||
int mac_type, bool wait_for_comp)
|
||||
|
|
@ -10002,6 +10078,81 @@ static void bnx2x_parity_recover(struct bnx2x *bp)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BNX2X_VXLAN
|
||||
static int bnx2x_vxlan_port_update(struct bnx2x *bp, u16 port)
|
||||
{
|
||||
struct bnx2x_func_switch_update_params *switch_update_params;
|
||||
struct bnx2x_func_state_params func_params = {NULL};
|
||||
int rc;
|
||||
|
||||
switch_update_params = &func_params.params.switch_update;
|
||||
|
||||
/* Prepare parameters for function state transitions */
|
||||
__set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags);
|
||||
__set_bit(RAMROD_RETRY, &func_params.ramrod_flags);
|
||||
|
||||
func_params.f_obj = &bp->func_obj;
|
||||
func_params.cmd = BNX2X_F_CMD_SWITCH_UPDATE;
|
||||
|
||||
/* Function parameters */
|
||||
__set_bit(BNX2X_F_UPDATE_TUNNEL_CFG_CHNG,
|
||||
&switch_update_params->changes);
|
||||
switch_update_params->vxlan_dst_port = port;
|
||||
rc = bnx2x_func_state_change(bp, &func_params);
|
||||
if (rc)
|
||||
BNX2X_ERR("failed to change vxlan dst port to %d (rc = 0x%x)\n",
|
||||
port, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void __bnx2x_add_vxlan_port(struct bnx2x *bp, u16 port)
|
||||
{
|
||||
if (!netif_running(bp->dev))
|
||||
return;
|
||||
|
||||
if (bp->vxlan_dst_port || !IS_PF(bp)) {
|
||||
DP(BNX2X_MSG_SP, "Vxlan destination port limit reached\n");
|
||||
return;
|
||||
}
|
||||
|
||||
bp->vxlan_dst_port = port;
|
||||
bnx2x_schedule_sp_rtnl(bp, BNX2X_SP_RTNL_ADD_VXLAN_PORT, 0);
|
||||
}
|
||||
|
||||
static void bnx2x_add_vxlan_port(struct net_device *netdev,
|
||||
sa_family_t sa_family, __be16 port)
|
||||
{
|
||||
struct bnx2x *bp = netdev_priv(netdev);
|
||||
u16 t_port = ntohs(port);
|
||||
|
||||
__bnx2x_add_vxlan_port(bp, t_port);
|
||||
}
|
||||
|
||||
static void __bnx2x_del_vxlan_port(struct bnx2x *bp, u16 port)
|
||||
{
|
||||
if (!bp->vxlan_dst_port || bp->vxlan_dst_port != port || !IS_PF(bp)) {
|
||||
DP(BNX2X_MSG_SP, "Invalid vxlan port\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (netif_running(bp->dev)) {
|
||||
bnx2x_schedule_sp_rtnl(bp, BNX2X_SP_RTNL_DEL_VXLAN_PORT, 0);
|
||||
} else {
|
||||
bp->vxlan_dst_port = 0;
|
||||
netdev_info(bp->dev, "Deleted vxlan dest port %d", port);
|
||||
}
|
||||
}
|
||||
|
||||
static void bnx2x_del_vxlan_port(struct net_device *netdev,
|
||||
sa_family_t sa_family, __be16 port)
|
||||
{
|
||||
struct bnx2x *bp = netdev_priv(netdev);
|
||||
u16 t_port = ntohs(port);
|
||||
|
||||
__bnx2x_del_vxlan_port(bp, t_port);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int bnx2x_close(struct net_device *dev);
|
||||
|
||||
/* bnx2x_nic_unload() flushes the bnx2x_wq, thus reset task is
|
||||
|
|
@ -10010,6 +10161,9 @@ static int bnx2x_close(struct net_device *dev);
|
|||
static void bnx2x_sp_rtnl_task(struct work_struct *work)
|
||||
{
|
||||
struct bnx2x *bp = container_of(work, struct bnx2x, sp_rtnl_task.work);
|
||||
#ifdef CONFIG_BNX2X_VXLAN
|
||||
u16 port;
|
||||
#endif
|
||||
|
||||
rtnl_lock();
|
||||
|
||||
|
|
@ -10108,6 +10262,27 @@ sp_rtnl_not_reset:
|
|||
&bp->sp_rtnl_state))
|
||||
bnx2x_update_mng_version(bp);
|
||||
|
||||
#ifdef CONFIG_BNX2X_VXLAN
|
||||
port = bp->vxlan_dst_port;
|
||||
if (test_and_clear_bit(BNX2X_SP_RTNL_ADD_VXLAN_PORT,
|
||||
&bp->sp_rtnl_state)) {
|
||||
if (!bnx2x_vxlan_port_update(bp, port))
|
||||
netdev_info(bp->dev, "Added vxlan dest port %d", port);
|
||||
else
|
||||
bp->vxlan_dst_port = 0;
|
||||
}
|
||||
|
||||
if (test_and_clear_bit(BNX2X_SP_RTNL_DEL_VXLAN_PORT,
|
||||
&bp->sp_rtnl_state)) {
|
||||
if (!bnx2x_vxlan_port_update(bp, 0)) {
|
||||
netdev_info(bp->dev,
|
||||
"Deleted vxlan dest port %d", port);
|
||||
bp->vxlan_dst_port = 0;
|
||||
vxlan_get_rx_port(bp->dev);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* work which needs rtnl lock not-taken (as it takes the lock itself and
|
||||
* can be called from other contexts as well)
|
||||
*/
|
||||
|
|
@ -11678,7 +11853,7 @@ static void validate_set_si_mode(struct bnx2x *bp)
|
|||
static int bnx2x_get_hwinfo(struct bnx2x *bp)
|
||||
{
|
||||
int /*abs*/func = BP_ABS_FUNC(bp);
|
||||
int vn;
|
||||
int vn, mfw_vn;
|
||||
u32 val = 0, val2 = 0;
|
||||
int rc = 0;
|
||||
|
||||
|
|
@ -11768,6 +11943,7 @@ static int bnx2x_get_hwinfo(struct bnx2x *bp)
|
|||
bp->mf_mode = 0;
|
||||
bp->mf_sub_mode = 0;
|
||||
vn = BP_VN(bp);
|
||||
mfw_vn = BP_FW_MB_IDX(bp);
|
||||
|
||||
if (!CHIP_IS_E1(bp) && !BP_NOMCP(bp)) {
|
||||
BNX2X_DEV_INFO("shmem2base 0x%x, size %d, mfcfg offset %d\n",
|
||||
|
|
@ -11824,6 +12000,31 @@ static int bnx2x_get_hwinfo(struct bnx2x *bp)
|
|||
} else
|
||||
BNX2X_DEV_INFO("illegal OV for SD\n");
|
||||
break;
|
||||
case SHARED_FEAT_CFG_FORCE_SF_MODE_BD_MODE:
|
||||
bp->mf_mode = MULTI_FUNCTION_SD;
|
||||
bp->mf_sub_mode = SUB_MF_MODE_BD;
|
||||
bp->mf_config[vn] =
|
||||
MF_CFG_RD(bp,
|
||||
func_mf_config[func].config);
|
||||
|
||||
if (SHMEM2_HAS(bp, mtu_size)) {
|
||||
int mtu_idx = BP_FW_MB_IDX(bp);
|
||||
u16 mtu_size;
|
||||
u32 mtu;
|
||||
|
||||
mtu = SHMEM2_RD(bp, mtu_size[mtu_idx]);
|
||||
mtu_size = (u16)mtu;
|
||||
DP(NETIF_MSG_IFUP, "Read MTU size %04x [%08x]\n",
|
||||
mtu_size, mtu);
|
||||
|
||||
/* if valid: update device mtu */
|
||||
if (((mtu_size + ETH_HLEN) >=
|
||||
ETH_MIN_PACKET_SIZE) &&
|
||||
(mtu_size <=
|
||||
ETH_MAX_JUMBO_PACKET_SIZE))
|
||||
bp->dev->mtu = mtu_size;
|
||||
}
|
||||
break;
|
||||
case SHARED_FEAT_CFG_FORCE_SF_MODE_UFP_MODE:
|
||||
bp->mf_mode = MULTI_FUNCTION_SD;
|
||||
bp->mf_sub_mode = SUB_MF_MODE_UFP;
|
||||
|
|
@ -11871,9 +12072,10 @@ static int bnx2x_get_hwinfo(struct bnx2x *bp)
|
|||
|
||||
BNX2X_DEV_INFO("MF OV for func %d is %d (0x%04x)\n",
|
||||
func, bp->mf_ov, bp->mf_ov);
|
||||
} else if (bp->mf_sub_mode == SUB_MF_MODE_UFP) {
|
||||
} else if ((bp->mf_sub_mode == SUB_MF_MODE_UFP) ||
|
||||
(bp->mf_sub_mode == SUB_MF_MODE_BD)) {
|
||||
dev_err(&bp->pdev->dev,
|
||||
"Unexpected - no valid MF OV for func %d in UFP mode\n",
|
||||
"Unexpected - no valid MF OV for func %d in UFP/BD mode\n",
|
||||
func);
|
||||
bp->path_has_ovlan = true;
|
||||
} else {
|
||||
|
|
@ -12078,6 +12280,7 @@ static int bnx2x_init_bp(struct bnx2x *bp)
|
|||
mutex_init(&bp->drv_info_mutex);
|
||||
sema_init(&bp->stats_lock, 1);
|
||||
bp->drv_info_mng_owner = false;
|
||||
INIT_LIST_HEAD(&bp->vlan_reg);
|
||||
|
||||
INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task);
|
||||
INIT_DELAYED_WORK(&bp->sp_rtnl_task, bnx2x_sp_rtnl_task);
|
||||
|
|
@ -12278,6 +12481,12 @@ static int bnx2x_open(struct net_device *dev)
|
|||
rc = bnx2x_nic_load(bp, LOAD_OPEN);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
#ifdef CONFIG_BNX2X_VXLAN
|
||||
if (IS_PF(bp))
|
||||
vxlan_get_rx_port(dev);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -12596,6 +12805,169 @@ static netdev_features_t bnx2x_features_check(struct sk_buff *skb,
|
|||
return vxlan_features_check(skb, features);
|
||||
}
|
||||
|
||||
static int __bnx2x_vlan_configure_vid(struct bnx2x *bp, u16 vid, bool add)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (IS_PF(bp)) {
|
||||
unsigned long ramrod_flags = 0;
|
||||
|
||||
__set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
|
||||
rc = bnx2x_set_vlan_one(bp, vid, &bp->sp_objs->vlan_obj,
|
||||
add, &ramrod_flags);
|
||||
} else {
|
||||
rc = bnx2x_vfpf_update_vlan(bp, vid, bp->fp->index, add);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int bnx2x_vlan_reconfigure_vid(struct bnx2x *bp)
|
||||
{
|
||||
struct bnx2x_vlan_entry *vlan;
|
||||
int rc = 0;
|
||||
|
||||
if (!bp->vlan_cnt) {
|
||||
DP(NETIF_MSG_IFUP, "No need to re-configure vlan filters\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
list_for_each_entry(vlan, &bp->vlan_reg, link) {
|
||||
/* Prepare for cleanup in case of errors */
|
||||
if (rc) {
|
||||
vlan->hw = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!vlan->hw)
|
||||
continue;
|
||||
|
||||
DP(NETIF_MSG_IFUP, "Re-configuring vlan 0x%04x\n", vlan->vid);
|
||||
|
||||
rc = __bnx2x_vlan_configure_vid(bp, vlan->vid, true);
|
||||
if (rc) {
|
||||
BNX2X_ERR("Unable to configure VLAN %d\n", vlan->vid);
|
||||
vlan->hw = false;
|
||||
rc = -EINVAL;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bnx2x_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid)
|
||||
{
|
||||
struct bnx2x *bp = netdev_priv(dev);
|
||||
struct bnx2x_vlan_entry *vlan;
|
||||
bool hw = false;
|
||||
int rc = 0;
|
||||
|
||||
if (!netif_running(bp->dev)) {
|
||||
DP(NETIF_MSG_IFUP,
|
||||
"Ignoring VLAN configuration the interface is down\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
DP(NETIF_MSG_IFUP, "Adding VLAN %d\n", vid);
|
||||
|
||||
vlan = kmalloc(sizeof(*vlan), GFP_KERNEL);
|
||||
if (!vlan)
|
||||
return -ENOMEM;
|
||||
|
||||
bp->vlan_cnt++;
|
||||
if (bp->vlan_cnt > bp->vlan_credit && !bp->accept_any_vlan) {
|
||||
DP(NETIF_MSG_IFUP, "Accept all VLAN raised\n");
|
||||
bp->accept_any_vlan = true;
|
||||
if (IS_PF(bp))
|
||||
bnx2x_set_rx_mode_inner(bp);
|
||||
else
|
||||
bnx2x_vfpf_storm_rx_mode(bp);
|
||||
} else if (bp->vlan_cnt <= bp->vlan_credit) {
|
||||
rc = __bnx2x_vlan_configure_vid(bp, vid, true);
|
||||
hw = true;
|
||||
}
|
||||
|
||||
vlan->vid = vid;
|
||||
vlan->hw = hw;
|
||||
|
||||
if (!rc) {
|
||||
list_add(&vlan->link, &bp->vlan_reg);
|
||||
} else {
|
||||
bp->vlan_cnt--;
|
||||
kfree(vlan);
|
||||
}
|
||||
|
||||
DP(NETIF_MSG_IFUP, "Adding VLAN result %d\n", rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bnx2x_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, u16 vid)
|
||||
{
|
||||
struct bnx2x *bp = netdev_priv(dev);
|
||||
struct bnx2x_vlan_entry *vlan;
|
||||
int rc = 0;
|
||||
|
||||
if (!netif_running(bp->dev)) {
|
||||
DP(NETIF_MSG_IFUP,
|
||||
"Ignoring VLAN configuration the interface is down\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
DP(NETIF_MSG_IFUP, "Removing VLAN %d\n", vid);
|
||||
|
||||
if (!bp->vlan_cnt) {
|
||||
BNX2X_ERR("Unable to kill VLAN %d\n", vid);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
list_for_each_entry(vlan, &bp->vlan_reg, link)
|
||||
if (vlan->vid == vid)
|
||||
break;
|
||||
|
||||
if (vlan->vid != vid) {
|
||||
BNX2X_ERR("Unable to kill VLAN %d - not found\n", vid);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (vlan->hw)
|
||||
rc = __bnx2x_vlan_configure_vid(bp, vid, false);
|
||||
|
||||
list_del(&vlan->link);
|
||||
kfree(vlan);
|
||||
|
||||
bp->vlan_cnt--;
|
||||
|
||||
if (bp->vlan_cnt <= bp->vlan_credit && bp->accept_any_vlan) {
|
||||
/* Configure all non-configured entries */
|
||||
list_for_each_entry(vlan, &bp->vlan_reg, link) {
|
||||
if (vlan->hw)
|
||||
continue;
|
||||
|
||||
rc = __bnx2x_vlan_configure_vid(bp, vlan->vid, true);
|
||||
if (rc) {
|
||||
BNX2X_ERR("Unable to config VLAN %d\n",
|
||||
vlan->vid);
|
||||
continue;
|
||||
}
|
||||
DP(NETIF_MSG_IFUP, "HW configured for VLAN %d\n",
|
||||
vlan->vid);
|
||||
vlan->hw = true;
|
||||
}
|
||||
DP(NETIF_MSG_IFUP, "Accept all VLAN Removed\n");
|
||||
bp->accept_any_vlan = false;
|
||||
if (IS_PF(bp))
|
||||
bnx2x_set_rx_mode_inner(bp);
|
||||
else
|
||||
bnx2x_vfpf_storm_rx_mode(bp);
|
||||
}
|
||||
|
||||
DP(NETIF_MSG_IFUP, "Removing VLAN result %d\n", rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static const struct net_device_ops bnx2x_netdev_ops = {
|
||||
.ndo_open = bnx2x_open,
|
||||
.ndo_stop = bnx2x_close,
|
||||
|
|
@ -12609,6 +12981,8 @@ static const struct net_device_ops bnx2x_netdev_ops = {
|
|||
.ndo_fix_features = bnx2x_fix_features,
|
||||
.ndo_set_features = bnx2x_set_features,
|
||||
.ndo_tx_timeout = bnx2x_tx_timeout,
|
||||
.ndo_vlan_rx_add_vid = bnx2x_vlan_rx_add_vid,
|
||||
.ndo_vlan_rx_kill_vid = bnx2x_vlan_rx_kill_vid,
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
.ndo_poll_controller = poll_bnx2x,
|
||||
#endif
|
||||
|
|
@ -12628,6 +13002,10 @@ static const struct net_device_ops bnx2x_netdev_ops = {
|
|||
.ndo_get_phys_port_id = bnx2x_get_phys_port_id,
|
||||
.ndo_set_vf_link_state = bnx2x_set_vf_link_state,
|
||||
.ndo_features_check = bnx2x_features_check,
|
||||
#ifdef CONFIG_BNX2X_VXLAN
|
||||
.ndo_add_vxlan_port = bnx2x_add_vxlan_port,
|
||||
.ndo_del_vxlan_port = bnx2x_del_vxlan_port,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int bnx2x_set_coherency_mask(struct bnx2x *bp)
|
||||
|
|
@ -12819,6 +13197,18 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev,
|
|||
dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
|
||||
NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_HIGHDMA;
|
||||
|
||||
/* VF with OLD Hypervisor or old PF do not support filtering */
|
||||
if (IS_PF(bp)) {
|
||||
if (CHIP_IS_E1x(bp))
|
||||
bp->accept_any_vlan = true;
|
||||
else
|
||||
dev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
|
||||
#ifdef CONFIG_BNX2X_SRIOV
|
||||
} else if (bp->acquire_resp.pfdev_info.pf_cap & PFVF_CAP_VLAN_FILTER) {
|
||||
dev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
|
||||
#endif
|
||||
}
|
||||
|
||||
dev->features |= dev->hw_features | NETIF_F_HW_VLAN_CTAG_RX;
|
||||
dev->features |= NETIF_F_HIGHDMA;
|
||||
|
||||
|
|
@ -13561,6 +13951,9 @@ static int bnx2x_init_one(struct pci_dev *pdev,
|
|||
|
||||
bnx2x_register_phc(bp);
|
||||
|
||||
if (!IS_MF_SD_STORAGE_PERSONALITY_ONLY(bp))
|
||||
bnx2x_set_os_driver_state(bp, OS_DRIVER_STATE_DISABLED);
|
||||
|
||||
return 0;
|
||||
|
||||
init_one_exit:
|
||||
|
|
@ -13623,6 +14016,7 @@ static void __bnx2x_remove(struct pci_dev *pdev,
|
|||
/* Power on: we can't let PCI layer write to us while we are in D3 */
|
||||
if (IS_PF(bp)) {
|
||||
bnx2x_set_power_state(bp, PCI_D0);
|
||||
bnx2x_set_os_driver_state(bp, OS_DRIVER_STATE_NOT_LOADED);
|
||||
|
||||
/* Set endianity registers to reset values in case next driver
|
||||
* boots in different endianty environment.
|
||||
|
|
@ -14371,6 +14765,90 @@ static int bnx2x_drv_ctl(struct net_device *dev, struct drv_ctl_info *ctl)
|
|||
rc = -EINVAL;
|
||||
}
|
||||
|
||||
/* For storage-only interfaces, change driver state */
|
||||
if (IS_MF_SD_STORAGE_PERSONALITY_ONLY(bp)) {
|
||||
switch (ctl->drv_state) {
|
||||
case DRV_NOP:
|
||||
break;
|
||||
case DRV_ACTIVE:
|
||||
bnx2x_set_os_driver_state(bp,
|
||||
OS_DRIVER_STATE_ACTIVE);
|
||||
break;
|
||||
case DRV_INACTIVE:
|
||||
bnx2x_set_os_driver_state(bp,
|
||||
OS_DRIVER_STATE_DISABLED);
|
||||
break;
|
||||
case DRV_UNLOADED:
|
||||
bnx2x_set_os_driver_state(bp,
|
||||
OS_DRIVER_STATE_NOT_LOADED);
|
||||
break;
|
||||
default:
|
||||
BNX2X_ERR("Unknown cnic driver state: %d\n", ctl->drv_state);
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bnx2x_get_fc_npiv(struct net_device *dev,
|
||||
struct cnic_fc_npiv_tbl *cnic_tbl)
|
||||
{
|
||||
struct bnx2x *bp = netdev_priv(dev);
|
||||
struct bdn_fc_npiv_tbl *tbl = NULL;
|
||||
u32 offset, entries;
|
||||
int rc = -EINVAL;
|
||||
int i;
|
||||
|
||||
if (!SHMEM2_HAS(bp, fc_npiv_nvram_tbl_addr[0]))
|
||||
goto out;
|
||||
|
||||
DP(BNX2X_MSG_MCP, "About to read the FC-NPIV table\n");
|
||||
|
||||
tbl = kmalloc(sizeof(*tbl), GFP_KERNEL);
|
||||
if (!tbl) {
|
||||
BNX2X_ERR("Failed to allocate fc_npiv table\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
offset = SHMEM2_RD(bp, fc_npiv_nvram_tbl_addr[BP_PORT(bp)]);
|
||||
DP(BNX2X_MSG_MCP, "Offset of FC-NPIV in NVRAM: %08x\n", offset);
|
||||
|
||||
/* Read the table contents from nvram */
|
||||
if (bnx2x_nvram_read(bp, offset, (u8 *)tbl, sizeof(*tbl))) {
|
||||
BNX2X_ERR("Failed to read FC-NPIV table\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Since bnx2x_nvram_read() returns data in be32, we need to convert
|
||||
* the number of entries back to cpu endianness.
|
||||
*/
|
||||
entries = tbl->fc_npiv_cfg.num_of_npiv;
|
||||
entries = (__force u32)be32_to_cpu((__force __be32)entries);
|
||||
tbl->fc_npiv_cfg.num_of_npiv = entries;
|
||||
|
||||
if (!tbl->fc_npiv_cfg.num_of_npiv) {
|
||||
DP(BNX2X_MSG_MCP,
|
||||
"No FC-NPIV table [valid, simply not present]\n");
|
||||
goto out;
|
||||
} else if (tbl->fc_npiv_cfg.num_of_npiv > MAX_NUMBER_NPIV) {
|
||||
BNX2X_ERR("FC-NPIV table with bad length 0x%08x\n",
|
||||
tbl->fc_npiv_cfg.num_of_npiv);
|
||||
goto out;
|
||||
} else {
|
||||
DP(BNX2X_MSG_MCP, "Read 0x%08x entries from NVRAM\n",
|
||||
tbl->fc_npiv_cfg.num_of_npiv);
|
||||
}
|
||||
|
||||
/* Copy the data into cnic-provided struct */
|
||||
cnic_tbl->count = tbl->fc_npiv_cfg.num_of_npiv;
|
||||
for (i = 0; i < cnic_tbl->count; i++) {
|
||||
memcpy(cnic_tbl->wwpn[i], tbl->settings[i].npiv_wwpn, 8);
|
||||
memcpy(cnic_tbl->wwnn[i], tbl->settings[i].npiv_wwnn, 8);
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
out:
|
||||
kfree(tbl);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
@ -14516,6 +14994,7 @@ static struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *dev)
|
|||
cp->starting_cid = bnx2x_cid_ilt_lines(bp) * ILT_PAGE_CIDS;
|
||||
cp->drv_submit_kwqes_16 = bnx2x_cnic_sp_queue;
|
||||
cp->drv_ctl = bnx2x_drv_ctl;
|
||||
cp->drv_get_fc_npiv_tbl = bnx2x_get_fc_npiv;
|
||||
cp->drv_register_cnic = bnx2x_register_cnic;
|
||||
cp->drv_unregister_cnic = bnx2x_unregister_cnic;
|
||||
cp->fcoe_init_cid = BNX2X_FCOE_ETH_CID(bp);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
/* bnx2x_mfw_req.h: Broadcom Everest network driver.
|
||||
/* bnx2x_mfw_req.h: Qlogic Everest network driver.
|
||||
*
|
||||
* Copyright (c) 2012-2013 Broadcom Corporation
|
||||
* Copyright (c) 2014 QLogic Corporation
|
||||
* All rights reserved
|
||||
*
|
||||
* 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
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
/* bnx2x_reg.h: Broadcom Everest network driver.
|
||||
/* bnx2x_reg.h: Qlogic Everest network driver.
|
||||
*
|
||||
* Copyright (c) 2007-2013 Broadcom Corporation
|
||||
* Copyright (c) 2014 QLogic Corporation
|
||||
* All rights reserved
|
||||
*
|
||||
* 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
|
||||
|
|
@ -2137,6 +2139,10 @@
|
|||
/* [RW 1] When this bit is set; the LLH will expect all packets to be with
|
||||
e1hov */
|
||||
#define NIG_REG_LLH_E1HOV_MODE 0x160d8
|
||||
/* [RW 16] Outer VLAN type identifier for multi-function mode. In non
|
||||
* multi-function mode; it will hold the inner VLAN type. Typically 0x8100.
|
||||
*/
|
||||
#define NIG_REG_LLH_E1HOV_TYPE_1 0x16028
|
||||
/* [RW 1] When this bit is set; the LLH will classify the packet before
|
||||
sending it to the BRB or calculating WoL on it. */
|
||||
#define NIG_REG_LLH_MF_MODE 0x16024
|
||||
|
|
@ -2953,7 +2959,12 @@
|
|||
#define PBF_REG_TQ_OCCUPANCY_Q0 0x1403ac
|
||||
/* [R 13] Number of 8 bytes lines occupied in the task queue of queue 1. */
|
||||
#define PBF_REG_TQ_OCCUPANCY_Q1 0x1403b0
|
||||
#define PB_REG_CONTROL 0
|
||||
/* [RW 16] One of 8 values that should be compared to type in Ethernet
|
||||
* parsing. If there is a match; the field after Ethernet is the first VLAN.
|
||||
* Reset value is 0x8100 which is the standard VLAN type. Note that when
|
||||
* checking second VLAN; type is compared only to 0x8100.
|
||||
*/
|
||||
#define PBF_REG_VLAN_TYPE_0 0x15c06c
|
||||
/* [RW 2] Interrupt mask register #0 read/write */
|
||||
#define PB_REG_PB_INT_MASK 0x28
|
||||
/* [R 2] Interrupt register #0 read */
|
||||
|
|
@ -3372,6 +3383,12 @@
|
|||
#define PRS_REG_TCM_CURRENT_CREDIT 0x40160
|
||||
/* [R 8] debug only: TSDM current credit. Transaction based. */
|
||||
#define PRS_REG_TSDM_CURRENT_CREDIT 0x4015c
|
||||
/* [RW 16] One of 8 values that should be compared to type in Ethernet
|
||||
* parsing. If there is a match; the field after Ethernet is the first VLAN.
|
||||
* Reset value is 0x8100 which is the standard VLAN type. Note that when
|
||||
* checking second VLAN; type is compared only to 0x8100.
|
||||
*/
|
||||
#define PRS_REG_VLAN_TYPE_0 0x401a8
|
||||
#define PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_AFT (0x1<<19)
|
||||
#define PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_OF (0x1<<20)
|
||||
#define PXP2_PXP2_INT_MASK_0_REG_PGL_PCIE_ATTN (0x1<<22)
|
||||
|
|
@ -7240,6 +7257,9 @@ Theotherbitsarereservedandshouldbezero*/
|
|||
#define MDIO_AN_REG_8481_LEGACY_MII_CTRL 0xffe0
|
||||
#define MDIO_AN_REG_8481_MII_CTRL_FORCE_1G 0x40
|
||||
#define MDIO_AN_REG_8481_LEGACY_MII_STATUS 0xffe1
|
||||
#define MDIO_AN_REG_848xx_ID_MSB 0xffe2
|
||||
#define BCM84858_PHY_ID 0x600d
|
||||
#define MDIO_AN_REG_848xx_ID_LSB 0xffe3
|
||||
#define MDIO_AN_REG_8481_LEGACY_AN_ADV 0xffe4
|
||||
#define MDIO_AN_REG_8481_LEGACY_AN_EXPANSION 0xffe6
|
||||
#define MDIO_AN_REG_8481_1000T_CTRL 0xffe9
|
||||
|
|
@ -7283,31 +7303,31 @@ Theotherbitsarereservedandshouldbezero*/
|
|||
#define MDIO_84833_TOP_CFG_FW_NO_EEE 0x1f81
|
||||
#define MDIO_84833_TOP_CFG_XGPHY_STRAP1 0x401a
|
||||
#define MDIO_84833_SUPER_ISOLATE 0x8000
|
||||
/* These are mailbox register set used by 84833. */
|
||||
#define MDIO_84833_TOP_CFG_SCRATCH_REG0 0x4005
|
||||
#define MDIO_84833_TOP_CFG_SCRATCH_REG1 0x4006
|
||||
#define MDIO_84833_TOP_CFG_SCRATCH_REG2 0x4007
|
||||
#define MDIO_84833_TOP_CFG_SCRATCH_REG3 0x4008
|
||||
#define MDIO_84833_TOP_CFG_SCRATCH_REG4 0x4009
|
||||
#define MDIO_84833_TOP_CFG_SCRATCH_REG26 0x4037
|
||||
#define MDIO_84833_TOP_CFG_SCRATCH_REG27 0x4038
|
||||
#define MDIO_84833_TOP_CFG_SCRATCH_REG28 0x4039
|
||||
#define MDIO_84833_TOP_CFG_SCRATCH_REG29 0x403a
|
||||
#define MDIO_84833_TOP_CFG_SCRATCH_REG30 0x403b
|
||||
#define MDIO_84833_TOP_CFG_SCRATCH_REG31 0x403c
|
||||
#define MDIO_84833_CMD_HDLR_COMMAND MDIO_84833_TOP_CFG_SCRATCH_REG0
|
||||
#define MDIO_84833_CMD_HDLR_STATUS MDIO_84833_TOP_CFG_SCRATCH_REG26
|
||||
#define MDIO_84833_CMD_HDLR_DATA1 MDIO_84833_TOP_CFG_SCRATCH_REG27
|
||||
#define MDIO_84833_CMD_HDLR_DATA2 MDIO_84833_TOP_CFG_SCRATCH_REG28
|
||||
#define MDIO_84833_CMD_HDLR_DATA3 MDIO_84833_TOP_CFG_SCRATCH_REG29
|
||||
#define MDIO_84833_CMD_HDLR_DATA4 MDIO_84833_TOP_CFG_SCRATCH_REG30
|
||||
#define MDIO_84833_CMD_HDLR_DATA5 MDIO_84833_TOP_CFG_SCRATCH_REG31
|
||||
/* These are mailbox register set used by 84833/84858. */
|
||||
#define MDIO_848xx_TOP_CFG_SCRATCH_REG0 0x4005
|
||||
#define MDIO_848xx_TOP_CFG_SCRATCH_REG1 0x4006
|
||||
#define MDIO_848xx_TOP_CFG_SCRATCH_REG2 0x4007
|
||||
#define MDIO_848xx_TOP_CFG_SCRATCH_REG3 0x4008
|
||||
#define MDIO_848xx_TOP_CFG_SCRATCH_REG4 0x4009
|
||||
#define MDIO_848xx_TOP_CFG_SCRATCH_REG26 0x4037
|
||||
#define MDIO_848xx_TOP_CFG_SCRATCH_REG27 0x4038
|
||||
#define MDIO_848xx_TOP_CFG_SCRATCH_REG28 0x4039
|
||||
#define MDIO_848xx_TOP_CFG_SCRATCH_REG29 0x403a
|
||||
#define MDIO_848xx_TOP_CFG_SCRATCH_REG30 0x403b
|
||||
#define MDIO_848xx_TOP_CFG_SCRATCH_REG31 0x403c
|
||||
#define MDIO_848xx_CMD_HDLR_COMMAND (MDIO_848xx_TOP_CFG_SCRATCH_REG0)
|
||||
#define MDIO_848xx_CMD_HDLR_STATUS (MDIO_848xx_TOP_CFG_SCRATCH_REG26)
|
||||
#define MDIO_848xx_CMD_HDLR_DATA1 (MDIO_848xx_TOP_CFG_SCRATCH_REG27)
|
||||
#define MDIO_848xx_CMD_HDLR_DATA2 (MDIO_848xx_TOP_CFG_SCRATCH_REG28)
|
||||
#define MDIO_848xx_CMD_HDLR_DATA3 (MDIO_848xx_TOP_CFG_SCRATCH_REG29)
|
||||
#define MDIO_848xx_CMD_HDLR_DATA4 (MDIO_848xx_TOP_CFG_SCRATCH_REG30)
|
||||
#define MDIO_848xx_CMD_HDLR_DATA5 (MDIO_848xx_TOP_CFG_SCRATCH_REG31)
|
||||
|
||||
/* Mailbox command set used by 84833. */
|
||||
#define PHY84833_CMD_SET_PAIR_SWAP 0x8001
|
||||
#define PHY84833_CMD_GET_EEE_MODE 0x8008
|
||||
#define PHY84833_CMD_SET_EEE_MODE 0x8009
|
||||
/* Mailbox status set used by 84833. */
|
||||
/* Mailbox command set used by 84833/84858 */
|
||||
#define PHY848xx_CMD_SET_PAIR_SWAP 0x8001
|
||||
#define PHY848xx_CMD_GET_EEE_MODE 0x8008
|
||||
#define PHY848xx_CMD_SET_EEE_MODE 0x8009
|
||||
/* Mailbox status set used by 84833 only */
|
||||
#define PHY84833_STATUS_CMD_RECEIVED 0x0001
|
||||
#define PHY84833_STATUS_CMD_IN_PROGRESS 0x0002
|
||||
#define PHY84833_STATUS_CMD_COMPLETE_PASS 0x0004
|
||||
|
|
@ -7318,6 +7338,13 @@ Theotherbitsarereservedandshouldbezero*/
|
|||
#define PHY84833_STATUS_CMD_CLEAR_COMPLETE 0x0080
|
||||
#define PHY84833_STATUS_CMD_OPEN_OVERRIDE 0xa5a5
|
||||
|
||||
/* Mailbox status set used by 84858 only */
|
||||
#define PHY84858_STATUS_CMD_RECEIVED 0x0001
|
||||
#define PHY84858_STATUS_CMD_IN_PROGRESS 0x0002
|
||||
#define PHY84858_STATUS_CMD_COMPLETE_PASS 0x0004
|
||||
#define PHY84858_STATUS_CMD_COMPLETE_ERROR 0x0008
|
||||
#define PHY84858_STATUS_CMD_SYSTEM_BUSY 0xbbbb
|
||||
|
||||
|
||||
/* Warpcore clause 45 addressing */
|
||||
#define MDIO_WC_DEVAD 0x3
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
/* bnx2x_sp.c: Broadcom Everest network driver.
|
||||
/* bnx2x_sp.c: Qlogic Everest network driver.
|
||||
*
|
||||
* Copyright (c) 2011-2013 Broadcom Corporation
|
||||
* Copyright 2011-2013 Broadcom Corporation
|
||||
* Copyright (c) 2014 QLogic Corporation
|
||||
* All rights reserved
|
||||
*
|
||||
* Unless you and Broadcom execute a separate written software license
|
||||
* Unless you and Qlogic execute a separate written software license
|
||||
* agreement governing use of this software, this software is licensed to you
|
||||
* under the terms of the GNU General Public License version 2, available
|
||||
* at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL").
|
||||
* at http://www.gnu.org/licenses/gpl-2.0.html (the "GPL").
|
||||
*
|
||||
* Notwithstanding the above, under no circumstances may you combine this
|
||||
* software in any way with any other Broadcom software provided under a
|
||||
* license other than the GPL, without Broadcom's express prior written
|
||||
* software in any way with any other Qlogic software provided under a
|
||||
* license other than the GPL, without Qlogic's express prior written
|
||||
* consent.
|
||||
*
|
||||
* Maintained by: Ariel Elior <ariel.elior@qlogic.com>
|
||||
|
|
@ -355,6 +357,23 @@ static bool bnx2x_get_credit_vlan(struct bnx2x_vlan_mac_obj *o)
|
|||
|
||||
return vp->get(vp, 1);
|
||||
}
|
||||
|
||||
static bool bnx2x_get_credit_vlan_mac(struct bnx2x_vlan_mac_obj *o)
|
||||
{
|
||||
struct bnx2x_credit_pool_obj *mp = o->macs_pool;
|
||||
struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
|
||||
|
||||
if (!mp->get(mp, 1))
|
||||
return false;
|
||||
|
||||
if (!vp->get(vp, 1)) {
|
||||
mp->put(mp, 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool bnx2x_put_cam_offset_mac(struct bnx2x_vlan_mac_obj *o, int offset)
|
||||
{
|
||||
struct bnx2x_credit_pool_obj *mp = o->macs_pool;
|
||||
|
|
@ -383,6 +402,22 @@ static bool bnx2x_put_credit_vlan(struct bnx2x_vlan_mac_obj *o)
|
|||
return vp->put(vp, 1);
|
||||
}
|
||||
|
||||
static bool bnx2x_put_credit_vlan_mac(struct bnx2x_vlan_mac_obj *o)
|
||||
{
|
||||
struct bnx2x_credit_pool_obj *mp = o->macs_pool;
|
||||
struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
|
||||
|
||||
if (!mp->put(mp, 1))
|
||||
return false;
|
||||
|
||||
if (!vp->put(vp, 1)) {
|
||||
mp->get(mp, 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* __bnx2x_vlan_mac_h_write_trylock - try getting the vlan mac writer lock
|
||||
*
|
||||
|
|
@ -636,6 +671,26 @@ static int bnx2x_check_vlan_add(struct bnx2x *bp,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int bnx2x_check_vlan_mac_add(struct bnx2x *bp,
|
||||
struct bnx2x_vlan_mac_obj *o,
|
||||
union bnx2x_classification_ramrod_data *data)
|
||||
{
|
||||
struct bnx2x_vlan_mac_registry_elem *pos;
|
||||
|
||||
DP(BNX2X_MSG_SP, "Checking VLAN_MAC (%pM, %d) for ADD command\n",
|
||||
data->vlan_mac.mac, data->vlan_mac.vlan);
|
||||
|
||||
list_for_each_entry(pos, &o->head, link)
|
||||
if ((data->vlan_mac.vlan == pos->u.vlan_mac.vlan) &&
|
||||
(!memcmp(data->vlan_mac.mac, pos->u.vlan_mac.mac,
|
||||
ETH_ALEN)) &&
|
||||
(data->vlan_mac.is_inner_mac ==
|
||||
pos->u.vlan_mac.is_inner_mac))
|
||||
return -EEXIST;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check_del() callbacks */
|
||||
static struct bnx2x_vlan_mac_registry_elem *
|
||||
bnx2x_check_mac_del(struct bnx2x *bp,
|
||||
|
|
@ -670,6 +725,27 @@ static struct bnx2x_vlan_mac_registry_elem *
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static struct bnx2x_vlan_mac_registry_elem *
|
||||
bnx2x_check_vlan_mac_del(struct bnx2x *bp,
|
||||
struct bnx2x_vlan_mac_obj *o,
|
||||
union bnx2x_classification_ramrod_data *data)
|
||||
{
|
||||
struct bnx2x_vlan_mac_registry_elem *pos;
|
||||
|
||||
DP(BNX2X_MSG_SP, "Checking VLAN_MAC (%pM, %d) for DEL command\n",
|
||||
data->vlan_mac.mac, data->vlan_mac.vlan);
|
||||
|
||||
list_for_each_entry(pos, &o->head, link)
|
||||
if ((data->vlan_mac.vlan == pos->u.vlan_mac.vlan) &&
|
||||
(!memcmp(data->vlan_mac.mac, pos->u.vlan_mac.mac,
|
||||
ETH_ALEN)) &&
|
||||
(data->vlan_mac.is_inner_mac ==
|
||||
pos->u.vlan_mac.is_inner_mac))
|
||||
return pos;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* check_move() callback */
|
||||
static bool bnx2x_check_move(struct bnx2x *bp,
|
||||
struct bnx2x_vlan_mac_obj *src_o,
|
||||
|
|
@ -1036,6 +1112,96 @@ static void bnx2x_set_one_vlan_e2(struct bnx2x *bp,
|
|||
rule_cnt);
|
||||
}
|
||||
|
||||
static void bnx2x_set_one_vlan_mac_e2(struct bnx2x *bp,
|
||||
struct bnx2x_vlan_mac_obj *o,
|
||||
struct bnx2x_exeq_elem *elem,
|
||||
int rule_idx, int cam_offset)
|
||||
{
|
||||
struct bnx2x_raw_obj *raw = &o->raw;
|
||||
struct eth_classify_rules_ramrod_data *data =
|
||||
(struct eth_classify_rules_ramrod_data *)(raw->rdata);
|
||||
int rule_cnt = rule_idx + 1;
|
||||
union eth_classify_rule_cmd *rule_entry = &data->rules[rule_idx];
|
||||
enum bnx2x_vlan_mac_cmd cmd = elem->cmd_data.vlan_mac.cmd;
|
||||
bool add = (cmd == BNX2X_VLAN_MAC_ADD) ? true : false;
|
||||
u16 vlan = elem->cmd_data.vlan_mac.u.vlan_mac.vlan;
|
||||
u8 *mac = elem->cmd_data.vlan_mac.u.vlan_mac.mac;
|
||||
u16 inner_mac;
|
||||
|
||||
/* Reset the ramrod data buffer for the first rule */
|
||||
if (rule_idx == 0)
|
||||
memset(data, 0, sizeof(*data));
|
||||
|
||||
/* Set a rule header */
|
||||
bnx2x_vlan_mac_set_cmd_hdr_e2(bp, o, add, CLASSIFY_RULE_OPCODE_PAIR,
|
||||
&rule_entry->pair.header);
|
||||
|
||||
/* Set VLAN and MAC themselves */
|
||||
rule_entry->pair.vlan = cpu_to_le16(vlan);
|
||||
bnx2x_set_fw_mac_addr(&rule_entry->pair.mac_msb,
|
||||
&rule_entry->pair.mac_mid,
|
||||
&rule_entry->pair.mac_lsb, mac);
|
||||
inner_mac = elem->cmd_data.vlan_mac.u.vlan_mac.is_inner_mac;
|
||||
rule_entry->pair.inner_mac = cpu_to_le16(inner_mac);
|
||||
/* MOVE: Add a rule that will add this MAC/VLAN to the target Queue */
|
||||
if (cmd == BNX2X_VLAN_MAC_MOVE) {
|
||||
struct bnx2x_vlan_mac_obj *target_obj;
|
||||
|
||||
rule_entry++;
|
||||
rule_cnt++;
|
||||
|
||||
/* Setup ramrod data */
|
||||
target_obj = elem->cmd_data.vlan_mac.target_obj;
|
||||
bnx2x_vlan_mac_set_cmd_hdr_e2(bp, target_obj,
|
||||
true, CLASSIFY_RULE_OPCODE_PAIR,
|
||||
&rule_entry->pair.header);
|
||||
|
||||
/* Set a VLAN itself */
|
||||
rule_entry->pair.vlan = cpu_to_le16(vlan);
|
||||
bnx2x_set_fw_mac_addr(&rule_entry->pair.mac_msb,
|
||||
&rule_entry->pair.mac_mid,
|
||||
&rule_entry->pair.mac_lsb, mac);
|
||||
rule_entry->pair.inner_mac = cpu_to_le16(inner_mac);
|
||||
}
|
||||
|
||||
/* Set the ramrod data header */
|
||||
bnx2x_vlan_mac_set_rdata_hdr_e2(raw->cid, raw->state, &data->header,
|
||||
rule_cnt);
|
||||
}
|
||||
|
||||
/**
|
||||
* bnx2x_set_one_vlan_mac_e1h -
|
||||
*
|
||||
* @bp: device handle
|
||||
* @o: bnx2x_vlan_mac_obj
|
||||
* @elem: bnx2x_exeq_elem
|
||||
* @rule_idx: rule_idx
|
||||
* @cam_offset: cam_offset
|
||||
*/
|
||||
static void bnx2x_set_one_vlan_mac_e1h(struct bnx2x *bp,
|
||||
struct bnx2x_vlan_mac_obj *o,
|
||||
struct bnx2x_exeq_elem *elem,
|
||||
int rule_idx, int cam_offset)
|
||||
{
|
||||
struct bnx2x_raw_obj *raw = &o->raw;
|
||||
struct mac_configuration_cmd *config =
|
||||
(struct mac_configuration_cmd *)(raw->rdata);
|
||||
/* 57710 and 57711 do not support MOVE command,
|
||||
* so it's either ADD or DEL
|
||||
*/
|
||||
bool add = (elem->cmd_data.vlan_mac.cmd == BNX2X_VLAN_MAC_ADD) ?
|
||||
true : false;
|
||||
|
||||
/* Reset the ramrod data buffer */
|
||||
memset(config, 0, sizeof(*config));
|
||||
|
||||
bnx2x_vlan_mac_set_rdata_e1x(bp, o, BNX2X_FILTER_VLAN_MAC_PENDING,
|
||||
cam_offset, add,
|
||||
elem->cmd_data.vlan_mac.u.vlan_mac.mac,
|
||||
elem->cmd_data.vlan_mac.u.vlan_mac.vlan,
|
||||
ETH_VLAN_FILTER_CLASSIFY, config);
|
||||
}
|
||||
|
||||
/**
|
||||
* bnx2x_vlan_mac_restore - reconfigure next MAC/VLAN/VLAN-MAC element
|
||||
*
|
||||
|
|
@ -1135,6 +1301,25 @@ static struct bnx2x_exeq_elem *bnx2x_exeq_get_vlan(
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static struct bnx2x_exeq_elem *bnx2x_exeq_get_vlan_mac(
|
||||
struct bnx2x_exe_queue_obj *o,
|
||||
struct bnx2x_exeq_elem *elem)
|
||||
{
|
||||
struct bnx2x_exeq_elem *pos;
|
||||
struct bnx2x_vlan_mac_ramrod_data *data =
|
||||
&elem->cmd_data.vlan_mac.u.vlan_mac;
|
||||
|
||||
/* Check pending for execution commands */
|
||||
list_for_each_entry(pos, &o->exe_queue, link)
|
||||
if (!memcmp(&pos->cmd_data.vlan_mac.u.vlan_mac, data,
|
||||
sizeof(*data)) &&
|
||||
(pos->cmd_data.vlan_mac.cmd ==
|
||||
elem->cmd_data.vlan_mac.cmd))
|
||||
return pos;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* bnx2x_validate_vlan_mac_add - check if an ADD command can be executed
|
||||
*
|
||||
|
|
@ -2042,6 +2227,68 @@ void bnx2x_init_vlan_obj(struct bnx2x *bp,
|
|||
}
|
||||
}
|
||||
|
||||
void bnx2x_init_vlan_mac_obj(struct bnx2x *bp,
|
||||
struct bnx2x_vlan_mac_obj *vlan_mac_obj,
|
||||
u8 cl_id, u32 cid, u8 func_id, void *rdata,
|
||||
dma_addr_t rdata_mapping, int state,
|
||||
unsigned long *pstate, bnx2x_obj_type type,
|
||||
struct bnx2x_credit_pool_obj *macs_pool,
|
||||
struct bnx2x_credit_pool_obj *vlans_pool)
|
||||
{
|
||||
union bnx2x_qable_obj *qable_obj =
|
||||
(union bnx2x_qable_obj *)vlan_mac_obj;
|
||||
|
||||
bnx2x_init_vlan_mac_common(vlan_mac_obj, cl_id, cid, func_id, rdata,
|
||||
rdata_mapping, state, pstate, type,
|
||||
macs_pool, vlans_pool);
|
||||
|
||||
/* CAM pool handling */
|
||||
vlan_mac_obj->get_credit = bnx2x_get_credit_vlan_mac;
|
||||
vlan_mac_obj->put_credit = bnx2x_put_credit_vlan_mac;
|
||||
/* CAM offset is relevant for 57710 and 57711 chips only which have a
|
||||
* single CAM for both MACs and VLAN-MAC pairs. So the offset
|
||||
* will be taken from MACs' pool object only.
|
||||
*/
|
||||
vlan_mac_obj->get_cam_offset = bnx2x_get_cam_offset_mac;
|
||||
vlan_mac_obj->put_cam_offset = bnx2x_put_cam_offset_mac;
|
||||
|
||||
if (CHIP_IS_E1(bp)) {
|
||||
BNX2X_ERR("Do not support chips others than E2\n");
|
||||
BUG();
|
||||
} else if (CHIP_IS_E1H(bp)) {
|
||||
vlan_mac_obj->set_one_rule = bnx2x_set_one_vlan_mac_e1h;
|
||||
vlan_mac_obj->check_del = bnx2x_check_vlan_mac_del;
|
||||
vlan_mac_obj->check_add = bnx2x_check_vlan_mac_add;
|
||||
vlan_mac_obj->check_move = bnx2x_check_move_always_err;
|
||||
vlan_mac_obj->ramrod_cmd = RAMROD_CMD_ID_ETH_SET_MAC;
|
||||
|
||||
/* Exe Queue */
|
||||
bnx2x_exe_queue_init(bp,
|
||||
&vlan_mac_obj->exe_queue, 1, qable_obj,
|
||||
bnx2x_validate_vlan_mac,
|
||||
bnx2x_remove_vlan_mac,
|
||||
bnx2x_optimize_vlan_mac,
|
||||
bnx2x_execute_vlan_mac,
|
||||
bnx2x_exeq_get_vlan_mac);
|
||||
} else {
|
||||
vlan_mac_obj->set_one_rule = bnx2x_set_one_vlan_mac_e2;
|
||||
vlan_mac_obj->check_del = bnx2x_check_vlan_mac_del;
|
||||
vlan_mac_obj->check_add = bnx2x_check_vlan_mac_add;
|
||||
vlan_mac_obj->check_move = bnx2x_check_move;
|
||||
vlan_mac_obj->ramrod_cmd =
|
||||
RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES;
|
||||
|
||||
/* Exe Queue */
|
||||
bnx2x_exe_queue_init(bp,
|
||||
&vlan_mac_obj->exe_queue,
|
||||
CLASSIFY_RULES_COUNT,
|
||||
qable_obj, bnx2x_validate_vlan_mac,
|
||||
bnx2x_remove_vlan_mac,
|
||||
bnx2x_optimize_vlan_mac,
|
||||
bnx2x_execute_vlan_mac,
|
||||
bnx2x_exeq_get_vlan_mac);
|
||||
}
|
||||
}
|
||||
/* RX_MODE verbs: DROP_ALL/ACCEPT_ALL/ACCEPT_ALL_MULTI/ACCEPT_ALL_VLAN/NORMAL */
|
||||
static inline void __storm_memset_mac_filters(struct bnx2x *bp,
|
||||
struct tstorm_eth_mac_filter_config *mac_filters,
|
||||
|
|
@ -3854,8 +4101,8 @@ static bool bnx2x_credit_pool_get_entry_always_true(
|
|||
* If credit is negative pool operations will always succeed (unlimited pool).
|
||||
*
|
||||
*/
|
||||
static inline void bnx2x_init_credit_pool(struct bnx2x_credit_pool_obj *p,
|
||||
int base, int credit)
|
||||
void bnx2x_init_credit_pool(struct bnx2x_credit_pool_obj *p,
|
||||
int base, int credit)
|
||||
{
|
||||
/* Zero the object first */
|
||||
memset(p, 0, sizeof(*p));
|
||||
|
|
@ -3934,9 +4181,9 @@ void bnx2x_init_mac_credit_pool(struct bnx2x *bp,
|
|||
/* CAM credit is equaly divided between all active functions
|
||||
* on the PATH.
|
||||
*/
|
||||
if ((func_num > 0)) {
|
||||
if (func_num > 0) {
|
||||
if (!CHIP_REV_IS_SLOW(bp))
|
||||
cam_sz = (MAX_MAC_CREDIT_E2 / func_num);
|
||||
cam_sz = PF_MAC_CREDIT_E2(bp, func_num);
|
||||
else
|
||||
cam_sz = BNX2X_CAM_SIZE_EMUL;
|
||||
|
||||
|
|
@ -3966,8 +4213,9 @@ void bnx2x_init_vlan_credit_pool(struct bnx2x *bp,
|
|||
* on the PATH.
|
||||
*/
|
||||
if (func_num > 0) {
|
||||
int credit = MAX_VLAN_CREDIT_E2 / func_num;
|
||||
bnx2x_init_credit_pool(p, func_id * credit, credit);
|
||||
int credit = PF_VLAN_CREDIT_E2(bp, func_num);
|
||||
|
||||
bnx2x_init_credit_pool(p, -1/*unused for E2*/, credit);
|
||||
} else
|
||||
/* this should never happen! Block VLAN operations. */
|
||||
bnx2x_init_credit_pool(p, 0, 0);
|
||||
|
|
@ -4060,8 +4308,14 @@ static int bnx2x_setup_rss(struct bnx2x *bp,
|
|||
if (test_bit(BNX2X_RSS_IPV6_UDP, &p->rss_flags))
|
||||
caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV6_UDP_CAPABILITY;
|
||||
|
||||
if (test_bit(BNX2X_RSS_GRE_INNER_HDRS, &p->rss_flags))
|
||||
caps |= ETH_RSS_UPDATE_RAMROD_DATA_GRE_INNER_HDRS_CAPABILITY;
|
||||
if (test_bit(BNX2X_RSS_IPV4_VXLAN, &p->rss_flags))
|
||||
caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV4_VXLAN_CAPABILITY;
|
||||
|
||||
if (test_bit(BNX2X_RSS_IPV6_VXLAN, &p->rss_flags))
|
||||
caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV6_VXLAN_CAPABILITY;
|
||||
|
||||
if (test_bit(BNX2X_RSS_TUNN_INNER_HDRS, &p->rss_flags))
|
||||
caps |= ETH_RSS_UPDATE_RAMROD_DATA_TUNN_INNER_HDRS_CAPABILITY;
|
||||
|
||||
/* RSS keys */
|
||||
if (test_bit(BNX2X_RSS_SET_SRCH, &p->rss_flags)) {
|
||||
|
|
@ -5669,10 +5923,14 @@ static inline int bnx2x_func_send_start(struct bnx2x *bp,
|
|||
rdata->sd_vlan_tag = cpu_to_le16(start_params->sd_vlan_tag);
|
||||
rdata->path_id = BP_PATH(bp);
|
||||
rdata->network_cos_mode = start_params->network_cos_mode;
|
||||
rdata->tunnel_mode = start_params->tunnel_mode;
|
||||
rdata->gre_tunnel_type = start_params->gre_tunnel_type;
|
||||
rdata->inner_gre_rss_en = start_params->inner_gre_rss_en;
|
||||
rdata->vxlan_dst_port = cpu_to_le16(4789);
|
||||
|
||||
rdata->vxlan_dst_port = cpu_to_le16(start_params->vxlan_dst_port);
|
||||
rdata->geneve_dst_port = cpu_to_le16(start_params->geneve_dst_port);
|
||||
rdata->inner_clss_l2gre = start_params->inner_clss_l2gre;
|
||||
rdata->inner_clss_l2geneve = start_params->inner_clss_l2geneve;
|
||||
rdata->inner_clss_vxlan = start_params->inner_clss_vxlan;
|
||||
rdata->inner_rss = start_params->inner_rss;
|
||||
|
||||
rdata->sd_accept_mf_clss_fail = start_params->class_fail;
|
||||
if (start_params->class_fail_ethtype) {
|
||||
rdata->sd_accept_mf_clss_fail_match_ethtype = 1;
|
||||
|
|
@ -5690,6 +5948,14 @@ static inline int bnx2x_func_send_start(struct bnx2x *bp,
|
|||
cpu_to_le16(0x8100);
|
||||
|
||||
rdata->no_added_tags = start_params->no_added_tags;
|
||||
|
||||
rdata->c2s_pri_tt_valid = start_params->c2s_pri_valid;
|
||||
if (rdata->c2s_pri_tt_valid) {
|
||||
memcpy(rdata->c2s_pri_trans_table.val,
|
||||
start_params->c2s_pri,
|
||||
MAX_VLAN_PRIORITIES);
|
||||
rdata->c2s_pri_default = start_params->c2s_pri_default;
|
||||
}
|
||||
/* No need for an explicit memory barrier here as long we would
|
||||
* need to ensure the ordering of writing to the SPQ element
|
||||
* and updating of the SPQ producer which involves a memory
|
||||
|
|
@ -5750,15 +6016,22 @@ static inline int bnx2x_func_send_switch_update(struct bnx2x *bp,
|
|||
if (test_bit(BNX2X_F_UPDATE_TUNNEL_CFG_CHNG,
|
||||
&switch_update_params->changes)) {
|
||||
rdata->update_tunn_cfg_flg = 1;
|
||||
if (test_bit(BNX2X_F_UPDATE_TUNNEL_CLSS_EN,
|
||||
if (test_bit(BNX2X_F_UPDATE_TUNNEL_INNER_CLSS_L2GRE,
|
||||
&switch_update_params->changes))
|
||||
rdata->tunn_clss_en = 1;
|
||||
if (test_bit(BNX2X_F_UPDATE_TUNNEL_INNER_GRE_RSS_EN,
|
||||
rdata->inner_clss_l2gre = 1;
|
||||
if (test_bit(BNX2X_F_UPDATE_TUNNEL_INNER_CLSS_VXLAN,
|
||||
&switch_update_params->changes))
|
||||
rdata->inner_gre_rss_en = 1;
|
||||
rdata->tunnel_mode = switch_update_params->tunnel_mode;
|
||||
rdata->gre_tunnel_type = switch_update_params->gre_tunnel_type;
|
||||
rdata->vxlan_dst_port = cpu_to_le16(4789);
|
||||
rdata->inner_clss_vxlan = 1;
|
||||
if (test_bit(BNX2X_F_UPDATE_TUNNEL_INNER_CLSS_L2GENEVE,
|
||||
&switch_update_params->changes))
|
||||
rdata->inner_clss_l2geneve = 1;
|
||||
if (test_bit(BNX2X_F_UPDATE_TUNNEL_INNER_RSS,
|
||||
&switch_update_params->changes))
|
||||
rdata->inner_rss = 1;
|
||||
rdata->vxlan_dst_port =
|
||||
cpu_to_le16(switch_update_params->vxlan_dst_port);
|
||||
rdata->geneve_dst_port =
|
||||
cpu_to_le16(switch_update_params->geneve_dst_port);
|
||||
}
|
||||
|
||||
rdata->echo = SWITCH_UPDATE;
|
||||
|
|
@ -5885,6 +6158,8 @@ static inline int bnx2x_func_send_tx_start(struct bnx2x *bp,
|
|||
rdata->traffic_type_to_priority_cos[i] =
|
||||
tx_start_params->traffic_type_to_priority_cos[i];
|
||||
|
||||
for (i = 0; i < MAX_TRAFFIC_TYPES; i++)
|
||||
rdata->dcb_outer_pri[i] = tx_start_params->dcb_outer_pri[i];
|
||||
/* No need for an explicit memory barrier here as long as we
|
||||
* ensure the ordering of writing to the SPQ element
|
||||
* and updating of the SPQ producer which involves a memory
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
/* bnx2x_sp.h: Broadcom Everest network driver.
|
||||
/* bnx2x_sp.h: Qlogic Everest network driver.
|
||||
*
|
||||
* Copyright (c) 2011-2013 Broadcom Corporation
|
||||
* Copyright 2011-2013 Broadcom Corporation
|
||||
* Copyright (c) 2014 QLogic Corporation
|
||||
* All rights reserved
|
||||
*
|
||||
* Unless you and Broadcom execute a separate written software license
|
||||
* Unless you and Qlogic execute a separate written software license
|
||||
* agreement governing use of this software, this software is licensed to you
|
||||
* under the terms of the GNU General Public License version 2, available
|
||||
* at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL").
|
||||
* at http://www.gnu.org/licenses/gpl-2.0.html (the "GPL").
|
||||
*
|
||||
* Notwithstanding the above, under no circumstances may you combine this
|
||||
* software in any way with any other Broadcom software provided under a
|
||||
* license other than the GPL, without Broadcom's express prior written
|
||||
* software in any way with any other Qlogic software provided under a
|
||||
* license other than the GPL, without Qlogic's express prior written
|
||||
* consent.
|
||||
*
|
||||
* Maintained by: Ariel Elior <ariel.elior@qlogic.com>
|
||||
|
|
@ -711,7 +713,10 @@ enum {
|
|||
BNX2X_RSS_IPV6,
|
||||
BNX2X_RSS_IPV6_TCP,
|
||||
BNX2X_RSS_IPV6_UDP,
|
||||
BNX2X_RSS_GRE_INNER_HDRS,
|
||||
|
||||
BNX2X_RSS_IPV4_VXLAN,
|
||||
BNX2X_RSS_IPV6_VXLAN,
|
||||
BNX2X_RSS_TUNN_INNER_HDRS,
|
||||
};
|
||||
|
||||
struct bnx2x_config_rss_params {
|
||||
|
|
@ -1105,8 +1110,10 @@ enum {
|
|||
BNX2X_F_UPDATE_VLAN_FORCE_PRIO_CHNG,
|
||||
BNX2X_F_UPDATE_VLAN_FORCE_PRIO_FLAG,
|
||||
BNX2X_F_UPDATE_TUNNEL_CFG_CHNG,
|
||||
BNX2X_F_UPDATE_TUNNEL_CLSS_EN,
|
||||
BNX2X_F_UPDATE_TUNNEL_INNER_GRE_RSS_EN,
|
||||
BNX2X_F_UPDATE_TUNNEL_INNER_CLSS_L2GRE,
|
||||
BNX2X_F_UPDATE_TUNNEL_INNER_CLSS_VXLAN,
|
||||
BNX2X_F_UPDATE_TUNNEL_INNER_CLSS_L2GENEVE,
|
||||
BNX2X_F_UPDATE_TUNNEL_INNER_RSS,
|
||||
};
|
||||
|
||||
/* Allowed Function states */
|
||||
|
|
@ -1171,19 +1178,23 @@ struct bnx2x_func_start_params {
|
|||
/* Function cos mode */
|
||||
u8 network_cos_mode;
|
||||
|
||||
/* TUNN_MODE_NONE/TUNN_MODE_VXLAN/TUNN_MODE_GRE */
|
||||
u8 tunnel_mode;
|
||||
/* UDP dest port for VXLAN */
|
||||
u16 vxlan_dst_port;
|
||||
|
||||
/* tunneling classification enablement */
|
||||
u8 tunn_clss_en;
|
||||
/* UDP dest port for Geneve */
|
||||
u16 geneve_dst_port;
|
||||
|
||||
/* NVGRE_TUNNEL/L2GRE_TUNNEL/IPGRE_TUNNEL */
|
||||
u8 gre_tunnel_type;
|
||||
/* Enable inner Rx classifications for L2GRE packets */
|
||||
u8 inner_clss_l2gre;
|
||||
|
||||
/* Enables Inner GRE RSS on the function, depends on the client RSS
|
||||
* capailities
|
||||
*/
|
||||
u8 inner_gre_rss_en;
|
||||
/* Enable inner Rx classifications for L2-Geneve packets */
|
||||
u8 inner_clss_l2geneve;
|
||||
|
||||
/* Enable inner Rx classification for vxlan packets */
|
||||
u8 inner_clss_vxlan;
|
||||
|
||||
/* Enable RSS according to inner header */
|
||||
u8 inner_rss;
|
||||
|
||||
/* Allows accepting of packets failing MF classification, possibly
|
||||
* only matching a given ethertype
|
||||
|
|
@ -1200,6 +1211,11 @@ struct bnx2x_func_start_params {
|
|||
|
||||
/* Prevent inner vlans from being added by FW */
|
||||
u8 no_added_tags;
|
||||
|
||||
/* Inner-to-Outer vlan priority mapping */
|
||||
u8 c2s_pri[MAX_VLAN_PRIORITIES];
|
||||
u8 c2s_pri_default;
|
||||
u8 c2s_pri_valid;
|
||||
};
|
||||
|
||||
struct bnx2x_func_switch_update_params {
|
||||
|
|
@ -1207,8 +1223,8 @@ struct bnx2x_func_switch_update_params {
|
|||
u16 vlan;
|
||||
u16 vlan_eth_type;
|
||||
u8 vlan_force_prio;
|
||||
u8 tunnel_mode;
|
||||
u8 gre_tunnel_type;
|
||||
u16 vxlan_dst_port;
|
||||
u16 geneve_dst_port;
|
||||
};
|
||||
|
||||
struct bnx2x_func_afex_update_params {
|
||||
|
|
@ -1229,6 +1245,7 @@ struct bnx2x_func_tx_start_params {
|
|||
u8 dcb_enabled;
|
||||
u8 dcb_version;
|
||||
u8 dont_add_pri_0_en;
|
||||
u8 dcb_outer_pri[MAX_TRAFFIC_TYPES];
|
||||
};
|
||||
|
||||
struct bnx2x_func_set_timesync_params {
|
||||
|
|
@ -1396,6 +1413,14 @@ void bnx2x_init_vlan_obj(struct bnx2x *bp,
|
|||
unsigned long *pstate, bnx2x_obj_type type,
|
||||
struct bnx2x_credit_pool_obj *vlans_pool);
|
||||
|
||||
void bnx2x_init_vlan_mac_obj(struct bnx2x *bp,
|
||||
struct bnx2x_vlan_mac_obj *vlan_mac_obj,
|
||||
u8 cl_id, u32 cid, u8 func_id, void *rdata,
|
||||
dma_addr_t rdata_mapping, int state,
|
||||
unsigned long *pstate, bnx2x_obj_type type,
|
||||
struct bnx2x_credit_pool_obj *macs_pool,
|
||||
struct bnx2x_credit_pool_obj *vlans_pool);
|
||||
|
||||
int bnx2x_vlan_mac_h_read_lock(struct bnx2x *bp,
|
||||
struct bnx2x_vlan_mac_obj *o);
|
||||
void bnx2x_vlan_mac_h_read_unlock(struct bnx2x *bp,
|
||||
|
|
@ -1466,6 +1491,8 @@ void bnx2x_init_mac_credit_pool(struct bnx2x *bp,
|
|||
void bnx2x_init_vlan_credit_pool(struct bnx2x *bp,
|
||||
struct bnx2x_credit_pool_obj *p, u8 func_id,
|
||||
u8 func_num);
|
||||
void bnx2x_init_credit_pool(struct bnx2x_credit_pool_obj *p,
|
||||
int base, int credit);
|
||||
|
||||
/****************** RSS CONFIGURATION ****************/
|
||||
void bnx2x_init_rss_config_obj(struct bnx2x *bp,
|
||||
|
|
@ -1493,4 +1520,12 @@ int bnx2x_config_rss(struct bnx2x *bp,
|
|||
void bnx2x_get_rss_ind_table(struct bnx2x_rss_config_obj *rss_obj,
|
||||
u8 *ind_table);
|
||||
|
||||
#define PF_MAC_CREDIT_E2(bp, func_num) \
|
||||
((MAX_MAC_CREDIT_E2 - GET_NUM_VFS_PER_PATH(bp) * VF_MAC_CREDIT_CNT) / \
|
||||
func_num + GET_NUM_VFS_PER_PF(bp) * VF_MAC_CREDIT_CNT)
|
||||
|
||||
#define PF_VLAN_CREDIT_E2(bp, func_num) \
|
||||
((MAX_MAC_CREDIT_E2 - GET_NUM_VFS_PER_PATH(bp) * VF_VLAN_CREDIT_CNT) / \
|
||||
func_num + GET_NUM_VFS_PER_PF(bp) * VF_VLAN_CREDIT_CNT)
|
||||
|
||||
#endif /* BNX2X_SP_VERBS */
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
/* bnx2x_sriov.c: Broadcom Everest network driver.
|
||||
/* bnx2x_sriov.c: QLogic Everest network driver.
|
||||
*
|
||||
* Copyright 2009-2013 Broadcom Corporation
|
||||
* Copyright 2014 QLogic Corporation
|
||||
* All rights reserved
|
||||
*
|
||||
* Unless you and Broadcom execute a separate written software license
|
||||
* Unless you and QLogic execute a separate written software license
|
||||
* agreement governing use of this software, this software is licensed to you
|
||||
* under the terms of the GNU General Public License version 2, available
|
||||
* at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL").
|
||||
*
|
||||
* Notwithstanding the above, under no circumstances may you combine this
|
||||
* software in any way with any other Broadcom software provided under a
|
||||
* license other than the GPL, without Broadcom's express prior written
|
||||
* software in any way with any other QLogic software provided under a
|
||||
* license other than the GPL, without QLogic's express prior written
|
||||
* consent.
|
||||
*
|
||||
* Maintained by: Ariel Elior <ariel.elior@qlogic.com>
|
||||
|
|
@ -195,14 +197,6 @@ void bnx2x_vfop_qctor_prep(struct bnx2x *bp,
|
|||
setup_p->gen_params.stat_id = vfq_stat_id(vf, q);
|
||||
setup_p->gen_params.fp_hsi = vf->fp_hsi;
|
||||
|
||||
/* Setup-op pause params:
|
||||
* Nothing to do, the pause thresholds are set by default to 0 which
|
||||
* effectively turns off the feature for this queue. We don't want
|
||||
* one queue (VF) to interfering with another queue (another VF)
|
||||
*/
|
||||
if (vf->cfg_flags & VF_CFG_FW_FC)
|
||||
BNX2X_ERR("No support for pause to VFs (abs_vfid: %d)\n",
|
||||
vf->abs_vfid);
|
||||
/* Setup-op flags:
|
||||
* collect statistics, zero statistics, local-switching, security,
|
||||
* OV for Flex10, RSS and MCAST for leading
|
||||
|
|
@ -358,22 +352,24 @@ static inline void bnx2x_vf_vlan_credit(struct bnx2x *bp,
|
|||
}
|
||||
|
||||
static int bnx2x_vf_vlan_mac_clear(struct bnx2x *bp, struct bnx2x_virtf *vf,
|
||||
int qid, bool drv_only, bool mac)
|
||||
int qid, bool drv_only, int type)
|
||||
{
|
||||
struct bnx2x_vlan_mac_ramrod_params ramrod;
|
||||
int rc;
|
||||
|
||||
DP(BNX2X_MSG_IOV, "vf[%d] - deleting all %s\n", vf->abs_vfid,
|
||||
mac ? "MACs" : "VLANs");
|
||||
(type == BNX2X_VF_FILTER_VLAN_MAC) ? "VLAN-MACs" :
|
||||
(type == BNX2X_VF_FILTER_MAC) ? "MACs" : "VLANs");
|
||||
|
||||
/* Prepare ramrod params */
|
||||
memset(&ramrod, 0, sizeof(struct bnx2x_vlan_mac_ramrod_params));
|
||||
if (mac) {
|
||||
if (type == BNX2X_VF_FILTER_VLAN_MAC) {
|
||||
set_bit(BNX2X_ETH_MAC, &ramrod.user_req.vlan_mac_flags);
|
||||
ramrod.vlan_mac_obj = &bnx2x_vfq(vf, qid, vlan_mac_obj);
|
||||
} else if (type == BNX2X_VF_FILTER_MAC) {
|
||||
set_bit(BNX2X_ETH_MAC, &ramrod.user_req.vlan_mac_flags);
|
||||
ramrod.vlan_mac_obj = &bnx2x_vfq(vf, qid, mac_obj);
|
||||
} else {
|
||||
set_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
|
||||
&ramrod.user_req.vlan_mac_flags);
|
||||
ramrod.vlan_mac_obj = &bnx2x_vfq(vf, qid, vlan_obj);
|
||||
}
|
||||
ramrod.user_req.cmd = BNX2X_VLAN_MAC_DEL;
|
||||
|
|
@ -391,14 +387,11 @@ static int bnx2x_vf_vlan_mac_clear(struct bnx2x *bp, struct bnx2x_virtf *vf,
|
|||
&ramrod.ramrod_flags);
|
||||
if (rc) {
|
||||
BNX2X_ERR("Failed to delete all %s\n",
|
||||
mac ? "MACs" : "VLANs");
|
||||
(type == BNX2X_VF_FILTER_VLAN_MAC) ? "VLAN-MACs" :
|
||||
(type == BNX2X_VF_FILTER_MAC) ? "MACs" : "VLANs");
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Clear the vlan counters */
|
||||
if (!mac)
|
||||
atomic_set(&bnx2x_vfq(vf, qid, vlan_count), 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -412,13 +405,17 @@ static int bnx2x_vf_mac_vlan_config(struct bnx2x *bp,
|
|||
|
||||
DP(BNX2X_MSG_IOV, "vf[%d] - %s a %s filter\n",
|
||||
vf->abs_vfid, filter->add ? "Adding" : "Deleting",
|
||||
filter->type == BNX2X_VF_FILTER_MAC ? "MAC" : "VLAN");
|
||||
(filter->type == BNX2X_VF_FILTER_VLAN_MAC) ? "VLAN-MAC" :
|
||||
(filter->type == BNX2X_VF_FILTER_MAC) ? "MAC" : "VLAN");
|
||||
|
||||
/* Prepare ramrod params */
|
||||
memset(&ramrod, 0, sizeof(struct bnx2x_vlan_mac_ramrod_params));
|
||||
if (filter->type == BNX2X_VF_FILTER_VLAN) {
|
||||
set_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
|
||||
&ramrod.user_req.vlan_mac_flags);
|
||||
if (filter->type == BNX2X_VF_FILTER_VLAN_MAC) {
|
||||
ramrod.vlan_mac_obj = &bnx2x_vfq(vf, qid, vlan_mac_obj);
|
||||
ramrod.user_req.u.vlan.vlan = filter->vid;
|
||||
memcpy(&ramrod.user_req.u.mac.mac, filter->mac, ETH_ALEN);
|
||||
set_bit(BNX2X_ETH_MAC, &ramrod.user_req.vlan_mac_flags);
|
||||
} else if (filter->type == BNX2X_VF_FILTER_VLAN) {
|
||||
ramrod.vlan_mac_obj = &bnx2x_vfq(vf, qid, vlan_obj);
|
||||
ramrod.user_req.u.vlan.vlan = filter->vid;
|
||||
} else {
|
||||
|
|
@ -429,16 +426,6 @@ static int bnx2x_vf_mac_vlan_config(struct bnx2x *bp,
|
|||
ramrod.user_req.cmd = filter->add ? BNX2X_VLAN_MAC_ADD :
|
||||
BNX2X_VLAN_MAC_DEL;
|
||||
|
||||
/* Verify there are available vlan credits */
|
||||
if (filter->add && filter->type == BNX2X_VF_FILTER_VLAN &&
|
||||
(atomic_read(&bnx2x_vfq(vf, qid, vlan_count)) >=
|
||||
vf_vlan_rules_cnt(vf))) {
|
||||
BNX2X_ERR("No credits for vlan [%d >= %d]\n",
|
||||
atomic_read(&bnx2x_vfq(vf, qid, vlan_count)),
|
||||
vf_vlan_rules_cnt(vf));
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
set_bit(RAMROD_EXEC, &ramrod.ramrod_flags);
|
||||
if (drv_only)
|
||||
set_bit(RAMROD_DRV_CLR_ONLY, &ramrod.ramrod_flags);
|
||||
|
|
@ -450,16 +437,13 @@ static int bnx2x_vf_mac_vlan_config(struct bnx2x *bp,
|
|||
if (rc && rc != -EEXIST) {
|
||||
BNX2X_ERR("Failed to %s %s\n",
|
||||
filter->add ? "add" : "delete",
|
||||
filter->type == BNX2X_VF_FILTER_MAC ? "MAC" :
|
||||
"VLAN");
|
||||
(filter->type == BNX2X_VF_FILTER_VLAN_MAC) ?
|
||||
"VLAN-MAC" :
|
||||
(filter->type == BNX2X_VF_FILTER_MAC) ?
|
||||
"MAC" : "VLAN");
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Update the vlan counters */
|
||||
if (filter->type == BNX2X_VF_FILTER_VLAN)
|
||||
bnx2x_vf_vlan_credit(bp, ramrod.vlan_mac_obj,
|
||||
&bnx2x_vfq(vf, qid, vlan_count));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -511,21 +495,7 @@ int bnx2x_vf_queue_setup(struct bnx2x *bp, struct bnx2x_virtf *vf, int qid,
|
|||
if (rc)
|
||||
goto op_err;
|
||||
|
||||
/* Configure vlan0 for leading queue */
|
||||
if (!qid) {
|
||||
struct bnx2x_vf_mac_vlan_filter filter;
|
||||
|
||||
memset(&filter, 0, sizeof(struct bnx2x_vf_mac_vlan_filter));
|
||||
filter.type = BNX2X_VF_FILTER_VLAN;
|
||||
filter.add = true;
|
||||
filter.vid = 0;
|
||||
rc = bnx2x_vf_mac_vlan_config(bp, vf, qid, &filter, false);
|
||||
if (rc)
|
||||
goto op_err;
|
||||
}
|
||||
|
||||
/* Schedule the configuration of any pending vlan filters */
|
||||
vf->cfg_flags |= VF_CFG_VLAN;
|
||||
bnx2x_schedule_sp_rtnl(bp, BNX2X_SP_RTNL_HYPERVISOR_VLAN,
|
||||
BNX2X_MSG_IOV);
|
||||
return 0;
|
||||
|
|
@ -544,10 +514,16 @@ static int bnx2x_vf_queue_flr(struct bnx2x *bp, struct bnx2x_virtf *vf,
|
|||
/* If needed, clean the filtering data base */
|
||||
if ((qid == LEADING_IDX) &&
|
||||
bnx2x_validate_vf_sp_objs(bp, vf, false)) {
|
||||
rc = bnx2x_vf_vlan_mac_clear(bp, vf, qid, true, false);
|
||||
rc = bnx2x_vf_vlan_mac_clear(bp, vf, qid, true,
|
||||
BNX2X_VF_FILTER_VLAN_MAC);
|
||||
if (rc)
|
||||
goto op_err;
|
||||
rc = bnx2x_vf_vlan_mac_clear(bp, vf, qid, true, true);
|
||||
rc = bnx2x_vf_vlan_mac_clear(bp, vf, qid, true,
|
||||
BNX2X_VF_FILTER_VLAN);
|
||||
if (rc)
|
||||
goto op_err;
|
||||
rc = bnx2x_vf_vlan_mac_clear(bp, vf, qid, true,
|
||||
BNX2X_VF_FILTER_MAC);
|
||||
if (rc)
|
||||
goto op_err;
|
||||
}
|
||||
|
|
@ -680,11 +656,18 @@ int bnx2x_vf_queue_teardown(struct bnx2x *bp, struct bnx2x_virtf *vf, int qid)
|
|||
/* Remove filtering if feasible */
|
||||
if (bnx2x_validate_vf_sp_objs(bp, vf, true)) {
|
||||
rc = bnx2x_vf_vlan_mac_clear(bp, vf, qid,
|
||||
false, false);
|
||||
false,
|
||||
BNX2X_VF_FILTER_VLAN_MAC);
|
||||
if (rc)
|
||||
goto op_err;
|
||||
rc = bnx2x_vf_vlan_mac_clear(bp, vf, qid,
|
||||
false, true);
|
||||
false,
|
||||
BNX2X_VF_FILTER_VLAN);
|
||||
if (rc)
|
||||
goto op_err;
|
||||
rc = bnx2x_vf_vlan_mac_clear(bp, vf, qid,
|
||||
false,
|
||||
BNX2X_VF_FILTER_MAC);
|
||||
if (rc)
|
||||
goto op_err;
|
||||
rc = bnx2x_vf_mcast(bp, vf, NULL, 0, false);
|
||||
|
|
@ -765,8 +748,6 @@ static void bnx2x_vf_igu_reset(struct bnx2x *bp, struct bnx2x_virtf *vf)
|
|||
|
||||
val = REG_RD(bp, IGU_REG_VF_CONFIGURATION);
|
||||
val |= (IGU_VF_CONF_FUNC_EN | IGU_VF_CONF_MSI_MSIX_EN);
|
||||
if (vf->cfg_flags & VF_CFG_INT_SIMD)
|
||||
val |= IGU_VF_CONF_SINGLE_ISR_EN;
|
||||
val &= ~IGU_VF_CONF_PARENT_MASK;
|
||||
val |= (BP_ABS_FUNC(bp) >> 1) << IGU_VF_CONF_PARENT_SHIFT;
|
||||
REG_WR(bp, IGU_REG_VF_CONFIGURATION, val);
|
||||
|
|
@ -845,29 +826,6 @@ int bnx2x_vf_flr_clnup_epilog(struct bnx2x *bp, u8 abs_vfid)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void bnx2x_iov_re_set_vlan_filters(struct bnx2x *bp,
|
||||
struct bnx2x_virtf *vf,
|
||||
int new)
|
||||
{
|
||||
int num = vf_vlan_rules_cnt(vf);
|
||||
int diff = new - num;
|
||||
bool rc = true;
|
||||
|
||||
DP(BNX2X_MSG_IOV, "vf[%d] - %d vlan filter credits [previously %d]\n",
|
||||
vf->abs_vfid, new, num);
|
||||
|
||||
if (diff > 0)
|
||||
rc = bp->vlans_pool.get(&bp->vlans_pool, diff);
|
||||
else if (diff < 0)
|
||||
rc = bp->vlans_pool.put(&bp->vlans_pool, -diff);
|
||||
|
||||
if (rc)
|
||||
vf_vlan_rules_cnt(vf) = new;
|
||||
else
|
||||
DP(BNX2X_MSG_IOV, "vf[%d] - Failed to configure vlan filter credits change\n",
|
||||
vf->abs_vfid);
|
||||
}
|
||||
|
||||
/* must be called after the number of PF queues and the number of VFs are
|
||||
* both known
|
||||
*/
|
||||
|
|
@ -875,21 +833,13 @@ static void
|
|||
bnx2x_iov_static_resc(struct bnx2x *bp, struct bnx2x_virtf *vf)
|
||||
{
|
||||
struct vf_pf_resc_request *resc = &vf->alloc_resc;
|
||||
u16 vlan_count = 0;
|
||||
|
||||
/* will be set only during VF-ACQUIRE */
|
||||
resc->num_rxqs = 0;
|
||||
resc->num_txqs = 0;
|
||||
|
||||
/* no credit calculations for macs (just yet) */
|
||||
resc->num_mac_filters = 1;
|
||||
|
||||
/* divvy up vlan rules */
|
||||
bnx2x_iov_re_set_vlan_filters(bp, vf, 0);
|
||||
vlan_count = bp->vlans_pool.check(&bp->vlans_pool);
|
||||
vlan_count = 1 << ilog2(vlan_count);
|
||||
bnx2x_iov_re_set_vlan_filters(bp, vf,
|
||||
vlan_count / BNX2X_NR_VIRTFN(bp));
|
||||
resc->num_mac_filters = VF_MAC_CREDIT_CNT;
|
||||
resc->num_vlan_filters = VF_VLAN_CREDIT_CNT;
|
||||
|
||||
/* no real limitation */
|
||||
resc->num_mc_filters = 0;
|
||||
|
|
@ -1338,6 +1288,9 @@ int bnx2x_iov_init_one(struct bnx2x *bp, int int_mode_param,
|
|||
|
||||
mutex_init(&bp->vfdb->bulletin_mutex);
|
||||
|
||||
if (SHMEM2_HAS(bp, sriov_switch_mode))
|
||||
SHMEM2_WR(bp, sriov_switch_mode, SRIOV_SWITCH_MODE_VEB);
|
||||
|
||||
return 0;
|
||||
failed:
|
||||
DP(BNX2X_MSG_IOV, "Failed err=%d\n", err);
|
||||
|
|
@ -1620,6 +1573,11 @@ int bnx2x_iov_nic_init(struct bnx2x *bp)
|
|||
vf->filter_state = 0;
|
||||
vf->sp_cl_id = bnx2x_fp(bp, 0, cl_id);
|
||||
|
||||
bnx2x_init_credit_pool(&vf->vf_vlans_pool, 0,
|
||||
vf_vlan_rules_cnt(vf));
|
||||
bnx2x_init_credit_pool(&vf->vf_macs_pool, 0,
|
||||
vf_mac_rules_cnt(vf));
|
||||
|
||||
/* init mcast object - This object will be re-initialized
|
||||
* during VF-ACQUIRE with the proper cl_id and cid.
|
||||
* It needs to be initialized here so that it can be safely
|
||||
|
|
@ -2032,12 +1990,11 @@ int bnx2x_vf_chk_avail_resc(struct bnx2x *bp, struct bnx2x_virtf *vf,
|
|||
u8 rxq_cnt = vf_rxq_count(vf) ? : bnx2x_vf_max_queue_cnt(bp, vf);
|
||||
u8 txq_cnt = vf_txq_count(vf) ? : bnx2x_vf_max_queue_cnt(bp, vf);
|
||||
|
||||
/* Save a vlan filter for the Hypervisor */
|
||||
return ((req_resc->num_rxqs <= rxq_cnt) &&
|
||||
(req_resc->num_txqs <= txq_cnt) &&
|
||||
(req_resc->num_sbs <= vf_sb_count(vf)) &&
|
||||
(req_resc->num_mac_filters <= vf_mac_rules_cnt(vf)) &&
|
||||
(req_resc->num_vlan_filters <= vf_vlan_rules_visible_cnt(vf)));
|
||||
(req_resc->num_vlan_filters <= vf_vlan_rules_cnt(vf)));
|
||||
}
|
||||
|
||||
/* CORE VF API */
|
||||
|
|
@ -2091,16 +2048,12 @@ int bnx2x_vf_acquire(struct bnx2x *bp, struct bnx2x_virtf *vf,
|
|||
vf_sb_count(vf) = resc->num_sbs;
|
||||
vf_rxq_count(vf) = resc->num_rxqs ? : bnx2x_vf_max_queue_cnt(bp, vf);
|
||||
vf_txq_count(vf) = resc->num_txqs ? : bnx2x_vf_max_queue_cnt(bp, vf);
|
||||
if (resc->num_mac_filters)
|
||||
vf_mac_rules_cnt(vf) = resc->num_mac_filters;
|
||||
/* Add an additional vlan filter credit for the hypervisor */
|
||||
bnx2x_iov_re_set_vlan_filters(bp, vf, resc->num_vlan_filters + 1);
|
||||
|
||||
DP(BNX2X_MSG_IOV,
|
||||
"Fulfilling vf request: sb count %d, tx_count %d, rx_count %d, mac_rules_count %d, vlan_rules_count %d\n",
|
||||
vf_sb_count(vf), vf_rxq_count(vf),
|
||||
vf_txq_count(vf), vf_mac_rules_cnt(vf),
|
||||
vf_vlan_rules_visible_cnt(vf));
|
||||
vf_vlan_rules_cnt(vf));
|
||||
|
||||
/* Initialize the queues */
|
||||
if (!vf->vfqs) {
|
||||
|
|
@ -2133,7 +2086,6 @@ int bnx2x_vf_acquire(struct bnx2x *bp, struct bnx2x_virtf *vf,
|
|||
int bnx2x_vf_init(struct bnx2x *bp, struct bnx2x_virtf *vf, dma_addr_t *sb_map)
|
||||
{
|
||||
struct bnx2x_func_init_params func_init = {0};
|
||||
u16 flags = 0;
|
||||
int i;
|
||||
|
||||
/* the sb resources are initialized at this point, do the
|
||||
|
|
@ -2160,23 +2112,9 @@ int bnx2x_vf_init(struct bnx2x *bp, struct bnx2x_virtf *vf, dma_addr_t *sb_map)
|
|||
/* reset IGU VF statistics: MSIX */
|
||||
REG_WR(bp, IGU_REG_STATISTIC_NUM_MESSAGE_SENT + vf->abs_vfid * 4 , 0);
|
||||
|
||||
/* vf init */
|
||||
if (vf->cfg_flags & VF_CFG_STATS)
|
||||
flags |= (FUNC_FLG_STATS | FUNC_FLG_SPQ);
|
||||
|
||||
if (vf->cfg_flags & VF_CFG_TPA)
|
||||
flags |= FUNC_FLG_TPA;
|
||||
|
||||
if (is_vf_multi(vf))
|
||||
flags |= FUNC_FLG_RSS;
|
||||
|
||||
/* function setup */
|
||||
func_init.func_flgs = flags;
|
||||
func_init.pf_id = BP_FUNC(bp);
|
||||
func_init.func_id = FW_VF_HANDLE(vf->abs_vfid);
|
||||
func_init.fw_stat_map = vf->fw_stat_map;
|
||||
func_init.spq_map = vf->spq_map;
|
||||
func_init.spq_prod = 0;
|
||||
bnx2x_func_init(bp, &func_init);
|
||||
|
||||
/* Enable the vf */
|
||||
|
|
@ -2589,8 +2527,8 @@ void bnx2x_pf_set_vfs_vlan(struct bnx2x *bp)
|
|||
|
||||
DP(BNX2X_MSG_IOV, "configuring vlan for VFs from sp-task\n");
|
||||
for_each_vf(bp, vfidx) {
|
||||
bulletin = BP_VF_BULLETIN(bp, vfidx);
|
||||
if (BP_VF(bp, vfidx)->cfg_flags & VF_CFG_VLAN)
|
||||
bulletin = BP_VF_BULLETIN(bp, vfidx);
|
||||
if (bulletin->valid_bitmap & (1 << VLAN_VALID))
|
||||
bnx2x_set_vf_vlan(bp->dev, vfidx, bulletin->vlan, 0);
|
||||
}
|
||||
}
|
||||
|
|
@ -2808,20 +2746,58 @@ out:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static void bnx2x_set_vf_vlan_acceptance(struct bnx2x *bp,
|
||||
struct bnx2x_virtf *vf, bool accept)
|
||||
{
|
||||
struct bnx2x_rx_mode_ramrod_params rx_ramrod;
|
||||
unsigned long accept_flags;
|
||||
|
||||
/* need to remove/add the VF's accept_any_vlan bit */
|
||||
accept_flags = bnx2x_leading_vfq(vf, accept_flags);
|
||||
if (accept)
|
||||
set_bit(BNX2X_ACCEPT_ANY_VLAN, &accept_flags);
|
||||
else
|
||||
clear_bit(BNX2X_ACCEPT_ANY_VLAN, &accept_flags);
|
||||
|
||||
bnx2x_vf_prep_rx_mode(bp, LEADING_IDX, &rx_ramrod, vf,
|
||||
accept_flags);
|
||||
bnx2x_leading_vfq(vf, accept_flags) = accept_flags;
|
||||
bnx2x_config_rx_mode(bp, &rx_ramrod);
|
||||
}
|
||||
|
||||
static int bnx2x_set_vf_vlan_filter(struct bnx2x *bp, struct bnx2x_virtf *vf,
|
||||
u16 vlan, bool add)
|
||||
{
|
||||
struct bnx2x_vlan_mac_ramrod_params ramrod_param;
|
||||
unsigned long ramrod_flags = 0;
|
||||
int rc = 0;
|
||||
|
||||
/* configure the new vlan to device */
|
||||
memset(&ramrod_param, 0, sizeof(ramrod_param));
|
||||
__set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
|
||||
ramrod_param.vlan_mac_obj = &bnx2x_leading_vfq(vf, vlan_obj);
|
||||
ramrod_param.ramrod_flags = ramrod_flags;
|
||||
ramrod_param.user_req.u.vlan.vlan = vlan;
|
||||
ramrod_param.user_req.cmd = add ? BNX2X_VLAN_MAC_ADD
|
||||
: BNX2X_VLAN_MAC_DEL;
|
||||
rc = bnx2x_config_vlan_mac(bp, &ramrod_param);
|
||||
if (rc) {
|
||||
BNX2X_ERR("failed to configure vlan\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bnx2x_set_vf_vlan(struct net_device *dev, int vfidx, u16 vlan, u8 qos)
|
||||
{
|
||||
struct bnx2x_queue_state_params q_params = {NULL};
|
||||
struct bnx2x_vlan_mac_ramrod_params ramrod_param;
|
||||
struct bnx2x_queue_update_params *update_params;
|
||||
struct pf_vf_bulletin_content *bulletin = NULL;
|
||||
struct bnx2x_rx_mode_ramrod_params rx_ramrod;
|
||||
struct bnx2x *bp = netdev_priv(dev);
|
||||
struct bnx2x_vlan_mac_obj *vlan_obj;
|
||||
unsigned long vlan_mac_flags = 0;
|
||||
unsigned long ramrod_flags = 0;
|
||||
struct bnx2x_virtf *vf = NULL;
|
||||
unsigned long accept_flags;
|
||||
int rc;
|
||||
int i, rc;
|
||||
|
||||
if (vlan > 4095) {
|
||||
BNX2X_ERR("illegal vlan value %d\n", vlan);
|
||||
|
|
@ -2850,6 +2826,10 @@ int bnx2x_set_vf_vlan(struct net_device *dev, int vfidx, u16 vlan, u8 qos)
|
|||
bulletin->valid_bitmap &= ~(1 << VLAN_VALID);
|
||||
bulletin->vlan = vlan;
|
||||
|
||||
/* Post update on VF's bulletin board */
|
||||
rc = bnx2x_post_vf_bulletin(bp, vfidx);
|
||||
if (rc)
|
||||
BNX2X_ERR("failed to update VF[%d] bulletin\n", vfidx);
|
||||
mutex_unlock(&bp->vfdb->bulletin_mutex);
|
||||
|
||||
/* is vf initialized and queue set up? */
|
||||
|
|
@ -2876,84 +2856,76 @@ int bnx2x_set_vf_vlan(struct net_device *dev, int vfidx, u16 vlan, u8 qos)
|
|||
goto out;
|
||||
}
|
||||
|
||||
/* need to remove/add the VF's accept_any_vlan bit */
|
||||
accept_flags = bnx2x_leading_vfq(vf, accept_flags);
|
||||
if (vlan)
|
||||
clear_bit(BNX2X_ACCEPT_ANY_VLAN, &accept_flags);
|
||||
else
|
||||
set_bit(BNX2X_ACCEPT_ANY_VLAN, &accept_flags);
|
||||
|
||||
bnx2x_vf_prep_rx_mode(bp, LEADING_IDX, &rx_ramrod, vf,
|
||||
accept_flags);
|
||||
bnx2x_leading_vfq(vf, accept_flags) = accept_flags;
|
||||
bnx2x_config_rx_mode(bp, &rx_ramrod);
|
||||
|
||||
/* configure the new vlan to device */
|
||||
memset(&ramrod_param, 0, sizeof(ramrod_param));
|
||||
__set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
|
||||
ramrod_param.vlan_mac_obj = vlan_obj;
|
||||
ramrod_param.ramrod_flags = ramrod_flags;
|
||||
set_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
|
||||
&ramrod_param.user_req.vlan_mac_flags);
|
||||
ramrod_param.user_req.u.vlan.vlan = vlan;
|
||||
ramrod_param.user_req.cmd = BNX2X_VLAN_MAC_ADD;
|
||||
rc = bnx2x_config_vlan_mac(bp, &ramrod_param);
|
||||
if (rc) {
|
||||
BNX2X_ERR("failed to configure vlan\n");
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* send queue update ramrod to configure default vlan and silent
|
||||
* vlan removal
|
||||
/* clear accept_any_vlan when HV forces vlan, otherwise
|
||||
* according to VF capabilities
|
||||
*/
|
||||
__set_bit(RAMROD_COMP_WAIT, &q_params.ramrod_flags);
|
||||
q_params.cmd = BNX2X_Q_CMD_UPDATE;
|
||||
q_params.q_obj = &bnx2x_leading_vfq(vf, sp_obj);
|
||||
update_params = &q_params.params.update;
|
||||
__set_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN_CHNG,
|
||||
&update_params->update_flags);
|
||||
__set_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM_CHNG,
|
||||
&update_params->update_flags);
|
||||
if (vlan == 0) {
|
||||
/* if vlan is 0 then we want to leave the VF traffic
|
||||
* untagged, and leave the incoming traffic untouched
|
||||
* (i.e. do not remove any vlan tags).
|
||||
*/
|
||||
__clear_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN,
|
||||
&update_params->update_flags);
|
||||
__clear_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM,
|
||||
&update_params->update_flags);
|
||||
} else {
|
||||
/* configure default vlan to vf queue and set silent
|
||||
* vlan removal (the vf remains unaware of this vlan).
|
||||
*/
|
||||
__set_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN,
|
||||
&update_params->update_flags);
|
||||
__set_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM,
|
||||
&update_params->update_flags);
|
||||
update_params->def_vlan = vlan;
|
||||
update_params->silent_removal_value =
|
||||
vlan & VLAN_VID_MASK;
|
||||
update_params->silent_removal_mask = VLAN_VID_MASK;
|
||||
}
|
||||
if (vlan || !(vf->cfg_flags & VF_CFG_VLAN_FILTER))
|
||||
bnx2x_set_vf_vlan_acceptance(bp, vf, !vlan);
|
||||
|
||||
/* Update the Queue state */
|
||||
rc = bnx2x_queue_state_change(bp, &q_params);
|
||||
if (rc) {
|
||||
BNX2X_ERR("Failed to configure default VLAN\n");
|
||||
rc = bnx2x_set_vf_vlan_filter(bp, vf, vlan, true);
|
||||
if (rc)
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
/* clear the flag indicating that this VF needs its vlan
|
||||
* (will only be set if the HV configured the Vlan before vf was
|
||||
* up and we were called because the VF came up later
|
||||
/* send queue update ramrods to configure default vlan and
|
||||
* silent vlan removal
|
||||
*/
|
||||
for_each_vfq(vf, i) {
|
||||
struct bnx2x_queue_state_params q_params = {NULL};
|
||||
struct bnx2x_queue_update_params *update_params;
|
||||
|
||||
q_params.q_obj = &bnx2x_vfq(vf, i, sp_obj);
|
||||
|
||||
/* validate the Q is UP */
|
||||
if (bnx2x_get_q_logical_state(bp, q_params.q_obj) !=
|
||||
BNX2X_Q_LOGICAL_STATE_ACTIVE)
|
||||
continue;
|
||||
|
||||
__set_bit(RAMROD_COMP_WAIT, &q_params.ramrod_flags);
|
||||
q_params.cmd = BNX2X_Q_CMD_UPDATE;
|
||||
update_params = &q_params.params.update;
|
||||
__set_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN_CHNG,
|
||||
&update_params->update_flags);
|
||||
__set_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM_CHNG,
|
||||
&update_params->update_flags);
|
||||
if (vlan == 0) {
|
||||
/* if vlan is 0 then we want to leave the VF traffic
|
||||
* untagged, and leave the incoming traffic untouched
|
||||
* (i.e. do not remove any vlan tags).
|
||||
*/
|
||||
__clear_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN,
|
||||
&update_params->update_flags);
|
||||
__clear_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM,
|
||||
&update_params->update_flags);
|
||||
} else {
|
||||
/* configure default vlan to vf queue and set silent
|
||||
* vlan removal (the vf remains unaware of this vlan).
|
||||
*/
|
||||
__set_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN,
|
||||
&update_params->update_flags);
|
||||
__set_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM,
|
||||
&update_params->update_flags);
|
||||
update_params->def_vlan = vlan;
|
||||
update_params->silent_removal_value =
|
||||
vlan & VLAN_VID_MASK;
|
||||
update_params->silent_removal_mask = VLAN_VID_MASK;
|
||||
}
|
||||
|
||||
/* Update the Queue state */
|
||||
rc = bnx2x_queue_state_change(bp, &q_params);
|
||||
if (rc) {
|
||||
BNX2X_ERR("Failed to configure default VLAN queue %d\n",
|
||||
i);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
out:
|
||||
vf->cfg_flags &= ~VF_CFG_VLAN;
|
||||
bnx2x_unlock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_VLAN);
|
||||
|
||||
if (rc)
|
||||
DP(BNX2X_MSG_IOV,
|
||||
"updated VF[%d] vlan configuration (vlan = %d)\n",
|
||||
vfidx, vlan);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
/* bnx2x_sriov.h: Broadcom Everest network driver.
|
||||
/* bnx2x_sriov.h: QLogic Everest network driver.
|
||||
*
|
||||
* Copyright 2009-2013 Broadcom Corporation
|
||||
* Copyright 2014 QLogic Corporation
|
||||
* All rights reserved
|
||||
*
|
||||
* Unless you and Broadcom execute a separate written software license
|
||||
* Unless you and QLogic execute a separate written software license
|
||||
* agreement governing use of this software, this software is licensed to you
|
||||
* under the terms of the GNU General Public License version 2, available
|
||||
* at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL").
|
||||
*
|
||||
* Notwithstanding the above, under no circumstances may you combine this
|
||||
* software in any way with any other Broadcom software provided under a
|
||||
* license other than the GPL, without Broadcom's express prior written
|
||||
* software in any way with any other QLogic software provided under a
|
||||
* license other than the GPL, without QLogic's express prior written
|
||||
* consent.
|
||||
*
|
||||
* Maintained by: Ariel Elior <ariel.elior@qlogic.com>
|
||||
|
|
@ -75,7 +77,10 @@ struct bnx2x_vf_queue {
|
|||
|
||||
/* VLANs object */
|
||||
struct bnx2x_vlan_mac_obj vlan_obj;
|
||||
atomic_t vlan_count; /* 0 means vlan-0 is set ~ untagged */
|
||||
|
||||
/* VLAN-MACs object */
|
||||
struct bnx2x_vlan_mac_obj vlan_mac_obj;
|
||||
|
||||
unsigned long accept_flags; /* last accept flags configured */
|
||||
|
||||
/* Queue Slow-path State object */
|
||||
|
|
@ -103,8 +108,10 @@ struct bnx2x_virtf;
|
|||
|
||||
struct bnx2x_vf_mac_vlan_filter {
|
||||
int type;
|
||||
#define BNX2X_VF_FILTER_MAC 1
|
||||
#define BNX2X_VF_FILTER_VLAN 2
|
||||
#define BNX2X_VF_FILTER_MAC BIT(0)
|
||||
#define BNX2X_VF_FILTER_VLAN BIT(1)
|
||||
#define BNX2X_VF_FILTER_VLAN_MAC \
|
||||
(BNX2X_VF_FILTER_MAC | BNX2X_VF_FILTER_VLAN) /*shortcut*/
|
||||
|
||||
bool add;
|
||||
u8 *mac;
|
||||
|
|
@ -119,14 +126,9 @@ struct bnx2x_vf_mac_vlan_filters {
|
|||
/* vf context */
|
||||
struct bnx2x_virtf {
|
||||
u16 cfg_flags;
|
||||
#define VF_CFG_STATS 0x0001
|
||||
#define VF_CFG_FW_FC 0x0002
|
||||
#define VF_CFG_TPA 0x0004
|
||||
#define VF_CFG_INT_SIMD 0x0008
|
||||
#define VF_CACHE_LINE 0x0010
|
||||
#define VF_CFG_VLAN 0x0020
|
||||
#define VF_CFG_STATS_COALESCE 0x0040
|
||||
#define VF_CFG_EXT_BULLETIN 0x0080
|
||||
#define VF_CFG_STATS_COALESCE 0x1
|
||||
#define VF_CFG_EXT_BULLETIN 0x2
|
||||
#define VF_CFG_VLAN_FILTER 0x4
|
||||
u8 link_cfg; /* IFLA_VF_LINK_STATE_AUTO
|
||||
* IFLA_VF_LINK_STATE_ENABLE
|
||||
* IFLA_VF_LINK_STATE_DISABLE
|
||||
|
|
@ -140,9 +142,8 @@ struct bnx2x_virtf {
|
|||
bool flr_clnup_stage; /* true during flr cleanup */
|
||||
|
||||
/* dma */
|
||||
dma_addr_t fw_stat_map; /* valid iff VF_CFG_STATS */
|
||||
dma_addr_t fw_stat_map;
|
||||
u16 stats_stride;
|
||||
dma_addr_t spq_map;
|
||||
dma_addr_t bulletin_map;
|
||||
|
||||
/* Allocated resources counters. Before the VF is acquired, the
|
||||
|
|
@ -163,8 +164,6 @@ struct bnx2x_virtf {
|
|||
#define vf_mac_rules_cnt(vf) ((vf)->alloc_resc.num_mac_filters)
|
||||
#define vf_vlan_rules_cnt(vf) ((vf)->alloc_resc.num_vlan_filters)
|
||||
#define vf_mc_rules_cnt(vf) ((vf)->alloc_resc.num_mc_filters)
|
||||
/* Hide a single vlan filter credit for the hypervisor */
|
||||
#define vf_vlan_rules_visible_cnt(vf) (vf_vlan_rules_cnt(vf) - 1)
|
||||
|
||||
u8 sb_count; /* actual number of SBs */
|
||||
u8 igu_base_id; /* base igu status block id */
|
||||
|
|
@ -207,6 +206,9 @@ struct bnx2x_virtf {
|
|||
enum channel_tlvs op_current;
|
||||
|
||||
u8 fp_hsi;
|
||||
|
||||
struct bnx2x_credit_pool_obj vf_vlans_pool;
|
||||
struct bnx2x_credit_pool_obj vf_macs_pool;
|
||||
};
|
||||
|
||||
#define BNX2X_NR_VIRTFN(bp) ((bp)->vfdb->sriov.nr_virtfn)
|
||||
|
|
@ -230,6 +232,12 @@ struct bnx2x_virtf {
|
|||
#define FW_VF_HANDLE(abs_vfid) \
|
||||
(abs_vfid + FW_PF_MAX_HANDLE)
|
||||
|
||||
#define GET_NUM_VFS_PER_PATH(bp) 64 /* use max possible value */
|
||||
#define GET_NUM_VFS_PER_PF(bp) ((bp)->vfdb ? (bp)->vfdb->sriov.total \
|
||||
: 0)
|
||||
#define VF_MAC_CREDIT_CNT 1
|
||||
#define VF_VLAN_CREDIT_CNT 2 /* VLAN0 + 'real' VLAN */
|
||||
|
||||
/* locking and unlocking the channel mutex */
|
||||
void bnx2x_lock_vf_pf_channel(struct bnx2x *bp, struct bnx2x_virtf *vf,
|
||||
enum channel_tlvs tlv);
|
||||
|
|
@ -273,6 +281,10 @@ struct bnx2x_vf_sp {
|
|||
struct eth_classify_rules_ramrod_data e2;
|
||||
} vlan_rdata;
|
||||
|
||||
union {
|
||||
struct eth_classify_rules_ramrod_data e2;
|
||||
} vlan_mac_rdata;
|
||||
|
||||
union {
|
||||
struct eth_filter_rules_ramrod_data e2;
|
||||
} rx_mode_rdata;
|
||||
|
|
@ -536,8 +548,14 @@ int bnx2x_iov_link_update_vf(struct bnx2x *bp, int idx);
|
|||
|
||||
int bnx2x_set_vf_link_state(struct net_device *dev, int vf, int link_state);
|
||||
|
||||
int bnx2x_vfpf_update_vlan(struct bnx2x *bp, u16 vid, u8 vf_qid, bool add);
|
||||
#else /* CONFIG_BNX2X_SRIOV */
|
||||
|
||||
#define GET_NUM_VFS_PER_PATH(bp) 0
|
||||
#define GET_NUM_VFS_PER_PF(bp) 0
|
||||
#define VF_MAC_CREDIT_CNT 0
|
||||
#define VF_VLAN_CREDIT_CNT 0
|
||||
|
||||
static inline void bnx2x_iov_set_queue_sp_obj(struct bnx2x *bp, int vf_cid,
|
||||
struct bnx2x_queue_sp_obj **q_obj) {}
|
||||
static inline void bnx2x_vf_handle_flr_event(struct bnx2x *bp) {}
|
||||
|
|
@ -604,5 +622,7 @@ struct pf_vf_bulletin_content;
|
|||
static inline void bnx2x_vf_bulletin_finalize(struct pf_vf_bulletin_content *bulletin,
|
||||
bool support_long) {}
|
||||
|
||||
static inline int bnx2x_vfpf_update_vlan(struct bnx2x *bp, u16 vid, u8 vf_qid, bool add) {return 0; }
|
||||
|
||||
#endif /* CONFIG_BNX2X_SRIOV */
|
||||
#endif /* bnx2x_sriov.h */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
/* bnx2x_stats.c: Broadcom Everest network driver.
|
||||
/* bnx2x_stats.c: QLogic Everest network driver.
|
||||
*
|
||||
* Copyright (c) 2007-2013 Broadcom Corporation
|
||||
* Copyright (c) 2014 QLogic Corporation
|
||||
* All rights reserved
|
||||
*
|
||||
* 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
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
/* bnx2x_stats.h: Broadcom Everest network driver.
|
||||
/* bnx2x_stats.h: QLogic Everest network driver.
|
||||
*
|
||||
* Copyright (c) 2007-2013 Broadcom Corporation
|
||||
* Copyright (c) 2014 QLogic Corporation
|
||||
* All rights reserved
|
||||
*
|
||||
* 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
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
/* bnx2x_vfpf.c: Broadcom Everest network driver.
|
||||
/* bnx2x_vfpf.c: QLogic Everest network driver.
|
||||
*
|
||||
* Copyright 2009-2013 Broadcom Corporation
|
||||
* Copyright 2014 QLogic Corporation
|
||||
* All rights reserved
|
||||
*
|
||||
* Unless you and Broadcom execute a separate written software license
|
||||
* Unless you and QLogic execute a separate written software license
|
||||
* agreement governing use of this software, this software is licensed to you
|
||||
* under the terms of the GNU General Public License version 2, available
|
||||
* at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL").
|
||||
*
|
||||
* Notwithstanding the above, under no circumstances may you combine this
|
||||
* software in any way with any other Broadcom software provided under a
|
||||
* license other than the GPL, without Broadcom's express prior written
|
||||
* software in any way with any other QLogic software provided under a
|
||||
* license other than the GPL, without QLogic's express prior written
|
||||
* consent.
|
||||
*
|
||||
* Maintained by: Ariel Elior <ariel.elior@qlogic.com>
|
||||
|
|
@ -245,6 +247,7 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count)
|
|||
req->resc_request.num_sbs = bp->igu_sb_cnt;
|
||||
req->resc_request.num_mac_filters = VF_ACQUIRE_MAC_FILTERS;
|
||||
req->resc_request.num_mc_filters = VF_ACQUIRE_MC_FILTERS;
|
||||
req->resc_request.num_vlan_filters = VF_ACQUIRE_VLAN_FILTERS;
|
||||
|
||||
/* pf 2 vf bulletin board address */
|
||||
req->bulletin_addr = bp->pf2vf_bulletin_mapping;
|
||||
|
|
@ -255,6 +258,8 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count)
|
|||
|
||||
/* Bulletin support for bulletin board with length > legacy length */
|
||||
req->vfdev_info.caps |= VF_CAP_SUPPORT_EXT_BULLETIN;
|
||||
/* vlan filtering is supported */
|
||||
req->vfdev_info.caps |= VF_CAP_SUPPORT_VLAN_FILTER;
|
||||
|
||||
/* add list termination tlv */
|
||||
bnx2x_add_tlv(bp, req,
|
||||
|
|
@ -373,6 +378,8 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count)
|
|||
NO_WOL_FLAG | NO_ISCSI_OOO_FLAG | NO_ISCSI_FLAG | NO_FCOE_FLAG;
|
||||
bp->igu_sb_cnt = bp->acquire_resp.resc.num_sbs;
|
||||
bp->igu_base_sb = bp->acquire_resp.resc.hw_sbs[0].hw_sb_id;
|
||||
bp->vlan_credit = bp->acquire_resp.resc.num_vlan_filters;
|
||||
|
||||
strlcpy(bp->fw_ver, bp->acquire_resp.pfdev_info.fw_ver,
|
||||
sizeof(bp->fw_ver));
|
||||
|
||||
|
|
@ -546,7 +553,7 @@ static void bnx2x_leading_vfq_init(struct bnx2x *bp, struct bnx2x_virtf *vf,
|
|||
BNX2X_FILTER_MAC_PENDING,
|
||||
&vf->filter_state,
|
||||
BNX2X_OBJ_TYPE_RX_TX,
|
||||
&bp->macs_pool);
|
||||
&vf->vf_macs_pool);
|
||||
/* vlan */
|
||||
bnx2x_init_vlan_obj(bp, &q->vlan_obj,
|
||||
cl_id, q->cid, func_id,
|
||||
|
|
@ -555,8 +562,17 @@ static void bnx2x_leading_vfq_init(struct bnx2x *bp, struct bnx2x_virtf *vf,
|
|||
BNX2X_FILTER_VLAN_PENDING,
|
||||
&vf->filter_state,
|
||||
BNX2X_OBJ_TYPE_RX_TX,
|
||||
&bp->vlans_pool);
|
||||
|
||||
&vf->vf_vlans_pool);
|
||||
/* vlan-mac */
|
||||
bnx2x_init_vlan_mac_obj(bp, &q->vlan_mac_obj,
|
||||
cl_id, q->cid, func_id,
|
||||
bnx2x_vf_sp(bp, vf, vlan_mac_rdata),
|
||||
bnx2x_vf_sp_map(bp, vf, vlan_mac_rdata),
|
||||
BNX2X_FILTER_VLAN_MAC_PENDING,
|
||||
&vf->filter_state,
|
||||
BNX2X_OBJ_TYPE_RX_TX,
|
||||
&vf->vf_macs_pool,
|
||||
&vf->vf_vlans_pool);
|
||||
/* mcast */
|
||||
bnx2x_init_mcast_obj(bp, &vf->mcast_obj, cl_id,
|
||||
q->cid, func_id, func_id,
|
||||
|
|
@ -723,7 +739,7 @@ int bnx2x_vfpf_config_mac(struct bnx2x *bp, u8 *addr, u8 vf_qid, bool set)
|
|||
|
||||
req->filters[0].flags = VFPF_Q_FILTER_DEST_MAC_VALID;
|
||||
if (set)
|
||||
req->filters[0].flags |= VFPF_Q_FILTER_SET_MAC;
|
||||
req->filters[0].flags |= VFPF_Q_FILTER_SET;
|
||||
|
||||
/* sample bulletin board for new mac */
|
||||
bnx2x_sample_bulletin(bp);
|
||||
|
|
@ -911,6 +927,67 @@ out:
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* request pf to add a vlan for the vf */
|
||||
int bnx2x_vfpf_update_vlan(struct bnx2x *bp, u16 vid, u8 vf_qid, bool add)
|
||||
{
|
||||
struct vfpf_set_q_filters_tlv *req = &bp->vf2pf_mbox->req.set_q_filters;
|
||||
struct pfvf_general_resp_tlv *resp = &bp->vf2pf_mbox->resp.general_resp;
|
||||
int rc = 0;
|
||||
|
||||
if (!(bp->acquire_resp.pfdev_info.pf_cap & PFVF_CAP_VLAN_FILTER)) {
|
||||
DP(BNX2X_MSG_IOV, "HV does not support vlan filtering\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* clear mailbox and prep first tlv */
|
||||
bnx2x_vfpf_prep(bp, &req->first_tlv, CHANNEL_TLV_SET_Q_FILTERS,
|
||||
sizeof(*req));
|
||||
|
||||
req->flags = VFPF_SET_Q_FILTERS_MAC_VLAN_CHANGED;
|
||||
req->vf_qid = vf_qid;
|
||||
req->n_mac_vlan_filters = 1;
|
||||
|
||||
req->filters[0].flags = VFPF_Q_FILTER_VLAN_TAG_VALID;
|
||||
|
||||
if (add)
|
||||
req->filters[0].flags |= VFPF_Q_FILTER_SET;
|
||||
|
||||
/* sample bulletin board for hypervisor vlan */
|
||||
bnx2x_sample_bulletin(bp);
|
||||
|
||||
if (bp->shadow_bulletin.content.valid_bitmap & 1 << VLAN_VALID) {
|
||||
BNX2X_ERR("Hypervisor will dicline the request, avoiding\n");
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
req->filters[0].vlan_tag = vid;
|
||||
|
||||
/* add list termination tlv */
|
||||
bnx2x_add_tlv(bp, req, req->first_tlv.tl.length, CHANNEL_TLV_LIST_END,
|
||||
sizeof(struct channel_list_end_tlv));
|
||||
|
||||
/* output tlvs list */
|
||||
bnx2x_dp_tlv_list(bp, req);
|
||||
|
||||
/* send message to pf */
|
||||
rc = bnx2x_send_msg2pf(bp, &resp->hdr.status, bp->vf2pf_mbox_mapping);
|
||||
if (rc) {
|
||||
BNX2X_ERR("failed to send message to pf. rc was %d\n", rc);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
|
||||
BNX2X_ERR("vfpf %s VLAN %d failed\n", add ? "add" : "del",
|
||||
vid);
|
||||
rc = -EINVAL;
|
||||
}
|
||||
out:
|
||||
bnx2x_vfpf_finalize(bp, &req->first_tlv);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int bnx2x_vfpf_storm_rx_mode(struct bnx2x *bp)
|
||||
{
|
||||
int mode = bp->rx_mode;
|
||||
|
|
@ -934,8 +1011,13 @@ int bnx2x_vfpf_storm_rx_mode(struct bnx2x *bp)
|
|||
req->rx_mask = VFPF_RX_MASK_ACCEPT_MATCHED_MULTICAST;
|
||||
req->rx_mask |= VFPF_RX_MASK_ACCEPT_MATCHED_UNICAST;
|
||||
req->rx_mask |= VFPF_RX_MASK_ACCEPT_BROADCAST;
|
||||
if (mode == BNX2X_RX_MODE_PROMISC)
|
||||
req->rx_mask |= VFPF_RX_MASK_ACCEPT_ANY_VLAN;
|
||||
}
|
||||
|
||||
if (bp->accept_any_vlan)
|
||||
req->rx_mask |= VFPF_RX_MASK_ACCEPT_ANY_VLAN;
|
||||
|
||||
req->flags |= VFPF_SET_Q_FILTERS_RX_MASK_CHANGED;
|
||||
req->vf_qid = 0;
|
||||
|
||||
|
|
@ -1188,7 +1270,8 @@ static void bnx2x_vf_mbx_acquire_resp(struct bnx2x *bp, struct bnx2x_virtf *vf,
|
|||
resp->pfdev_info.indices_per_sb = HC_SB_MAX_INDICES_E2;
|
||||
resp->pfdev_info.pf_cap = (PFVF_CAP_RSS |
|
||||
PFVF_CAP_TPA |
|
||||
PFVF_CAP_TPA_UPDATE);
|
||||
PFVF_CAP_TPA_UPDATE |
|
||||
PFVF_CAP_VLAN_FILTER);
|
||||
bnx2x_fill_fw_str(bp, resp->pfdev_info.fw_ver,
|
||||
sizeof(resp->pfdev_info.fw_ver));
|
||||
|
||||
|
|
@ -1203,7 +1286,7 @@ static void bnx2x_vf_mbx_acquire_resp(struct bnx2x *bp, struct bnx2x_virtf *vf,
|
|||
bnx2x_vf_max_queue_cnt(bp, vf);
|
||||
resc->num_sbs = vf_sb_count(vf);
|
||||
resc->num_mac_filters = vf_mac_rules_cnt(vf);
|
||||
resc->num_vlan_filters = vf_vlan_rules_visible_cnt(vf);
|
||||
resc->num_vlan_filters = vf_vlan_rules_cnt(vf);
|
||||
resc->num_mc_filters = 0;
|
||||
|
||||
if (status == PFVF_STATUS_SUCCESS) {
|
||||
|
|
@ -1370,6 +1453,14 @@ static void bnx2x_vf_mbx_acquire(struct bnx2x *bp, struct bnx2x_virtf *vf,
|
|||
vf->cfg_flags &= ~VF_CFG_EXT_BULLETIN;
|
||||
}
|
||||
|
||||
if (acquire->vfdev_info.caps & VF_CAP_SUPPORT_VLAN_FILTER) {
|
||||
DP(BNX2X_MSG_IOV, "VF[%d] supports vlan filtering\n",
|
||||
vf->abs_vfid);
|
||||
vf->cfg_flags |= VF_CFG_VLAN_FILTER;
|
||||
} else {
|
||||
vf->cfg_flags &= ~VF_CFG_VLAN_FILTER;
|
||||
}
|
||||
|
||||
out:
|
||||
/* response */
|
||||
bnx2x_vf_mbx_acquire_resp(bp, vf, mbx, rc);
|
||||
|
|
@ -1382,7 +1473,6 @@ static void bnx2x_vf_mbx_init_vf(struct bnx2x *bp, struct bnx2x_virtf *vf,
|
|||
int rc;
|
||||
|
||||
/* record ghost addresses from vf message */
|
||||
vf->spq_map = init->spq_addr;
|
||||
vf->fw_stat_map = init->stats_addr;
|
||||
vf->stats_stride = init->stats_stride;
|
||||
rc = bnx2x_vf_init(bp, vf, (dma_addr_t *)init->sb_addr);
|
||||
|
|
@ -1578,17 +1668,18 @@ static int bnx2x_vf_mbx_macvlan_list(struct bnx2x *bp,
|
|||
|
||||
if ((msg_filter->flags & type_flag) != type_flag)
|
||||
continue;
|
||||
if (type_flag == VFPF_Q_FILTER_DEST_MAC_VALID) {
|
||||
memset(&fl->filters[j], 0, sizeof(fl->filters[j]));
|
||||
if (type_flag & VFPF_Q_FILTER_DEST_MAC_VALID) {
|
||||
fl->filters[j].mac = msg_filter->mac;
|
||||
fl->filters[j].type = BNX2X_VF_FILTER_MAC;
|
||||
} else {
|
||||
fl->filters[j].vid = msg_filter->vlan_tag;
|
||||
fl->filters[j].type = BNX2X_VF_FILTER_VLAN;
|
||||
fl->filters[j].type |= BNX2X_VF_FILTER_MAC;
|
||||
}
|
||||
fl->filters[j].add =
|
||||
(msg_filter->flags & VFPF_Q_FILTER_SET_MAC) ?
|
||||
true : false;
|
||||
if (type_flag & VFPF_Q_FILTER_VLAN_TAG_VALID) {
|
||||
fl->filters[j].vid = msg_filter->vlan_tag;
|
||||
fl->filters[j].type |= BNX2X_VF_FILTER_VLAN;
|
||||
}
|
||||
fl->filters[j].add = !!(msg_filter->flags & VFPF_Q_FILTER_SET);
|
||||
fl->count++;
|
||||
j++;
|
||||
}
|
||||
if (!fl->count)
|
||||
kfree(fl);
|
||||
|
|
@ -1598,6 +1689,18 @@ static int bnx2x_vf_mbx_macvlan_list(struct bnx2x *bp,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int bnx2x_vf_filters_contain(struct vfpf_set_q_filters_tlv *filters,
|
||||
u32 flags)
|
||||
{
|
||||
int i, cnt = 0;
|
||||
|
||||
for (i = 0; i < filters->n_mac_vlan_filters; i++)
|
||||
if ((filters->filters[i].flags & flags) == flags)
|
||||
cnt++;
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
static void bnx2x_vf_mbx_dp_q_filter(struct bnx2x *bp, int msglvl, int idx,
|
||||
struct vfpf_q_mac_vlan_filter *filter)
|
||||
{
|
||||
|
|
@ -1629,6 +1732,7 @@ static void bnx2x_vf_mbx_dp_q_filters(struct bnx2x *bp, int msglvl,
|
|||
|
||||
#define VFPF_MAC_FILTER VFPF_Q_FILTER_DEST_MAC_VALID
|
||||
#define VFPF_VLAN_FILTER VFPF_Q_FILTER_VLAN_TAG_VALID
|
||||
#define VFPF_VLAN_MAC_FILTER (VFPF_VLAN_FILTER | VFPF_MAC_FILTER)
|
||||
|
||||
static int bnx2x_vf_mbx_qfilters(struct bnx2x *bp, struct bnx2x_virtf *vf)
|
||||
{
|
||||
|
|
@ -1639,16 +1743,33 @@ static int bnx2x_vf_mbx_qfilters(struct bnx2x *bp, struct bnx2x_virtf *vf)
|
|||
|
||||
/* check for any mac/vlan changes */
|
||||
if (msg->flags & VFPF_SET_Q_FILTERS_MAC_VLAN_CHANGED) {
|
||||
/* build mac list */
|
||||
struct bnx2x_vf_mac_vlan_filters *fl = NULL;
|
||||
|
||||
/* build vlan-mac list */
|
||||
rc = bnx2x_vf_mbx_macvlan_list(bp, vf, msg, &fl,
|
||||
VFPF_VLAN_MAC_FILTER);
|
||||
if (rc)
|
||||
goto op_err;
|
||||
|
||||
if (fl) {
|
||||
|
||||
/* set vlan-mac list */
|
||||
rc = bnx2x_vf_mac_vlan_config_list(bp, vf, fl,
|
||||
msg->vf_qid,
|
||||
false);
|
||||
if (rc)
|
||||
goto op_err;
|
||||
}
|
||||
|
||||
/* build mac list */
|
||||
fl = NULL;
|
||||
|
||||
rc = bnx2x_vf_mbx_macvlan_list(bp, vf, msg, &fl,
|
||||
VFPF_MAC_FILTER);
|
||||
if (rc)
|
||||
goto op_err;
|
||||
|
||||
if (fl) {
|
||||
|
||||
/* set mac list */
|
||||
rc = bnx2x_vf_mac_vlan_config_list(bp, vf, fl,
|
||||
msg->vf_qid,
|
||||
|
|
@ -1657,22 +1778,6 @@ static int bnx2x_vf_mbx_qfilters(struct bnx2x *bp, struct bnx2x_virtf *vf)
|
|||
goto op_err;
|
||||
}
|
||||
|
||||
/* build vlan list */
|
||||
fl = NULL;
|
||||
|
||||
rc = bnx2x_vf_mbx_macvlan_list(bp, vf, msg, &fl,
|
||||
VFPF_VLAN_FILTER);
|
||||
if (rc)
|
||||
goto op_err;
|
||||
|
||||
if (fl) {
|
||||
/* set vlan list */
|
||||
rc = bnx2x_vf_mac_vlan_config_list(bp, vf, fl,
|
||||
msg->vf_qid,
|
||||
false);
|
||||
if (rc)
|
||||
goto op_err;
|
||||
}
|
||||
}
|
||||
|
||||
if (msg->flags & VFPF_SET_Q_FILTERS_RX_MASK_CHANGED) {
|
||||
|
|
@ -1687,11 +1792,15 @@ static int bnx2x_vf_mbx_qfilters(struct bnx2x *bp, struct bnx2x_virtf *vf)
|
|||
__set_bit(BNX2X_ACCEPT_BROADCAST, &accept);
|
||||
}
|
||||
|
||||
/* A packet arriving the vf's mac should be accepted
|
||||
* with any vlan, unless a vlan has already been
|
||||
* configured.
|
||||
/* any_vlan is not configured if HV is forcing VLAN
|
||||
* any_vlan is configured if
|
||||
* 1. VF does not support vlan filtering
|
||||
* OR
|
||||
* 2. VF supports vlan filtering and explicitly requested it
|
||||
*/
|
||||
if (!(bulletin->valid_bitmap & (1 << VLAN_VALID)))
|
||||
if (!(bulletin->valid_bitmap & (1 << VLAN_VALID)) &&
|
||||
(!(vf->cfg_flags & VF_CFG_VLAN_FILTER) ||
|
||||
msg->rx_mask & VFPF_RX_MASK_ACCEPT_ANY_VLAN))
|
||||
__set_bit(BNX2X_ACCEPT_ANY_VLAN, &accept);
|
||||
|
||||
/* set rx-mode */
|
||||
|
|
@ -1727,17 +1836,31 @@ static int bnx2x_filters_validate_mac(struct bnx2x *bp,
|
|||
* since queue was not set up.
|
||||
*/
|
||||
if (bulletin->valid_bitmap & 1 << MAC_ADDR_VALID) {
|
||||
/* once a mac was set by ndo can only accept a single mac... */
|
||||
if (filters->n_mac_vlan_filters > 1) {
|
||||
BNX2X_ERR("VF[%d] requested the addition of multiple macs after set_vf_mac ndo was called\n",
|
||||
vf->abs_vfid);
|
||||
rc = -EPERM;
|
||||
goto response;
|
||||
struct vfpf_q_mac_vlan_filter *filter = NULL;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < filters->n_mac_vlan_filters; i++) {
|
||||
if (!(filters->filters[i].flags &
|
||||
VFPF_Q_FILTER_DEST_MAC_VALID))
|
||||
continue;
|
||||
|
||||
/* once a mac was set by ndo can only accept
|
||||
* a single mac...
|
||||
*/
|
||||
if (filter) {
|
||||
BNX2X_ERR("VF[%d] requested the addition of multiple macs after set_vf_mac ndo was called [%d filters]\n",
|
||||
vf->abs_vfid,
|
||||
filters->n_mac_vlan_filters);
|
||||
rc = -EPERM;
|
||||
goto response;
|
||||
}
|
||||
|
||||
filter = &filters->filters[i];
|
||||
}
|
||||
|
||||
/* ...and only the mac set by the ndo */
|
||||
if (filters->n_mac_vlan_filters == 1 &&
|
||||
!ether_addr_equal(filters->filters->mac, bulletin->mac)) {
|
||||
if (filter &&
|
||||
!ether_addr_equal(filter->mac, bulletin->mac)) {
|
||||
BNX2X_ERR("VF[%d] requested the addition of a mac address not matching the one configured by set_vf_mac ndo\n",
|
||||
vf->abs_vfid);
|
||||
|
||||
|
|
@ -1759,17 +1882,14 @@ static int bnx2x_filters_validate_vlan(struct bnx2x *bp,
|
|||
|
||||
/* if vlan was set by hypervisor we don't allow guest to config vlan */
|
||||
if (bulletin->valid_bitmap & 1 << VLAN_VALID) {
|
||||
int i;
|
||||
|
||||
/* search for vlan filters */
|
||||
for (i = 0; i < filters->n_mac_vlan_filters; i++) {
|
||||
if (filters->filters[i].flags &
|
||||
VFPF_Q_FILTER_VLAN_TAG_VALID) {
|
||||
BNX2X_ERR("VF[%d] attempted to configure vlan but one was already set by Hypervisor. Aborting request\n",
|
||||
vf->abs_vfid);
|
||||
rc = -EPERM;
|
||||
goto response;
|
||||
}
|
||||
|
||||
if (bnx2x_vf_filters_contain(filters,
|
||||
VFPF_Q_FILTER_VLAN_TAG_VALID)) {
|
||||
BNX2X_ERR("VF[%d] attempted to configure vlan but one was already set by Hypervisor. Aborting request\n",
|
||||
vf->abs_vfid);
|
||||
rc = -EPERM;
|
||||
goto response;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,22 @@
|
|||
/* bnx2x_vfpf.h: Broadcom Everest network driver.
|
||||
/* bnx2x_vfpf.h: Qlogic Everest network driver.
|
||||
*
|
||||
* Copyright (c) 2011-2013 Broadcom Corporation
|
||||
* Copyright (c) 2014 QLogic Corporation
|
||||
* All rights reserved
|
||||
*
|
||||
* Unless you and Broadcom execute a separate written software license
|
||||
* Unless you and Qlogic execute a separate written software license
|
||||
* agreement governing use of this software, this software is licensed to you
|
||||
* under the terms of the GNU General Public License version 2, available
|
||||
* at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL").
|
||||
* under the terms of the GNU General Public License version 2 (the “GPL”),
|
||||
* available at http://www.gnu.org/licenses/gpl-2.0.html, with the following
|
||||
* added to such license:
|
||||
*
|
||||
* Notwithstanding the above, under no circumstances may you combine this
|
||||
* software in any way with any other Broadcom software provided under a
|
||||
* license other than the GPL, without Broadcom's express prior written
|
||||
* consent.
|
||||
* As a special exception, the copyright holders of this software give you
|
||||
* permission to link this software with independent modules, and to copy and
|
||||
* distribute the resulting executable under terms of your choice, provided that
|
||||
* you also meet, for each linked independent module, the terms and conditions
|
||||
* of the license of that module. An independent module is a module which is
|
||||
* not derived from this software. The special exception does not apply to any
|
||||
* modifications of the software.
|
||||
*
|
||||
* Maintained by: Ariel Elior <ariel.elior@qlogic.com>
|
||||
* Written by: Ariel Elior <ariel.elior@qlogic.com>
|
||||
|
|
@ -64,6 +70,8 @@ struct hw_sb_info {
|
|||
#define VFPF_RX_MASK_ACCEPT_ALL_UNICAST 0x00000004
|
||||
#define VFPF_RX_MASK_ACCEPT_ALL_MULTICAST 0x00000008
|
||||
#define VFPF_RX_MASK_ACCEPT_BROADCAST 0x00000010
|
||||
#define VFPF_RX_MASK_ACCEPT_ANY_VLAN 0x00000020
|
||||
|
||||
#define BULLETIN_CONTENT_SIZE (sizeof(struct pf_vf_bulletin_content))
|
||||
#define BULLETIN_CONTENT_LEGACY_SIZE (32)
|
||||
#define BULLETIN_ATTEMPTS 5 /* crc failures before throwing towel */
|
||||
|
|
@ -127,6 +135,7 @@ struct vfpf_acquire_tlv {
|
|||
u8 fp_hsi_ver;
|
||||
u8 caps;
|
||||
#define VF_CAP_SUPPORT_EXT_BULLETIN (1 << 0)
|
||||
#define VF_CAP_SUPPORT_VLAN_FILTER (1 << 1)
|
||||
} vfdev_info;
|
||||
|
||||
struct vf_pf_resc_request resc_request;
|
||||
|
|
@ -168,10 +177,12 @@ struct pfvf_acquire_resp_tlv {
|
|||
struct pf_vf_pfdev_info {
|
||||
u32 chip_num;
|
||||
u32 pf_cap;
|
||||
#define PFVF_CAP_RSS 0x00000001
|
||||
#define PFVF_CAP_DHC 0x00000002
|
||||
#define PFVF_CAP_TPA 0x00000004
|
||||
#define PFVF_CAP_TPA_UPDATE 0x00000008
|
||||
#define PFVF_CAP_RSS 0x00000001
|
||||
#define PFVF_CAP_DHC 0x00000002
|
||||
#define PFVF_CAP_TPA 0x00000004
|
||||
#define PFVF_CAP_TPA_UPDATE 0x00000008
|
||||
#define PFVF_CAP_VLAN_FILTER 0x00000010
|
||||
|
||||
char fw_ver[32];
|
||||
u16 db_size;
|
||||
u8 indices_per_sb;
|
||||
|
|
@ -288,7 +299,7 @@ struct vfpf_q_mac_vlan_filter {
|
|||
u32 flags;
|
||||
#define VFPF_Q_FILTER_DEST_MAC_VALID 0x01
|
||||
#define VFPF_Q_FILTER_VLAN_TAG_VALID 0x02
|
||||
#define VFPF_Q_FILTER_SET_MAC 0x100 /* set/clear */
|
||||
#define VFPF_Q_FILTER_SET 0x100 /* set/clear */
|
||||
u8 mac[ETH_ALEN];
|
||||
u16 vlan_tag;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -192,6 +192,7 @@ static void cnic_ctx_wr(struct cnic_dev *dev, u32 cid_addr, u32 off, u32 val)
|
|||
struct drv_ctl_info info;
|
||||
struct drv_ctl_io *io = &info.data.io;
|
||||
|
||||
memset(&info, 0, sizeof(struct drv_ctl_info));
|
||||
info.cmd = DRV_CTL_CTX_WR_CMD;
|
||||
io->cid_addr = cid_addr;
|
||||
io->offset = off;
|
||||
|
|
@ -206,6 +207,7 @@ static void cnic_ctx_tbl_wr(struct cnic_dev *dev, u32 off, dma_addr_t addr)
|
|||
struct drv_ctl_info info;
|
||||
struct drv_ctl_io *io = &info.data.io;
|
||||
|
||||
memset(&info, 0, sizeof(struct drv_ctl_info));
|
||||
info.cmd = DRV_CTL_CTXTBL_WR_CMD;
|
||||
io->offset = off;
|
||||
io->dma_addr = addr;
|
||||
|
|
@ -219,6 +221,7 @@ static void cnic_ring_ctl(struct cnic_dev *dev, u32 cid, u32 cl_id, int start)
|
|||
struct drv_ctl_info info;
|
||||
struct drv_ctl_l2_ring *ring = &info.data.ring;
|
||||
|
||||
memset(&info, 0, sizeof(struct drv_ctl_info));
|
||||
if (start)
|
||||
info.cmd = DRV_CTL_START_L2_CMD;
|
||||
else
|
||||
|
|
@ -236,6 +239,7 @@ static void cnic_reg_wr_ind(struct cnic_dev *dev, u32 off, u32 val)
|
|||
struct drv_ctl_info info;
|
||||
struct drv_ctl_io *io = &info.data.io;
|
||||
|
||||
memset(&info, 0, sizeof(struct drv_ctl_info));
|
||||
info.cmd = DRV_CTL_IO_WR_CMD;
|
||||
io->offset = off;
|
||||
io->data = val;
|
||||
|
|
@ -249,13 +253,14 @@ static u32 cnic_reg_rd_ind(struct cnic_dev *dev, u32 off)
|
|||
struct drv_ctl_info info;
|
||||
struct drv_ctl_io *io = &info.data.io;
|
||||
|
||||
memset(&info, 0, sizeof(struct drv_ctl_info));
|
||||
info.cmd = DRV_CTL_IO_RD_CMD;
|
||||
io->offset = off;
|
||||
ethdev->drv_ctl(dev->netdev, &info);
|
||||
return io->data;
|
||||
}
|
||||
|
||||
static void cnic_ulp_ctl(struct cnic_dev *dev, int ulp_type, bool reg)
|
||||
static void cnic_ulp_ctl(struct cnic_dev *dev, int ulp_type, bool reg, int state)
|
||||
{
|
||||
struct cnic_local *cp = dev->cnic_priv;
|
||||
struct cnic_eth_dev *ethdev = cp->ethdev;
|
||||
|
|
@ -263,6 +268,7 @@ static void cnic_ulp_ctl(struct cnic_dev *dev, int ulp_type, bool reg)
|
|||
struct fcoe_capabilities *fcoe_cap =
|
||||
&info.data.register_data.fcoe_features;
|
||||
|
||||
memset(&info, 0, sizeof(struct drv_ctl_info));
|
||||
if (reg) {
|
||||
info.cmd = DRV_CTL_ULP_REGISTER_CMD;
|
||||
if (ulp_type == CNIC_ULP_FCOE && dev->fcoe_cap)
|
||||
|
|
@ -272,6 +278,7 @@ static void cnic_ulp_ctl(struct cnic_dev *dev, int ulp_type, bool reg)
|
|||
}
|
||||
|
||||
info.data.ulp_type = ulp_type;
|
||||
info.drv_state = state;
|
||||
ethdev->drv_ctl(dev->netdev, &info);
|
||||
}
|
||||
|
||||
|
|
@ -286,6 +293,7 @@ static void cnic_spq_completion(struct cnic_dev *dev, int cmd, u32 count)
|
|||
struct cnic_eth_dev *ethdev = cp->ethdev;
|
||||
struct drv_ctl_info info;
|
||||
|
||||
memset(&info, 0, sizeof(struct drv_ctl_info));
|
||||
info.cmd = cmd;
|
||||
info.data.credit.credit_count = count;
|
||||
ethdev->drv_ctl(dev->netdev, &info);
|
||||
|
|
@ -591,7 +599,7 @@ static int cnic_register_device(struct cnic_dev *dev, int ulp_type,
|
|||
|
||||
mutex_unlock(&cnic_lock);
|
||||
|
||||
cnic_ulp_ctl(dev, ulp_type, true);
|
||||
cnic_ulp_ctl(dev, ulp_type, true, DRV_ACTIVE);
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
@ -636,7 +644,10 @@ static int cnic_unregister_device(struct cnic_dev *dev, int ulp_type)
|
|||
if (test_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[ulp_type]))
|
||||
netdev_warn(dev->netdev, "Failed waiting for ULP up call to complete\n");
|
||||
|
||||
cnic_ulp_ctl(dev, ulp_type, false);
|
||||
if (test_bit(ULP_F_INIT, &cp->ulp_flags[ulp_type]))
|
||||
cnic_ulp_ctl(dev, ulp_type, false, DRV_UNLOADED);
|
||||
else
|
||||
cnic_ulp_ctl(dev, ulp_type, false, DRV_INACTIVE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -4267,6 +4278,7 @@ static void cnic_delete_task(struct work_struct *work)
|
|||
|
||||
cnic_ulp_stop_one(cp, CNIC_ULP_ISCSI);
|
||||
|
||||
memset(&info, 0, sizeof(struct drv_ctl_info));
|
||||
info.cmd = DRV_CTL_ISCSI_STOPPED_CMD;
|
||||
cp->ethdev->drv_ctl(dev->netdev, &info);
|
||||
}
|
||||
|
|
@ -5433,6 +5445,23 @@ static void cnic_free_dev(struct cnic_dev *dev)
|
|||
kfree(dev);
|
||||
}
|
||||
|
||||
static int cnic_get_fc_npiv_tbl(struct cnic_dev *dev,
|
||||
struct cnic_fc_npiv_tbl *npiv_tbl)
|
||||
{
|
||||
struct cnic_local *cp = dev->cnic_priv;
|
||||
struct bnx2x *bp = netdev_priv(dev->netdev);
|
||||
int ret;
|
||||
|
||||
if (!test_bit(CNIC_F_CNIC_UP, &dev->flags))
|
||||
return -EAGAIN; /* bnx2x is down */
|
||||
|
||||
if (!BNX2X_CHIP_IS_E2_PLUS(bp))
|
||||
return -EINVAL;
|
||||
|
||||
ret = cp->ethdev->drv_get_fc_npiv_tbl(dev->netdev, npiv_tbl);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct cnic_dev *cnic_alloc_dev(struct net_device *dev,
|
||||
struct pci_dev *pdev)
|
||||
{
|
||||
|
|
@ -5451,6 +5480,7 @@ static struct cnic_dev *cnic_alloc_dev(struct net_device *dev,
|
|||
cdev->register_device = cnic_register_device;
|
||||
cdev->unregister_device = cnic_unregister_device;
|
||||
cdev->iscsi_nl_msg_recv = cnic_iscsi_nl_msg_recv;
|
||||
cdev->get_fc_npiv_tbl = cnic_get_fc_npiv_tbl;
|
||||
|
||||
cp = cdev->cnic_priv;
|
||||
cp->dev = cdev;
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@
|
|||
|
||||
#include "bnx2x/bnx2x_mfw_req.h"
|
||||
|
||||
#define CNIC_MODULE_VERSION "2.5.21"
|
||||
#define CNIC_MODULE_RELDATE "January 29, 2015"
|
||||
#define CNIC_MODULE_VERSION "2.5.22"
|
||||
#define CNIC_MODULE_RELDATE "July 20, 2015"
|
||||
|
||||
#define CNIC_ULP_RDMA 0
|
||||
#define CNIC_ULP_ISCSI 1
|
||||
|
|
@ -151,6 +151,11 @@ struct drv_ctl_register_data {
|
|||
|
||||
struct drv_ctl_info {
|
||||
int cmd;
|
||||
int drv_state;
|
||||
#define DRV_NOP 0
|
||||
#define DRV_ACTIVE 1
|
||||
#define DRV_INACTIVE 2
|
||||
#define DRV_UNLOADED 3
|
||||
union {
|
||||
struct drv_ctl_spq_credit credit;
|
||||
struct drv_ctl_io io;
|
||||
|
|
@ -161,6 +166,15 @@ struct drv_ctl_info {
|
|||
} data;
|
||||
};
|
||||
|
||||
#define MAX_NPIV_ENTRIES 64
|
||||
#define FC_NPIV_WWN_SIZE 8
|
||||
|
||||
struct cnic_fc_npiv_tbl {
|
||||
u8 wwpn[MAX_NPIV_ENTRIES][FC_NPIV_WWN_SIZE];
|
||||
u8 wwnn[MAX_NPIV_ENTRIES][FC_NPIV_WWN_SIZE];
|
||||
u32 count;
|
||||
};
|
||||
|
||||
struct cnic_ops {
|
||||
struct module *cnic_owner;
|
||||
/* Calls to these functions are protected by RCU. When
|
||||
|
|
@ -226,6 +240,8 @@ struct cnic_eth_dev {
|
|||
int (*drv_submit_kwqes_16)(struct net_device *,
|
||||
struct kwqe_16 *[], u32);
|
||||
int (*drv_ctl)(struct net_device *, struct drv_ctl_info *);
|
||||
int (*drv_get_fc_npiv_tbl)(struct net_device *,
|
||||
struct cnic_fc_npiv_tbl *);
|
||||
unsigned long reserved1[2];
|
||||
union drv_info_to_mcp *addr_drv_info_to_mcp;
|
||||
};
|
||||
|
|
@ -314,6 +330,7 @@ struct cnic_dev {
|
|||
struct cnic_dev *(*cm_select_dev)(struct sockaddr_in *, int ulp_type);
|
||||
int (*iscsi_nl_msg_recv)(struct cnic_dev *dev, u32 msg_type,
|
||||
char *data, u16 data_size);
|
||||
int (*get_fc_npiv_tbl)(struct cnic_dev *, struct cnic_fc_npiv_tbl *);
|
||||
unsigned long flags;
|
||||
#define CNIC_F_CNIC_UP 1
|
||||
#define CNIC_F_BNX2_CLASS 3
|
||||
|
|
|
|||
|
|
@ -907,9 +907,8 @@ static void bcmgenet_power_up(struct bcmgenet_priv *priv,
|
|||
}
|
||||
|
||||
bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
|
||||
|
||||
if (mode == GENET_POWER_PASSIVE)
|
||||
bcmgenet_mii_reset(priv->dev);
|
||||
bcmgenet_phy_power_set(priv->dev, true);
|
||||
}
|
||||
|
||||
/* ioctl handle special commands that are not present in ethtool. */
|
||||
|
|
@ -1725,7 +1724,7 @@ static int init_umac(struct bcmgenet_priv *priv)
|
|||
int0_enable |= UMAC_IRQ_TXDMA_DONE;
|
||||
|
||||
/* Monitor cable plug/unplugged event for internal PHY */
|
||||
if (phy_is_internal(priv->phydev)) {
|
||||
if (priv->internal_phy) {
|
||||
int0_enable |= UMAC_IRQ_LINK_EVENT;
|
||||
} else if (priv->ext_phy) {
|
||||
int0_enable |= UMAC_IRQ_LINK_EVENT;
|
||||
|
|
@ -2405,6 +2404,23 @@ static irqreturn_t bcmgenet_wol_isr(int irq, void *dev_id)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
static void bcmgenet_poll_controller(struct net_device *dev)
|
||||
{
|
||||
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||
|
||||
/* Invoke the main RX/TX interrupt handler */
|
||||
disable_irq(priv->irq0);
|
||||
bcmgenet_isr0(priv->irq0, priv);
|
||||
enable_irq(priv->irq0);
|
||||
|
||||
/* And the interrupt handler for RX/TX priority queues */
|
||||
disable_irq(priv->irq1);
|
||||
bcmgenet_isr1(priv->irq1, priv);
|
||||
enable_irq(priv->irq1);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void bcmgenet_umac_reset(struct bcmgenet_priv *priv)
|
||||
{
|
||||
u32 reg;
|
||||
|
|
@ -2642,13 +2658,12 @@ static int bcmgenet_open(struct net_device *dev)
|
|||
netif_dbg(priv, ifup, dev, "bcmgenet_open\n");
|
||||
|
||||
/* Turn on the clock */
|
||||
if (!IS_ERR(priv->clk))
|
||||
clk_prepare_enable(priv->clk);
|
||||
clk_prepare_enable(priv->clk);
|
||||
|
||||
/* If this is an internal GPHY, power it back on now, before UniMAC is
|
||||
* brought out of reset as absolutely no UniMAC activity is allowed
|
||||
*/
|
||||
if (phy_is_internal(priv->phydev))
|
||||
if (priv->internal_phy)
|
||||
bcmgenet_power_up(priv, GENET_POWER_PASSIVE);
|
||||
|
||||
/* take MAC out of reset */
|
||||
|
|
@ -2667,7 +2682,7 @@ static int bcmgenet_open(struct net_device *dev)
|
|||
|
||||
bcmgenet_set_hw_addr(priv, dev->dev_addr);
|
||||
|
||||
if (phy_is_internal(priv->phydev)) {
|
||||
if (priv->internal_phy) {
|
||||
reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
|
||||
reg |= EXT_ENERGY_DET_MASK;
|
||||
bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
|
||||
|
|
@ -2703,23 +2718,24 @@ static int bcmgenet_open(struct net_device *dev)
|
|||
goto err_irq0;
|
||||
}
|
||||
|
||||
/* Re-configure the port multiplexer towards the PHY device */
|
||||
bcmgenet_mii_config(priv->dev, false);
|
||||
|
||||
phy_connect_direct(dev, priv->phydev, bcmgenet_mii_setup,
|
||||
priv->phy_interface);
|
||||
ret = bcmgenet_mii_probe(dev);
|
||||
if (ret) {
|
||||
netdev_err(dev, "failed to connect to PHY\n");
|
||||
goto err_irq1;
|
||||
}
|
||||
|
||||
bcmgenet_netif_start(dev);
|
||||
|
||||
return 0;
|
||||
|
||||
err_irq1:
|
||||
free_irq(priv->irq1, priv);
|
||||
err_irq0:
|
||||
free_irq(priv->irq0, dev);
|
||||
free_irq(priv->irq0, priv);
|
||||
err_fini_dma:
|
||||
bcmgenet_fini_dma(priv);
|
||||
err_clk_disable:
|
||||
if (!IS_ERR(priv->clk))
|
||||
clk_disable_unprepare(priv->clk);
|
||||
clk_disable_unprepare(priv->clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -2773,11 +2789,10 @@ static int bcmgenet_close(struct net_device *dev)
|
|||
free_irq(priv->irq0, priv);
|
||||
free_irq(priv->irq1, priv);
|
||||
|
||||
if (phy_is_internal(priv->phydev))
|
||||
if (priv->internal_phy)
|
||||
ret = bcmgenet_power_down(priv, GENET_POWER_PASSIVE);
|
||||
|
||||
if (!IS_ERR(priv->clk))
|
||||
clk_disable_unprepare(priv->clk);
|
||||
clk_disable_unprepare(priv->clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -2953,6 +2968,9 @@ static const struct net_device_ops bcmgenet_netdev_ops = {
|
|||
.ndo_set_mac_address = bcmgenet_set_mac_addr,
|
||||
.ndo_do_ioctl = bcmgenet_ioctl,
|
||||
.ndo_set_features = bcmgenet_set_features,
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
.ndo_poll_controller = bcmgenet_poll_controller,
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Array of GENET hardware parameters/characteristics */
|
||||
|
|
@ -3226,11 +3244,12 @@ static int bcmgenet_probe(struct platform_device *pdev)
|
|||
priv->version = pd->genet_version;
|
||||
|
||||
priv->clk = devm_clk_get(&priv->pdev->dev, "enet");
|
||||
if (IS_ERR(priv->clk))
|
||||
if (IS_ERR(priv->clk)) {
|
||||
dev_warn(&priv->pdev->dev, "failed to get enet clock\n");
|
||||
priv->clk = NULL;
|
||||
}
|
||||
|
||||
if (!IS_ERR(priv->clk))
|
||||
clk_prepare_enable(priv->clk);
|
||||
clk_prepare_enable(priv->clk);
|
||||
|
||||
bcmgenet_set_hw_params(priv);
|
||||
|
||||
|
|
@ -3241,8 +3260,10 @@ static int bcmgenet_probe(struct platform_device *pdev)
|
|||
INIT_WORK(&priv->bcmgenet_irq_work, bcmgenet_irq_task);
|
||||
|
||||
priv->clk_wol = devm_clk_get(&priv->pdev->dev, "enet-wol");
|
||||
if (IS_ERR(priv->clk_wol))
|
||||
if (IS_ERR(priv->clk_wol)) {
|
||||
dev_warn(&priv->pdev->dev, "failed to get enet-wol clock\n");
|
||||
priv->clk_wol = NULL;
|
||||
}
|
||||
|
||||
priv->clk_eee = devm_clk_get(&priv->pdev->dev, "enet-eee");
|
||||
if (IS_ERR(priv->clk_eee)) {
|
||||
|
|
@ -3268,8 +3289,7 @@ static int bcmgenet_probe(struct platform_device *pdev)
|
|||
netif_carrier_off(dev);
|
||||
|
||||
/* Turn off the main clock, WOL clock is handled separately */
|
||||
if (!IS_ERR(priv->clk))
|
||||
clk_disable_unprepare(priv->clk);
|
||||
clk_disable_unprepare(priv->clk);
|
||||
|
||||
err = register_netdev(dev);
|
||||
if (err)
|
||||
|
|
@ -3278,8 +3298,7 @@ static int bcmgenet_probe(struct platform_device *pdev)
|
|||
return err;
|
||||
|
||||
err_clk_disable:
|
||||
if (!IS_ERR(priv->clk))
|
||||
clk_disable_unprepare(priv->clk);
|
||||
clk_disable_unprepare(priv->clk);
|
||||
err:
|
||||
free_netdev(dev);
|
||||
return err;
|
||||
|
|
@ -3331,7 +3350,7 @@ static int bcmgenet_suspend(struct device *d)
|
|||
if (device_may_wakeup(d) && priv->wolopts) {
|
||||
ret = bcmgenet_power_down(priv, GENET_POWER_WOL_MAGIC);
|
||||
clk_prepare_enable(priv->clk_wol);
|
||||
} else if (phy_is_internal(priv->phydev)) {
|
||||
} else if (priv->internal_phy) {
|
||||
ret = bcmgenet_power_down(priv, GENET_POWER_PASSIVE);
|
||||
}
|
||||
|
||||
|
|
@ -3360,7 +3379,7 @@ static int bcmgenet_resume(struct device *d)
|
|||
/* If this is an internal GPHY, power it back on now, before UniMAC is
|
||||
* brought out of reset as absolutely no UniMAC activity is allowed
|
||||
*/
|
||||
if (phy_is_internal(priv->phydev))
|
||||
if (priv->internal_phy)
|
||||
bcmgenet_power_up(priv, GENET_POWER_PASSIVE);
|
||||
|
||||
bcmgenet_umac_reset(priv);
|
||||
|
|
@ -3375,14 +3394,14 @@ static int bcmgenet_resume(struct device *d)
|
|||
|
||||
phy_init_hw(priv->phydev);
|
||||
/* Speed settings must be restored */
|
||||
bcmgenet_mii_config(priv->dev, false);
|
||||
bcmgenet_mii_config(priv->dev);
|
||||
|
||||
/* disable ethernet MAC while updating its registers */
|
||||
umac_enable_set(priv, CMD_TX_EN | CMD_RX_EN, false);
|
||||
|
||||
bcmgenet_set_hw_addr(priv, dev->dev_addr);
|
||||
|
||||
if (phy_is_internal(priv->phydev)) {
|
||||
if (priv->internal_phy) {
|
||||
reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
|
||||
reg |= EXT_ENERGY_DET_MASK;
|
||||
bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
|
||||
|
|
|
|||
|
|
@ -593,6 +593,7 @@ struct bcmgenet_priv {
|
|||
/* MDIO bus variables */
|
||||
wait_queue_head_t wq;
|
||||
struct phy_device *phydev;
|
||||
bool internal_phy;
|
||||
struct device_node *phy_dn;
|
||||
struct device_node *mdio_dn;
|
||||
struct mii_bus *mii_bus;
|
||||
|
|
@ -670,9 +671,9 @@ GENET_IO_MACRO(rbuf, GENET_RBUF_OFF);
|
|||
|
||||
/* MDIO routines */
|
||||
int bcmgenet_mii_init(struct net_device *dev);
|
||||
int bcmgenet_mii_config(struct net_device *dev, bool init);
|
||||
int bcmgenet_mii_config(struct net_device *dev);
|
||||
int bcmgenet_mii_probe(struct net_device *dev);
|
||||
void bcmgenet_mii_exit(struct net_device *dev);
|
||||
void bcmgenet_mii_reset(struct net_device *dev);
|
||||
void bcmgenet_phy_power_set(struct net_device *dev, bool enable);
|
||||
void bcmgenet_mii_setup(struct net_device *dev);
|
||||
|
||||
|
|
|
|||
|
|
@ -163,14 +163,13 @@ void bcmgenet_mii_setup(struct net_device *dev)
|
|||
phy_print_status(phydev);
|
||||
}
|
||||
|
||||
void bcmgenet_mii_reset(struct net_device *dev)
|
||||
static int bcmgenet_fixed_phy_link_update(struct net_device *dev,
|
||||
struct fixed_phy_status *status)
|
||||
{
|
||||
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||
if (dev && dev->phydev && status)
|
||||
status->link = dev->phydev->link;
|
||||
|
||||
if (priv->phydev) {
|
||||
phy_init_hw(priv->phydev);
|
||||
phy_start_aneg(priv->phydev);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bcmgenet_phy_power_set(struct net_device *dev, bool enable)
|
||||
|
|
@ -215,7 +214,6 @@ static void bcmgenet_internal_phy_setup(struct net_device *dev)
|
|||
reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
|
||||
reg |= EXT_PWR_DN_EN_LD;
|
||||
bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
|
||||
bcmgenet_mii_reset(dev);
|
||||
}
|
||||
|
||||
static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv)
|
||||
|
|
@ -226,9 +224,13 @@ static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv)
|
|||
reg = bcmgenet_sys_readl(priv, SYS_PORT_CTRL);
|
||||
reg |= LED_ACT_SOURCE_MAC;
|
||||
bcmgenet_sys_writel(priv, reg, SYS_PORT_CTRL);
|
||||
|
||||
if (priv->hw_params->flags & GENET_HAS_MOCA_LINK_DET)
|
||||
fixed_phy_set_link_update(priv->phydev,
|
||||
bcmgenet_fixed_phy_link_update);
|
||||
}
|
||||
|
||||
int bcmgenet_mii_config(struct net_device *dev, bool init)
|
||||
int bcmgenet_mii_config(struct net_device *dev)
|
||||
{
|
||||
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||
struct phy_device *phydev = priv->phydev;
|
||||
|
|
@ -238,10 +240,10 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
|
|||
u32 port_ctrl;
|
||||
u32 reg;
|
||||
|
||||
priv->ext_phy = !phy_is_internal(priv->phydev) &&
|
||||
priv->ext_phy = !priv->internal_phy &&
|
||||
(priv->phy_interface != PHY_INTERFACE_MODE_MOCA);
|
||||
|
||||
if (phy_is_internal(priv->phydev))
|
||||
if (priv->internal_phy)
|
||||
priv->phy_interface = PHY_INTERFACE_MODE_NA;
|
||||
|
||||
switch (priv->phy_interface) {
|
||||
|
|
@ -259,7 +261,7 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
|
|||
|
||||
bcmgenet_sys_writel(priv, port_ctrl, SYS_PORT_CTRL);
|
||||
|
||||
if (phy_is_internal(priv->phydev)) {
|
||||
if (priv->internal_phy) {
|
||||
phy_name = "internal PHY";
|
||||
bcmgenet_internal_phy_setup(dev);
|
||||
} else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
|
||||
|
|
@ -321,13 +323,12 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
|
|||
bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL);
|
||||
}
|
||||
|
||||
if (init)
|
||||
dev_info(kdev, "configuring instance for %s\n", phy_name);
|
||||
dev_info_once(kdev, "configuring instance for %s\n", phy_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcmgenet_mii_probe(struct net_device *dev)
|
||||
int bcmgenet_mii_probe(struct net_device *dev)
|
||||
{
|
||||
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||
struct device_node *dn = priv->pdev->dev.of_node;
|
||||
|
|
@ -345,22 +346,6 @@ static int bcmgenet_mii_probe(struct net_device *dev)
|
|||
priv->old_pause = -1;
|
||||
|
||||
if (dn) {
|
||||
if (priv->phydev) {
|
||||
pr_info("PHY already attached\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* In the case of a fixed PHY, the DT node associated
|
||||
* to the PHY is the Ethernet MAC DT node.
|
||||
*/
|
||||
if (!priv->phy_dn && of_phy_is_fixed_link(dn)) {
|
||||
ret = of_phy_register_fixed_link(dn);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->phy_dn = of_node_get(dn);
|
||||
}
|
||||
|
||||
phydev = of_phy_connect(dev, priv->phy_dn, bcmgenet_mii_setup,
|
||||
phy_flags, priv->phy_interface);
|
||||
if (!phydev) {
|
||||
|
|
@ -386,7 +371,7 @@ static int bcmgenet_mii_probe(struct net_device *dev)
|
|||
* PHY speed which is needed for bcmgenet_mii_config() to configure
|
||||
* things appropriately.
|
||||
*/
|
||||
ret = bcmgenet_mii_config(dev, true);
|
||||
ret = bcmgenet_mii_config(dev);
|
||||
if (ret) {
|
||||
phy_disconnect(priv->phydev);
|
||||
return ret;
|
||||
|
|
@ -397,14 +382,11 @@ static int bcmgenet_mii_probe(struct net_device *dev)
|
|||
/* The internal PHY has its link interrupts routed to the
|
||||
* Ethernet MAC ISRs
|
||||
*/
|
||||
if (phy_is_internal(priv->phydev))
|
||||
if (priv->internal_phy)
|
||||
priv->mii_bus->irq[phydev->addr] = PHY_IGNORE_INTERRUPT;
|
||||
else
|
||||
priv->mii_bus->irq[phydev->addr] = PHY_POLL;
|
||||
|
||||
pr_info("attached PHY at address %d [%s]\n",
|
||||
phydev->addr, phydev->drv->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -490,7 +472,10 @@ static int bcmgenet_mii_of_init(struct bcmgenet_priv *priv)
|
|||
{
|
||||
struct device_node *dn = priv->pdev->dev.of_node;
|
||||
struct device *kdev = &priv->pdev->dev;
|
||||
const char *phy_mode_str = NULL;
|
||||
struct phy_device *phydev = NULL;
|
||||
char *compat;
|
||||
int phy_mode;
|
||||
int ret;
|
||||
|
||||
compat = kasprintf(GFP_KERNEL, "brcm,genet-mdio-v%d", priv->version);
|
||||
|
|
@ -513,17 +498,43 @@ static int bcmgenet_mii_of_init(struct bcmgenet_priv *priv)
|
|||
/* Fetch the PHY phandle */
|
||||
priv->phy_dn = of_parse_phandle(dn, "phy-handle", 0);
|
||||
|
||||
/* In the case of a fixed PHY, the DT node associated
|
||||
* to the PHY is the Ethernet MAC DT node.
|
||||
*/
|
||||
if (!priv->phy_dn && of_phy_is_fixed_link(dn)) {
|
||||
ret = of_phy_register_fixed_link(dn);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->phy_dn = of_node_get(dn);
|
||||
}
|
||||
|
||||
/* Get the link mode */
|
||||
priv->phy_interface = of_get_phy_mode(dn);
|
||||
phy_mode = of_get_phy_mode(dn);
|
||||
priv->phy_interface = phy_mode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* We need to specifically look up whether this PHY interface is internal
|
||||
* or not *before* we even try to probe the PHY driver over MDIO as we
|
||||
* may have shut down the internal PHY for power saving purposes.
|
||||
*/
|
||||
if (phy_mode < 0) {
|
||||
ret = of_property_read_string(dn, "phy-mode", &phy_mode_str);
|
||||
if (ret < 0) {
|
||||
dev_err(kdev, "invalid PHY mode property\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bcmgenet_fixed_phy_link_update(struct net_device *dev,
|
||||
struct fixed_phy_status *status)
|
||||
{
|
||||
if (dev && dev->phydev && status)
|
||||
status->link = dev->phydev->link;
|
||||
priv->phy_interface = PHY_INTERFACE_MODE_NA;
|
||||
if (!strcasecmp(phy_mode_str, "internal"))
|
||||
priv->internal_phy = true;
|
||||
}
|
||||
|
||||
/* Make sure we initialize MoCA PHYs with a link down */
|
||||
if (phy_mode == PHY_INTERFACE_MODE_MOCA) {
|
||||
phydev = of_phy_find_device(dn);
|
||||
if (phydev)
|
||||
phydev->link = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -574,18 +585,15 @@ static int bcmgenet_mii_pd_init(struct bcmgenet_priv *priv)
|
|||
.asym_pause = 0,
|
||||
};
|
||||
|
||||
phydev = fixed_phy_register(PHY_POLL, &fphy_status, NULL);
|
||||
phydev = fixed_phy_register(PHY_POLL, &fphy_status, -1, NULL);
|
||||
if (!phydev || IS_ERR(phydev)) {
|
||||
dev_err(kdev, "failed to register fixed PHY device\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (priv->hw_params->flags & GENET_HAS_MOCA_LINK_DET) {
|
||||
ret = fixed_phy_set_link_update(
|
||||
phydev, bcmgenet_fixed_phy_link_update);
|
||||
if (!ret)
|
||||
phydev->link = 0;
|
||||
}
|
||||
/* Make sure we initialize MoCA PHYs with a link down */
|
||||
phydev->link = 0;
|
||||
|
||||
}
|
||||
|
||||
priv->phydev = phydev;
|
||||
|
|
@ -614,10 +622,6 @@ int bcmgenet_mii_init(struct net_device *dev)
|
|||
return ret;
|
||||
|
||||
ret = bcmgenet_mii_bus_init(priv);
|
||||
if (ret)
|
||||
goto out_free;
|
||||
|
||||
ret = bcmgenet_mii_probe(dev);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
|
|
@ -626,7 +630,6 @@ int bcmgenet_mii_init(struct net_device *dev)
|
|||
out:
|
||||
of_node_put(priv->phy_dn);
|
||||
mdiobus_unregister(priv->mii_bus);
|
||||
out_free:
|
||||
kfree(priv->mii_bus->irq);
|
||||
mdiobus_free(priv->mii_bus);
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -10757,7 +10757,7 @@ static ssize_t tg3_show_temp(struct device *dev,
|
|||
tg3_ape_scratchpad_read(tp, &temperature, attr->index,
|
||||
sizeof(temperature));
|
||||
spin_unlock_bh(&tp->lock);
|
||||
return sprintf(buf, "%u\n", temperature);
|
||||
return sprintf(buf, "%u\n", temperature * 1000);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2774,8 +2774,7 @@ static const struct macb_config emac_config = {
|
|||
|
||||
|
||||
static const struct macb_config zynqmp_config = {
|
||||
.caps = MACB_CAPS_SG_DISABLED | MACB_CAPS_GIGABIT_MODE_AVAILABLE |
|
||||
MACB_CAPS_JUMBO,
|
||||
.caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_JUMBO,
|
||||
.dma_burst_length = 16,
|
||||
.clk_init = macb_clk_init,
|
||||
.init = macb_init,
|
||||
|
|
@ -2783,8 +2782,7 @@ static const struct macb_config zynqmp_config = {
|
|||
};
|
||||
|
||||
static const struct macb_config zynq_config = {
|
||||
.caps = MACB_CAPS_SG_DISABLED | MACB_CAPS_GIGABIT_MODE_AVAILABLE |
|
||||
MACB_CAPS_NO_GIGABIT_HALF,
|
||||
.caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_NO_GIGABIT_HALF,
|
||||
.dma_burst_length = 16,
|
||||
.clk_init = macb_clk_init,
|
||||
.init = macb_init,
|
||||
|
|
|
|||
|
|
@ -399,7 +399,7 @@
|
|||
#define MACB_CAPS_GIGABIT_MODE_AVAILABLE 0x20000000
|
||||
#define MACB_CAPS_SG_DISABLED 0x40000000
|
||||
#define MACB_CAPS_MACB_IS_GEM 0x80000000
|
||||
#define MACB_CAPS_JUMBO 0x00000008
|
||||
#define MACB_CAPS_JUMBO 0x00000010
|
||||
|
||||
/* Bit manipulation macros */
|
||||
#define MACB_BIT(name) \
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@ config THUNDER_NIC_VF
|
|||
config THUNDER_NIC_BGX
|
||||
tristate "Thunder MAC interface driver (BGX)"
|
||||
depends on 64BIT
|
||||
select PHYLIB
|
||||
select MDIO_OCTEON
|
||||
---help---
|
||||
This driver supports programming and controlling of MAC
|
||||
interface from NIC physical function driver.
|
||||
|
|
|
|||
|
|
@ -135,6 +135,7 @@
|
|||
#define NICVF_TX_TIMEOUT (50 * HZ)
|
||||
|
||||
struct nicvf_cq_poll {
|
||||
struct nicvf *nicvf;
|
||||
u8 cq_idx; /* Completion queue index */
|
||||
struct napi_struct napi;
|
||||
};
|
||||
|
|
@ -190,10 +191,10 @@ enum tx_stats_reg_offset {
|
|||
};
|
||||
|
||||
struct nicvf_hw_stats {
|
||||
u64 rx_bytes_ok;
|
||||
u64 rx_ucast_frames_ok;
|
||||
u64 rx_bcast_frames_ok;
|
||||
u64 rx_mcast_frames_ok;
|
||||
u64 rx_bytes;
|
||||
u64 rx_ucast_frames;
|
||||
u64 rx_bcast_frames;
|
||||
u64 rx_mcast_frames;
|
||||
u64 rx_fcs_errors;
|
||||
u64 rx_l2_errors;
|
||||
u64 rx_drop_red;
|
||||
|
|
@ -204,6 +205,31 @@ struct nicvf_hw_stats {
|
|||
u64 rx_drop_mcast;
|
||||
u64 rx_drop_l3_bcast;
|
||||
u64 rx_drop_l3_mcast;
|
||||
u64 rx_bgx_truncated_pkts;
|
||||
u64 rx_jabber_errs;
|
||||
u64 rx_fcs_errs;
|
||||
u64 rx_bgx_errs;
|
||||
u64 rx_prel2_errs;
|
||||
u64 rx_l2_hdr_malformed;
|
||||
u64 rx_oversize;
|
||||
u64 rx_undersize;
|
||||
u64 rx_l2_len_mismatch;
|
||||
u64 rx_l2_pclp;
|
||||
u64 rx_ip_ver_errs;
|
||||
u64 rx_ip_csum_errs;
|
||||
u64 rx_ip_hdr_malformed;
|
||||
u64 rx_ip_payload_malformed;
|
||||
u64 rx_ip_ttl_errs;
|
||||
u64 rx_l3_pclp;
|
||||
u64 rx_l4_malformed;
|
||||
u64 rx_l4_csum_errs;
|
||||
u64 rx_udp_len_errs;
|
||||
u64 rx_l4_port_errs;
|
||||
u64 rx_tcp_flag_errs;
|
||||
u64 rx_tcp_offset_errs;
|
||||
u64 rx_l4_pclp;
|
||||
u64 rx_truncated_pkts;
|
||||
|
||||
u64 tx_bytes_ok;
|
||||
u64 tx_ucast_frames_ok;
|
||||
u64 tx_bcast_frames_ok;
|
||||
|
|
@ -222,6 +248,7 @@ struct nicvf_drv_stats {
|
|||
u64 rx_frames_1518;
|
||||
u64 rx_frames_jumbo;
|
||||
u64 rx_drops;
|
||||
|
||||
/* Tx */
|
||||
u64 tx_frames_ok;
|
||||
u64 tx_drops;
|
||||
|
|
@ -231,13 +258,24 @@ struct nicvf_drv_stats {
|
|||
};
|
||||
|
||||
struct nicvf {
|
||||
struct nicvf *pnicvf;
|
||||
struct net_device *netdev;
|
||||
struct pci_dev *pdev;
|
||||
u8 vf_id;
|
||||
u8 node;
|
||||
u8 tns_mode;
|
||||
u8 tns_mode:1;
|
||||
u8 sqs_mode:1;
|
||||
u8 loopback_supported:1;
|
||||
u16 mtu;
|
||||
struct queue_set *qs;
|
||||
#define MAX_SQS_PER_VF_SINGLE_NODE 5
|
||||
#define MAX_SQS_PER_VF 11
|
||||
u8 sqs_id;
|
||||
u8 sqs_count; /* Secondary Qset count */
|
||||
struct nicvf *snicvf[MAX_SQS_PER_VF];
|
||||
u8 rx_queues;
|
||||
u8 tx_queues;
|
||||
u8 max_queues;
|
||||
void __iomem *reg_base;
|
||||
bool link_up;
|
||||
u8 duplex;
|
||||
|
|
@ -257,7 +295,7 @@ struct nicvf {
|
|||
u32 cq_coalesce_usecs;
|
||||
|
||||
u32 msg_enable;
|
||||
struct nicvf_hw_stats stats;
|
||||
struct nicvf_hw_stats hw_stats;
|
||||
struct nicvf_drv_stats drv_stats;
|
||||
struct bgx_stats bgx_stats;
|
||||
struct work_struct reset_task;
|
||||
|
|
@ -269,10 +307,9 @@ struct nicvf {
|
|||
char irq_name[NIC_VF_MSIX_VECTORS][20];
|
||||
bool irq_allocated[NIC_VF_MSIX_VECTORS];
|
||||
|
||||
bool pf_ready_to_rcv_msg;
|
||||
/* VF <-> PF mailbox communication */
|
||||
bool pf_acked;
|
||||
bool pf_nacked;
|
||||
bool bgx_stats_acked;
|
||||
bool set_mac_pending;
|
||||
} ____cacheline_aligned_in_smp;
|
||||
|
||||
|
|
@ -304,14 +341,21 @@ struct nicvf {
|
|||
#define NIC_MBOX_MSG_RQ_SW_SYNC 0x0F /* Flush inflight pkts to RQ */
|
||||
#define NIC_MBOX_MSG_BGX_STATS 0x10 /* Get stats from BGX */
|
||||
#define NIC_MBOX_MSG_BGX_LINK_CHANGE 0x11 /* BGX:LMAC link status */
|
||||
#define NIC_MBOX_MSG_CFG_DONE 0x12 /* VF configuration done */
|
||||
#define NIC_MBOX_MSG_SHUTDOWN 0x13 /* VF is being shutdown */
|
||||
#define NIC_MBOX_MSG_ALLOC_SQS 0x12 /* Allocate secondary Qset */
|
||||
#define NIC_MBOX_MSG_NICVF_PTR 0x13 /* Send nicvf ptr to PF */
|
||||
#define NIC_MBOX_MSG_PNICVF_PTR 0x14 /* Get primary qset nicvf ptr */
|
||||
#define NIC_MBOX_MSG_SNICVF_PTR 0x15 /* Send sqet nicvf ptr to PVF */
|
||||
#define NIC_MBOX_MSG_LOOPBACK 0x16 /* Set interface in loopback */
|
||||
#define NIC_MBOX_MSG_CFG_DONE 0xF0 /* VF configuration done */
|
||||
#define NIC_MBOX_MSG_SHUTDOWN 0xF1 /* VF is being shutdown */
|
||||
|
||||
struct nic_cfg_msg {
|
||||
u8 msg;
|
||||
u8 vf_id;
|
||||
u8 tns_mode;
|
||||
u8 node_id;
|
||||
u8 tns_mode:1;
|
||||
u8 sqs_mode:1;
|
||||
u8 loopback_supported:1;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
};
|
||||
|
||||
|
|
@ -319,6 +363,7 @@ struct nic_cfg_msg {
|
|||
struct qs_cfg_msg {
|
||||
u8 msg;
|
||||
u8 num;
|
||||
u8 sqs_count;
|
||||
u64 cfg;
|
||||
};
|
||||
|
||||
|
|
@ -335,6 +380,7 @@ struct sq_cfg_msg {
|
|||
u8 msg;
|
||||
u8 qs_num;
|
||||
u8 sq_num;
|
||||
bool sqs_mode;
|
||||
u64 cfg;
|
||||
};
|
||||
|
||||
|
|
@ -394,6 +440,28 @@ struct bgx_link_status {
|
|||
u32 speed;
|
||||
};
|
||||
|
||||
/* Get Extra Qset IDs */
|
||||
struct sqs_alloc {
|
||||
u8 msg;
|
||||
u8 vf_id;
|
||||
u8 qs_count;
|
||||
};
|
||||
|
||||
struct nicvf_ptr {
|
||||
u8 msg;
|
||||
u8 vf_id;
|
||||
bool sqs_mode;
|
||||
u8 sqs_id;
|
||||
u64 nicvf;
|
||||
};
|
||||
|
||||
/* Set interface in loopback mode */
|
||||
struct set_loopback {
|
||||
u8 msg;
|
||||
u8 vf_id;
|
||||
bool enable;
|
||||
};
|
||||
|
||||
/* 128 bit shared memory between PF and each VF */
|
||||
union nic_mbx {
|
||||
struct { u8 msg; } msg;
|
||||
|
|
@ -408,6 +476,9 @@ union nic_mbx {
|
|||
struct rss_cfg_msg rss_cfg;
|
||||
struct bgx_stats_msg bgx_stats;
|
||||
struct bgx_link_status link_status;
|
||||
struct sqs_alloc sqs_alloc;
|
||||
struct nicvf_ptr nicvf;
|
||||
struct set_loopback lbk;
|
||||
};
|
||||
|
||||
#define NIC_NODE_ID_MASK 0x03
|
||||
|
|
|
|||
|
|
@ -28,6 +28,11 @@ struct nicpf {
|
|||
u8 num_vf_en; /* No of VF enabled */
|
||||
bool vf_enabled[MAX_NUM_VFS_SUPPORTED];
|
||||
void __iomem *reg_base; /* Register start address */
|
||||
u8 num_sqs_en; /* Secondary qsets enabled */
|
||||
u64 nicvf[MAX_NUM_VFS_SUPPORTED];
|
||||
u8 vf_sqs[MAX_NUM_VFS_SUPPORTED][MAX_SQS_PER_VF];
|
||||
u8 pqs_vf[MAX_NUM_VFS_SUPPORTED];
|
||||
bool sqs_used[MAX_NUM_VFS_SUPPORTED];
|
||||
struct pkind_cfg pkind;
|
||||
#define NIC_SET_VF_LMAC_MAP(bgx, lmac) (((bgx & 0xF) << 4) | (lmac & 0xF))
|
||||
#define NIC_GET_BGX_FROM_VF_LMAC_MAP(map) ((map >> 4) & 0xF)
|
||||
|
|
@ -139,14 +144,19 @@ static void nic_mbx_send_ready(struct nicpf *nic, int vf)
|
|||
|
||||
mbx.nic_cfg.tns_mode = NIC_TNS_BYPASS_MODE;
|
||||
|
||||
bgx_idx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
|
||||
lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
|
||||
|
||||
mac = bgx_get_lmac_mac(nic->node, bgx_idx, lmac);
|
||||
if (mac)
|
||||
ether_addr_copy((u8 *)&mbx.nic_cfg.mac_addr, mac);
|
||||
if (vf < MAX_LMAC) {
|
||||
bgx_idx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
|
||||
lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
|
||||
|
||||
mac = bgx_get_lmac_mac(nic->node, bgx_idx, lmac);
|
||||
if (mac)
|
||||
ether_addr_copy((u8 *)&mbx.nic_cfg.mac_addr, mac);
|
||||
}
|
||||
mbx.nic_cfg.sqs_mode = (vf >= nic->num_vf_en) ? true : false;
|
||||
mbx.nic_cfg.node_id = nic->node;
|
||||
|
||||
mbx.nic_cfg.loopback_supported = vf < MAX_LMAC;
|
||||
|
||||
nic_send_msg_to_vf(nic, vf, &mbx);
|
||||
}
|
||||
|
||||
|
|
@ -329,6 +339,10 @@ static void nic_init_hw(struct nicpf *nic)
|
|||
|
||||
/* Timer config */
|
||||
nic_reg_write(nic, NIC_PF_INTR_TIMER_CFG, NICPF_CLK_PER_INT_TICK);
|
||||
|
||||
/* Enable VLAN ethertype matching and stripping */
|
||||
nic_reg_write(nic, NIC_PF_RX_ETYPE_0_7,
|
||||
(2 << 19) | (ETYPE_ALG_VLAN_STRIP << 16) | ETH_P_8021Q);
|
||||
}
|
||||
|
||||
/* Channel parse index configuration */
|
||||
|
|
@ -429,6 +443,12 @@ static void nic_config_rss(struct nicpf *nic, struct rss_cfg_msg *cfg)
|
|||
qset = cfg->vf_id;
|
||||
|
||||
for (; rssi < (rssi_base + cfg->tbl_len); rssi++) {
|
||||
u8 svf = cfg->ind_tbl[idx] >> 3;
|
||||
|
||||
if (svf)
|
||||
qset = nic->vf_sqs[cfg->vf_id][svf - 1];
|
||||
else
|
||||
qset = cfg->vf_id;
|
||||
nic_reg_write(nic, NIC_PF_RSSI_0_4097_RQ | (rssi << 3),
|
||||
(qset << 3) | (cfg->ind_tbl[idx] & 0x7));
|
||||
idx++;
|
||||
|
|
@ -452,19 +472,31 @@ static void nic_config_rss(struct nicpf *nic, struct rss_cfg_msg *cfg)
|
|||
* VNIC6-SQ0 -> TL4(528) -> TL3[132] -> TL2[33] -> TL1[1] -> BGX1
|
||||
* VNIC7-SQ0 -> TL4(536) -> TL3[134] -> TL2[33] -> TL1[1] -> BGX1
|
||||
*/
|
||||
static void nic_tx_channel_cfg(struct nicpf *nic, u8 vnic, u8 sq_idx)
|
||||
static void nic_tx_channel_cfg(struct nicpf *nic, u8 vnic,
|
||||
struct sq_cfg_msg *sq)
|
||||
{
|
||||
u32 bgx, lmac, chan;
|
||||
u32 tl2, tl3, tl4;
|
||||
u32 rr_quantum;
|
||||
u8 sq_idx = sq->sq_num;
|
||||
u8 pqs_vnic;
|
||||
|
||||
if (sq->sqs_mode)
|
||||
pqs_vnic = nic->pqs_vf[vnic];
|
||||
else
|
||||
pqs_vnic = vnic;
|
||||
|
||||
bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[pqs_vnic]);
|
||||
lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[pqs_vnic]);
|
||||
|
||||
bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vnic]);
|
||||
lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vnic]);
|
||||
/* 24 bytes for FCS, IPG and preamble */
|
||||
rr_quantum = ((NIC_HW_MAX_FRS + 24) / 4);
|
||||
|
||||
tl4 = (lmac * NIC_TL4_PER_LMAC) + (bgx * NIC_TL4_PER_BGX);
|
||||
tl4 += sq_idx;
|
||||
if (sq->sqs_mode)
|
||||
tl4 += vnic * 8;
|
||||
|
||||
tl3 = tl4 / (NIC_MAX_TL4 / NIC_MAX_TL3);
|
||||
nic_reg_write(nic, NIC_PF_QSET_0_127_SQ_0_7_CFG2 |
|
||||
((u64)vnic << NIC_QS_ID_SHIFT) |
|
||||
|
|
@ -485,6 +517,86 @@ static void nic_tx_channel_cfg(struct nicpf *nic, u8 vnic, u8 sq_idx)
|
|||
nic_reg_write(nic, NIC_PF_TL2_0_63_PRI | (tl2 << 3), 0x00);
|
||||
}
|
||||
|
||||
/* Send primary nicvf pointer to secondary QS's VF */
|
||||
static void nic_send_pnicvf(struct nicpf *nic, int sqs)
|
||||
{
|
||||
union nic_mbx mbx = {};
|
||||
|
||||
mbx.nicvf.msg = NIC_MBOX_MSG_PNICVF_PTR;
|
||||
mbx.nicvf.nicvf = nic->nicvf[nic->pqs_vf[sqs]];
|
||||
nic_send_msg_to_vf(nic, sqs, &mbx);
|
||||
}
|
||||
|
||||
/* Send SQS's nicvf pointer to primary QS's VF */
|
||||
static void nic_send_snicvf(struct nicpf *nic, struct nicvf_ptr *nicvf)
|
||||
{
|
||||
union nic_mbx mbx = {};
|
||||
int sqs_id = nic->vf_sqs[nicvf->vf_id][nicvf->sqs_id];
|
||||
|
||||
mbx.nicvf.msg = NIC_MBOX_MSG_SNICVF_PTR;
|
||||
mbx.nicvf.sqs_id = nicvf->sqs_id;
|
||||
mbx.nicvf.nicvf = nic->nicvf[sqs_id];
|
||||
nic_send_msg_to_vf(nic, nicvf->vf_id, &mbx);
|
||||
}
|
||||
|
||||
/* Find next available Qset that can be assigned as a
|
||||
* secondary Qset to a VF.
|
||||
*/
|
||||
static int nic_nxt_avail_sqs(struct nicpf *nic)
|
||||
{
|
||||
int sqs;
|
||||
|
||||
for (sqs = 0; sqs < nic->num_sqs_en; sqs++) {
|
||||
if (!nic->sqs_used[sqs])
|
||||
nic->sqs_used[sqs] = true;
|
||||
else
|
||||
continue;
|
||||
return sqs + nic->num_vf_en;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Allocate additional Qsets for requested VF */
|
||||
static void nic_alloc_sqs(struct nicpf *nic, struct sqs_alloc *sqs)
|
||||
{
|
||||
union nic_mbx mbx = {};
|
||||
int idx, alloc_qs = 0;
|
||||
int sqs_id;
|
||||
|
||||
if (!nic->num_sqs_en)
|
||||
goto send_mbox;
|
||||
|
||||
for (idx = 0; idx < sqs->qs_count; idx++) {
|
||||
sqs_id = nic_nxt_avail_sqs(nic);
|
||||
if (sqs_id < 0)
|
||||
break;
|
||||
nic->vf_sqs[sqs->vf_id][idx] = sqs_id;
|
||||
nic->pqs_vf[sqs_id] = sqs->vf_id;
|
||||
alloc_qs++;
|
||||
}
|
||||
|
||||
send_mbox:
|
||||
mbx.sqs_alloc.msg = NIC_MBOX_MSG_ALLOC_SQS;
|
||||
mbx.sqs_alloc.vf_id = sqs->vf_id;
|
||||
mbx.sqs_alloc.qs_count = alloc_qs;
|
||||
nic_send_msg_to_vf(nic, sqs->vf_id, &mbx);
|
||||
}
|
||||
|
||||
static int nic_config_loopback(struct nicpf *nic, struct set_loopback *lbk)
|
||||
{
|
||||
int bgx_idx, lmac_idx;
|
||||
|
||||
if (lbk->vf_id > MAX_LMAC)
|
||||
return -1;
|
||||
|
||||
bgx_idx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[lbk->vf_id]);
|
||||
lmac_idx = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[lbk->vf_id]);
|
||||
|
||||
bgx_lmac_internal_loopback(nic->node, bgx_idx, lmac_idx, lbk->enable);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Interrupt handler to handle mailbox messages from VFs */
|
||||
static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
|
||||
{
|
||||
|
|
@ -492,6 +604,7 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
|
|||
u64 *mbx_data;
|
||||
u64 mbx_addr;
|
||||
u64 reg_addr;
|
||||
u64 cfg;
|
||||
int bgx, lmac;
|
||||
int i;
|
||||
int ret = 0;
|
||||
|
|
@ -512,15 +625,24 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
|
|||
switch (mbx.msg.msg) {
|
||||
case NIC_MBOX_MSG_READY:
|
||||
nic_mbx_send_ready(nic, vf);
|
||||
nic->link[vf] = 0;
|
||||
nic->duplex[vf] = 0;
|
||||
nic->speed[vf] = 0;
|
||||
if (vf < MAX_LMAC) {
|
||||
nic->link[vf] = 0;
|
||||
nic->duplex[vf] = 0;
|
||||
nic->speed[vf] = 0;
|
||||
}
|
||||
ret = 1;
|
||||
break;
|
||||
case NIC_MBOX_MSG_QS_CFG:
|
||||
reg_addr = NIC_PF_QSET_0_127_CFG |
|
||||
(mbx.qs.num << NIC_QS_ID_SHIFT);
|
||||
nic_reg_write(nic, reg_addr, mbx.qs.cfg);
|
||||
cfg = mbx.qs.cfg;
|
||||
/* Check if its a secondary Qset */
|
||||
if (vf >= nic->num_vf_en) {
|
||||
cfg = cfg & (~0x7FULL);
|
||||
/* Assign this Qset to primary Qset's VF */
|
||||
cfg |= nic->pqs_vf[vf];
|
||||
}
|
||||
nic_reg_write(nic, reg_addr, cfg);
|
||||
break;
|
||||
case NIC_MBOX_MSG_RQ_CFG:
|
||||
reg_addr = NIC_PF_QSET_0_127_RQ_0_7_CFG |
|
||||
|
|
@ -548,9 +670,11 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
|
|||
(mbx.sq.qs_num << NIC_QS_ID_SHIFT) |
|
||||
(mbx.sq.sq_num << NIC_Q_NUM_SHIFT);
|
||||
nic_reg_write(nic, reg_addr, mbx.sq.cfg);
|
||||
nic_tx_channel_cfg(nic, mbx.qs.num, mbx.sq.sq_num);
|
||||
nic_tx_channel_cfg(nic, mbx.qs.num, &mbx.sq);
|
||||
break;
|
||||
case NIC_MBOX_MSG_SET_MAC:
|
||||
if (vf >= nic->num_vf_en)
|
||||
break;
|
||||
lmac = mbx.mac.vf_id;
|
||||
bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[lmac]);
|
||||
lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[lmac]);
|
||||
|
|
@ -577,10 +701,28 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
|
|||
case NIC_MBOX_MSG_SHUTDOWN:
|
||||
/* First msg in VF teardown sequence */
|
||||
nic->vf_enabled[vf] = false;
|
||||
if (vf >= nic->num_vf_en)
|
||||
nic->sqs_used[vf - nic->num_vf_en] = false;
|
||||
nic->pqs_vf[vf] = 0;
|
||||
break;
|
||||
case NIC_MBOX_MSG_ALLOC_SQS:
|
||||
nic_alloc_sqs(nic, &mbx.sqs_alloc);
|
||||
goto unlock;
|
||||
case NIC_MBOX_MSG_NICVF_PTR:
|
||||
nic->nicvf[vf] = mbx.nicvf.nicvf;
|
||||
break;
|
||||
case NIC_MBOX_MSG_PNICVF_PTR:
|
||||
nic_send_pnicvf(nic, vf);
|
||||
goto unlock;
|
||||
case NIC_MBOX_MSG_SNICVF_PTR:
|
||||
nic_send_snicvf(nic, &mbx.nicvf);
|
||||
goto unlock;
|
||||
case NIC_MBOX_MSG_BGX_STATS:
|
||||
nic_get_bgx_stats(nic, &mbx.bgx_stats);
|
||||
goto unlock;
|
||||
case NIC_MBOX_MSG_LOOPBACK:
|
||||
ret = nic_config_loopback(nic, &mbx.lbk);
|
||||
break;
|
||||
default:
|
||||
dev_err(&nic->pdev->dev,
|
||||
"Invalid msg from VF%d, msg 0x%x\n", vf, mbx.msg.msg);
|
||||
|
|
@ -606,8 +748,7 @@ static void nic_mbx_intr_handler (struct nicpf *nic, int mbx)
|
|||
if (intr & (1ULL << vf)) {
|
||||
dev_dbg(&nic->pdev->dev, "Intr from VF %d\n",
|
||||
vf + (mbx * vf_per_mbx_reg));
|
||||
if ((vf + (mbx * vf_per_mbx_reg)) > nic->num_vf_en)
|
||||
break;
|
||||
|
||||
nic_handle_mbx_intr(nic, vf + (mbx * vf_per_mbx_reg));
|
||||
nic_clear_mbx_intr(nic, vf, mbx);
|
||||
}
|
||||
|
|
@ -713,9 +854,24 @@ static void nic_unregister_interrupts(struct nicpf *nic)
|
|||
nic_disable_msix(nic);
|
||||
}
|
||||
|
||||
static int nic_num_sqs_en(struct nicpf *nic, int vf_en)
|
||||
{
|
||||
int pos, sqs_per_vf = MAX_SQS_PER_VF_SINGLE_NODE;
|
||||
u16 total_vf;
|
||||
|
||||
/* Check if its a multi-node environment */
|
||||
if (nr_node_ids > 1)
|
||||
sqs_per_vf = MAX_SQS_PER_VF;
|
||||
|
||||
pos = pci_find_ext_capability(nic->pdev, PCI_EXT_CAP_ID_SRIOV);
|
||||
pci_read_config_word(nic->pdev, (pos + PCI_SRIOV_TOTAL_VF), &total_vf);
|
||||
return min(total_vf - vf_en, vf_en * sqs_per_vf);
|
||||
}
|
||||
|
||||
static int nic_sriov_init(struct pci_dev *pdev, struct nicpf *nic)
|
||||
{
|
||||
int pos = 0;
|
||||
int vf_en;
|
||||
int err;
|
||||
u16 total_vf_cnt;
|
||||
|
||||
|
|
@ -732,16 +888,20 @@ static int nic_sriov_init(struct pci_dev *pdev, struct nicpf *nic)
|
|||
if (!total_vf_cnt)
|
||||
return 0;
|
||||
|
||||
err = pci_enable_sriov(pdev, nic->num_vf_en);
|
||||
vf_en = nic->num_vf_en;
|
||||
nic->num_sqs_en = nic_num_sqs_en(nic, nic->num_vf_en);
|
||||
vf_en += nic->num_sqs_en;
|
||||
|
||||
err = pci_enable_sriov(pdev, vf_en);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "SRIOV enable failed, num VF is %d\n",
|
||||
nic->num_vf_en);
|
||||
vf_en);
|
||||
nic->num_vf_en = 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
dev_info(&pdev->dev, "SRIOV enabled, number of VF available %d\n",
|
||||
nic->num_vf_en);
|
||||
vf_en);
|
||||
|
||||
nic->flags |= NIC_SRIOV_ENABLED;
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -35,10 +35,10 @@ struct nicvf_stat {
|
|||
}
|
||||
|
||||
static const struct nicvf_stat nicvf_hw_stats[] = {
|
||||
NICVF_HW_STAT(rx_bytes_ok),
|
||||
NICVF_HW_STAT(rx_ucast_frames_ok),
|
||||
NICVF_HW_STAT(rx_bcast_frames_ok),
|
||||
NICVF_HW_STAT(rx_mcast_frames_ok),
|
||||
NICVF_HW_STAT(rx_bytes),
|
||||
NICVF_HW_STAT(rx_ucast_frames),
|
||||
NICVF_HW_STAT(rx_bcast_frames),
|
||||
NICVF_HW_STAT(rx_mcast_frames),
|
||||
NICVF_HW_STAT(rx_fcs_errors),
|
||||
NICVF_HW_STAT(rx_l2_errors),
|
||||
NICVF_HW_STAT(rx_drop_red),
|
||||
|
|
@ -49,6 +49,30 @@ static const struct nicvf_stat nicvf_hw_stats[] = {
|
|||
NICVF_HW_STAT(rx_drop_mcast),
|
||||
NICVF_HW_STAT(rx_drop_l3_bcast),
|
||||
NICVF_HW_STAT(rx_drop_l3_mcast),
|
||||
NICVF_HW_STAT(rx_bgx_truncated_pkts),
|
||||
NICVF_HW_STAT(rx_jabber_errs),
|
||||
NICVF_HW_STAT(rx_fcs_errs),
|
||||
NICVF_HW_STAT(rx_bgx_errs),
|
||||
NICVF_HW_STAT(rx_prel2_errs),
|
||||
NICVF_HW_STAT(rx_l2_hdr_malformed),
|
||||
NICVF_HW_STAT(rx_oversize),
|
||||
NICVF_HW_STAT(rx_undersize),
|
||||
NICVF_HW_STAT(rx_l2_len_mismatch),
|
||||
NICVF_HW_STAT(rx_l2_pclp),
|
||||
NICVF_HW_STAT(rx_ip_ver_errs),
|
||||
NICVF_HW_STAT(rx_ip_csum_errs),
|
||||
NICVF_HW_STAT(rx_ip_hdr_malformed),
|
||||
NICVF_HW_STAT(rx_ip_payload_malformed),
|
||||
NICVF_HW_STAT(rx_ip_ttl_errs),
|
||||
NICVF_HW_STAT(rx_l3_pclp),
|
||||
NICVF_HW_STAT(rx_l4_malformed),
|
||||
NICVF_HW_STAT(rx_l4_csum_errs),
|
||||
NICVF_HW_STAT(rx_udp_len_errs),
|
||||
NICVF_HW_STAT(rx_l4_port_errs),
|
||||
NICVF_HW_STAT(rx_tcp_flag_errs),
|
||||
NICVF_HW_STAT(rx_tcp_offset_errs),
|
||||
NICVF_HW_STAT(rx_l4_pclp),
|
||||
NICVF_HW_STAT(rx_truncated_pkts),
|
||||
NICVF_HW_STAT(tx_bytes_ok),
|
||||
NICVF_HW_STAT(tx_ucast_frames_ok),
|
||||
NICVF_HW_STAT(tx_bcast_frames_ok),
|
||||
|
|
@ -125,10 +149,33 @@ static void nicvf_set_msglevel(struct net_device *netdev, u32 lvl)
|
|||
nic->msg_enable = lvl;
|
||||
}
|
||||
|
||||
static void nicvf_get_qset_strings(struct nicvf *nic, u8 **data, int qset)
|
||||
{
|
||||
int stats, qidx;
|
||||
int start_qidx = qset * MAX_RCV_QUEUES_PER_QS;
|
||||
|
||||
for (qidx = 0; qidx < nic->qs->rq_cnt; qidx++) {
|
||||
for (stats = 0; stats < nicvf_n_queue_stats; stats++) {
|
||||
sprintf(*data, "rxq%d: %s", qidx + start_qidx,
|
||||
nicvf_queue_stats[stats].name);
|
||||
*data += ETH_GSTRING_LEN;
|
||||
}
|
||||
}
|
||||
|
||||
for (qidx = 0; qidx < nic->qs->sq_cnt; qidx++) {
|
||||
for (stats = 0; stats < nicvf_n_queue_stats; stats++) {
|
||||
sprintf(*data, "txq%d: %s", qidx + start_qidx,
|
||||
nicvf_queue_stats[stats].name);
|
||||
*data += ETH_GSTRING_LEN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void nicvf_get_strings(struct net_device *netdev, u32 sset, u8 *data)
|
||||
{
|
||||
struct nicvf *nic = netdev_priv(netdev);
|
||||
int stats, qidx;
|
||||
int stats;
|
||||
int sqs;
|
||||
|
||||
if (sset != ETH_SS_STATS)
|
||||
return;
|
||||
|
|
@ -143,20 +190,12 @@ static void nicvf_get_strings(struct net_device *netdev, u32 sset, u8 *data)
|
|||
data += ETH_GSTRING_LEN;
|
||||
}
|
||||
|
||||
for (qidx = 0; qidx < nic->qs->rq_cnt; qidx++) {
|
||||
for (stats = 0; stats < nicvf_n_queue_stats; stats++) {
|
||||
sprintf(data, "rxq%d: %s", qidx,
|
||||
nicvf_queue_stats[stats].name);
|
||||
data += ETH_GSTRING_LEN;
|
||||
}
|
||||
}
|
||||
nicvf_get_qset_strings(nic, &data, 0);
|
||||
|
||||
for (qidx = 0; qidx < nic->qs->sq_cnt; qidx++) {
|
||||
for (stats = 0; stats < nicvf_n_queue_stats; stats++) {
|
||||
sprintf(data, "txq%d: %s", qidx,
|
||||
nicvf_queue_stats[stats].name);
|
||||
data += ETH_GSTRING_LEN;
|
||||
}
|
||||
for (sqs = 0; sqs < nic->sqs_count; sqs++) {
|
||||
if (!nic->snicvf[sqs])
|
||||
continue;
|
||||
nicvf_get_qset_strings(nic->snicvf[sqs], &data, sqs + 1);
|
||||
}
|
||||
|
||||
for (stats = 0; stats < BGX_RX_STATS_COUNT; stats++) {
|
||||
|
|
@ -173,21 +212,58 @@ static void nicvf_get_strings(struct net_device *netdev, u32 sset, u8 *data)
|
|||
static int nicvf_get_sset_count(struct net_device *netdev, int sset)
|
||||
{
|
||||
struct nicvf *nic = netdev_priv(netdev);
|
||||
int qstats_count;
|
||||
int sqs;
|
||||
|
||||
if (sset != ETH_SS_STATS)
|
||||
return -EINVAL;
|
||||
|
||||
qstats_count = nicvf_n_queue_stats *
|
||||
(nic->qs->rq_cnt + nic->qs->sq_cnt);
|
||||
for (sqs = 0; sqs < nic->sqs_count; sqs++) {
|
||||
struct nicvf *snic;
|
||||
|
||||
snic = nic->snicvf[sqs];
|
||||
if (!snic)
|
||||
continue;
|
||||
qstats_count += nicvf_n_queue_stats *
|
||||
(snic->qs->rq_cnt + snic->qs->sq_cnt);
|
||||
}
|
||||
|
||||
return nicvf_n_hw_stats + nicvf_n_drv_stats +
|
||||
(nicvf_n_queue_stats *
|
||||
(nic->qs->rq_cnt + nic->qs->sq_cnt)) +
|
||||
qstats_count +
|
||||
BGX_RX_STATS_COUNT + BGX_TX_STATS_COUNT;
|
||||
}
|
||||
|
||||
static void nicvf_get_qset_stats(struct nicvf *nic,
|
||||
struct ethtool_stats *stats, u64 **data)
|
||||
{
|
||||
int stat, qidx;
|
||||
|
||||
if (!nic)
|
||||
return;
|
||||
|
||||
for (qidx = 0; qidx < nic->qs->rq_cnt; qidx++) {
|
||||
nicvf_update_rq_stats(nic, qidx);
|
||||
for (stat = 0; stat < nicvf_n_queue_stats; stat++)
|
||||
*((*data)++) = ((u64 *)&nic->qs->rq[qidx].stats)
|
||||
[nicvf_queue_stats[stat].index];
|
||||
}
|
||||
|
||||
for (qidx = 0; qidx < nic->qs->sq_cnt; qidx++) {
|
||||
nicvf_update_sq_stats(nic, qidx);
|
||||
for (stat = 0; stat < nicvf_n_queue_stats; stat++)
|
||||
*((*data)++) = ((u64 *)&nic->qs->sq[qidx].stats)
|
||||
[nicvf_queue_stats[stat].index];
|
||||
}
|
||||
}
|
||||
|
||||
static void nicvf_get_ethtool_stats(struct net_device *netdev,
|
||||
struct ethtool_stats *stats, u64 *data)
|
||||
{
|
||||
struct nicvf *nic = netdev_priv(netdev);
|
||||
int stat, qidx;
|
||||
int stat;
|
||||
int sqs;
|
||||
|
||||
nicvf_update_stats(nic);
|
||||
|
||||
|
|
@ -195,22 +271,18 @@ static void nicvf_get_ethtool_stats(struct net_device *netdev,
|
|||
nicvf_update_lmac_stats(nic);
|
||||
|
||||
for (stat = 0; stat < nicvf_n_hw_stats; stat++)
|
||||
*(data++) = ((u64 *)&nic->stats)
|
||||
*(data++) = ((u64 *)&nic->hw_stats)
|
||||
[nicvf_hw_stats[stat].index];
|
||||
for (stat = 0; stat < nicvf_n_drv_stats; stat++)
|
||||
*(data++) = ((u64 *)&nic->drv_stats)
|
||||
[nicvf_drv_stats[stat].index];
|
||||
|
||||
for (qidx = 0; qidx < nic->qs->rq_cnt; qidx++) {
|
||||
for (stat = 0; stat < nicvf_n_queue_stats; stat++)
|
||||
*(data++) = ((u64 *)&nic->qs->rq[qidx].stats)
|
||||
[nicvf_queue_stats[stat].index];
|
||||
}
|
||||
nicvf_get_qset_stats(nic, stats, &data);
|
||||
|
||||
for (qidx = 0; qidx < nic->qs->sq_cnt; qidx++) {
|
||||
for (stat = 0; stat < nicvf_n_queue_stats; stat++)
|
||||
*(data++) = ((u64 *)&nic->qs->sq[qidx].stats)
|
||||
[nicvf_queue_stats[stat].index];
|
||||
for (sqs = 0; sqs < nic->sqs_count; sqs++) {
|
||||
if (!nic->snicvf[sqs])
|
||||
continue;
|
||||
nicvf_get_qset_stats(nic->snicvf[sqs], stats, &data);
|
||||
}
|
||||
|
||||
for (stat = 0; stat < BGX_RX_STATS_COUNT; stat++)
|
||||
|
|
@ -369,7 +441,7 @@ static int nicvf_get_rxnfc(struct net_device *dev,
|
|||
|
||||
switch (info->cmd) {
|
||||
case ETHTOOL_GRXRINGS:
|
||||
info->data = nic->qs->rq_cnt;
|
||||
info->data = nic->rx_queues;
|
||||
ret = 0;
|
||||
break;
|
||||
case ETHTOOL_GRXFH:
|
||||
|
|
@ -501,17 +573,15 @@ static int nicvf_set_rxfh(struct net_device *dev, const u32 *indir,
|
|||
struct nicvf_rss_info *rss = &nic->rss_info;
|
||||
int idx;
|
||||
|
||||
if ((nic->qs->rq_cnt <= 1) || (nic->cpi_alg != CPI_ALG_NONE)) {
|
||||
rss->enable = false;
|
||||
rss->hash_bits = 0;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* We do not allow change in unsupported parameters */
|
||||
if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
rss->enable = true;
|
||||
if (!rss->enable) {
|
||||
netdev_err(nic->netdev,
|
||||
"RSS is disabled, cannot change settings\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (indir) {
|
||||
for (idx = 0; idx < rss->rss_size; idx++)
|
||||
rss->ind_tbl[idx] = indir[idx];
|
||||
|
|
@ -534,11 +604,11 @@ static void nicvf_get_channels(struct net_device *dev,
|
|||
|
||||
memset(channel, 0, sizeof(*channel));
|
||||
|
||||
channel->max_rx = MAX_RCV_QUEUES_PER_QS;
|
||||
channel->max_tx = MAX_SND_QUEUES_PER_QS;
|
||||
channel->max_rx = nic->max_queues;
|
||||
channel->max_tx = nic->max_queues;
|
||||
|
||||
channel->rx_count = nic->qs->rq_cnt;
|
||||
channel->tx_count = nic->qs->sq_cnt;
|
||||
channel->rx_count = nic->rx_queues;
|
||||
channel->tx_count = nic->tx_queues;
|
||||
}
|
||||
|
||||
/* Set no of Tx, Rx queues to be used */
|
||||
|
|
@ -548,22 +618,34 @@ static int nicvf_set_channels(struct net_device *dev,
|
|||
struct nicvf *nic = netdev_priv(dev);
|
||||
int err = 0;
|
||||
bool if_up = netif_running(dev);
|
||||
int cqcount;
|
||||
|
||||
if (!channel->rx_count || !channel->tx_count)
|
||||
return -EINVAL;
|
||||
if (channel->rx_count > MAX_RCV_QUEUES_PER_QS)
|
||||
if (channel->rx_count > nic->max_queues)
|
||||
return -EINVAL;
|
||||
if (channel->tx_count > MAX_SND_QUEUES_PER_QS)
|
||||
if (channel->tx_count > nic->max_queues)
|
||||
return -EINVAL;
|
||||
|
||||
if (if_up)
|
||||
nicvf_stop(dev);
|
||||
|
||||
nic->qs->rq_cnt = channel->rx_count;
|
||||
nic->qs->sq_cnt = channel->tx_count;
|
||||
cqcount = max(channel->rx_count, channel->tx_count);
|
||||
|
||||
if (cqcount > MAX_CMP_QUEUES_PER_QS) {
|
||||
nic->sqs_count = roundup(cqcount, MAX_CMP_QUEUES_PER_QS);
|
||||
nic->sqs_count = (nic->sqs_count / MAX_CMP_QUEUES_PER_QS) - 1;
|
||||
} else {
|
||||
nic->sqs_count = 0;
|
||||
}
|
||||
|
||||
nic->qs->rq_cnt = min_t(u32, channel->rx_count, MAX_RCV_QUEUES_PER_QS);
|
||||
nic->qs->sq_cnt = min_t(u32, channel->tx_count, MAX_SND_QUEUES_PER_QS);
|
||||
nic->qs->cq_cnt = max(nic->qs->rq_cnt, nic->qs->sq_cnt);
|
||||
|
||||
err = nicvf_set_real_num_queues(dev, nic->qs->sq_cnt, nic->qs->rq_cnt);
|
||||
nic->rx_queues = channel->rx_count;
|
||||
nic->tx_queues = channel->tx_count;
|
||||
err = nicvf_set_real_num_queues(dev, nic->tx_queues, nic->rx_queues);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
|
@ -571,7 +653,7 @@ static int nicvf_set_channels(struct net_device *dev,
|
|||
nicvf_open(dev);
|
||||
|
||||
netdev_info(dev, "Setting num Tx rings to %d, Rx rings to %d success\n",
|
||||
nic->qs->sq_cnt, nic->qs->rq_cnt);
|
||||
nic->tx_queues, nic->rx_queues);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/log2.h>
|
||||
|
|
@ -50,6 +51,14 @@ module_param(cpi_alg, int, S_IRUGO);
|
|||
MODULE_PARM_DESC(cpi_alg,
|
||||
"PFC algorithm (0=none, 1=VLAN, 2=VLAN16, 3=IP Diffserv)");
|
||||
|
||||
static inline u8 nicvf_netdev_qidx(struct nicvf *nic, u8 qidx)
|
||||
{
|
||||
if (nic->sqs_mode)
|
||||
return qidx + ((nic->sqs_id + 1) * MAX_CMP_QUEUES_PER_QS);
|
||||
else
|
||||
return qidx;
|
||||
}
|
||||
|
||||
static inline void nicvf_set_rx_frame_cnt(struct nicvf *nic,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
|
|
@ -105,7 +114,6 @@ u64 nicvf_queue_reg_read(struct nicvf *nic, u64 offset, u64 qidx)
|
|||
}
|
||||
|
||||
/* VF -> PF mailbox communication */
|
||||
|
||||
static void nicvf_write_to_mbx(struct nicvf *nic, union nic_mbx *mbx)
|
||||
{
|
||||
u64 *msg = (u64 *)mbx;
|
||||
|
|
@ -147,26 +155,15 @@ int nicvf_send_msg_to_pf(struct nicvf *nic, union nic_mbx *mbx)
|
|||
*/
|
||||
static int nicvf_check_pf_ready(struct nicvf *nic)
|
||||
{
|
||||
int timeout = 5000, sleep = 20;
|
||||
union nic_mbx mbx = {};
|
||||
|
||||
mbx.msg.msg = NIC_MBOX_MSG_READY;
|
||||
|
||||
nic->pf_ready_to_rcv_msg = false;
|
||||
|
||||
nicvf_write_to_mbx(nic, &mbx);
|
||||
|
||||
while (!nic->pf_ready_to_rcv_msg) {
|
||||
msleep(sleep);
|
||||
if (nic->pf_ready_to_rcv_msg)
|
||||
break;
|
||||
timeout -= sleep;
|
||||
if (!timeout) {
|
||||
netdev_err(nic->netdev,
|
||||
"PF didn't respond to READY msg\n");
|
||||
return 0;
|
||||
}
|
||||
if (nicvf_send_msg_to_pf(nic, &mbx)) {
|
||||
netdev_err(nic->netdev,
|
||||
"PF didn't respond to READY msg\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -197,13 +194,15 @@ static void nicvf_handle_mbx_intr(struct nicvf *nic)
|
|||
netdev_dbg(nic->netdev, "Mbox message: msg: 0x%x\n", mbx.msg.msg);
|
||||
switch (mbx.msg.msg) {
|
||||
case NIC_MBOX_MSG_READY:
|
||||
nic->pf_ready_to_rcv_msg = true;
|
||||
nic->pf_acked = true;
|
||||
nic->vf_id = mbx.nic_cfg.vf_id & 0x7F;
|
||||
nic->tns_mode = mbx.nic_cfg.tns_mode & 0x7F;
|
||||
nic->node = mbx.nic_cfg.node_id;
|
||||
if (!nic->set_mac_pending)
|
||||
ether_addr_copy(nic->netdev->dev_addr,
|
||||
mbx.nic_cfg.mac_addr);
|
||||
nic->sqs_mode = mbx.nic_cfg.sqs_mode;
|
||||
nic->loopback_supported = mbx.nic_cfg.loopback_supported;
|
||||
nic->link_up = false;
|
||||
nic->duplex = 0;
|
||||
nic->speed = 0;
|
||||
|
|
@ -221,7 +220,6 @@ static void nicvf_handle_mbx_intr(struct nicvf *nic)
|
|||
case NIC_MBOX_MSG_BGX_STATS:
|
||||
nicvf_read_bgx_stats(nic, &mbx.bgx_stats);
|
||||
nic->pf_acked = true;
|
||||
nic->bgx_stats_acked = true;
|
||||
break;
|
||||
case NIC_MBOX_MSG_BGX_LINK_CHANGE:
|
||||
nic->pf_acked = true;
|
||||
|
|
@ -242,6 +240,26 @@ static void nicvf_handle_mbx_intr(struct nicvf *nic)
|
|||
netif_tx_stop_all_queues(nic->netdev);
|
||||
}
|
||||
break;
|
||||
case NIC_MBOX_MSG_ALLOC_SQS:
|
||||
nic->sqs_count = mbx.sqs_alloc.qs_count;
|
||||
nic->pf_acked = true;
|
||||
break;
|
||||
case NIC_MBOX_MSG_SNICVF_PTR:
|
||||
/* Primary VF: make note of secondary VF's pointer
|
||||
* to be used while packet transmission.
|
||||
*/
|
||||
nic->snicvf[mbx.nicvf.sqs_id] =
|
||||
(struct nicvf *)mbx.nicvf.nicvf;
|
||||
nic->pf_acked = true;
|
||||
break;
|
||||
case NIC_MBOX_MSG_PNICVF_PTR:
|
||||
/* Secondary VF/Qset: make note of primary VF's pointer
|
||||
* to be used while packet reception, to handover packet
|
||||
* to primary VF's netdev.
|
||||
*/
|
||||
nic->pnicvf = (struct nicvf *)mbx.nicvf.nicvf;
|
||||
nic->pf_acked = true;
|
||||
break;
|
||||
default:
|
||||
netdev_err(nic->netdev,
|
||||
"Invalid message from PF, msg 0x%x\n", mbx.msg.msg);
|
||||
|
|
@ -326,7 +344,7 @@ static int nicvf_rss_init(struct nicvf *nic)
|
|||
|
||||
nicvf_get_rss_size(nic);
|
||||
|
||||
if ((nic->qs->rq_cnt <= 1) || (cpi_alg != CPI_ALG_NONE)) {
|
||||
if (cpi_alg != CPI_ALG_NONE) {
|
||||
rss->enable = false;
|
||||
rss->hash_bits = 0;
|
||||
return 0;
|
||||
|
|
@ -350,11 +368,100 @@ static int nicvf_rss_init(struct nicvf *nic)
|
|||
|
||||
for (idx = 0; idx < rss->rss_size; idx++)
|
||||
rss->ind_tbl[idx] = ethtool_rxfh_indir_default(idx,
|
||||
nic->qs->rq_cnt);
|
||||
nic->rx_queues);
|
||||
nicvf_config_rss(nic);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Request PF to allocate additional Qsets */
|
||||
static void nicvf_request_sqs(struct nicvf *nic)
|
||||
{
|
||||
union nic_mbx mbx = {};
|
||||
int sqs;
|
||||
int sqs_count = nic->sqs_count;
|
||||
int rx_queues = 0, tx_queues = 0;
|
||||
|
||||
/* Only primary VF should request */
|
||||
if (nic->sqs_mode || !nic->sqs_count)
|
||||
return;
|
||||
|
||||
mbx.sqs_alloc.msg = NIC_MBOX_MSG_ALLOC_SQS;
|
||||
mbx.sqs_alloc.vf_id = nic->vf_id;
|
||||
mbx.sqs_alloc.qs_count = nic->sqs_count;
|
||||
if (nicvf_send_msg_to_pf(nic, &mbx)) {
|
||||
/* No response from PF */
|
||||
nic->sqs_count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Return if no Secondary Qsets available */
|
||||
if (!nic->sqs_count)
|
||||
return;
|
||||
|
||||
if (nic->rx_queues > MAX_RCV_QUEUES_PER_QS)
|
||||
rx_queues = nic->rx_queues - MAX_RCV_QUEUES_PER_QS;
|
||||
if (nic->tx_queues > MAX_SND_QUEUES_PER_QS)
|
||||
tx_queues = nic->tx_queues - MAX_SND_QUEUES_PER_QS;
|
||||
|
||||
/* Set no of Rx/Tx queues in each of the SQsets */
|
||||
for (sqs = 0; sqs < nic->sqs_count; sqs++) {
|
||||
mbx.nicvf.msg = NIC_MBOX_MSG_SNICVF_PTR;
|
||||
mbx.nicvf.vf_id = nic->vf_id;
|
||||
mbx.nicvf.sqs_id = sqs;
|
||||
nicvf_send_msg_to_pf(nic, &mbx);
|
||||
|
||||
nic->snicvf[sqs]->sqs_id = sqs;
|
||||
if (rx_queues > MAX_RCV_QUEUES_PER_QS) {
|
||||
nic->snicvf[sqs]->qs->rq_cnt = MAX_RCV_QUEUES_PER_QS;
|
||||
rx_queues -= MAX_RCV_QUEUES_PER_QS;
|
||||
} else {
|
||||
nic->snicvf[sqs]->qs->rq_cnt = rx_queues;
|
||||
rx_queues = 0;
|
||||
}
|
||||
|
||||
if (tx_queues > MAX_SND_QUEUES_PER_QS) {
|
||||
nic->snicvf[sqs]->qs->sq_cnt = MAX_SND_QUEUES_PER_QS;
|
||||
tx_queues -= MAX_SND_QUEUES_PER_QS;
|
||||
} else {
|
||||
nic->snicvf[sqs]->qs->sq_cnt = tx_queues;
|
||||
tx_queues = 0;
|
||||
}
|
||||
|
||||
nic->snicvf[sqs]->qs->cq_cnt =
|
||||
max(nic->snicvf[sqs]->qs->rq_cnt, nic->snicvf[sqs]->qs->sq_cnt);
|
||||
|
||||
/* Initialize secondary Qset's queues and its interrupts */
|
||||
nicvf_open(nic->snicvf[sqs]->netdev);
|
||||
}
|
||||
|
||||
/* Update stack with actual Rx/Tx queue count allocated */
|
||||
if (sqs_count != nic->sqs_count)
|
||||
nicvf_set_real_num_queues(nic->netdev,
|
||||
nic->tx_queues, nic->rx_queues);
|
||||
}
|
||||
|
||||
/* Send this Qset's nicvf pointer to PF.
|
||||
* PF inturn sends primary VF's nicvf struct to secondary Qsets/VFs
|
||||
* so that packets received by these Qsets can use primary VF's netdev
|
||||
*/
|
||||
static void nicvf_send_vf_struct(struct nicvf *nic)
|
||||
{
|
||||
union nic_mbx mbx = {};
|
||||
|
||||
mbx.nicvf.msg = NIC_MBOX_MSG_NICVF_PTR;
|
||||
mbx.nicvf.sqs_mode = nic->sqs_mode;
|
||||
mbx.nicvf.nicvf = (u64)nic;
|
||||
nicvf_send_msg_to_pf(nic, &mbx);
|
||||
}
|
||||
|
||||
static void nicvf_get_primary_vf_struct(struct nicvf *nic)
|
||||
{
|
||||
union nic_mbx mbx = {};
|
||||
|
||||
mbx.nicvf.msg = NIC_MBOX_MSG_PNICVF_PTR;
|
||||
nicvf_send_msg_to_pf(nic, &mbx);
|
||||
}
|
||||
|
||||
int nicvf_set_real_num_queues(struct net_device *netdev,
|
||||
int tx_queues, int rx_queues)
|
||||
{
|
||||
|
|
@ -429,6 +536,34 @@ static void nicvf_snd_pkt_handler(struct net_device *netdev,
|
|||
}
|
||||
}
|
||||
|
||||
static inline void nicvf_set_rxhash(struct net_device *netdev,
|
||||
struct cqe_rx_t *cqe_rx,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
u8 hash_type;
|
||||
u32 hash;
|
||||
|
||||
if (!(netdev->features & NETIF_F_RXHASH))
|
||||
return;
|
||||
|
||||
switch (cqe_rx->rss_alg) {
|
||||
case RSS_ALG_TCP_IP:
|
||||
case RSS_ALG_UDP_IP:
|
||||
hash_type = PKT_HASH_TYPE_L4;
|
||||
hash = cqe_rx->rss_tag;
|
||||
break;
|
||||
case RSS_ALG_IP:
|
||||
hash_type = PKT_HASH_TYPE_L3;
|
||||
hash = cqe_rx->rss_tag;
|
||||
break;
|
||||
default:
|
||||
hash_type = PKT_HASH_TYPE_NONE;
|
||||
hash = 0;
|
||||
}
|
||||
|
||||
skb_set_hash(skb, hash, hash_type);
|
||||
}
|
||||
|
||||
static void nicvf_rcv_pkt_handler(struct net_device *netdev,
|
||||
struct napi_struct *napi,
|
||||
struct cmp_queue *cq,
|
||||
|
|
@ -437,6 +572,15 @@ static void nicvf_rcv_pkt_handler(struct net_device *netdev,
|
|||
struct sk_buff *skb;
|
||||
struct nicvf *nic = netdev_priv(netdev);
|
||||
int err = 0;
|
||||
int rq_idx;
|
||||
|
||||
rq_idx = nicvf_netdev_qidx(nic, cqe_rx->rq_idx);
|
||||
|
||||
if (nic->sqs_mode) {
|
||||
/* Use primary VF's 'nicvf' struct */
|
||||
nic = nic->pnicvf;
|
||||
netdev = nic->netdev;
|
||||
}
|
||||
|
||||
/* Check for errors */
|
||||
err = nicvf_check_cqe_rx_errs(nic, cq, cqe_rx);
|
||||
|
|
@ -456,9 +600,17 @@ static void nicvf_rcv_pkt_handler(struct net_device *netdev,
|
|||
skb->data, skb->len, true);
|
||||
}
|
||||
|
||||
/* If error packet, drop it here */
|
||||
if (err) {
|
||||
dev_kfree_skb_any(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
nicvf_set_rx_frame_cnt(nic, skb);
|
||||
|
||||
skb_record_rx_queue(skb, cqe_rx->rq_idx);
|
||||
nicvf_set_rxhash(netdev, cqe_rx, skb);
|
||||
|
||||
skb_record_rx_queue(skb, rq_idx);
|
||||
if (netdev->hw_features & NETIF_F_RXCSUM) {
|
||||
/* HW by default verifies TCP/UDP/SCTP checksums */
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
|
|
@ -468,6 +620,11 @@ static void nicvf_rcv_pkt_handler(struct net_device *netdev,
|
|||
|
||||
skb->protocol = eth_type_trans(skb, netdev);
|
||||
|
||||
/* Check for stripped VLAN */
|
||||
if (cqe_rx->vlan_found && cqe_rx->vlan_stripped)
|
||||
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
|
||||
ntohs((__force __be16)cqe_rx->vlan_tci));
|
||||
|
||||
if (napi && (netdev->features & NETIF_F_GRO))
|
||||
napi_gro_receive(napi, skb);
|
||||
else
|
||||
|
|
@ -549,8 +706,11 @@ loop:
|
|||
done:
|
||||
/* Wakeup TXQ if its stopped earlier due to SQ full */
|
||||
if (tx_done) {
|
||||
txq = netdev_get_tx_queue(netdev, cq_idx);
|
||||
if (netif_tx_queue_stopped(txq)) {
|
||||
netdev = nic->pnicvf->netdev;
|
||||
txq = netdev_get_tx_queue(netdev,
|
||||
nicvf_netdev_qidx(nic, cq_idx));
|
||||
nic = nic->pnicvf;
|
||||
if (netif_tx_queue_stopped(txq) && netif_carrier_ok(netdev)) {
|
||||
netif_tx_start_queue(txq);
|
||||
nic->drv_stats.txq_wake++;
|
||||
if (netif_msg_tx_err(nic))
|
||||
|
|
@ -624,11 +784,20 @@ static void nicvf_handle_qs_err(unsigned long data)
|
|||
nicvf_enable_intr(nic, NICVF_INTR_QS_ERR, 0);
|
||||
}
|
||||
|
||||
static void nicvf_dump_intr_status(struct nicvf *nic)
|
||||
{
|
||||
if (netif_msg_intr(nic))
|
||||
netdev_info(nic->netdev, "%s: interrupt status 0x%llx\n",
|
||||
nic->netdev->name, nicvf_reg_read(nic, NIC_VF_INT));
|
||||
}
|
||||
|
||||
static irqreturn_t nicvf_misc_intr_handler(int irq, void *nicvf_irq)
|
||||
{
|
||||
struct nicvf *nic = (struct nicvf *)nicvf_irq;
|
||||
u64 intr;
|
||||
|
||||
nicvf_dump_intr_status(nic);
|
||||
|
||||
intr = nicvf_reg_read(nic, NIC_VF_INT);
|
||||
/* Check for spurious interrupt */
|
||||
if (!(intr & NICVF_INTR_MBOX_MASK))
|
||||
|
|
@ -639,59 +808,58 @@ static irqreturn_t nicvf_misc_intr_handler(int irq, void *nicvf_irq)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t nicvf_intr_handler(int irq, void *nicvf_irq)
|
||||
static irqreturn_t nicvf_intr_handler(int irq, void *cq_irq)
|
||||
{
|
||||
struct nicvf_cq_poll *cq_poll = (struct nicvf_cq_poll *)cq_irq;
|
||||
struct nicvf *nic = cq_poll->nicvf;
|
||||
int qidx = cq_poll->cq_idx;
|
||||
|
||||
nicvf_dump_intr_status(nic);
|
||||
|
||||
/* Disable interrupts */
|
||||
nicvf_disable_intr(nic, NICVF_INTR_CQ, qidx);
|
||||
|
||||
/* Schedule NAPI */
|
||||
napi_schedule(&cq_poll->napi);
|
||||
|
||||
/* Clear interrupt */
|
||||
nicvf_clear_intr(nic, NICVF_INTR_CQ, qidx);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t nicvf_rbdr_intr_handler(int irq, void *nicvf_irq)
|
||||
{
|
||||
u64 qidx, intr, clear_intr = 0;
|
||||
u64 cq_intr, rbdr_intr, qs_err_intr;
|
||||
struct nicvf *nic = (struct nicvf *)nicvf_irq;
|
||||
struct queue_set *qs = nic->qs;
|
||||
struct nicvf_cq_poll *cq_poll = NULL;
|
||||
u8 qidx;
|
||||
|
||||
intr = nicvf_reg_read(nic, NIC_VF_INT);
|
||||
if (netif_msg_intr(nic))
|
||||
netdev_info(nic->netdev, "%s: interrupt status 0x%llx\n",
|
||||
nic->netdev->name, intr);
|
||||
|
||||
qs_err_intr = intr & NICVF_INTR_QS_ERR_MASK;
|
||||
if (qs_err_intr) {
|
||||
/* Disable Qset err interrupt and schedule softirq */
|
||||
nicvf_disable_intr(nic, NICVF_INTR_QS_ERR, 0);
|
||||
tasklet_hi_schedule(&nic->qs_err_task);
|
||||
clear_intr |= qs_err_intr;
|
||||
}
|
||||
nicvf_dump_intr_status(nic);
|
||||
|
||||
/* Disable interrupts and start polling */
|
||||
cq_intr = (intr & NICVF_INTR_CQ_MASK) >> NICVF_INTR_CQ_SHIFT;
|
||||
for (qidx = 0; qidx < qs->cq_cnt; qidx++) {
|
||||
if (!(cq_intr & (1 << qidx)))
|
||||
/* Disable RBDR interrupt and schedule softirq */
|
||||
for (qidx = 0; qidx < nic->qs->rbdr_cnt; qidx++) {
|
||||
if (!nicvf_is_intr_enabled(nic, NICVF_INTR_RBDR, qidx))
|
||||
continue;
|
||||
if (!nicvf_is_intr_enabled(nic, NICVF_INTR_CQ, qidx))
|
||||
continue;
|
||||
|
||||
nicvf_disable_intr(nic, NICVF_INTR_CQ, qidx);
|
||||
clear_intr |= ((1 << qidx) << NICVF_INTR_CQ_SHIFT);
|
||||
|
||||
cq_poll = nic->napi[qidx];
|
||||
/* Schedule NAPI */
|
||||
if (cq_poll)
|
||||
napi_schedule(&cq_poll->napi);
|
||||
nicvf_disable_intr(nic, NICVF_INTR_RBDR, qidx);
|
||||
tasklet_hi_schedule(&nic->rbdr_task);
|
||||
/* Clear interrupt */
|
||||
nicvf_clear_intr(nic, NICVF_INTR_RBDR, qidx);
|
||||
}
|
||||
|
||||
/* Handle RBDR interrupts */
|
||||
rbdr_intr = (intr & NICVF_INTR_RBDR_MASK) >> NICVF_INTR_RBDR_SHIFT;
|
||||
if (rbdr_intr) {
|
||||
/* Disable RBDR interrupt and schedule softirq */
|
||||
for (qidx = 0; qidx < qs->rbdr_cnt; qidx++) {
|
||||
if (!nicvf_is_intr_enabled(nic, NICVF_INTR_RBDR, qidx))
|
||||
continue;
|
||||
nicvf_disable_intr(nic, NICVF_INTR_RBDR, qidx);
|
||||
tasklet_hi_schedule(&nic->rbdr_task);
|
||||
clear_intr |= ((1 << qidx) << NICVF_INTR_RBDR_SHIFT);
|
||||
}
|
||||
}
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t nicvf_qs_err_intr_handler(int irq, void *nicvf_irq)
|
||||
{
|
||||
struct nicvf *nic = (struct nicvf *)nicvf_irq;
|
||||
|
||||
nicvf_dump_intr_status(nic);
|
||||
|
||||
/* Disable Qset err interrupt and schedule softirq */
|
||||
nicvf_disable_intr(nic, NICVF_INTR_QS_ERR, 0);
|
||||
tasklet_hi_schedule(&nic->qs_err_task);
|
||||
nicvf_clear_intr(nic, NICVF_INTR_QS_ERR, 0);
|
||||
|
||||
/* Clear interrupts */
|
||||
nicvf_reg_write(nic, NIC_VF_INT, clear_intr);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
|
@ -725,7 +893,7 @@ static void nicvf_disable_msix(struct nicvf *nic)
|
|||
|
||||
static int nicvf_register_interrupts(struct nicvf *nic)
|
||||
{
|
||||
int irq, free, ret = 0;
|
||||
int irq, ret = 0;
|
||||
int vector;
|
||||
|
||||
for_each_cq_irq(irq)
|
||||
|
|
@ -740,44 +908,42 @@ static int nicvf_register_interrupts(struct nicvf *nic)
|
|||
sprintf(nic->irq_name[irq], "NICVF%d RBDR%d",
|
||||
nic->vf_id, irq - NICVF_INTR_ID_RBDR);
|
||||
|
||||
/* Register all interrupts except mailbox */
|
||||
for (irq = 0; irq < NICVF_INTR_ID_SQ; irq++) {
|
||||
/* Register CQ interrupts */
|
||||
for (irq = 0; irq < nic->qs->cq_cnt; irq++) {
|
||||
vector = nic->msix_entries[irq].vector;
|
||||
ret = request_irq(vector, nicvf_intr_handler,
|
||||
0, nic->irq_name[irq], nic);
|
||||
0, nic->irq_name[irq], nic->napi[irq]);
|
||||
if (ret)
|
||||
break;
|
||||
goto err;
|
||||
nic->irq_allocated[irq] = true;
|
||||
}
|
||||
|
||||
for (irq = NICVF_INTR_ID_SQ; irq < NICVF_INTR_ID_MISC; irq++) {
|
||||
/* Register RBDR interrupt */
|
||||
for (irq = NICVF_INTR_ID_RBDR;
|
||||
irq < (NICVF_INTR_ID_RBDR + nic->qs->rbdr_cnt); irq++) {
|
||||
vector = nic->msix_entries[irq].vector;
|
||||
ret = request_irq(vector, nicvf_intr_handler,
|
||||
ret = request_irq(vector, nicvf_rbdr_intr_handler,
|
||||
0, nic->irq_name[irq], nic);
|
||||
if (ret)
|
||||
break;
|
||||
goto err;
|
||||
nic->irq_allocated[irq] = true;
|
||||
}
|
||||
|
||||
/* Register QS error interrupt */
|
||||
sprintf(nic->irq_name[NICVF_INTR_ID_QS_ERR],
|
||||
"NICVF%d Qset error", nic->vf_id);
|
||||
if (!ret) {
|
||||
vector = nic->msix_entries[NICVF_INTR_ID_QS_ERR].vector;
|
||||
irq = NICVF_INTR_ID_QS_ERR;
|
||||
ret = request_irq(vector, nicvf_intr_handler,
|
||||
0, nic->irq_name[irq], nic);
|
||||
if (!ret)
|
||||
nic->irq_allocated[irq] = true;
|
||||
}
|
||||
irq = NICVF_INTR_ID_QS_ERR;
|
||||
ret = request_irq(nic->msix_entries[irq].vector,
|
||||
nicvf_qs_err_intr_handler,
|
||||
0, nic->irq_name[irq], nic);
|
||||
if (!ret)
|
||||
nic->irq_allocated[irq] = true;
|
||||
|
||||
if (ret) {
|
||||
netdev_err(nic->netdev, "Request irq failed\n");
|
||||
for (free = 0; free < irq; free++)
|
||||
free_irq(nic->msix_entries[free].vector, nic);
|
||||
return ret;
|
||||
}
|
||||
err:
|
||||
if (ret)
|
||||
netdev_err(nic->netdev, "request_irq failed, vector %d\n", irq);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void nicvf_unregister_interrupts(struct nicvf *nic)
|
||||
|
|
@ -786,8 +952,14 @@ static void nicvf_unregister_interrupts(struct nicvf *nic)
|
|||
|
||||
/* Free registered interrupts */
|
||||
for (irq = 0; irq < nic->num_vec; irq++) {
|
||||
if (nic->irq_allocated[irq])
|
||||
if (!nic->irq_allocated[irq])
|
||||
continue;
|
||||
|
||||
if (irq < NICVF_INTR_ID_SQ)
|
||||
free_irq(nic->msix_entries[irq].vector, nic->napi[irq]);
|
||||
else
|
||||
free_irq(nic->msix_entries[irq].vector, nic);
|
||||
|
||||
nic->irq_allocated[irq] = false;
|
||||
}
|
||||
|
||||
|
|
@ -852,13 +1024,26 @@ static netdev_tx_t nicvf_xmit(struct sk_buff *skb, struct net_device *netdev)
|
|||
netdev_warn(netdev,
|
||||
"%s: Transmit ring full, stopping SQ%d\n",
|
||||
netdev->name, qid);
|
||||
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
static inline void nicvf_free_cq_poll(struct nicvf *nic)
|
||||
{
|
||||
struct nicvf_cq_poll *cq_poll;
|
||||
int qidx;
|
||||
|
||||
for (qidx = 0; qidx < nic->qs->cq_cnt; qidx++) {
|
||||
cq_poll = nic->napi[qidx];
|
||||
if (!cq_poll)
|
||||
continue;
|
||||
nic->napi[qidx] = NULL;
|
||||
kfree(cq_poll);
|
||||
}
|
||||
}
|
||||
|
||||
int nicvf_stop(struct net_device *netdev)
|
||||
{
|
||||
int irq, qidx;
|
||||
|
|
@ -871,6 +1056,17 @@ int nicvf_stop(struct net_device *netdev)
|
|||
nicvf_send_msg_to_pf(nic, &mbx);
|
||||
|
||||
netif_carrier_off(netdev);
|
||||
netif_tx_stop_all_queues(nic->netdev);
|
||||
|
||||
/* Teardown secondary qsets first */
|
||||
if (!nic->sqs_mode) {
|
||||
for (qidx = 0; qidx < nic->sqs_count; qidx++) {
|
||||
if (!nic->snicvf[qidx])
|
||||
continue;
|
||||
nicvf_stop(nic->snicvf[qidx]->netdev);
|
||||
nic->snicvf[qidx] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable RBDR & QS error interrupts */
|
||||
for (qidx = 0; qidx < qs->rbdr_cnt; qidx++) {
|
||||
|
|
@ -893,7 +1089,6 @@ int nicvf_stop(struct net_device *netdev)
|
|||
cq_poll = nic->napi[qidx];
|
||||
if (!cq_poll)
|
||||
continue;
|
||||
nic->napi[qidx] = NULL;
|
||||
napi_synchronize(&cq_poll->napi);
|
||||
/* CQ intr is enabled while napi_complete,
|
||||
* so disable it now
|
||||
|
|
@ -902,7 +1097,6 @@ int nicvf_stop(struct net_device *netdev)
|
|||
nicvf_clear_intr(nic, NICVF_INTR_CQ, qidx);
|
||||
napi_disable(&cq_poll->napi);
|
||||
netif_napi_del(&cq_poll->napi);
|
||||
kfree(cq_poll);
|
||||
}
|
||||
|
||||
netif_tx_disable(netdev);
|
||||
|
|
@ -918,6 +1112,12 @@ int nicvf_stop(struct net_device *netdev)
|
|||
|
||||
nicvf_unregister_interrupts(nic);
|
||||
|
||||
nicvf_free_cq_poll(nic);
|
||||
|
||||
/* Clear multiqset info */
|
||||
nic->pnicvf = nic;
|
||||
nic->sqs_count = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -944,6 +1144,7 @@ int nicvf_open(struct net_device *netdev)
|
|||
goto napi_del;
|
||||
}
|
||||
cq_poll->cq_idx = qidx;
|
||||
cq_poll->nicvf = nic;
|
||||
netif_napi_add(netdev, &cq_poll->napi, nicvf_poll,
|
||||
NAPI_POLL_WEIGHT);
|
||||
napi_enable(&cq_poll->napi);
|
||||
|
|
@ -972,10 +1173,16 @@ int nicvf_open(struct net_device *netdev)
|
|||
|
||||
/* Configure CPI alorithm */
|
||||
nic->cpi_alg = cpi_alg;
|
||||
nicvf_config_cpi(nic);
|
||||
if (!nic->sqs_mode)
|
||||
nicvf_config_cpi(nic);
|
||||
|
||||
nicvf_request_sqs(nic);
|
||||
if (nic->sqs_mode)
|
||||
nicvf_get_primary_vf_struct(nic);
|
||||
|
||||
/* Configure receive side scaling */
|
||||
nicvf_rss_init(nic);
|
||||
if (!nic->sqs_mode)
|
||||
nicvf_rss_init(nic);
|
||||
|
||||
err = nicvf_register_interrupts(nic);
|
||||
if (err)
|
||||
|
|
@ -1011,6 +1218,8 @@ int nicvf_open(struct net_device *netdev)
|
|||
cleanup:
|
||||
nicvf_disable_intr(nic, NICVF_INTR_MBOX, 0);
|
||||
nicvf_unregister_interrupts(nic);
|
||||
tasklet_kill(&nic->qs_err_task);
|
||||
tasklet_kill(&nic->rbdr_task);
|
||||
napi_del:
|
||||
for (qidx = 0; qidx < qs->cq_cnt; qidx++) {
|
||||
cq_poll = nic->napi[qidx];
|
||||
|
|
@ -1018,9 +1227,8 @@ napi_del:
|
|||
continue;
|
||||
napi_disable(&cq_poll->napi);
|
||||
netif_napi_del(&cq_poll->napi);
|
||||
kfree(cq_poll);
|
||||
nic->napi[qidx] = NULL;
|
||||
}
|
||||
nicvf_free_cq_poll(nic);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -1077,7 +1285,6 @@ void nicvf_update_lmac_stats(struct nicvf *nic)
|
|||
{
|
||||
int stat = 0;
|
||||
union nic_mbx mbx = {};
|
||||
int timeout;
|
||||
|
||||
if (!netif_running(nic->netdev))
|
||||
return;
|
||||
|
|
@ -1087,14 +1294,9 @@ void nicvf_update_lmac_stats(struct nicvf *nic)
|
|||
/* Rx stats */
|
||||
mbx.bgx_stats.rx = 1;
|
||||
while (stat < BGX_RX_STATS_COUNT) {
|
||||
nic->bgx_stats_acked = 0;
|
||||
mbx.bgx_stats.idx = stat;
|
||||
nicvf_send_msg_to_pf(nic, &mbx);
|
||||
timeout = 0;
|
||||
while ((!nic->bgx_stats_acked) && (timeout < 10)) {
|
||||
msleep(2);
|
||||
timeout++;
|
||||
}
|
||||
if (nicvf_send_msg_to_pf(nic, &mbx))
|
||||
return;
|
||||
stat++;
|
||||
}
|
||||
|
||||
|
|
@ -1103,14 +1305,9 @@ void nicvf_update_lmac_stats(struct nicvf *nic)
|
|||
/* Tx stats */
|
||||
mbx.bgx_stats.rx = 0;
|
||||
while (stat < BGX_TX_STATS_COUNT) {
|
||||
nic->bgx_stats_acked = 0;
|
||||
mbx.bgx_stats.idx = stat;
|
||||
nicvf_send_msg_to_pf(nic, &mbx);
|
||||
timeout = 0;
|
||||
while ((!nic->bgx_stats_acked) && (timeout < 10)) {
|
||||
msleep(2);
|
||||
timeout++;
|
||||
}
|
||||
if (nicvf_send_msg_to_pf(nic, &mbx))
|
||||
return;
|
||||
stat++;
|
||||
}
|
||||
}
|
||||
|
|
@ -1118,7 +1315,7 @@ void nicvf_update_lmac_stats(struct nicvf *nic)
|
|||
void nicvf_update_stats(struct nicvf *nic)
|
||||
{
|
||||
int qidx;
|
||||
struct nicvf_hw_stats *stats = &nic->stats;
|
||||
struct nicvf_hw_stats *stats = &nic->hw_stats;
|
||||
struct nicvf_drv_stats *drv_stats = &nic->drv_stats;
|
||||
struct queue_set *qs = nic->qs;
|
||||
|
||||
|
|
@ -1127,14 +1324,16 @@ void nicvf_update_stats(struct nicvf *nic)
|
|||
#define GET_TX_STATS(reg) \
|
||||
nicvf_reg_read(nic, NIC_VNIC_TX_STAT_0_4 | (reg << 3))
|
||||
|
||||
stats->rx_bytes_ok = GET_RX_STATS(RX_OCTS);
|
||||
stats->rx_ucast_frames_ok = GET_RX_STATS(RX_UCAST);
|
||||
stats->rx_bcast_frames_ok = GET_RX_STATS(RX_BCAST);
|
||||
stats->rx_mcast_frames_ok = GET_RX_STATS(RX_MCAST);
|
||||
stats->rx_bytes = GET_RX_STATS(RX_OCTS);
|
||||
stats->rx_ucast_frames = GET_RX_STATS(RX_UCAST);
|
||||
stats->rx_bcast_frames = GET_RX_STATS(RX_BCAST);
|
||||
stats->rx_mcast_frames = GET_RX_STATS(RX_MCAST);
|
||||
stats->rx_fcs_errors = GET_RX_STATS(RX_FCS);
|
||||
stats->rx_l2_errors = GET_RX_STATS(RX_L2ERR);
|
||||
stats->rx_drop_red = GET_RX_STATS(RX_RED);
|
||||
stats->rx_drop_red_bytes = GET_RX_STATS(RX_RED_OCTS);
|
||||
stats->rx_drop_overrun = GET_RX_STATS(RX_ORUN);
|
||||
stats->rx_drop_overrun_bytes = GET_RX_STATS(RX_ORUN_OCTS);
|
||||
stats->rx_drop_bcast = GET_RX_STATS(RX_DRP_BCAST);
|
||||
stats->rx_drop_mcast = GET_RX_STATS(RX_DRP_MCAST);
|
||||
stats->rx_drop_l3_bcast = GET_RX_STATS(RX_DRP_L3BCAST);
|
||||
|
|
@ -1146,9 +1345,6 @@ void nicvf_update_stats(struct nicvf *nic)
|
|||
stats->tx_mcast_frames_ok = GET_TX_STATS(TX_MCAST);
|
||||
stats->tx_drops = GET_TX_STATS(TX_DROP);
|
||||
|
||||
drv_stats->rx_frames_ok = stats->rx_ucast_frames_ok +
|
||||
stats->rx_bcast_frames_ok +
|
||||
stats->rx_mcast_frames_ok;
|
||||
drv_stats->tx_frames_ok = stats->tx_ucast_frames_ok +
|
||||
stats->tx_bcast_frames_ok +
|
||||
stats->tx_mcast_frames_ok;
|
||||
|
|
@ -1167,14 +1363,15 @@ static struct rtnl_link_stats64 *nicvf_get_stats64(struct net_device *netdev,
|
|||
struct rtnl_link_stats64 *stats)
|
||||
{
|
||||
struct nicvf *nic = netdev_priv(netdev);
|
||||
struct nicvf_hw_stats *hw_stats = &nic->stats;
|
||||
struct nicvf_hw_stats *hw_stats = &nic->hw_stats;
|
||||
struct nicvf_drv_stats *drv_stats = &nic->drv_stats;
|
||||
|
||||
nicvf_update_stats(nic);
|
||||
|
||||
stats->rx_bytes = hw_stats->rx_bytes_ok;
|
||||
stats->rx_bytes = hw_stats->rx_bytes;
|
||||
stats->rx_packets = drv_stats->rx_frames_ok;
|
||||
stats->rx_dropped = drv_stats->rx_drops;
|
||||
stats->multicast = hw_stats->rx_mcast_frames;
|
||||
|
||||
stats->tx_bytes = hw_stats->tx_bytes_ok;
|
||||
stats->tx_packets = drv_stats->tx_frames_ok;
|
||||
|
|
@ -1208,6 +1405,45 @@ static void nicvf_reset_task(struct work_struct *work)
|
|||
nic->netdev->trans_start = jiffies;
|
||||
}
|
||||
|
||||
static int nicvf_config_loopback(struct nicvf *nic,
|
||||
netdev_features_t features)
|
||||
{
|
||||
union nic_mbx mbx = {};
|
||||
|
||||
mbx.lbk.msg = NIC_MBOX_MSG_LOOPBACK;
|
||||
mbx.lbk.vf_id = nic->vf_id;
|
||||
mbx.lbk.enable = (features & NETIF_F_LOOPBACK) != 0;
|
||||
|
||||
return nicvf_send_msg_to_pf(nic, &mbx);
|
||||
}
|
||||
|
||||
static netdev_features_t nicvf_fix_features(struct net_device *netdev,
|
||||
netdev_features_t features)
|
||||
{
|
||||
struct nicvf *nic = netdev_priv(netdev);
|
||||
|
||||
if ((features & NETIF_F_LOOPBACK) &&
|
||||
netif_running(netdev) && !nic->loopback_supported)
|
||||
features &= ~NETIF_F_LOOPBACK;
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
static int nicvf_set_features(struct net_device *netdev,
|
||||
netdev_features_t features)
|
||||
{
|
||||
struct nicvf *nic = netdev_priv(netdev);
|
||||
netdev_features_t changed = features ^ netdev->features;
|
||||
|
||||
if (changed & NETIF_F_HW_VLAN_CTAG_RX)
|
||||
nicvf_config_vlan_stripping(nic, features);
|
||||
|
||||
if ((changed & NETIF_F_LOOPBACK) && netif_running(netdev))
|
||||
return nicvf_config_loopback(nic, features);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct net_device_ops nicvf_netdev_ops = {
|
||||
.ndo_open = nicvf_open,
|
||||
.ndo_stop = nicvf_stop,
|
||||
|
|
@ -1216,6 +1452,8 @@ static const struct net_device_ops nicvf_netdev_ops = {
|
|||
.ndo_set_mac_address = nicvf_set_mac_address,
|
||||
.ndo_get_stats64 = nicvf_get_stats64,
|
||||
.ndo_tx_timeout = nicvf_tx_timeout,
|
||||
.ndo_fix_features = nicvf_fix_features,
|
||||
.ndo_set_features = nicvf_set_features,
|
||||
};
|
||||
|
||||
static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
|
|
@ -1223,8 +1461,7 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
struct device *dev = &pdev->dev;
|
||||
struct net_device *netdev;
|
||||
struct nicvf *nic;
|
||||
struct queue_set *qs;
|
||||
int err;
|
||||
int err, qcount;
|
||||
|
||||
err = pci_enable_device(pdev);
|
||||
if (err) {
|
||||
|
|
@ -1250,9 +1487,17 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
goto err_release_regions;
|
||||
}
|
||||
|
||||
netdev = alloc_etherdev_mqs(sizeof(struct nicvf),
|
||||
MAX_RCV_QUEUES_PER_QS,
|
||||
MAX_SND_QUEUES_PER_QS);
|
||||
qcount = MAX_CMP_QUEUES_PER_QS;
|
||||
|
||||
/* Restrict multiqset support only for host bound VFs */
|
||||
if (pdev->is_virtfn) {
|
||||
/* Set max number of queues per VF */
|
||||
qcount = roundup(num_online_cpus(), MAX_CMP_QUEUES_PER_QS);
|
||||
qcount = min(qcount,
|
||||
(MAX_SQS_PER_VF + 1) * MAX_CMP_QUEUES_PER_QS);
|
||||
}
|
||||
|
||||
netdev = alloc_etherdev_mqs(sizeof(struct nicvf), qcount, qcount);
|
||||
if (!netdev) {
|
||||
err = -ENOMEM;
|
||||
goto err_release_regions;
|
||||
|
|
@ -1265,6 +1510,8 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
nic = netdev_priv(netdev);
|
||||
nic->netdev = netdev;
|
||||
nic->pdev = pdev;
|
||||
nic->pnicvf = nic;
|
||||
nic->max_queues = qcount;
|
||||
|
||||
/* MAP VF's configuration registers */
|
||||
nic->reg_base = pcim_iomap(pdev, PCI_CFG_REG_BAR_NUM, 0);
|
||||
|
|
@ -1278,20 +1525,31 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
if (err)
|
||||
goto err_free_netdev;
|
||||
|
||||
qs = nic->qs;
|
||||
|
||||
err = nicvf_set_real_num_queues(netdev, qs->sq_cnt, qs->rq_cnt);
|
||||
if (err)
|
||||
goto err_free_netdev;
|
||||
|
||||
/* Check if PF is alive and get MAC address for this VF */
|
||||
err = nicvf_register_misc_interrupt(nic);
|
||||
if (err)
|
||||
goto err_free_netdev;
|
||||
|
||||
netdev->features |= (NETIF_F_RXCSUM | NETIF_F_IP_CSUM | NETIF_F_SG |
|
||||
NETIF_F_TSO | NETIF_F_GRO);
|
||||
netdev->hw_features = netdev->features;
|
||||
nicvf_send_vf_struct(nic);
|
||||
|
||||
/* Check if this VF is in QS only mode */
|
||||
if (nic->sqs_mode)
|
||||
return 0;
|
||||
|
||||
err = nicvf_set_real_num_queues(netdev, nic->tx_queues, nic->rx_queues);
|
||||
if (err)
|
||||
goto err_unregister_interrupts;
|
||||
|
||||
netdev->hw_features = (NETIF_F_RXCSUM | NETIF_F_IP_CSUM | NETIF_F_SG |
|
||||
NETIF_F_TSO | NETIF_F_GRO |
|
||||
NETIF_F_HW_VLAN_CTAG_RX);
|
||||
|
||||
netdev->hw_features |= NETIF_F_RXHASH;
|
||||
|
||||
netdev->features |= netdev->hw_features;
|
||||
netdev->hw_features |= NETIF_F_LOOPBACK;
|
||||
|
||||
netdev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO;
|
||||
|
||||
netdev->netdev_ops = &nicvf_netdev_ops;
|
||||
netdev->watchdog_timeo = NICVF_TX_TIMEOUT;
|
||||
|
|
@ -1326,8 +1584,13 @@ static void nicvf_remove(struct pci_dev *pdev)
|
|||
{
|
||||
struct net_device *netdev = pci_get_drvdata(pdev);
|
||||
struct nicvf *nic = netdev_priv(netdev);
|
||||
struct net_device *pnetdev = nic->pnicvf->netdev;
|
||||
|
||||
unregister_netdev(netdev);
|
||||
/* Check if this Qset is assigned to different VF.
|
||||
* If yes, clean primary and all secondary Qsets.
|
||||
*/
|
||||
if (pnetdev && (pnetdev->reg_state == NETREG_REGISTERED))
|
||||
unregister_netdev(pnetdev);
|
||||
nicvf_unregister_interrupts(nic);
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
free_netdev(netdev);
|
||||
|
|
|
|||
|
|
@ -475,6 +475,27 @@ static void nicvf_reclaim_rbdr(struct nicvf *nic,
|
|||
return;
|
||||
}
|
||||
|
||||
void nicvf_config_vlan_stripping(struct nicvf *nic, netdev_features_t features)
|
||||
{
|
||||
u64 rq_cfg;
|
||||
int sqs;
|
||||
|
||||
rq_cfg = nicvf_queue_reg_read(nic, NIC_QSET_RQ_GEN_CFG, 0);
|
||||
|
||||
/* Enable first VLAN stripping */
|
||||
if (features & NETIF_F_HW_VLAN_CTAG_RX)
|
||||
rq_cfg |= (1ULL << 25);
|
||||
else
|
||||
rq_cfg &= ~(1ULL << 25);
|
||||
nicvf_queue_reg_write(nic, NIC_QSET_RQ_GEN_CFG, 0, rq_cfg);
|
||||
|
||||
/* Configure Secondary Qsets, if any */
|
||||
for (sqs = 0; sqs < nic->sqs_count; sqs++)
|
||||
if (nic->snicvf[sqs])
|
||||
nicvf_queue_reg_write(nic->snicvf[sqs],
|
||||
NIC_QSET_RQ_GEN_CFG, 0, rq_cfg);
|
||||
}
|
||||
|
||||
/* Configures receive queue */
|
||||
static void nicvf_rcv_queue_config(struct nicvf *nic, struct queue_set *qs,
|
||||
int qidx, bool enable)
|
||||
|
|
@ -524,7 +545,9 @@ static void nicvf_rcv_queue_config(struct nicvf *nic, struct queue_set *qs,
|
|||
mbx.rq.cfg = (1ULL << 62) | (RQ_CQ_DROP << 8);
|
||||
nicvf_send_msg_to_pf(nic, &mbx);
|
||||
|
||||
nicvf_queue_reg_write(nic, NIC_QSET_RQ_GEN_CFG, qidx, 0x00);
|
||||
nicvf_queue_reg_write(nic, NIC_QSET_RQ_GEN_CFG, 0, 0x00);
|
||||
if (!nic->sqs_mode)
|
||||
nicvf_config_vlan_stripping(nic, nic->netdev->features);
|
||||
|
||||
/* Enable Receive queue */
|
||||
rq_cfg.ena = 1;
|
||||
|
|
@ -598,6 +621,7 @@ static void nicvf_snd_queue_config(struct nicvf *nic, struct queue_set *qs,
|
|||
mbx.sq.msg = NIC_MBOX_MSG_SQ_CFG;
|
||||
mbx.sq.qs_num = qs->vnic_id;
|
||||
mbx.sq.sq_num = qidx;
|
||||
mbx.sq.sqs_mode = nic->sqs_mode;
|
||||
mbx.sq.cfg = (sq->cq_qs << 3) | sq->cq_idx;
|
||||
nicvf_send_msg_to_pf(nic, &mbx);
|
||||
|
||||
|
|
@ -679,6 +703,7 @@ void nicvf_qset_config(struct nicvf *nic, bool enable)
|
|||
/* Send a mailbox msg to PF to config Qset */
|
||||
mbx.qs.msg = NIC_MBOX_MSG_QS_CFG;
|
||||
mbx.qs.num = qs->vnic_id;
|
||||
mbx.qs.sqs_count = nic->sqs_count;
|
||||
|
||||
mbx.qs.cfg = 0;
|
||||
qs_cfg = (struct qs_cfg *)&mbx.qs.cfg;
|
||||
|
|
@ -759,6 +784,10 @@ int nicvf_set_qset_resources(struct nicvf *nic)
|
|||
qs->rbdr_len = RCV_BUF_COUNT;
|
||||
qs->sq_len = SND_QUEUE_LEN;
|
||||
qs->cq_len = CMP_QUEUE_LEN;
|
||||
|
||||
nic->rx_queues = qs->rq_cnt;
|
||||
nic->tx_queues = qs->sq_cnt;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -961,9 +990,6 @@ nicvf_sq_add_hdr_subdesc(struct snd_queue *sq, int qentry,
|
|||
|
||||
/* Offload checksum calculation to HW */
|
||||
if (skb->ip_summed == CHECKSUM_PARTIAL) {
|
||||
if (skb->protocol != htons(ETH_P_IP))
|
||||
return;
|
||||
|
||||
hdr->csum_l3 = 1; /* Enable IP csum calculation */
|
||||
hdr->l3_offset = skb_network_offset(skb);
|
||||
hdr->l4_offset = skb_transport_offset(skb);
|
||||
|
|
@ -1005,7 +1031,7 @@ static inline void nicvf_sq_add_gather_subdesc(struct snd_queue *sq, int qentry,
|
|||
* them to SQ for transfer
|
||||
*/
|
||||
static int nicvf_sq_append_tso(struct nicvf *nic, struct snd_queue *sq,
|
||||
int qentry, struct sk_buff *skb)
|
||||
int sq_num, int qentry, struct sk_buff *skb)
|
||||
{
|
||||
struct tso_t tso;
|
||||
int seg_subdescs = 0, desc_cnt = 0;
|
||||
|
|
@ -1065,7 +1091,7 @@ static int nicvf_sq_append_tso(struct nicvf *nic, struct snd_queue *sq,
|
|||
|
||||
/* Inform HW to xmit all TSO segments */
|
||||
nicvf_queue_reg_write(nic, NIC_QSET_SQ_0_7_DOOR,
|
||||
skb_get_queue_mapping(skb), desc_cnt);
|
||||
sq_num, desc_cnt);
|
||||
nic->drv_stats.tx_tso++;
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -1076,10 +1102,24 @@ int nicvf_sq_append_skb(struct nicvf *nic, struct sk_buff *skb)
|
|||
int i, size;
|
||||
int subdesc_cnt;
|
||||
int sq_num, qentry;
|
||||
struct queue_set *qs = nic->qs;
|
||||
struct queue_set *qs;
|
||||
struct snd_queue *sq;
|
||||
|
||||
sq_num = skb_get_queue_mapping(skb);
|
||||
if (sq_num >= MAX_SND_QUEUES_PER_QS) {
|
||||
/* Get secondary Qset's SQ structure */
|
||||
i = sq_num / MAX_SND_QUEUES_PER_QS;
|
||||
if (!nic->snicvf[i - 1]) {
|
||||
netdev_warn(nic->netdev,
|
||||
"Secondary Qset#%d's ptr not initialized\n",
|
||||
i - 1);
|
||||
return 1;
|
||||
}
|
||||
nic = (struct nicvf *)nic->snicvf[i - 1];
|
||||
sq_num = sq_num % MAX_SND_QUEUES_PER_QS;
|
||||
}
|
||||
|
||||
qs = nic->qs;
|
||||
sq = &qs->sq[sq_num];
|
||||
|
||||
subdesc_cnt = nicvf_sq_subdesc_required(nic, skb);
|
||||
|
|
@ -1090,7 +1130,7 @@ int nicvf_sq_append_skb(struct nicvf *nic, struct sk_buff *skb)
|
|||
|
||||
/* Check if its a TSO packet */
|
||||
if (skb_shinfo(skb)->gso_size)
|
||||
return nicvf_sq_append_tso(nic, sq, qentry, skb);
|
||||
return nicvf_sq_append_tso(nic, sq, sq_num, qentry, skb);
|
||||
|
||||
/* Add SQ header subdesc */
|
||||
nicvf_sq_add_hdr_subdesc(sq, qentry, subdesc_cnt - 1, skb, skb->len);
|
||||
|
|
@ -1126,6 +1166,8 @@ doorbell:
|
|||
return 1;
|
||||
|
||||
append_fail:
|
||||
/* Use original PCI dev for debug log */
|
||||
nic = nic->pnicvf;
|
||||
netdev_dbg(nic->netdev, "Not enough SQ descriptors to xmit pkt\n");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1371,10 +1413,11 @@ void nicvf_update_sq_stats(struct nicvf *nic, int sq_idx)
|
|||
int nicvf_check_cqe_rx_errs(struct nicvf *nic,
|
||||
struct cmp_queue *cq, struct cqe_rx_t *cqe_rx)
|
||||
{
|
||||
struct cmp_queue_stats *stats = &cq->stats;
|
||||
struct nicvf_hw_stats *stats = &nic->hw_stats;
|
||||
struct nicvf_drv_stats *drv_stats = &nic->drv_stats;
|
||||
|
||||
if (!cqe_rx->err_level && !cqe_rx->err_opcode) {
|
||||
stats->rx.errop.good++;
|
||||
drv_stats->rx_frames_ok++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1384,111 +1427,78 @@ int nicvf_check_cqe_rx_errs(struct nicvf *nic,
|
|||
nic->netdev->name,
|
||||
cqe_rx->err_level, cqe_rx->err_opcode);
|
||||
|
||||
switch (cqe_rx->err_level) {
|
||||
case CQ_ERRLVL_MAC:
|
||||
stats->rx.errlvl.mac_errs++;
|
||||
break;
|
||||
case CQ_ERRLVL_L2:
|
||||
stats->rx.errlvl.l2_errs++;
|
||||
break;
|
||||
case CQ_ERRLVL_L3:
|
||||
stats->rx.errlvl.l3_errs++;
|
||||
break;
|
||||
case CQ_ERRLVL_L4:
|
||||
stats->rx.errlvl.l4_errs++;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (cqe_rx->err_opcode) {
|
||||
case CQ_RX_ERROP_RE_PARTIAL:
|
||||
stats->rx.errop.partial_pkts++;
|
||||
stats->rx_bgx_truncated_pkts++;
|
||||
break;
|
||||
case CQ_RX_ERROP_RE_JABBER:
|
||||
stats->rx.errop.jabber_errs++;
|
||||
stats->rx_jabber_errs++;
|
||||
break;
|
||||
case CQ_RX_ERROP_RE_FCS:
|
||||
stats->rx.errop.fcs_errs++;
|
||||
break;
|
||||
case CQ_RX_ERROP_RE_TERMINATE:
|
||||
stats->rx.errop.terminate_errs++;
|
||||
stats->rx_fcs_errs++;
|
||||
break;
|
||||
case CQ_RX_ERROP_RE_RX_CTL:
|
||||
stats->rx.errop.bgx_rx_errs++;
|
||||
stats->rx_bgx_errs++;
|
||||
break;
|
||||
case CQ_RX_ERROP_PREL2_ERR:
|
||||
stats->rx.errop.prel2_errs++;
|
||||
break;
|
||||
case CQ_RX_ERROP_L2_FRAGMENT:
|
||||
stats->rx.errop.l2_frags++;
|
||||
break;
|
||||
case CQ_RX_ERROP_L2_OVERRUN:
|
||||
stats->rx.errop.l2_overruns++;
|
||||
break;
|
||||
case CQ_RX_ERROP_L2_PFCS:
|
||||
stats->rx.errop.l2_pfcs++;
|
||||
break;
|
||||
case CQ_RX_ERROP_L2_PUNY:
|
||||
stats->rx.errop.l2_puny++;
|
||||
stats->rx_prel2_errs++;
|
||||
break;
|
||||
case CQ_RX_ERROP_L2_MAL:
|
||||
stats->rx.errop.l2_hdr_malformed++;
|
||||
stats->rx_l2_hdr_malformed++;
|
||||
break;
|
||||
case CQ_RX_ERROP_L2_OVERSIZE:
|
||||
stats->rx.errop.l2_oversize++;
|
||||
stats->rx_oversize++;
|
||||
break;
|
||||
case CQ_RX_ERROP_L2_UNDERSIZE:
|
||||
stats->rx.errop.l2_undersize++;
|
||||
stats->rx_undersize++;
|
||||
break;
|
||||
case CQ_RX_ERROP_L2_LENMISM:
|
||||
stats->rx.errop.l2_len_mismatch++;
|
||||
stats->rx_l2_len_mismatch++;
|
||||
break;
|
||||
case CQ_RX_ERROP_L2_PCLP:
|
||||
stats->rx.errop.l2_pclp++;
|
||||
stats->rx_l2_pclp++;
|
||||
break;
|
||||
case CQ_RX_ERROP_IP_NOT:
|
||||
stats->rx.errop.non_ip++;
|
||||
stats->rx_ip_ver_errs++;
|
||||
break;
|
||||
case CQ_RX_ERROP_IP_CSUM_ERR:
|
||||
stats->rx.errop.ip_csum_err++;
|
||||
stats->rx_ip_csum_errs++;
|
||||
break;
|
||||
case CQ_RX_ERROP_IP_MAL:
|
||||
stats->rx.errop.ip_hdr_malformed++;
|
||||
stats->rx_ip_hdr_malformed++;
|
||||
break;
|
||||
case CQ_RX_ERROP_IP_MALD:
|
||||
stats->rx.errop.ip_payload_malformed++;
|
||||
stats->rx_ip_payload_malformed++;
|
||||
break;
|
||||
case CQ_RX_ERROP_IP_HOP:
|
||||
stats->rx.errop.ip_hop_errs++;
|
||||
break;
|
||||
case CQ_RX_ERROP_L3_ICRC:
|
||||
stats->rx.errop.l3_icrc_errs++;
|
||||
stats->rx_ip_ttl_errs++;
|
||||
break;
|
||||
case CQ_RX_ERROP_L3_PCLP:
|
||||
stats->rx.errop.l3_pclp++;
|
||||
stats->rx_l3_pclp++;
|
||||
break;
|
||||
case CQ_RX_ERROP_L4_MAL:
|
||||
stats->rx.errop.l4_malformed++;
|
||||
stats->rx_l4_malformed++;
|
||||
break;
|
||||
case CQ_RX_ERROP_L4_CHK:
|
||||
stats->rx.errop.l4_csum_errs++;
|
||||
stats->rx_l4_csum_errs++;
|
||||
break;
|
||||
case CQ_RX_ERROP_UDP_LEN:
|
||||
stats->rx.errop.udp_len_err++;
|
||||
stats->rx_udp_len_errs++;
|
||||
break;
|
||||
case CQ_RX_ERROP_L4_PORT:
|
||||
stats->rx.errop.bad_l4_port++;
|
||||
stats->rx_l4_port_errs++;
|
||||
break;
|
||||
case CQ_RX_ERROP_TCP_FLAG:
|
||||
stats->rx.errop.bad_tcp_flag++;
|
||||
stats->rx_tcp_flag_errs++;
|
||||
break;
|
||||
case CQ_RX_ERROP_TCP_OFFSET:
|
||||
stats->rx.errop.tcp_offset_errs++;
|
||||
stats->rx_tcp_offset_errs++;
|
||||
break;
|
||||
case CQ_RX_ERROP_L4_PCLP:
|
||||
stats->rx.errop.l4_pclp++;
|
||||
stats->rx_l4_pclp++;
|
||||
break;
|
||||
case CQ_RX_ERROP_RBDR_TRUNC:
|
||||
stats->rx.errop.pkt_truncated++;
|
||||
stats->rx_truncated_pkts++;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -181,47 +181,6 @@ enum CQ_TX_ERROP_E {
|
|||
};
|
||||
|
||||
struct cmp_queue_stats {
|
||||
struct rx_stats {
|
||||
struct {
|
||||
u64 mac_errs;
|
||||
u64 l2_errs;
|
||||
u64 l3_errs;
|
||||
u64 l4_errs;
|
||||
} errlvl;
|
||||
struct {
|
||||
u64 good;
|
||||
u64 partial_pkts;
|
||||
u64 jabber_errs;
|
||||
u64 fcs_errs;
|
||||
u64 terminate_errs;
|
||||
u64 bgx_rx_errs;
|
||||
u64 prel2_errs;
|
||||
u64 l2_frags;
|
||||
u64 l2_overruns;
|
||||
u64 l2_pfcs;
|
||||
u64 l2_puny;
|
||||
u64 l2_hdr_malformed;
|
||||
u64 l2_oversize;
|
||||
u64 l2_undersize;
|
||||
u64 l2_len_mismatch;
|
||||
u64 l2_pclp;
|
||||
u64 non_ip;
|
||||
u64 ip_csum_err;
|
||||
u64 ip_hdr_malformed;
|
||||
u64 ip_payload_malformed;
|
||||
u64 ip_hop_errs;
|
||||
u64 l3_icrc_errs;
|
||||
u64 l3_pclp;
|
||||
u64 l4_malformed;
|
||||
u64 l4_csum_errs;
|
||||
u64 udp_len_err;
|
||||
u64 bad_l4_port;
|
||||
u64 bad_tcp_flag;
|
||||
u64 tcp_offset_errs;
|
||||
u64 l4_pclp;
|
||||
u64 pkt_truncated;
|
||||
} errop;
|
||||
} rx;
|
||||
struct tx_stats {
|
||||
u64 good;
|
||||
u64 desc_fault;
|
||||
|
|
@ -292,6 +251,7 @@ struct cmp_queue {
|
|||
void *desc;
|
||||
struct q_desc_mem dmem;
|
||||
struct cmp_queue_stats stats;
|
||||
int irq;
|
||||
} ____cacheline_aligned_in_smp;
|
||||
|
||||
struct snd_queue {
|
||||
|
|
@ -347,6 +307,8 @@ struct queue_set {
|
|||
|
||||
#define CQ_ERR_MASK (CQ_WR_FULL | CQ_WR_DISABLE | CQ_WR_FAULT)
|
||||
|
||||
void nicvf_config_vlan_stripping(struct nicvf *nic,
|
||||
netdev_features_t features);
|
||||
int nicvf_set_qset_resources(struct nicvf *nic);
|
||||
int nicvf_config_data_transfer(struct nicvf *nic, bool enable);
|
||||
void nicvf_qset_config(struct nicvf *nic, bool enable);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
* as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/pci.h>
|
||||
|
|
@ -26,7 +27,7 @@
|
|||
struct lmac {
|
||||
struct bgx *bgx;
|
||||
int dmac;
|
||||
unsigned char mac[ETH_ALEN];
|
||||
u8 mac[ETH_ALEN];
|
||||
bool link_up;
|
||||
int lmacid; /* ID within BGX */
|
||||
int lmacid_bd; /* ID on board */
|
||||
|
|
@ -328,6 +329,37 @@ static void bgx_flush_dmac_addrs(struct bgx *bgx, int lmac)
|
|||
}
|
||||
}
|
||||
|
||||
/* Configure BGX LMAC in internal loopback mode */
|
||||
void bgx_lmac_internal_loopback(int node, int bgx_idx,
|
||||
int lmac_idx, bool enable)
|
||||
{
|
||||
struct bgx *bgx;
|
||||
struct lmac *lmac;
|
||||
u64 cfg;
|
||||
|
||||
bgx = bgx_vnic[(node * MAX_BGX_PER_CN88XX) + bgx_idx];
|
||||
if (!bgx)
|
||||
return;
|
||||
|
||||
lmac = &bgx->lmac[lmac_idx];
|
||||
if (lmac->is_sgmii) {
|
||||
cfg = bgx_reg_read(bgx, lmac_idx, BGX_GMP_PCS_MRX_CTL);
|
||||
if (enable)
|
||||
cfg |= PCS_MRX_CTL_LOOPBACK1;
|
||||
else
|
||||
cfg &= ~PCS_MRX_CTL_LOOPBACK1;
|
||||
bgx_reg_write(bgx, lmac_idx, BGX_GMP_PCS_MRX_CTL, cfg);
|
||||
} else {
|
||||
cfg = bgx_reg_read(bgx, lmac_idx, BGX_SPUX_CONTROL1);
|
||||
if (enable)
|
||||
cfg |= SPU_CTL_LOOPBACK;
|
||||
else
|
||||
cfg &= ~SPU_CTL_LOOPBACK;
|
||||
bgx_reg_write(bgx, lmac_idx, BGX_SPUX_CONTROL1, cfg);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(bgx_lmac_internal_loopback);
|
||||
|
||||
static int bgx_lmac_sgmii_init(struct bgx *bgx, int lmacid)
|
||||
{
|
||||
u64 cfg;
|
||||
|
|
@ -835,18 +867,108 @@ static void bgx_get_qlm_mode(struct bgx *bgx)
|
|||
}
|
||||
}
|
||||
|
||||
static void bgx_init_of(struct bgx *bgx, struct device_node *np)
|
||||
#ifdef CONFIG_ACPI
|
||||
|
||||
static int acpi_get_mac_address(struct acpi_device *adev, u8 *dst)
|
||||
{
|
||||
u8 mac[ETH_ALEN];
|
||||
int ret;
|
||||
|
||||
ret = fwnode_property_read_u8_array(acpi_fwnode_handle(adev),
|
||||
"mac-address", mac, ETH_ALEN);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (!is_valid_ether_addr(mac)) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(dst, mac, ETH_ALEN);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Currently only sets the MAC address. */
|
||||
static acpi_status bgx_acpi_register_phy(acpi_handle handle,
|
||||
u32 lvl, void *context, void **rv)
|
||||
{
|
||||
struct bgx *bgx = context;
|
||||
struct acpi_device *adev;
|
||||
|
||||
if (acpi_bus_get_device(handle, &adev))
|
||||
goto out;
|
||||
|
||||
acpi_get_mac_address(adev, bgx->lmac[bgx->lmac_count].mac);
|
||||
|
||||
SET_NETDEV_DEV(&bgx->lmac[bgx->lmac_count].netdev, &bgx->pdev->dev);
|
||||
|
||||
bgx->lmac[bgx->lmac_count].lmacid = bgx->lmac_count;
|
||||
out:
|
||||
bgx->lmac_count++;
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
static acpi_status bgx_acpi_match_id(acpi_handle handle, u32 lvl,
|
||||
void *context, void **ret_val)
|
||||
{
|
||||
struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
struct bgx *bgx = context;
|
||||
char bgx_sel[5];
|
||||
|
||||
snprintf(bgx_sel, 5, "BGX%d", bgx->bgx_id);
|
||||
if (ACPI_FAILURE(acpi_get_name(handle, ACPI_SINGLE_NAME, &string))) {
|
||||
pr_warn("Invalid link device\n");
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
if (strncmp(string.pointer, bgx_sel, 4))
|
||||
return AE_OK;
|
||||
|
||||
acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
|
||||
bgx_acpi_register_phy, NULL, bgx, NULL);
|
||||
|
||||
kfree(string.pointer);
|
||||
return AE_CTRL_TERMINATE;
|
||||
}
|
||||
|
||||
static int bgx_init_acpi_phy(struct bgx *bgx)
|
||||
{
|
||||
acpi_get_devices(NULL, bgx_acpi_match_id, bgx, (void **)NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int bgx_init_acpi_phy(struct bgx *bgx)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
||||
#if IS_ENABLED(CONFIG_OF_MDIO)
|
||||
|
||||
static int bgx_init_of_phy(struct bgx *bgx)
|
||||
{
|
||||
struct device_node *np;
|
||||
struct device_node *np_child;
|
||||
u8 lmac = 0;
|
||||
char bgx_sel[5];
|
||||
const char *mac;
|
||||
|
||||
/* Get BGX node from DT */
|
||||
snprintf(bgx_sel, 5, "bgx%d", bgx->bgx_id);
|
||||
np = of_find_node_by_name(NULL, bgx_sel);
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
|
||||
for_each_child_of_node(np, np_child) {
|
||||
struct device_node *phy_np;
|
||||
const char *mac;
|
||||
|
||||
phy_np = of_parse_phandle(np_child, "phy-handle", 0);
|
||||
if (phy_np)
|
||||
bgx->lmac[lmac].phydev = of_phy_find_device(phy_np);
|
||||
struct device_node *phy_np = of_parse_phandle(np_child,
|
||||
"phy-handle", 0);
|
||||
if (!phy_np)
|
||||
continue;
|
||||
bgx->lmac[lmac].phydev = of_phy_find_device(phy_np);
|
||||
|
||||
mac = of_get_mac_address(np_child);
|
||||
if (mac)
|
||||
|
|
@ -858,6 +980,24 @@ static void bgx_init_of(struct bgx *bgx, struct device_node *np)
|
|||
if (lmac == MAX_LMAC_PER_BGX)
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int bgx_init_of_phy(struct bgx *bgx)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_OF_MDIO */
|
||||
|
||||
static int bgx_init_phy(struct bgx *bgx)
|
||||
{
|
||||
if (!acpi_disabled)
|
||||
return bgx_init_acpi_phy(bgx);
|
||||
|
||||
return bgx_init_of_phy(bgx);
|
||||
}
|
||||
|
||||
static int bgx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
|
|
@ -865,8 +1005,6 @@ static int bgx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
int err;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct bgx *bgx = NULL;
|
||||
struct device_node *np;
|
||||
char bgx_sel[5];
|
||||
u8 lmac;
|
||||
|
||||
bgx = devm_kzalloc(dev, sizeof(*bgx), GFP_KERNEL);
|
||||
|
|
@ -902,10 +1040,9 @@ static int bgx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
bgx_vnic[bgx->bgx_id] = bgx;
|
||||
bgx_get_qlm_mode(bgx);
|
||||
|
||||
snprintf(bgx_sel, 5, "bgx%d", bgx->bgx_id);
|
||||
np = of_find_node_by_name(NULL, bgx_sel);
|
||||
if (np)
|
||||
bgx_init_of(bgx, np);
|
||||
err = bgx_init_phy(bgx);
|
||||
if (err)
|
||||
goto err_enable;
|
||||
|
||||
bgx_init_hw(bgx);
|
||||
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@
|
|||
|
||||
#define BGX_SPUX_CONTROL1 0x10000
|
||||
#define SPU_CTL_LOW_POWER BIT_ULL(11)
|
||||
#define SPU_CTL_LOOPBACK BIT_ULL(14)
|
||||
#define SPU_CTL_RESET BIT_ULL(15)
|
||||
#define BGX_SPUX_STATUS1 0x10008
|
||||
#define SPU_STATUS1_RCV_LNK BIT_ULL(2)
|
||||
|
|
@ -126,6 +127,7 @@
|
|||
#define PCS_MRX_CTL_RST_AN BIT_ULL(9)
|
||||
#define PCS_MRX_CTL_PWR_DN BIT_ULL(11)
|
||||
#define PCS_MRX_CTL_AN_EN BIT_ULL(12)
|
||||
#define PCS_MRX_CTL_LOOPBACK1 BIT_ULL(14)
|
||||
#define PCS_MRX_CTL_RESET BIT_ULL(15)
|
||||
#define BGX_GMP_PCS_MRX_STATUS 0x30008
|
||||
#define PCS_MRX_STATUS_AN_CPT BIT_ULL(5)
|
||||
|
|
@ -186,6 +188,8 @@ int bgx_get_lmac_count(int node, int bgx);
|
|||
const u8 *bgx_get_lmac_mac(int node, int bgx_idx, int lmacid);
|
||||
void bgx_set_lmac_mac(int node, int bgx_idx, int lmacid, const u8 *mac);
|
||||
void bgx_get_lmac_link_state(int node, int bgx_idx, int lmacid, void *status);
|
||||
void bgx_lmac_internal_loopback(int node, int bgx_idx,
|
||||
int lmac_idx, bool enable);
|
||||
u64 bgx_get_rx_stats(int node, int bgx_idx, int lmac, int idx);
|
||||
u64 bgx_get_tx_stats(int node, int bgx_idx, int lmac, int idx);
|
||||
#define BGX_RX_STATS_COUNT 11
|
||||
|
|
|
|||
|
|
@ -767,6 +767,11 @@ struct adapter {
|
|||
bool tid_release_task_busy;
|
||||
|
||||
struct dentry *debugfs_root;
|
||||
u32 use_bd; /* Use SGE Back Door intfc for reading SGE Contexts */
|
||||
u32 trace_rss; /* 1 implies that different RSS flit per filter is
|
||||
* used per filter else if 0 default RSS flit is
|
||||
* used for all 4 filters.
|
||||
*/
|
||||
|
||||
spinlock_t stats_lock;
|
||||
spinlock_t win0_lock ____cacheline_aligned_in_smp;
|
||||
|
|
@ -1284,6 +1289,7 @@ int t4_fwcache(struct adapter *adap, enum fw_params_param_dev_fwcache op);
|
|||
int t4_fw_upgrade(struct adapter *adap, unsigned int mbox,
|
||||
const u8 *fw_data, unsigned int size, int force);
|
||||
unsigned int t4_flash_cfg_addr(struct adapter *adapter);
|
||||
int t4_check_fw_version(struct adapter *adap);
|
||||
int t4_get_fw_version(struct adapter *adapter, u32 *vers);
|
||||
int t4_get_tp_version(struct adapter *adapter, u32 *vers);
|
||||
int t4_get_exprom_version(struct adapter *adapter, u32 *vers);
|
||||
|
|
@ -1440,6 +1446,10 @@ int t4_sge_ctxt_flush(struct adapter *adap, unsigned int mbox);
|
|||
int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl);
|
||||
void t4_db_full(struct adapter *adapter);
|
||||
void t4_db_dropped(struct adapter *adapter);
|
||||
int t4_set_trace_filter(struct adapter *adapter, const struct trace_params *tp,
|
||||
int filter_index, int enable);
|
||||
void t4_get_trace_filter(struct adapter *adapter, struct trace_params *tp,
|
||||
int filter_index, int *enabled);
|
||||
int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox,
|
||||
u32 addr, u32 val);
|
||||
void t4_sge_decode_idma_state(struct adapter *adapter, int state);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,15 @@ static const char * const dcb_ver_array[] = {
|
|||
"Auto Negotiated"
|
||||
};
|
||||
|
||||
static inline bool cxgb4_dcb_state_synced(enum cxgb4_dcb_state state)
|
||||
{
|
||||
if (state == CXGB4_DCB_STATE_FW_ALLSYNCED ||
|
||||
state == CXGB4_DCB_STATE_HOST)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Initialize a port's Data Center Bridging state. Typically used after a
|
||||
* Link Down event.
|
||||
*/
|
||||
|
|
@ -603,7 +612,7 @@ static void cxgb4_getpfccfg(struct net_device *dev, int priority, u8 *pfccfg)
|
|||
struct port_info *pi = netdev2pinfo(dev);
|
||||
struct port_dcb_info *dcb = &pi->dcb;
|
||||
|
||||
if (dcb->state != CXGB4_DCB_STATE_FW_ALLSYNCED ||
|
||||
if (!cxgb4_dcb_state_synced(dcb->state) ||
|
||||
priority >= CXGB4_MAX_PRIORITY)
|
||||
*pfccfg = 0;
|
||||
else
|
||||
|
|
@ -620,7 +629,7 @@ static void cxgb4_setpfccfg(struct net_device *dev, int priority, u8 pfccfg)
|
|||
struct adapter *adap = pi->adapter;
|
||||
int err;
|
||||
|
||||
if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED ||
|
||||
if (!cxgb4_dcb_state_synced(pi->dcb.state) ||
|
||||
priority >= CXGB4_MAX_PRIORITY)
|
||||
return;
|
||||
|
||||
|
|
@ -732,7 +741,7 @@ static u8 cxgb4_getpfcstate(struct net_device *dev)
|
|||
{
|
||||
struct port_info *pi = netdev2pinfo(dev);
|
||||
|
||||
if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED)
|
||||
if (!cxgb4_dcb_state_synced(pi->dcb.state))
|
||||
return false;
|
||||
|
||||
return pi->dcb.pfcen != 0;
|
||||
|
|
@ -756,7 +765,7 @@ static int __cxgb4_getapp(struct net_device *dev, u8 app_idtype, u16 app_id,
|
|||
struct adapter *adap = pi->adapter;
|
||||
int i;
|
||||
|
||||
if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED)
|
||||
if (!cxgb4_dcb_state_synced(pi->dcb.state))
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
|
||||
|
|
@ -794,7 +803,9 @@ static int __cxgb4_getapp(struct net_device *dev, u8 app_idtype, u16 app_id,
|
|||
*/
|
||||
static int cxgb4_getapp(struct net_device *dev, u8 app_idtype, u16 app_id)
|
||||
{
|
||||
return __cxgb4_getapp(dev, app_idtype, app_id, 0);
|
||||
/* Convert app_idtype to firmware format before querying */
|
||||
return __cxgb4_getapp(dev, app_idtype == DCB_APP_IDTYPE_ETHTYPE ?
|
||||
app_idtype : 3, app_id, 0);
|
||||
}
|
||||
|
||||
/* Write a new Application User Priority Map for the specified Application ID
|
||||
|
|
@ -808,7 +819,7 @@ static int __cxgb4_setapp(struct net_device *dev, u8 app_idtype, u16 app_id,
|
|||
int i, err;
|
||||
|
||||
|
||||
if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED)
|
||||
if (!cxgb4_dcb_state_synced(pi->dcb.state))
|
||||
return -EINVAL;
|
||||
|
||||
/* DCB info gets thrown away on link up */
|
||||
|
|
@ -896,10 +907,11 @@ cxgb4_ieee_negotiation_complete(struct net_device *dev,
|
|||
struct port_info *pi = netdev2pinfo(dev);
|
||||
struct port_dcb_info *dcb = &pi->dcb;
|
||||
|
||||
if (dcb_subtype && !(dcb->msgs & dcb_subtype))
|
||||
return 0;
|
||||
if (dcb->state == CXGB4_DCB_STATE_FW_ALLSYNCED)
|
||||
if (dcb_subtype && !(dcb->msgs & dcb_subtype))
|
||||
return 0;
|
||||
|
||||
return (dcb->state == CXGB4_DCB_STATE_FW_ALLSYNCED &&
|
||||
return (cxgb4_dcb_state_synced(dcb->state) &&
|
||||
(dcb->supported & DCB_CAP_DCBX_VER_IEEE));
|
||||
}
|
||||
|
||||
|
|
@ -1057,7 +1069,7 @@ static u8 cxgb4_setdcbx(struct net_device *dev, u8 dcb_request)
|
|||
|
||||
/* Can't enable DCB if we haven't successfully negotiated it.
|
||||
*/
|
||||
if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED)
|
||||
if (!cxgb4_dcb_state_synced(pi->dcb.state))
|
||||
return 1;
|
||||
|
||||
/* There's currently no mechanism to allow for the firmware DCBX
|
||||
|
|
@ -1080,7 +1092,7 @@ static int cxgb4_getpeer_app(struct net_device *dev,
|
|||
struct adapter *adap = pi->adapter;
|
||||
int i, err = 0;
|
||||
|
||||
if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED)
|
||||
if (!cxgb4_dcb_state_synced(pi->dcb.state))
|
||||
return 1;
|
||||
|
||||
info->willing = 0;
|
||||
|
|
@ -1114,7 +1126,7 @@ static int cxgb4_getpeerapp_tbl(struct net_device *dev, struct dcb_app *table)
|
|||
struct adapter *adap = pi->adapter;
|
||||
int i, err = 0;
|
||||
|
||||
if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED)
|
||||
if (!cxgb4_dcb_state_synced(pi->dcb.state))
|
||||
return 1;
|
||||
|
||||
for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
|
||||
|
|
@ -1133,7 +1145,7 @@ static int cxgb4_getpeerapp_tbl(struct net_device *dev, struct dcb_app *table)
|
|||
if (!pcmd.u.dcb.app_priority.protocolid)
|
||||
break;
|
||||
|
||||
table[i].selector = pcmd.u.dcb.app_priority.sel_field;
|
||||
table[i].selector = (pcmd.u.dcb.app_priority.sel_field + 1);
|
||||
table[i].protocol =
|
||||
be16_to_cpu(pcmd.u.dcb.app_priority.protocolid);
|
||||
table[i].priority =
|
||||
|
|
@ -1181,6 +1193,8 @@ static int cxgb4_cee_peer_getpg(struct net_device *dev, struct cee_pg *pg)
|
|||
for (i = 0; i < CXGB4_MAX_PRIORITY; i++)
|
||||
pg->pg_bw[i] = pcmd.u.dcb.pgrate.pgrate[i];
|
||||
|
||||
pg->tcs_supported = pcmd.u.dcb.pgrate.num_tcs_supported;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1198,6 +1212,8 @@ static int cxgb4_cee_peer_getpfc(struct net_device *dev, struct cee_pfc *pfc)
|
|||
*/
|
||||
pfc->pfc_en = bitswap_1(pi->dcb.pfcen);
|
||||
|
||||
pfc->tcs_supported = pi->dcb.pfc_num_tcs_supported;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -151,6 +151,45 @@ static int cim_la_show_3in1(struct seq_file *seq, void *v, int idx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cim_la_show_t6(struct seq_file *seq, void *v, int idx)
|
||||
{
|
||||
if (v == SEQ_START_TOKEN) {
|
||||
seq_puts(seq, "Status Inst Data PC LS0Stat "
|
||||
"LS0Addr LS0Data LS1Stat LS1Addr LS1Data\n");
|
||||
} else {
|
||||
const u32 *p = v;
|
||||
|
||||
seq_printf(seq, " %02x %04x%04x %04x%04x %04x%04x %08x %08x %08x %08x %08x %08x\n",
|
||||
(p[9] >> 16) & 0xff, /* Status */
|
||||
p[9] & 0xffff, p[8] >> 16, /* Inst */
|
||||
p[8] & 0xffff, p[7] >> 16, /* Data */
|
||||
p[7] & 0xffff, p[6] >> 16, /* PC */
|
||||
p[2], p[1], p[0], /* LS0 Stat, Addr and Data */
|
||||
p[5], p[4], p[3]); /* LS1 Stat, Addr and Data */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cim_la_show_pc_t6(struct seq_file *seq, void *v, int idx)
|
||||
{
|
||||
if (v == SEQ_START_TOKEN) {
|
||||
seq_puts(seq, "Status Inst Data PC\n");
|
||||
} else {
|
||||
const u32 *p = v;
|
||||
|
||||
seq_printf(seq, " %02x %08x %08x %08x\n",
|
||||
p[3] & 0xff, p[2], p[1], p[0]);
|
||||
seq_printf(seq, " %02x %02x%06x %02x%06x %02x%06x\n",
|
||||
(p[6] >> 8) & 0xff, p[6] & 0xff, p[5] >> 8,
|
||||
p[5] & 0xff, p[4] >> 8, p[4] & 0xff, p[3] >> 8);
|
||||
seq_printf(seq, " %02x %04x%04x %04x%04x %04x%04x\n",
|
||||
(p[9] >> 16) & 0xff, p[9] & 0xffff, p[8] >> 16,
|
||||
p[8] & 0xffff, p[7] >> 16, p[7] & 0xffff,
|
||||
p[6] >> 16);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cim_la_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
int ret;
|
||||
|
|
@ -162,9 +201,18 @@ static int cim_la_open(struct inode *inode, struct file *file)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
p = seq_open_tab(file, adap->params.cim_la_size / 8, 8 * sizeof(u32), 1,
|
||||
cfg & UPDBGLACAPTPCONLY_F ?
|
||||
cim_la_show_3in1 : cim_la_show);
|
||||
if (is_t6(adap->params.chip)) {
|
||||
/* +1 to account for integer division of CIMLA_SIZE/10 */
|
||||
p = seq_open_tab(file, (adap->params.cim_la_size / 10) + 1,
|
||||
10 * sizeof(u32), 1,
|
||||
cfg & UPDBGLACAPTPCONLY_F ?
|
||||
cim_la_show_pc_t6 : cim_la_show_t6);
|
||||
} else {
|
||||
p = seq_open_tab(file, adap->params.cim_la_size / 8,
|
||||
8 * sizeof(u32), 1,
|
||||
cfg & UPDBGLACAPTPCONLY_F ? cim_la_show_3in1 :
|
||||
cim_la_show);
|
||||
}
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -298,11 +346,11 @@ static int cim_qcfg_show(struct seq_file *seq, void *v)
|
|||
if (is_t4(adap->params.chip)) {
|
||||
i = t4_cim_read(adap, UP_OBQ_0_REALADDR_A,
|
||||
ARRAY_SIZE(obq_wr_t4), obq_wr_t4);
|
||||
wr = obq_wr_t4;
|
||||
wr = obq_wr_t4;
|
||||
} else {
|
||||
i = t4_cim_read(adap, UP_OBQ_0_SHADOW_REALADDR_A,
|
||||
ARRAY_SIZE(obq_wr_t5), obq_wr_t5);
|
||||
wr = obq_wr_t5;
|
||||
wr = obq_wr_t5;
|
||||
}
|
||||
}
|
||||
if (i)
|
||||
|
|
@ -1153,6 +1201,299 @@ static const struct file_operations mbox_debugfs_fops = {
|
|||
.write = mbox_write
|
||||
};
|
||||
|
||||
static int mps_trc_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
int enabled, i;
|
||||
struct trace_params tp;
|
||||
unsigned int trcidx = (uintptr_t)seq->private & 3;
|
||||
struct adapter *adap = seq->private - trcidx;
|
||||
|
||||
t4_get_trace_filter(adap, &tp, trcidx, &enabled);
|
||||
if (!enabled) {
|
||||
seq_puts(seq, "tracer is disabled\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tp.skip_ofst * 8 >= TRACE_LEN) {
|
||||
dev_err(adap->pdev_dev, "illegal trace pattern skip offset\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (tp.port < 8) {
|
||||
i = adap->chan_map[tp.port & 3];
|
||||
if (i >= MAX_NPORTS) {
|
||||
dev_err(adap->pdev_dev, "tracer %u is assigned "
|
||||
"to non-existing port\n", trcidx);
|
||||
return -EINVAL;
|
||||
}
|
||||
seq_printf(seq, "tracer is capturing %s %s, ",
|
||||
adap->port[i]->name, tp.port < 4 ? "Rx" : "Tx");
|
||||
} else
|
||||
seq_printf(seq, "tracer is capturing loopback %d, ",
|
||||
tp.port - 8);
|
||||
seq_printf(seq, "snap length: %u, min length: %u\n", tp.snap_len,
|
||||
tp.min_len);
|
||||
seq_printf(seq, "packets captured %smatch filter\n",
|
||||
tp.invert ? "do not " : "");
|
||||
|
||||
if (tp.skip_ofst) {
|
||||
seq_puts(seq, "filter pattern: ");
|
||||
for (i = 0; i < tp.skip_ofst * 2; i += 2)
|
||||
seq_printf(seq, "%08x%08x", tp.data[i], tp.data[i + 1]);
|
||||
seq_putc(seq, '/');
|
||||
for (i = 0; i < tp.skip_ofst * 2; i += 2)
|
||||
seq_printf(seq, "%08x%08x", tp.mask[i], tp.mask[i + 1]);
|
||||
seq_puts(seq, "@0\n");
|
||||
}
|
||||
|
||||
seq_puts(seq, "filter pattern: ");
|
||||
for (i = tp.skip_ofst * 2; i < TRACE_LEN / 4; i += 2)
|
||||
seq_printf(seq, "%08x%08x", tp.data[i], tp.data[i + 1]);
|
||||
seq_putc(seq, '/');
|
||||
for (i = tp.skip_ofst * 2; i < TRACE_LEN / 4; i += 2)
|
||||
seq_printf(seq, "%08x%08x", tp.mask[i], tp.mask[i + 1]);
|
||||
seq_printf(seq, "@%u\n", (tp.skip_ofst + tp.skip_len) * 8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mps_trc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, mps_trc_show, inode->i_private);
|
||||
}
|
||||
|
||||
static unsigned int xdigit2int(unsigned char c)
|
||||
{
|
||||
return isdigit(c) ? c - '0' : tolower(c) - 'a' + 10;
|
||||
}
|
||||
|
||||
#define TRC_PORT_NONE 0xff
|
||||
#define TRC_RSS_ENABLE 0x33
|
||||
#define TRC_RSS_DISABLE 0x13
|
||||
|
||||
/* Set an MPS trace filter. Syntax is:
|
||||
*
|
||||
* disable
|
||||
*
|
||||
* to disable tracing, or
|
||||
*
|
||||
* interface qid=<qid no> [snaplen=<val>] [minlen=<val>] [not] [<pattern>]...
|
||||
*
|
||||
* where interface is one of rxN, txN, or loopbackN, N = 0..3, qid can be one
|
||||
* of the NIC's response qid obtained from sge_qinfo and pattern has the form
|
||||
*
|
||||
* <pattern data>[/<pattern mask>][@<anchor>]
|
||||
*
|
||||
* Up to 2 filter patterns can be specified. If 2 are supplied the first one
|
||||
* must be anchored at 0. An omited mask is taken as a mask of 1s, an omitted
|
||||
* anchor is taken as 0.
|
||||
*/
|
||||
static ssize_t mps_trc_write(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *pos)
|
||||
{
|
||||
int i, enable, ret;
|
||||
u32 *data, *mask;
|
||||
struct trace_params tp;
|
||||
const struct inode *ino;
|
||||
unsigned int trcidx;
|
||||
char *s, *p, *word, *end;
|
||||
struct adapter *adap;
|
||||
u32 j;
|
||||
|
||||
ino = file_inode(file);
|
||||
trcidx = (uintptr_t)ino->i_private & 3;
|
||||
adap = ino->i_private - trcidx;
|
||||
|
||||
/* Don't accept input more than 1K, can't be anything valid except lots
|
||||
* of whitespace. Well, use less.
|
||||
*/
|
||||
if (count > 1024)
|
||||
return -EFBIG;
|
||||
p = s = kzalloc(count + 1, GFP_USER);
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
if (copy_from_user(s, buf, count)) {
|
||||
count = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (s[count - 1] == '\n')
|
||||
s[count - 1] = '\0';
|
||||
|
||||
enable = strcmp("disable", s) != 0;
|
||||
if (!enable)
|
||||
goto apply;
|
||||
|
||||
/* enable or disable trace multi rss filter */
|
||||
if (adap->trace_rss)
|
||||
t4_write_reg(adap, MPS_TRC_CFG_A, TRC_RSS_ENABLE);
|
||||
else
|
||||
t4_write_reg(adap, MPS_TRC_CFG_A, TRC_RSS_DISABLE);
|
||||
|
||||
memset(&tp, 0, sizeof(tp));
|
||||
tp.port = TRC_PORT_NONE;
|
||||
i = 0; /* counts pattern nibbles */
|
||||
|
||||
while (p) {
|
||||
while (isspace(*p))
|
||||
p++;
|
||||
word = strsep(&p, " ");
|
||||
if (!*word)
|
||||
break;
|
||||
|
||||
if (!strncmp(word, "qid=", 4)) {
|
||||
end = (char *)word + 4;
|
||||
ret = kstrtouint(end, 10, &j);
|
||||
if (ret)
|
||||
goto out;
|
||||
if (!adap->trace_rss) {
|
||||
t4_write_reg(adap, MPS_T5_TRC_RSS_CONTROL_A, j);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (trcidx) {
|
||||
case 0:
|
||||
t4_write_reg(adap, MPS_TRC_RSS_CONTROL_A, j);
|
||||
break;
|
||||
case 1:
|
||||
t4_write_reg(adap,
|
||||
MPS_TRC_FILTER1_RSS_CONTROL_A, j);
|
||||
break;
|
||||
case 2:
|
||||
t4_write_reg(adap,
|
||||
MPS_TRC_FILTER2_RSS_CONTROL_A, j);
|
||||
break;
|
||||
case 3:
|
||||
t4_write_reg(adap,
|
||||
MPS_TRC_FILTER3_RSS_CONTROL_A, j);
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!strncmp(word, "snaplen=", 8)) {
|
||||
end = (char *)word + 8;
|
||||
ret = kstrtouint(end, 10, &j);
|
||||
if (ret || j > 9600) {
|
||||
inval: count = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
tp.snap_len = j;
|
||||
continue;
|
||||
}
|
||||
if (!strncmp(word, "minlen=", 7)) {
|
||||
end = (char *)word + 7;
|
||||
ret = kstrtouint(end, 10, &j);
|
||||
if (ret || j > TFMINPKTSIZE_M)
|
||||
goto inval;
|
||||
tp.min_len = j;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(word, "not")) {
|
||||
tp.invert = !tp.invert;
|
||||
continue;
|
||||
}
|
||||
if (!strncmp(word, "loopback", 8) && tp.port == TRC_PORT_NONE) {
|
||||
if (word[8] < '0' || word[8] > '3' || word[9])
|
||||
goto inval;
|
||||
tp.port = word[8] - '0' + 8;
|
||||
continue;
|
||||
}
|
||||
if (!strncmp(word, "tx", 2) && tp.port == TRC_PORT_NONE) {
|
||||
if (word[2] < '0' || word[2] > '3' || word[3])
|
||||
goto inval;
|
||||
tp.port = word[2] - '0' + 4;
|
||||
if (adap->chan_map[tp.port & 3] >= MAX_NPORTS)
|
||||
goto inval;
|
||||
continue;
|
||||
}
|
||||
if (!strncmp(word, "rx", 2) && tp.port == TRC_PORT_NONE) {
|
||||
if (word[2] < '0' || word[2] > '3' || word[3])
|
||||
goto inval;
|
||||
tp.port = word[2] - '0';
|
||||
if (adap->chan_map[tp.port] >= MAX_NPORTS)
|
||||
goto inval;
|
||||
continue;
|
||||
}
|
||||
if (!isxdigit(*word))
|
||||
goto inval;
|
||||
|
||||
/* we have found a trace pattern */
|
||||
if (i) { /* split pattern */
|
||||
if (tp.skip_len) /* too many splits */
|
||||
goto inval;
|
||||
tp.skip_ofst = i / 16;
|
||||
}
|
||||
|
||||
data = &tp.data[i / 8];
|
||||
mask = &tp.mask[i / 8];
|
||||
j = i;
|
||||
|
||||
while (isxdigit(*word)) {
|
||||
if (i >= TRACE_LEN * 2) {
|
||||
count = -EFBIG;
|
||||
goto out;
|
||||
}
|
||||
*data = (*data << 4) + xdigit2int(*word++);
|
||||
if (++i % 8 == 0)
|
||||
data++;
|
||||
}
|
||||
if (*word == '/') {
|
||||
word++;
|
||||
while (isxdigit(*word)) {
|
||||
if (j >= i) /* mask longer than data */
|
||||
goto inval;
|
||||
*mask = (*mask << 4) + xdigit2int(*word++);
|
||||
if (++j % 8 == 0)
|
||||
mask++;
|
||||
}
|
||||
if (i != j) /* mask shorter than data */
|
||||
goto inval;
|
||||
} else { /* no mask, use all 1s */
|
||||
for ( ; i - j >= 8; j += 8)
|
||||
*mask++ = 0xffffffff;
|
||||
if (i % 8)
|
||||
*mask = (1 << (i % 8) * 4) - 1;
|
||||
}
|
||||
if (*word == '@') {
|
||||
end = (char *)word + 1;
|
||||
ret = kstrtouint(end, 10, &j);
|
||||
if (*end && *end != '\n')
|
||||
goto inval;
|
||||
if (j & 7) /* doesn't start at multiple of 8 */
|
||||
goto inval;
|
||||
j /= 8;
|
||||
if (j < tp.skip_ofst) /* overlaps earlier pattern */
|
||||
goto inval;
|
||||
if (j - tp.skip_ofst > 31) /* skip too big */
|
||||
goto inval;
|
||||
tp.skip_len = j - tp.skip_ofst;
|
||||
}
|
||||
if (i % 8) {
|
||||
*data <<= (8 - i % 8) * 4;
|
||||
*mask <<= (8 - i % 8) * 4;
|
||||
i = (i + 15) & ~15; /* 8-byte align */
|
||||
}
|
||||
}
|
||||
|
||||
if (tp.port == TRC_PORT_NONE)
|
||||
goto inval;
|
||||
|
||||
apply:
|
||||
i = t4_set_trace_filter(adap, &tp, trcidx, enable);
|
||||
if (i)
|
||||
count = i;
|
||||
out:
|
||||
kfree(s);
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations mps_trc_debugfs_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = mps_trc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
.write = mps_trc_write
|
||||
};
|
||||
|
||||
static ssize_t flash_read(struct file *file, char __user *buf, size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
|
|
@ -1895,13 +2236,13 @@ static int sge_qinfo_show(struct seq_file *seq, void *v)
|
|||
{
|
||||
struct adapter *adap = seq->private;
|
||||
int eth_entries = DIV_ROUND_UP(adap->sge.ethqsets, 4);
|
||||
int toe_entries = DIV_ROUND_UP(adap->sge.ofldqsets, 4);
|
||||
int iscsi_entries = DIV_ROUND_UP(adap->sge.ofldqsets, 4);
|
||||
int rdma_entries = DIV_ROUND_UP(adap->sge.rdmaqs, 4);
|
||||
int ciq_entries = DIV_ROUND_UP(adap->sge.rdmaciqs, 4);
|
||||
int ctrl_entries = DIV_ROUND_UP(MAX_CTRL_QUEUES, 4);
|
||||
int i, r = (uintptr_t)v - 1;
|
||||
int toe_idx = r - eth_entries;
|
||||
int rdma_idx = toe_idx - toe_entries;
|
||||
int iscsi_idx = r - eth_entries;
|
||||
int rdma_idx = iscsi_idx - iscsi_entries;
|
||||
int ciq_idx = rdma_idx - rdma_entries;
|
||||
int ctrl_idx = ciq_idx - ciq_entries;
|
||||
int fq_idx = ctrl_idx - ctrl_entries;
|
||||
|
|
@ -1917,8 +2258,12 @@ do { \
|
|||
seq_putc(seq, '\n'); \
|
||||
} while (0)
|
||||
#define S(s, v) S3("s", s, v)
|
||||
#define T3(fmt_spec, s, v) S3(fmt_spec, s, tx[i].v)
|
||||
#define T(s, v) S3("u", s, tx[i].v)
|
||||
#define TL(s, v) T3("lu", s, v)
|
||||
#define R3(fmt_spec, s, v) S3(fmt_spec, s, rx[i].v)
|
||||
#define R(s, v) S3("u", s, rx[i].v)
|
||||
#define RL(s, v) R3("lu", s, v)
|
||||
|
||||
if (r < eth_entries) {
|
||||
int base_qset = r * 4;
|
||||
|
|
@ -1957,12 +2302,30 @@ do { \
|
|||
R("FL avail:", fl.avail);
|
||||
R("FL PIDX:", fl.pidx);
|
||||
R("FL CIDX:", fl.cidx);
|
||||
} else if (toe_idx < toe_entries) {
|
||||
const struct sge_ofld_rxq *rx = &adap->sge.ofldrxq[toe_idx * 4];
|
||||
const struct sge_ofld_txq *tx = &adap->sge.ofldtxq[toe_idx * 4];
|
||||
int n = min(4, adap->sge.ofldqsets - 4 * toe_idx);
|
||||
RL("RxPackets:", stats.pkts);
|
||||
RL("RxCSO:", stats.rx_cso);
|
||||
RL("VLANxtract:", stats.vlan_ex);
|
||||
RL("LROmerged:", stats.lro_merged);
|
||||
RL("LROpackets:", stats.lro_pkts);
|
||||
RL("RxDrops:", stats.rx_drops);
|
||||
TL("TSO:", tso);
|
||||
TL("TxCSO:", tx_cso);
|
||||
TL("VLANins:", vlan_ins);
|
||||
TL("TxQFull:", q.stops);
|
||||
TL("TxQRestarts:", q.restarts);
|
||||
TL("TxMapErr:", mapping_err);
|
||||
RL("FLAllocErr:", fl.alloc_failed);
|
||||
RL("FLLrgAlcErr:", fl.large_alloc_failed);
|
||||
RL("FLStarving:", fl.starving);
|
||||
|
||||
S("QType:", "TOE");
|
||||
} else if (iscsi_idx < iscsi_entries) {
|
||||
const struct sge_ofld_rxq *rx =
|
||||
&adap->sge.ofldrxq[iscsi_idx * 4];
|
||||
const struct sge_ofld_txq *tx =
|
||||
&adap->sge.ofldtxq[iscsi_idx * 4];
|
||||
int n = min(4, adap->sge.ofldqsets - 4 * iscsi_idx);
|
||||
|
||||
S("QType:", "iSCSI");
|
||||
T("TxQ ID:", q.cntxt_id);
|
||||
T("TxQ size:", q.size);
|
||||
T("TxQ inuse:", q.in_use);
|
||||
|
|
@ -1982,6 +2345,13 @@ do { \
|
|||
R("FL avail:", fl.avail);
|
||||
R("FL PIDX:", fl.pidx);
|
||||
R("FL CIDX:", fl.cidx);
|
||||
RL("RxPackets:", stats.pkts);
|
||||
RL("RxImmPkts:", stats.imm);
|
||||
RL("RxNoMem:", stats.nomem);
|
||||
RL("FLAllocErr:", fl.alloc_failed);
|
||||
RL("FLLrgAlcErr:", fl.large_alloc_failed);
|
||||
RL("FLStarving:", fl.starving);
|
||||
|
||||
} else if (rdma_idx < rdma_entries) {
|
||||
const struct sge_ofld_rxq *rx =
|
||||
&adap->sge.rdmarxq[rdma_idx * 4];
|
||||
|
|
@ -2004,6 +2374,13 @@ do { \
|
|||
R("FL avail:", fl.avail);
|
||||
R("FL PIDX:", fl.pidx);
|
||||
R("FL CIDX:", fl.cidx);
|
||||
RL("RxPackets:", stats.pkts);
|
||||
RL("RxImmPkts:", stats.imm);
|
||||
RL("RxNoMem:", stats.nomem);
|
||||
RL("FLAllocErr:", fl.alloc_failed);
|
||||
RL("FLLrgAlcErr:", fl.large_alloc_failed);
|
||||
RL("FLStarving:", fl.starving);
|
||||
|
||||
} else if (ciq_idx < ciq_entries) {
|
||||
const struct sge_ofld_rxq *rx = &adap->sge.rdmaciq[ciq_idx * 4];
|
||||
int n = min(4, adap->sge.rdmaciqs - 4 * ciq_idx);
|
||||
|
|
@ -2019,6 +2396,9 @@ do { \
|
|||
S3("u", "Intr delay:", qtimer_val(adap, &rx[i].rspq));
|
||||
S3("u", "Intr pktcnt:",
|
||||
adap->sge.counter_val[rx[i].rspq.pktcnt_idx]);
|
||||
RL("RxAN:", stats.an);
|
||||
RL("RxNoMem:", stats.nomem);
|
||||
|
||||
} else if (ctrl_idx < ctrl_entries) {
|
||||
const struct sge_ctrl_txq *tx = &adap->sge.ctrlq[ctrl_idx * 4];
|
||||
int n = min(4, adap->params.nports - 4 * ctrl_idx);
|
||||
|
|
@ -2029,6 +2409,8 @@ do { \
|
|||
T("TxQ inuse:", q.in_use);
|
||||
T("TxQ CIDX:", q.cidx);
|
||||
T("TxQ PIDX:", q.pidx);
|
||||
TL("TxQFull:", q.stops);
|
||||
TL("TxQRestarts:", q.restarts);
|
||||
} else if (fq_idx == 0) {
|
||||
const struct sge_rspq *evtq = &adap->sge.fw_evtq;
|
||||
|
||||
|
|
@ -2044,10 +2426,14 @@ do { \
|
|||
adap->sge.counter_val[evtq->pktcnt_idx]);
|
||||
}
|
||||
#undef R
|
||||
#undef RL
|
||||
#undef T
|
||||
#undef TL
|
||||
#undef S
|
||||
#undef R3
|
||||
#undef T3
|
||||
#undef S3
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sge_queue_entries(const struct adapter *adap)
|
||||
|
|
@ -2164,6 +2550,73 @@ static const struct file_operations mem_debugfs_fops = {
|
|||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static int tid_info_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
struct adapter *adap = seq->private;
|
||||
const struct tid_info *t = &adap->tids;
|
||||
enum chip_type chip = CHELSIO_CHIP_VERSION(adap->params.chip);
|
||||
|
||||
if (t4_read_reg(adap, LE_DB_CONFIG_A) & HASHEN_F) {
|
||||
unsigned int sb;
|
||||
|
||||
if (chip <= CHELSIO_T5)
|
||||
sb = t4_read_reg(adap, LE_DB_SERVER_INDEX_A) / 4;
|
||||
else
|
||||
sb = t4_read_reg(adap, LE_DB_SRVR_START_INDEX_A);
|
||||
|
||||
if (sb) {
|
||||
seq_printf(seq, "TID range: 0..%u/%u..%u", sb - 1,
|
||||
adap->tids.hash_base,
|
||||
t->ntids - 1);
|
||||
seq_printf(seq, ", in use: %u/%u\n",
|
||||
atomic_read(&t->tids_in_use),
|
||||
atomic_read(&t->hash_tids_in_use));
|
||||
} else if (adap->flags & FW_OFLD_CONN) {
|
||||
seq_printf(seq, "TID range: %u..%u/%u..%u",
|
||||
t->aftid_base,
|
||||
t->aftid_end,
|
||||
adap->tids.hash_base,
|
||||
t->ntids - 1);
|
||||
seq_printf(seq, ", in use: %u/%u\n",
|
||||
atomic_read(&t->tids_in_use),
|
||||
atomic_read(&t->hash_tids_in_use));
|
||||
} else {
|
||||
seq_printf(seq, "TID range: %u..%u",
|
||||
adap->tids.hash_base,
|
||||
t->ntids - 1);
|
||||
seq_printf(seq, ", in use: %u\n",
|
||||
atomic_read(&t->hash_tids_in_use));
|
||||
}
|
||||
} else if (t->ntids) {
|
||||
seq_printf(seq, "TID range: 0..%u", t->ntids - 1);
|
||||
seq_printf(seq, ", in use: %u\n",
|
||||
atomic_read(&t->tids_in_use));
|
||||
}
|
||||
|
||||
if (t->nstids)
|
||||
seq_printf(seq, "STID range: %u..%u, in use: %u\n",
|
||||
(!t->stid_base &&
|
||||
(chip <= CHELSIO_T5)) ?
|
||||
t->stid_base + 1 : t->stid_base,
|
||||
t->stid_base + t->nstids - 1, t->stids_in_use);
|
||||
if (t->natids)
|
||||
seq_printf(seq, "ATID range: 0..%u, in use: %u\n",
|
||||
t->natids - 1, t->atids_in_use);
|
||||
seq_printf(seq, "FTID range: %u..%u\n", t->ftid_base,
|
||||
t->ftid_base + t->nftids - 1);
|
||||
if (t->nsftids)
|
||||
seq_printf(seq, "SFTID range: %u..%u in use: %u\n",
|
||||
t->sftid_base, t->sftid_base + t->nsftids - 2,
|
||||
t->sftids_in_use);
|
||||
if (t->ntids)
|
||||
seq_printf(seq, "HW TID usage: %u IP users, %u IPv6 users\n",
|
||||
t4_read_reg(adap, LE_DB_ACT_CNT_IPV4_A),
|
||||
t4_read_reg(adap, LE_DB_ACT_CNT_IPV6_A));
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_SIMPLE_DEBUGFS_FILE(tid_info);
|
||||
|
||||
static void add_debugfs_mem(struct adapter *adap, const char *name,
|
||||
unsigned int idx, unsigned int size_mb)
|
||||
{
|
||||
|
|
@ -2227,6 +2680,290 @@ static const struct file_operations blocked_fl_fops = {
|
|||
.llseek = generic_file_llseek,
|
||||
};
|
||||
|
||||
struct mem_desc {
|
||||
unsigned int base;
|
||||
unsigned int limit;
|
||||
unsigned int idx;
|
||||
};
|
||||
|
||||
static int mem_desc_cmp(const void *a, const void *b)
|
||||
{
|
||||
return ((const struct mem_desc *)a)->base -
|
||||
((const struct mem_desc *)b)->base;
|
||||
}
|
||||
|
||||
static void mem_region_show(struct seq_file *seq, const char *name,
|
||||
unsigned int from, unsigned int to)
|
||||
{
|
||||
char buf[40];
|
||||
|
||||
string_get_size((u64)to - from + 1, 1, STRING_UNITS_2, buf,
|
||||
sizeof(buf));
|
||||
seq_printf(seq, "%-15s %#x-%#x [%s]\n", name, from, to, buf);
|
||||
}
|
||||
|
||||
static int meminfo_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
static const char * const memory[] = { "EDC0:", "EDC1:", "MC:",
|
||||
"MC0:", "MC1:"};
|
||||
static const char * const region[] = {
|
||||
"DBQ contexts:", "IMSG contexts:", "FLM cache:", "TCBs:",
|
||||
"Pstructs:", "Timers:", "Rx FL:", "Tx FL:", "Pstruct FL:",
|
||||
"Tx payload:", "Rx payload:", "LE hash:", "iSCSI region:",
|
||||
"TDDP region:", "TPT region:", "STAG region:", "RQ region:",
|
||||
"RQUDP region:", "PBL region:", "TXPBL region:",
|
||||
"DBVFIFO region:", "ULPRX state:", "ULPTX state:",
|
||||
"On-chip queues:"
|
||||
};
|
||||
|
||||
int i, n;
|
||||
u32 lo, hi, used, alloc;
|
||||
struct mem_desc avail[4];
|
||||
struct mem_desc mem[ARRAY_SIZE(region) + 3]; /* up to 3 holes */
|
||||
struct mem_desc *md = mem;
|
||||
struct adapter *adap = seq->private;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mem); i++) {
|
||||
mem[i].limit = 0;
|
||||
mem[i].idx = i;
|
||||
}
|
||||
|
||||
/* Find and sort the populated memory ranges */
|
||||
i = 0;
|
||||
lo = t4_read_reg(adap, MA_TARGET_MEM_ENABLE_A);
|
||||
if (lo & EDRAM0_ENABLE_F) {
|
||||
hi = t4_read_reg(adap, MA_EDRAM0_BAR_A);
|
||||
avail[i].base = EDRAM0_BASE_G(hi) << 20;
|
||||
avail[i].limit = avail[i].base + (EDRAM0_SIZE_G(hi) << 20);
|
||||
avail[i].idx = 0;
|
||||
i++;
|
||||
}
|
||||
if (lo & EDRAM1_ENABLE_F) {
|
||||
hi = t4_read_reg(adap, MA_EDRAM1_BAR_A);
|
||||
avail[i].base = EDRAM1_BASE_G(hi) << 20;
|
||||
avail[i].limit = avail[i].base + (EDRAM1_SIZE_G(hi) << 20);
|
||||
avail[i].idx = 1;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (is_t5(adap->params.chip)) {
|
||||
if (lo & EXT_MEM0_ENABLE_F) {
|
||||
hi = t4_read_reg(adap, MA_EXT_MEMORY0_BAR_A);
|
||||
avail[i].base = EXT_MEM0_BASE_G(hi) << 20;
|
||||
avail[i].limit =
|
||||
avail[i].base + (EXT_MEM0_SIZE_G(hi) << 20);
|
||||
avail[i].idx = 3;
|
||||
i++;
|
||||
}
|
||||
if (lo & EXT_MEM1_ENABLE_F) {
|
||||
hi = t4_read_reg(adap, MA_EXT_MEMORY1_BAR_A);
|
||||
avail[i].base = EXT_MEM1_BASE_G(hi) << 20;
|
||||
avail[i].limit =
|
||||
avail[i].base + (EXT_MEM1_SIZE_G(hi) << 20);
|
||||
avail[i].idx = 4;
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
if (lo & EXT_MEM_ENABLE_F) {
|
||||
hi = t4_read_reg(adap, MA_EXT_MEMORY_BAR_A);
|
||||
avail[i].base = EXT_MEM_BASE_G(hi) << 20;
|
||||
avail[i].limit =
|
||||
avail[i].base + (EXT_MEM_SIZE_G(hi) << 20);
|
||||
avail[i].idx = 2;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (!i) /* no memory available */
|
||||
return 0;
|
||||
sort(avail, i, sizeof(struct mem_desc), mem_desc_cmp, NULL);
|
||||
|
||||
(md++)->base = t4_read_reg(adap, SGE_DBQ_CTXT_BADDR_A);
|
||||
(md++)->base = t4_read_reg(adap, SGE_IMSG_CTXT_BADDR_A);
|
||||
(md++)->base = t4_read_reg(adap, SGE_FLM_CACHE_BADDR_A);
|
||||
(md++)->base = t4_read_reg(adap, TP_CMM_TCB_BASE_A);
|
||||
(md++)->base = t4_read_reg(adap, TP_CMM_MM_BASE_A);
|
||||
(md++)->base = t4_read_reg(adap, TP_CMM_TIMER_BASE_A);
|
||||
(md++)->base = t4_read_reg(adap, TP_CMM_MM_RX_FLST_BASE_A);
|
||||
(md++)->base = t4_read_reg(adap, TP_CMM_MM_TX_FLST_BASE_A);
|
||||
(md++)->base = t4_read_reg(adap, TP_CMM_MM_PS_FLST_BASE_A);
|
||||
|
||||
/* the next few have explicit upper bounds */
|
||||
md->base = t4_read_reg(adap, TP_PMM_TX_BASE_A);
|
||||
md->limit = md->base - 1 +
|
||||
t4_read_reg(adap, TP_PMM_TX_PAGE_SIZE_A) *
|
||||
PMTXMAXPAGE_G(t4_read_reg(adap, TP_PMM_TX_MAX_PAGE_A));
|
||||
md++;
|
||||
|
||||
md->base = t4_read_reg(adap, TP_PMM_RX_BASE_A);
|
||||
md->limit = md->base - 1 +
|
||||
t4_read_reg(adap, TP_PMM_RX_PAGE_SIZE_A) *
|
||||
PMRXMAXPAGE_G(t4_read_reg(adap, TP_PMM_RX_MAX_PAGE_A));
|
||||
md++;
|
||||
|
||||
if (t4_read_reg(adap, LE_DB_CONFIG_A) & HASHEN_F) {
|
||||
if (CHELSIO_CHIP_VERSION(adap->params.chip) <= CHELSIO_T5) {
|
||||
hi = t4_read_reg(adap, LE_DB_TID_HASHBASE_A) / 4;
|
||||
md->base = t4_read_reg(adap, LE_DB_HASH_TID_BASE_A);
|
||||
} else {
|
||||
hi = t4_read_reg(adap, LE_DB_HASH_TID_BASE_A);
|
||||
md->base = t4_read_reg(adap,
|
||||
LE_DB_HASH_TBL_BASE_ADDR_A);
|
||||
}
|
||||
md->limit = 0;
|
||||
} else {
|
||||
md->base = 0;
|
||||
md->idx = ARRAY_SIZE(region); /* hide it */
|
||||
}
|
||||
md++;
|
||||
|
||||
#define ulp_region(reg) do { \
|
||||
md->base = t4_read_reg(adap, ULP_ ## reg ## _LLIMIT_A);\
|
||||
(md++)->limit = t4_read_reg(adap, ULP_ ## reg ## _ULIMIT_A); \
|
||||
} while (0)
|
||||
|
||||
ulp_region(RX_ISCSI);
|
||||
ulp_region(RX_TDDP);
|
||||
ulp_region(TX_TPT);
|
||||
ulp_region(RX_STAG);
|
||||
ulp_region(RX_RQ);
|
||||
ulp_region(RX_RQUDP);
|
||||
ulp_region(RX_PBL);
|
||||
ulp_region(TX_PBL);
|
||||
#undef ulp_region
|
||||
md->base = 0;
|
||||
md->idx = ARRAY_SIZE(region);
|
||||
if (!is_t4(adap->params.chip)) {
|
||||
u32 size = 0;
|
||||
u32 sge_ctrl = t4_read_reg(adap, SGE_CONTROL2_A);
|
||||
u32 fifo_size = t4_read_reg(adap, SGE_DBVFIFO_SIZE_A);
|
||||
|
||||
if (is_t5(adap->params.chip)) {
|
||||
if (sge_ctrl & VFIFO_ENABLE_F)
|
||||
size = DBVFIFO_SIZE_G(fifo_size);
|
||||
} else {
|
||||
size = T6_DBVFIFO_SIZE_G(fifo_size);
|
||||
}
|
||||
|
||||
if (size) {
|
||||
md->base = BASEADDR_G(t4_read_reg(adap,
|
||||
SGE_DBVFIFO_BADDR_A));
|
||||
md->limit = md->base + (size << 2) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
md++;
|
||||
|
||||
md->base = t4_read_reg(adap, ULP_RX_CTX_BASE_A);
|
||||
md->limit = 0;
|
||||
md++;
|
||||
md->base = t4_read_reg(adap, ULP_TX_ERR_TABLE_BASE_A);
|
||||
md->limit = 0;
|
||||
md++;
|
||||
|
||||
md->base = adap->vres.ocq.start;
|
||||
if (adap->vres.ocq.size)
|
||||
md->limit = md->base + adap->vres.ocq.size - 1;
|
||||
else
|
||||
md->idx = ARRAY_SIZE(region); /* hide it */
|
||||
md++;
|
||||
|
||||
/* add any address-space holes, there can be up to 3 */
|
||||
for (n = 0; n < i - 1; n++)
|
||||
if (avail[n].limit < avail[n + 1].base)
|
||||
(md++)->base = avail[n].limit;
|
||||
if (avail[n].limit)
|
||||
(md++)->base = avail[n].limit;
|
||||
|
||||
n = md - mem;
|
||||
sort(mem, n, sizeof(struct mem_desc), mem_desc_cmp, NULL);
|
||||
|
||||
for (lo = 0; lo < i; lo++)
|
||||
mem_region_show(seq, memory[avail[lo].idx], avail[lo].base,
|
||||
avail[lo].limit - 1);
|
||||
|
||||
seq_putc(seq, '\n');
|
||||
for (i = 0; i < n; i++) {
|
||||
if (mem[i].idx >= ARRAY_SIZE(region))
|
||||
continue; /* skip holes */
|
||||
if (!mem[i].limit)
|
||||
mem[i].limit = i < n - 1 ? mem[i + 1].base - 1 : ~0;
|
||||
mem_region_show(seq, region[mem[i].idx], mem[i].base,
|
||||
mem[i].limit);
|
||||
}
|
||||
|
||||
seq_putc(seq, '\n');
|
||||
lo = t4_read_reg(adap, CIM_SDRAM_BASE_ADDR_A);
|
||||
hi = t4_read_reg(adap, CIM_SDRAM_ADDR_SIZE_A) + lo - 1;
|
||||
mem_region_show(seq, "uP RAM:", lo, hi);
|
||||
|
||||
lo = t4_read_reg(adap, CIM_EXTMEM2_BASE_ADDR_A);
|
||||
hi = t4_read_reg(adap, CIM_EXTMEM2_ADDR_SIZE_A) + lo - 1;
|
||||
mem_region_show(seq, "uP Extmem2:", lo, hi);
|
||||
|
||||
lo = t4_read_reg(adap, TP_PMM_RX_MAX_PAGE_A);
|
||||
seq_printf(seq, "\n%u Rx pages of size %uKiB for %u channels\n",
|
||||
PMRXMAXPAGE_G(lo),
|
||||
t4_read_reg(adap, TP_PMM_RX_PAGE_SIZE_A) >> 10,
|
||||
(lo & PMRXNUMCHN_F) ? 2 : 1);
|
||||
|
||||
lo = t4_read_reg(adap, TP_PMM_TX_MAX_PAGE_A);
|
||||
hi = t4_read_reg(adap, TP_PMM_TX_PAGE_SIZE_A);
|
||||
seq_printf(seq, "%u Tx pages of size %u%ciB for %u channels\n",
|
||||
PMTXMAXPAGE_G(lo),
|
||||
hi >= (1 << 20) ? (hi >> 20) : (hi >> 10),
|
||||
hi >= (1 << 20) ? 'M' : 'K', 1 << PMTXNUMCHN_G(lo));
|
||||
seq_printf(seq, "%u p-structs\n\n",
|
||||
t4_read_reg(adap, TP_CMM_MM_MAX_PSTRUCT_A));
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (CHELSIO_CHIP_VERSION(adap->params.chip) > CHELSIO_T5)
|
||||
lo = t4_read_reg(adap, MPS_RX_MAC_BG_PG_CNT0_A + i * 4);
|
||||
else
|
||||
lo = t4_read_reg(adap, MPS_RX_PG_RSV0_A + i * 4);
|
||||
if (is_t5(adap->params.chip)) {
|
||||
used = T5_USED_G(lo);
|
||||
alloc = T5_ALLOC_G(lo);
|
||||
} else {
|
||||
used = USED_G(lo);
|
||||
alloc = ALLOC_G(lo);
|
||||
}
|
||||
/* For T6 these are MAC buffer groups */
|
||||
seq_printf(seq, "Port %d using %u pages out of %u allocated\n",
|
||||
i, used, alloc);
|
||||
}
|
||||
for (i = 0; i < adap->params.arch.nchan; i++) {
|
||||
if (CHELSIO_CHIP_VERSION(adap->params.chip) > CHELSIO_T5)
|
||||
lo = t4_read_reg(adap,
|
||||
MPS_RX_LPBK_BG_PG_CNT0_A + i * 4);
|
||||
else
|
||||
lo = t4_read_reg(adap, MPS_RX_PG_RSV4_A + i * 4);
|
||||
if (is_t5(adap->params.chip)) {
|
||||
used = T5_USED_G(lo);
|
||||
alloc = T5_ALLOC_G(lo);
|
||||
} else {
|
||||
used = USED_G(lo);
|
||||
alloc = ALLOC_G(lo);
|
||||
}
|
||||
/* For T6 these are MAC buffer groups */
|
||||
seq_printf(seq,
|
||||
"Loopback %d using %u pages out of %u allocated\n",
|
||||
i, used, alloc);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int meminfo_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, meminfo_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations meminfo_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = meminfo_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
/* Add an array of Debug FS files.
|
||||
*/
|
||||
void add_debugfs_files(struct adapter *adap,
|
||||
|
|
@ -2264,6 +3001,10 @@ int t4_setup_debugfs(struct adapter *adap)
|
|||
{ "mbox5", &mbox_debugfs_fops, S_IRUSR | S_IWUSR, 5 },
|
||||
{ "mbox6", &mbox_debugfs_fops, S_IRUSR | S_IWUSR, 6 },
|
||||
{ "mbox7", &mbox_debugfs_fops, S_IRUSR | S_IWUSR, 7 },
|
||||
{ "trace0", &mps_trc_debugfs_fops, S_IRUSR | S_IWUSR, 0 },
|
||||
{ "trace1", &mps_trc_debugfs_fops, S_IRUSR | S_IWUSR, 1 },
|
||||
{ "trace2", &mps_trc_debugfs_fops, S_IRUSR | S_IWUSR, 2 },
|
||||
{ "trace3", &mps_trc_debugfs_fops, S_IRUSR | S_IWUSR, 3 },
|
||||
{ "l2t", &t4_l2t_fops, S_IRUSR, 0},
|
||||
{ "mps_tcam", &mps_tcam_debugfs_fops, S_IRUSR, 0 },
|
||||
{ "rss", &rss_debugfs_fops, S_IRUSR, 0 },
|
||||
|
|
@ -2293,7 +3034,9 @@ int t4_setup_debugfs(struct adapter *adap)
|
|||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
{ "clip_tbl", &clip_tbl_debugfs_fops, S_IRUSR, 0 },
|
||||
#endif
|
||||
{ "tids", &tid_info_debugfs_fops, S_IRUSR, 0},
|
||||
{ "blocked_fl", &blocked_fl_fops, S_IRUSR | S_IWUSR, 0 },
|
||||
{ "meminfo", &meminfo_fops, S_IRUSR, 0 },
|
||||
};
|
||||
|
||||
/* Debug FS nodes common to all T5 and later adapters.
|
||||
|
|
@ -2341,6 +3084,10 @@ int t4_setup_debugfs(struct adapter *adap)
|
|||
|
||||
de = debugfs_create_file_size("flash", S_IRUSR, adap->debugfs_root, adap,
|
||||
&flash_debugfs_fops, adap->params.sf_size);
|
||||
debugfs_create_bool("use_backdoor", S_IWUSR | S_IRUSR,
|
||||
adap->debugfs_root, &adap->use_bd);
|
||||
debugfs_create_bool("trace_rss", S_IWUSR | S_IRUSR,
|
||||
adap->debugfs_root, &adap->trace_rss);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -925,6 +925,20 @@ static int set_flash(struct net_device *netdev, struct ethtool_flash *ef)
|
|||
const struct firmware *fw;
|
||||
struct adapter *adap = netdev2adap(netdev);
|
||||
unsigned int mbox = PCIE_FW_MASTER_M + 1;
|
||||
u32 pcie_fw;
|
||||
unsigned int master;
|
||||
u8 master_vld = 0;
|
||||
|
||||
pcie_fw = t4_read_reg(adap, PCIE_FW_A);
|
||||
master = PCIE_FW_MASTER_G(pcie_fw);
|
||||
if (pcie_fw & PCIE_FW_MASTER_VLD_F)
|
||||
master_vld = 1;
|
||||
/* if csiostor is the master return */
|
||||
if (master_vld && (master != adap->pf)) {
|
||||
dev_warn(adap->pdev_dev,
|
||||
"cxgb4 driver needs to be loaded as MASTER to support FW flash\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
ef->data[sizeof(ef->data) - 1] = '\0';
|
||||
ret = request_firmware(&fw, ef->data, adap->pdev_dev);
|
||||
|
|
|
|||
|
|
@ -1548,7 +1548,7 @@ int cxgb4_alloc_sftid(struct tid_info *t, int family, void *data)
|
|||
t->stid_tab[stid].data = data;
|
||||
stid -= t->nstids;
|
||||
stid += t->sftid_base;
|
||||
t->stids_in_use++;
|
||||
t->sftids_in_use++;
|
||||
}
|
||||
spin_unlock_bh(&t->stid_lock);
|
||||
return stid;
|
||||
|
|
@ -1573,10 +1573,14 @@ void cxgb4_free_stid(struct tid_info *t, unsigned int stid, int family)
|
|||
else
|
||||
bitmap_release_region(t->stid_bmap, stid, 2);
|
||||
t->stid_tab[stid].data = NULL;
|
||||
if (family == PF_INET)
|
||||
t->stids_in_use--;
|
||||
else
|
||||
t->stids_in_use -= 4;
|
||||
if (stid < t->nstids) {
|
||||
if (family == PF_INET)
|
||||
t->stids_in_use--;
|
||||
else
|
||||
t->stids_in_use -= 4;
|
||||
} else {
|
||||
t->sftids_in_use--;
|
||||
}
|
||||
spin_unlock_bh(&t->stid_lock);
|
||||
}
|
||||
EXPORT_SYMBOL(cxgb4_free_stid);
|
||||
|
|
@ -1654,20 +1658,25 @@ static void process_tid_release_list(struct work_struct *work)
|
|||
*/
|
||||
void cxgb4_remove_tid(struct tid_info *t, unsigned int chan, unsigned int tid)
|
||||
{
|
||||
void *old;
|
||||
struct sk_buff *skb;
|
||||
struct adapter *adap = container_of(t, struct adapter, tids);
|
||||
|
||||
old = t->tid_tab[tid];
|
||||
WARN_ON(tid >= t->ntids);
|
||||
|
||||
if (t->tid_tab[tid]) {
|
||||
t->tid_tab[tid] = NULL;
|
||||
if (t->hash_base && (tid >= t->hash_base))
|
||||
atomic_dec(&t->hash_tids_in_use);
|
||||
else
|
||||
atomic_dec(&t->tids_in_use);
|
||||
}
|
||||
|
||||
skb = alloc_skb(sizeof(struct cpl_tid_release), GFP_ATOMIC);
|
||||
if (likely(skb)) {
|
||||
t->tid_tab[tid] = NULL;
|
||||
mk_tid_release(skb, chan, tid);
|
||||
t4_ofld_send(adap, skb);
|
||||
} else
|
||||
cxgb4_queue_tid_release(t, chan, tid);
|
||||
if (old)
|
||||
atomic_dec(&t->tids_in_use);
|
||||
}
|
||||
EXPORT_SYMBOL(cxgb4_remove_tid);
|
||||
|
||||
|
|
@ -1702,9 +1711,11 @@ static int tid_init(struct tid_info *t)
|
|||
spin_lock_init(&t->atid_lock);
|
||||
|
||||
t->stids_in_use = 0;
|
||||
t->sftids_in_use = 0;
|
||||
t->afree = NULL;
|
||||
t->atids_in_use = 0;
|
||||
atomic_set(&t->tids_in_use, 0);
|
||||
atomic_set(&t->hash_tids_in_use, 0);
|
||||
|
||||
/* Setup the free list for atid_tab and clear the stid bitmap. */
|
||||
if (natids) {
|
||||
|
|
@ -3657,6 +3668,10 @@ static int adap_init0(struct adapter *adap)
|
|||
*/
|
||||
t4_get_fw_version(adap, &adap->params.fw_vers);
|
||||
t4_get_tp_version(adap, &adap->params.tp_vers);
|
||||
ret = t4_check_fw_version(adap);
|
||||
/* If firmware is too old (not supported by driver) force an update. */
|
||||
if (ret == -EFAULT)
|
||||
state = DEV_STATE_UNINIT;
|
||||
if ((adap->flags & MASTER_PF) && state != DEV_STATE_INIT) {
|
||||
struct fw_info *fw_info;
|
||||
struct fw_hdr *card_fw;
|
||||
|
|
@ -4551,6 +4566,32 @@ static void free_some_resources(struct adapter *adapter)
|
|||
NETIF_F_IPV6_CSUM | NETIF_F_HIGHDMA)
|
||||
#define SEGMENT_SIZE 128
|
||||
|
||||
static int get_chip_type(struct pci_dev *pdev, u32 pl_rev)
|
||||
{
|
||||
int ver, chip;
|
||||
u16 device_id;
|
||||
|
||||
/* Retrieve adapter's device ID */
|
||||
pci_read_config_word(pdev, PCI_DEVICE_ID, &device_id);
|
||||
ver = device_id >> 12;
|
||||
switch (ver) {
|
||||
case CHELSIO_T4:
|
||||
chip |= CHELSIO_CHIP_CODE(CHELSIO_T4, pl_rev);
|
||||
break;
|
||||
case CHELSIO_T5:
|
||||
chip |= CHELSIO_CHIP_CODE(CHELSIO_T5, pl_rev);
|
||||
break;
|
||||
case CHELSIO_T6:
|
||||
chip |= CHELSIO_CHIP_CODE(CHELSIO_T6, pl_rev);
|
||||
break;
|
||||
default:
|
||||
dev_err(&pdev->dev, "Device %d is not supported\n",
|
||||
device_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
return chip;
|
||||
}
|
||||
|
||||
static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
{
|
||||
int func, i, err, s_qpp, qpp, num_seg;
|
||||
|
|
@ -4558,6 +4599,8 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
bool highdma = false;
|
||||
struct adapter *adapter = NULL;
|
||||
void __iomem *regs;
|
||||
u32 whoami, pl_rev;
|
||||
enum chip_type chip;
|
||||
|
||||
printk_once(KERN_INFO "%s - version %s\n", DRV_DESC, DRV_VERSION);
|
||||
|
||||
|
|
@ -4586,7 +4629,11 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
goto out_unmap_bar0;
|
||||
|
||||
/* We control everything through one PF */
|
||||
func = SOURCEPF_G(readl(regs + PL_WHOAMI_A));
|
||||
whoami = readl(regs + PL_WHOAMI_A);
|
||||
pl_rev = REV_G(readl(regs + PL_REV_A));
|
||||
chip = get_chip_type(pdev, pl_rev);
|
||||
func = CHELSIO_CHIP_VERSION(chip) <= CHELSIO_T5 ?
|
||||
SOURCEPF_G(whoami) : T6_SOURCEPF_G(whoami);
|
||||
if (func != ent->driver_data) {
|
||||
iounmap(regs);
|
||||
pci_disable_device(pdev);
|
||||
|
|
@ -4757,7 +4804,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
*/
|
||||
cfg_queues(adapter);
|
||||
|
||||
adapter->l2t = t4_init_l2t();
|
||||
adapter->l2t = t4_init_l2t(adapter->l2t_start, adapter->l2t_end);
|
||||
if (!adapter->l2t) {
|
||||
/* We tolerate a lack of L2T, giving up some functionality */
|
||||
dev_warn(&pdev->dev, "could not allocate L2T, continuing\n");
|
||||
|
|
@ -4782,6 +4829,22 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
adapter->params.offload = 0;
|
||||
}
|
||||
|
||||
if (is_offload(adapter)) {
|
||||
if (t4_read_reg(adapter, LE_DB_CONFIG_A) & HASHEN_F) {
|
||||
u32 hash_base, hash_reg;
|
||||
|
||||
if (chip <= CHELSIO_T5) {
|
||||
hash_reg = LE_DB_TID_HASHBASE_A;
|
||||
hash_base = t4_read_reg(adapter, hash_reg);
|
||||
adapter->tids.hash_base = hash_base / 4;
|
||||
} else {
|
||||
hash_reg = T6_LE_DB_HASH_TID_BASE_A;
|
||||
hash_base = t4_read_reg(adapter, hash_reg);
|
||||
adapter->tids.hash_base = hash_base;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* See what interrupts we'll be using */
|
||||
if (msi > 1 && enable_msix(adapter) == 0)
|
||||
adapter->flags |= USING_MSIX;
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@ struct tid_info {
|
|||
unsigned long *stid_bmap;
|
||||
unsigned int nstids;
|
||||
unsigned int stid_base;
|
||||
unsigned int hash_base;
|
||||
|
||||
union aopen_entry *atid_tab;
|
||||
unsigned int natids;
|
||||
|
|
@ -116,8 +117,12 @@ struct tid_info {
|
|||
|
||||
spinlock_t stid_lock;
|
||||
unsigned int stids_in_use;
|
||||
unsigned int sftids_in_use;
|
||||
|
||||
/* TIDs in the TCAM */
|
||||
atomic_t tids_in_use;
|
||||
/* TIDs in the HASH */
|
||||
atomic_t hash_tids_in_use;
|
||||
};
|
||||
|
||||
static inline void *lookup_tid(const struct tid_info *t, unsigned int tid)
|
||||
|
|
@ -147,7 +152,10 @@ static inline void cxgb4_insert_tid(struct tid_info *t, void *data,
|
|||
unsigned int tid)
|
||||
{
|
||||
t->tid_tab[tid] = data;
|
||||
atomic_inc(&t->tids_in_use);
|
||||
if (t->hash_base && (tid >= t->hash_base))
|
||||
atomic_inc(&t->hash_tids_in_use);
|
||||
else
|
||||
atomic_inc(&t->tids_in_use);
|
||||
}
|
||||
|
||||
int cxgb4_alloc_atid(struct tid_info *t, void *data);
|
||||
|
|
|
|||
|
|
@ -51,24 +51,17 @@
|
|||
#define VLAN_NONE 0xfff
|
||||
|
||||
/* identifies sync vs async L2T_WRITE_REQs */
|
||||
#define F_SYNC_WR (1 << 12)
|
||||
|
||||
enum {
|
||||
L2T_STATE_VALID, /* entry is up to date */
|
||||
L2T_STATE_STALE, /* entry may be used but needs revalidation */
|
||||
L2T_STATE_RESOLVING, /* entry needs address resolution */
|
||||
L2T_STATE_SYNC_WRITE, /* synchronous write of entry underway */
|
||||
|
||||
/* when state is one of the below the entry is not hashed */
|
||||
L2T_STATE_SWITCHING, /* entry is being used by a switching filter */
|
||||
L2T_STATE_UNUSED /* entry not in use */
|
||||
};
|
||||
#define SYNC_WR_S 12
|
||||
#define SYNC_WR_V(x) ((x) << SYNC_WR_S)
|
||||
#define SYNC_WR_F SYNC_WR_V(1)
|
||||
|
||||
struct l2t_data {
|
||||
unsigned int l2t_start; /* start index of our piece of the L2T */
|
||||
unsigned int l2t_size; /* number of entries in l2tab */
|
||||
rwlock_t lock;
|
||||
atomic_t nfree; /* number of free entries */
|
||||
struct l2t_entry *rover; /* starting point for next allocation */
|
||||
struct l2t_entry l2tab[L2T_SIZE];
|
||||
struct l2t_entry l2tab[0]; /* MUST BE LAST */
|
||||
};
|
||||
|
||||
static inline unsigned int vlan_prio(const struct l2t_entry *e)
|
||||
|
|
@ -85,29 +78,36 @@ static inline void l2t_hold(struct l2t_data *d, struct l2t_entry *e)
|
|||
/*
|
||||
* To avoid having to check address families we do not allow v4 and v6
|
||||
* neighbors to be on the same hash chain. We keep v4 entries in the first
|
||||
* half of available hash buckets and v6 in the second.
|
||||
* half of available hash buckets and v6 in the second. We need at least two
|
||||
* entries in our L2T for this scheme to work.
|
||||
*/
|
||||
enum {
|
||||
L2T_SZ_HALF = L2T_SIZE / 2,
|
||||
L2T_HASH_MASK = L2T_SZ_HALF - 1
|
||||
L2T_MIN_HASH_BUCKETS = 2,
|
||||
};
|
||||
|
||||
static inline unsigned int arp_hash(const u32 *key, int ifindex)
|
||||
static inline unsigned int arp_hash(struct l2t_data *d, const u32 *key,
|
||||
int ifindex)
|
||||
{
|
||||
return jhash_2words(*key, ifindex, 0) & L2T_HASH_MASK;
|
||||
unsigned int l2t_size_half = d->l2t_size / 2;
|
||||
|
||||
return jhash_2words(*key, ifindex, 0) % l2t_size_half;
|
||||
}
|
||||
|
||||
static inline unsigned int ipv6_hash(const u32 *key, int ifindex)
|
||||
static inline unsigned int ipv6_hash(struct l2t_data *d, const u32 *key,
|
||||
int ifindex)
|
||||
{
|
||||
unsigned int l2t_size_half = d->l2t_size / 2;
|
||||
u32 xor = key[0] ^ key[1] ^ key[2] ^ key[3];
|
||||
|
||||
return L2T_SZ_HALF + (jhash_2words(xor, ifindex, 0) & L2T_HASH_MASK);
|
||||
return (l2t_size_half +
|
||||
(jhash_2words(xor, ifindex, 0) % l2t_size_half));
|
||||
}
|
||||
|
||||
static unsigned int addr_hash(const u32 *addr, int addr_len, int ifindex)
|
||||
static unsigned int addr_hash(struct l2t_data *d, const u32 *addr,
|
||||
int addr_len, int ifindex)
|
||||
{
|
||||
return addr_len == 4 ? arp_hash(addr, ifindex) :
|
||||
ipv6_hash(addr, ifindex);
|
||||
return addr_len == 4 ? arp_hash(d, addr, ifindex) :
|
||||
ipv6_hash(d, addr, ifindex);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -139,6 +139,8 @@ static void neigh_replace(struct l2t_entry *e, struct neighbour *n)
|
|||
*/
|
||||
static int write_l2e(struct adapter *adap, struct l2t_entry *e, int sync)
|
||||
{
|
||||
struct l2t_data *d = adap->l2t;
|
||||
unsigned int l2t_idx = e->idx + d->l2t_start;
|
||||
struct sk_buff *skb;
|
||||
struct cpl_l2t_write_req *req;
|
||||
|
||||
|
|
@ -150,10 +152,10 @@ static int write_l2e(struct adapter *adap, struct l2t_entry *e, int sync)
|
|||
INIT_TP_WR(req, 0);
|
||||
|
||||
OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_L2T_WRITE_REQ,
|
||||
e->idx | (sync ? F_SYNC_WR : 0) |
|
||||
l2t_idx | (sync ? SYNC_WR_F : 0) |
|
||||
TID_QID_V(adap->sge.fw_evtq.abs_id)));
|
||||
req->params = htons(L2T_W_PORT_V(e->lport) | L2T_W_NOREPLY_V(!sync));
|
||||
req->l2t_idx = htons(e->idx);
|
||||
req->l2t_idx = htons(l2t_idx);
|
||||
req->vlan = htons(e->vlan);
|
||||
if (e->neigh && !(e->neigh->dev->flags & IFF_LOOPBACK))
|
||||
memcpy(e->dmac, e->neigh->ha, sizeof(e->dmac));
|
||||
|
|
@ -190,18 +192,19 @@ static void send_pending(struct adapter *adap, struct l2t_entry *e)
|
|||
*/
|
||||
void do_l2t_write_rpl(struct adapter *adap, const struct cpl_l2t_write_rpl *rpl)
|
||||
{
|
||||
struct l2t_data *d = adap->l2t;
|
||||
unsigned int tid = GET_TID(rpl);
|
||||
unsigned int idx = tid & (L2T_SIZE - 1);
|
||||
unsigned int l2t_idx = tid % L2T_SIZE;
|
||||
|
||||
if (unlikely(rpl->status != CPL_ERR_NONE)) {
|
||||
dev_err(adap->pdev_dev,
|
||||
"Unexpected L2T_WRITE_RPL status %u for entry %u\n",
|
||||
rpl->status, idx);
|
||||
rpl->status, l2t_idx);
|
||||
return;
|
||||
}
|
||||
|
||||
if (tid & F_SYNC_WR) {
|
||||
struct l2t_entry *e = &adap->l2t->l2tab[idx];
|
||||
if (tid & SYNC_WR_F) {
|
||||
struct l2t_entry *e = &d->l2tab[l2t_idx - d->l2t_start];
|
||||
|
||||
spin_lock(&e->lock);
|
||||
if (e->state != L2T_STATE_SWITCHING) {
|
||||
|
|
@ -276,7 +279,7 @@ static struct l2t_entry *alloc_l2e(struct l2t_data *d)
|
|||
return NULL;
|
||||
|
||||
/* there's definitely a free entry */
|
||||
for (e = d->rover, end = &d->l2tab[L2T_SIZE]; e != end; ++e)
|
||||
for (e = d->rover, end = &d->l2tab[d->l2t_size]; e != end; ++e)
|
||||
if (atomic_read(&e->refcnt) == 0)
|
||||
goto found;
|
||||
|
||||
|
|
@ -368,7 +371,7 @@ struct l2t_entry *cxgb4_l2t_get(struct l2t_data *d, struct neighbour *neigh,
|
|||
int addr_len = neigh->tbl->key_len;
|
||||
u32 *addr = (u32 *)neigh->primary_key;
|
||||
int ifidx = neigh->dev->ifindex;
|
||||
int hash = addr_hash(addr, addr_len, ifidx);
|
||||
int hash = addr_hash(d, addr, addr_len, ifidx);
|
||||
|
||||
if (neigh->dev->flags & IFF_LOOPBACK)
|
||||
lport = netdev2pinfo(physdev)->tx_chan + 4;
|
||||
|
|
@ -481,7 +484,7 @@ void t4_l2t_update(struct adapter *adap, struct neighbour *neigh)
|
|||
int addr_len = neigh->tbl->key_len;
|
||||
u32 *addr = (u32 *) neigh->primary_key;
|
||||
int ifidx = neigh->dev->ifindex;
|
||||
int hash = addr_hash(addr, addr_len, ifidx);
|
||||
int hash = addr_hash(d, addr, addr_len, ifidx);
|
||||
|
||||
read_lock_bh(&d->lock);
|
||||
for (e = d->l2tab[hash].first; e; e = e->next)
|
||||
|
|
@ -554,20 +557,30 @@ int t4_l2t_set_switching(struct adapter *adap, struct l2t_entry *e, u16 vlan,
|
|||
return write_l2e(adap, e, 0);
|
||||
}
|
||||
|
||||
struct l2t_data *t4_init_l2t(void)
|
||||
struct l2t_data *t4_init_l2t(unsigned int l2t_start, unsigned int l2t_end)
|
||||
{
|
||||
unsigned int l2t_size;
|
||||
int i;
|
||||
struct l2t_data *d;
|
||||
|
||||
d = t4_alloc_mem(sizeof(*d));
|
||||
if (l2t_start >= l2t_end || l2t_end >= L2T_SIZE)
|
||||
return NULL;
|
||||
l2t_size = l2t_end - l2t_start + 1;
|
||||
if (l2t_size < L2T_MIN_HASH_BUCKETS)
|
||||
return NULL;
|
||||
|
||||
d = t4_alloc_mem(sizeof(*d) + l2t_size * sizeof(struct l2t_entry));
|
||||
if (!d)
|
||||
return NULL;
|
||||
|
||||
d->l2t_start = l2t_start;
|
||||
d->l2t_size = l2t_size;
|
||||
|
||||
d->rover = d->l2tab;
|
||||
atomic_set(&d->nfree, L2T_SIZE);
|
||||
atomic_set(&d->nfree, l2t_size);
|
||||
rwlock_init(&d->lock);
|
||||
|
||||
for (i = 0; i < L2T_SIZE; ++i) {
|
||||
for (i = 0; i < d->l2t_size; ++i) {
|
||||
d->l2tab[i].idx = i;
|
||||
d->l2tab[i].state = L2T_STATE_UNUSED;
|
||||
spin_lock_init(&d->l2tab[i].lock);
|
||||
|
|
@ -578,9 +591,9 @@ struct l2t_data *t4_init_l2t(void)
|
|||
|
||||
static inline void *l2t_get_idx(struct seq_file *seq, loff_t pos)
|
||||
{
|
||||
struct l2t_entry *l2tab = seq->private;
|
||||
struct l2t_data *d = seq->private;
|
||||
|
||||
return pos >= L2T_SIZE ? NULL : &l2tab[pos];
|
||||
return pos >= d->l2t_size ? NULL : &d->l2tab[pos];
|
||||
}
|
||||
|
||||
static void *l2t_seq_start(struct seq_file *seq, loff_t *pos)
|
||||
|
|
@ -620,6 +633,7 @@ static int l2t_seq_show(struct seq_file *seq, void *v)
|
|||
"Ethernet address VLAN/P LP State Users Port\n");
|
||||
else {
|
||||
char ip[60];
|
||||
struct l2t_data *d = seq->private;
|
||||
struct l2t_entry *e = v;
|
||||
|
||||
spin_lock_bh(&e->lock);
|
||||
|
|
@ -628,7 +642,7 @@ static int l2t_seq_show(struct seq_file *seq, void *v)
|
|||
else
|
||||
sprintf(ip, e->v6 ? "%pI6c" : "%pI4", e->addr);
|
||||
seq_printf(seq, "%4u %-25s %17pM %4d %u %2u %c %5u %s\n",
|
||||
e->idx, ip, e->dmac,
|
||||
e->idx + d->l2t_start, ip, e->dmac,
|
||||
e->vlan & VLAN_VID_MASK, vlan_prio(e), e->lport,
|
||||
l2e_state(e), atomic_read(&e->refcnt),
|
||||
e->neigh ? e->neigh->dev->name : "");
|
||||
|
|
@ -652,7 +666,7 @@ static int l2t_seq_open(struct inode *inode, struct file *file)
|
|||
struct adapter *adap = inode->i_private;
|
||||
struct seq_file *seq = file->private_data;
|
||||
|
||||
seq->private = adap->l2t->l2tab;
|
||||
seq->private = adap->l2t;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,20 @@
|
|||
#include <linux/if_ether.h>
|
||||
#include <linux/atomic.h>
|
||||
|
||||
enum { L2T_SIZE = 4096 }; /* # of L2T entries */
|
||||
|
||||
enum {
|
||||
L2T_STATE_VALID, /* entry is up to date */
|
||||
L2T_STATE_STALE, /* entry may be used but needs revalidation */
|
||||
L2T_STATE_RESOLVING, /* entry needs address resolution */
|
||||
L2T_STATE_SYNC_WRITE, /* synchronous write of entry underway */
|
||||
L2T_STATE_NOARP, /* Netdev down or removed*/
|
||||
|
||||
/* when state is one of the below the entry is not hashed */
|
||||
L2T_STATE_SWITCHING, /* entry is being used by a switching filter */
|
||||
L2T_STATE_UNUSED /* entry not in use */
|
||||
};
|
||||
|
||||
struct adapter;
|
||||
struct l2t_data;
|
||||
struct neighbour;
|
||||
|
|
@ -56,7 +70,7 @@ struct cpl_l2t_write_rpl;
|
|||
*/
|
||||
struct l2t_entry {
|
||||
u16 state; /* entry state */
|
||||
u16 idx; /* entry index */
|
||||
u16 idx; /* entry index within in-memory table */
|
||||
u32 addr[4]; /* next hop IP or IPv6 address */
|
||||
int ifindex; /* neighbor's net_device's ifindex */
|
||||
struct neighbour *neigh; /* associated neighbour */
|
||||
|
|
@ -104,7 +118,7 @@ void t4_l2t_update(struct adapter *adap, struct neighbour *neigh);
|
|||
struct l2t_entry *t4_l2t_alloc_switching(struct l2t_data *d);
|
||||
int t4_l2t_set_switching(struct adapter *adap, struct l2t_entry *e, u16 vlan,
|
||||
u8 port, u8 *eth_addr);
|
||||
struct l2t_data *t4_init_l2t(void);
|
||||
struct l2t_data *t4_init_l2t(unsigned int l2t_start, unsigned int l2t_end);
|
||||
void do_l2t_write_rpl(struct adapter *p, const struct cpl_l2t_write_rpl *rpl);
|
||||
|
||||
extern const struct file_operations t4_l2t_fops;
|
||||
|
|
|
|||
|
|
@ -1137,7 +1137,7 @@ cxgb_fcoe_offload(struct sk_buff *skb, struct adapter *adap,
|
|||
*/
|
||||
netdev_tx_t t4_eth_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
u32 wr_mid;
|
||||
u32 wr_mid, ctrl0;
|
||||
u64 cntrl, *end;
|
||||
int qidx, credits;
|
||||
unsigned int flits, ndesc;
|
||||
|
|
@ -1274,9 +1274,15 @@ out_free: dev_kfree_skb_any(skb);
|
|||
#endif /* CONFIG_CHELSIO_T4_FCOE */
|
||||
}
|
||||
|
||||
cpl->ctrl0 = htonl(TXPKT_OPCODE_V(CPL_TX_PKT_XT) |
|
||||
TXPKT_INTF_V(pi->tx_chan) |
|
||||
TXPKT_PF_V(adap->pf));
|
||||
ctrl0 = TXPKT_OPCODE_V(CPL_TX_PKT_XT) | TXPKT_INTF_V(pi->tx_chan) |
|
||||
TXPKT_PF_V(adap->pf);
|
||||
#ifdef CONFIG_CHELSIO_T4_DCB
|
||||
if (is_t4(adap->params.chip))
|
||||
ctrl0 |= TXPKT_OVLAN_IDX_V(q->dcb_prio);
|
||||
else
|
||||
ctrl0 |= TXPKT_T5_OVLAN_IDX_V(q->dcb_prio);
|
||||
#endif
|
||||
cpl->ctrl0 = htonl(ctrl0);
|
||||
cpl->pack = htons(0);
|
||||
cpl->len = htons(skb->len);
|
||||
cpl->ctrl1 = cpu_to_be64(cntrl);
|
||||
|
|
@ -1418,18 +1424,17 @@ static void restart_ctrlq(unsigned long data)
|
|||
struct fw_wr_hdr *wr;
|
||||
unsigned int ndesc = skb->priority; /* previously saved */
|
||||
|
||||
/*
|
||||
* Write descriptors and free skbs outside the lock to limit
|
||||
written += ndesc;
|
||||
/* Write descriptors and free skbs outside the lock to limit
|
||||
* wait times. q->full is still set so new skbs will be queued.
|
||||
*/
|
||||
wr = (struct fw_wr_hdr *)&q->q.desc[q->q.pidx];
|
||||
txq_advance(&q->q, ndesc);
|
||||
spin_unlock(&q->sendq.lock);
|
||||
|
||||
wr = (struct fw_wr_hdr *)&q->q.desc[q->q.pidx];
|
||||
inline_tx_skb(skb, &q->q, wr);
|
||||
kfree_skb(skb);
|
||||
|
||||
written += ndesc;
|
||||
txq_advance(&q->q, ndesc);
|
||||
if (unlikely(txq_avail(&q->q) < TXQ_STOP_THRES)) {
|
||||
unsigned long old = q->q.stops;
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#include "t4_regs.h"
|
||||
#include "t4_values.h"
|
||||
#include "t4fw_api.h"
|
||||
#include "t4fw_version.h"
|
||||
|
||||
/**
|
||||
* t4_wait_op_done_val - wait until an operation is completed
|
||||
|
|
@ -345,6 +346,43 @@ int t4_wr_mbox_meat(struct adapter *adap, int mbox, const void *cmd, int size,
|
|||
FW_CMD_MAX_TIMEOUT);
|
||||
}
|
||||
|
||||
static int t4_edc_err_read(struct adapter *adap, int idx)
|
||||
{
|
||||
u32 edc_ecc_err_addr_reg;
|
||||
u32 rdata_reg;
|
||||
|
||||
if (is_t4(adap->params.chip)) {
|
||||
CH_WARN(adap, "%s: T4 NOT supported.\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
if (idx != 0 && idx != 1) {
|
||||
CH_WARN(adap, "%s: idx %d NOT supported.\n", __func__, idx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
edc_ecc_err_addr_reg = EDC_T5_REG(EDC_H_ECC_ERR_ADDR_A, idx);
|
||||
rdata_reg = EDC_T5_REG(EDC_H_BIST_STATUS_RDATA_A, idx);
|
||||
|
||||
CH_WARN(adap,
|
||||
"edc%d err addr 0x%x: 0x%x.\n",
|
||||
idx, edc_ecc_err_addr_reg,
|
||||
t4_read_reg(adap, edc_ecc_err_addr_reg));
|
||||
CH_WARN(adap,
|
||||
"bist: 0x%x, status %llx %llx %llx %llx %llx %llx %llx %llx %llx.\n",
|
||||
rdata_reg,
|
||||
(unsigned long long)t4_read_reg64(adap, rdata_reg),
|
||||
(unsigned long long)t4_read_reg64(adap, rdata_reg + 8),
|
||||
(unsigned long long)t4_read_reg64(adap, rdata_reg + 16),
|
||||
(unsigned long long)t4_read_reg64(adap, rdata_reg + 24),
|
||||
(unsigned long long)t4_read_reg64(adap, rdata_reg + 32),
|
||||
(unsigned long long)t4_read_reg64(adap, rdata_reg + 40),
|
||||
(unsigned long long)t4_read_reg64(adap, rdata_reg + 48),
|
||||
(unsigned long long)t4_read_reg64(adap, rdata_reg + 56),
|
||||
(unsigned long long)t4_read_reg64(adap, rdata_reg + 64));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* t4_memory_rw - read/write EDC 0, EDC 1 or MC via PCIE memory window
|
||||
* @adap: the adapter
|
||||
|
|
@ -1322,9 +1360,10 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size)
|
|||
};
|
||||
|
||||
static const unsigned int t6_reg_ranges[] = {
|
||||
0x1008, 0x114c,
|
||||
0x1008, 0x1124,
|
||||
0x1138, 0x114c,
|
||||
0x1180, 0x11b4,
|
||||
0x11fc, 0x1250,
|
||||
0x11fc, 0x1254,
|
||||
0x1280, 0x133c,
|
||||
0x1800, 0x18fc,
|
||||
0x3000, 0x302c,
|
||||
|
|
@ -1345,18 +1384,18 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size)
|
|||
0x5a80, 0x5a9c,
|
||||
0x5b94, 0x5bfc,
|
||||
0x5c10, 0x5ec0,
|
||||
0x5ec8, 0x5ec8,
|
||||
0x5ec8, 0x5ecc,
|
||||
0x6000, 0x6040,
|
||||
0x6058, 0x6154,
|
||||
0x6058, 0x619c,
|
||||
0x7700, 0x7798,
|
||||
0x77c0, 0x7880,
|
||||
0x78cc, 0x78fc,
|
||||
0x7b00, 0x7c54,
|
||||
0x7d00, 0x7efc,
|
||||
0x8dc0, 0x8de0,
|
||||
0x8dc0, 0x8de4,
|
||||
0x8df8, 0x8e84,
|
||||
0x8ea0, 0x8f88,
|
||||
0x8fb8, 0x911c,
|
||||
0x8fb8, 0x9124,
|
||||
0x9400, 0x9470,
|
||||
0x9600, 0x971c,
|
||||
0x9800, 0x9808,
|
||||
|
|
@ -1371,20 +1410,21 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size)
|
|||
0x9f00, 0x9f6c,
|
||||
0x9f80, 0xa020,
|
||||
0xd004, 0xd03c,
|
||||
0xd100, 0xd118,
|
||||
0xd200, 0xd31c,
|
||||
0xdfc0, 0xdfe0,
|
||||
0xe000, 0xf008,
|
||||
0x11000, 0x11014,
|
||||
0x11048, 0x11110,
|
||||
0x11118, 0x1117c,
|
||||
0x11190, 0x11260,
|
||||
0x11048, 0x1117c,
|
||||
0x11190, 0x11270,
|
||||
0x11300, 0x1130c,
|
||||
0x12000, 0x1205c,
|
||||
0x12000, 0x1206c,
|
||||
0x19040, 0x1906c,
|
||||
0x19078, 0x19080,
|
||||
0x1908c, 0x19124,
|
||||
0x19150, 0x191b0,
|
||||
0x191d0, 0x191e8,
|
||||
0x19238, 0x192b8,
|
||||
0x19238, 0x192bc,
|
||||
0x193f8, 0x19474,
|
||||
0x19490, 0x194cc,
|
||||
0x194f0, 0x194f8,
|
||||
|
|
@ -1461,12 +1501,11 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size)
|
|||
0x1ff00, 0x1ff84,
|
||||
0x1ffc0, 0x1ffc8,
|
||||
0x30000, 0x30070,
|
||||
0x30100, 0x3015c,
|
||||
0x30190, 0x301d0,
|
||||
0x30200, 0x30318,
|
||||
0x30100, 0x301d0,
|
||||
0x30200, 0x30320,
|
||||
0x30400, 0x3052c,
|
||||
0x30540, 0x3061c,
|
||||
0x30800, 0x3088c,
|
||||
0x30800, 0x30890,
|
||||
0x308c0, 0x30908,
|
||||
0x30910, 0x309b8,
|
||||
0x30a00, 0x30a04,
|
||||
|
|
@ -1539,12 +1578,11 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size)
|
|||
0x33c24, 0x33c50,
|
||||
0x33cf0, 0x33cfc,
|
||||
0x34000, 0x34070,
|
||||
0x34100, 0x3415c,
|
||||
0x34190, 0x341d0,
|
||||
0x34200, 0x34318,
|
||||
0x34100, 0x341d0,
|
||||
0x34200, 0x34320,
|
||||
0x34400, 0x3452c,
|
||||
0x34540, 0x3461c,
|
||||
0x34800, 0x3488c,
|
||||
0x34800, 0x34890,
|
||||
0x348c0, 0x34908,
|
||||
0x34910, 0x349b8,
|
||||
0x34a00, 0x34a04,
|
||||
|
|
@ -2129,6 +2167,61 @@ int t4_get_exprom_version(struct adapter *adap, u32 *vers)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* t4_check_fw_version - check if the FW is supported with this driver
|
||||
* @adap: the adapter
|
||||
*
|
||||
* Checks if an adapter's FW is compatible with the driver. Returns 0
|
||||
* if there's exact match, a negative error if the version could not be
|
||||
* read or there's a major version mismatch
|
||||
*/
|
||||
int t4_check_fw_version(struct adapter *adap)
|
||||
{
|
||||
int ret, major, minor, micro;
|
||||
int exp_major, exp_minor, exp_micro;
|
||||
unsigned int chip_version = CHELSIO_CHIP_VERSION(adap->params.chip);
|
||||
|
||||
ret = t4_get_fw_version(adap, &adap->params.fw_vers);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
major = FW_HDR_FW_VER_MAJOR_G(adap->params.fw_vers);
|
||||
minor = FW_HDR_FW_VER_MINOR_G(adap->params.fw_vers);
|
||||
micro = FW_HDR_FW_VER_MICRO_G(adap->params.fw_vers);
|
||||
|
||||
switch (chip_version) {
|
||||
case CHELSIO_T4:
|
||||
exp_major = T4FW_MIN_VERSION_MAJOR;
|
||||
exp_minor = T4FW_MIN_VERSION_MINOR;
|
||||
exp_micro = T4FW_MIN_VERSION_MICRO;
|
||||
break;
|
||||
case CHELSIO_T5:
|
||||
exp_major = T5FW_MIN_VERSION_MAJOR;
|
||||
exp_minor = T5FW_MIN_VERSION_MINOR;
|
||||
exp_micro = T5FW_MIN_VERSION_MICRO;
|
||||
break;
|
||||
case CHELSIO_T6:
|
||||
exp_major = T6FW_MIN_VERSION_MAJOR;
|
||||
exp_minor = T6FW_MIN_VERSION_MINOR;
|
||||
exp_micro = T6FW_MIN_VERSION_MICRO;
|
||||
break;
|
||||
default:
|
||||
dev_err(adap->pdev_dev, "Unsupported chip type, %x\n",
|
||||
adap->chip);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (major < exp_major || (major == exp_major && minor < exp_minor) ||
|
||||
(major == exp_major && minor == exp_minor && micro < exp_micro)) {
|
||||
dev_err(adap->pdev_dev,
|
||||
"Card has firmware version %u.%u.%u, minimum "
|
||||
"supported firmware is %u.%u.%u.\n", major, minor,
|
||||
micro, exp_major, exp_minor, exp_micro);
|
||||
return -EFAULT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Is the given firmware API compatible with the one the driver was compiled
|
||||
* with?
|
||||
*/
|
||||
|
|
@ -3281,6 +3374,8 @@ static void mem_intr_handler(struct adapter *adapter, int idx)
|
|||
if (v & ECC_CE_INT_CAUSE_F) {
|
||||
u32 cnt = ECC_CECNT_G(t4_read_reg(adapter, cnt_addr));
|
||||
|
||||
t4_edc_err_read(adapter, idx);
|
||||
|
||||
t4_write_reg(adapter, cnt_addr, ECC_CECNT_V(ECC_CECNT_M));
|
||||
if (printk_ratelimit())
|
||||
dev_warn(adapter->pdev_dev,
|
||||
|
|
@ -3488,7 +3583,9 @@ int t4_slow_intr_handler(struct adapter *adapter)
|
|||
void t4_intr_enable(struct adapter *adapter)
|
||||
{
|
||||
u32 val = 0;
|
||||
u32 pf = SOURCEPF_G(t4_read_reg(adapter, PL_WHOAMI_A));
|
||||
u32 whoami = t4_read_reg(adapter, PL_WHOAMI_A);
|
||||
u32 pf = CHELSIO_CHIP_VERSION(adapter->params.chip) <= CHELSIO_T5 ?
|
||||
SOURCEPF_G(whoami) : T6_SOURCEPF_G(whoami);
|
||||
|
||||
if (CHELSIO_CHIP_VERSION(adapter->params.chip) <= CHELSIO_T5)
|
||||
val = ERR_DROPPED_DB_F | ERR_EGR_CTXT_PRIO_F | DBFIFO_HP_INT_F;
|
||||
|
|
@ -3513,7 +3610,9 @@ void t4_intr_enable(struct adapter *adapter)
|
|||
*/
|
||||
void t4_intr_disable(struct adapter *adapter)
|
||||
{
|
||||
u32 pf = SOURCEPF_G(t4_read_reg(adapter, PL_WHOAMI_A));
|
||||
u32 whoami = t4_read_reg(adapter, PL_WHOAMI_A);
|
||||
u32 pf = CHELSIO_CHIP_VERSION(adapter->params.chip) <= CHELSIO_T5 ?
|
||||
SOURCEPF_G(whoami) : T6_SOURCEPF_G(whoami);
|
||||
|
||||
t4_write_reg(adapter, MYPF_REG(PL_PF_INT_ENABLE_A), 0);
|
||||
t4_set_reg_field(adapter, PL_INT_MAP0_A, 1 << pf, 0);
|
||||
|
|
@ -3687,6 +3786,11 @@ int t4_read_rss(struct adapter *adapter, u16 *map)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int t4_use_ldst(struct adapter *adap)
|
||||
{
|
||||
return (adap->flags & FW_OK) || !adap->use_bd;
|
||||
}
|
||||
|
||||
/**
|
||||
* t4_fw_tp_pio_rw - Access TP PIO through LDST
|
||||
* @adap: the adapter
|
||||
|
|
@ -3730,7 +3834,7 @@ static void t4_fw_tp_pio_rw(struct adapter *adap, u32 *vals, unsigned int nregs,
|
|||
*/
|
||||
void t4_read_rss_key(struct adapter *adap, u32 *key)
|
||||
{
|
||||
if (adap->flags & FW_OK)
|
||||
if (t4_use_ldst(adap))
|
||||
t4_fw_tp_pio_rw(adap, key, 10, TP_RSS_SECRET_KEY0_A, 1);
|
||||
else
|
||||
t4_read_indirect(adap, TP_PIO_ADDR_A, TP_PIO_DATA_A, key, 10,
|
||||
|
|
@ -3760,7 +3864,7 @@ void t4_write_rss_key(struct adapter *adap, const u32 *key, int idx)
|
|||
(vrt & KEYEXTEND_F) && (KEYMODE_G(vrt) == 3))
|
||||
rss_key_addr_cnt = 32;
|
||||
|
||||
if (adap->flags & FW_OK)
|
||||
if (t4_use_ldst(adap))
|
||||
t4_fw_tp_pio_rw(adap, (void *)key, 10, TP_RSS_SECRET_KEY0_A, 0);
|
||||
else
|
||||
t4_write_indirect(adap, TP_PIO_ADDR_A, TP_PIO_DATA_A, key, 10,
|
||||
|
|
@ -3789,7 +3893,7 @@ void t4_write_rss_key(struct adapter *adap, const u32 *key, int idx)
|
|||
void t4_read_rss_pf_config(struct adapter *adapter, unsigned int index,
|
||||
u32 *valp)
|
||||
{
|
||||
if (adapter->flags & FW_OK)
|
||||
if (t4_use_ldst(adapter))
|
||||
t4_fw_tp_pio_rw(adapter, valp, 1,
|
||||
TP_RSS_PF0_CONFIG_A + index, 1);
|
||||
else
|
||||
|
|
@ -3829,7 +3933,7 @@ void t4_read_rss_vf_config(struct adapter *adapter, unsigned int index,
|
|||
|
||||
/* Grab the VFL/VFH values ...
|
||||
*/
|
||||
if (adapter->flags & FW_OK) {
|
||||
if (t4_use_ldst(adapter)) {
|
||||
t4_fw_tp_pio_rw(adapter, vfl, 1, TP_RSS_VFL_CONFIG_A, 1);
|
||||
t4_fw_tp_pio_rw(adapter, vfh, 1, TP_RSS_VFH_CONFIG_A, 1);
|
||||
} else {
|
||||
|
|
@ -3850,7 +3954,7 @@ u32 t4_read_rss_pf_map(struct adapter *adapter)
|
|||
{
|
||||
u32 pfmap;
|
||||
|
||||
if (adapter->flags & FW_OK)
|
||||
if (t4_use_ldst(adapter))
|
||||
t4_fw_tp_pio_rw(adapter, &pfmap, 1, TP_RSS_PF_MAP_A, 1);
|
||||
else
|
||||
t4_read_indirect(adapter, TP_PIO_ADDR_A, TP_PIO_DATA_A,
|
||||
|
|
@ -3868,7 +3972,7 @@ u32 t4_read_rss_pf_mask(struct adapter *adapter)
|
|||
{
|
||||
u32 pfmask;
|
||||
|
||||
if (adapter->flags & FW_OK)
|
||||
if (t4_use_ldst(adapter))
|
||||
t4_fw_tp_pio_rw(adapter, &pfmask, 1, TP_RSS_PF_MSK_A, 1);
|
||||
else
|
||||
t4_read_indirect(adapter, TP_PIO_ADDR_A, TP_PIO_DATA_A,
|
||||
|
|
@ -3924,43 +4028,25 @@ void t4_tp_get_tcp_stats(struct adapter *adap, struct tp_tcp_stats *v4,
|
|||
*/
|
||||
void t4_tp_get_err_stats(struct adapter *adap, struct tp_err_stats *st)
|
||||
{
|
||||
/* T6 and later has 2 channels */
|
||||
if (adap->params.arch.nchan == NCHAN) {
|
||||
t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A,
|
||||
st->mac_in_errs, 12, TP_MIB_MAC_IN_ERR_0_A);
|
||||
t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A,
|
||||
st->tnl_cong_drops, 8,
|
||||
TP_MIB_TNL_CNG_DROP_0_A);
|
||||
t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A,
|
||||
st->tnl_tx_drops, 4,
|
||||
TP_MIB_TNL_DROP_0_A);
|
||||
t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A,
|
||||
st->ofld_vlan_drops, 4,
|
||||
TP_MIB_OFD_VLN_DROP_0_A);
|
||||
t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A,
|
||||
st->tcp6_in_errs, 4,
|
||||
TP_MIB_TCP_V6IN_ERR_0_A);
|
||||
} else {
|
||||
t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A,
|
||||
st->mac_in_errs, 2, TP_MIB_MAC_IN_ERR_0_A);
|
||||
t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A,
|
||||
st->hdr_in_errs, 2, TP_MIB_HDR_IN_ERR_0_A);
|
||||
t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A,
|
||||
st->tcp_in_errs, 2, TP_MIB_TCP_IN_ERR_0_A);
|
||||
t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A,
|
||||
st->tnl_cong_drops, 2,
|
||||
TP_MIB_TNL_CNG_DROP_0_A);
|
||||
t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A,
|
||||
st->ofld_chan_drops, 2,
|
||||
TP_MIB_OFD_CHN_DROP_0_A);
|
||||
t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A,
|
||||
st->tnl_tx_drops, 2, TP_MIB_TNL_DROP_0_A);
|
||||
t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A,
|
||||
st->ofld_vlan_drops, 2,
|
||||
TP_MIB_OFD_VLN_DROP_0_A);
|
||||
t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A,
|
||||
st->tcp6_in_errs, 2, TP_MIB_TCP_V6IN_ERR_0_A);
|
||||
}
|
||||
int nchan = adap->params.arch.nchan;
|
||||
|
||||
t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A,
|
||||
st->mac_in_errs, nchan, TP_MIB_MAC_IN_ERR_0_A);
|
||||
t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A,
|
||||
st->hdr_in_errs, nchan, TP_MIB_HDR_IN_ERR_0_A);
|
||||
t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A,
|
||||
st->tcp_in_errs, nchan, TP_MIB_TCP_IN_ERR_0_A);
|
||||
t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A,
|
||||
st->tnl_cong_drops, nchan, TP_MIB_TNL_CNG_DROP_0_A);
|
||||
t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A,
|
||||
st->ofld_chan_drops, nchan, TP_MIB_OFD_CHN_DROP_0_A);
|
||||
t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A,
|
||||
st->tnl_tx_drops, nchan, TP_MIB_TNL_DROP_0_A);
|
||||
t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A,
|
||||
st->ofld_vlan_drops, nchan, TP_MIB_OFD_VLN_DROP_0_A);
|
||||
t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A,
|
||||
st->tcp6_in_errs, nchan, TP_MIB_TCP_V6IN_ERR_0_A);
|
||||
|
||||
t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A,
|
||||
&st->ofld_no_neigh, 2, TP_MIB_OFD_ARP_DROP_A);
|
||||
}
|
||||
|
|
@ -3974,16 +4060,13 @@ void t4_tp_get_err_stats(struct adapter *adap, struct tp_err_stats *st)
|
|||
*/
|
||||
void t4_tp_get_cpl_stats(struct adapter *adap, struct tp_cpl_stats *st)
|
||||
{
|
||||
/* T6 and later has 2 channels */
|
||||
if (adap->params.arch.nchan == NCHAN) {
|
||||
t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A, st->req,
|
||||
8, TP_MIB_CPL_IN_REQ_0_A);
|
||||
} else {
|
||||
t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A, st->req,
|
||||
2, TP_MIB_CPL_IN_REQ_0_A);
|
||||
t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A, st->rsp,
|
||||
2, TP_MIB_CPL_OUT_RSP_0_A);
|
||||
}
|
||||
int nchan = adap->params.arch.nchan;
|
||||
|
||||
t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A, st->req,
|
||||
nchan, TP_MIB_CPL_IN_REQ_0_A);
|
||||
t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A, st->rsp,
|
||||
nchan, TP_MIB_CPL_OUT_RSP_0_A);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -4237,6 +4320,119 @@ void t4_get_chan_txrate(struct adapter *adap, u64 *nic_rate, u64 *ofld_rate)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* t4_set_trace_filter - configure one of the tracing filters
|
||||
* @adap: the adapter
|
||||
* @tp: the desired trace filter parameters
|
||||
* @idx: which filter to configure
|
||||
* @enable: whether to enable or disable the filter
|
||||
*
|
||||
* Configures one of the tracing filters available in HW. If @enable is
|
||||
* %0 @tp is not examined and may be %NULL. The user is responsible to
|
||||
* set the single/multiple trace mode by writing to MPS_TRC_CFG_A register
|
||||
*/
|
||||
int t4_set_trace_filter(struct adapter *adap, const struct trace_params *tp,
|
||||
int idx, int enable)
|
||||
{
|
||||
int i, ofst = idx * 4;
|
||||
u32 data_reg, mask_reg, cfg;
|
||||
u32 multitrc = TRCMULTIFILTER_F;
|
||||
|
||||
if (!enable) {
|
||||
t4_write_reg(adap, MPS_TRC_FILTER_MATCH_CTL_A_A + ofst, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cfg = t4_read_reg(adap, MPS_TRC_CFG_A);
|
||||
if (cfg & TRCMULTIFILTER_F) {
|
||||
/* If multiple tracers are enabled, then maximum
|
||||
* capture size is 2.5KB (FIFO size of a single channel)
|
||||
* minus 2 flits for CPL_TRACE_PKT header.
|
||||
*/
|
||||
if (tp->snap_len > ((10 * 1024 / 4) - (2 * 8)))
|
||||
return -EINVAL;
|
||||
} else {
|
||||
/* If multiple tracers are disabled, to avoid deadlocks
|
||||
* maximum packet capture size of 9600 bytes is recommended.
|
||||
* Also in this mode, only trace0 can be enabled and running.
|
||||
*/
|
||||
multitrc = 0;
|
||||
if (tp->snap_len > 9600 || idx)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (tp->port > (is_t4(adap->params.chip) ? 11 : 19) || tp->invert > 1 ||
|
||||
tp->skip_len > TFLENGTH_M || tp->skip_ofst > TFOFFSET_M ||
|
||||
tp->min_len > TFMINPKTSIZE_M)
|
||||
return -EINVAL;
|
||||
|
||||
/* stop the tracer we'll be changing */
|
||||
t4_write_reg(adap, MPS_TRC_FILTER_MATCH_CTL_A_A + ofst, 0);
|
||||
|
||||
idx *= (MPS_TRC_FILTER1_MATCH_A - MPS_TRC_FILTER0_MATCH_A);
|
||||
data_reg = MPS_TRC_FILTER0_MATCH_A + idx;
|
||||
mask_reg = MPS_TRC_FILTER0_DONT_CARE_A + idx;
|
||||
|
||||
for (i = 0; i < TRACE_LEN / 4; i++, data_reg += 4, mask_reg += 4) {
|
||||
t4_write_reg(adap, data_reg, tp->data[i]);
|
||||
t4_write_reg(adap, mask_reg, ~tp->mask[i]);
|
||||
}
|
||||
t4_write_reg(adap, MPS_TRC_FILTER_MATCH_CTL_B_A + ofst,
|
||||
TFCAPTUREMAX_V(tp->snap_len) |
|
||||
TFMINPKTSIZE_V(tp->min_len));
|
||||
t4_write_reg(adap, MPS_TRC_FILTER_MATCH_CTL_A_A + ofst,
|
||||
TFOFFSET_V(tp->skip_ofst) | TFLENGTH_V(tp->skip_len) |
|
||||
(is_t4(adap->params.chip) ?
|
||||
TFPORT_V(tp->port) | TFEN_F | TFINVERTMATCH_V(tp->invert) :
|
||||
T5_TFPORT_V(tp->port) | T5_TFEN_F |
|
||||
T5_TFINVERTMATCH_V(tp->invert)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* t4_get_trace_filter - query one of the tracing filters
|
||||
* @adap: the adapter
|
||||
* @tp: the current trace filter parameters
|
||||
* @idx: which trace filter to query
|
||||
* @enabled: non-zero if the filter is enabled
|
||||
*
|
||||
* Returns the current settings of one of the HW tracing filters.
|
||||
*/
|
||||
void t4_get_trace_filter(struct adapter *adap, struct trace_params *tp, int idx,
|
||||
int *enabled)
|
||||
{
|
||||
u32 ctla, ctlb;
|
||||
int i, ofst = idx * 4;
|
||||
u32 data_reg, mask_reg;
|
||||
|
||||
ctla = t4_read_reg(adap, MPS_TRC_FILTER_MATCH_CTL_A_A + ofst);
|
||||
ctlb = t4_read_reg(adap, MPS_TRC_FILTER_MATCH_CTL_B_A + ofst);
|
||||
|
||||
if (is_t4(adap->params.chip)) {
|
||||
*enabled = !!(ctla & TFEN_F);
|
||||
tp->port = TFPORT_G(ctla);
|
||||
tp->invert = !!(ctla & TFINVERTMATCH_F);
|
||||
} else {
|
||||
*enabled = !!(ctla & T5_TFEN_F);
|
||||
tp->port = T5_TFPORT_G(ctla);
|
||||
tp->invert = !!(ctla & T5_TFINVERTMATCH_F);
|
||||
}
|
||||
tp->snap_len = TFCAPTUREMAX_G(ctlb);
|
||||
tp->min_len = TFMINPKTSIZE_G(ctlb);
|
||||
tp->skip_ofst = TFOFFSET_G(ctla);
|
||||
tp->skip_len = TFLENGTH_G(ctla);
|
||||
|
||||
ofst = (MPS_TRC_FILTER1_MATCH_A - MPS_TRC_FILTER0_MATCH_A) * idx;
|
||||
data_reg = MPS_TRC_FILTER0_MATCH_A + ofst;
|
||||
mask_reg = MPS_TRC_FILTER0_DONT_CARE_A + ofst;
|
||||
|
||||
for (i = 0; i < TRACE_LEN / 4; i++, data_reg += 4, mask_reg += 4) {
|
||||
tp->mask[i] = ~t4_read_reg(adap, mask_reg);
|
||||
tp->data[i] = t4_read_reg(adap, data_reg) & tp->mask[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* t4_pmtx_get_stats - returns the HW stats from PMTX
|
||||
* @adap: the adapter
|
||||
|
|
@ -6294,7 +6490,7 @@ int t4_init_tp_params(struct adapter *adap)
|
|||
/* Cache the adapter's Compressed Filter Mode and global Incress
|
||||
* Configuration.
|
||||
*/
|
||||
if (adap->flags & FW_OK) {
|
||||
if (t4_use_ldst(adap)) {
|
||||
t4_fw_tp_pio_rw(adap, &adap->params.tp.vlan_pri_map, 1,
|
||||
TP_VLAN_PRI_MAP_A, 1);
|
||||
t4_fw_tp_pio_rw(adap, &adap->params.tp.ingress_config, 1,
|
||||
|
|
|
|||
|
|
@ -47,7 +47,6 @@ enum {
|
|||
TCB_SIZE = 128, /* TCB size */
|
||||
NMTUS = 16, /* size of MTU table */
|
||||
NCCTRL_WIN = 32, /* # of congestion control windows */
|
||||
L2T_SIZE = 4096, /* # of L2T entries */
|
||||
PM_NSTATS = 5, /* # of PM stats */
|
||||
MBOX_LEN = 64, /* mailbox size in bytes */
|
||||
TRACE_LEN = 112, /* length of trace data and mask */
|
||||
|
|
|
|||
|
|
@ -660,6 +660,9 @@ struct cpl_tx_pkt {
|
|||
#define TXPKT_OVLAN_IDX_S 12
|
||||
#define TXPKT_OVLAN_IDX_V(x) ((x) << TXPKT_OVLAN_IDX_S)
|
||||
|
||||
#define TXPKT_T5_OVLAN_IDX_S 12
|
||||
#define TXPKT_T5_OVLAN_IDX_V(x) ((x) << TXPKT_T5_OVLAN_IDX_S)
|
||||
|
||||
#define TXPKT_INTF_S 16
|
||||
#define TXPKT_INTF_V(x) ((x) << TXPKT_INTF_S)
|
||||
|
||||
|
|
|
|||
|
|
@ -142,6 +142,8 @@ CH_PCI_DEVICE_ID_TABLE_DEFINE_BEGIN
|
|||
CH_PCI_ID_TABLE_FENTRY(0x5013), /* T580-chr */
|
||||
CH_PCI_ID_TABLE_FENTRY(0x5014), /* T580-so */
|
||||
CH_PCI_ID_TABLE_FENTRY(0x5015), /* T502-bt */
|
||||
CH_PCI_ID_TABLE_FENTRY(0x5016), /* T580-OCP-SO */
|
||||
CH_PCI_ID_TABLE_FENTRY(0x5017), /* T520-OCP-SO */
|
||||
CH_PCI_ID_TABLE_FENTRY(0x5080), /* Custom T540-cr */
|
||||
CH_PCI_ID_TABLE_FENTRY(0x5081), /* Custom T540-LL-cr */
|
||||
CH_PCI_ID_TABLE_FENTRY(0x5082), /* Custom T504-cr */
|
||||
|
|
@ -155,6 +157,22 @@ CH_PCI_DEVICE_ID_TABLE_DEFINE_BEGIN
|
|||
CH_PCI_ID_TABLE_FENTRY(0x5090), /* Custom T540-CR */
|
||||
CH_PCI_ID_TABLE_FENTRY(0x5091), /* Custom T522-CR */
|
||||
CH_PCI_ID_TABLE_FENTRY(0x5092), /* Custom T520-CR */
|
||||
|
||||
/* T6 adapters:
|
||||
*/
|
||||
CH_PCI_ID_TABLE_FENTRY(0x6001),
|
||||
CH_PCI_ID_TABLE_FENTRY(0x6002),
|
||||
CH_PCI_ID_TABLE_FENTRY(0x6003),
|
||||
CH_PCI_ID_TABLE_FENTRY(0x6004),
|
||||
CH_PCI_ID_TABLE_FENTRY(0x6005),
|
||||
CH_PCI_ID_TABLE_FENTRY(0x6006),
|
||||
CH_PCI_ID_TABLE_FENTRY(0x6007),
|
||||
CH_PCI_ID_TABLE_FENTRY(0x6009),
|
||||
CH_PCI_ID_TABLE_FENTRY(0x600d),
|
||||
CH_PCI_ID_TABLE_FENTRY(0x6010),
|
||||
CH_PCI_ID_TABLE_FENTRY(0x6011),
|
||||
CH_PCI_ID_TABLE_FENTRY(0x6014),
|
||||
CH_PCI_ID_TABLE_FENTRY(0x6015),
|
||||
CH_PCI_DEVICE_ID_TABLE_DEFINE_END;
|
||||
|
||||
#endif /* __T4_PCI_ID_TBL_H__ */
|
||||
|
|
|
|||
|
|
@ -136,6 +136,20 @@
|
|||
#define INGPACKBOUNDARY_G(x) (((x) >> INGPACKBOUNDARY_S) \
|
||||
& INGPACKBOUNDARY_M)
|
||||
|
||||
#define VFIFO_ENABLE_S 10
|
||||
#define VFIFO_ENABLE_V(x) ((x) << VFIFO_ENABLE_S)
|
||||
#define VFIFO_ENABLE_F VFIFO_ENABLE_V(1U)
|
||||
|
||||
#define SGE_DBVFIFO_BADDR_A 0x1138
|
||||
|
||||
#define DBVFIFO_SIZE_S 6
|
||||
#define DBVFIFO_SIZE_M 0xfffU
|
||||
#define DBVFIFO_SIZE_G(x) (((x) >> DBVFIFO_SIZE_S) & DBVFIFO_SIZE_M)
|
||||
|
||||
#define T6_DBVFIFO_SIZE_S 0
|
||||
#define T6_DBVFIFO_SIZE_M 0x1fffU
|
||||
#define T6_DBVFIFO_SIZE_G(x) (((x) >> T6_DBVFIFO_SIZE_S) & T6_DBVFIFO_SIZE_M)
|
||||
|
||||
#define GLOBALENABLE_S 0
|
||||
#define GLOBALENABLE_V(x) ((x) << GLOBALENABLE_S)
|
||||
#define GLOBALENABLE_F GLOBALENABLE_V(1U)
|
||||
|
|
@ -303,6 +317,8 @@
|
|||
#define SGE_FL_BUFFER_SIZE7_A 0x1060
|
||||
#define SGE_FL_BUFFER_SIZE8_A 0x1064
|
||||
|
||||
#define SGE_IMSG_CTXT_BADDR_A 0x1088
|
||||
#define SGE_FLM_CACHE_BADDR_A 0x108c
|
||||
#define SGE_INGRESS_RX_THRESHOLD_A 0x10a0
|
||||
|
||||
#define THRESHOLD_0_S 24
|
||||
|
|
@ -338,6 +354,11 @@
|
|||
#define EGRTHRESHOLDPACKING_G(x) \
|
||||
(((x) >> EGRTHRESHOLDPACKING_S) & EGRTHRESHOLDPACKING_M)
|
||||
|
||||
#define T6_EGRTHRESHOLDPACKING_S 16
|
||||
#define T6_EGRTHRESHOLDPACKING_M 0xffU
|
||||
#define T6_EGRTHRESHOLDPACKING_G(x) \
|
||||
(((x) >> T6_EGRTHRESHOLDPACKING_S) & T6_EGRTHRESHOLDPACKING_M)
|
||||
|
||||
#define SGE_TIMESTAMP_LO_A 0x1098
|
||||
#define SGE_TIMESTAMP_HI_A 0x109c
|
||||
|
||||
|
|
@ -352,6 +373,7 @@
|
|||
#define TSVAL_G(x) (((x) >> TSVAL_S) & TSVAL_M)
|
||||
|
||||
#define SGE_DBFIFO_STATUS_A 0x10a4
|
||||
#define SGE_DBVFIFO_SIZE_A 0x113c
|
||||
|
||||
#define HP_INT_THRESH_S 28
|
||||
#define HP_INT_THRESH_M 0xfU
|
||||
|
|
@ -864,6 +886,10 @@
|
|||
/* registers for module MA */
|
||||
#define MA_EDRAM0_BAR_A 0x77c0
|
||||
|
||||
#define EDRAM0_BASE_S 16
|
||||
#define EDRAM0_BASE_M 0xfffU
|
||||
#define EDRAM0_BASE_G(x) (((x) >> EDRAM0_BASE_S) & EDRAM0_BASE_M)
|
||||
|
||||
#define EDRAM0_SIZE_S 0
|
||||
#define EDRAM0_SIZE_M 0xfffU
|
||||
#define EDRAM0_SIZE_V(x) ((x) << EDRAM0_SIZE_S)
|
||||
|
|
@ -871,6 +897,10 @@
|
|||
|
||||
#define MA_EDRAM1_BAR_A 0x77c4
|
||||
|
||||
#define EDRAM1_BASE_S 16
|
||||
#define EDRAM1_BASE_M 0xfffU
|
||||
#define EDRAM1_BASE_G(x) (((x) >> EDRAM1_BASE_S) & EDRAM1_BASE_M)
|
||||
|
||||
#define EDRAM1_SIZE_S 0
|
||||
#define EDRAM1_SIZE_M 0xfffU
|
||||
#define EDRAM1_SIZE_V(x) ((x) << EDRAM1_SIZE_S)
|
||||
|
|
@ -878,6 +908,11 @@
|
|||
|
||||
#define MA_EXT_MEMORY_BAR_A 0x77c8
|
||||
|
||||
#define EXT_MEM_BASE_S 16
|
||||
#define EXT_MEM_BASE_M 0xfffU
|
||||
#define EXT_MEM_BASE_V(x) ((x) << EXT_MEM_BASE_S)
|
||||
#define EXT_MEM_BASE_G(x) (((x) >> EXT_MEM_BASE_S) & EXT_MEM_BASE_M)
|
||||
|
||||
#define EXT_MEM_SIZE_S 0
|
||||
#define EXT_MEM_SIZE_M 0xfffU
|
||||
#define EXT_MEM_SIZE_V(x) ((x) << EXT_MEM_SIZE_S)
|
||||
|
|
@ -885,6 +920,10 @@
|
|||
|
||||
#define MA_EXT_MEMORY1_BAR_A 0x7808
|
||||
|
||||
#define EXT_MEM1_BASE_S 16
|
||||
#define EXT_MEM1_BASE_M 0xfffU
|
||||
#define EXT_MEM1_BASE_G(x) (((x) >> EXT_MEM1_BASE_S) & EXT_MEM1_BASE_M)
|
||||
|
||||
#define EXT_MEM1_SIZE_S 0
|
||||
#define EXT_MEM1_SIZE_M 0xfffU
|
||||
#define EXT_MEM1_SIZE_V(x) ((x) << EXT_MEM1_SIZE_S)
|
||||
|
|
@ -892,6 +931,10 @@
|
|||
|
||||
#define MA_EXT_MEMORY0_BAR_A 0x77c8
|
||||
|
||||
#define EXT_MEM0_BASE_S 16
|
||||
#define EXT_MEM0_BASE_M 0xfffU
|
||||
#define EXT_MEM0_BASE_G(x) (((x) >> EXT_MEM0_BASE_S) & EXT_MEM0_BASE_M)
|
||||
|
||||
#define EXT_MEM0_SIZE_S 0
|
||||
#define EXT_MEM0_SIZE_M 0xfffU
|
||||
#define EXT_MEM0_SIZE_V(x) ((x) << EXT_MEM0_SIZE_S)
|
||||
|
|
@ -973,6 +1016,10 @@
|
|||
|
||||
/* registers for module CIM */
|
||||
#define CIM_BOOT_CFG_A 0x7b00
|
||||
#define CIM_SDRAM_BASE_ADDR_A 0x7b14
|
||||
#define CIM_SDRAM_ADDR_SIZE_A 0x7b18
|
||||
#define CIM_EXTMEM2_BASE_ADDR_A 0x7b1c
|
||||
#define CIM_EXTMEM2_ADDR_SIZE_A 0x7b20
|
||||
#define CIM_PF_MAILBOX_CTRL_SHADOW_COPY_A 0x290
|
||||
|
||||
#define BOOTADDR_M 0xffffff00U
|
||||
|
|
@ -1231,6 +1278,33 @@
|
|||
#define TP_OUT_CONFIG_A 0x7d04
|
||||
#define TP_GLOBAL_CONFIG_A 0x7d08
|
||||
|
||||
#define TP_CMM_TCB_BASE_A 0x7d10
|
||||
#define TP_CMM_MM_BASE_A 0x7d14
|
||||
#define TP_CMM_TIMER_BASE_A 0x7d18
|
||||
#define TP_PMM_TX_BASE_A 0x7d20
|
||||
#define TP_PMM_RX_BASE_A 0x7d28
|
||||
#define TP_PMM_RX_PAGE_SIZE_A 0x7d2c
|
||||
#define TP_PMM_RX_MAX_PAGE_A 0x7d30
|
||||
#define TP_PMM_TX_PAGE_SIZE_A 0x7d34
|
||||
#define TP_PMM_TX_MAX_PAGE_A 0x7d38
|
||||
#define TP_CMM_MM_MAX_PSTRUCT_A 0x7e6c
|
||||
|
||||
#define PMRXNUMCHN_S 31
|
||||
#define PMRXNUMCHN_V(x) ((x) << PMRXNUMCHN_S)
|
||||
#define PMRXNUMCHN_F PMRXNUMCHN_V(1U)
|
||||
|
||||
#define PMTXNUMCHN_S 30
|
||||
#define PMTXNUMCHN_M 0x3U
|
||||
#define PMTXNUMCHN_G(x) (((x) >> PMTXNUMCHN_S) & PMTXNUMCHN_M)
|
||||
|
||||
#define PMTXMAXPAGE_S 0
|
||||
#define PMTXMAXPAGE_M 0x1fffffU
|
||||
#define PMTXMAXPAGE_G(x) (((x) >> PMTXMAXPAGE_S) & PMTXMAXPAGE_M)
|
||||
|
||||
#define PMRXMAXPAGE_S 0
|
||||
#define PMRXMAXPAGE_M 0x1fffffU
|
||||
#define PMRXMAXPAGE_G(x) (((x) >> PMRXMAXPAGE_S) & PMRXMAXPAGE_M)
|
||||
|
||||
#define DBGLAMODE_S 14
|
||||
#define DBGLAMODE_M 0x3U
|
||||
#define DBGLAMODE_G(x) (((x) >> DBGLAMODE_S) & DBGLAMODE_M)
|
||||
|
|
@ -1338,6 +1412,9 @@
|
|||
#define MTUVALUE_G(x) (((x) >> MTUVALUE_S) & MTUVALUE_M)
|
||||
|
||||
#define TP_RSS_LKP_TABLE_A 0x7dec
|
||||
#define TP_CMM_MM_RX_FLST_BASE_A 0x7e60
|
||||
#define TP_CMM_MM_TX_FLST_BASE_A 0x7e64
|
||||
#define TP_CMM_MM_PS_FLST_BASE_A 0x7e68
|
||||
|
||||
#define LKPTBLROWVLD_S 31
|
||||
#define LKPTBLROWVLD_V(x) ((x) << LKPTBLROWVLD_S)
|
||||
|
|
@ -1483,6 +1560,11 @@
|
|||
#define TP_MIB_RQE_DFR_PKT_A 0x64
|
||||
|
||||
#define ULP_TX_INT_CAUSE_A 0x8dcc
|
||||
#define ULP_TX_TPT_LLIMIT_A 0x8dd4
|
||||
#define ULP_TX_TPT_ULIMIT_A 0x8dd8
|
||||
#define ULP_TX_PBL_LLIMIT_A 0x8ddc
|
||||
#define ULP_TX_PBL_ULIMIT_A 0x8de0
|
||||
#define ULP_TX_ERR_TABLE_BASE_A 0x8e04
|
||||
|
||||
#define PBL_BOUND_ERR_CH3_S 31
|
||||
#define PBL_BOUND_ERR_CH3_V(x) ((x) << PBL_BOUND_ERR_CH3_S)
|
||||
|
|
@ -1804,6 +1886,9 @@
|
|||
#define TRCMULTIFILTER_F TRCMULTIFILTER_V(1U)
|
||||
|
||||
#define MPS_TRC_RSS_CONTROL_A 0x9808
|
||||
#define MPS_TRC_FILTER1_RSS_CONTROL_A 0x9ff4
|
||||
#define MPS_TRC_FILTER2_RSS_CONTROL_A 0x9ffc
|
||||
#define MPS_TRC_FILTER3_RSS_CONTROL_A 0xa004
|
||||
#define MPS_T5_TRC_RSS_CONTROL_A 0xa00c
|
||||
|
||||
#define RSSCONTROL_S 16
|
||||
|
|
@ -1812,6 +1897,59 @@
|
|||
#define QUEUENUMBER_S 0
|
||||
#define QUEUENUMBER_V(x) ((x) << QUEUENUMBER_S)
|
||||
|
||||
#define TFINVERTMATCH_S 24
|
||||
#define TFINVERTMATCH_V(x) ((x) << TFINVERTMATCH_S)
|
||||
#define TFINVERTMATCH_F TFINVERTMATCH_V(1U)
|
||||
|
||||
#define TFEN_S 22
|
||||
#define TFEN_V(x) ((x) << TFEN_S)
|
||||
#define TFEN_F TFEN_V(1U)
|
||||
|
||||
#define TFPORT_S 18
|
||||
#define TFPORT_M 0xfU
|
||||
#define TFPORT_V(x) ((x) << TFPORT_S)
|
||||
#define TFPORT_G(x) (((x) >> TFPORT_S) & TFPORT_M)
|
||||
|
||||
#define TFLENGTH_S 8
|
||||
#define TFLENGTH_M 0x1fU
|
||||
#define TFLENGTH_V(x) ((x) << TFLENGTH_S)
|
||||
#define TFLENGTH_G(x) (((x) >> TFLENGTH_S) & TFLENGTH_M)
|
||||
|
||||
#define TFOFFSET_S 0
|
||||
#define TFOFFSET_M 0x1fU
|
||||
#define TFOFFSET_V(x) ((x) << TFOFFSET_S)
|
||||
#define TFOFFSET_G(x) (((x) >> TFOFFSET_S) & TFOFFSET_M)
|
||||
|
||||
#define T5_TFINVERTMATCH_S 25
|
||||
#define T5_TFINVERTMATCH_V(x) ((x) << T5_TFINVERTMATCH_S)
|
||||
#define T5_TFINVERTMATCH_F T5_TFINVERTMATCH_V(1U)
|
||||
|
||||
#define T5_TFEN_S 23
|
||||
#define T5_TFEN_V(x) ((x) << T5_TFEN_S)
|
||||
#define T5_TFEN_F T5_TFEN_V(1U)
|
||||
|
||||
#define T5_TFPORT_S 18
|
||||
#define T5_TFPORT_M 0x1fU
|
||||
#define T5_TFPORT_V(x) ((x) << T5_TFPORT_S)
|
||||
#define T5_TFPORT_G(x) (((x) >> T5_TFPORT_S) & T5_TFPORT_M)
|
||||
|
||||
#define MPS_TRC_FILTER_MATCH_CTL_A_A 0x9810
|
||||
#define MPS_TRC_FILTER_MATCH_CTL_B_A 0x9820
|
||||
|
||||
#define TFMINPKTSIZE_S 16
|
||||
#define TFMINPKTSIZE_M 0x1ffU
|
||||
#define TFMINPKTSIZE_V(x) ((x) << TFMINPKTSIZE_S)
|
||||
#define TFMINPKTSIZE_G(x) (((x) >> TFMINPKTSIZE_S) & TFMINPKTSIZE_M)
|
||||
|
||||
#define TFCAPTUREMAX_S 0
|
||||
#define TFCAPTUREMAX_M 0x3fffU
|
||||
#define TFCAPTUREMAX_V(x) ((x) << TFCAPTUREMAX_S)
|
||||
#define TFCAPTUREMAX_G(x) (((x) >> TFCAPTUREMAX_S) & TFCAPTUREMAX_M)
|
||||
|
||||
#define MPS_TRC_FILTER0_MATCH_A 0x9c00
|
||||
#define MPS_TRC_FILTER0_DONT_CARE_A 0x9c80
|
||||
#define MPS_TRC_FILTER1_MATCH_A 0x9d00
|
||||
|
||||
#define TP_RSS_CONFIG_A 0x7df0
|
||||
|
||||
#define TNL4TUPENIPV6_S 31
|
||||
|
|
@ -2247,12 +2385,32 @@
|
|||
#define MATCHSRAM_V(x) ((x) << MATCHSRAM_S)
|
||||
#define MATCHSRAM_F MATCHSRAM_V(1U)
|
||||
|
||||
#define MPS_RX_PG_RSV0_A 0x11010
|
||||
#define MPS_RX_PG_RSV4_A 0x11020
|
||||
#define MPS_RX_PERR_INT_CAUSE_A 0x11074
|
||||
#define MPS_RX_MAC_BG_PG_CNT0_A 0x11208
|
||||
#define MPS_RX_LPBK_BG_PG_CNT0_A 0x11218
|
||||
|
||||
#define MPS_CLS_TCAM_Y_L_A 0xf000
|
||||
#define MPS_CLS_TCAM_DATA0_A 0xf000
|
||||
#define MPS_CLS_TCAM_DATA1_A 0xf004
|
||||
|
||||
#define USED_S 16
|
||||
#define USED_M 0x7ffU
|
||||
#define USED_G(x) (((x) >> USED_S) & USED_M)
|
||||
|
||||
#define ALLOC_S 0
|
||||
#define ALLOC_M 0x7ffU
|
||||
#define ALLOC_G(x) (((x) >> ALLOC_S) & ALLOC_M)
|
||||
|
||||
#define T5_USED_S 16
|
||||
#define T5_USED_M 0xfffU
|
||||
#define T5_USED_G(x) (((x) >> T5_USED_S) & T5_USED_M)
|
||||
|
||||
#define T5_ALLOC_S 0
|
||||
#define T5_ALLOC_M 0xfffU
|
||||
#define T5_ALLOC_G(x) (((x) >> T5_ALLOC_S) & T5_ALLOC_M)
|
||||
|
||||
#define DMACH_S 0
|
||||
#define DMACH_M 0xffffU
|
||||
#define DMACH_G(x) (((x) >> DMACH_S) & DMACH_M)
|
||||
|
|
@ -2410,8 +2568,21 @@
|
|||
#define SLVFIFOPARINT_F SLVFIFOPARINT_V(1U)
|
||||
|
||||
#define ULP_RX_INT_CAUSE_A 0x19158
|
||||
#define ULP_RX_ISCSI_LLIMIT_A 0x1915c
|
||||
#define ULP_RX_ISCSI_ULIMIT_A 0x19160
|
||||
#define ULP_RX_ISCSI_TAGMASK_A 0x19164
|
||||
#define ULP_RX_ISCSI_PSZ_A 0x19168
|
||||
#define ULP_RX_TDDP_LLIMIT_A 0x1916c
|
||||
#define ULP_RX_TDDP_ULIMIT_A 0x19170
|
||||
#define ULP_RX_STAG_LLIMIT_A 0x1917c
|
||||
#define ULP_RX_STAG_ULIMIT_A 0x19180
|
||||
#define ULP_RX_RQ_LLIMIT_A 0x19184
|
||||
#define ULP_RX_RQ_ULIMIT_A 0x19188
|
||||
#define ULP_RX_PBL_LLIMIT_A 0x1918c
|
||||
#define ULP_RX_PBL_ULIMIT_A 0x19190
|
||||
#define ULP_RX_CTX_BASE_A 0x19194
|
||||
#define ULP_RX_RQUDP_LLIMIT_A 0x191a4
|
||||
#define ULP_RX_RQUDP_ULIMIT_A 0x191a8
|
||||
#define ULP_RX_LA_CTL_A 0x1923c
|
||||
#define ULP_RX_LA_RDPTR_A 0x19240
|
||||
#define ULP_RX_LA_RDDATA_A 0x19244
|
||||
|
|
@ -2473,6 +2644,10 @@
|
|||
#define SOURCEPF_M 0x7U
|
||||
#define SOURCEPF_G(x) (((x) >> SOURCEPF_S) & SOURCEPF_M)
|
||||
|
||||
#define T6_SOURCEPF_S 9
|
||||
#define T6_SOURCEPF_M 0x7U
|
||||
#define T6_SOURCEPF_G(x) (((x) >> T6_SOURCEPF_S) & T6_SOURCEPF_M)
|
||||
|
||||
#define PL_INT_CAUSE_A 0x1940c
|
||||
|
||||
#define ULP_TX_S 27
|
||||
|
|
@ -2612,7 +2787,20 @@
|
|||
#define T6_LIPMISS_V(x) ((x) << T6_LIPMISS_S)
|
||||
#define T6_LIPMISS_F T6_LIPMISS_V(1U)
|
||||
|
||||
#define LE_DB_CONFIG_A 0x19c04
|
||||
#define LE_DB_SERVER_INDEX_A 0x19c18
|
||||
#define LE_DB_SRVR_START_INDEX_A 0x19c18
|
||||
#define LE_DB_ACT_CNT_IPV4_A 0x19c20
|
||||
#define LE_DB_ACT_CNT_IPV6_A 0x19c24
|
||||
#define LE_DB_HASH_TID_BASE_A 0x19c30
|
||||
#define LE_DB_HASH_TBL_BASE_ADDR_A 0x19c30
|
||||
#define LE_DB_INT_CAUSE_A 0x19c3c
|
||||
#define LE_DB_TID_HASHBASE_A 0x19df8
|
||||
#define T6_LE_DB_HASH_TID_BASE_A 0x19df8
|
||||
|
||||
#define HASHEN_S 20
|
||||
#define HASHEN_V(x) ((x) << HASHEN_S)
|
||||
#define HASHEN_F HASHEN_V(1U)
|
||||
|
||||
#define REQQPARERR_S 16
|
||||
#define REQQPARERR_V(x) ((x) << REQQPARERR_S)
|
||||
|
|
@ -2634,6 +2822,10 @@
|
|||
#define LIP0_V(x) ((x) << LIP0_S)
|
||||
#define LIP0_F LIP0_V(1U)
|
||||
|
||||
#define BASEADDR_S 3
|
||||
#define BASEADDR_M 0x1fffffffU
|
||||
#define BASEADDR_G(x) (((x) >> BASEADDR_S) & BASEADDR_M)
|
||||
|
||||
#define TCAMINTPERR_S 13
|
||||
#define TCAMINTPERR_V(x) ((x) << TCAMINTPERR_S)
|
||||
#define TCAMINTPERR_F TCAMINTPERR_V(1U)
|
||||
|
|
@ -2740,10 +2932,11 @@
|
|||
#define EDC_H_BIST_DATA_PATTERN_A 0x50010
|
||||
#define EDC_H_BIST_STATUS_RDATA_A 0x50028
|
||||
|
||||
#define EDC_H_ECC_ERR_ADDR_A 0x50084
|
||||
#define EDC_T51_BASE_ADDR 0x50800
|
||||
|
||||
#define EDC_STRIDE_T5 (EDC_T51_BASE_ADDR - EDC_T50_BASE_ADDR)
|
||||
#define EDC_REG_T5(reg, idx) (reg + EDC_STRIDE_T5 * idx)
|
||||
#define EDC_T5_STRIDE (EDC_T51_BASE_ADDR - EDC_T50_BASE_ADDR)
|
||||
#define EDC_T5_REG(reg, idx) (reg + EDC_T5_STRIDE * idx)
|
||||
|
||||
#define PL_VF_REV_A 0x4
|
||||
#define PL_VF_WHOAMI_A 0x0
|
||||
|
|
|
|||
|
|
@ -40,14 +40,25 @@
|
|||
#define T4FW_VERSION_MICRO 0x20
|
||||
#define T4FW_VERSION_BUILD 0x00
|
||||
|
||||
#define T4FW_MIN_VERSION_MAJOR 0x01
|
||||
#define T4FW_MIN_VERSION_MINOR 0x04
|
||||
#define T4FW_MIN_VERSION_MICRO 0x00
|
||||
|
||||
#define T5FW_VERSION_MAJOR 0x01
|
||||
#define T5FW_VERSION_MINOR 0x0D
|
||||
#define T5FW_VERSION_MICRO 0x20
|
||||
#define T5FW_VERSION_BUILD 0x00
|
||||
|
||||
#define T5FW_MIN_VERSION_MAJOR 0x00
|
||||
#define T5FW_MIN_VERSION_MINOR 0x00
|
||||
#define T5FW_MIN_VERSION_MICRO 0x00
|
||||
|
||||
#define T6FW_VERSION_MAJOR 0x01
|
||||
#define T6FW_VERSION_MINOR 0x0D
|
||||
#define T6FW_VERSION_MICRO 0x2D
|
||||
#define T6FW_VERSION_BUILD 0x00
|
||||
|
||||
#define T6FW_MIN_VERSION_MAJOR 0x00
|
||||
#define T6FW_MIN_VERSION_MINOR 0x00
|
||||
#define T6FW_MIN_VERSION_MICRO 0x00
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1898,7 +1898,10 @@ static int napi_rx_handler(struct napi_struct *napi, int budget)
|
|||
rspq->unhandled_irqs++;
|
||||
|
||||
val = CIDXINC_V(work_done) | SEINTARM_V(intr_params);
|
||||
if (is_t4(rspq->adapter->params.chip)) {
|
||||
/* If we don't have access to the new User GTS (T5+), use the old
|
||||
* doorbell mechanism; otherwise use the new BAR2 mechanism.
|
||||
*/
|
||||
if (unlikely(!rspq->bar2_addr)) {
|
||||
t4_write_reg(rspq->adapter,
|
||||
T4VF_SGE_BASE_ADDR + SGE_VF_GTS,
|
||||
val | INGRESSQID_V((u32)rspq->cntxt_id));
|
||||
|
|
@ -1998,10 +2001,13 @@ static unsigned int process_intrq(struct adapter *adapter)
|
|||
}
|
||||
|
||||
val = CIDXINC_V(work_done) | SEINTARM_V(intrq->intr_params);
|
||||
if (is_t4(adapter->params.chip))
|
||||
/* If we don't have access to the new User GTS (T5+), use the old
|
||||
* doorbell mechanism; otherwise use the new BAR2 mechanism.
|
||||
*/
|
||||
if (unlikely(!intrq->bar2_addr)) {
|
||||
t4_write_reg(adapter, T4VF_SGE_BASE_ADDR + SGE_VF_GTS,
|
||||
val | INGRESSQID_V(intrq->cntxt_id));
|
||||
else {
|
||||
} else {
|
||||
writel(val | INGRESSQID_V(intrq->bar2_qid),
|
||||
intrq->bar2_addr + SGE_UDB_GTS);
|
||||
wmb();
|
||||
|
|
@ -2662,8 +2668,22 @@ int t4vf_sge_init(struct adapter *adapter)
|
|||
* give it more Free List entries. (Note that the SGE's Egress
|
||||
* Congestion Threshold is in units of 2 Free List pointers.)
|
||||
*/
|
||||
s->fl_starve_thres
|
||||
= EGRTHRESHOLD_G(sge_params->sge_congestion_control)*2 + 1;
|
||||
switch (CHELSIO_CHIP_VERSION(adapter->params.chip)) {
|
||||
case CHELSIO_T4:
|
||||
s->fl_starve_thres =
|
||||
EGRTHRESHOLD_G(sge_params->sge_congestion_control);
|
||||
break;
|
||||
case CHELSIO_T5:
|
||||
s->fl_starve_thres =
|
||||
EGRTHRESHOLDPACKING_G(sge_params->sge_congestion_control);
|
||||
break;
|
||||
case CHELSIO_T6:
|
||||
default:
|
||||
s->fl_starve_thres =
|
||||
T6_EGRTHRESHOLDPACKING_G(sge_params->sge_congestion_control);
|
||||
break;
|
||||
}
|
||||
s->fl_starve_thres = s->fl_starve_thres * 2 + 1;
|
||||
|
||||
/*
|
||||
* Set up tasklet timers.
|
||||
|
|
|
|||
|
|
@ -619,7 +619,8 @@ int t4vf_get_sge_params(struct adapter *adapter)
|
|||
*/
|
||||
whoami = t4_read_reg(adapter,
|
||||
T4VF_PL_BASE_ADDR + PL_VF_WHOAMI_A);
|
||||
pf = SOURCEPF_G(whoami);
|
||||
pf = CHELSIO_CHIP_VERSION(adapter->params.chip) <= CHELSIO_T5 ?
|
||||
SOURCEPF_G(whoami) : T6_SOURCEPF_G(whoami);
|
||||
|
||||
s_hps = (HOSTPAGESIZEPF0_S +
|
||||
(HOSTPAGESIZEPF1_S - HOSTPAGESIZEPF0_S) * pf);
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
|
||||
#define DRV_NAME "enic"
|
||||
#define DRV_DESCRIPTION "Cisco VIC Ethernet NIC Driver"
|
||||
#define DRV_VERSION "2.1.1.83"
|
||||
#define DRV_VERSION "2.3.0.12"
|
||||
#define DRV_COPYRIGHT "Copyright 2008-2013 Cisco Systems, Inc"
|
||||
|
||||
#define ENIC_BARS_MAX 6
|
||||
|
|
@ -191,6 +191,25 @@ struct enic {
|
|||
struct vnic_gen_stats gen_stats;
|
||||
};
|
||||
|
||||
static inline struct net_device *vnic_get_netdev(struct vnic_dev *vdev)
|
||||
{
|
||||
struct enic *enic = vdev->priv;
|
||||
|
||||
return enic->netdev;
|
||||
}
|
||||
|
||||
/* wrappers function for kernel log
|
||||
* Make sure variable vdev of struct vnic_dev is available in the block where
|
||||
* these macros are used
|
||||
*/
|
||||
#define vdev_info(args...) dev_info(&vdev->pdev->dev, args)
|
||||
#define vdev_warn(args...) dev_warn(&vdev->pdev->dev, args)
|
||||
#define vdev_err(args...) dev_err(&vdev->pdev->dev, args)
|
||||
|
||||
#define vdev_netinfo(args...) netdev_info(vnic_get_netdev(vdev), args)
|
||||
#define vdev_netwarn(args...) netdev_warn(vnic_get_netdev(vdev), args)
|
||||
#define vdev_neterr(args...) netdev_err(vnic_get_netdev(vdev), args)
|
||||
|
||||
static inline struct device *enic_get_dev(struct enic *enic)
|
||||
{
|
||||
return &(enic->pdev->dev);
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ int enic_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
|
|||
int res, i;
|
||||
|
||||
enic = netdev_priv(dev);
|
||||
res = skb_flow_dissect_flow_keys(skb, &keys);
|
||||
res = skb_flow_dissect_flow_keys(skb, &keys, 0);
|
||||
if (!res || keys.basic.n_proto != htons(ETH_P_IP) ||
|
||||
(keys.basic.ip_proto != IPPROTO_TCP &&
|
||||
keys.basic.ip_proto != IPPROTO_UDP))
|
||||
|
|
|
|||
|
|
@ -224,7 +224,8 @@ static int enic_get_coalesce(struct net_device *netdev,
|
|||
struct enic *enic = netdev_priv(netdev);
|
||||
struct enic_rx_coal *rxcoal = &enic->rx_coalesce_setting;
|
||||
|
||||
ecmd->tx_coalesce_usecs = enic->tx_coalesce_usecs;
|
||||
if (vnic_dev_get_intr_mode(enic->vdev) == VNIC_DEV_INTR_MODE_MSIX)
|
||||
ecmd->tx_coalesce_usecs = enic->tx_coalesce_usecs;
|
||||
ecmd->rx_coalesce_usecs = enic->rx_coalesce_usecs;
|
||||
if (rxcoal->use_adaptive_rx_coalesce)
|
||||
ecmd->use_adaptive_rx_coalesce = 1;
|
||||
|
|
@ -234,6 +235,53 @@ static int enic_get_coalesce(struct net_device *netdev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int enic_coalesce_valid(struct enic *enic,
|
||||
struct ethtool_coalesce *ec)
|
||||
{
|
||||
u32 coalesce_usecs_max = vnic_dev_get_intr_coal_timer_max(enic->vdev);
|
||||
u32 rx_coalesce_usecs_high = min_t(u32, coalesce_usecs_max,
|
||||
ec->rx_coalesce_usecs_high);
|
||||
u32 rx_coalesce_usecs_low = min_t(u32, coalesce_usecs_max,
|
||||
ec->rx_coalesce_usecs_low);
|
||||
|
||||
if (ec->rx_max_coalesced_frames ||
|
||||
ec->rx_coalesce_usecs_irq ||
|
||||
ec->rx_max_coalesced_frames_irq ||
|
||||
ec->tx_max_coalesced_frames ||
|
||||
ec->tx_coalesce_usecs_irq ||
|
||||
ec->tx_max_coalesced_frames_irq ||
|
||||
ec->stats_block_coalesce_usecs ||
|
||||
ec->use_adaptive_tx_coalesce ||
|
||||
ec->pkt_rate_low ||
|
||||
ec->rx_max_coalesced_frames_low ||
|
||||
ec->tx_coalesce_usecs_low ||
|
||||
ec->tx_max_coalesced_frames_low ||
|
||||
ec->pkt_rate_high ||
|
||||
ec->rx_max_coalesced_frames_high ||
|
||||
ec->tx_coalesce_usecs_high ||
|
||||
ec->tx_max_coalesced_frames_high ||
|
||||
ec->rate_sample_interval)
|
||||
return -EINVAL;
|
||||
|
||||
if ((vnic_dev_get_intr_mode(enic->vdev) != VNIC_DEV_INTR_MODE_MSIX) &&
|
||||
ec->tx_coalesce_usecs)
|
||||
return -EINVAL;
|
||||
|
||||
if ((ec->tx_coalesce_usecs > coalesce_usecs_max) ||
|
||||
(ec->rx_coalesce_usecs > coalesce_usecs_max) ||
|
||||
(ec->rx_coalesce_usecs_low > coalesce_usecs_max) ||
|
||||
(ec->rx_coalesce_usecs_high > coalesce_usecs_max))
|
||||
netdev_info(enic->netdev, "ethtool_set_coalesce: adaptor supports max coalesce value of %d. Setting max value.\n",
|
||||
coalesce_usecs_max);
|
||||
|
||||
if (ec->rx_coalesce_usecs_high &&
|
||||
(rx_coalesce_usecs_high <
|
||||
rx_coalesce_usecs_low + ENIC_AIC_LARGE_PKT_DIFF))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int enic_set_coalesce(struct net_device *netdev,
|
||||
struct ethtool_coalesce *ecmd)
|
||||
{
|
||||
|
|
@ -244,8 +292,12 @@ static int enic_set_coalesce(struct net_device *netdev,
|
|||
u32 rx_coalesce_usecs_high;
|
||||
u32 coalesce_usecs_max;
|
||||
unsigned int i, intr;
|
||||
int ret;
|
||||
struct enic_rx_coal *rxcoal = &enic->rx_coalesce_setting;
|
||||
|
||||
ret = enic_coalesce_valid(enic, ecmd);
|
||||
if (ret)
|
||||
return ret;
|
||||
coalesce_usecs_max = vnic_dev_get_intr_coal_timer_max(enic->vdev);
|
||||
tx_coalesce_usecs = min_t(u32, ecmd->tx_coalesce_usecs,
|
||||
coalesce_usecs_max);
|
||||
|
|
@ -257,59 +309,24 @@ static int enic_set_coalesce(struct net_device *netdev,
|
|||
rx_coalesce_usecs_high = min_t(u32, ecmd->rx_coalesce_usecs_high,
|
||||
coalesce_usecs_max);
|
||||
|
||||
switch (vnic_dev_get_intr_mode(enic->vdev)) {
|
||||
case VNIC_DEV_INTR_MODE_INTX:
|
||||
if (tx_coalesce_usecs != rx_coalesce_usecs)
|
||||
return -EINVAL;
|
||||
if (ecmd->use_adaptive_rx_coalesce ||
|
||||
ecmd->rx_coalesce_usecs_low ||
|
||||
ecmd->rx_coalesce_usecs_high)
|
||||
return -EINVAL;
|
||||
|
||||
intr = enic_legacy_io_intr();
|
||||
vnic_intr_coalescing_timer_set(&enic->intr[intr],
|
||||
tx_coalesce_usecs);
|
||||
break;
|
||||
case VNIC_DEV_INTR_MODE_MSI:
|
||||
if (tx_coalesce_usecs != rx_coalesce_usecs)
|
||||
return -EINVAL;
|
||||
if (ecmd->use_adaptive_rx_coalesce ||
|
||||
ecmd->rx_coalesce_usecs_low ||
|
||||
ecmd->rx_coalesce_usecs_high)
|
||||
return -EINVAL;
|
||||
|
||||
vnic_intr_coalescing_timer_set(&enic->intr[0],
|
||||
tx_coalesce_usecs);
|
||||
break;
|
||||
case VNIC_DEV_INTR_MODE_MSIX:
|
||||
if (ecmd->rx_coalesce_usecs_high &&
|
||||
(rx_coalesce_usecs_high <
|
||||
rx_coalesce_usecs_low + ENIC_AIC_LARGE_PKT_DIFF))
|
||||
return -EINVAL;
|
||||
|
||||
if (vnic_dev_get_intr_mode(enic->vdev) == VNIC_DEV_INTR_MODE_MSIX) {
|
||||
for (i = 0; i < enic->wq_count; i++) {
|
||||
intr = enic_msix_wq_intr(enic, i);
|
||||
vnic_intr_coalescing_timer_set(&enic->intr[intr],
|
||||
tx_coalesce_usecs);
|
||||
tx_coalesce_usecs);
|
||||
}
|
||||
|
||||
rxcoal->use_adaptive_rx_coalesce =
|
||||
!!ecmd->use_adaptive_rx_coalesce;
|
||||
if (!rxcoal->use_adaptive_rx_coalesce)
|
||||
enic_intr_coal_set_rx(enic, rx_coalesce_usecs);
|
||||
|
||||
if (ecmd->rx_coalesce_usecs_high) {
|
||||
rxcoal->range_end = rx_coalesce_usecs_high;
|
||||
rxcoal->small_pkt_range_start = rx_coalesce_usecs_low;
|
||||
rxcoal->large_pkt_range_start = rx_coalesce_usecs_low +
|
||||
ENIC_AIC_LARGE_PKT_DIFF;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
enic->tx_coalesce_usecs = tx_coalesce_usecs;
|
||||
}
|
||||
rxcoal->use_adaptive_rx_coalesce = !!ecmd->use_adaptive_rx_coalesce;
|
||||
if (!rxcoal->use_adaptive_rx_coalesce)
|
||||
enic_intr_coal_set_rx(enic, rx_coalesce_usecs);
|
||||
if (ecmd->rx_coalesce_usecs_high) {
|
||||
rxcoal->range_end = rx_coalesce_usecs_high;
|
||||
rxcoal->small_pkt_range_start = rx_coalesce_usecs_low;
|
||||
rxcoal->large_pkt_range_start = rx_coalesce_usecs_low +
|
||||
ENIC_AIC_LARGE_PKT_DIFF;
|
||||
}
|
||||
|
||||
enic->tx_coalesce_usecs = tx_coalesce_usecs;
|
||||
enic->rx_coalesce_usecs = rx_coalesce_usecs;
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1149,70 +1149,6 @@ static int enic_rq_service(struct vnic_dev *vdev, struct cq_desc *cq_desc,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int enic_poll(struct napi_struct *napi, int budget)
|
||||
{
|
||||
struct net_device *netdev = napi->dev;
|
||||
struct enic *enic = netdev_priv(netdev);
|
||||
unsigned int cq_rq = enic_cq_rq(enic, 0);
|
||||
unsigned int cq_wq = enic_cq_wq(enic, 0);
|
||||
unsigned int intr = enic_legacy_io_intr();
|
||||
unsigned int rq_work_to_do = budget;
|
||||
unsigned int wq_work_to_do = -1; /* no limit */
|
||||
unsigned int work_done, rq_work_done = 0, wq_work_done;
|
||||
int err;
|
||||
|
||||
wq_work_done = vnic_cq_service(&enic->cq[cq_wq], wq_work_to_do,
|
||||
enic_wq_service, NULL);
|
||||
|
||||
if (!enic_poll_lock_napi(&enic->rq[cq_rq])) {
|
||||
if (wq_work_done > 0)
|
||||
vnic_intr_return_credits(&enic->intr[intr],
|
||||
wq_work_done,
|
||||
0 /* dont unmask intr */,
|
||||
0 /* dont reset intr timer */);
|
||||
return budget;
|
||||
}
|
||||
|
||||
if (budget > 0)
|
||||
rq_work_done = vnic_cq_service(&enic->cq[cq_rq],
|
||||
rq_work_to_do, enic_rq_service, NULL);
|
||||
|
||||
/* Accumulate intr event credits for this polling
|
||||
* cycle. An intr event is the completion of a
|
||||
* a WQ or RQ packet.
|
||||
*/
|
||||
|
||||
work_done = rq_work_done + wq_work_done;
|
||||
|
||||
if (work_done > 0)
|
||||
vnic_intr_return_credits(&enic->intr[intr],
|
||||
work_done,
|
||||
0 /* don't unmask intr */,
|
||||
0 /* don't reset intr timer */);
|
||||
|
||||
err = vnic_rq_fill(&enic->rq[0], enic_rq_alloc_buf);
|
||||
enic_poll_unlock_napi(&enic->rq[cq_rq], napi);
|
||||
|
||||
/* Buffer allocation failed. Stay in polling
|
||||
* mode so we can try to fill the ring again.
|
||||
*/
|
||||
|
||||
if (err)
|
||||
rq_work_done = rq_work_to_do;
|
||||
|
||||
if (rq_work_done < rq_work_to_do) {
|
||||
|
||||
/* Some work done, but not enough to stay in polling,
|
||||
* exit polling
|
||||
*/
|
||||
|
||||
napi_complete(napi);
|
||||
vnic_intr_unmask(&enic->intr[intr]);
|
||||
}
|
||||
|
||||
return rq_work_done;
|
||||
}
|
||||
|
||||
static void enic_set_int_moderation(struct enic *enic, struct vnic_rq *rq)
|
||||
{
|
||||
unsigned int intr = enic_msix_rq_intr(enic, rq->index);
|
||||
|
|
@ -1271,6 +1207,77 @@ static void enic_calc_int_moderation(struct enic *enic, struct vnic_rq *rq)
|
|||
pkt_size_counter->small_pkt_bytes_cnt = 0;
|
||||
}
|
||||
|
||||
static int enic_poll(struct napi_struct *napi, int budget)
|
||||
{
|
||||
struct net_device *netdev = napi->dev;
|
||||
struct enic *enic = netdev_priv(netdev);
|
||||
unsigned int cq_rq = enic_cq_rq(enic, 0);
|
||||
unsigned int cq_wq = enic_cq_wq(enic, 0);
|
||||
unsigned int intr = enic_legacy_io_intr();
|
||||
unsigned int rq_work_to_do = budget;
|
||||
unsigned int wq_work_to_do = -1; /* no limit */
|
||||
unsigned int work_done, rq_work_done = 0, wq_work_done;
|
||||
int err;
|
||||
|
||||
wq_work_done = vnic_cq_service(&enic->cq[cq_wq], wq_work_to_do,
|
||||
enic_wq_service, NULL);
|
||||
|
||||
if (!enic_poll_lock_napi(&enic->rq[cq_rq])) {
|
||||
if (wq_work_done > 0)
|
||||
vnic_intr_return_credits(&enic->intr[intr],
|
||||
wq_work_done,
|
||||
0 /* dont unmask intr */,
|
||||
0 /* dont reset intr timer */);
|
||||
return budget;
|
||||
}
|
||||
|
||||
if (budget > 0)
|
||||
rq_work_done = vnic_cq_service(&enic->cq[cq_rq],
|
||||
rq_work_to_do, enic_rq_service, NULL);
|
||||
|
||||
/* Accumulate intr event credits for this polling
|
||||
* cycle. An intr event is the completion of a
|
||||
* a WQ or RQ packet.
|
||||
*/
|
||||
|
||||
work_done = rq_work_done + wq_work_done;
|
||||
|
||||
if (work_done > 0)
|
||||
vnic_intr_return_credits(&enic->intr[intr],
|
||||
work_done,
|
||||
0 /* don't unmask intr */,
|
||||
0 /* don't reset intr timer */);
|
||||
|
||||
err = vnic_rq_fill(&enic->rq[0], enic_rq_alloc_buf);
|
||||
enic_poll_unlock_napi(&enic->rq[cq_rq], napi);
|
||||
|
||||
/* Buffer allocation failed. Stay in polling
|
||||
* mode so we can try to fill the ring again.
|
||||
*/
|
||||
|
||||
if (err)
|
||||
rq_work_done = rq_work_to_do;
|
||||
if (enic->rx_coalesce_setting.use_adaptive_rx_coalesce)
|
||||
/* Call the function which refreshes the intr coalescing timer
|
||||
* value based on the traffic.
|
||||
*/
|
||||
enic_calc_int_moderation(enic, &enic->rq[0]);
|
||||
|
||||
if (rq_work_done < rq_work_to_do) {
|
||||
|
||||
/* Some work done, but not enough to stay in polling,
|
||||
* exit polling
|
||||
*/
|
||||
|
||||
napi_complete(napi);
|
||||
if (enic->rx_coalesce_setting.use_adaptive_rx_coalesce)
|
||||
enic_set_int_moderation(enic, &enic->rq[0]);
|
||||
vnic_intr_unmask(&enic->intr[intr]);
|
||||
}
|
||||
|
||||
return rq_work_done;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RFS_ACCEL
|
||||
static void enic_free_rx_cpu_rmap(struct enic *enic)
|
||||
{
|
||||
|
|
@ -1407,10 +1414,8 @@ static int enic_poll_msix_rq(struct napi_struct *napi, int budget)
|
|||
if (err)
|
||||
work_done = work_to_do;
|
||||
if (enic->rx_coalesce_setting.use_adaptive_rx_coalesce)
|
||||
/* Call the function which refreshes
|
||||
* the intr coalescing timer value based on
|
||||
* the traffic. This is supported only in
|
||||
* the case of MSI-x mode
|
||||
/* Call the function which refreshes the intr coalescing timer
|
||||
* value based on the traffic.
|
||||
*/
|
||||
enic_calc_int_moderation(enic, &enic->rq[rq]);
|
||||
|
||||
|
|
@ -1569,12 +1574,6 @@ static void enic_set_rx_coal_setting(struct enic *enic)
|
|||
int index = -1;
|
||||
struct enic_rx_coal *rx_coal = &enic->rx_coalesce_setting;
|
||||
|
||||
/* If intr mode is not MSIX, do not do adaptive coalescing */
|
||||
if (VNIC_DEV_INTR_MODE_MSIX != vnic_dev_get_intr_mode(enic->vdev)) {
|
||||
netdev_info(enic->netdev, "INTR mode is not MSIX, Not initializing adaptive coalescing");
|
||||
return;
|
||||
}
|
||||
|
||||
/* 1. Read the link speed from fw
|
||||
* 2. Pick the default range for the speed
|
||||
* 3. Update it in enic->rx_coalesce_setting
|
||||
|
|
@ -2485,6 +2484,11 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
goto err_out_iounmap;
|
||||
}
|
||||
|
||||
err = vnic_devcmd_init(enic->vdev);
|
||||
|
||||
if (err)
|
||||
goto err_out_vnic_unregister;
|
||||
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
/* Get number of subvnics */
|
||||
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV);
|
||||
|
|
@ -2659,8 +2663,8 @@ err_out_disable_sriov_pp:
|
|||
pci_disable_sriov(pdev);
|
||||
enic->priv_flags &= ~ENIC_SRIOV_ENABLED;
|
||||
}
|
||||
err_out_vnic_unregister:
|
||||
#endif
|
||||
err_out_vnic_unregister:
|
||||
vnic_dev_unregister(enic->vdev);
|
||||
err_out_iounmap:
|
||||
enic_iounmap(enic);
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue