Re: [PATCH net] net: sched: fix NULL pointer dereference when action calls some targets
On Thu, Aug 17, 2017 at 5:57 PM, Cong Wang wrote: > On Wed, Aug 16, 2017 at 1:39 AM, Xin Long wrote: >> On Wed, Aug 9, 2017 at 7:33 AM, Cong Wang wrote: >>> On Mon, Aug 7, 2017 at 7:33 PM, Xin Long wrote: On Tue, Aug 8, 2017 at 9:15 AM, Cong Wang wrote: > This looks like a completely API burden? netfilter xt targets are not really compatible with netsched action. I've got to say, the patch is just a way to make checkentry return false and avoid panic. like [1] said >>> >>> I don't doubt you fix a crash, I am thinking if we can >>> "fix" the API instead of fixing the caller. >> Hi, Cong, >> >> For now, I don't think it's possible to change APIs or some of their targets >> for the panic caused by action xt calling. >> >> The common way should be fixed in net_sched side. >> >> Given that the issue is very easy to triggered, >> let's wait for netfilter's replies for another few days, >> otherwise I will repost the fix, agree ? > > Yeah, no objections from me. > > By the way, do you know how other callers of this API > use 'entryinfo'? Do they pass the address of the struct > on stack too? afaik, two places: 1. translate_table -> find_check_entry -> check_target -> xt_check_target most iptables operations go there and .entryinfo is set in check_target with struct ipt_entry *e, which is an iptable rule, so can't be NULL. (as well as ip6table in netfilter/ip6_tables.c ) 2. nft_target_init -> xt_check_target, where nft_target_set_tgchk_param does the exact thing to set .entryinfo with a local varible union nft_entry e: union nft_entry { struct ipt_entry e4; struct ip6t_entry e6; struct ebt_entry ebt; struct arpt_entry arp; }; case 2 is actually what nft does to use xt targets, so net/sched action should do the same.
[PATCH v2 6/6] net: stmmac: dwmac-sun8i: choose internal PHY via phy-is-integrated
The current way to find if the phy is internal is to compare DT phy-mode and emac_variant/internal_phy. But it will negate a possible future SoC where an external PHY use the same phy mode than the internal one. This patch adds a new way to find if the PHY is internal, via the phy-is-integrated property. Since the internal_phy variable does not need anymore to contain the xMII mode used by the internal PHY, it is still used for knowing the presence of an internal PHY, so it is modified to a boolean soc_has_internal_phy. Signed-off-by: Corentin Labbe --- drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 16 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c index fffd6d5fc907..672553b652bd 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c @@ -41,14 +41,14 @@ * This value is used for disabling properly EMAC * and used as a good starting value in case of the * boot process(uboot) leave some stuff. - * @internal_phy: Does the MAC embed an internal PHY + * @soc_has_internal_phy: Does the MAC embed an internal PHY * @support_mii: Does the MAC handle MII * @support_rmii: Does the MAC handle RMII * @support_rgmii: Does the MAC handle RGMII */ struct emac_variant { u32 default_syscon_value; - int internal_phy; + bool soc_has_internal_phy; bool support_mii; bool support_rmii; bool support_rgmii; @@ -75,7 +75,7 @@ struct sunxi_priv_data { static const struct emac_variant emac_variant_h3 = { .default_syscon_value = 0x58000, - .internal_phy = PHY_INTERFACE_MODE_MII, + .soc_has_internal_phy = true, .support_mii = true, .support_rmii = true, .support_rgmii = true @@ -83,20 +83,20 @@ static const struct emac_variant emac_variant_h3 = { static const struct emac_variant emac_variant_v3s = { .default_syscon_value = 0x38000, - .internal_phy = PHY_INTERFACE_MODE_MII, + .soc_has_internal_phy = true, .support_mii = true }; static const struct emac_variant emac_variant_a83t = { .default_syscon_value = 0, - .internal_phy = 0, + .soc_has_internal_phy = false, .support_mii = true, .support_rgmii = true }; static const struct emac_variant emac_variant_a64 = { .default_syscon_value = 0, - .internal_phy = 0, + .soc_has_internal_phy = false, .support_mii = true, .support_rmii = true, .support_rgmii = true @@ -648,7 +648,7 @@ static int sun8i_dwmac_set_syscon(struct stmmac_priv *priv) "Current syscon value is not the default %x (expect %x)\n", val, reg); - if (gmac->variant->internal_phy) { + if (gmac->variant->soc_has_internal_phy) { if (!gmac->use_internal_phy) { /* switch to external PHY interface */ reg &= ~H3_EPHY_SELECT; @@ -932,7 +932,7 @@ static int sun8i_dwmac_probe(struct platform_device *pdev) } plat_dat->interface = of_get_phy_mode(dev->of_node); - if (plat_dat->interface == gmac->variant->internal_phy) { + if (of_property_read_bool(plat_dat->phy_node, "phy-is-integrated")) { dev_info(&pdev->dev, "Will use internal PHY\n"); gmac->use_internal_phy = true; gmac->ephy_clk = of_clk_get(plat_dat->phy_node, 0); -- 2.13.0
[PATCH v2 5/6] ARM: sun8i: orangepi-one: Set phy-is-integrated to the internal phy node
This patch add the new phy-is-integrated property to the internal PHY node. Signed-off-by: Corentin Labbe --- arch/arm/boot/dts/sun8i-h3-orangepi-one.dts | 4 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts index 6880268e8b87..22c471473909 100644 --- a/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts +++ b/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts @@ -105,6 +105,10 @@ status = "okay"; }; +&int_mii_phy { + phy-is-integrated; +}; + &mmc0 { pinctrl-names = "default"; pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>; -- 2.13.0
[PATCH v2 4/6] ARM: sun8i: orangepi-2: Set phy-is-integrated to the internal phy node
This patch add the new phy-is-integrated property to the internal PHY node. Signed-off-by: Corentin Labbe --- arch/arm/boot/dts/sun8i-h3-orangepi-2.dts | 4 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts index 17cdeae19c6f..0801c808c5e5 100644 --- a/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts +++ b/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts @@ -131,6 +131,10 @@ status = "okay"; }; +&int_mii_phy { + phy-is-integrated; +}; + &mmc0 { pinctrl-names = "default"; pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>; -- 2.13.0
[PATCH v2 1/6] ARM: sun8i: orangepipc: Set phy-is-integrated to the internal phy node
This patch add the new phy-is-integrated property to the internal PHY node. Signed-off-by: Corentin Labbe --- arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts | 4 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts index f5f0f15a2088..68a618b5f18c 100644 --- a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts +++ b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts @@ -131,6 +131,10 @@ status = "okay"; }; +&int_mii_phy { + phy-is-integrated; +}; + &mmc0 { pinctrl-names = "default"; pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>; -- 2.13.0
[PATCH v2 3/6] ARM: sun8i: nanopi-neo: Set phy-is-integrated to the internal phy node
This patch add the new phy-is-integrated property to the internal PHY node. Signed-off-by: Corentin Labbe --- arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts | 4 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts b/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts index 78f6c24952dd..e77b51c98374 100644 --- a/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts +++ b/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts @@ -53,3 +53,7 @@ allwinner,leds-active-low; status = "okay"; }; + +&int_mii_phy { + phy-is-integrated; +}; -- 2.13.0
[PATCH v2 0/6] net: stmmac: Detect PHY location with phy-is-integrated
Hello The current way to find if the phy is internal is to compare DT phy-mode and emac_variant/internal_phy. But it will negate a possible future SoC where an external PHY use the same phy mode than the integrated one. This patchs series adds a new way to find if the PHY is integrated, via the phy-is-integrated DT property. Since it exists both integrated and external ethernet-phy@1, they are merged in the final DTB and so share all properties. For avoiding this, the phy-is-integrated is added only to board DT. The first five patchs should go via the sunxi tree. the last one should go via the net tree. Note that this serie will need backporting the patch "Documentation: net: phy: Add phy-is-integrated binding" which is in net-next Thanks Regards Changes since v1: - Dropped phy-is-integrated documentation patch since another same patch was already merged - Moved phy-is-integrated from SoC dtsi to final board DT. Corentin Labbe (6): ARM: sun8i: orangepipc: Set phy-is-integrated to the internal phy node ARM: sun8i: beelink-x2: Set phy-is-integrated to the internal phy node ARM: sun8i: nanopi-neo: Set phy-is-integrated to the internal phy node ARM: sun8i: orangepi-2: Set phy-is-integrated to the internal phy node ARM: sun8i: orangepi-one: Set phy-is-integrated to the internal phy node net: stmmac: dwmac-sun8i: choose internal PHY via phy-is-integrated arch/arm/boot/dts/sun8i-h3-beelink-x2.dts | 4 arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts | 4 arch/arm/boot/dts/sun8i-h3-orangepi-2.dts | 4 arch/arm/boot/dts/sun8i-h3-orangepi-one.dts | 4 arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts| 4 drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 16 6 files changed, 28 insertions(+), 8 deletions(-) -- 2.13.0
[PATCH v2 2/6] ARM: sun8i: beelink-x2: Set phy-is-integrated to the internal phy node
This patch add the new phy-is-integrated property to the internal PHY node. Signed-off-by: Corentin Labbe --- arch/arm/boot/dts/sun8i-h3-beelink-x2.dts | 4 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/sun8i-h3-beelink-x2.dts b/arch/arm/boot/dts/sun8i-h3-beelink-x2.dts index 546837ccd8af..d0517240d5e3 100644 --- a/arch/arm/boot/dts/sun8i-h3-beelink-x2.dts +++ b/arch/arm/boot/dts/sun8i-h3-beelink-x2.dts @@ -121,6 +121,10 @@ status = "okay"; }; +&int_mii_phy { + phy-is-integrated; +}; + &mmc0 { pinctrl-names = "default"; pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>; -- 2.13.0
[PATCH] vsock: only load vmci transport on VMware hypervisor by default
Without the patch, vmw_vsock_vmci_transport.ko can automatically load when an application creates an AF_VSOCK socket. This is the expected good behavior on VMware hypervisor, but as we are going to add hv_sock.ko (i.e. Hyper-V transport for AF_VSOCK), we should make sure vmw_vsock_vmci_transport.ko can't load on Hyper-V, otherwise there is a -EBUSY conflict when both vmw_vsock_vmci_transport.ko and hv_sock.ko try to call vsock_core_init() on Hyper-V. On the other hand, hv_sock.ko can only load on Hyper-V, because it depends on hv_vmbus.ko, which detects Hyper-V in hv_acpi_init(). KVM's vsock_virtio_transport doesn't have the issue because it doesn't define MODULE_ALIAS_NETPROTO(PF_VSOCK). The patch also adds a module parameter "skip_hypervisor_check" for vmw_vsock_vmci_transport.ko. Signed-off-by: Dexuan Cui Cc: Alok Kataria Cc: Andy King Cc: Adit Ranadive Cc: George Zhang Cc: Jorgen Hansen Cc: K. Y. Srinivasan Cc: Haiyang Zhang Cc: Stephen Hemminger --- net/vmw_vsock/Kconfig | 2 +- net/vmw_vsock/vmci_transport.c | 11 +++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/net/vmw_vsock/Kconfig b/net/vmw_vsock/Kconfig index a24369d..3f52929 100644 --- a/net/vmw_vsock/Kconfig +++ b/net/vmw_vsock/Kconfig @@ -17,7 +17,7 @@ config VSOCKETS config VMWARE_VMCI_VSOCKETS tristate "VMware VMCI transport for Virtual Sockets" - depends on VSOCKETS && VMWARE_VMCI + depends on VSOCKETS && VMWARE_VMCI && HYPERVISOR_GUEST help This module implements a VMCI transport for Virtual Sockets. diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c index 10ae782..c068873 100644 --- a/net/vmw_vsock/vmci_transport.c +++ b/net/vmw_vsock/vmci_transport.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -73,6 +74,10 @@ struct vmci_transport_recv_pkt_info { struct vmci_transport_packet pkt; }; +static bool skip_hypervisor_check; +module_param(skip_hypervisor_check, bool, 0444); +MODULE_PARM_DESC(hot_add, "If set, attempt to load on non-VMware platforms"); + static LIST_HEAD(vmci_transport_cleanup_list); static DEFINE_SPINLOCK(vmci_transport_cleanup_lock); static DECLARE_WORK(vmci_transport_cleanup_work, vmci_transport_cleanup); @@ -2085,6 +2090,12 @@ static int __init vmci_transport_init(void) { int err; + /* Check if we are running on VMware's hypervisor and bail out +* if we are not. +*/ + if (!skip_hypervisor_check && x86_hyper != &x86_hyper_vmware) + return -ENODEV; + /* Create the datagram handle that we will use to send and receive all * VSocket control messages for this context. */ -- 2.7.4
RE: [PATCH net-next 1/3] VMCI: only load on VMware hypervisor
> From: Dexuan Cui > Sent: Wednesday, August 16, 2017 15:34 > > From: Jorgen S. Hansen [mailto:jhan...@vmware.com] > > > Without the patch, vmw_vsock_vmci_transport.ko and vmw_vmci.ko can > > > automatically load when an application creates an AF_VSOCK socket. > > > > > > This is the expected good behavior on VMware hypervisor, but as we > > > are going to add hv_sock.ko (i.e. Hyper-V transport for AF_VSOCK), we > > > should make sure vmw_vsock_vmci_transport.ko doesn't load on Hyper- > V, > > > otherwise there is a -EBUSY conflict when both > vmw_vsock_vmci_transport.ko > > > and hv_sock.ko try to call vsock_core_init() on Hyper-V. > > > > The VMCI driver (vmw_vmci.ko) is used both by the VMware guest support > > (VMware Tools primarily) and by our Workstation product. Always > disabling the > > VMCI driver on Hyper-V means that user won’t be able to run Workstation > > nested in Linux VMs on Hyper-V. Since the VMCI driver itself isn’t the > problem > > here, maybe we could move the check to vmw_vsock_vmci_transport.ko? > > Ideally, there should be some way for a user to have access to both > protocols, > > but for now disabling the VMCI socket transport for Hyper-V (possibly with > a > > module option to skip that check and always load it) but leaving the VMCI > driver > > functional would be better, > > > > Jorgen > > Thank you for explaining the background! > Then I'll make a new patch, following your suggestion. > > -- Dexuan Hi Jorgen, David, Just now I posted a new patch "[PATCH] vsock: only load vmci transport on VMware hypervisor by default" to replace this patch. @Jorgen: FWIW, with the new patch, when I create an AF_VSOCK sockets on Hyper-V, vmw_vmci.ko is also automatically loaded and 3 lines of kernel messages are printed, but I think I'm OK with this, since it's harmless. -- Dexuan
[PATCH] liquidio: fix spelling mistake: "interuupt" -> "interrupt"
From: Colin Ian King Trivial fix to spelling mistake in dev_info message Signed-off-by: Colin Ian King --- drivers/net/ethernet/cavium/liquidio/lio_ethtool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c b/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c index 08aa06c90d46..a63ddf07f168 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c @@ -412,7 +412,7 @@ lio_irq_reallocate_irqs(struct octeon_device *oct, uint32_t num_ioqs) kfree(oct->irq_name_storage); oct->irq_name_storage = NULL; if (octeon_setup_interrupt(oct, num_ioqs)) { - dev_info(&oct->pci_dev->dev, "Setup interuupt failed\n"); + dev_info(&oct->pci_dev->dev, "Setup interrupt failed\n"); return 1; } -- 2.11.0
[PATCH][net-next] net: hns3: ensure media_type is unitialized
From: Colin Ian King Media type is only set if h->ae_algo->ops->get_media_type is called so there is a possibility that media_type is uninitialized when it is used a switch statement. Fix this by initializing media_type to HNAE3_MEDIA_TYPE_UNKNOWN. Detected by CoverityScan, CID#1452624("Uninitialized scalar variable") Fixes: 496d03e960ae ("net: hns3: Add Ethtool support to HNS3 driver") Signed-off-by: Colin Ian King --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_ethtool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_ethtool.c index 0ad65e47c77e..53cab3ad4cda 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_ethtool.c @@ -304,7 +304,7 @@ static int hns3_get_link_ksettings(struct net_device *netdev, struct hnae3_handle *h = priv->ae_handle; u32 supported_caps; u32 advertised_caps; - u8 media_type; + u8 media_type = HNAE3_MEDIA_TYPE_UNKNOWN; u8 link_stat; u8 auto_neg; u8 duplex; -- 2.11.0
Re: [PATCH net-next] phylink: Fix an uninitialized variable bug
On Thu, Aug 10, 2017 at 05:21:12PM +0200, Andrew Lunn wrote: > On Thu, Aug 10, 2017 at 12:35:50AM +0300, Dan Carpenter wrote: > > "ret" isn't necessarily initialized here. > > > > Fixes: 9525ae83959b ("phylink: add phylink infrastructure") > > Signed-off-by: Dan Carpenter > > Reviewed-by: Andrew Lunn Thanks, not sure how that got missed - it was probably introduced when migrating the code to ksettings. -- RMK's Patch system: http://www.armlinux.org.uk/developer/patches/ FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up According to speedtest.net: 8.21Mbps down 510kbps up
Re: Something hitting my total number of connections to the server
On Wed, Aug 16, 2017 at 4:04 PM, Eric Dumazet wrote: > On Wed, 2017-08-16 at 10:18 +0530, Akshat Kakkar wrote: >> On Mon, Aug 14, 2017 at 2:37 PM, Akshat Kakkar wrote: >> > I have centos 7.3 (Kernel 3.10) running on a server with 128GB RAM and >> > 2 x 10 Core Xeon Processor. >> > I have hosted a webserver on it and enabled ssh for remote maintenance. >> > Previously it was running on Centos 6.3. >> > After upgrading to CentOS 7.3, occasionally (probably when number of >> > hits are more on the server), I am not able to create new connections >> > (neither on web nor on ssh). Existing connections keeps on running >> > fine. >> > >> > I did packet capturing using tcpdump to understand if its some >> > intermediate network issue. >> > What I found was the server is not replying for new SYN requests. >> > >> > So it's clear that its not at all application issue. Also, there are >> > no logs in applications logs for any connections dropped, if any. >> > >> > I check my firewall rules if there is some rate limiting imposed. >> > There is nothing in there. >> > >> > I check tc, if by mistake some rate limiting is imposed. There is >> > nothing in there too. >> > >> > I have increased noOfFiles to 100 and other sysctl parameters, but >> > the issue is still there. >> > >> > Has anybody experienced the same? >> > >> > How to go about? Anybody ... Please Help!!! >> >> Its getting lonely out here. Anybody there ??? > > We wont help you unless you use a recent kernel. > > 3.10 misses all recent improvements in TCP stack (4 years of hard work) > > > > > I upgraded to 4.4 but still experiencing same issue. Please help.
RE: [PATCH net] datagram: When peeking datagrams with offset < 0 don't skip empty skbs
From: Willem de Bruijn > Sent: 17 August 2017 00:27 > Actually, it is safe even without the check. Overflow of the signed integer > is benign here. IIRC the C language states that 'signed integer overflow' is undefined. So 'MAXINT + 1' doesn't have to equal '-MAXINT - 1' (as one would expect on a 2's compliment system). While the linux kernel probably won't run on systems where this isn't true (eg where signed arithmetic saturates) gcc will assume it can't happen and optimise code with that assumption. This may not matter here ... David
Re: [PATCH] Adding-Agile-SD-TCP-module-and-modifying-Kconfig-and-makefile (fwd)
It is intentional that the code on lines 122 and 124 is the same? julia -- Forwarded message -- Date: Thu, 17 Aug 2017 09:18:50 +0800 From: kbuild test robot To: kbu...@01.org Cc: Julia Lawall Subject: Re: [PATCH] Adding-Agile-SD-TCP-module-and-modifying-Kconfig-and-makefile Hi mohamedalrshah, [auto build test WARNING on net/master] [also build test WARNING on v4.13-rc5 next-20170816] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/mohamedalrshah/Adding-Agile-SD-TCP-module-and-modifying-Kconfig-and-makefile/20170817-055643 :: branch date: 3 hours ago :: commit date: 3 hours ago >> net/ipv4/tcp_agilesd.c:121:1-3: WARNING: possible condition with no effect >> (if == else) # https://github.com/0day-ci/linux/commit/839e8cb5e5f068e0310442909f9a89753a218c59 git remote add linux-review https://github.com/0day-ci/linux git remote update linux-review git checkout 839e8cb5e5f068e0310442909f9a89753a218c59 vim +121 net/ipv4/tcp_agilesd.c 839e8cb5 mohamedalrshah 2017-08-15 111 839e8cb5 mohamedalrshah 2017-08-15 112 /* This function is called when the TCP flow detects a loss. 839e8cb5 mohamedalrshah 2017-08-15 113 * It returns the slow start threshold of a flow, after a packet loss is detected. */ 839e8cb5 mohamedalrshah 2017-08-15 114 static u32 agilesdtcp_recalc_ssthresh(struct sock *sk) 839e8cb5 mohamedalrshah 2017-08-15 115 { 839e8cb5 mohamedalrshah 2017-08-15 116 const struct tcp_sock *tp = tcp_sk(sk); 839e8cb5 mohamedalrshah 2017-08-15 117 struct agilesdtcp *ca = inet_csk_ca(sk); 839e8cb5 mohamedalrshah 2017-08-15 118 839e8cb5 mohamedalrshah 2017-08-15 119 ca->loss_cwnd = tp->snd_cwnd; 839e8cb5 mohamedalrshah 2017-08-15 120 839e8cb5 mohamedalrshah 2017-08-15 @121 if (ca->agilesd_tcp_status == CA) 839e8cb5 mohamedalrshah 2017-08-15 122 ca->degraded_loss_cwnd = max((tp->snd_cwnd * beta) / SCALE, 2U); 839e8cb5 mohamedalrshah 2017-08-15 123 else 839e8cb5 mohamedalrshah 2017-08-15 124 ca->degraded_loss_cwnd = max((tp->snd_cwnd * beta) / SCALE, 2U); 839e8cb5 mohamedalrshah 2017-08-15 125 839e8cb5 mohamedalrshah 2017-08-15 126 ca->frac_tracer = 0; 839e8cb5 mohamedalrshah 2017-08-15 127 839e8cb5 mohamedalrshah 2017-08-15 128 return ca->degraded_loss_cwnd; 839e8cb5 mohamedalrshah 2017-08-15 129 } 839e8cb5 mohamedalrshah 2017-08-15 130 --- 0-DAY kernel test infrastructureOpen Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
Re: [PATCH] i40e{,vf}: Fix out-of-bound cpumask read in IRQ affinity handler
Jeff, Dave, This is a pretty bad issue as one can crash a kernel quite easily by forcing interrupt affinity changes. We now have three versions of this patch, with exactly the same code changes. I posted mine as I independently found this issue last week and didn't notice Juergen patch which was posted two days earlier. I didn't notice the other patch in the pull request from Jeff either, I just checked his tree and it wasn't there until yesterday. Frankly speaking, I think this was quite vaguely worded and hidden in the cover letter, and queued up for net-next, while it should really go to net as it fixes a panic in mainline. FWIW, I don't care too much about which version ends up applied, even though I'd prefer one which a commit message which clearly describes the issue with its implications and reports the right Fixed: tag. Both my patch and Juergen's v2, posted later, are fine by me (I still think mine is a bit clearer). -- Stefano On Tue, 15 Aug 2017 12:30:14 +0200 Stefano Brivio wrote: > The cpumask used in i40e{,vf}_irq_affinity_notify() is allocated > by irq_affinity_notify() with alloc_cpumask_var(), which doesn't > allocate NR_CPUS bits, but only nr_cpumask_bits bits. If we just > dereference it, we'll read way more than what is allocated, e.g. > 1024 bytes vs. 8 bytes allocated on x86_64 machine with 24 CPUs. > > Use cpumask_copy() instead. A comprehensive explanation is given > in the comments about cpumask_var_t, in include/linux/cpumask.h. > > KASAN reports: > [ 25.242312] BUG: KASAN: slab-out-of-bounds in > i40e_irq_affinity_notify+0x30/0x50 [i40e] at addr 880462eea960 > [ 25.242315] Read of size 1024 by task kworker/2:1/170 > [ 25.242322] CPU: 2 PID: 170 Comm: kworker/2:1 Not tainted > 4.11.0-22.el7a.x86_64 #1 > [ 25.242325] Hardware name: HP ProLiant DL380 Gen9, BIOS P89 05/06/2015 > [ 25.242336] Workqueue: events irq_affinity_notify > [ 25.242340] Call Trace: > [ 25.242350] dump_stack+0x63/0x8d > [ 25.242358] kasan_object_err+0x21/0x70 > [ 25.242364] kasan_report+0x288/0x540 > [ 25.242397] ? i40e_irq_affinity_notify+0x30/0x50 [i40e] > [ 25.242403] check_memory_region+0x13c/0x1a0 > [ 25.242408] __asan_loadN+0xf/0x20 > [ 25.242440] i40e_irq_affinity_notify+0x30/0x50 [i40e] > [ 25.242446] irq_affinity_notify+0x1b4/0x230 > [ 25.242452] ? irq_set_affinity_notifier+0x130/0x130 > [ 25.242457] ? kasan_slab_free+0x89/0xc0 > [ 25.242466] process_one_work+0x32f/0x6f0 > [ 25.242472] worker_thread+0x89/0x770 > [ 25.242481] ? pci_mmcfg_check_reserved+0xc0/0xc0 > [ 25.242488] kthread+0x18c/0x1e0 > [ 25.242493] ? process_one_work+0x6f0/0x6f0 > [ 25.242499] ? kthread_create_on_node+0xc0/0xc0 > [ 25.242506] ret_from_fork+0x2c/0x40 > [ 25.242511] Object at 880462eea960, in cache kmalloc-8 size: 8 > [ 25.242513] Allocated: > [ 25.242514] PID = 170 > [ 25.242522] save_stack_trace+0x1b/0x20 > [ 25.242529] save_stack+0x46/0xd0 > [ 25.242533] kasan_kmalloc+0xad/0xe0 > [ 25.242537] __kmalloc_node+0x12c/0x2b0 > [ 25.242542] alloc_cpumask_var_node+0x3c/0x60 > [ 25.242546] alloc_cpumask_var+0xe/0x10 > [ 25.242550] irq_affinity_notify+0x94/0x230 > [ 25.242555] process_one_work+0x32f/0x6f0 > [ 25.242559] worker_thread+0x89/0x770 > [ 25.242564] kthread+0x18c/0x1e0 > [ 25.242568] ret_from_fork+0x2c/0x40 > [ 25.242569] Freed: > [ 25.242570] PID = 0 > [ 25.242572] (stack is not available) > [ 25.242573] Memory state around the buggy address: > [ 25.242578] 880462eea800: fc fc 00 fc fc 00 fc fc 00 fc fc 00 fc fc > fb fc > [ 25.242582] 880462eea880: fc fb fc fc fb fc fc 00 fc fc 00 fc fc 00 > fc fc > [ 25.242586] >880462eea900: 00 fc fc 00 fc fc 00 fc fc fb fc fc 00 fc > fc fc > [ 25.242588] ^ > [ 25.242592] 880462eea980: fc fc fc fc fc fc fc fc fc fc fc fc fc fc > fc fc > [ 25.242596] 880462eeaa00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc > fc fc > [ 25.242597] > == > > Fixes: 96db776a3682 ("i40e/i40evf: fix interrupt affinity bug") > Signed-off-by: Stefano Brivio > --- > This should be considered for -stable, back to 4.10. > > drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- > drivers/net/ethernet/intel/i40evf/i40evf_main.c | 2 +- > 2 files changed, 2 insertions(+), 2 deletions(-) > > diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c > b/drivers/net/ethernet/intel/i40e/i40e_main.c > index 2db93d3f6d23..c0e42d162c7c 100644 > --- a/drivers/net/ethernet/intel/i40e/i40e_main.c > +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c > @@ -3495,7 +3495,7 @@ static void i40e_irq_affinity_notify(struct > irq_affinity_notify *notify, > struct i40e_q_vector *q_vector = > container_of(notify, struct i40e_q_vector, affinity_notify); > > - q_vector->affinity_mask = *mask; > + cpumask_copy(&q_vec
Re: [PATCH net] net: sched: fix NULL pointer dereference when action calls some targets
On Wed, Aug 16, 2017 at 08:39:44PM +1200, Xin Long wrote: > On Wed, Aug 9, 2017 at 7:33 AM, Cong Wang wrote: > > On Mon, Aug 7, 2017 at 7:33 PM, Xin Long wrote: > >> On Tue, Aug 8, 2017 at 9:15 AM, Cong Wang wrote: > >>> This looks like a completely API burden? > >> netfilter xt targets are not really compatible with netsched action. > >> I've got to say, the patch is just a way to make checkentry return > >> false and avoid panic. like [1] said > > > > I don't doubt you fix a crash, I am thinking if we can > > "fix" the API instead of fixing the caller. > Hi, Cong, > > For now, I don't think it's possible to change APIs or some of their targets > for the panic caused by action xt calling. > > The common way should be fixed in net_sched side. > > Given that the issue is very easy to triggered, > let's wait for netfilter's replies for another few days, > otherwise I will repost the fix, agree ? Please, post the workaround so the kernel doesn't crash anymore. This is going to be very hard to fix, it's broken since the very beginning... Thanks!
[RFC PATCH v2 1/6] [net-next]net: sched: act_mirred: Extend redirect action to accept a traffic class
The Mirred/redirect action is extended to forward to a traffic class on the device. The traffic class index needs to be provided in addition to the device's ifindex. Example: # tc filter add dev eth0 protocol ip parent : prio 1 flower\ dst_ip 192.168.1.1/32 ip_proto udp dst_port 22\ skip_sw action mirred ingress redirect dev eth0 tclass 1 v2: Introduced is_tcf_mirred_tc() helper function to check if the rule is supported in current offloaders. Removed the additional definitions for max number of TCs and its bitmask and replaced their usages with existing defines in linux/netdevice.h. Signed-off-by: Amritha Nambiar --- drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c |2 +- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c |2 +- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c|2 +- drivers/net/ethernet/mellanox/mlxsw/spectrum.c |3 ++- .../net/ethernet/mellanox/mlxsw/spectrum_flower.c |3 ++- drivers/net/ethernet/netronome/nfp/bpf/offload.c |1 + drivers/net/ethernet/netronome/nfp/flower/action.c |4 ++-- include/net/tc_act/tc_mirred.h | 16 include/uapi/linux/tc_act/tc_mirred.h |3 +++ net/dsa/slave.c|3 ++- net/sched/act_mirred.c | 15 +++ 11 files changed, 46 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c index 48970ba..54a7004 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c @@ -113,7 +113,7 @@ static int fill_action_fields(struct adapter *adap, } /* Re-direct to specified port in hardware. */ - if (is_tcf_mirred_egress_redirect(a)) { + if (is_tcf_mirred_egress_redirect(a) && !is_tcf_mirred_tc(a)) { struct net_device *n_dev; unsigned int i, index; bool found = false; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 5d674f9..5b67cf0 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -8995,7 +8995,7 @@ static int parse_tc_actions(struct ixgbe_adapter *adapter, } /* Redirect to a VF or a offloaded macvlan */ - if (is_tcf_mirred_egress_redirect(a)) { + if (is_tcf_mirred_egress_redirect(a) && !is_tcf_mirred_tc(a)) { int ifindex = tcf_mirred_ifindex(a); err = handle_redirect_action(adapter, ifindex, queue, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 3b10d3d..eae02f8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -1871,7 +1871,7 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts, return -EOPNOTSUPP; } - if (is_tcf_mirred_egress_redirect(a)) { + if (is_tcf_mirred_egress_redirect(a) && !is_tcf_mirred_tc(a)) { int ifindex = tcf_mirred_ifindex(a); struct net_device *out_dev, *encap_dev = NULL; struct mlx5e_priv *out_priv; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 90a95cd..ce0b114 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -1639,7 +1639,8 @@ static int mlxsw_sp_port_add_cls_matchall(struct mlxsw_sp_port *mlxsw_sp_port, tcf_exts_to_list(f->exts, &actions); a = list_first_entry(&actions, struct tc_action, list); - if (is_tcf_mirred_egress_mirror(a) && protocol == htons(ETH_P_ALL)) { + if (is_tcf_mirred_egress_mirror(a) && !is_tcf_mirred_tc(a) && + protocol == htons(ETH_P_ALL)) { struct mlxsw_sp_port_mall_mirror_tc_entry *mirror; mall_tc_entry->type = MLXSW_SP_PORT_MALL_MIRROR; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c index 95428b4..8ed3a0a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c @@ -71,7 +71,8 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp, err = mlxsw_sp_acl_rulei_act_trap(rulei); if (err) return err; - } else if (is_tcf_mirred_egress_redirect(a)) { + } else if (is_tcf_mirred_egress_redirect(a) && + !is_tcf_mirred_tc(a)) {
[RFC PATCH v2 2/6] [net-next]net: i40e: Maintain a mapping of TCs with the VSI seids
Add mapping of TCs with the seids of the channel VSIs. TC0 will be mapped to the main VSI seid and all other TCs are mapped to the seid of the channel VSI. Signed-off-by: Amritha Nambiar --- drivers/net/ethernet/intel/i40e/i40e.h |1 + drivers/net/ethernet/intel/i40e/i40e_main.c |2 ++ 2 files changed, 3 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 8852ac0..1391e5d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -738,6 +738,7 @@ struct i40e_vsi { atomic_t next_base_queue; struct list_head ch_list; + u16 tc_seid_map[I40E_MAX_TRAFFIC_CLASS]; void *priv; /* client driver data reference. */ diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 601a86d..b02da99 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -6127,6 +6127,7 @@ static int i40e_configure_queue_channels(struct i40e_vsi *vsi) int ret = 0, i; /* Create app vsi with the TCs. Main VSI with TC0 is already set up */ + vsi->tc_seid_map[0] = vsi->seid; for (i = 1; i < I40E_MAX_TRAFFIC_CLASS; i++) if (vsi->tc_config.enabled_tc & BIT(i)) { ch = kzalloc(sizeof(*ch), GFP_KERNEL); @@ -6156,6 +6157,7 @@ static int i40e_configure_queue_channels(struct i40e_vsi *vsi) i, ch->num_queue_pairs); goto err_free; } + vsi->tc_seid_map[i] = ch->seid; } return ret;
[RFC PATCH v2 0/6] Configure cloud filters in i40e via tc-flower classifier
This patch series enables configuring cloud filters in i40e using the tc-flower classifier. The only tc-filter action supported is to redirect packets to a traffic class on the same device. The tc/mirred:redirect action is extended to accept a traffic class to achieve this. The cloud filters are added for a VSI and are cleaned up when the VSI is deleted. The filters that match on L4 ports needs enhanced admin queue functions with big buffer support for extended general fields in Add/Remove Cloud filters command. Example: # tc qdisc add dev eth0 ingress # ethtool -K eth0 hw-tc-offload on # tc filter add dev eth0 protocol ip parent : prio 1 flower\ dst_ip 192.168.1.1/32 ip_proto udp dst_port 22\ skip_sw action mirred ingress redirect dev eth0 tclass 1 # tc filter show dev eth0 parent : filter protocol ip pref 1 flower chain 0 filter protocol ip pref 1 flower chain 0 handle 0x1 eth_type ipv4 ip_proto udp dst_ip 192.168.1.1 dst_port 22 skip_sw in_hw action order 1: mirred (Ingress Redirect to device eth0) stolen tclass 1 index 7 ref 1 bind 1 --- Amritha Nambiar (6): [net-next]net: sched: act_mirred: Extend redirect action to accept a traffic class [net-next]net: i40e: Maintain a mapping of TCs with the VSI seids [net-next]net: i40e: Extend set switch config command to accept cloud filter mode [net-next]net: i40e: Admin queue definitions for cloud filters [net-next]net: i40e: Clean up of cloud filters [net-next]net: i40e: Enable cloud filters in i40e via tc flower classifier drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c |2 drivers/net/ethernet/intel/i40e/i40e.h | 56 + drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h | 139 +++ drivers/net/ethernet/intel/i40e/i40e_common.c | 194 drivers/net/ethernet/intel/i40e/i40e_ethtool.c |2 drivers/net/ethernet/intel/i40e/i40e_main.c| 1003 +++- drivers/net/ethernet/intel/i40e/i40e_prototype.h | 19 drivers/net/ethernet/intel/i40e/i40e_type.h| 10 .../net/ethernet/intel/i40evf/i40e_adminq_cmd.h| 108 ++ drivers/net/ethernet/intel/ixgbe/ixgbe_main.c |2 drivers/net/ethernet/mellanox/mlx5/core/en_tc.c|2 drivers/net/ethernet/mellanox/mlxsw/spectrum.c |3 .../net/ethernet/mellanox/mlxsw/spectrum_flower.c |3 drivers/net/ethernet/netronome/nfp/bpf/offload.c |1 drivers/net/ethernet/netronome/nfp/flower/action.c |4 include/net/tc_act/tc_mirred.h | 16 include/uapi/linux/tc_act/tc_mirred.h |3 net/dsa/slave.c|3 net/sched/act_mirred.c | 15 19 files changed, 1543 insertions(+), 42 deletions(-) --
[RFC PATCH v2 5/6] [net-next]net: i40e: Clean up of cloud filters
Introduce the cloud filter datastructure and cleanup of cloud filters associated with the device. v2: Moved field comments in struct i40e_cloud_filter to the right. Removed hlist_empty check from i40e_cloud_filter_exit() Signed-off-by: Amritha Nambiar --- drivers/net/ethernet/intel/i40e/i40e.h |9 + drivers/net/ethernet/intel/i40e/i40e_main.c | 24 2 files changed, 33 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 1391e5d..ac57ab0 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -252,6 +252,12 @@ struct i40e_fdir_filter { u32 fd_id; }; +struct i40e_cloud_filter { + struct hlist_node cloud_node; + unsigned long cookie; + u16 seid; /* filter control */ +}; + #define I40E_ETH_P_LLDP0x88cc #define I40E_DCB_PRIO_TYPE_STRICT 0 @@ -419,6 +425,9 @@ struct i40e_pf { struct i40e_udp_port_config udp_ports[I40E_MAX_PF_UDP_OFFLOAD_PORTS]; u16 pending_udp_bitmap; + struct hlist_head cloud_filter_list; + u16 num_cloud_filters; + enum i40e_interrupt_policy int_policy; u16 rx_itr_default; u16 tx_itr_default; diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index e53d1be..15f0975 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -6967,6 +6967,26 @@ static void i40e_fdir_filter_exit(struct i40e_pf *pf) } /** + * i40e_cloud_filter_exit - Cleans up the Cloud Filters + * @pf: Pointer to PF + * + * This function destroys the hlist where all the Cloud Filters + * filters were saved. + **/ +static void i40e_cloud_filter_exit(struct i40e_pf *pf) +{ + struct i40e_cloud_filter *cfilter; + struct hlist_node *node; + + hlist_for_each_entry_safe(cfilter, node, + &pf->cloud_filter_list, cloud_node) { + hlist_del(&cfilter->cloud_node); + kfree(cfilter); + } + pf->num_cloud_filters = 0; +} + +/** * i40e_close - Disables a network interface * @netdev: network interface device structure * @@ -12176,6 +12196,7 @@ static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit) vsi = i40e_vsi_reinit_setup(pf->vsi[pf->lan_vsi]); if (!vsi) { dev_info(&pf->pdev->dev, "setup of MAIN VSI failed\n"); + i40e_cloud_filter_exit(pf); i40e_fdir_teardown(pf); return -EAGAIN; } @@ -13003,6 +13024,8 @@ static void i40e_remove(struct pci_dev *pdev) if (pf->vsi[pf->lan_vsi]) i40e_vsi_release(pf->vsi[pf->lan_vsi]); + i40e_cloud_filter_exit(pf); + /* remove attached clients */ if (pf->flags & I40E_FLAG_IWARP_ENABLED) { ret_code = i40e_lan_del_device(pf); @@ -13212,6 +13235,7 @@ static void i40e_shutdown(struct pci_dev *pdev) del_timer_sync(&pf->service_timer); cancel_work_sync(&pf->service_task); + i40e_cloud_filter_exit(pf); i40e_fdir_teardown(pf); /* Client close must be called explicitly here because the timer
[RFC PATCH v2 3/6] [net-next]net: i40e: Extend set switch config command to accept cloud filter mode
Add definitions for L4 filters and switch modes based on cloud filters modes and extend the set switch config command to include the additional cloud filter mode. Signed-off-by: Amritha Nambiar Signed-off-by: Kiran Patil --- drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h | 31 - drivers/net/ethernet/intel/i40e/i40e_common.c |4 ++- drivers/net/ethernet/intel/i40e/i40e_ethtool.c|2 + drivers/net/ethernet/intel/i40e/i40e_main.c |2 + drivers/net/ethernet/intel/i40e/i40e_prototype.h |2 + drivers/net/ethernet/intel/i40e/i40e_type.h |9 ++ 6 files changed, 45 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h index e2a9ec8..eac5ff5 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h @@ -773,7 +773,36 @@ struct i40e_aqc_set_switch_config { #define I40E_AQ_SET_SWITCH_CFG_PROMISC 0x0001 #define I40E_AQ_SET_SWITCH_CFG_L2_FILTER 0x0002 __le16 valid_flags; - u8 reserved[12]; + u8 rsvd6[6]; + /* Next byte is split into following: +* Bit 7 : 0: No action, 1: Switch to mode defined by bits 6:0 +* Bit 6: 0 : Destination Port, 1: source port +* Bit 5..4: L4 type +* 0: rsvd +* 1: TCP +* 2: UDP +* 3: Both TCP and UDP +* Bits 3:0 Mode +* 0: default mode +* 1: L4 port only mode +* 2: non-tunneled mode +* 3: tunneled mode +*/ +#define I40E_AQ_SET_SWITCH_BIT7_VALID 0x80 + +#define I40E_AQ_SET_SWITCH_L4_SRC_PORT 0x40 + +#define I40E_AQ_SET_SWITCH_L4_TYPE_RSVD0x00 +#define I40E_AQ_SET_SWITCH_L4_TYPE_TCP 0x10 +#define I40E_AQ_SET_SWITCH_L4_TYPE_UDP 0x20 +#define I40E_AQ_SET_SWITCH_L4_TYPE_BOTH0x30 + +#define I40E_AQ_SET_SWITCH_MODE_DEFAULT0x00 +#define I40E_AQ_SET_SWITCH_MODE_L4_PORT0x01 +#define I40E_AQ_SET_SWITCH_MODE_NON_TUNNEL 0x02 +#define I40E_AQ_SET_SWITCH_MODE_TUNNEL 0x03 + u8 mode; + u8 rsvd5[5]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_set_switch_config); diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index e4e86e0..d0e8138 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -2380,13 +2380,14 @@ i40e_status i40e_aq_get_switch_config(struct i40e_hw *hw, * @hw: pointer to the hardware structure * @flags: bit flag values to set * @valid_flags: which bit flags to set + * @mode: cloud filter mode * @cmd_details: pointer to command details structure or NULL * * Set switch configuration bits **/ enum i40e_status_code i40e_aq_set_switch_config(struct i40e_hw *hw, u16 flags, - u16 valid_flags, + u16 valid_flags, u8 mode, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; @@ -2398,6 +2399,7 @@ enum i40e_status_code i40e_aq_set_switch_config(struct i40e_hw *hw, i40e_aqc_opc_set_switch_config); scfg->flags = cpu_to_le16(flags); scfg->valid_flags = cpu_to_le16(valid_flags); + scfg->mode = mode; status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 326fc18..232e066e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -4181,7 +4181,7 @@ static int i40e_set_priv_flags(struct net_device *dev, u32 flags) sw_flags = I40E_AQ_SET_SWITCH_CFG_PROMISC; valid_flags = I40E_AQ_SET_SWITCH_CFG_PROMISC; ret = i40e_aq_set_switch_config(&pf->hw, sw_flags, valid_flags, - NULL); + 0, NULL); if (ret && pf->hw.aq.asq_last_status != I40E_AQ_RC_ESRCH) { dev_info(&pf->pdev->dev, "couldn't set switch config bits, err %s aq_err %s\n", diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index b02da99..e53d1be 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -12146,7 +12146,7 @@ static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit) u16 valid_flags; valid_flags = I40E_AQ_SET_SWITCH_CFG_PROMISC; - ret = i40e_aq_set_switch_config(&pf->hw, flags, valid_flags, +
[RFC PATCH v2 4/6] [net-next]net: i40e: Admin queue definitions for cloud filters
Add new admin queue definitions and extended fields for cloud filter support. Define big buffer for extended general fields in Add/Remove Cloud filters command. v2: Added I40E_CHECK_STRUCT_LEN check to AQ command structs and added AQ definitions to i40evf for consistency based on Shannon's feedback. Signed-off-by: Amritha Nambiar Signed-off-by: Kiran Patil Signed-off-by: Jingjing Wu --- drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h | 108 .../net/ethernet/intel/i40evf/i40e_adminq_cmd.h| 108 2 files changed, 214 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h index eac5ff5..1f5 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h @@ -1355,7 +1355,9 @@ struct i40e_aqc_add_remove_cloud_filters { #define I40E_AQC_ADD_CLOUD_CMD_SEID_NUM_SHIFT 0 #define I40E_AQC_ADD_CLOUD_CMD_SEID_NUM_MASK (0x3FF << \ I40E_AQC_ADD_CLOUD_CMD_SEID_NUM_SHIFT) - u8 reserved2[4]; + u8 big_buffer_flag; +#defineI40E_AQC_ADD_REM_CLOUD_CMD_BIG_BUFFER 1 + u8 reserved2[3]; __le32 addr_high; __le32 addr_low; }; @@ -1392,6 +1394,13 @@ struct i40e_aqc_add_remove_cloud_filters_element_data { #define I40E_AQC_ADD_CLOUD_FILTER_IMAC 0x000A #define I40E_AQC_ADD_CLOUD_FILTER_OMAC_TEN_ID_IMAC 0x000B #define I40E_AQC_ADD_CLOUD_FILTER_IIP 0x000C +/* 0x0010 to 0x0017 is for custom filters */ +/* flag to be used when adding cloud filter: IP + L4 Port */ +#define I40E_AQC_ADD_CLOUD_FILTER_IP_PORT 0x0010 +/* flag to be used when adding cloud filter: Dest MAC + L4 Port */ +#define I40E_AQC_ADD_CLOUD_FILTER_MAC_PORT 0x0011 +/* flag to be used when adding cloud filter: Dest MAC + VLAN + L4 Port */ +#define I40E_AQC_ADD_CLOUD_FILTER_MAC_VLAN_PORT0x0012 #define I40E_AQC_ADD_CLOUD_FLAGS_TO_QUEUE 0x0080 #define I40E_AQC_ADD_CLOUD_VNK_SHIFT 6 @@ -1426,6 +1435,49 @@ struct i40e_aqc_add_remove_cloud_filters_element_data { u8 response_reserved[7]; }; +I40E_CHECK_STRUCT_LEN(0x40, i40e_aqc_add_remove_cloud_filters_element_data); + +/* i40e_aqc_add_remove_cloud_filters_element_big_data is used when + * I40E_AQC_ADD_REM_CLOUD_CMD_BIG_BUFFER flag is set. + */ +struct i40e_aqc_add_remove_cloud_filters_element_big_data { + struct i40e_aqc_add_remove_cloud_filters_element_data element; + u16 general_fields[32]; +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD0 0 +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1 1 +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD2 2 +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0 3 +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1 4 +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2 5 +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X12_WORD0 6 +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X12_WORD1 7 +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X12_WORD2 8 +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X13_WORD0 9 +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X13_WORD1 10 +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X13_WORD2 11 +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X14_WORD0 12 +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X14_WORD1 13 +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X14_WORD2 14 +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X16_WORD0 15 +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X16_WORD1 16 +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X16_WORD2 17 +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X16_WORD3 18 +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X16_WORD4 19 +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X16_WORD5 20 +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X16_WORD6 21 +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X16_WORD7 22 +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X17_WORD0 23 +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X17_WORD1 24 +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X17_WORD2 25 +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X17_WORD3 26 +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X17_WORD4 27 +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X17_WORD5 28 +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X17_WORD6 29 +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X17_WORD7 30 +}; + +I40E_CHECK_STRUCT_LEN(0x80, i40e_aqc_add_remove_cloud_filters_element_big_data); + struct i40e_aqc_remove_cloud_filters_completion { __le16 perfect_ovlan_used; __le16 perfect_ovlan_free; @@ -1437,6 +1489,60 @@ struct i40e_aqc_remove_cloud_filters_completion { I40E_CHECK_CMD_LENGTH(i40e_aqc_remove_cloud_filters_completion); +/* Replace filter Command 0x025F + * uses the i40e_aqc_replace_cloud_filters, + * and the generic indirect completion structure + */ +struct i40e_filter_data { + u8 filter_type; + u8 input[3]; +}; + +I40E_CHECK_STRUCT_LEN(4, i40e_filter_data); + +struct i40e_aqc_replace_cloud_filters_cmd { + u8 valid_flags; +#define I40E_AQC_REPLACE_L1_FILTER 0x0 +#define I40E_AQC_REPL
[RFC PATCH v2 6/6] [net-next]net: i40e: Enable cloud filters in i40e via tc flower classifier
This patch enables tc-flower based hardware offloads. tc flower filter provided by the kernel is configured as driver specific cloud filter. The patch implements functions and admin queue commands needed to support cloud filters in the driver and adds cloud filters to configure these tc-flower filters. The only action supported is to redirect packets to a traffic class on the same device. # tc qdisc add dev eth0 ingress # ethtool -K eth0 hw-tc-offload on # tc filter add dev eth0 protocol ip parent :\ prio 1 flower dst_mac 3c:fd:fe:a0:d6:70 skip_sw\ action mirred ingress redirect dev eth0 tclass 0 # tc filter add dev eth0 protocol ip parent :\ prio 2 flower dst_ip 192.168.3.5/32\ ip_proto udp dst_port 25 skip_sw\ action mirred ingress redirect dev eth0 tclass 1 # tc filter add dev eth0 protocol ipv6 parent :\ prio 3 flower dst_ip fe8::200:1\ ip_proto udp dst_port 66 skip_sw\ action mirred ingress redirect dev eth0 tclass 2 Delete tc flower filter: Example: # tc filter del dev eth0 parent : prio 3 handle 0x1 flower # tc filter del dev eth0 parent : Flow Director Sideband is disabled while configuring cloud filters via tc-flower and until any cloud filter exists. Unsupported matches when cloud filters are added using enhanced big buffer cloud filter mode of underlying switch include: 1. source port and source IP 2. Combined MAC address and IP fields. 3. Not specifying L4 port These filter matches can however be used to redirect traffic to the main VSI (tc 0) which does not require the enhanced big buffer cloud filter support. v2: 1. Moved I40E_SWITCH_MODE_MASK definition to i40e_type.h 2. Moved dev_info for add/deleting cloud filters in else condition 3. Fixed some format specifier in dev_err logs 4. Refactored i40e_get_capabilities to take an additional list_type parameter and use it to query device and function level capabilities. 5. Fixed parsing tc redirect action to check for the is_tcf_mirred_tc() to verify if redirect to a traffic class is supported. 6. Added comments for Geneve fix in cloud filter big buffer AQ function definitions. 7. Cleaned up setup_tc interface to rebase and work with Jiri's updates, separate function to process tc cls flower offloads. 8. Changes to make Flow Director Sideband and Cloud filters mutually exclusive. Signed-off-by: Amritha Nambiar Signed-off-by: Kiran Patil Signed-off-by: Anjali Singhai Jain Signed-off-by: Jingjing Wu --- drivers/net/ethernet/intel/i40e/i40e.h | 46 + drivers/net/ethernet/intel/i40e/i40e_common.c| 190 drivers/net/ethernet/intel/i40e/i40e_main.c | 975 +- drivers/net/ethernet/intel/i40e/i40e_prototype.h | 17 drivers/net/ethernet/intel/i40e/i40e_type.h |1 5 files changed, 1202 insertions(+), 27 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index ac57ab0..dbf4b9d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -55,6 +55,8 @@ #include #include #include +#include +#include #include "i40e_type.h" #include "i40e_prototype.h" #include "i40e_client.h" @@ -252,9 +254,49 @@ struct i40e_fdir_filter { u32 fd_id; }; +#define I40E_CLOUD_FIELD_OMAC 0x01 +#define I40E_CLOUD_FIELD_IMAC 0x02 +#define I40E_CLOUD_FIELD_IVLAN 0x04 +#define I40E_CLOUD_FIELD_TEN_ID0x08 +#define I40E_CLOUD_FIELD_IIP 0x10 + +#define I40E_CLOUD_FILTER_FLAGS_OMAC I40E_CLOUD_FIELD_OMAC +#define I40E_CLOUD_FILTER_FLAGS_IMAC I40E_CLOUD_FIELD_IMAC +#define I40E_CLOUD_FILTER_FLAGS_IMAC_IVLAN (I40E_CLOUD_FIELD_IMAC | \ +I40E_CLOUD_FIELD_IVLAN) +#define I40E_CLOUD_FILTER_FLAGS_IMAC_TEN_ID(I40E_CLOUD_FIELD_IMAC | \ +I40E_CLOUD_FIELD_TEN_ID) +#define I40E_CLOUD_FILTER_FLAGS_OMAC_TEN_ID_IMAC (I40E_CLOUD_FIELD_OMAC | \ + I40E_CLOUD_FIELD_IMAC | \ + I40E_CLOUD_FIELD_TEN_ID) +#define I40E_CLOUD_FILTER_FLAGS_IMAC_IVLAN_TEN_ID (I40E_CLOUD_FIELD_IMAC | \ + I40E_CLOUD_FIELD_IVLAN | \ + I40E_CLOUD_FIELD_TEN_ID) +#define I40E_CLOUD_FILTER_FLAGS_IIPI40E_CLOUD_FIELD_IIP + struct i40e_cloud_filter { struct hlist_node cloud_node; unsigned long cookie; + /* cloud filter input set follows */ + u8 dst_mac[ETH_ALEN]; + u8 src_mac[ETH_ALEN]; + __be16 vlan_id; + __be32 dst_ip[4]; + __be32 src_ip[4]; + u8 dst_ipv6[16]; + u8 src_ipv6[16]; + __be16 dst_port; + __be16 src_port; + bool is_ipv6; /* IPv6 based filtering */ + u8 ip_proto;/* IPPROTO value */ + /* L4 port type: src or destination port */ +#define I40E_CLOUD_FILTER_PORT_SRC 0x01 +#defin
[PATCH v2] bpf: Update sysctl documentation to list all supported architectures
The sysctl documentation states that the JIT is only available on x86_64, which is no longer correct. Update the list, and break it out to indicate which architectures support the cBPF JIT (via HAVE_CBPF_JIT) or the eBPF JIT (HAVE_EBPF_JIT). Signed-off-by: Michael Ellerman --- Documentation/sysctl/net.txt | 19 +-- 1 file changed, 17 insertions(+), 2 deletions(-) v2: Split the list based on cBPF vs eBPF. diff --git a/Documentation/sysctl/net.txt b/Documentation/sysctl/net.txt index 14db18c970b1..b9c3c6078010 100644 --- a/Documentation/sysctl/net.txt +++ b/Documentation/sysctl/net.txt @@ -36,8 +36,23 @@ bpf_jit_enable -- This enables Berkeley Packet Filter Just in Time compiler. -Currently supported on x86_64 architecture, bpf_jit provides a framework -to speed packet filtering, the one used by tcpdump/libpcap for example. + +There are two flavors of JIT, the new eBPF JIT supported on: + - x86_64 + - arm64 + - ppc64 + - sparc64 + - mips64 + +And the older cBPF JIT supported on: + - arm + - mips + - ppc + - sparc + +The BPF JIT provides a framework to speed packet filtering, the one used by +tcpdump/libpcap for example. + Values : 0 - disable the JIT (default value) 1 - enable the JIT -- 2.7.4
Re: [PATCH] bpf: Update sysctl documentation to list all supported architectures
Daniel Borkmann writes: > On 08/16/2017 01:10 PM, Michael Ellerman wrote: >> Daniel Borkmann writes: >>> On 08/16/2017 07:15 AM, Michael Ellerman wrote: diff --git a/Documentation/sysctl/net.txt b/Documentation/sysctl/net.txt index 14db18c970b1..f68356024d09 100644 --- a/Documentation/sysctl/net.txt +++ b/Documentation/sysctl/net.txt @@ -36,8 +36,9 @@ bpf_jit_enable -- This enables Berkeley Packet Filter Just in Time compiler. -Currently supported on x86_64 architecture, bpf_jit provides a framework -to speed packet filtering, the one used by tcpdump/libpcap for example. +Currently supported on arm, arm64, mips, powerpc, s390, sparc and x86_64 +architectures, bpf_jit provides a framework to speed packet filtering, the one +used by tcpdump/libpcap for example. >>> >>> Good point, could we actually make that as a bullet list and >>> differentiate between cBPF and eBPF JITs, so that a user doesn't >>> need to run git grep HAVE_{E,C}BPF_JIT to figure it out what the >>> switch enables on the arch used? That would be great. >> >> We could. >> >> Does a user of the sysctl want/need to know the difference though? Or do >> they just want to turn on "the JIT"? > > They would just turn it on, but I think it would be nice to inform > them which archs support eBPF (which is a superset of cBPF in term > of what can be jited), so in case they have some native eBPF programs > they would see whether these can also be jited. OK. v2 just sent. The text could probably use some more tweaking to mention the other things BPF is used for these days, but I didn't really feel qualified to do that. cheers
Re: [PATCH net] net: sched: fix NULL pointer dereference when action calls some targets
On Thu, Aug 17, 2017 at 12:02:20PM +0200, Pablo Neira Ayuso wrote: > On Wed, Aug 16, 2017 at 08:39:44PM +1200, Xin Long wrote: > > On Wed, Aug 9, 2017 at 7:33 AM, Cong Wang wrote: > > > On Mon, Aug 7, 2017 at 7:33 PM, Xin Long wrote: > > >> On Tue, Aug 8, 2017 at 9:15 AM, Cong Wang > > >> wrote: > > >>> This looks like a completely API burden? > > >> netfilter xt targets are not really compatible with netsched action. > > >> I've got to say, the patch is just a way to make checkentry return > > >> false and avoid panic. like [1] said > > > > > > I don't doubt you fix a crash, I am thinking if we can > > > "fix" the API instead of fixing the caller. > > Hi, Cong, > > > > For now, I don't think it's possible to change APIs or some of their > > targets > > for the panic caused by action xt calling. > > > > The common way should be fixed in net_sched side. > > > > Given that the issue is very easy to triggered, > > let's wait for netfilter's replies for another few days, > > otherwise I will repost the fix, agree ? > > Please, post the workaround so the kernel doesn't crash anymore. > > This is going to be very hard to fix, it's broken since the very > beginning... Wait a second, you could rename par->nft_compat to par->no_entry. From net/sched/ you can set this to 1, so the entry checks are ignored. I'm refering to patch 55917a21d0cc0
[RFC, iproute2 PATCH v2] tc/mirred: Extend the mirred/redirect action to accept additional traffic class parameter
The Mirred/redirect action is extended to accept a traffic class on the device in addition to the device's ifindex. Usage: mirred Example: # tc qdisc add dev eth0 ingress # tc filter add dev eth0 protocol ip parent : prio 1 flower\ dst_ip 192.168.1.1/32 ip_proto udp dst_port 22\ skip_sw action mirred ingress redirect dev eth0 tclass 1 v2: Renamed the parameter 'tc' to 'tclass'. Replaced atoi with strtoul and used NEXT_ARG() construct. Signed-off-by: Amritha Nambiar --- include/linux/tc_act/tc_mirred.h |3 +++ tc/m_mirred.c| 35 +++ 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/include/linux/tc_act/tc_mirred.h b/include/linux/tc_act/tc_mirred.h index 3d7a2b3..ea06a47 100644 --- a/include/linux/tc_act/tc_mirred.h +++ b/include/linux/tc_act/tc_mirred.h @@ -9,6 +9,8 @@ #define TCA_EGRESS_MIRROR 2 /* mirror packet to EGRESS */ #define TCA_INGRESS_REDIR 3 /* packet redirect to INGRESS*/ #define TCA_INGRESS_MIRROR 4 /* mirror packet to INGRESS */ + +#define MIRRED_F_TCLASS0x1 struct tc_mirred { tc_gen; @@ -21,6 +23,7 @@ enum { TCA_MIRRED_TM, TCA_MIRRED_PARMS, TCA_MIRRED_PAD, + TCA_MIRRED_TCLASS, __TCA_MIRRED_MAX }; #define TCA_MIRRED_MAX (__TCA_MIRRED_MAX - 1) diff --git a/tc/m_mirred.c b/tc/m_mirred.c index 2384bda..1cb477a 100644 --- a/tc/m_mirred.c +++ b/tc/m_mirred.c @@ -29,12 +29,13 @@ static void explain(void) { - fprintf(stderr, "Usage: mirred [index INDEX] \n"); + fprintf(stderr, "Usage: mirred [index INDEX] [tclass TCINDEX]\n"); fprintf(stderr, "where:\n"); fprintf(stderr, "\tDIRECTION := \n"); fprintf(stderr, "\tACTION := \n"); fprintf(stderr, "\tINDEX is the specific policy instance id\n"); fprintf(stderr, "\tDEVICENAME is the devicename\n"); + fprintf(stderr, "\tTCINDEX is the traffic class index\n"); } @@ -72,6 +73,9 @@ parse_direction(struct action_util *a, int *argc_p, char ***argv_p, struct tc_mirred p = {}; struct rtattr *tail; char d[16] = {}; + __u32 flags = 0; + char *end; + __u8 tc; while (argc > 0) { @@ -139,9 +143,23 @@ parse_direction(struct action_util *a, int *argc_p, char ***argv_p, duparg("dev", *argv); strncpy(d, *argv, sizeof(d)-1); - argc--; - argv++; - + NEXT_ARG_FWD(); + + if (argc > 0 && matches(*argv, "tclass") == 0) { + NEXT_ARG(); + tc = strtoul(*argv, &end, 0); + if (*end) { + fprintf(stderr, "Illegal TC index\n"); + return -1; + } + if (tc >= TC_QOPT_MAX_QUEUE) { + fprintf(stderr, "TC index exceeds max range\n"); + return -1; + } + flags |= MIRRED_F_TCLASS; + ok++; + NEXT_ARG_FWD(); + } break; } @@ -193,6 +211,9 @@ parse_direction(struct action_util *a, int *argc_p, char ***argv_p, tail = NLMSG_TAIL(n); addattr_l(n, MAX_MSG, tca_id, NULL, 0); addattr_l(n, MAX_MSG, TCA_MIRRED_PARMS, &p, sizeof(p)); + if (flags & MIRRED_F_TCLASS) + addattr_l(n, MAX_MSG, TCA_MIRRED_TCLASS, + &tc, sizeof(tc)); tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; *argc_p = argc; @@ -248,6 +269,7 @@ print_mirred(struct action_util *au, FILE * f, struct rtattr *arg) struct tc_mirred *p; struct rtattr *tb[TCA_MIRRED_MAX + 1]; const char *dev; + __u8 *tc; if (arg == NULL) return -1; @@ -273,6 +295,11 @@ print_mirred(struct action_util *au, FILE * f, struct rtattr *arg) fprintf(f, "mirred (%s to device %s)", mirred_n2a(p->eaction), dev); print_action_control(f, " ", p->action, ""); + if (tb[TCA_MIRRED_TCLASS]) { + tc = RTA_DATA(tb[TCA_MIRRED_TCLASS]); + fprintf(f, " tclass %u", *tc); + } + fprintf(f, "\n "); fprintf(f, "\tindex %u ref %d bind %d", p->index, p->refcnt, p->bindcnt);
Re: [PATCH net] PCI: fix the return value for the pci_find_pcie_root_port()
On Thu, Aug 17, 2017 at 10:25:30AM +0800, Ding Tianhong wrote: > The pci_find_pcie_root_port() would return NULL if the given > dev is already a Root Port, it looks like unfriendly to the > PCIe Root Port device, Thierry and Bjorn suggest to let this > function return the given dev under this circumstances. > > Fixes: 0e405232871d6 ("PCI: fix oops when try to find Root Port for a PCI > device") > Suggested-by: Thierry Reding > Suggested-by: Bjorn Helgaas > Signed-off-by: Thierry Reding > Signed-off-by: Ding Tianhong > --- > drivers/pci/pci.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c > index 7e2022f..352bb53 100644 > --- a/drivers/pci/pci.c > +++ b/drivers/pci/pci.c > @@ -514,7 +514,7 @@ struct resource *pci_find_resource(struct pci_dev *dev, > struct resource *res) > */ > struct pci_dev *pci_find_pcie_root_port(struct pci_dev *dev) > { > - struct pci_dev *bridge, *highest_pcie_bridge = NULL; > + struct pci_dev *bridge, *highest_pcie_bridge = dev; > > bridge = pci_upstream_bridge(dev); > while (bridge && pci_is_pcie(bridge)) { I think this should actually be this change on top of a revert of commit 0e405232871d6 ("PCI: fix oops when try to find Root Port for a PCI device"). After the above change, the previous fix will have a redundant check because highest_pcie_bridge will never be NULL. Let me send out that version to clarify what I mean. Thierry signature.asc Description: PGP signature
Re: [PATCH 1/6] bridge: learn dst metadata in FDB
Hi Nikolay, On Wed, Aug 16, 2017 at 11:38:06PM +0300, Nikolay Aleksandrov wrote: > On 16/08/17 20:01, David Lamparter wrote: > > This implements holding dst metadata information in the bridge layer, > > but only for unicast entries in the MAC table. Multicast is still left > > to design and implement. > > Sorry but I do not agree with this change, adding a special case for > VPLS in the bridge code I don't think this is specific to VPLS at all, though you're right that VPLS is the only user currently. > and hitting the fast path for everyone in a few different places for a > feature that the majority will not use does not sound acceptable to > me. We've been trying hard to optimize it, trying to avoid additional > cache lines, removing tests and keeping special cases to a minimum. skb->dst is on the same cacheline as skb->len. fdb->md_dst is on the same cacheline as fdb->dst. Both will be 0 in a lot of cases, so this should be two null checks on data that is hot in the cache. Are you sure this is an actual problem? > I understand that you want to use the fdb tables and avoid > duplication, but this is not worth it. There're other similar use > cases and they have their own private fdb tables, that way the user > can opt out and is much cleaner and separated. Sure, this can be done. I think it's a noticeable performance penalty to have the entire fdb copied (multiple times for H-VPLS even), but I understand that it's preferable to have the normal cases faster in exchange. As the previous paragraph notes, I still wonder if that hit to the normal case exists though. I will leave this to Amine, he's paid to work on VPLS while I'm doing this for fun ;) There is however another concern I have here. As I noted in my introductory mail, I'm working on the bridge MDB making similar changes. And there's actually strong use cases for this in both VPLS and the 802.11 code (though I'm not sure I can code the latter one up, it's related to rate control and this is seriously complicated - the goal is to select a multicast rate based on the now-known receiving STAs). I really hope you're not suggesting the entire MDB with IPv4 & IPv6 snooping be duplicated into both VPLS and mac80211? > As you've noted this is only an RFC so I will not point out every issue, but > there seems > to be a major problem with br_fdb_update(), note that it runs without any > locks except RCU. Right, Thanks! ... I only thought about concurrent access, forgetting about concurrent modification... I'll replace it with an xchg I think. (No need for a lock that way) That said, now that I think about it, the skb_dst_set_noref() in the following chunk is probably not safe if the VPLS device has a qdisc on it. I was relying on the fact that br_dev_xmit is holding RCU there, but if the SKB is queued, md_dst might go away in the meantime... ... probably need to change this to dst_hold() + skb_dst_set()... -David > > diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c > > index 861ae2a165f4..534cacf02f8d 100644 > > --- a/net/bridge/br_device.c > > +++ b/net/bridge/br_device.c > > @@ -81,6 +82,9 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct > > net_device *dev) > > else > > br_flood(br, skb, BR_PKT_MULTICAST, false, true); > > } else if ((dst = br_fdb_find_rcu(br, dest, vid)) != NULL) { > > + struct dst_entry *md_dst = rcu_dereference(dst->md_dst); > > + if (md_dst) > > + skb_dst_set_noref(skb, md_dst); > > br_forward(dst->dst, skb, false, true); > > } else { > > br_flood(br, skb, BR_PKT_UNICAST, false, true); > > diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c > > index a79b648aac88..0751fcb89699 100644 > > @@ -567,10 +579,15 @@ void br_fdb_update(struct net_bridge *br, struct > > net_bridge_port *source, > > source->dev->name, addr, vid); > > } else { > > unsigned long now = jiffies; > > + struct dst_entry *ref_md = > > rcu_access_pointer(fdb->md_dst); > > > > /* fastpath: update of existing entry */ > > - if (unlikely(source != fdb->dst)) { > > + if (unlikely(source != fdb->dst || > > + dst_metadata_cmp(md_dst, ref_md))) { > > fdb->dst = source; > > + dst_release(ref_md); > > + rcu_assign_pointer(fdb->md_dst, > > + dst_clone(md_dst)); > > fdb_modified = true; > > /* Take over HW learned entry */ > > if (unlikely(fdb->added_by_external_learn))
[PATCH] PCI: Allow PCI express root ports to find themselves
From: Thierry Reding If the pci_find_pcie_root_port() function is called on a root port itself, return the root port rather than NULL. This effectively reverts commit 0e405232871d6 ("PCI: fix oops when try to find Root Port for a PCI device") which added an extra check that would now be redundant. Fixes: a99b646afa8a ("PCI: Disable PCIe Relaxed Ordering if unsupported") Fixes: c56d4450eb68 ("PCI: Turn off Request Attributes to avoid Chelsio T5 Completion erratum") Signed-off-by: Thierry Reding --- This applies on top of and was tested on next-20170817. Michael, it'd be great if you could test this one again to clarify whether or not the fix that's already in Linus' tree is still needed, or whether it's indeed obsoleted by this patch. drivers/pci/pci.c | 9 - 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index b05c587e335a..dd56c1c05614 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -514,7 +514,7 @@ EXPORT_SYMBOL(pci_find_resource); */ struct pci_dev *pci_find_pcie_root_port(struct pci_dev *dev) { - struct pci_dev *bridge, *highest_pcie_bridge = NULL; + struct pci_dev *bridge, *highest_pcie_bridge = dev; bridge = pci_upstream_bridge(dev); while (bridge && pci_is_pcie(bridge)) { @@ -522,11 +522,10 @@ struct pci_dev *pci_find_pcie_root_port(struct pci_dev *dev) bridge = pci_upstream_bridge(bridge); } - if (highest_pcie_bridge && - pci_pcie_type(highest_pcie_bridge) == PCI_EXP_TYPE_ROOT_PORT) - return highest_pcie_bridge; + if (pci_pcie_type(highest_pcie_bridge) != PCI_EXP_TYPE_ROOT_PORT) + return NULL; - return NULL; + return highest_pcie_bridge; } EXPORT_SYMBOL(pci_find_pcie_root_port); -- 2.13.3
Re: [PATCH net] net: sched: fix NULL pointer dereference when action calls some targets
On Thu, Aug 17, 2017 at 10:33 PM, Pablo Neira Ayuso wrote: > On Thu, Aug 17, 2017 at 12:02:20PM +0200, Pablo Neira Ayuso wrote: >> On Wed, Aug 16, 2017 at 08:39:44PM +1200, Xin Long wrote: >> > On Wed, Aug 9, 2017 at 7:33 AM, Cong Wang wrote: >> > > On Mon, Aug 7, 2017 at 7:33 PM, Xin Long wrote: >> > >> On Tue, Aug 8, 2017 at 9:15 AM, Cong Wang >> > >> wrote: >> > >>> This looks like a completely API burden? >> > >> netfilter xt targets are not really compatible with netsched action. >> > >> I've got to say, the patch is just a way to make checkentry return >> > >> false and avoid panic. like [1] said >> > > >> > > I don't doubt you fix a crash, I am thinking if we can >> > > "fix" the API instead of fixing the caller. >> > Hi, Cong, >> > >> > For now, I don't think it's possible to change APIs or some of their >> > targets >> > for the panic caused by action xt calling. >> > >> > The common way should be fixed in net_sched side. >> > >> > Given that the issue is very easy to triggered, >> > let's wait for netfilter's replies for another few days, >> > otherwise I will repost the fix, agree ? >> >> Please, post the workaround so the kernel doesn't crash anymore. >> >> This is going to be very hard to fix, it's broken since the very >> beginning... > > Wait a second, you could rename par->nft_compat to par->no_entry. From > net/sched/ you can set this to 1, so the entry checks are ignored. > > I'm refering to patch 55917a21d0cc0 par->nft_compat wasn't used to ignore the entry checks, if we rename it as no_entry, some other targets still needs to update. like the ones in this patch's changelog: ECN: ecn_tg_check() TPROXY: tproxy_tg4_check() which means these two checks will be ignored for nft as well, that is not what we want. As nft has e4.ip.proto and e4.ip.invflags being set which net/sched gets nothing. they are still different.
Re: Something hitting my total number of connections to the server
On Thu, 2017-08-17 at 14:35 +0530, Akshat Kakkar wrote: > I upgraded to 4.4 but still experiencing same issue. > Please help. Still too old kernel, shoot again ;)
Re: [PATCH 1/6] bridge: learn dst metadata in FDB
On 17/08/17 14:03, David Lamparter wrote: > Hi Nikolay, > > > On Wed, Aug 16, 2017 at 11:38:06PM +0300, Nikolay Aleksandrov wrote: >> On 16/08/17 20:01, David Lamparter wrote: >>> This implements holding dst metadata information in the bridge layer, >>> but only for unicast entries in the MAC table. Multicast is still left >>> to design and implement. >> >> Sorry but I do not agree with this change, adding a special case for >> VPLS in the bridge code > > I don't think this is specific to VPLS at all, though you're right that > VPLS is the only user currently. > >> and hitting the fast path for everyone in a few different places for a >> feature that the majority will not use does not sound acceptable to >> me. We've been trying hard to optimize it, trying to avoid additional >> cache lines, removing tests and keeping special cases to a minimum. > > skb->dst is on the same cacheline as skb->len. > fdb->md_dst is on the same cacheline as fdb->dst. > Both will be 0 in a lot of cases, so this should be two null checks on > data that is hot in the cache. Are you sure this is an actual problem? > Sure - no, I haven't benchmarked it, but I don't see skb->len being on the same cache line as _skb_refdst assuming 64 byte cache lines. But again any special cases, in my opinion, should be handled on their own, it is both about the fast path and the code complexity that they bring in. >> I understand that you want to use the fdb tables and avoid >> duplication, but this is not worth it. There're other similar use >> cases and they have their own private fdb tables, that way the user >> can opt out and is much cleaner and separated. > > Sure, this can be done. I think it's a noticeable performance penalty > to have the entire fdb copied (multiple times for H-VPLS even), but I > understand that it's preferable to have the normal cases faster in > exchange. As the previous paragraph notes, I still wonder if that hit > to the normal case exists though. > > I will leave this to Amine, he's paid to work on VPLS while I'm doing > this for fun ;) > > There is however another concern I have here. As I noted in my > introductory mail, I'm working on the bridge MDB making similar changes. > And there's actually strong use cases for this in both VPLS and the > 802.11 code (though I'm not sure I can code the latter one up, it's > related to rate control and this is seriously complicated - the goal is > to select a multicast rate based on the now-known receiving STAs). > > I really hope you're not suggesting the entire MDB with IPv4 & IPv6 > snooping be duplicated into both VPLS and mac80211? > Code can always be shared if there are more users, no need to stuff everything in the bridge, but I'm not that familiar with this case, once patches are out I can comment further. >> As you've noted this is only an RFC so I will not point out every issue, but >> there seems >> to be a major problem with br_fdb_update(), note that it runs without any >> locks except RCU. > > Right, Thanks! ... I only thought about concurrent access, forgetting > about concurrent modification... I'll replace it with an xchg I think. > (No need for a lock that way) I think you can still lose references to a dst that way, what if someone changes the dst you read before the xchg and you xchg it ? > > That said, now that I think about it, the skb_dst_set_noref() in the > following chunk is probably not safe if the VPLS device has a qdisc on > it. I was relying on the fact that br_dev_xmit is holding RCU there, > but if the SKB is queued, md_dst might go away in the meantime... > ... probably need to change this to dst_hold() + skb_dst_set()... > > > -David > >>> diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c >>> index 861ae2a165f4..534cacf02f8d 100644 >>> --- a/net/bridge/br_device.c >>> +++ b/net/bridge/br_device.c >>> @@ -81,6 +82,9 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct >>> net_device *dev) >>> else >>> br_flood(br, skb, BR_PKT_MULTICAST, false, true); >>> } else if ((dst = br_fdb_find_rcu(br, dest, vid)) != NULL) { >>> + struct dst_entry *md_dst = rcu_dereference(dst->md_dst); >>> + if (md_dst) >>> + skb_dst_set_noref(skb, md_dst); >>> br_forward(dst->dst, skb, false, true); >>> } else { >>> br_flood(br, skb, BR_PKT_UNICAST, false, true); > > >>> diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c >>> index a79b648aac88..0751fcb89699 100644 >>> @@ -567,10 +579,15 @@ void br_fdb_update(struct net_bridge *br, struct >>> net_bridge_port *source, >>> source->dev->name, addr, vid); >>> } else { >>> unsigned long now = jiffies; >>> + struct dst_entry *ref_md = >>> rcu_access_pointer(fdb->md_dst); >>> >>> /* fastpath: update of existing entry */ >>> - if (unlikely(source !
[PATCH V5 net-next 00/21] Huawei HiNIC Ethernet Driver
The patch-set contains the support of the HiNIC Ethernet driver for hinic family of PCIE Network Interface Cards. The Huawei's PCIE HiNIC card is a new Ethernet card and hence there was a need of a new driver. The current driver is meant to be used for the Physical Function and there would soon be a support for Virtual Function and more features once the basic PF driver has been accepted. Changes V4 -> V5: 1. Remove select_queue NOP - David Miller comment https://lkml.org/lkml/2017/8/16/625 Changes V3 -> V4: 1. Reverse christmas tree order - David Miller comment https://lkml.org/lkml/2017/8/3/862 Changes V2 -> V3: 1. Replace dev_ functions by netif_ functions - Joe Perches comment https://lkml.org/lkml/2017/7/19/424 2. Fix the driver directory in MAINTAINERS file - Sergei Shtylyov comment https://lkml.org/lkml/2017/7/19/615 3. Add a newline at the end of Makefile - David Miller comment https://lkml.org/lkml/2017/7/19/1345 4. Return a pointer as a val instead of in arg - Francois Romieu comment https://lkml.org/lkml/2017/7/19/1319 5. Change the error labels to err_xyz - Francois Romieu comment https://lkml.org/lkml/2017/7/19/1319 6. Remove check of Func Type in free function - Francois Romieu comment https://lkml.org/lkml/2017/7/19/1319 7. Remove !netdev check in remove function - Francois Romieu comment https://lkml.org/lkml/2017/7/19/1319 8. Use module_pci_driver - Francois Romieu comment https://lkml.org/lkml/2017/7/19/1319 9. Move the PCI device ID to the .c file - Francois Romieu comment https://lkml.org/lkml/2017/7/19/1319 10. Remove void * to avoid passing wrong ptr - Francois Romieu comment https://lkml.org/lkml/2017/7/19/1319 Changes V1 -> V2: 1. remove driver verstion - Andrew Lunn comment https://lkml.org/lkml/2017/7/12/372 2. replace kzalloc by devm_kzalloc for short clean - Andrew Lunn comment https://lkml.org/lkml/2017/7/12/372 3. replace pr_ functions by dev_ functions - Andrew Lunn comment https://lkml.org/lkml/2017/7/12/375 4. seperate last patch by moving ops to a new patch - Andrew Lunn comment https://lkml.org/lkml/2017/7/12/377 Aviad Krawczyk (21): net-next/hinic: Initialize hw interface net-next/hinic: Initialize hw device components net-next/hinic: Initialize api cmd resources net-next/hinic: Initialize api cmd hw net-next/hinic: Add management messages net-next/hinic: Add api cmd commands net-next/hinic: Add aeqs net-next/hinic: Add port management commands net-next/hinic: Add Rx mode and link event handler net-next/hinic: Add logical Txq and Rxq net-next/hinic: Add wq net-next/hinic: Add qp resources net-next/hinic: Set qp context net-next/hinic: Initialize cmdq net-next/hinic: Add ceqs net-next/hinic: Add cmdq commands net-next/hinic: Add cmdq completion handler net-next/hinic: Add Rx handler net-next/hinic: Add Tx operation net-next/hinic: Add ethtool and stats net-next/hinic: Add netpoll Documentation/networking/hinic.txt | 125 +++ MAINTAINERS|7 + drivers/net/ethernet/Kconfig |1 + drivers/net/ethernet/Makefile |1 + drivers/net/ethernet/huawei/Kconfig| 19 + drivers/net/ethernet/huawei/Makefile |5 + drivers/net/ethernet/huawei/hinic/Kconfig | 13 + drivers/net/ethernet/huawei/hinic/Makefile |6 + drivers/net/ethernet/huawei/hinic/hinic_common.c | 80 ++ drivers/net/ethernet/huawei/hinic/hinic_common.h | 38 + drivers/net/ethernet/huawei/hinic/hinic_dev.h | 64 ++ .../net/ethernet/huawei/hinic/hinic_hw_api_cmd.c | 977 + .../net/ethernet/huawei/hinic/hinic_hw_api_cmd.h | 208 drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c | 946 + drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.h | 187 drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h | 149 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c | 1045 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h | 239 + drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c | 888 drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.h | 265 + drivers/net/ethernet/huawei/hinic/hinic_hw_if.c| 352 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_if.h| 272 + drivers/net/ethernet/huawei/hinic/hinic_hw_io.c| 533 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_io.h| 97 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c | 597 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h | 153 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c| 892 drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h| 180 .../net/ethernet/huawei/hinic/hinic_hw_qp_ctxt.h | 214 drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c
Re: [PATCH v2] bpf: Update sysctl documentation to list all supported architectures
On 08/17/2017 12:30 PM, Michael Ellerman wrote: The sysctl documentation states that the JIT is only available on x86_64, which is no longer correct. Update the list, and break it out to indicate which architectures support the cBPF JIT (via HAVE_CBPF_JIT) or the eBPF JIT (HAVE_EBPF_JIT). Signed-off-by: Michael Ellerman The last paragraph speaking about tcpdump, I can take care of later, also given the patch is about updating list of archs, so lgtm, thanks! Acked-by: Daniel Borkmann
Re: [PATCH 1/6] bridge: learn dst metadata in FDB
On 17/08/17 14:39, Nikolay Aleksandrov wrote: > On 17/08/17 14:03, David Lamparter wrote: >> Hi Nikolay, >> >> >> On Wed, Aug 16, 2017 at 11:38:06PM +0300, Nikolay Aleksandrov wrote: >>> On 16/08/17 20:01, David Lamparter wrote: This implements holding dst metadata information in the bridge layer, but only for unicast entries in the MAC table. Multicast is still left to design and implement. >>> >>> Sorry but I do not agree with this change, adding a special case for >>> VPLS in the bridge code >> >> I don't think this is specific to VPLS at all, though you're right that >> VPLS is the only user currently. >> >>> and hitting the fast path for everyone in a few different places for a >>> feature that the majority will not use does not sound acceptable to >>> me. We've been trying hard to optimize it, trying to avoid additional >>> cache lines, removing tests and keeping special cases to a minimum. >> >> skb->dst is on the same cacheline as skb->len. >> fdb->md_dst is on the same cacheline as fdb->dst. >> Both will be 0 in a lot of cases, so this should be two null checks on >> data that is hot in the cache. Are you sure this is an actual problem? >> > > Sure - no, I haven't benchmarked it, but I don't see skb->len being on > the same cache line as _skb_refdst assuming 64 byte cache lines. I should've been clearer - that obviously depends on the kernel config, but in order for them to be in the same line you need to disable either one of conntrack, bridge_netfilter or xfrm, these are almost always enabled (at least in all major distributions). > But again any special cases, in my opinion, should be handled on their own, > it is both about the fast path and the code complexity that they bring in. > >>> I understand that you want to use the fdb tables and avoid >>> duplication, but this is not worth it. There're other similar use >>> cases and they have their own private fdb tables, that way the user >>> can opt out and is much cleaner and separated. >> >> Sure, this can be done. I think it's a noticeable performance penalty >> to have the entire fdb copied (multiple times for H-VPLS even), but I >> understand that it's preferable to have the normal cases faster in >> exchange. As the previous paragraph notes, I still wonder if that hit >> to the normal case exists though. >> >> I will leave this to Amine, he's paid to work on VPLS while I'm doing >> this for fun ;) >> >> There is however another concern I have here. As I noted in my >> introductory mail, I'm working on the bridge MDB making similar changes. >> And there's actually strong use cases for this in both VPLS and the >> 802.11 code (though I'm not sure I can code the latter one up, it's >> related to rate control and this is seriously complicated - the goal is >> to select a multicast rate based on the now-known receiving STAs). >> >> I really hope you're not suggesting the entire MDB with IPv4 & IPv6 >> snooping be duplicated into both VPLS and mac80211? >> > > Code can always be shared if there are more users, no need to stuff > everything in > the bridge, but I'm not that familiar with this case, once patches are out I > can > comment further. > >>> As you've noted this is only an RFC so I will not point out every issue, >>> but there seems >>> to be a major problem with br_fdb_update(), note that it runs without any >>> locks except RCU. >> >> Right, Thanks! ... I only thought about concurrent access, forgetting >> about concurrent modification... I'll replace it with an xchg I think. >> (No need for a lock that way) > > I think you can still lose references to a dst that way, what if someone > changes the > dst you read before the xchg and you xchg it ? > >> >> That said, now that I think about it, the skb_dst_set_noref() in the >> following chunk is probably not safe if the VPLS device has a qdisc on >> it. I was relying on the fact that br_dev_xmit is holding RCU there, >> but if the SKB is queued, md_dst might go away in the meantime... >> ... probably need to change this to dst_hold() + skb_dst_set()... >> >> >> -David >> diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 861ae2a165f4..534cacf02f8d 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -81,6 +82,9 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) else br_flood(br, skb, BR_PKT_MULTICAST, false, true); } else if ((dst = br_fdb_find_rcu(br, dest, vid)) != NULL) { + struct dst_entry *md_dst = rcu_dereference(dst->md_dst); + if (md_dst) + skb_dst_set_noref(skb, md_dst); br_forward(dst->dst, skb, false, true); } else { br_flood(br, skb, BR_PKT_UNICAST, false, true); >> >> diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index a79b648aac88..0751fcb89699 100644 @@ -567,10 +579,15 @@ void br_fdb_update(struct
[PATCH V5 net-next 00/21] Huawei HiNIC Ethernet Driver
The patch-set contains the support of the HiNIC Ethernet driver for hinic family of PCIE Network Interface Cards. The Huawei's PCIE HiNIC card is a new Ethernet card and hence there was a need of a new driver. The current driver is meant to be used for the Physical Function and there would soon be a support for Virtual Function and more features once the basic PF driver has been accepted. Changes V4 -> V5: 1. Remove select_queue NOP - David Miller comment https://lkml.org/lkml/2017/8/16/625 Changes V3 -> V4: 1. Reverse christmas tree order - David Miller comment https://lkml.org/lkml/2017/8/3/862 Changes V2 -> V3: 1. Replace dev_ functions by netif_ functions - Joe Perches comment https://lkml.org/lkml/2017/7/19/424 2. Fix the driver directory in MAINTAINERS file - Sergei Shtylyov comment https://lkml.org/lkml/2017/7/19/615 3. Add a newline at the end of Makefile - David Miller comment https://lkml.org/lkml/2017/7/19/1345 4. Return a pointer as a val instead of in arg - Francois Romieu comment https://lkml.org/lkml/2017/7/19/1319 5. Change the error labels to err_xyz - Francois Romieu comment https://lkml.org/lkml/2017/7/19/1319 6. Remove check of Func Type in free function - Francois Romieu comment https://lkml.org/lkml/2017/7/19/1319 7. Remove !netdev check in remove function - Francois Romieu comment https://lkml.org/lkml/2017/7/19/1319 8. Use module_pci_driver - Francois Romieu comment https://lkml.org/lkml/2017/7/19/1319 9. Move the PCI device ID to the .c file - Francois Romieu comment https://lkml.org/lkml/2017/7/19/1319 10. Remove void * to avoid passing wrong ptr - Francois Romieu comment https://lkml.org/lkml/2017/7/19/1319 Changes V1 -> V2: 1. remove driver verstion - Andrew Lunn comment https://lkml.org/lkml/2017/7/12/372 2. replace kzalloc by devm_kzalloc for short clean - Andrew Lunn comment https://lkml.org/lkml/2017/7/12/372 3. replace pr_ functions by dev_ functions - Andrew Lunn comment https://lkml.org/lkml/2017/7/12/375 4. seperate last patch by moving ops to a new patch - Andrew Lunn comment https://lkml.org/lkml/2017/7/12/377 Aviad Krawczyk (21): net-next/hinic: Initialize hw interface net-next/hinic: Initialize hw device components net-next/hinic: Initialize api cmd resources net-next/hinic: Initialize api cmd hw net-next/hinic: Add management messages net-next/hinic: Add api cmd commands net-next/hinic: Add aeqs net-next/hinic: Add port management commands net-next/hinic: Add Rx mode and link event handler net-next/hinic: Add logical Txq and Rxq net-next/hinic: Add wq net-next/hinic: Add qp resources net-next/hinic: Set qp context net-next/hinic: Initialize cmdq net-next/hinic: Add ceqs net-next/hinic: Add cmdq commands net-next/hinic: Add cmdq completion handler net-next/hinic: Add Rx handler net-next/hinic: Add Tx operation net-next/hinic: Add ethtool and stats net-next/hinic: Add netpoll Documentation/networking/hinic.txt | 125 +++ MAINTAINERS|7 + drivers/net/ethernet/Kconfig |1 + drivers/net/ethernet/Makefile |1 + drivers/net/ethernet/huawei/Kconfig| 19 + drivers/net/ethernet/huawei/Makefile |5 + drivers/net/ethernet/huawei/hinic/Kconfig | 13 + drivers/net/ethernet/huawei/hinic/Makefile |6 + drivers/net/ethernet/huawei/hinic/hinic_common.c | 80 ++ drivers/net/ethernet/huawei/hinic/hinic_common.h | 38 + drivers/net/ethernet/huawei/hinic/hinic_dev.h | 64 ++ .../net/ethernet/huawei/hinic/hinic_hw_api_cmd.c | 977 + .../net/ethernet/huawei/hinic/hinic_hw_api_cmd.h | 208 drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c | 946 + drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.h | 187 drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h | 149 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c | 1045 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h | 239 + drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c | 888 drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.h | 265 + drivers/net/ethernet/huawei/hinic/hinic_hw_if.c| 352 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_if.h| 272 + drivers/net/ethernet/huawei/hinic/hinic_hw_io.c| 533 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_io.h| 97 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c | 597 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h | 153 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c| 892 drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h| 180 .../net/ethernet/huawei/hinic/hinic_hw_qp_ctxt.h | 214 drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c
[PATCH V5 net-next 01/21] net-next/hinic: Initialize hw interface
Initialize hw interface as part of the nic initialization for accessing hw. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- Documentation/networking/hinic.txt | 125 ++ drivers/net/ethernet/Kconfig | 1 + drivers/net/ethernet/Makefile| 1 + drivers/net/ethernet/huawei/Kconfig | 19 +++ drivers/net/ethernet/huawei/Makefile | 5 + drivers/net/ethernet/huawei/hinic/Kconfig| 13 ++ drivers/net/ethernet/huawei/hinic/Makefile | 3 + drivers/net/ethernet/huawei/hinic/hinic_dev.h| 33 drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h | 36 drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c | 201 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h | 42 + drivers/net/ethernet/huawei/hinic/hinic_hw_if.c | 208 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_if.h | 160 + drivers/net/ethernet/huawei/hinic/hinic_main.c | 195 + 14 files changed, 1042 insertions(+) create mode 100644 Documentation/networking/hinic.txt create mode 100644 drivers/net/ethernet/huawei/Kconfig create mode 100644 drivers/net/ethernet/huawei/Makefile create mode 100644 drivers/net/ethernet/huawei/hinic/Kconfig create mode 100644 drivers/net/ethernet/huawei/hinic/Makefile create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_dev.h create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_if.c create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_if.h create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_main.c diff --git a/Documentation/networking/hinic.txt b/Documentation/networking/hinic.txt new file mode 100644 index 000..989366a --- /dev/null +++ b/Documentation/networking/hinic.txt @@ -0,0 +1,125 @@ +Linux Kernel Driver for Huawei Intelligent NIC(HiNIC) family + + +Overview: += +HiNIC is a network interface card for the Data Center Area. + +The driver supports a range of link-speed devices (10GbE, 25GbE, 40GbE, etc.). +The driver supports also a negotiated and extendable feature set. + +Some HiNIC devices support SR-IOV. This driver is used for Physical Function +(PF). + +HiNIC devices support MSI-X interrupt vector for each Tx/Rx queue and +adaptive interrupt moderation. + +HiNIC devices support also various offload features such as checksum offload, +TCP Transmit Segmentation Offload(TSO), Receive-Side Scaling(RSS) and +LRO(Large Receive Offload). + + +Supported PCI vendor ID/device IDs: +=== + +19e5:1822 - HiNIC PF + + +Driver Architecture and Source Code: + + +hinic_dev - Implement a Logical Network device that is independent from +specific HW details about HW data structure formats. + +hinic_hwdev - Implement the HW details of the device and include the components +for accessing the PCI NIC. + +hinic_hwdev contains the following components: +=== + +HW Interface: += + +The interface for accessing the pci device (DMA memory and PCI BARs). +(hinic_hw_if.c, hinic_hw_if.h) + +Configuration Status Registers Area that describes the HW Registers on the +configuration and status BAR0. (hinic_hw_csr.h) + +MGMT components: + + +Asynchronous Event Queues(AEQs) - The event queues for receiving messages from +the MGMT modules on the cards. (hinic_hw_eqs.c, hinic_hw_eqs.h) + +Application Programmable Interface commands(API CMD) - Interface for sending +MGMT commands to the card. (hinic_hw_api_cmd.c, hinic_hw_api_cmd.h) + +Management (MGMT) - the PF to MGMT channel that uses API CMD for sending MGMT +commands to the card and receives notifications from the MGMT modules on the +card by AEQs. Also set the addresses of the IO CMDQs in HW. +(hinic_hw_mgmt.c, hinic_hw_mgmt.h) + +IO components: +== + +Completion Event Queues(CEQs) - The completion Event Queues that describe IO +tasks that are finished. (hinic_hw_eqs.c, hinic_hw_eqs.h) + +Work Queues(WQ) - Contain the memory and operations for use by CMD queues and +the Queue Pairs. The WQ is a Memory Block in a Page. The Block contains +pointers to Memory Areas that are the Memory for the Work Queue Elements(WQEs). +(hinic_hw_wq.c, hinic_hw_wq.h) + +Command Queues(CMDQ) - The queues for sending commands for IO management and is +used to set the QPs addresses in HW. The commands completion events are +accumulated on the CEQ that is configured to receive the CMDQ completion events. +(hinic_hw_cmdq.c, hinic_hw_cmdq.h) + +Queue Pairs(QPs) - The HW Receive and Send queues for Receiving and Transmitting +Data. (hinic_hw_qp.c, hini
[PATCH V5 net-next 09/21] net-next/hinic: Add Rx mode and link event handler
Add port management message for setting Rx mode in the card, used for rx_mode netdev operation. The link event handler is used for getting a notification about the link state. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- drivers/net/ethernet/huawei/hinic/hinic_dev.h | 17 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h | 2 + drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c | 118 + drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h | 37 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_if.c | 17 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_if.h | 17 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c | 64 - drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h | 28 +++ drivers/net/ethernet/huawei/hinic/hinic_main.c| 284 ++ drivers/net/ethernet/huawei/hinic/hinic_port.c| 92 +++ drivers/net/ethernet/huawei/hinic/hinic_port.h| 66 + 11 files changed, 741 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_dev.h index e54a45c..5c5b4e9 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_dev.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_dev.h @@ -19,19 +19,36 @@ #include #include #include +#include +#include #include "hinic_hw_dev.h" #define HINIC_DRV_NAME "hinic" +enum hinic_flags { + HINIC_LINK_UP = BIT(0), + HINIC_INTF_UP = BIT(1), +}; + +struct hinic_rx_mode_work { + struct work_struct work; + u32 rx_mode; +}; + struct hinic_dev { struct net_device *netdev; struct hinic_hwdev *hwdev; u32 msg_enable; + unsigned intflags; + struct semaphoremgmt_lock; unsigned long *vlan_bitmap; + + struct hinic_rx_mode_work rx_mode_work; + struct workqueue_struct *workq; }; #endif diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h index 52eb89c..1f57301 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h @@ -20,6 +20,8 @@ #define HINIC_CSR_FUNC_ATTR0_ADDR 0x0 #define HINIC_CSR_FUNC_ATTR1_ADDR 0x4 +#define HINIC_CSR_FUNC_ATTR5_ADDR 0x14 + #define HINIC_DMA_ATTR_BASE 0xC80 #define HINIC_ELECTION_BASE 0x4200 diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c index 6bb6c33..75fd6d2 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c @@ -230,6 +230,114 @@ int hinic_port_msg_cmd(struct hinic_hwdev *hwdev, enum hinic_port_cmd cmd, } /** + * hinic_hwdev_cb_register - register callback handler for MGMT events + * @hwdev: the NIC HW device + * @cmd: the mgmt event + * @handle: private data for the handler + * @handler: event handler + **/ +void hinic_hwdev_cb_register(struct hinic_hwdev *hwdev, +enum hinic_mgmt_msg_cmd cmd, void *handle, +void (*handler)(void *handle, void *buf_in, +u16 in_size, void *buf_out, +u16 *out_size)) +{ + struct hinic_hwif *hwif = hwdev->hwif; + struct pci_dev *pdev = hwif->pdev; + struct hinic_pfhwdev *pfhwdev; + struct hinic_nic_cb *nic_cb; + u8 cmd_cb; + + if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) { + dev_err(&pdev->dev, "unsupported PCI Function type\n"); + return; + } + + pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev); + + cmd_cb = cmd - HINIC_MGMT_MSG_CMD_BASE; + nic_cb = &pfhwdev->nic_cb[cmd_cb]; + + nic_cb->handler = handler; + nic_cb->handle = handle; + nic_cb->cb_state = HINIC_CB_ENABLED; +} + +/** + * hinic_hwdev_cb_unregister - unregister callback handler for MGMT events + * @hwdev: the NIC HW device + * @cmd: the mgmt event + **/ +void hinic_hwdev_cb_unregister(struct hinic_hwdev *hwdev, + enum hinic_mgmt_msg_cmd cmd) +{ + struct hinic_hwif *hwif = hwdev->hwif; + struct pci_dev *pdev = hwif->pdev; + struct hinic_pfhwdev *pfhwdev; + struct hinic_nic_cb *nic_cb; + u8 cmd_cb; + + if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) { + dev_err(&pdev->dev, "unsupported PCI Function type\n"); + return; + } + + pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev); + + cmd_cb = cmd - HINIC_MGMT_MSG_CMD_BASE; + nic_cb = &pfhwdev->nic_cb[cmd_cb]; + + nic_cb->cb_state &= ~HINIC_CB_ENABLED; + + while (
[PATCH V5 net-next 21/21] net-next/hinic: Add netpoll
Add more netdev operation - netpoll. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- MAINTAINERS| 7 +++ drivers/net/ethernet/huawei/hinic/hinic_main.c | 20 2 files changed, 27 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 0e967b3..8f9ea9b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6240,6 +6240,13 @@ L: linux-in...@vger.kernel.org S: Maintained F: drivers/input/touchscreen/htcpen.c +HUAWEI ETHERNET DRIVER +M: Aviad Krawczyk +L: netdev@vger.kernel.org +S: Supported +F: Documentation/networking/hinic.txt +F: drivers/net/ethernet/huawei/hinic/ + HUGETLB FILESYSTEM M: Nadia Yvette Chambers S: Maintained diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c index a77a7f8..59f3358 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_main.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c @@ -787,6 +787,23 @@ static void hinic_get_stats64(struct net_device *netdev, stats->tx_errors = nic_tx_stats->tx_dropped; } +#ifdef CONFIG_NET_POLL_CONTROLLER +static void hinic_netpoll(struct net_device *netdev) +{ + struct hinic_dev *nic_dev = netdev_priv(netdev); + int i, num_qps; + + num_qps = hinic_hwdev_num_qps(nic_dev->hwdev); + for (i = 0; i < num_qps; i++) { + struct hinic_txq *txq = &nic_dev->txqs[i]; + struct hinic_rxq *rxq = &nic_dev->rxqs[i]; + + napi_schedule(&txq->napi); + napi_schedule(&rxq->napi); + } +} +#endif + static const struct net_device_ops hinic_netdev_ops = { .ndo_open = hinic_open, .ndo_stop = hinic_close, @@ -799,6 +816,9 @@ static void hinic_get_stats64(struct net_device *netdev, .ndo_start_xmit = hinic_xmit_frame, .ndo_tx_timeout = hinic_tx_timeout, .ndo_get_stats64 = hinic_get_stats64, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = hinic_netpoll, +#endif }; static void netdev_features_init(struct net_device *netdev) -- 1.9.1
[PATCH V5 net-next 20/21] net-next/hinic: Add ethtool and stats
Add ethtool operations and statistics operations. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- drivers/net/ethernet/huawei/hinic/hinic_dev.h | 3 + drivers/net/ethernet/huawei/hinic/hinic_main.c | 218 - drivers/net/ethernet/huawei/hinic/hinic_port.c | 31 drivers/net/ethernet/huawei/hinic/hinic_port.h | 45 + drivers/net/ethernet/huawei/hinic/hinic_rx.c | 19 +++ drivers/net/ethernet/huawei/hinic/hinic_rx.h | 2 + drivers/net/ethernet/huawei/hinic/hinic_tx.c | 22 +++ drivers/net/ethernet/huawei/hinic/hinic_tx.h | 2 + 8 files changed, 341 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_dev.h index 15d0c2e..5186cc9 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_dev.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_dev.h @@ -56,6 +56,9 @@ struct hinic_dev { struct hinic_txq*txqs; struct hinic_rxq*rxqs; + + struct hinic_txq_stats tx_stats; + struct hinic_rxq_stats rx_stats; }; #endif diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c index 4a5f23f..a77a7f8 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_main.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c @@ -69,6 +69,186 @@ static int change_mac_addr(struct net_device *netdev, const u8 *addr); +static void set_link_speed(struct ethtool_link_ksettings *link_ksettings, + enum hinic_speed speed) +{ + switch (speed) { + case HINIC_SPEED_10MB_LINK: + link_ksettings->base.speed = SPEED_10; + break; + + case HINIC_SPEED_100MB_LINK: + link_ksettings->base.speed = SPEED_100; + break; + + case HINIC_SPEED_1000MB_LINK: + link_ksettings->base.speed = SPEED_1000; + break; + + case HINIC_SPEED_10GB_LINK: + link_ksettings->base.speed = SPEED_1; + break; + + case HINIC_SPEED_25GB_LINK: + link_ksettings->base.speed = SPEED_25000; + break; + + case HINIC_SPEED_40GB_LINK: + link_ksettings->base.speed = SPEED_4; + break; + + case HINIC_SPEED_100GB_LINK: + link_ksettings->base.speed = SPEED_10; + break; + + default: + link_ksettings->base.speed = SPEED_UNKNOWN; + break; + } +} + +static int hinic_get_link_ksettings(struct net_device *netdev, + struct ethtool_link_ksettings + *link_ksettings) +{ + struct hinic_dev *nic_dev = netdev_priv(netdev); + enum hinic_port_link_state link_state; + struct hinic_port_cap port_cap; + int err; + + ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising); + ethtool_link_ksettings_add_link_mode(link_ksettings, supported, +Autoneg); + + link_ksettings->base.speed = SPEED_UNKNOWN; + link_ksettings->base.autoneg = AUTONEG_DISABLE; + link_ksettings->base.duplex = DUPLEX_UNKNOWN; + + err = hinic_port_get_cap(nic_dev, &port_cap); + if (err) { + netif_err(nic_dev, drv, netdev, + "Failed to get port capabilities\n"); + return err; + } + + err = hinic_port_link_state(nic_dev, &link_state); + if (err) { + netif_err(nic_dev, drv, netdev, + "Failed to get port link state\n"); + return err; + } + + if (link_state != HINIC_LINK_STATE_UP) { + netif_info(nic_dev, drv, netdev, "No link\n"); + return err; + } + + set_link_speed(link_ksettings, port_cap.speed); + + if (!!(port_cap.autoneg_cap & HINIC_AUTONEG_SUPPORTED)) + ethtool_link_ksettings_add_link_mode(link_ksettings, +advertising, Autoneg); + + if (port_cap.autoneg_state == HINIC_AUTONEG_ACTIVE) + link_ksettings->base.autoneg = AUTONEG_ENABLE; + + link_ksettings->base.duplex = (port_cap.duplex == HINIC_DUPLEX_FULL) ? + DUPLEX_FULL : DUPLEX_HALF; + return 0; +} + +static void hinic_get_drvinfo(struct net_device *netdev, + struct ethtool_drvinfo *info) +{ + struct hinic_dev *nic_dev = netdev_priv(netdev); + struct hinic_hwdev *hwdev = nic_dev->hwdev; + struct hinic_hwif *hwif = hwdev->hwif; + + strlcpy(info->driver, HINIC_DRV_NAME, sizeof(info->driver)); + strlcpy(info->bus_info, pci_name(hwif->pdev), sizeof(info->bus_info)); +} + +static void hinic_get_ringparam(struct net_device *netdev, + struct
[PATCH V5 net-next 18/21] net-next/hinic: Add Rx handler
Set the io resources in the nic and handle rx events by qp operations. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- drivers/net/ethernet/huawei/hinic/hinic_dev.h | 1 + drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h | 1 + drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c | 361 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h | 77 drivers/net/ethernet/huawei/hinic/hinic_hw_if.c | 36 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_if.h | 35 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h | 13 + drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c | 210 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h | 29 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c | 12 + drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h | 2 + drivers/net/ethernet/huawei/hinic/hinic_main.c| 27 ++ drivers/net/ethernet/huawei/hinic/hinic_port.c| 32 ++ drivers/net/ethernet/huawei/hinic/hinic_port.h| 19 + drivers/net/ethernet/huawei/hinic/hinic_rx.c | 419 ++ drivers/net/ethernet/huawei/hinic/hinic_rx.h | 7 + 16 files changed, 1281 insertions(+) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_dev.h index 5b8231d..3d0f6cf 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_dev.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_dev.h @@ -43,6 +43,7 @@ struct hinic_dev { struct hinic_hwdev *hwdev; u32 msg_enable; + unsigned intrx_weight; unsigned intflags; diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h index 10b8c7b..f39b184 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h @@ -20,6 +20,7 @@ #define HINIC_CSR_FUNC_ATTR0_ADDR 0x0 #define HINIC_CSR_FUNC_ATTR1_ADDR 0x4 +#define HINIC_CSR_FUNC_ATTR4_ADDR 0x10 #define HINIC_CSR_FUNC_ATTR5_ADDR 0x14 #define HINIC_DMA_ATTR_BASE 0xC80 diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c index cb4c472..03149e8 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c @@ -20,6 +20,9 @@ #include #include #include +#include +#include +#include #include #include "hinic_hw_if.h" @@ -30,6 +33,10 @@ #include "hinic_hw_io.h" #include "hinic_hw_dev.h" +#define IO_STATUS_TIMEOUT 100 +#define OUTBOUND_STATE_TIMEOUT 100 +#define DB_STATE_TIMEOUT100 + #define MAX_IRQS(max_qps, num_aeqs, num_ceqs) \ (2 * (max_qps) + (num_aeqs) + (num_ceqs)) @@ -37,6 +44,15 @@ enum intr_type { INTR_MSIX_TYPE, }; +enum io_status { + IO_STOPPED = 0, + IO_RUNNING = 1, +}; + +enum hw_ioctxt_set_cmdq_depth { + HW_IOCTXT_SET_CMDQ_DEPTH_DEFAULT, +}; + /* HW struct */ struct hinic_dev_cap { u8 status; @@ -51,6 +67,31 @@ struct hinic_dev_cap { u8 rsvd3[208]; }; +struct rx_buf_sz { + int idx; + size_t sz; +}; + +static struct rx_buf_sz rx_buf_sz_table[] = { + {0, 32}, + {1, 64}, + {2, 96}, + {3, 128}, + {4, 192}, + {5, 256}, + {6, 384}, + {7, 512}, + {8, 768}, + {9, 1024}, + {10, 1536}, + {11, 2048}, + {12, 3072}, + {13, 4096}, + {14, 8192}, + {15, 16384}, + {-1, -1}, +}; + /** * get_capability - convert device capabilities to NIC capabilities * @hwdev: the HW device to set and convert device capabilities for @@ -236,6 +277,252 @@ int hinic_port_msg_cmd(struct hinic_hwdev *hwdev, enum hinic_port_cmd cmd, } /** + * init_fw_ctxt- Init Firmware tables before network mgmt and io operations + * @hwdev: the NIC HW device + * + * Return 0 - Success, negative - Failure + **/ +static int init_fw_ctxt(struct hinic_hwdev *hwdev) +{ + struct hinic_hwif *hwif = hwdev->hwif; + struct pci_dev *pdev = hwif->pdev; + struct hinic_cmd_fw_ctxt fw_ctxt; + struct hinic_pfhwdev *pfhwdev; + u16 out_size; + int err; + + if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) { + dev_err(&pdev->dev, "Unsupported PCI Function type\n"); + return -EINVAL; + } + + fw_ctxt.func_idx = HINIC_HWIF_FUNC_IDX(hwif); + fw_ctxt.rx_buf_sz = HINIC_RX_BUF_SZ; + + pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev); + + err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_FWCTXT_INIT, +&fw_ctxt, sizeof(fw_ctxt), +&fw_ctxt, &out_size); + if (err || (out_size != sizeof(fw_ctxt)) || fw_c
[PATCH V5 net-next 17/21] net-next/hinic: Add cmdq completion handler
Add cmdq completion handler for getting a notification about the completion of cmdq commands. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c | 297 +- drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.h | 12 + 2 files changed, 308 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c index d8c0807..8d72762 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c @@ -40,12 +40,31 @@ #include "hinic_hw_io.h" #include "hinic_hw_dev.h" +#define CMDQ_CEQE_TYPE_SHIFT0 + +#define CMDQ_CEQE_TYPE_MASK 0x7 + +#define CMDQ_CEQE_GET(val, member) \ + (((val) >> CMDQ_CEQE_##member##_SHIFT) \ +& CMDQ_CEQE_##member##_MASK) + +#define CMDQ_WQE_ERRCODE_VAL_SHIFT 20 + +#define CMDQ_WQE_ERRCODE_VAL_MASK 0xF + +#define CMDQ_WQE_ERRCODE_GET(val, member) \ + (((val) >> CMDQ_WQE_ERRCODE_##member##_SHIFT) \ +& CMDQ_WQE_ERRCODE_##member##_MASK) + #define CMDQ_DB_PI_OFF(pi) (((u16)LOWER_8_BITS(pi)) << 3) #define CMDQ_DB_ADDR(db_base, pi) ((db_base) + CMDQ_DB_PI_OFF(pi)) #define CMDQ_WQE_HEADER(wqe)((struct hinic_cmdq_header *)(wqe)) +#define CMDQ_WQE_COMPLETED(ctrl_info) \ + HINIC_CMDQ_CTRL_GET(ctrl_info, HW_BUSY_BIT) + #define FIRST_DATA_TO_WRITE_LASTsizeof(u64) #define CMDQ_DB_OFF SZ_2K @@ -145,6 +164,22 @@ void hinic_free_cmdq_buf(struct hinic_cmdqs *cmdqs, pci_pool_free(cmdqs->cmdq_buf_pool, cmdq_buf->buf, cmdq_buf->dma_addr); } +static unsigned int cmdq_wqe_size_from_bdlen(enum bufdesc_len len) +{ + unsigned int wqe_size = 0; + + switch (len) { + case BUFDESC_LCMD_LEN: + wqe_size = WQE_LCMD_SIZE; + break; + case BUFDESC_SCMD_LEN: + wqe_size = WQE_SCMD_SIZE; + break; + } + + return wqe_size; +} + static void cmdq_set_sge_completion(struct hinic_cmdq_completion *completion, struct hinic_cmdq_buf *buf_out) { @@ -211,6 +246,15 @@ static void cmdq_set_lcmd_bufdesc(struct hinic_cmdq_wqe_lcmd *wqe_lcmd, hinic_set_sge(&wqe_lcmd->buf_desc.sge, buf_in->dma_addr, buf_in->size); } +static void cmdq_set_direct_wqe_data(struct hinic_cmdq_direct_wqe *wqe, +void *buf_in, u32 in_size) +{ + struct hinic_cmdq_wqe_scmd *wqe_scmd = &wqe->wqe_scmd; + + wqe_scmd->buf_desc.buf_len = in_size; + memcpy(wqe_scmd->buf_desc.data, buf_in, in_size); +} + static void cmdq_set_lcmd_wqe(struct hinic_cmdq_wqe *wqe, enum cmdq_cmd_type cmd_type, struct hinic_cmdq_buf *buf_in, @@ -239,6 +283,36 @@ static void cmdq_set_lcmd_wqe(struct hinic_cmdq_wqe *wqe, cmdq_set_lcmd_bufdesc(wqe_lcmd, buf_in); } +static void cmdq_set_direct_wqe(struct hinic_cmdq_wqe *wqe, + enum cmdq_cmd_type cmd_type, + void *buf_in, u16 in_size, + struct hinic_cmdq_buf *buf_out, int wrapped, + enum hinic_cmd_ack_type ack_type, + enum hinic_mod_type mod, u8 cmd, u16 prod_idx) +{ + struct hinic_cmdq_direct_wqe *direct_wqe = &wqe->direct_wqe; + enum completion_format complete_format; + struct hinic_cmdq_wqe_scmd *wqe_scmd; + + wqe_scmd = &direct_wqe->wqe_scmd; + + switch (cmd_type) { + case CMDQ_CMD_SYNC_SGE_RESP: + complete_format = COMPLETE_SGE; + cmdq_set_sge_completion(&wqe_scmd->completion, buf_out); + break; + case CMDQ_CMD_SYNC_DIRECT_RESP: + complete_format = COMPLETE_DIRECT; + wqe_scmd->completion.direct_resp = 0; + break; + } + + cmdq_prepare_wqe_ctrl(wqe, wrapped, ack_type, mod, cmd, prod_idx, + complete_format, DATA_DIRECT, BUFDESC_SCMD_LEN); + + cmdq_set_direct_wqe_data(direct_wqe, buf_in, in_size); +} + static void cmdq_wqe_fill(void *dst, void *src) { memcpy(dst + FIRST_DATA_TO_WRITE_LAST, src + FIRST_DATA_TO_WRITE_LAST, @@ -352,6 +426,52 @@ static int cmdq_sync_cmd_direct_resp(struct hinic_cmdq *cmdq, return 0; } +static int cmdq_set_arm_bit(struct hinic_cmdq *cmdq, void *buf_in, + u16 in_size) +{ + struct hinic_cmdq_wqe *curr_cmdq_wqe, cmdq_wqe; + u16 curr_prod_idx, next_prod_idx; + struct hinic_wq *wq = cmdq->wq; + struct hinic_hw_wqe *hw_wqe; + int wrapped, num_wqebbs; + + /* Keep doorbell index corr
[PATCH V5 net-next 15/21] net-next/hinic: Add ceqs
Initialize the completion event queues and handle ceq events by calling the registered handlers. Used for cmdq command completion. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c | 16 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h | 29 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c | 7 +- drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c | 291 +- drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.h | 75 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_io.c | 15 +- drivers/net/ethernet/huawei/hinic/hinic_hw_io.h | 3 + 7 files changed, 428 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c index 0dccbe6..ec24b95 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c @@ -27,6 +27,7 @@ #include #include "hinic_hw_if.h" +#include "hinic_hw_eqs.h" #include "hinic_hw_mgmt.h" #include "hinic_hw_wq.h" #include "hinic_hw_cmdq.h" @@ -110,6 +111,16 @@ int hinic_cmdq_direct_resp(struct hinic_cmdqs *cmdqs, } /** + * cmdq_ceq_handler - cmdq completion event handler + * @handle: private data for the handler(cmdqs) + * @ceqe_data: ceq element data + **/ +static void cmdq_ceq_handler(void *handle, u32 ceqe_data) +{ + /* should be implemented */ +} + +/** * cmdq_init_queue_ctxt - init the queue ctxt of a cmdq * @cmdq_ctxt: cmdq ctxt to initialize * @cmdq: the cmdq @@ -320,6 +331,8 @@ int hinic_init_cmdqs(struct hinic_cmdqs *cmdqs, struct hinic_hwif *hwif, goto err_cmdq_ctxt; } + hinic_ceq_register_cb(&func_to_io->ceqs, HINIC_CEQ_CMDQ, cmdqs, + cmdq_ceq_handler); return 0; err_cmdq_ctxt: @@ -340,10 +353,13 @@ int hinic_init_cmdqs(struct hinic_cmdqs *cmdqs, struct hinic_hwif *hwif, **/ void hinic_free_cmdqs(struct hinic_cmdqs *cmdqs) { + struct hinic_func_to_io *func_to_io = cmdqs_to_func_to_io(cmdqs); struct hinic_hwif *hwif = cmdqs->hwif; struct pci_dev *pdev = hwif->pdev; enum hinic_cmdq_type cmdq_type; + hinic_ceq_unregister_cb(&func_to_io->ceqs, HINIC_CEQ_CMDQ); + cmdq_type = HINIC_CMDQ_SYNC; for (; cmdq_type < HINIC_MAX_CMDQ_TYPES; cmdq_type++) free_cmdq(&cmdqs->cmdq[cmdq_type]); diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h index 1f57301..10b8c7b 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h @@ -81,27 +81,44 @@ /* EQ registers */ #define HINIC_AEQ_MTT_OFF_BASE_ADDR 0x200 +#define HINIC_CEQ_MTT_OFF_BASE_ADDR 0x400 #define HINIC_EQ_MTT_OFF_STRIDE 0x40 #define HINIC_CSR_AEQ_MTT_OFF(id) \ (HINIC_AEQ_MTT_OFF_BASE_ADDR + (id) * HINIC_EQ_MTT_OFF_STRIDE) +#define HINIC_CSR_CEQ_MTT_OFF(id) \ + (HINIC_CEQ_MTT_OFF_BASE_ADDR + (id) * HINIC_EQ_MTT_OFF_STRIDE) + #define HINIC_CSR_EQ_PAGE_OFF_STRIDE8 #define HINIC_CSR_AEQ_HI_PHYS_ADDR_REG(q_id, pg_num)\ (HINIC_CSR_AEQ_MTT_OFF(q_id) + \ (pg_num) * HINIC_CSR_EQ_PAGE_OFF_STRIDE) +#define HINIC_CSR_CEQ_HI_PHYS_ADDR_REG(q_id, pg_num)\ + (HINIC_CSR_CEQ_MTT_OFF(q_id) + \ +(pg_num) * HINIC_CSR_EQ_PAGE_OFF_STRIDE) + #define HINIC_CSR_AEQ_LO_PHYS_ADDR_REG(q_id, pg_num)\ (HINIC_CSR_AEQ_MTT_OFF(q_id) + \ (pg_num) * HINIC_CSR_EQ_PAGE_OFF_STRIDE + 4) +#define HINIC_CSR_CEQ_LO_PHYS_ADDR_REG(q_id, pg_num)\ + (HINIC_CSR_CEQ_MTT_OFF(q_id) + \ +(pg_num) * HINIC_CSR_EQ_PAGE_OFF_STRIDE + 4) + #define HINIC_AEQ_CTRL_0_ADDR_BASE 0xE00 #define HINIC_AEQ_CTRL_1_ADDR_BASE 0xE04 #define HINIC_AEQ_CONS_IDX_ADDR_BASE0xE08 #define HINIC_AEQ_PROD_IDX_ADDR_BASE0xE0C +#define HINIC_CEQ_CTRL_0_ADDR_BASE 0x1000 +#define HINIC_CEQ_CTRL_1_ADDR_BASE 0x1004 +#define HINIC_CEQ_CONS_IDX_ADDR_BASE0x1008 +#define HINIC_CEQ_PROD_IDX_ADDR_BASE0x100C + #define HINIC_EQ_OFF_STRIDE 0x80 #define HINIC_CSR_AEQ_CTRL_0_ADDR(idx) \ @@ -116,4 +133,16 @@ #define HINIC_CSR_AEQ_PROD_IDX_ADDR(idx)\ (HINIC_AEQ_PROD_IDX_ADDR_BASE + (idx) * HINIC_EQ_OFF_STRIDE) +#define HINIC_CSR_CEQ_CTRL_0_ADDR(idx) \ + (HINIC_CEQ_CTRL_0_ADDR_BASE + (idx) * HINIC_EQ_OFF_STRIDE) + +#define HINIC_CSR_CEQ_CTRL_1_ADDR(idx) \ + (HINIC_CEQ_CTRL_1_ADDR_BASE + (idx) * HINIC_EQ_OFF_STRIDE) + +#define HINIC_CSR_CEQ_CONS_IDX_ADDR(idx)\ + (HINI
[PATCH V5 net-next 19/21] net-next/hinic: Add Tx operation
Add transmit operation for sending data by qp operations. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- drivers/net/ethernet/huawei/hinic/hinic_dev.h| 1 + drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c | 47 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h | 22 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c | 257 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h | 48 +++ drivers/net/ethernet/huawei/hinic/hinic_main.c | 12 +- drivers/net/ethernet/huawei/hinic/hinic_tx.c | 406 +++ drivers/net/ethernet/huawei/hinic/hinic_tx.h | 11 + 8 files changed, 802 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_dev.h index 3d0f6cf..15d0c2e 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_dev.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_dev.h @@ -43,6 +43,7 @@ struct hinic_dev { struct hinic_hwdev *hwdev; u32 msg_enable; + unsigned inttx_weight; unsigned intrx_weight; unsigned intflags; diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c index 03149e8..6606fba 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c @@ -40,6 +40,8 @@ #define MAX_IRQS(max_qps, num_aeqs, num_ceqs) \ (2 * (max_qps) + (num_aeqs) + (num_ceqs)) +#define ADDR_IN_4BYTES(addr)((addr) >> 2) + enum intr_type { INTR_MSIX_TYPE, }; @@ -996,3 +998,48 @@ int hinic_hwdev_msix_set(struct hinic_hwdev *hwdev, u16 msix_index, lli_timer_cfg, lli_credit_limit, resend_timer); } + +/** + * hinic_hwdev_hw_ci_addr_set - set cons idx addr and attributes in HW for sq + * @hwdev: the NIC HW device + * @sq: send queue + * @pending_limit: the maximum pending update ci events (unit 8) + * @coalesc_timer: coalesc period for update ci (unit 8 us) + * + * Return 0 - Success, negative - Failure + **/ +int hinic_hwdev_hw_ci_addr_set(struct hinic_hwdev *hwdev, struct hinic_sq *sq, + u8 pending_limit, u8 coalesc_timer) +{ + struct hinic_qp *qp = container_of(sq, struct hinic_qp, sq); + struct hinic_hwif *hwif = hwdev->hwif; + struct pci_dev *pdev = hwif->pdev; + struct hinic_pfhwdev *pfhwdev; + struct hinic_cmd_hw_ci hw_ci; + + if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) { + dev_err(&pdev->dev, "Unsupported PCI Function type\n"); + return -EINVAL; + } + + hw_ci.dma_attr_off = 0; + hw_ci.pending_limit = pending_limit; + hw_ci.coalesc_timer = coalesc_timer; + + hw_ci.msix_en = 1; + hw_ci.msix_entry_idx = sq->msix_entry; + + hw_ci.func_idx = HINIC_HWIF_FUNC_IDX(hwif); + + hw_ci.sq_id = qp->q_id; + + hw_ci.ci_addr = ADDR_IN_4BYTES(sq->hw_ci_dma_addr); + + pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev); + + return hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, +HINIC_MOD_COMM, +HINIC_COMM_CMD_SQ_HI_CI_SET, +&hw_ci, sizeof(hw_ci), NULL, +NULL, HINIC_MGMT_MSG_SYNC); +} diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h index e7277d1..0f5563f 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h @@ -153,6 +153,25 @@ struct hinic_cmd_base_qpn { u16 qpn; }; +struct hinic_cmd_hw_ci { + u8 status; + u8 version; + u8 rsvd0[6]; + + u16 func_idx; + + u8 dma_attr_off; + u8 pending_limit; + u8 coalesc_timer; + + u8 msix_en; + u16 msix_entry_idx; + + u32 sq_id; + u32 rsvd1; + u64 ci_addr; +}; + struct hinic_hwdev { struct hinic_hwif *hwif; struct msix_entry *msix_entries; @@ -214,4 +233,7 @@ int hinic_hwdev_msix_set(struct hinic_hwdev *hwdev, u16 msix_index, u8 lli_timer_cfg, u8 lli_credit_limit, u8 resend_timer); +int hinic_hwdev_hw_ci_addr_set(struct hinic_hwdev *hwdev, struct hinic_sq *sq, + u8 pending_limit, u8 coalesc_timer); + #endif diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c index 6e540d2..97ee8eb 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #incl
[PATCH V5 net-next 16/21] net-next/hinic: Add cmdq commands
Add cmdq commands for setting queue pair contexts in the nic. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- drivers/net/ethernet/huawei/hinic/hinic_common.c | 25 ++ drivers/net/ethernet/huawei/hinic/hinic_common.h | 9 + drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c | 282 +- drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.h | 38 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_io.h | 10 + drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c | 194 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h | 12 + drivers/net/ethernet/huawei/hinic/hinic_hw_wqe.h | 115 + 8 files changed, 683 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_common.c b/drivers/net/ethernet/huawei/hinic/hinic_common.c index 1915ad6..02c74fd 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_common.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_common.c @@ -13,6 +13,7 @@ * */ +#include #include #include @@ -53,3 +54,27 @@ void hinic_be32_to_cpu(void *data, int len) mem++; } } + +/** + * hinic_set_sge - set dma area in scatter gather entry + * @sge: scatter gather entry + * @addr: dma address + * @len: length of relevant data in the dma address + **/ +void hinic_set_sge(struct hinic_sge *sge, dma_addr_t addr, int len) +{ + sge->hi_addr = upper_32_bits(addr); + sge->lo_addr = lower_32_bits(addr); + sge->len = len; +} + +/** + * hinic_sge_to_dma - get dma address from scatter gather entry + * @sge: scatter gather entry + * + * Return dma address of sg entry + **/ +dma_addr_t hinic_sge_to_dma(struct hinic_sge *sge) +{ + return (dma_addr_t)u64)sge->hi_addr) << 32) | sge->lo_addr); +} diff --git a/drivers/net/ethernet/huawei/hinic/hinic_common.h b/drivers/net/ethernet/huawei/hinic/hinic_common.h index 0f2f4ff..2c06b76 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_common.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_common.h @@ -16,6 +16,11 @@ #ifndef HINIC_COMMON_H #define HINIC_COMMON_H +#include + +#define UPPER_8_BITS(data) (((data) >> 8) & 0xFF) +#define LOWER_8_BITS(data) ((data) & 0xFF) + struct hinic_sge { u32 hi_addr; u32 lo_addr; @@ -26,4 +31,8 @@ struct hinic_sge { void hinic_be32_to_cpu(void *data, int len); +void hinic_set_sge(struct hinic_sge *sge, dma_addr_t addr, int len); + +dma_addr_t hinic_sge_to_dma(struct hinic_sge *sge); + #endif diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c index ec24b95..d8c0807 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c @@ -24,19 +24,34 @@ #include #include #include +#include +#include +#include #include +#include +#include "hinic_common.h" #include "hinic_hw_if.h" #include "hinic_hw_eqs.h" #include "hinic_hw_mgmt.h" +#include "hinic_hw_wqe.h" #include "hinic_hw_wq.h" #include "hinic_hw_cmdq.h" #include "hinic_hw_io.h" #include "hinic_hw_dev.h" +#define CMDQ_DB_PI_OFF(pi) (((u16)LOWER_8_BITS(pi)) << 3) + +#define CMDQ_DB_ADDR(db_base, pi) ((db_base) + CMDQ_DB_PI_OFF(pi)) + +#define CMDQ_WQE_HEADER(wqe)((struct hinic_cmdq_header *)(wqe)) + +#define FIRST_DATA_TO_WRITE_LASTsizeof(u64) + #define CMDQ_DB_OFF SZ_2K #define CMDQ_WQEBB_SIZE 64 +#define CMDQ_WQE_SIZE 64 #define CMDQ_DEPTH SZ_4K #define CMDQ_WQ_PAGE_SIZE SZ_4K @@ -44,6 +59,10 @@ #define WQE_LCMD_SIZE 64 #define WQE_SCMD_SIZE 64 +#define COMPLETE_LEN3 + +#define CMDQ_TIMEOUT1000 + #define CMDQ_PFN(addr, page_size) ((addr) >> (ilog2(page_size))) #define cmdq_to_cmdqs(cmdq) container_of((cmdq) - (cmdq)->cmdq_type, \ @@ -58,6 +77,40 @@ enum cmdq_wqe_type { WQE_SCMD_TYPE = 1, }; +enum completion_format { + COMPLETE_DIRECT = 0, + COMPLETE_SGE= 1, +}; + +enum data_format { + DATA_SGE= 0, + DATA_DIRECT = 1, +}; + +enum bufdesc_len { + BUFDESC_LCMD_LEN = 2, /* 16 bytes - 2(8 byte unit) */ + BUFDESC_SCMD_LEN = 3, /* 24 bytes - 3(8 byte unit) */ +}; + +enum ctrl_sect_len { + CTRL_SECT_LEN= 1, /* 4 bytes (ctrl) - 1(8 byte unit) */ + CTRL_DIRECT_SECT_LEN = 2, /* 12 bytes (ctrl + rsvd) - 2(8 byte unit) */ +}; + +enum cmdq_scmd_type { + CMDQ_SET_ARM_CMD = 2, +}; + +enum cmdq_cmd_type { + CMDQ_CMD_SYNC_DIRECT_RESP = 0, + CMDQ_CMD_SYNC_SGE_RESP= 1, +}; + +enum completion_request { + NO_CEQ = 0, + CEQ_SET = 1, +}; + /** * hinic_alloc_cmdq_buf - alloc buffer for sending command * @cmdqs: the cmdqs @@ -92,6 +145,221 @@ void hinic_free_cmdq_buf(struct hinic_cmdqs *cmdqs, pci_pool_free(cmdqs->c
[PATCH V5 net-next 13/21] net-next/hinic: Set qp context
Update the nic about the resources of the queue pairs. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- drivers/net/ethernet/huawei/hinic/Makefile | 5 +- drivers/net/ethernet/huawei/hinic/hinic_common.c | 55 ++ drivers/net/ethernet/huawei/hinic/hinic_common.h | 4 + drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c | 87 + drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.h | 84 drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c | 4 + drivers/net/ethernet/huawei/hinic/hinic_hw_io.c| 151 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_io.h| 5 + drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c| 159 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h| 11 ++ .../net/ethernet/huawei/hinic/hinic_hw_qp_ctxt.h | 214 + drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h| 9 + 12 files changed, 786 insertions(+), 2 deletions(-) create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_common.c create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.h create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_qp_ctxt.h diff --git a/drivers/net/ethernet/huawei/hinic/Makefile b/drivers/net/ethernet/huawei/hinic/Makefile index 84815f7..289ce88b 100644 --- a/drivers/net/ethernet/huawei/hinic/Makefile +++ b/drivers/net/ethernet/huawei/hinic/Makefile @@ -1,5 +1,6 @@ obj-$(CONFIG_HINIC) += hinic.o hinic-y := hinic_main.o hinic_tx.o hinic_rx.o hinic_port.o hinic_hw_dev.o \ - hinic_hw_io.o hinic_hw_qp.o hinic_hw_wq.o hinic_hw_mgmt.o \ - hinic_hw_api_cmd.o hinic_hw_eqs.o hinic_hw_if.o + hinic_hw_io.o hinic_hw_qp.o hinic_hw_cmdq.o hinic_hw_wq.o \ + hinic_hw_mgmt.o hinic_hw_api_cmd.o hinic_hw_eqs.o hinic_hw_if.o \ + hinic_common.o diff --git a/drivers/net/ethernet/huawei/hinic/hinic_common.c b/drivers/net/ethernet/huawei/hinic/hinic_common.c new file mode 100644 index 000..1915ad6 --- /dev/null +++ b/drivers/net/ethernet/huawei/hinic/hinic_common.c @@ -0,0 +1,55 @@ +/* + * Huawei HiNIC PCI Express Linux driver + * Copyright(c) 2017 Huawei Technologies Co., Ltd + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + */ + +#include +#include + +#include "hinic_common.h" + +/** + * hinic_cpu_to_be32 - convert data to big endian 32 bit format + * @data: the data to convert + * @len: length of data to convert + **/ +void hinic_cpu_to_be32(void *data, int len) +{ + u32 *mem = data; + int i; + + len = len / sizeof(u32); + + for (i = 0; i < len; i++) { + *mem = cpu_to_be32(*mem); + mem++; + } +} + +/** + * hinic_be32_to_cpu - convert data from big endian 32 bit format + * @data: the data to convert + * @len: length of data to convert + **/ +void hinic_be32_to_cpu(void *data, int len) +{ + u32 *mem = data; + int i; + + len = len / sizeof(u32); + + for (i = 0; i < len; i++) { + *mem = be32_to_cpu(*mem); + mem++; + } +} diff --git a/drivers/net/ethernet/huawei/hinic/hinic_common.h b/drivers/net/ethernet/huawei/hinic/hinic_common.h index 6a83c15..0f2f4ff 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_common.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_common.h @@ -22,4 +22,8 @@ struct hinic_sge { u32 len; }; +void hinic_cpu_to_be32(void *data, int len); + +void hinic_be32_to_cpu(void *data, int len); + #endif diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c new file mode 100644 index 000..2fd3924 --- /dev/null +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c @@ -0,0 +1,87 @@ +/* + * Huawei HiNIC PCI Express Linux driver + * Copyright(c) 2017 Huawei Technologies Co., Ltd + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + */ + +#include +#include + +#include "hinic_hw_if.h" +#include "hinic_hw_cmdq.h" + +/** + * hinic_alloc_cmdq_buf - alloc buffer for sending command + * @cmdqs: the cmdqs + * @cmdq_buf: the buffer returned in this struct
[PATCH V5 net-next 12/21] net-next/hinic: Add qp resources
Create the resources for queue pair operations: doorbell area, consumer index address and producer index address. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- drivers/net/ethernet/huawei/hinic/Makefile | 4 +- drivers/net/ethernet/huawei/hinic/hinic_hw_if.h | 1 + drivers/net/ethernet/huawei/hinic/hinic_hw_io.c | 164 ++- drivers/net/ethernet/huawei/hinic/hinic_hw_io.h | 27 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c | 266 drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h | 50 - 6 files changed, 507 insertions(+), 5 deletions(-) create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c diff --git a/drivers/net/ethernet/huawei/hinic/Makefile b/drivers/net/ethernet/huawei/hinic/Makefile index 0575a34..84815f7 100644 --- a/drivers/net/ethernet/huawei/hinic/Makefile +++ b/drivers/net/ethernet/huawei/hinic/Makefile @@ -1,5 +1,5 @@ obj-$(CONFIG_HINIC) += hinic.o hinic-y := hinic_main.o hinic_tx.o hinic_rx.o hinic_port.o hinic_hw_dev.o \ - hinic_hw_io.o hinic_hw_wq.o hinic_hw_mgmt.o hinic_hw_api_cmd.o \ - hinic_hw_eqs.o hinic_hw_if.o + hinic_hw_io.o hinic_hw_qp.o hinic_hw_wq.o hinic_hw_mgmt.o \ + hinic_hw_api_cmd.o hinic_hw_eqs.o hinic_hw_if.o diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h index 2280698..8f59195 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h @@ -137,6 +137,7 @@ #define HINIC_IS_PPF(hwif) (HINIC_FUNC_TYPE(hwif) == HINIC_PPF) #define HINIC_PCI_CFG_REGS_BAR 0 +#define HINIC_PCI_DB_BAR4 #define HINIC_PCIE_ST_DISABLE 0 #define HINIC_PCIE_AT_DISABLE 0 diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_io.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_io.c index 1bf944e..ad12cc7 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_io.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_io.c @@ -13,11 +13,16 @@ * */ +#include #include #include #include #include #include +#include +#include +#include +#include #include "hinic_hw_if.h" #include "hinic_hw_wqe.h" @@ -25,6 +30,76 @@ #include "hinic_hw_qp.h" #include "hinic_hw_io.h" +#define CI_Q_ADDR_SIZE sizeof(u32) + +#define CI_ADDR(base_addr, q_id)((base_addr) + \ +(q_id) * CI_Q_ADDR_SIZE) + +#define CI_TABLE_SIZE(num_qps) ((num_qps) * CI_Q_ADDR_SIZE) + +#define DB_IDX(db, db_base) \ + (((unsigned long)(db) - (unsigned long)(db_base)) / HINIC_DB_PAGE_SIZE) + +static void init_db_area_idx(struct hinic_free_db_area *free_db_area) +{ + int i; + + for (i = 0; i < HINIC_DB_MAX_AREAS; i++) + free_db_area->db_idx[i] = i; + + free_db_area->alloc_pos = 0; + free_db_area->return_pos = HINIC_DB_MAX_AREAS; + + free_db_area->num_free = HINIC_DB_MAX_AREAS; + + sema_init(&free_db_area->idx_lock, 1); +} + +static void __iomem *get_db_area(struct hinic_func_to_io *func_to_io) +{ + struct hinic_free_db_area *free_db_area = &func_to_io->free_db_area; + int pos, idx; + + down(&free_db_area->idx_lock); + + free_db_area->num_free--; + + if (free_db_area->num_free < 0) { + free_db_area->num_free++; + up(&free_db_area->idx_lock); + return ERR_PTR(-ENOMEM); + } + + pos = free_db_area->alloc_pos++; + pos &= HINIC_DB_MAX_AREAS - 1; + + idx = free_db_area->db_idx[pos]; + + free_db_area->db_idx[pos] = -1; + + up(&free_db_area->idx_lock); + + return func_to_io->db_base + idx * HINIC_DB_PAGE_SIZE; +} + +static void return_db_area(struct hinic_func_to_io *func_to_io, + void __iomem *db_base) +{ + struct hinic_free_db_area *free_db_area = &func_to_io->free_db_area; + int pos, idx = DB_IDX(db_base, func_to_io->db_base); + + down(&free_db_area->idx_lock); + + pos = free_db_area->return_pos++; + pos &= HINIC_DB_MAX_AREAS - 1; + + free_db_area->db_idx[pos] = idx; + + free_db_area->num_free++; + + up(&free_db_area->idx_lock); +} + /** * init_qp - Initialize a Queue Pair * @func_to_io: func to io channel that holds the IO components @@ -42,6 +117,7 @@ static int init_qp(struct hinic_func_to_io *func_to_io, { struct hinic_hwif *hwif = func_to_io->hwif; struct pci_dev *pdev = hwif->pdev; + void __iomem *db_base; int err; qp->q_id = q_id; @@ -62,8 +138,42 @@ static int init_qp(struct hinic_func_to_io *func_to_io, goto err_rq_alloc; } + db_base = get_db_area(func_to_io); + if (IS_ERR(db_base)) { + dev_err(&pdev->dev, "Failed to get DB area for SQ\n"); + err = PTR_ERR(db_base); + goto err_get_
[PATCH V5 net-next 14/21] net-next/hinic: Initialize cmdq
Create the work queues for cmdq and update the nic about the work queue contexts. cmdq commands are used for updating the nic about the qp contexts. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c | 282 +- drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.h | 53 drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.h | 2 + drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h | 5 + drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c | 156 drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h | 8 + 6 files changed, 500 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c index 2fd3924..0dccbe6 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c @@ -13,11 +13,49 @@ * */ +#include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "hinic_hw_if.h" +#include "hinic_hw_mgmt.h" +#include "hinic_hw_wq.h" #include "hinic_hw_cmdq.h" +#include "hinic_hw_io.h" +#include "hinic_hw_dev.h" + +#define CMDQ_DB_OFF SZ_2K + +#define CMDQ_WQEBB_SIZE 64 +#define CMDQ_DEPTH SZ_4K + +#define CMDQ_WQ_PAGE_SIZE SZ_4K + +#define WQE_LCMD_SIZE 64 +#define WQE_SCMD_SIZE 64 + +#define CMDQ_PFN(addr, page_size) ((addr) >> (ilog2(page_size))) + +#define cmdq_to_cmdqs(cmdq) container_of((cmdq) - (cmdq)->cmdq_type, \ +struct hinic_cmdqs, cmdq[0]) + +#define cmdqs_to_func_to_io(cmdqs) container_of(cmdqs, \ +struct hinic_func_to_io, \ +cmdqs) + +enum cmdq_wqe_type { + WQE_LCMD_TYPE = 0, + WQE_SCMD_TYPE = 1, +}; /** * hinic_alloc_cmdq_buf - alloc buffer for sending command @@ -29,8 +67,17 @@ int hinic_alloc_cmdq_buf(struct hinic_cmdqs *cmdqs, struct hinic_cmdq_buf *cmdq_buf) { - /* should be implemented */ - return -ENOMEM; + struct hinic_hwif *hwif = cmdqs->hwif; + struct pci_dev *pdev = hwif->pdev; + + cmdq_buf->buf = pci_pool_alloc(cmdqs->cmdq_buf_pool, GFP_KERNEL, + &cmdq_buf->dma_addr); + if (!cmdq_buf->buf) { + dev_err(&pdev->dev, "Failed to allocate cmd from the pool\n"); + return -ENOMEM; + } + + return 0; } /** @@ -41,7 +88,7 @@ int hinic_alloc_cmdq_buf(struct hinic_cmdqs *cmdqs, void hinic_free_cmdq_buf(struct hinic_cmdqs *cmdqs, struct hinic_cmdq_buf *cmdq_buf) { - /* should be implemented */ + pci_pool_free(cmdqs->cmdq_buf_pool, cmdq_buf->buf, cmdq_buf->dma_addr); } /** @@ -63,6 +110,169 @@ int hinic_cmdq_direct_resp(struct hinic_cmdqs *cmdqs, } /** + * cmdq_init_queue_ctxt - init the queue ctxt of a cmdq + * @cmdq_ctxt: cmdq ctxt to initialize + * @cmdq: the cmdq + * @cmdq_pages: the memory of the queue + **/ +static void cmdq_init_queue_ctxt(struct hinic_cmdq_ctxt *cmdq_ctxt, +struct hinic_cmdq *cmdq, +struct hinic_cmdq_pages *cmdq_pages) +{ + struct hinic_cmdq_ctxt_info *ctxt_info = &cmdq_ctxt->ctxt_info; + u64 wq_first_page_paddr, cmdq_first_block_paddr, pfn; + struct hinic_cmdqs *cmdqs = cmdq_to_cmdqs(cmdq); + struct hinic_wq *wq = cmdq->wq; + + /* The data in the HW is in Big Endian Format */ + wq_first_page_paddr = be64_to_cpu(*wq->block_vaddr); + + pfn = CMDQ_PFN(wq_first_page_paddr, wq->wq_page_size); + + ctxt_info->curr_wqe_page_pfn = + HINIC_CMDQ_CTXT_PAGE_INFO_SET(pfn, CURR_WQE_PAGE_PFN) | + HINIC_CMDQ_CTXT_PAGE_INFO_SET(HINIC_CEQ_ID_CMDQ, EQ_ID) | + HINIC_CMDQ_CTXT_PAGE_INFO_SET(1, CEQ_ARM) | + HINIC_CMDQ_CTXT_PAGE_INFO_SET(1, CEQ_EN)| + HINIC_CMDQ_CTXT_PAGE_INFO_SET(cmdq->wrapped, WRAPPED); + + /* block PFN - Read Modify Write */ + cmdq_first_block_paddr = cmdq_pages->page_paddr; + + pfn = CMDQ_PFN(cmdq_first_block_paddr, wq->wq_page_size); + + ctxt_info->wq_block_pfn = + HINIC_CMDQ_CTXT_BLOCK_INFO_SET(pfn, WQ_BLOCK_PFN) | + HINIC_CMDQ_CTXT_BLOCK_INFO_SET(atomic_read(&wq->cons_idx), CI); + + cmdq_ctxt->func_idx = HINIC_HWIF_FUNC_IDX(cmdqs->hwif); + cmdq_ctxt->cmdq_type = cmdq->cmdq_type; +} + +/** + * init_cmdq - initialize cmdq + * @cmdq: the cmdq + * @wq: the wq attaced to the cmdq + * @q_type: the cmdq type of the cmdq + * @db_area: doorbell area for the cmdq + * + * Return 0 - Success, negative - Failure + **/ +static int init_
[PATCH V5 net-next 11/21] net-next/hinic: Add wq
Create work queues for being used by the queue pairs. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- drivers/net/ethernet/huawei/hinic/Makefile | 4 +- drivers/net/ethernet/huawei/hinic/hinic_common.h | 25 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_io.c | 69 ++- drivers/net/ethernet/huawei/hinic/hinic_hw_io.h | 6 + drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h | 14 + drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c | 517 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h | 86 drivers/net/ethernet/huawei/hinic/hinic_hw_wqe.h | 253 +++ 8 files changed, 969 insertions(+), 5 deletions(-) create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_common.h create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_wqe.h diff --git a/drivers/net/ethernet/huawei/hinic/Makefile b/drivers/net/ethernet/huawei/hinic/Makefile index f60c449..0575a34 100644 --- a/drivers/net/ethernet/huawei/hinic/Makefile +++ b/drivers/net/ethernet/huawei/hinic/Makefile @@ -1,5 +1,5 @@ obj-$(CONFIG_HINIC) += hinic.o hinic-y := hinic_main.o hinic_tx.o hinic_rx.o hinic_port.o hinic_hw_dev.o \ - hinic_hw_io.o hinic_hw_mgmt.o hinic_hw_api_cmd.o hinic_hw_eqs.o \ - hinic_hw_if.o + hinic_hw_io.o hinic_hw_wq.o hinic_hw_mgmt.o hinic_hw_api_cmd.o \ + hinic_hw_eqs.o hinic_hw_if.o diff --git a/drivers/net/ethernet/huawei/hinic/hinic_common.h b/drivers/net/ethernet/huawei/hinic/hinic_common.h new file mode 100644 index 000..6a83c15 --- /dev/null +++ b/drivers/net/ethernet/huawei/hinic/hinic_common.h @@ -0,0 +1,25 @@ +/* + * Huawei HiNIC PCI Express Linux driver + * Copyright(c) 2017 Huawei Technologies Co., Ltd + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + */ + +#ifndef HINIC_COMMON_H +#define HINIC_COMMON_H + +struct hinic_sge { + u32 hi_addr; + u32 lo_addr; + u32 len; +}; + +#endif diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_io.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_io.c index ebe28ee..1bf944e 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_io.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_io.c @@ -20,6 +20,8 @@ #include #include "hinic_hw_if.h" +#include "hinic_hw_wqe.h" +#include "hinic_hw_wq.h" #include "hinic_hw_qp.h" #include "hinic_hw_io.h" @@ -38,8 +40,33 @@ static int init_qp(struct hinic_func_to_io *func_to_io, struct msix_entry *sq_msix_entry, struct msix_entry *rq_msix_entry) { - /* should be implemented */ + struct hinic_hwif *hwif = func_to_io->hwif; + struct pci_dev *pdev = hwif->pdev; + int err; + + qp->q_id = q_id; + + err = hinic_wq_allocate(&func_to_io->wqs, &func_to_io->sq_wq[q_id], + HINIC_SQ_WQEBB_SIZE, HINIC_SQ_PAGE_SIZE, + HINIC_SQ_DEPTH, HINIC_SQ_WQE_MAX_SIZE); + if (err) { + dev_err(&pdev->dev, "Failed to allocate WQ for SQ\n"); + return err; + } + + err = hinic_wq_allocate(&func_to_io->wqs, &func_to_io->rq_wq[q_id], + HINIC_RQ_WQEBB_SIZE, HINIC_RQ_PAGE_SIZE, + HINIC_RQ_DEPTH, HINIC_RQ_WQE_SIZE); + if (err) { + dev_err(&pdev->dev, "Failed to allocate WQ for RQ\n"); + goto err_rq_alloc; + } + return 0; + +err_rq_alloc: + hinic_wq_free(&func_to_io->wqs, &func_to_io->sq_wq[q_id]); + return err; } /** @@ -50,7 +77,10 @@ static int init_qp(struct hinic_func_to_io *func_to_io, static void destroy_qp(struct hinic_func_to_io *func_to_io, struct hinic_qp *qp) { - /* should be implemented */ + int q_id = qp->q_id; + + hinic_wq_free(&func_to_io->wqs, &func_to_io->rq_wq[q_id]); + hinic_wq_free(&func_to_io->wqs, &func_to_io->sq_wq[q_id]); } /** @@ -70,7 +100,7 @@ int hinic_io_create_qps(struct hinic_func_to_io *func_to_io, { struct hinic_hwif *hwif = func_to_io->hwif; struct pci_dev *pdev = hwif->pdev; - size_t qps_size; + size_t qps_size, wq_size; int i, j, err; qps_size = num_qps * sizeof(*func_to_io->qps); @@ -78,6 +108,20 @@ int hinic_io_create_qps(struct hinic_func_to_io *func_to_io, if (!func_to_io->qps) return -ENOMEM; + wq_size = n
[PATCH V5 net-next 10/21] net-next/hinic: Add logical Txq and Rxq
Create the logical queues of the nic. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- drivers/net/ethernet/huawei/hinic/Makefile | 5 +- drivers/net/ethernet/huawei/hinic/hinic_dev.h| 5 + drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c | 131 + drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h | 20 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_io.c | 144 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_io.h | 46 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h | 32 + drivers/net/ethernet/huawei/hinic/hinic_main.c | 172 ++- drivers/net/ethernet/huawei/hinic/hinic_rx.c | 72 ++ drivers/net/ethernet/huawei/hinic/hinic_rx.h | 46 ++ drivers/net/ethernet/huawei/hinic/hinic_tx.c | 75 ++ drivers/net/ethernet/huawei/hinic/hinic_tx.h | 49 +++ 12 files changed, 793 insertions(+), 4 deletions(-) create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_io.c create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_io.h create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_rx.c create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_rx.h create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_tx.c create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_tx.h diff --git a/drivers/net/ethernet/huawei/hinic/Makefile b/drivers/net/ethernet/huawei/hinic/Makefile index dbb1b9d..f60c449 100644 --- a/drivers/net/ethernet/huawei/hinic/Makefile +++ b/drivers/net/ethernet/huawei/hinic/Makefile @@ -1,4 +1,5 @@ obj-$(CONFIG_HINIC) += hinic.o -hinic-y := hinic_main.o hinic_port.o hinic_hw_dev.o hinic_hw_mgmt.o \ - hinic_hw_api_cmd.o hinic_hw_eqs.o hinic_hw_if.o +hinic-y := hinic_main.o hinic_tx.o hinic_rx.o hinic_port.o hinic_hw_dev.o \ + hinic_hw_io.o hinic_hw_mgmt.o hinic_hw_api_cmd.o hinic_hw_eqs.o \ + hinic_hw_if.o diff --git a/drivers/net/ethernet/huawei/hinic/hinic_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_dev.h index 5c5b4e9..5b8231d 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_dev.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_dev.h @@ -23,6 +23,8 @@ #include #include "hinic_hw_dev.h" +#include "hinic_tx.h" +#include "hinic_rx.h" #define HINIC_DRV_NAME "hinic" @@ -49,6 +51,9 @@ struct hinic_dev { struct hinic_rx_mode_work rx_mode_work; struct workqueue_struct *workq; + + struct hinic_txq*txqs; + struct hinic_rxq*rxqs; }; #endif diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c index 75fd6d2..d113908 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c @@ -25,6 +25,8 @@ #include "hinic_hw_if.h" #include "hinic_hw_eqs.h" #include "hinic_hw_mgmt.h" +#include "hinic_hw_qp.h" +#include "hinic_hw_io.h" #include "hinic_hw_dev.h" #define MAX_IRQS(max_qps, num_aeqs, num_ceqs) \ @@ -230,6 +232,99 @@ int hinic_port_msg_cmd(struct hinic_hwdev *hwdev, enum hinic_port_cmd cmd, } /** + * get_base_qpn - get the first qp number + * @hwdev: the NIC HW device + * @base_qpn: returned qp number + * + * Return 0 - Success, negative - Failure + **/ +static int get_base_qpn(struct hinic_hwdev *hwdev, u16 *base_qpn) +{ + struct hinic_cmd_base_qpn cmd_base_qpn; + struct hinic_hwif *hwif = hwdev->hwif; + struct pci_dev *pdev = hwif->pdev; + u16 out_size; + int err; + + cmd_base_qpn.func_idx = HINIC_HWIF_FUNC_IDX(hwif); + + err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_GLOBAL_QPN, +&cmd_base_qpn, sizeof(cmd_base_qpn), +&cmd_base_qpn, &out_size); + if (err || (out_size != sizeof(cmd_base_qpn)) || cmd_base_qpn.status) { + dev_err(&pdev->dev, "Failed to get base qpn, status = %d\n", + cmd_base_qpn.status); + return -EFAULT; + } + + *base_qpn = cmd_base_qpn.qpn; + return 0; +} + +/** + * hinic_hwdev_ifup - Preparing the HW for passing IO + * @hwdev: the NIC HW device + * + * Return 0 - Success, negative - Failure + **/ +int hinic_hwdev_ifup(struct hinic_hwdev *hwdev) +{ + struct hinic_func_to_io *func_to_io = &hwdev->func_to_io; + struct hinic_cap *nic_cap = &hwdev->nic_cap; + struct hinic_hwif *hwif = hwdev->hwif; + int err, num_aeqs, num_ceqs, num_qps; + struct msix_entry *sq_msix_entries; + struct msix_entry *rq_msix_entries; + struct pci_dev *pdev = hwif->pdev; + u16 base_qpn; + + err = get_base_qpn(hwdev, &base_qpn); + if (err) { + dev_err(&pdev->dev, "Failed to get global base qp number\n"); + return err; + } + + num_aeqs = HINIC_HWIF_NUM_AEQS(hw
[PATCH V5 net-next 08/21] net-next/hinic: Add port management commands
Add the port management commands that are sent as management messages. The port management commands are used for netdev operations. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- drivers/net/ethernet/huawei/hinic/Makefile | 4 +- drivers/net/ethernet/huawei/hinic/hinic_dev.h| 4 + drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c | 30 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h | 29 +++ drivers/net/ethernet/huawei/hinic/hinic_main.c | 195 +++- drivers/net/ethernet/huawei/hinic/hinic_port.c | 224 +++ drivers/net/ethernet/huawei/hinic/hinic_port.h | 68 +++ 7 files changed, 551 insertions(+), 3 deletions(-) create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_port.c create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_port.h diff --git a/drivers/net/ethernet/huawei/hinic/Makefile b/drivers/net/ethernet/huawei/hinic/Makefile index beba90a..dbb1b9d 100644 --- a/drivers/net/ethernet/huawei/hinic/Makefile +++ b/drivers/net/ethernet/huawei/hinic/Makefile @@ -1,4 +1,4 @@ obj-$(CONFIG_HINIC) += hinic.o -hinic-y := hinic_main.o hinic_hw_dev.o hinic_hw_mgmt.o hinic_hw_api_cmd.o \ - hinic_hw_eqs.o hinic_hw_if.o +hinic-y := hinic_main.o hinic_port.o hinic_hw_dev.o hinic_hw_mgmt.o \ + hinic_hw_api_cmd.o hinic_hw_eqs.o hinic_hw_if.o diff --git a/drivers/net/ethernet/huawei/hinic/hinic_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_dev.h index 6c2c896..e54a45c 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_dev.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_dev.h @@ -18,6 +18,7 @@ #include #include +#include #include "hinic_hw_dev.h" @@ -28,6 +29,9 @@ struct hinic_dev { struct hinic_hwdev *hwdev; u32 msg_enable; + + struct semaphoremgmt_lock; + unsigned long *vlan_bitmap; }; #endif diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c index d430e60..6bb6c33 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c @@ -200,6 +200,36 @@ static void disable_msix(struct hinic_hwdev *hwdev) } /** + * hinic_port_msg_cmd - send port msg to mgmt + * @hwdev: the NIC HW device + * @cmd: the port command + * @buf_in: input buffer + * @in_size: input size + * @buf_out: output buffer + * @out_size: returned output size + * + * Return 0 - Success, negative - Failure + **/ +int hinic_port_msg_cmd(struct hinic_hwdev *hwdev, enum hinic_port_cmd cmd, + void *buf_in, u16 in_size, void *buf_out, u16 *out_size) +{ + struct hinic_hwif *hwif = hwdev->hwif; + struct pci_dev *pdev = hwif->pdev; + struct hinic_pfhwdev *pfhwdev; + + if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) { + dev_err(&pdev->dev, "unsupported PCI Function type\n"); + return -EINVAL; + } + + pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev); + + return hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_L2NIC, cmd, +buf_in, in_size, buf_out, out_size, +HINIC_MGMT_MSG_SYNC); +} + +/** * init_pfhwdev - Initialize the extended components of PF * @pfhwdev: the HW device for PF * diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h index feb60138..ee9e76a 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h @@ -30,6 +30,31 @@ struct hinic_cap { u16 num_qps; }; +enum hinic_port_cmd { + HINIC_PORT_CMD_CHANGE_MTU = 2, + + HINIC_PORT_CMD_ADD_VLAN = 3, + HINIC_PORT_CMD_DEL_VLAN = 4, + + HINIC_PORT_CMD_SET_MAC = 9, + HINIC_PORT_CMD_GET_MAC = 10, + HINIC_PORT_CMD_DEL_MAC = 11, + + HINIC_PORT_CMD_SET_RX_MODE = 12, + + HINIC_PORT_CMD_GET_LINK_STATE = 24, + + HINIC_PORT_CMD_SET_PORT_STATE = 41, + + HINIC_PORT_CMD_FWCTXT_INIT = 69, + + HINIC_PORT_CMD_SET_FUNC_STATE = 93, + + HINIC_PORT_CMD_GET_GLOBAL_QPN = 102, + + HINIC_PORT_CMD_GET_CAP = 170, +}; + struct hinic_hwdev { struct hinic_hwif *hwif; struct msix_entry *msix_entries; @@ -45,6 +70,10 @@ struct hinic_pfhwdev { struct hinic_pf_to_mgmt pf_to_mgmt; }; +int hinic_port_msg_cmd(struct hinic_hwdev *hwdev, enum hinic_port_cmd cmd, + void *buf_in, u16 in_size, void *buf_out, + u16 *out_size); + struct hinic_hwdev *hinic_init_hwdev(struct pci_dev *pdev); void hinic_free_hwdev(struct hinic_hwdev *hwdev); diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.
[PATCH V5 net-next 07/21] net-next/hinic: Add aeqs
Handle aeq elements that are accumulated on the aeq by calling the registered handler for the specific event. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h | 49 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c | 464 ++- drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.h | 81 drivers/net/ethernet/huawei/hinic/hinic_hw_if.c | 91 + drivers/net/ethernet/huawei/hinic/hinic_hw_if.h | 46 +++ 5 files changed, 729 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h index ebbf054..52eb89c 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h @@ -65,4 +65,53 @@ #define HINIC_CSR_API_CMD_STATUS_ADDR(idx) \ (HINIC_CSR_API_CMD_BASE + 0x30 + (idx) * HINIC_CSR_API_CMD_STRIDE) +/* MSI-X registers */ +#define HINIC_CSR_MSIX_CTRL_BASE0x2000 +#define HINIC_CSR_MSIX_CNT_BASE 0x2004 + +#define HINIC_CSR_MSIX_STRIDE 0x8 + +#define HINIC_CSR_MSIX_CTRL_ADDR(idx) \ + (HINIC_CSR_MSIX_CTRL_BASE + (idx) * HINIC_CSR_MSIX_STRIDE) + +#define HINIC_CSR_MSIX_CNT_ADDR(idx)\ + (HINIC_CSR_MSIX_CNT_BASE + (idx) * HINIC_CSR_MSIX_STRIDE) + +/* EQ registers */ +#define HINIC_AEQ_MTT_OFF_BASE_ADDR 0x200 + +#define HINIC_EQ_MTT_OFF_STRIDE 0x40 + +#define HINIC_CSR_AEQ_MTT_OFF(id) \ + (HINIC_AEQ_MTT_OFF_BASE_ADDR + (id) * HINIC_EQ_MTT_OFF_STRIDE) + +#define HINIC_CSR_EQ_PAGE_OFF_STRIDE8 + +#define HINIC_CSR_AEQ_HI_PHYS_ADDR_REG(q_id, pg_num)\ + (HINIC_CSR_AEQ_MTT_OFF(q_id) + \ +(pg_num) * HINIC_CSR_EQ_PAGE_OFF_STRIDE) + +#define HINIC_CSR_AEQ_LO_PHYS_ADDR_REG(q_id, pg_num)\ + (HINIC_CSR_AEQ_MTT_OFF(q_id) + \ +(pg_num) * HINIC_CSR_EQ_PAGE_OFF_STRIDE + 4) + +#define HINIC_AEQ_CTRL_0_ADDR_BASE 0xE00 +#define HINIC_AEQ_CTRL_1_ADDR_BASE 0xE04 +#define HINIC_AEQ_CONS_IDX_ADDR_BASE0xE08 +#define HINIC_AEQ_PROD_IDX_ADDR_BASE0xE0C + +#define HINIC_EQ_OFF_STRIDE 0x80 + +#define HINIC_CSR_AEQ_CTRL_0_ADDR(idx) \ + (HINIC_AEQ_CTRL_0_ADDR_BASE + (idx) * HINIC_EQ_OFF_STRIDE) + +#define HINIC_CSR_AEQ_CTRL_1_ADDR(idx) \ + (HINIC_AEQ_CTRL_1_ADDR_BASE + (idx) * HINIC_EQ_OFF_STRIDE) + +#define HINIC_CSR_AEQ_CONS_IDX_ADDR(idx)\ + (HINIC_AEQ_CONS_IDX_ADDR_BASE + (idx) * HINIC_EQ_OFF_STRIDE) + +#define HINIC_CSR_AEQ_PROD_IDX_ADDR(idx)\ + (HINIC_AEQ_PROD_IDX_ADDR_BASE + (idx) * HINIC_EQ_OFF_STRIDE) + #endif diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c index a099d20..a53d5b3 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c @@ -13,17 +13,74 @@ * */ +#include #include #include #include #include #include +#include +#include +#include +#include +#include +#include +#include "hinic_hw_csr.h" #include "hinic_hw_if.h" #include "hinic_hw_eqs.h" #define HINIC_EQS_WQ_NAME "hinic_eqs" +#define GET_EQ_NUM_PAGES(eq, pg_size) \ + (ALIGN((eq)->q_len * (eq)->elem_size, pg_size) / (pg_size)) + +#define GET_EQ_NUM_ELEMS_IN_PG(eq, pg_size) ((pg_size) / (eq)->elem_size) + +#define EQ_CONS_IDX_REG_ADDR(eq)HINIC_CSR_AEQ_CONS_IDX_ADDR((eq)->q_id) +#define EQ_PROD_IDX_REG_ADDR(eq)HINIC_CSR_AEQ_PROD_IDX_ADDR((eq)->q_id) + +#define EQ_HI_PHYS_ADDR_REG(eq, pg_num) \ + HINIC_CSR_AEQ_HI_PHYS_ADDR_REG((eq)->q_id, pg_num) + +#define EQ_LO_PHYS_ADDR_REG(eq, pg_num) \ + HINIC_CSR_AEQ_LO_PHYS_ADDR_REG((eq)->q_id, pg_num) + +#define GET_EQ_ELEMENT(eq, idx) \ + ((eq)->virt_addr[(idx) / (eq)->num_elem_in_pg] + \ +(((idx) & ((eq)->num_elem_in_pg - 1)) * (eq)->elem_size)) + +#define GET_AEQ_ELEM(eq, idx) ((struct hinic_aeq_elem *) \ + GET_EQ_ELEMENT(eq, idx)) + +#define GET_CURR_AEQ_ELEM(eq) GET_AEQ_ELEM(eq, (eq)->cons_idx) + +#define PAGE_IN_4K(page_size) ((page_size) >> 12) +#define EQ_SET_HW_PAGE_SIZE_VAL(eq) (ilog2(PAGE_IN_4K((eq)->page_size))) + +#define ELEMENT_SIZE_IN_32B(eq) (((eq)->elem_size) >> 5) +#define EQ_SET_HW_ELEM_SIZE_VAL(eq) (ilog2(ELEMENT_SIZE_IN_32B(eq))) + +#define EQ_MAX_PAGES8 + +#define aeq_to_aeqs(eq) \ + container_of((eq) - (eq)->q_id, struct hinic_aeqs, aeq[0]) + +#define work_to_aeq_work(work) \ + container_
[PATCH V5 net-next 04/21] net-next/hinic: Initialize api cmd hw
Update the hardware about api cmd resources and initialize it. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- .../net/ethernet/huawei/hinic/hinic_hw_api_cmd.c | 173 - .../net/ethernet/huawei/hinic/hinic_hw_api_cmd.h | 38 + drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h | 26 3 files changed, 236 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c index 4291f8e..234ede9 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c @@ -13,6 +13,7 @@ * */ +#include #include #include #include @@ -21,8 +22,12 @@ #include #include #include +#include +#include +#include #include +#include "hinic_hw_csr.h" #include "hinic_hw_if.h" #include "hinic_hw_api_cmd.h" @@ -35,8 +40,157 @@ (((cell_size) >= API_CMD_CELL_SIZE_MIN) ? \ (1 << (fls(cell_size - 1))) : API_CMD_CELL_SIZE_MIN) +#define API_CMD_CELL_SIZE_VAL(size) \ + ilog2((size) >> API_CMD_CELL_SIZE_SHIFT) + #define API_CMD_BUF_SIZE2048 +#define API_CMD_TIMEOUT 1000 + +enum api_cmd_xor_chk_level { + XOR_CHK_DIS = 0, + + XOR_CHK_ALL = 3, +}; + +/** + * api_cmd_hw_restart - restart the chain in the HW + * @chain: the API CMD specific chain to restart + * + * Return 0 - Success, negative - Failure + **/ +static int api_cmd_hw_restart(struct hinic_api_cmd_chain *chain) +{ + struct hinic_hwif *hwif = chain->hwif; + int err = -ETIMEDOUT; + unsigned long end; + u32 reg_addr, val; + + /* Read Modify Write */ + reg_addr = HINIC_CSR_API_CMD_CHAIN_REQ_ADDR(chain->chain_type); + val = hinic_hwif_read_reg(hwif, reg_addr); + + val = HINIC_API_CMD_CHAIN_REQ_CLEAR(val, RESTART); + val |= HINIC_API_CMD_CHAIN_REQ_SET(1, RESTART); + + hinic_hwif_write_reg(hwif, reg_addr, val); + + end = jiffies + msecs_to_jiffies(API_CMD_TIMEOUT); + do { + val = hinic_hwif_read_reg(hwif, reg_addr); + + if (!HINIC_API_CMD_CHAIN_REQ_GET(val, RESTART)) { + err = 0; + break; + } + + msleep(20); + } while (time_before(jiffies, end)); + + return err; +} + +/** + * api_cmd_ctrl_init - set the control register of a chain + * @chain: the API CMD specific chain to set control register for + **/ +static void api_cmd_ctrl_init(struct hinic_api_cmd_chain *chain) +{ + struct hinic_hwif *hwif = chain->hwif; + u32 reg_addr, ctrl; + u16 cell_size; + + /* Read Modify Write */ + reg_addr = HINIC_CSR_API_CMD_CHAIN_CTRL_ADDR(chain->chain_type); + + cell_size = API_CMD_CELL_SIZE_VAL(chain->cell_size); + + ctrl = hinic_hwif_read_reg(hwif, reg_addr); + + ctrl = HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, RESTART_WB_STAT) & + HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, XOR_ERR) & + HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, AEQE_EN) & + HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, XOR_CHK_EN) & + HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, CELL_SIZE); + + ctrl |= HINIC_API_CMD_CHAIN_CTRL_SET(1, XOR_ERR) | + HINIC_API_CMD_CHAIN_CTRL_SET(XOR_CHK_ALL, XOR_CHK_EN) | + HINIC_API_CMD_CHAIN_CTRL_SET(cell_size, CELL_SIZE); + + hinic_hwif_write_reg(hwif, reg_addr, ctrl); +} + +/** + * api_cmd_set_status_addr - set the status address of a chain in the HW + * @chain: the API CMD specific chain to set in HW status address for + **/ +static void api_cmd_set_status_addr(struct hinic_api_cmd_chain *chain) +{ + struct hinic_hwif *hwif = chain->hwif; + u32 addr, val; + + addr = HINIC_CSR_API_CMD_STATUS_HI_ADDR(chain->chain_type); + val = upper_32_bits(chain->wb_status_paddr); + hinic_hwif_write_reg(hwif, addr, val); + + addr = HINIC_CSR_API_CMD_STATUS_LO_ADDR(chain->chain_type); + val = lower_32_bits(chain->wb_status_paddr); + hinic_hwif_write_reg(hwif, addr, val); +} + +/** + * api_cmd_set_num_cells - set the number cells of a chain in the HW + * @chain: the API CMD specific chain to set in HW the number of cells for + **/ +static void api_cmd_set_num_cells(struct hinic_api_cmd_chain *chain) +{ + struct hinic_hwif *hwif = chain->hwif; + u32 addr, val; + + addr = HINIC_CSR_API_CMD_CHAIN_NUM_CELLS_ADDR(chain->chain_type); + val = chain->num_cells; + hinic_hwif_write_reg(hwif, addr, val); +} + +/** + * api_cmd_head_init - set the head of a chain in the HW + * @chain: the API CMD specific chain to set in HW the head for + **/ +static void api_cmd_head_init(struct hinic_api_cmd_chain *chain) +{ + struct hinic_hwif *hwif = chain->hwif; + u32 addr, val; + + addr = HINIC_C
[PATCH V5 net-next 06/21] net-next/hinic: Add api cmd commands
Add the api cmd commands for sending management messages to the nic. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- .../net/ethernet/huawei/hinic/hinic_hw_api_cmd.c | 329 - .../net/ethernet/huawei/hinic/hinic_hw_api_cmd.h | 65 drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h | 6 + 3 files changed, 398 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c index b44ddf2..d0145c6 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c @@ -25,7 +25,9 @@ #include #include #include +#include #include +#include #include "hinic_hw_csr.h" #include "hinic_hw_if.h" @@ -45,14 +47,313 @@ #define API_CMD_BUF_SIZE2048 +/* Sizes of the members in hinic_api_cmd_cell */ +#define API_CMD_CELL_DESC_SIZE 8 +#define API_CMD_CELL_DATA_ADDR_SIZE 8 + +#define API_CMD_CELL_ALIGNMENT 8 + #define API_CMD_TIMEOUT 1000 +#define MASKED_IDX(chain, idx) ((idx) & ((chain)->num_cells - 1)) + +#define SIZE_8BYTES(size) (ALIGN((size), 8) >> 3) +#define SIZE_4BYTES(size) (ALIGN((size), 4) >> 2) + +#define RD_DMA_ATTR_DEFAULT 0 +#define WR_DMA_ATTR_DEFAULT 0 + +enum api_cmd_data_format { + SGE_DATA = 1, /* cell data is passed by hw address */ +}; + +enum api_cmd_type { + API_CMD_WRITE = 0, +}; + +enum api_cmd_bypass { + NO_BYPASS = 0, + BYPASS = 1, +}; + enum api_cmd_xor_chk_level { XOR_CHK_DIS = 0, XOR_CHK_ALL = 3, }; +static u8 xor_chksum_set(void *data) +{ + int idx; + u8 *val, checksum = 0; + + val = data; + + for (idx = 0; idx < 7; idx++) + checksum ^= val[idx]; + + return checksum; +} + +static void set_prod_idx(struct hinic_api_cmd_chain *chain) +{ + enum hinic_api_cmd_chain_type chain_type = chain->chain_type; + struct hinic_hwif *hwif = chain->hwif; + u32 hw_prod_idx_addr, prod_idx; + + hw_prod_idx_addr = HINIC_CSR_API_CMD_CHAIN_PI_ADDR(chain_type); + prod_idx = hinic_hwif_read_reg(hwif, hw_prod_idx_addr); + + prod_idx = HINIC_API_CMD_PI_CLEAR(prod_idx, IDX); + + prod_idx |= HINIC_API_CMD_PI_SET(chain->prod_idx, IDX); + + hinic_hwif_write_reg(hwif, hw_prod_idx_addr, prod_idx); +} + +static u32 get_hw_cons_idx(struct hinic_api_cmd_chain *chain) +{ + u32 addr, val; + + addr = HINIC_CSR_API_CMD_STATUS_ADDR(chain->chain_type); + val = hinic_hwif_read_reg(chain->hwif, addr); + + return HINIC_API_CMD_STATUS_GET(val, CONS_IDX); +} + +/** + * chain_busy - check if the chain is still processing last requests + * @chain: chain to check + * + * Return 0 - Success, negative - Failure + **/ +static int chain_busy(struct hinic_api_cmd_chain *chain) +{ + struct hinic_hwif *hwif = chain->hwif; + struct pci_dev *pdev = hwif->pdev; + u32 prod_idx; + + switch (chain->chain_type) { + case HINIC_API_CMD_WRITE_TO_MGMT_CPU: + chain->cons_idx = get_hw_cons_idx(chain); + prod_idx = chain->prod_idx; + + /* check for a space for a new command */ + if (chain->cons_idx == MASKED_IDX(chain, prod_idx + 1)) { + dev_err(&pdev->dev, "API CMD chain %d is busy\n", + chain->chain_type); + return -EBUSY; + } + break; + + default: + dev_err(&pdev->dev, "Unknown API CMD Chain type\n"); + break; + } + + return 0; +} + +/** + * get_cell_data_size - get the data size of a specific cell type + * @type: chain type + * + * Return the data(Desc + Address) size in the cell + **/ +static u8 get_cell_data_size(enum hinic_api_cmd_chain_type type) +{ + u8 cell_data_size = 0; + + switch (type) { + case HINIC_API_CMD_WRITE_TO_MGMT_CPU: + cell_data_size = ALIGN(API_CMD_CELL_DESC_SIZE + + API_CMD_CELL_DATA_ADDR_SIZE, + API_CMD_CELL_ALIGNMENT); + break; + default: + break; + } + + return cell_data_size; +} + +/** + * prepare_cell_ctrl - prepare the ctrl of the cell for the command + * @cell_ctrl: the control of the cell to set the control value into it + * @data_size: the size of the data in the cell + **/ +static void prepare_cell_ctrl(u64 *cell_ctrl, u16 data_size) +{ + u8 chksum; + u64 ctrl; + + ctrl = HINIC_API_CMD_CELL_CTRL_SET(SIZE_8BYTES(data_size), DATA_SZ) | + HINIC_API_CMD_CELL_CTRL_SET(RD_DMA_ATTR_DEFAULT, RD_DMA_ATTR) | + HINIC_API_CMD_CELL_CTRL_SET(WR_DMA_ATTR_DEFAULT, WR_DMA_ATTR); + + chksum = xor_chks
[PATCH V5 net-next 05/21] net-next/hinic: Add management messages
Add the management messages for sending to api cmd and add the asynchronous event handler for the completion of the messages. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- .../net/ethernet/huawei/hinic/hinic_hw_api_cmd.c | 35 ++ .../net/ethernet/huawei/hinic/hinic_hw_api_cmd.h | 3 + drivers/net/ethernet/huawei/hinic/hinic_hw_if.h| 5 + drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c | 439 - drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h | 59 +++ 5 files changed, 538 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c index 234ede9..b44ddf2 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c @@ -54,6 +54,41 @@ enum api_cmd_xor_chk_level { }; /** + * api_cmd - API CMD command + * @chain: chain for the command + * @dest: destination node on the card that will receive the command + * @cmd: command data + * @size: the command size + * + * Return 0 - Success, negative - Failure + **/ +static int api_cmd(struct hinic_api_cmd_chain *chain, + enum hinic_node_id dest, u8 *cmd, u16 cmd_size) +{ + /* should be implemented */ + return -EINVAL; +} + +/** + * hinic_api_cmd_write - Write API CMD command + * @chain: chain for write command + * @dest: destination node on the card that will receive the command + * @cmd: command data + * @size: the command size + * + * Return 0 - Success, negative - Failure + **/ +int hinic_api_cmd_write(struct hinic_api_cmd_chain *chain, + enum hinic_node_id dest, u8 *cmd, u16 size) +{ + /* Verify the chain type */ + if (chain->chain_type == HINIC_API_CMD_WRITE_TO_MGMT_CPU) + return api_cmd(chain, dest, cmd, size); + + return -EINVAL; +} + +/** * api_cmd_hw_restart - restart the chain in the HW * @chain: the API CMD specific chain to restart * diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.h index 0c83b80..e8865d6 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.h @@ -132,6 +132,9 @@ struct hinic_api_cmd_chain { struct hinic_api_cmd_cell *curr_node; }; +int hinic_api_cmd_write(struct hinic_api_cmd_chain *chain, + enum hinic_node_id dest, u8 *cmd, u16 size); + int hinic_api_cmd_init(struct hinic_api_cmd_chain **chain, struct hinic_hwif *hwif); diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h index b6d9850..98623d6 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h @@ -93,6 +93,7 @@ #define HINIC_HWIF_NUM_IRQS(hwif) ((hwif)->attr.num_irqs) #define HINIC_HWIF_FUNC_IDX(hwif) ((hwif)->attr.func_idx) #define HINIC_HWIF_PCI_INTF(hwif) ((hwif)->attr.pci_intf_idx) +#define HINIC_HWIF_PF_IDX(hwif) ((hwif)->attr.pf_idx) #define HINIC_FUNC_TYPE(hwif) ((hwif)->attr.func_type) #define HINIC_IS_PF(hwif) (HINIC_FUNC_TYPE(hwif) == HINIC_PF) @@ -127,6 +128,10 @@ enum hinic_mod_type { HINIC_MOD_MAX = 15 }; +enum hinic_node_id { + HINIC_NODE_ID_MGMT = 21, +}; + struct hinic_func_attr { u16 func_idx; u8 pf_idx; diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c index f914bc7..147c404 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c @@ -16,6 +16,12 @@ #include #include #include +#include +#include +#include +#include +#include +#include #include "hinic_hw_if.h" #include "hinic_hw_eqs.h" @@ -23,9 +29,267 @@ #include "hinic_hw_mgmt.h" #include "hinic_hw_dev.h" +#define SYNC_MSG_ID_MASK0x1FF + +#define SYNC_MSG_ID(pf_to_mgmt) ((pf_to_mgmt)->sync_msg_id) + +#define SYNC_MSG_ID_INC(pf_to_mgmt) (SYNC_MSG_ID(pf_to_mgmt) = \ + ((SYNC_MSG_ID(pf_to_mgmt) + 1) & \ +SYNC_MSG_ID_MASK)) + +#define MSG_SZ_IS_VALID(in_size)((in_size) <= MAX_MSG_LEN) + +#define MGMT_MSG_LEN_MIN20 +#define MGMT_MSG_LEN_STEP 16 +#define MGMT_MSG_RSVD_FOR_DEV 8 + +#define SEGMENT_LEN 48 + +#define MAX_PF_MGMT_BUF_SIZE2048 + +/* Data should be SEG LEN size aligned */ +#define MAX_MSG_LEN 2016 + +#define MSG_NOT_RESP0x + +#define MGMT_MSG_TIMEOUT1000 + #define mgmt_to_pfhwdev(pf_mgmt)\ container_of(pf_mgmt, struct hinic_pfhwdev, pf_to_mgmt) +enu
[PATCH V5 net-next 03/21] net-next/hinic: Initialize api cmd resources
Initialize api cmd resources as part of management initialization. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- drivers/net/ethernet/huawei/hinic/Makefile | 4 +- .../net/ethernet/huawei/hinic/hinic_hw_api_cmd.c | 446 + .../net/ethernet/huawei/hinic/hinic_hw_api_cmd.h | 102 + drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c | 10 + drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h | 3 + 5 files changed, 563 insertions(+), 2 deletions(-) create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.h diff --git a/drivers/net/ethernet/huawei/hinic/Makefile b/drivers/net/ethernet/huawei/hinic/Makefile index 717ad71..beba90a 100644 --- a/drivers/net/ethernet/huawei/hinic/Makefile +++ b/drivers/net/ethernet/huawei/hinic/Makefile @@ -1,4 +1,4 @@ obj-$(CONFIG_HINIC) += hinic.o -hinic-y := hinic_main.o hinic_hw_dev.o hinic_hw_mgmt.o hinic_hw_eqs.o \ - hinic_hw_if.o +hinic-y := hinic_main.o hinic_hw_dev.o hinic_hw_mgmt.o hinic_hw_api_cmd.o \ + hinic_hw_eqs.o hinic_hw_if.o diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c new file mode 100644 index 000..4291f8e --- /dev/null +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c @@ -0,0 +1,446 @@ +/* + * Huawei HiNIC PCI Express Linux driver + * Copyright(c) 2017 Huawei Technologies Co., Ltd + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hinic_hw_if.h" +#include "hinic_hw_api_cmd.h" + +#define API_CHAIN_NUM_CELLS 32 + +#define API_CMD_CELL_SIZE_SHIFT 6 +#define API_CMD_CELL_SIZE_MIN (BIT(API_CMD_CELL_SIZE_SHIFT)) + +#define API_CMD_CELL_SIZE(cell_size)\ + (((cell_size) >= API_CMD_CELL_SIZE_MIN) ? \ +(1 << (fls(cell_size - 1))) : API_CMD_CELL_SIZE_MIN) + +#define API_CMD_BUF_SIZE2048 + +/** + * api_cmd_chain_hw_init - initialize the chain in the HW + * @chain: the API CMD specific chain to initialize in HW + * + * Return 0 - Success, negative - Failure + **/ +static int api_cmd_chain_hw_init(struct hinic_api_cmd_chain *chain) +{ + /* should be implemented */ + return 0; +} + +/** + * free_cmd_buf - free the dma buffer of API CMD command + * @chain: the API CMD specific chain of the cmd + * @cell_idx: the cell index of the cmd + **/ +static void free_cmd_buf(struct hinic_api_cmd_chain *chain, int cell_idx) +{ + struct hinic_api_cmd_cell_ctxt *cell_ctxt; + struct hinic_hwif *hwif = chain->hwif; + struct pci_dev *pdev = hwif->pdev; + + cell_ctxt = &chain->cell_ctxt[cell_idx]; + + dma_free_coherent(&pdev->dev, API_CMD_BUF_SIZE, + cell_ctxt->api_cmd_vaddr, + cell_ctxt->api_cmd_paddr); +} + +/** + * alloc_cmd_buf - allocate a dma buffer for API CMD command + * @chain: the API CMD specific chain for the cmd + * @cell: the cell in the HW for the cmd + * @cell_idx: the index of the cell + * + * Return 0 - Success, negative - Failure + **/ +static int alloc_cmd_buf(struct hinic_api_cmd_chain *chain, +struct hinic_api_cmd_cell *cell, int cell_idx) +{ + struct hinic_api_cmd_cell_ctxt *cell_ctxt; + struct hinic_hwif *hwif = chain->hwif; + struct pci_dev *pdev = hwif->pdev; + dma_addr_t cmd_paddr; + u8 *cmd_vaddr; + int err = 0; + + cmd_vaddr = dma_zalloc_coherent(&pdev->dev, API_CMD_BUF_SIZE, + &cmd_paddr, GFP_KERNEL); + if (!cmd_vaddr) { + dev_err(&pdev->dev, "Failed to allocate API CMD DMA memory\n"); + return -ENOMEM; + } + + cell_ctxt = &chain->cell_ctxt[cell_idx]; + + cell_ctxt->api_cmd_vaddr = cmd_vaddr; + cell_ctxt->api_cmd_paddr = cmd_paddr; + + /* set the cmd DMA address in the cell */ + switch (chain->chain_type) { + case HINIC_API_CMD_WRITE_TO_MGMT_CPU: + /* The data in the HW should be in Big Endian Format */ + cell->write.hw_cmd_paddr = cpu_to_be64(cmd_paddr); + break; + + default: + dev_err(&pdev->dev, "Unsupported API CMD chain type\n"); + free_cmd_buf(chain, cell_idx); + err = -EINVAL; + break; + } + +
[PATCH V5 net-next 02/21] net-next/hinic: Initialize hw device components
Initialize hw device by calling the initialization functions of aeqs and management channel. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- drivers/net/ethernet/huawei/hinic/Makefile| 3 +- drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c | 172 -- drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h | 14 +- drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c | 149 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.h | 107 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_if.h | 8 + drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c | 92 drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h | 45 ++ 8 files changed, 576 insertions(+), 14 deletions(-) create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.h create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h diff --git a/drivers/net/ethernet/huawei/hinic/Makefile b/drivers/net/ethernet/huawei/hinic/Makefile index 353cee0..717ad71 100644 --- a/drivers/net/ethernet/huawei/hinic/Makefile +++ b/drivers/net/ethernet/huawei/hinic/Makefile @@ -1,3 +1,4 @@ obj-$(CONFIG_HINIC) += hinic.o -hinic-y := hinic_main.o hinic_hw_dev.o hinic_hw_if.o +hinic-y := hinic_main.o hinic_hw_dev.o hinic_hw_mgmt.o hinic_hw_eqs.o \ + hinic_hw_if.o diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c index f681846..d430e60 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c @@ -23,11 +23,132 @@ #include #include "hinic_hw_if.h" +#include "hinic_hw_eqs.h" +#include "hinic_hw_mgmt.h" #include "hinic_hw_dev.h" #define MAX_IRQS(max_qps, num_aeqs, num_ceqs) \ (2 * (max_qps) + (num_aeqs) + (num_ceqs)) +enum intr_type { + INTR_MSIX_TYPE, +}; + +/* HW struct */ +struct hinic_dev_cap { + u8 status; + u8 version; + u8 rsvd0[6]; + + u8 rsvd1[5]; + u8 intr_type; + u8 rsvd2[66]; + u16 max_sqs; + u16 max_rqs; + u8 rsvd3[208]; +}; + +/** + * get_capability - convert device capabilities to NIC capabilities + * @hwdev: the HW device to set and convert device capabilities for + * @dev_cap: device capabilities from FW + * + * Return 0 - Success, negative - Failure + **/ +static int get_capability(struct hinic_hwdev *hwdev, + struct hinic_dev_cap *dev_cap) +{ + struct hinic_cap *nic_cap = &hwdev->nic_cap; + int num_aeqs, num_ceqs, num_irqs; + + if (!HINIC_IS_PF(hwdev->hwif) && !HINIC_IS_PPF(hwdev->hwif)) + return -EINVAL; + + if (dev_cap->intr_type != INTR_MSIX_TYPE) + return -EFAULT; + + num_aeqs = HINIC_HWIF_NUM_AEQS(hwdev->hwif); + num_ceqs = HINIC_HWIF_NUM_CEQS(hwdev->hwif); + num_irqs = HINIC_HWIF_NUM_IRQS(hwdev->hwif); + + /* Each QP has its own (SQ + RQ) interrupts */ + nic_cap->num_qps = (num_irqs - (num_aeqs + num_ceqs)) / 2; + + /* num_qps must be power of 2 */ + nic_cap->num_qps = BIT(fls(nic_cap->num_qps) - 1); + + nic_cap->max_qps = dev_cap->max_sqs + 1; + if (nic_cap->max_qps != (dev_cap->max_rqs + 1)) + return -EFAULT; + + if (nic_cap->num_qps > nic_cap->max_qps) + nic_cap->num_qps = nic_cap->max_qps; + + return 0; +} + +/** + * get_cap_from_fw - get device capabilities from FW + * @pfhwdev: the PF HW device to get capabilities for + * + * Return 0 - Success, negative - Failure + **/ +static int get_cap_from_fw(struct hinic_pfhwdev *pfhwdev) +{ + struct hinic_hwdev *hwdev = &pfhwdev->hwdev; + struct hinic_hwif *hwif = hwdev->hwif; + struct pci_dev *pdev = hwif->pdev; + struct hinic_dev_cap dev_cap; + u16 in_len, out_len; + int err; + + in_len = 0; + out_len = sizeof(dev_cap); + + err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_CFGM, + HINIC_CFG_NIC_CAP, &dev_cap, in_len, &dev_cap, + &out_len, HINIC_MGMT_MSG_SYNC); + if (err) { + dev_err(&pdev->dev, "Failed to get capability from FW\n"); + return err; + } + + return get_capability(hwdev, &dev_cap); +} + +/** + * get_dev_cap - get device capabilities + * @hwdev: the NIC HW device to get capabilities for + * + * Return 0 - Success, negative - Failure + **/ +static int get_dev_cap(struct hinic_hwdev *hwdev) +{ + struct hinic_hwif *hwif = hwdev->hwif; + struct pci_dev *pdev = hwif->pdev; + struct hinic_pfhwdev *pfhwdev; + int err; + + switch (HINIC_FUNC_TYPE(hwif)) { + case HINIC_PPF: + case HINIC_PF: + pfhwdev = container_of(hwdev, stru
Re: [PATCH 1/6] bridge: learn dst metadata in FDB
On Thu, Aug 17, 2017 at 02:51:12PM +0300, Nikolay Aleksandrov wrote: > On 17/08/17 14:39, Nikolay Aleksandrov wrote: > > On 17/08/17 14:03, David Lamparter wrote: > >> On Wed, Aug 16, 2017 at 11:38:06PM +0300, Nikolay Aleksandrov wrote: [cut] > >>> and hitting the fast path for everyone in a few different places for a > >>> feature that the majority will not use does not sound acceptable to > >>> me. We've been trying hard to optimize it, trying to avoid additional > >>> cache lines, removing tests and keeping special cases to a minimum. > >> > >> skb->dst is on the same cacheline as skb->len. > >> fdb->md_dst is on the same cacheline as fdb->dst. > >> Both will be 0 in a lot of cases, so this should be two null checks on > >> data that is hot in the cache. Are you sure this is an actual problem? > >> > > > > Sure - no, I haven't benchmarked it, but I don't see skb->len being on > > the same cache line as _skb_refdst assuming 64 byte cache lines. > > I should've been clearer - that obviously depends on the kernel config, but > in order for them to be in the same line you need to disable either one of > conntrack, bridge_netfilter or xfrm, these are almost always enabled (at > least in all major distributions). Did I miscount somewhere? This is what I counted: offssize 00 16 next/prev/other union bits 16 8 sk 24 8 dev 32 32 cb (first 32 bytes) boundary @ 64 64 16 cb (last 16 bytes) 80 8 _skb_refdst 88 8 destructor 96 8 (0) sp 104 8 (0) _nfct 112 8 (0) nf_bridge 120 4 len 124 4 data_len boundary @ 128 128 2 mac_len 130 2 hdr_len -David
Re: [PATCH 1/6] bridge: learn dst metadata in FDB
On Thu, Aug 17, 2017 at 02:10:20PM +0200, David Lamparter wrote: > On Thu, Aug 17, 2017 at 02:51:12PM +0300, Nikolay Aleksandrov wrote: > > On 17/08/17 14:39, Nikolay Aleksandrov wrote: > > > On 17/08/17 14:03, David Lamparter wrote: > > >> On Wed, Aug 16, 2017 at 11:38:06PM +0300, Nikolay Aleksandrov wrote: > [cut] > > >>> and hitting the fast path for everyone in a few different places for a > > >>> feature that the majority will not use does not sound acceptable to > > >>> me. We've been trying hard to optimize it, trying to avoid additional > > >>> cache lines, removing tests and keeping special cases to a minimum. > > >> > > >> skb->dst is on the same cacheline as skb->len. > > >> fdb->md_dst is on the same cacheline as fdb->dst. > > >> Both will be 0 in a lot of cases, so this should be two null checks on > > >> data that is hot in the cache. Are you sure this is an actual problem? > > >> > > > > > > Sure - no, I haven't benchmarked it, but I don't see skb->len being on > > > the same cache line as _skb_refdst assuming 64 byte cache lines. > > > > I should've been clearer - that obviously depends on the kernel config, but > > in order for them to be in the same line you need to disable either one of > > conntrack, bridge_netfilter or xfrm, these are almost always enabled (at > > least in all major distributions). > > Did I miscount somewhere? This is what I counted: > offssize > 00 16 next/prev/other union bits Argh, struct rb_node is 24 bytes. *sigh* Am I going to be stoned for saying that maybe the conditional fields (sp, nfcd, nf_bridge) should be moved down? :D btw: nf_bridge / BRIDGE_NETFILTER is incompatible with this to begin with because it tramples over skb->dst with its DST_FAKE_RTABLE dst. -David > 16 8 sk > 24 8 dev > 3232 cb (first 32 bytes) > boundary @ 64 > 64 16 cb (last 16 bytes) > 80 8 _skb_refdst > 88 8 destructor > 96 8 (0) sp > 104 8 (0) _nfct > 112 8 (0) nf_bridge > 120 4 len > 124 4 data_len > boundary @ 128 > 128 2 mac_len > 130 2 hdr_len
Re: [PATCH 1/6] bridge: learn dst metadata in FDB
On 17/08/17 15:10, David Lamparter wrote: > On Thu, Aug 17, 2017 at 02:51:12PM +0300, Nikolay Aleksandrov wrote: >> On 17/08/17 14:39, Nikolay Aleksandrov wrote: >>> On 17/08/17 14:03, David Lamparter wrote: On Wed, Aug 16, 2017 at 11:38:06PM +0300, Nikolay Aleksandrov wrote: > [cut] > and hitting the fast path for everyone in a few different places for a > feature that the majority will not use does not sound acceptable to > me. We've been trying hard to optimize it, trying to avoid additional > cache lines, removing tests and keeping special cases to a minimum. skb->dst is on the same cacheline as skb->len. fdb->md_dst is on the same cacheline as fdb->dst. Both will be 0 in a lot of cases, so this should be two null checks on data that is hot in the cache. Are you sure this is an actual problem? >>> >>> Sure - no, I haven't benchmarked it, but I don't see skb->len being on >>> the same cache line as _skb_refdst assuming 64 byte cache lines. >> >> I should've been clearer - that obviously depends on the kernel config, but >> in order for them to be in the same line you need to disable either one of >> conntrack, bridge_netfilter or xfrm, these are almost always enabled (at >> least in all major distributions). > > Did I miscount somewhere? This is what I counted: > offssize > 00 16 next/prev/other union bits > 16 8 sk > 24 8 dev > 3232 cb (first 32 bytes) > boundary @ 64 > 64 16 cb (last 16 bytes) > 80 8 _skb_refdst > 88 8 destructor > 96 8 (0) sp > 104 8 (0) _nfct > 112 8 (0) nf_bridge > 120 4 len > 124 4 data_len > boundary @ 128 > 128 2 mac_len > 130 2 hdr_len > > > -David > What kernel ? pahole -C sk_buff struct sk_buff { union { struct { struct sk_buff * next; /* 0 8 */ struct sk_buff * prev; /* 8 8 */ union { ktime_t tstamp; /* 8 */ u64 skb_mstamp; /* 8 */ }; /*16 8 */ }; /* 24 */ struct rb_node rbnode; /* 24 */ }; /* 024 */ struct sock * sk; /*24 8 */ union { struct net_device * dev; /* 8 */ long unsigned int dev_scratch; /* 8 */ }; /*32 8 */ char cb[48]; /*4048 */ /* --- cacheline 1 boundary (64 bytes) was 24 bytes ago --- */ long unsigned int _skb_refdst; /*88 8 */ void (*destructor)(struct sk_buff *); /*96 8 */ struct sec_path * sp; /* 104 8 */ long unsigned int _nfct;/* 112 8 */ struct nf_bridge_info *nf_bridge;/* 120 8 */ /* --- cacheline 2 boundary (128 bytes) --- */ unsigned int len; /* 128 4 */ unsigned int data_len; /* 132 4 */
[PATCH V6 02/21] net-next/hinic: Initialize hw device components
Initialize hw device by calling the initialization functions of aeqs and management channel. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- drivers/net/ethernet/huawei/hinic/Makefile| 3 +- drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c | 172 -- drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h | 14 +- drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c | 149 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.h | 107 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_if.h | 8 + drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c | 92 drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h | 45 ++ 8 files changed, 576 insertions(+), 14 deletions(-) create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.h create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h diff --git a/drivers/net/ethernet/huawei/hinic/Makefile b/drivers/net/ethernet/huawei/hinic/Makefile index 353cee0..717ad71 100644 --- a/drivers/net/ethernet/huawei/hinic/Makefile +++ b/drivers/net/ethernet/huawei/hinic/Makefile @@ -1,3 +1,4 @@ obj-$(CONFIG_HINIC) += hinic.o -hinic-y := hinic_main.o hinic_hw_dev.o hinic_hw_if.o +hinic-y := hinic_main.o hinic_hw_dev.o hinic_hw_mgmt.o hinic_hw_eqs.o \ + hinic_hw_if.o diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c index f681846..d430e60 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c @@ -23,11 +23,132 @@ #include #include "hinic_hw_if.h" +#include "hinic_hw_eqs.h" +#include "hinic_hw_mgmt.h" #include "hinic_hw_dev.h" #define MAX_IRQS(max_qps, num_aeqs, num_ceqs) \ (2 * (max_qps) + (num_aeqs) + (num_ceqs)) +enum intr_type { + INTR_MSIX_TYPE, +}; + +/* HW struct */ +struct hinic_dev_cap { + u8 status; + u8 version; + u8 rsvd0[6]; + + u8 rsvd1[5]; + u8 intr_type; + u8 rsvd2[66]; + u16 max_sqs; + u16 max_rqs; + u8 rsvd3[208]; +}; + +/** + * get_capability - convert device capabilities to NIC capabilities + * @hwdev: the HW device to set and convert device capabilities for + * @dev_cap: device capabilities from FW + * + * Return 0 - Success, negative - Failure + **/ +static int get_capability(struct hinic_hwdev *hwdev, + struct hinic_dev_cap *dev_cap) +{ + struct hinic_cap *nic_cap = &hwdev->nic_cap; + int num_aeqs, num_ceqs, num_irqs; + + if (!HINIC_IS_PF(hwdev->hwif) && !HINIC_IS_PPF(hwdev->hwif)) + return -EINVAL; + + if (dev_cap->intr_type != INTR_MSIX_TYPE) + return -EFAULT; + + num_aeqs = HINIC_HWIF_NUM_AEQS(hwdev->hwif); + num_ceqs = HINIC_HWIF_NUM_CEQS(hwdev->hwif); + num_irqs = HINIC_HWIF_NUM_IRQS(hwdev->hwif); + + /* Each QP has its own (SQ + RQ) interrupts */ + nic_cap->num_qps = (num_irqs - (num_aeqs + num_ceqs)) / 2; + + /* num_qps must be power of 2 */ + nic_cap->num_qps = BIT(fls(nic_cap->num_qps) - 1); + + nic_cap->max_qps = dev_cap->max_sqs + 1; + if (nic_cap->max_qps != (dev_cap->max_rqs + 1)) + return -EFAULT; + + if (nic_cap->num_qps > nic_cap->max_qps) + nic_cap->num_qps = nic_cap->max_qps; + + return 0; +} + +/** + * get_cap_from_fw - get device capabilities from FW + * @pfhwdev: the PF HW device to get capabilities for + * + * Return 0 - Success, negative - Failure + **/ +static int get_cap_from_fw(struct hinic_pfhwdev *pfhwdev) +{ + struct hinic_hwdev *hwdev = &pfhwdev->hwdev; + struct hinic_hwif *hwif = hwdev->hwif; + struct pci_dev *pdev = hwif->pdev; + struct hinic_dev_cap dev_cap; + u16 in_len, out_len; + int err; + + in_len = 0; + out_len = sizeof(dev_cap); + + err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_CFGM, + HINIC_CFG_NIC_CAP, &dev_cap, in_len, &dev_cap, + &out_len, HINIC_MGMT_MSG_SYNC); + if (err) { + dev_err(&pdev->dev, "Failed to get capability from FW\n"); + return err; + } + + return get_capability(hwdev, &dev_cap); +} + +/** + * get_dev_cap - get device capabilities + * @hwdev: the NIC HW device to get capabilities for + * + * Return 0 - Success, negative - Failure + **/ +static int get_dev_cap(struct hinic_hwdev *hwdev) +{ + struct hinic_hwif *hwif = hwdev->hwif; + struct pci_dev *pdev = hwif->pdev; + struct hinic_pfhwdev *pfhwdev; + int err; + + switch (HINIC_FUNC_TYPE(hwif)) { + case HINIC_PPF: + case HINIC_PF: + pfhwdev = container_of(hwdev, stru
[PATCH V6 20/21] net-next/hinic: Add ethtool and stats
Add ethtool operations and statistics operations. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- drivers/net/ethernet/huawei/hinic/hinic_dev.h | 3 + drivers/net/ethernet/huawei/hinic/hinic_main.c | 218 - drivers/net/ethernet/huawei/hinic/hinic_port.c | 31 drivers/net/ethernet/huawei/hinic/hinic_port.h | 45 + drivers/net/ethernet/huawei/hinic/hinic_rx.c | 19 +++ drivers/net/ethernet/huawei/hinic/hinic_rx.h | 2 + drivers/net/ethernet/huawei/hinic/hinic_tx.c | 22 +++ drivers/net/ethernet/huawei/hinic/hinic_tx.h | 2 + 8 files changed, 341 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_dev.h index 15d0c2e..5186cc9 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_dev.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_dev.h @@ -56,6 +56,9 @@ struct hinic_dev { struct hinic_txq*txqs; struct hinic_rxq*rxqs; + + struct hinic_txq_stats tx_stats; + struct hinic_rxq_stats rx_stats; }; #endif diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c index 4a5f23f..a77a7f8 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_main.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c @@ -69,6 +69,186 @@ static int change_mac_addr(struct net_device *netdev, const u8 *addr); +static void set_link_speed(struct ethtool_link_ksettings *link_ksettings, + enum hinic_speed speed) +{ + switch (speed) { + case HINIC_SPEED_10MB_LINK: + link_ksettings->base.speed = SPEED_10; + break; + + case HINIC_SPEED_100MB_LINK: + link_ksettings->base.speed = SPEED_100; + break; + + case HINIC_SPEED_1000MB_LINK: + link_ksettings->base.speed = SPEED_1000; + break; + + case HINIC_SPEED_10GB_LINK: + link_ksettings->base.speed = SPEED_1; + break; + + case HINIC_SPEED_25GB_LINK: + link_ksettings->base.speed = SPEED_25000; + break; + + case HINIC_SPEED_40GB_LINK: + link_ksettings->base.speed = SPEED_4; + break; + + case HINIC_SPEED_100GB_LINK: + link_ksettings->base.speed = SPEED_10; + break; + + default: + link_ksettings->base.speed = SPEED_UNKNOWN; + break; + } +} + +static int hinic_get_link_ksettings(struct net_device *netdev, + struct ethtool_link_ksettings + *link_ksettings) +{ + struct hinic_dev *nic_dev = netdev_priv(netdev); + enum hinic_port_link_state link_state; + struct hinic_port_cap port_cap; + int err; + + ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising); + ethtool_link_ksettings_add_link_mode(link_ksettings, supported, +Autoneg); + + link_ksettings->base.speed = SPEED_UNKNOWN; + link_ksettings->base.autoneg = AUTONEG_DISABLE; + link_ksettings->base.duplex = DUPLEX_UNKNOWN; + + err = hinic_port_get_cap(nic_dev, &port_cap); + if (err) { + netif_err(nic_dev, drv, netdev, + "Failed to get port capabilities\n"); + return err; + } + + err = hinic_port_link_state(nic_dev, &link_state); + if (err) { + netif_err(nic_dev, drv, netdev, + "Failed to get port link state\n"); + return err; + } + + if (link_state != HINIC_LINK_STATE_UP) { + netif_info(nic_dev, drv, netdev, "No link\n"); + return err; + } + + set_link_speed(link_ksettings, port_cap.speed); + + if (!!(port_cap.autoneg_cap & HINIC_AUTONEG_SUPPORTED)) + ethtool_link_ksettings_add_link_mode(link_ksettings, +advertising, Autoneg); + + if (port_cap.autoneg_state == HINIC_AUTONEG_ACTIVE) + link_ksettings->base.autoneg = AUTONEG_ENABLE; + + link_ksettings->base.duplex = (port_cap.duplex == HINIC_DUPLEX_FULL) ? + DUPLEX_FULL : DUPLEX_HALF; + return 0; +} + +static void hinic_get_drvinfo(struct net_device *netdev, + struct ethtool_drvinfo *info) +{ + struct hinic_dev *nic_dev = netdev_priv(netdev); + struct hinic_hwdev *hwdev = nic_dev->hwdev; + struct hinic_hwif *hwif = hwdev->hwif; + + strlcpy(info->driver, HINIC_DRV_NAME, sizeof(info->driver)); + strlcpy(info->bus_info, pci_name(hwif->pdev), sizeof(info->bus_info)); +} + +static void hinic_get_ringparam(struct net_device *netdev, + struct
[PATCH V6 21/21] net-next/hinic: Add netpoll
Add more netdev operation - netpoll. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- MAINTAINERS| 7 +++ drivers/net/ethernet/huawei/hinic/hinic_main.c | 20 2 files changed, 27 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 0e967b3..8f9ea9b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6240,6 +6240,13 @@ L: linux-in...@vger.kernel.org S: Maintained F: drivers/input/touchscreen/htcpen.c +HUAWEI ETHERNET DRIVER +M: Aviad Krawczyk +L: netdev@vger.kernel.org +S: Supported +F: Documentation/networking/hinic.txt +F: drivers/net/ethernet/huawei/hinic/ + HUGETLB FILESYSTEM M: Nadia Yvette Chambers S: Maintained diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c index a77a7f8..59f3358 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_main.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c @@ -787,6 +787,23 @@ static void hinic_get_stats64(struct net_device *netdev, stats->tx_errors = nic_tx_stats->tx_dropped; } +#ifdef CONFIG_NET_POLL_CONTROLLER +static void hinic_netpoll(struct net_device *netdev) +{ + struct hinic_dev *nic_dev = netdev_priv(netdev); + int i, num_qps; + + num_qps = hinic_hwdev_num_qps(nic_dev->hwdev); + for (i = 0; i < num_qps; i++) { + struct hinic_txq *txq = &nic_dev->txqs[i]; + struct hinic_rxq *rxq = &nic_dev->rxqs[i]; + + napi_schedule(&txq->napi); + napi_schedule(&rxq->napi); + } +} +#endif + static const struct net_device_ops hinic_netdev_ops = { .ndo_open = hinic_open, .ndo_stop = hinic_close, @@ -799,6 +816,9 @@ static void hinic_get_stats64(struct net_device *netdev, .ndo_start_xmit = hinic_xmit_frame, .ndo_tx_timeout = hinic_tx_timeout, .ndo_get_stats64 = hinic_get_stats64, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = hinic_netpoll, +#endif }; static void netdev_features_init(struct net_device *netdev) -- 1.9.1
[PATCH V6 18/21] net-next/hinic: Add Rx handler
Set the io resources in the nic and handle rx events by qp operations. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- drivers/net/ethernet/huawei/hinic/hinic_dev.h | 1 + drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h | 1 + drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c | 361 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h | 77 drivers/net/ethernet/huawei/hinic/hinic_hw_if.c | 36 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_if.h | 35 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h | 13 + drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c | 210 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h | 29 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c | 12 + drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h | 2 + drivers/net/ethernet/huawei/hinic/hinic_main.c| 27 ++ drivers/net/ethernet/huawei/hinic/hinic_port.c| 32 ++ drivers/net/ethernet/huawei/hinic/hinic_port.h| 19 + drivers/net/ethernet/huawei/hinic/hinic_rx.c | 419 ++ drivers/net/ethernet/huawei/hinic/hinic_rx.h | 7 + 16 files changed, 1281 insertions(+) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_dev.h index 5b8231d..3d0f6cf 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_dev.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_dev.h @@ -43,6 +43,7 @@ struct hinic_dev { struct hinic_hwdev *hwdev; u32 msg_enable; + unsigned intrx_weight; unsigned intflags; diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h index 10b8c7b..f39b184 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h @@ -20,6 +20,7 @@ #define HINIC_CSR_FUNC_ATTR0_ADDR 0x0 #define HINIC_CSR_FUNC_ATTR1_ADDR 0x4 +#define HINIC_CSR_FUNC_ATTR4_ADDR 0x10 #define HINIC_CSR_FUNC_ATTR5_ADDR 0x14 #define HINIC_DMA_ATTR_BASE 0xC80 diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c index cb4c472..03149e8 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c @@ -20,6 +20,9 @@ #include #include #include +#include +#include +#include #include #include "hinic_hw_if.h" @@ -30,6 +33,10 @@ #include "hinic_hw_io.h" #include "hinic_hw_dev.h" +#define IO_STATUS_TIMEOUT 100 +#define OUTBOUND_STATE_TIMEOUT 100 +#define DB_STATE_TIMEOUT100 + #define MAX_IRQS(max_qps, num_aeqs, num_ceqs) \ (2 * (max_qps) + (num_aeqs) + (num_ceqs)) @@ -37,6 +44,15 @@ enum intr_type { INTR_MSIX_TYPE, }; +enum io_status { + IO_STOPPED = 0, + IO_RUNNING = 1, +}; + +enum hw_ioctxt_set_cmdq_depth { + HW_IOCTXT_SET_CMDQ_DEPTH_DEFAULT, +}; + /* HW struct */ struct hinic_dev_cap { u8 status; @@ -51,6 +67,31 @@ struct hinic_dev_cap { u8 rsvd3[208]; }; +struct rx_buf_sz { + int idx; + size_t sz; +}; + +static struct rx_buf_sz rx_buf_sz_table[] = { + {0, 32}, + {1, 64}, + {2, 96}, + {3, 128}, + {4, 192}, + {5, 256}, + {6, 384}, + {7, 512}, + {8, 768}, + {9, 1024}, + {10, 1536}, + {11, 2048}, + {12, 3072}, + {13, 4096}, + {14, 8192}, + {15, 16384}, + {-1, -1}, +}; + /** * get_capability - convert device capabilities to NIC capabilities * @hwdev: the HW device to set and convert device capabilities for @@ -236,6 +277,252 @@ int hinic_port_msg_cmd(struct hinic_hwdev *hwdev, enum hinic_port_cmd cmd, } /** + * init_fw_ctxt- Init Firmware tables before network mgmt and io operations + * @hwdev: the NIC HW device + * + * Return 0 - Success, negative - Failure + **/ +static int init_fw_ctxt(struct hinic_hwdev *hwdev) +{ + struct hinic_hwif *hwif = hwdev->hwif; + struct pci_dev *pdev = hwif->pdev; + struct hinic_cmd_fw_ctxt fw_ctxt; + struct hinic_pfhwdev *pfhwdev; + u16 out_size; + int err; + + if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) { + dev_err(&pdev->dev, "Unsupported PCI Function type\n"); + return -EINVAL; + } + + fw_ctxt.func_idx = HINIC_HWIF_FUNC_IDX(hwif); + fw_ctxt.rx_buf_sz = HINIC_RX_BUF_SZ; + + pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev); + + err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_FWCTXT_INIT, +&fw_ctxt, sizeof(fw_ctxt), +&fw_ctxt, &out_size); + if (err || (out_size != sizeof(fw_ctxt)) || fw_c
[PATCH V6 19/21] net-next/hinic: Add Tx operation
Add transmit operation for sending data by qp operations. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- drivers/net/ethernet/huawei/hinic/hinic_dev.h| 1 + drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c | 47 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h | 22 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c | 257 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h | 48 +++ drivers/net/ethernet/huawei/hinic/hinic_main.c | 12 +- drivers/net/ethernet/huawei/hinic/hinic_tx.c | 406 +++ drivers/net/ethernet/huawei/hinic/hinic_tx.h | 11 + 8 files changed, 802 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_dev.h index 3d0f6cf..15d0c2e 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_dev.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_dev.h @@ -43,6 +43,7 @@ struct hinic_dev { struct hinic_hwdev *hwdev; u32 msg_enable; + unsigned inttx_weight; unsigned intrx_weight; unsigned intflags; diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c index 03149e8..6606fba 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c @@ -40,6 +40,8 @@ #define MAX_IRQS(max_qps, num_aeqs, num_ceqs) \ (2 * (max_qps) + (num_aeqs) + (num_ceqs)) +#define ADDR_IN_4BYTES(addr)((addr) >> 2) + enum intr_type { INTR_MSIX_TYPE, }; @@ -996,3 +998,48 @@ int hinic_hwdev_msix_set(struct hinic_hwdev *hwdev, u16 msix_index, lli_timer_cfg, lli_credit_limit, resend_timer); } + +/** + * hinic_hwdev_hw_ci_addr_set - set cons idx addr and attributes in HW for sq + * @hwdev: the NIC HW device + * @sq: send queue + * @pending_limit: the maximum pending update ci events (unit 8) + * @coalesc_timer: coalesc period for update ci (unit 8 us) + * + * Return 0 - Success, negative - Failure + **/ +int hinic_hwdev_hw_ci_addr_set(struct hinic_hwdev *hwdev, struct hinic_sq *sq, + u8 pending_limit, u8 coalesc_timer) +{ + struct hinic_qp *qp = container_of(sq, struct hinic_qp, sq); + struct hinic_hwif *hwif = hwdev->hwif; + struct pci_dev *pdev = hwif->pdev; + struct hinic_pfhwdev *pfhwdev; + struct hinic_cmd_hw_ci hw_ci; + + if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) { + dev_err(&pdev->dev, "Unsupported PCI Function type\n"); + return -EINVAL; + } + + hw_ci.dma_attr_off = 0; + hw_ci.pending_limit = pending_limit; + hw_ci.coalesc_timer = coalesc_timer; + + hw_ci.msix_en = 1; + hw_ci.msix_entry_idx = sq->msix_entry; + + hw_ci.func_idx = HINIC_HWIF_FUNC_IDX(hwif); + + hw_ci.sq_id = qp->q_id; + + hw_ci.ci_addr = ADDR_IN_4BYTES(sq->hw_ci_dma_addr); + + pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev); + + return hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, +HINIC_MOD_COMM, +HINIC_COMM_CMD_SQ_HI_CI_SET, +&hw_ci, sizeof(hw_ci), NULL, +NULL, HINIC_MGMT_MSG_SYNC); +} diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h index e7277d1..0f5563f 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h @@ -153,6 +153,25 @@ struct hinic_cmd_base_qpn { u16 qpn; }; +struct hinic_cmd_hw_ci { + u8 status; + u8 version; + u8 rsvd0[6]; + + u16 func_idx; + + u8 dma_attr_off; + u8 pending_limit; + u8 coalesc_timer; + + u8 msix_en; + u16 msix_entry_idx; + + u32 sq_id; + u32 rsvd1; + u64 ci_addr; +}; + struct hinic_hwdev { struct hinic_hwif *hwif; struct msix_entry *msix_entries; @@ -214,4 +233,7 @@ int hinic_hwdev_msix_set(struct hinic_hwdev *hwdev, u16 msix_index, u8 lli_timer_cfg, u8 lli_credit_limit, u8 resend_timer); +int hinic_hwdev_hw_ci_addr_set(struct hinic_hwdev *hwdev, struct hinic_sq *sq, + u8 pending_limit, u8 coalesc_timer); + #endif diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c index 6e540d2..97ee8eb 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #incl
[PATCH V6 16/21] net-next/hinic: Add cmdq commands
Add cmdq commands for setting queue pair contexts in the nic. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- drivers/net/ethernet/huawei/hinic/hinic_common.c | 25 ++ drivers/net/ethernet/huawei/hinic/hinic_common.h | 9 + drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c | 282 +- drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.h | 38 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_io.h | 10 + drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c | 194 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h | 12 + drivers/net/ethernet/huawei/hinic/hinic_hw_wqe.h | 115 + 8 files changed, 683 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_common.c b/drivers/net/ethernet/huawei/hinic/hinic_common.c index 1915ad6..02c74fd 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_common.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_common.c @@ -13,6 +13,7 @@ * */ +#include #include #include @@ -53,3 +54,27 @@ void hinic_be32_to_cpu(void *data, int len) mem++; } } + +/** + * hinic_set_sge - set dma area in scatter gather entry + * @sge: scatter gather entry + * @addr: dma address + * @len: length of relevant data in the dma address + **/ +void hinic_set_sge(struct hinic_sge *sge, dma_addr_t addr, int len) +{ + sge->hi_addr = upper_32_bits(addr); + sge->lo_addr = lower_32_bits(addr); + sge->len = len; +} + +/** + * hinic_sge_to_dma - get dma address from scatter gather entry + * @sge: scatter gather entry + * + * Return dma address of sg entry + **/ +dma_addr_t hinic_sge_to_dma(struct hinic_sge *sge) +{ + return (dma_addr_t)u64)sge->hi_addr) << 32) | sge->lo_addr); +} diff --git a/drivers/net/ethernet/huawei/hinic/hinic_common.h b/drivers/net/ethernet/huawei/hinic/hinic_common.h index 0f2f4ff..2c06b76 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_common.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_common.h @@ -16,6 +16,11 @@ #ifndef HINIC_COMMON_H #define HINIC_COMMON_H +#include + +#define UPPER_8_BITS(data) (((data) >> 8) & 0xFF) +#define LOWER_8_BITS(data) ((data) & 0xFF) + struct hinic_sge { u32 hi_addr; u32 lo_addr; @@ -26,4 +31,8 @@ struct hinic_sge { void hinic_be32_to_cpu(void *data, int len); +void hinic_set_sge(struct hinic_sge *sge, dma_addr_t addr, int len); + +dma_addr_t hinic_sge_to_dma(struct hinic_sge *sge); + #endif diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c index ec24b95..d8c0807 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c @@ -24,19 +24,34 @@ #include #include #include +#include +#include +#include #include +#include +#include "hinic_common.h" #include "hinic_hw_if.h" #include "hinic_hw_eqs.h" #include "hinic_hw_mgmt.h" +#include "hinic_hw_wqe.h" #include "hinic_hw_wq.h" #include "hinic_hw_cmdq.h" #include "hinic_hw_io.h" #include "hinic_hw_dev.h" +#define CMDQ_DB_PI_OFF(pi) (((u16)LOWER_8_BITS(pi)) << 3) + +#define CMDQ_DB_ADDR(db_base, pi) ((db_base) + CMDQ_DB_PI_OFF(pi)) + +#define CMDQ_WQE_HEADER(wqe)((struct hinic_cmdq_header *)(wqe)) + +#define FIRST_DATA_TO_WRITE_LASTsizeof(u64) + #define CMDQ_DB_OFF SZ_2K #define CMDQ_WQEBB_SIZE 64 +#define CMDQ_WQE_SIZE 64 #define CMDQ_DEPTH SZ_4K #define CMDQ_WQ_PAGE_SIZE SZ_4K @@ -44,6 +59,10 @@ #define WQE_LCMD_SIZE 64 #define WQE_SCMD_SIZE 64 +#define COMPLETE_LEN3 + +#define CMDQ_TIMEOUT1000 + #define CMDQ_PFN(addr, page_size) ((addr) >> (ilog2(page_size))) #define cmdq_to_cmdqs(cmdq) container_of((cmdq) - (cmdq)->cmdq_type, \ @@ -58,6 +77,40 @@ enum cmdq_wqe_type { WQE_SCMD_TYPE = 1, }; +enum completion_format { + COMPLETE_DIRECT = 0, + COMPLETE_SGE= 1, +}; + +enum data_format { + DATA_SGE= 0, + DATA_DIRECT = 1, +}; + +enum bufdesc_len { + BUFDESC_LCMD_LEN = 2, /* 16 bytes - 2(8 byte unit) */ + BUFDESC_SCMD_LEN = 3, /* 24 bytes - 3(8 byte unit) */ +}; + +enum ctrl_sect_len { + CTRL_SECT_LEN= 1, /* 4 bytes (ctrl) - 1(8 byte unit) */ + CTRL_DIRECT_SECT_LEN = 2, /* 12 bytes (ctrl + rsvd) - 2(8 byte unit) */ +}; + +enum cmdq_scmd_type { + CMDQ_SET_ARM_CMD = 2, +}; + +enum cmdq_cmd_type { + CMDQ_CMD_SYNC_DIRECT_RESP = 0, + CMDQ_CMD_SYNC_SGE_RESP= 1, +}; + +enum completion_request { + NO_CEQ = 0, + CEQ_SET = 1, +}; + /** * hinic_alloc_cmdq_buf - alloc buffer for sending command * @cmdqs: the cmdqs @@ -92,6 +145,221 @@ void hinic_free_cmdq_buf(struct hinic_cmdqs *cmdqs, pci_pool_free(cmdqs->c
[PATCH V6 17/21] net-next/hinic: Add cmdq completion handler
Add cmdq completion handler for getting a notification about the completion of cmdq commands. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c | 297 +- drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.h | 12 + 2 files changed, 308 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c index d8c0807..8d72762 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c @@ -40,12 +40,31 @@ #include "hinic_hw_io.h" #include "hinic_hw_dev.h" +#define CMDQ_CEQE_TYPE_SHIFT0 + +#define CMDQ_CEQE_TYPE_MASK 0x7 + +#define CMDQ_CEQE_GET(val, member) \ + (((val) >> CMDQ_CEQE_##member##_SHIFT) \ +& CMDQ_CEQE_##member##_MASK) + +#define CMDQ_WQE_ERRCODE_VAL_SHIFT 20 + +#define CMDQ_WQE_ERRCODE_VAL_MASK 0xF + +#define CMDQ_WQE_ERRCODE_GET(val, member) \ + (((val) >> CMDQ_WQE_ERRCODE_##member##_SHIFT) \ +& CMDQ_WQE_ERRCODE_##member##_MASK) + #define CMDQ_DB_PI_OFF(pi) (((u16)LOWER_8_BITS(pi)) << 3) #define CMDQ_DB_ADDR(db_base, pi) ((db_base) + CMDQ_DB_PI_OFF(pi)) #define CMDQ_WQE_HEADER(wqe)((struct hinic_cmdq_header *)(wqe)) +#define CMDQ_WQE_COMPLETED(ctrl_info) \ + HINIC_CMDQ_CTRL_GET(ctrl_info, HW_BUSY_BIT) + #define FIRST_DATA_TO_WRITE_LASTsizeof(u64) #define CMDQ_DB_OFF SZ_2K @@ -145,6 +164,22 @@ void hinic_free_cmdq_buf(struct hinic_cmdqs *cmdqs, pci_pool_free(cmdqs->cmdq_buf_pool, cmdq_buf->buf, cmdq_buf->dma_addr); } +static unsigned int cmdq_wqe_size_from_bdlen(enum bufdesc_len len) +{ + unsigned int wqe_size = 0; + + switch (len) { + case BUFDESC_LCMD_LEN: + wqe_size = WQE_LCMD_SIZE; + break; + case BUFDESC_SCMD_LEN: + wqe_size = WQE_SCMD_SIZE; + break; + } + + return wqe_size; +} + static void cmdq_set_sge_completion(struct hinic_cmdq_completion *completion, struct hinic_cmdq_buf *buf_out) { @@ -211,6 +246,15 @@ static void cmdq_set_lcmd_bufdesc(struct hinic_cmdq_wqe_lcmd *wqe_lcmd, hinic_set_sge(&wqe_lcmd->buf_desc.sge, buf_in->dma_addr, buf_in->size); } +static void cmdq_set_direct_wqe_data(struct hinic_cmdq_direct_wqe *wqe, +void *buf_in, u32 in_size) +{ + struct hinic_cmdq_wqe_scmd *wqe_scmd = &wqe->wqe_scmd; + + wqe_scmd->buf_desc.buf_len = in_size; + memcpy(wqe_scmd->buf_desc.data, buf_in, in_size); +} + static void cmdq_set_lcmd_wqe(struct hinic_cmdq_wqe *wqe, enum cmdq_cmd_type cmd_type, struct hinic_cmdq_buf *buf_in, @@ -239,6 +283,36 @@ static void cmdq_set_lcmd_wqe(struct hinic_cmdq_wqe *wqe, cmdq_set_lcmd_bufdesc(wqe_lcmd, buf_in); } +static void cmdq_set_direct_wqe(struct hinic_cmdq_wqe *wqe, + enum cmdq_cmd_type cmd_type, + void *buf_in, u16 in_size, + struct hinic_cmdq_buf *buf_out, int wrapped, + enum hinic_cmd_ack_type ack_type, + enum hinic_mod_type mod, u8 cmd, u16 prod_idx) +{ + struct hinic_cmdq_direct_wqe *direct_wqe = &wqe->direct_wqe; + enum completion_format complete_format; + struct hinic_cmdq_wqe_scmd *wqe_scmd; + + wqe_scmd = &direct_wqe->wqe_scmd; + + switch (cmd_type) { + case CMDQ_CMD_SYNC_SGE_RESP: + complete_format = COMPLETE_SGE; + cmdq_set_sge_completion(&wqe_scmd->completion, buf_out); + break; + case CMDQ_CMD_SYNC_DIRECT_RESP: + complete_format = COMPLETE_DIRECT; + wqe_scmd->completion.direct_resp = 0; + break; + } + + cmdq_prepare_wqe_ctrl(wqe, wrapped, ack_type, mod, cmd, prod_idx, + complete_format, DATA_DIRECT, BUFDESC_SCMD_LEN); + + cmdq_set_direct_wqe_data(direct_wqe, buf_in, in_size); +} + static void cmdq_wqe_fill(void *dst, void *src) { memcpy(dst + FIRST_DATA_TO_WRITE_LAST, src + FIRST_DATA_TO_WRITE_LAST, @@ -352,6 +426,52 @@ static int cmdq_sync_cmd_direct_resp(struct hinic_cmdq *cmdq, return 0; } +static int cmdq_set_arm_bit(struct hinic_cmdq *cmdq, void *buf_in, + u16 in_size) +{ + struct hinic_cmdq_wqe *curr_cmdq_wqe, cmdq_wqe; + u16 curr_prod_idx, next_prod_idx; + struct hinic_wq *wq = cmdq->wq; + struct hinic_hw_wqe *hw_wqe; + int wrapped, num_wqebbs; + + /* Keep doorbell index corr
[PATCH V6 15/21] net-next/hinic: Add ceqs
Initialize the completion event queues and handle ceq events by calling the registered handlers. Used for cmdq command completion. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c | 16 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h | 29 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c | 7 +- drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c | 291 +- drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.h | 75 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_io.c | 15 +- drivers/net/ethernet/huawei/hinic/hinic_hw_io.h | 3 + 7 files changed, 428 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c index 0dccbe6..ec24b95 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c @@ -27,6 +27,7 @@ #include #include "hinic_hw_if.h" +#include "hinic_hw_eqs.h" #include "hinic_hw_mgmt.h" #include "hinic_hw_wq.h" #include "hinic_hw_cmdq.h" @@ -110,6 +111,16 @@ int hinic_cmdq_direct_resp(struct hinic_cmdqs *cmdqs, } /** + * cmdq_ceq_handler - cmdq completion event handler + * @handle: private data for the handler(cmdqs) + * @ceqe_data: ceq element data + **/ +static void cmdq_ceq_handler(void *handle, u32 ceqe_data) +{ + /* should be implemented */ +} + +/** * cmdq_init_queue_ctxt - init the queue ctxt of a cmdq * @cmdq_ctxt: cmdq ctxt to initialize * @cmdq: the cmdq @@ -320,6 +331,8 @@ int hinic_init_cmdqs(struct hinic_cmdqs *cmdqs, struct hinic_hwif *hwif, goto err_cmdq_ctxt; } + hinic_ceq_register_cb(&func_to_io->ceqs, HINIC_CEQ_CMDQ, cmdqs, + cmdq_ceq_handler); return 0; err_cmdq_ctxt: @@ -340,10 +353,13 @@ int hinic_init_cmdqs(struct hinic_cmdqs *cmdqs, struct hinic_hwif *hwif, **/ void hinic_free_cmdqs(struct hinic_cmdqs *cmdqs) { + struct hinic_func_to_io *func_to_io = cmdqs_to_func_to_io(cmdqs); struct hinic_hwif *hwif = cmdqs->hwif; struct pci_dev *pdev = hwif->pdev; enum hinic_cmdq_type cmdq_type; + hinic_ceq_unregister_cb(&func_to_io->ceqs, HINIC_CEQ_CMDQ); + cmdq_type = HINIC_CMDQ_SYNC; for (; cmdq_type < HINIC_MAX_CMDQ_TYPES; cmdq_type++) free_cmdq(&cmdqs->cmdq[cmdq_type]); diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h index 1f57301..10b8c7b 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h @@ -81,27 +81,44 @@ /* EQ registers */ #define HINIC_AEQ_MTT_OFF_BASE_ADDR 0x200 +#define HINIC_CEQ_MTT_OFF_BASE_ADDR 0x400 #define HINIC_EQ_MTT_OFF_STRIDE 0x40 #define HINIC_CSR_AEQ_MTT_OFF(id) \ (HINIC_AEQ_MTT_OFF_BASE_ADDR + (id) * HINIC_EQ_MTT_OFF_STRIDE) +#define HINIC_CSR_CEQ_MTT_OFF(id) \ + (HINIC_CEQ_MTT_OFF_BASE_ADDR + (id) * HINIC_EQ_MTT_OFF_STRIDE) + #define HINIC_CSR_EQ_PAGE_OFF_STRIDE8 #define HINIC_CSR_AEQ_HI_PHYS_ADDR_REG(q_id, pg_num)\ (HINIC_CSR_AEQ_MTT_OFF(q_id) + \ (pg_num) * HINIC_CSR_EQ_PAGE_OFF_STRIDE) +#define HINIC_CSR_CEQ_HI_PHYS_ADDR_REG(q_id, pg_num)\ + (HINIC_CSR_CEQ_MTT_OFF(q_id) + \ +(pg_num) * HINIC_CSR_EQ_PAGE_OFF_STRIDE) + #define HINIC_CSR_AEQ_LO_PHYS_ADDR_REG(q_id, pg_num)\ (HINIC_CSR_AEQ_MTT_OFF(q_id) + \ (pg_num) * HINIC_CSR_EQ_PAGE_OFF_STRIDE + 4) +#define HINIC_CSR_CEQ_LO_PHYS_ADDR_REG(q_id, pg_num)\ + (HINIC_CSR_CEQ_MTT_OFF(q_id) + \ +(pg_num) * HINIC_CSR_EQ_PAGE_OFF_STRIDE + 4) + #define HINIC_AEQ_CTRL_0_ADDR_BASE 0xE00 #define HINIC_AEQ_CTRL_1_ADDR_BASE 0xE04 #define HINIC_AEQ_CONS_IDX_ADDR_BASE0xE08 #define HINIC_AEQ_PROD_IDX_ADDR_BASE0xE0C +#define HINIC_CEQ_CTRL_0_ADDR_BASE 0x1000 +#define HINIC_CEQ_CTRL_1_ADDR_BASE 0x1004 +#define HINIC_CEQ_CONS_IDX_ADDR_BASE0x1008 +#define HINIC_CEQ_PROD_IDX_ADDR_BASE0x100C + #define HINIC_EQ_OFF_STRIDE 0x80 #define HINIC_CSR_AEQ_CTRL_0_ADDR(idx) \ @@ -116,4 +133,16 @@ #define HINIC_CSR_AEQ_PROD_IDX_ADDR(idx)\ (HINIC_AEQ_PROD_IDX_ADDR_BASE + (idx) * HINIC_EQ_OFF_STRIDE) +#define HINIC_CSR_CEQ_CTRL_0_ADDR(idx) \ + (HINIC_CEQ_CTRL_0_ADDR_BASE + (idx) * HINIC_EQ_OFF_STRIDE) + +#define HINIC_CSR_CEQ_CTRL_1_ADDR(idx) \ + (HINIC_CEQ_CTRL_1_ADDR_BASE + (idx) * HINIC_EQ_OFF_STRIDE) + +#define HINIC_CSR_CEQ_CONS_IDX_ADDR(idx)\ + (HINI
[PATCH V6 14/21] net-next/hinic: Initialize cmdq
Create the work queues for cmdq and update the nic about the work queue contexts. cmdq commands are used for updating the nic about the qp contexts. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c | 282 +- drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.h | 53 drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.h | 2 + drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h | 5 + drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c | 156 drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h | 8 + 6 files changed, 500 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c index 2fd3924..0dccbe6 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c @@ -13,11 +13,49 @@ * */ +#include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "hinic_hw_if.h" +#include "hinic_hw_mgmt.h" +#include "hinic_hw_wq.h" #include "hinic_hw_cmdq.h" +#include "hinic_hw_io.h" +#include "hinic_hw_dev.h" + +#define CMDQ_DB_OFF SZ_2K + +#define CMDQ_WQEBB_SIZE 64 +#define CMDQ_DEPTH SZ_4K + +#define CMDQ_WQ_PAGE_SIZE SZ_4K + +#define WQE_LCMD_SIZE 64 +#define WQE_SCMD_SIZE 64 + +#define CMDQ_PFN(addr, page_size) ((addr) >> (ilog2(page_size))) + +#define cmdq_to_cmdqs(cmdq) container_of((cmdq) - (cmdq)->cmdq_type, \ +struct hinic_cmdqs, cmdq[0]) + +#define cmdqs_to_func_to_io(cmdqs) container_of(cmdqs, \ +struct hinic_func_to_io, \ +cmdqs) + +enum cmdq_wqe_type { + WQE_LCMD_TYPE = 0, + WQE_SCMD_TYPE = 1, +}; /** * hinic_alloc_cmdq_buf - alloc buffer for sending command @@ -29,8 +67,17 @@ int hinic_alloc_cmdq_buf(struct hinic_cmdqs *cmdqs, struct hinic_cmdq_buf *cmdq_buf) { - /* should be implemented */ - return -ENOMEM; + struct hinic_hwif *hwif = cmdqs->hwif; + struct pci_dev *pdev = hwif->pdev; + + cmdq_buf->buf = pci_pool_alloc(cmdqs->cmdq_buf_pool, GFP_KERNEL, + &cmdq_buf->dma_addr); + if (!cmdq_buf->buf) { + dev_err(&pdev->dev, "Failed to allocate cmd from the pool\n"); + return -ENOMEM; + } + + return 0; } /** @@ -41,7 +88,7 @@ int hinic_alloc_cmdq_buf(struct hinic_cmdqs *cmdqs, void hinic_free_cmdq_buf(struct hinic_cmdqs *cmdqs, struct hinic_cmdq_buf *cmdq_buf) { - /* should be implemented */ + pci_pool_free(cmdqs->cmdq_buf_pool, cmdq_buf->buf, cmdq_buf->dma_addr); } /** @@ -63,6 +110,169 @@ int hinic_cmdq_direct_resp(struct hinic_cmdqs *cmdqs, } /** + * cmdq_init_queue_ctxt - init the queue ctxt of a cmdq + * @cmdq_ctxt: cmdq ctxt to initialize + * @cmdq: the cmdq + * @cmdq_pages: the memory of the queue + **/ +static void cmdq_init_queue_ctxt(struct hinic_cmdq_ctxt *cmdq_ctxt, +struct hinic_cmdq *cmdq, +struct hinic_cmdq_pages *cmdq_pages) +{ + struct hinic_cmdq_ctxt_info *ctxt_info = &cmdq_ctxt->ctxt_info; + u64 wq_first_page_paddr, cmdq_first_block_paddr, pfn; + struct hinic_cmdqs *cmdqs = cmdq_to_cmdqs(cmdq); + struct hinic_wq *wq = cmdq->wq; + + /* The data in the HW is in Big Endian Format */ + wq_first_page_paddr = be64_to_cpu(*wq->block_vaddr); + + pfn = CMDQ_PFN(wq_first_page_paddr, wq->wq_page_size); + + ctxt_info->curr_wqe_page_pfn = + HINIC_CMDQ_CTXT_PAGE_INFO_SET(pfn, CURR_WQE_PAGE_PFN) | + HINIC_CMDQ_CTXT_PAGE_INFO_SET(HINIC_CEQ_ID_CMDQ, EQ_ID) | + HINIC_CMDQ_CTXT_PAGE_INFO_SET(1, CEQ_ARM) | + HINIC_CMDQ_CTXT_PAGE_INFO_SET(1, CEQ_EN)| + HINIC_CMDQ_CTXT_PAGE_INFO_SET(cmdq->wrapped, WRAPPED); + + /* block PFN - Read Modify Write */ + cmdq_first_block_paddr = cmdq_pages->page_paddr; + + pfn = CMDQ_PFN(cmdq_first_block_paddr, wq->wq_page_size); + + ctxt_info->wq_block_pfn = + HINIC_CMDQ_CTXT_BLOCK_INFO_SET(pfn, WQ_BLOCK_PFN) | + HINIC_CMDQ_CTXT_BLOCK_INFO_SET(atomic_read(&wq->cons_idx), CI); + + cmdq_ctxt->func_idx = HINIC_HWIF_FUNC_IDX(cmdqs->hwif); + cmdq_ctxt->cmdq_type = cmdq->cmdq_type; +} + +/** + * init_cmdq - initialize cmdq + * @cmdq: the cmdq + * @wq: the wq attaced to the cmdq + * @q_type: the cmdq type of the cmdq + * @db_area: doorbell area for the cmdq + * + * Return 0 - Success, negative - Failure + **/ +static int init_
[PATCH V6 13/21] net-next/hinic: Set qp context
Update the nic about the resources of the queue pairs. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- drivers/net/ethernet/huawei/hinic/Makefile | 5 +- drivers/net/ethernet/huawei/hinic/hinic_common.c | 55 ++ drivers/net/ethernet/huawei/hinic/hinic_common.h | 4 + drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c | 87 + drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.h | 84 drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c | 4 + drivers/net/ethernet/huawei/hinic/hinic_hw_io.c| 151 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_io.h| 5 + drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c| 159 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h| 11 ++ .../net/ethernet/huawei/hinic/hinic_hw_qp_ctxt.h | 214 + drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h| 9 + 12 files changed, 786 insertions(+), 2 deletions(-) create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_common.c create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.h create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_qp_ctxt.h diff --git a/drivers/net/ethernet/huawei/hinic/Makefile b/drivers/net/ethernet/huawei/hinic/Makefile index 84815f7..289ce88b 100644 --- a/drivers/net/ethernet/huawei/hinic/Makefile +++ b/drivers/net/ethernet/huawei/hinic/Makefile @@ -1,5 +1,6 @@ obj-$(CONFIG_HINIC) += hinic.o hinic-y := hinic_main.o hinic_tx.o hinic_rx.o hinic_port.o hinic_hw_dev.o \ - hinic_hw_io.o hinic_hw_qp.o hinic_hw_wq.o hinic_hw_mgmt.o \ - hinic_hw_api_cmd.o hinic_hw_eqs.o hinic_hw_if.o + hinic_hw_io.o hinic_hw_qp.o hinic_hw_cmdq.o hinic_hw_wq.o \ + hinic_hw_mgmt.o hinic_hw_api_cmd.o hinic_hw_eqs.o hinic_hw_if.o \ + hinic_common.o diff --git a/drivers/net/ethernet/huawei/hinic/hinic_common.c b/drivers/net/ethernet/huawei/hinic/hinic_common.c new file mode 100644 index 000..1915ad6 --- /dev/null +++ b/drivers/net/ethernet/huawei/hinic/hinic_common.c @@ -0,0 +1,55 @@ +/* + * Huawei HiNIC PCI Express Linux driver + * Copyright(c) 2017 Huawei Technologies Co., Ltd + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + */ + +#include +#include + +#include "hinic_common.h" + +/** + * hinic_cpu_to_be32 - convert data to big endian 32 bit format + * @data: the data to convert + * @len: length of data to convert + **/ +void hinic_cpu_to_be32(void *data, int len) +{ + u32 *mem = data; + int i; + + len = len / sizeof(u32); + + for (i = 0; i < len; i++) { + *mem = cpu_to_be32(*mem); + mem++; + } +} + +/** + * hinic_be32_to_cpu - convert data from big endian 32 bit format + * @data: the data to convert + * @len: length of data to convert + **/ +void hinic_be32_to_cpu(void *data, int len) +{ + u32 *mem = data; + int i; + + len = len / sizeof(u32); + + for (i = 0; i < len; i++) { + *mem = be32_to_cpu(*mem); + mem++; + } +} diff --git a/drivers/net/ethernet/huawei/hinic/hinic_common.h b/drivers/net/ethernet/huawei/hinic/hinic_common.h index 6a83c15..0f2f4ff 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_common.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_common.h @@ -22,4 +22,8 @@ struct hinic_sge { u32 len; }; +void hinic_cpu_to_be32(void *data, int len); + +void hinic_be32_to_cpu(void *data, int len); + #endif diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c new file mode 100644 index 000..2fd3924 --- /dev/null +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c @@ -0,0 +1,87 @@ +/* + * Huawei HiNIC PCI Express Linux driver + * Copyright(c) 2017 Huawei Technologies Co., Ltd + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + */ + +#include +#include + +#include "hinic_hw_if.h" +#include "hinic_hw_cmdq.h" + +/** + * hinic_alloc_cmdq_buf - alloc buffer for sending command + * @cmdqs: the cmdqs + * @cmdq_buf: the buffer returned in this struct
[PATCH V6 11/21] net-next/hinic: Add wq
Create work queues for being used by the queue pairs. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- drivers/net/ethernet/huawei/hinic/Makefile | 4 +- drivers/net/ethernet/huawei/hinic/hinic_common.h | 25 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_io.c | 69 ++- drivers/net/ethernet/huawei/hinic/hinic_hw_io.h | 6 + drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h | 14 + drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c | 517 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h | 86 drivers/net/ethernet/huawei/hinic/hinic_hw_wqe.h | 253 +++ 8 files changed, 969 insertions(+), 5 deletions(-) create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_common.h create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_wqe.h diff --git a/drivers/net/ethernet/huawei/hinic/Makefile b/drivers/net/ethernet/huawei/hinic/Makefile index f60c449..0575a34 100644 --- a/drivers/net/ethernet/huawei/hinic/Makefile +++ b/drivers/net/ethernet/huawei/hinic/Makefile @@ -1,5 +1,5 @@ obj-$(CONFIG_HINIC) += hinic.o hinic-y := hinic_main.o hinic_tx.o hinic_rx.o hinic_port.o hinic_hw_dev.o \ - hinic_hw_io.o hinic_hw_mgmt.o hinic_hw_api_cmd.o hinic_hw_eqs.o \ - hinic_hw_if.o + hinic_hw_io.o hinic_hw_wq.o hinic_hw_mgmt.o hinic_hw_api_cmd.o \ + hinic_hw_eqs.o hinic_hw_if.o diff --git a/drivers/net/ethernet/huawei/hinic/hinic_common.h b/drivers/net/ethernet/huawei/hinic/hinic_common.h new file mode 100644 index 000..6a83c15 --- /dev/null +++ b/drivers/net/ethernet/huawei/hinic/hinic_common.h @@ -0,0 +1,25 @@ +/* + * Huawei HiNIC PCI Express Linux driver + * Copyright(c) 2017 Huawei Technologies Co., Ltd + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + */ + +#ifndef HINIC_COMMON_H +#define HINIC_COMMON_H + +struct hinic_sge { + u32 hi_addr; + u32 lo_addr; + u32 len; +}; + +#endif diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_io.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_io.c index ebe28ee..1bf944e 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_io.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_io.c @@ -20,6 +20,8 @@ #include #include "hinic_hw_if.h" +#include "hinic_hw_wqe.h" +#include "hinic_hw_wq.h" #include "hinic_hw_qp.h" #include "hinic_hw_io.h" @@ -38,8 +40,33 @@ static int init_qp(struct hinic_func_to_io *func_to_io, struct msix_entry *sq_msix_entry, struct msix_entry *rq_msix_entry) { - /* should be implemented */ + struct hinic_hwif *hwif = func_to_io->hwif; + struct pci_dev *pdev = hwif->pdev; + int err; + + qp->q_id = q_id; + + err = hinic_wq_allocate(&func_to_io->wqs, &func_to_io->sq_wq[q_id], + HINIC_SQ_WQEBB_SIZE, HINIC_SQ_PAGE_SIZE, + HINIC_SQ_DEPTH, HINIC_SQ_WQE_MAX_SIZE); + if (err) { + dev_err(&pdev->dev, "Failed to allocate WQ for SQ\n"); + return err; + } + + err = hinic_wq_allocate(&func_to_io->wqs, &func_to_io->rq_wq[q_id], + HINIC_RQ_WQEBB_SIZE, HINIC_RQ_PAGE_SIZE, + HINIC_RQ_DEPTH, HINIC_RQ_WQE_SIZE); + if (err) { + dev_err(&pdev->dev, "Failed to allocate WQ for RQ\n"); + goto err_rq_alloc; + } + return 0; + +err_rq_alloc: + hinic_wq_free(&func_to_io->wqs, &func_to_io->sq_wq[q_id]); + return err; } /** @@ -50,7 +77,10 @@ static int init_qp(struct hinic_func_to_io *func_to_io, static void destroy_qp(struct hinic_func_to_io *func_to_io, struct hinic_qp *qp) { - /* should be implemented */ + int q_id = qp->q_id; + + hinic_wq_free(&func_to_io->wqs, &func_to_io->rq_wq[q_id]); + hinic_wq_free(&func_to_io->wqs, &func_to_io->sq_wq[q_id]); } /** @@ -70,7 +100,7 @@ int hinic_io_create_qps(struct hinic_func_to_io *func_to_io, { struct hinic_hwif *hwif = func_to_io->hwif; struct pci_dev *pdev = hwif->pdev; - size_t qps_size; + size_t qps_size, wq_size; int i, j, err; qps_size = num_qps * sizeof(*func_to_io->qps); @@ -78,6 +108,20 @@ int hinic_io_create_qps(struct hinic_func_to_io *func_to_io, if (!func_to_io->qps) return -ENOMEM; + wq_size = n
[PATCH V6 10/21] net-next/hinic: Add logical Txq and Rxq
Create the logical queues of the nic. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- drivers/net/ethernet/huawei/hinic/Makefile | 5 +- drivers/net/ethernet/huawei/hinic/hinic_dev.h| 5 + drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c | 131 + drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h | 20 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_io.c | 144 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_io.h | 46 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h | 32 + drivers/net/ethernet/huawei/hinic/hinic_main.c | 172 ++- drivers/net/ethernet/huawei/hinic/hinic_rx.c | 72 ++ drivers/net/ethernet/huawei/hinic/hinic_rx.h | 46 ++ drivers/net/ethernet/huawei/hinic/hinic_tx.c | 75 ++ drivers/net/ethernet/huawei/hinic/hinic_tx.h | 49 +++ 12 files changed, 793 insertions(+), 4 deletions(-) create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_io.c create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_io.h create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_rx.c create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_rx.h create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_tx.c create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_tx.h diff --git a/drivers/net/ethernet/huawei/hinic/Makefile b/drivers/net/ethernet/huawei/hinic/Makefile index dbb1b9d..f60c449 100644 --- a/drivers/net/ethernet/huawei/hinic/Makefile +++ b/drivers/net/ethernet/huawei/hinic/Makefile @@ -1,4 +1,5 @@ obj-$(CONFIG_HINIC) += hinic.o -hinic-y := hinic_main.o hinic_port.o hinic_hw_dev.o hinic_hw_mgmt.o \ - hinic_hw_api_cmd.o hinic_hw_eqs.o hinic_hw_if.o +hinic-y := hinic_main.o hinic_tx.o hinic_rx.o hinic_port.o hinic_hw_dev.o \ + hinic_hw_io.o hinic_hw_mgmt.o hinic_hw_api_cmd.o hinic_hw_eqs.o \ + hinic_hw_if.o diff --git a/drivers/net/ethernet/huawei/hinic/hinic_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_dev.h index 5c5b4e9..5b8231d 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_dev.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_dev.h @@ -23,6 +23,8 @@ #include #include "hinic_hw_dev.h" +#include "hinic_tx.h" +#include "hinic_rx.h" #define HINIC_DRV_NAME "hinic" @@ -49,6 +51,9 @@ struct hinic_dev { struct hinic_rx_mode_work rx_mode_work; struct workqueue_struct *workq; + + struct hinic_txq*txqs; + struct hinic_rxq*rxqs; }; #endif diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c index 75fd6d2..d113908 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c @@ -25,6 +25,8 @@ #include "hinic_hw_if.h" #include "hinic_hw_eqs.h" #include "hinic_hw_mgmt.h" +#include "hinic_hw_qp.h" +#include "hinic_hw_io.h" #include "hinic_hw_dev.h" #define MAX_IRQS(max_qps, num_aeqs, num_ceqs) \ @@ -230,6 +232,99 @@ int hinic_port_msg_cmd(struct hinic_hwdev *hwdev, enum hinic_port_cmd cmd, } /** + * get_base_qpn - get the first qp number + * @hwdev: the NIC HW device + * @base_qpn: returned qp number + * + * Return 0 - Success, negative - Failure + **/ +static int get_base_qpn(struct hinic_hwdev *hwdev, u16 *base_qpn) +{ + struct hinic_cmd_base_qpn cmd_base_qpn; + struct hinic_hwif *hwif = hwdev->hwif; + struct pci_dev *pdev = hwif->pdev; + u16 out_size; + int err; + + cmd_base_qpn.func_idx = HINIC_HWIF_FUNC_IDX(hwif); + + err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_GLOBAL_QPN, +&cmd_base_qpn, sizeof(cmd_base_qpn), +&cmd_base_qpn, &out_size); + if (err || (out_size != sizeof(cmd_base_qpn)) || cmd_base_qpn.status) { + dev_err(&pdev->dev, "Failed to get base qpn, status = %d\n", + cmd_base_qpn.status); + return -EFAULT; + } + + *base_qpn = cmd_base_qpn.qpn; + return 0; +} + +/** + * hinic_hwdev_ifup - Preparing the HW for passing IO + * @hwdev: the NIC HW device + * + * Return 0 - Success, negative - Failure + **/ +int hinic_hwdev_ifup(struct hinic_hwdev *hwdev) +{ + struct hinic_func_to_io *func_to_io = &hwdev->func_to_io; + struct hinic_cap *nic_cap = &hwdev->nic_cap; + struct hinic_hwif *hwif = hwdev->hwif; + int err, num_aeqs, num_ceqs, num_qps; + struct msix_entry *sq_msix_entries; + struct msix_entry *rq_msix_entries; + struct pci_dev *pdev = hwif->pdev; + u16 base_qpn; + + err = get_base_qpn(hwdev, &base_qpn); + if (err) { + dev_err(&pdev->dev, "Failed to get global base qp number\n"); + return err; + } + + num_aeqs = HINIC_HWIF_NUM_AEQS(hw
[PATCH V6 12/21] net-next/hinic: Add qp resources
Create the resources for queue pair operations: doorbell area, consumer index address and producer index address. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- drivers/net/ethernet/huawei/hinic/Makefile | 4 +- drivers/net/ethernet/huawei/hinic/hinic_hw_if.h | 1 + drivers/net/ethernet/huawei/hinic/hinic_hw_io.c | 164 ++- drivers/net/ethernet/huawei/hinic/hinic_hw_io.h | 27 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c | 266 drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h | 50 - 6 files changed, 507 insertions(+), 5 deletions(-) create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c diff --git a/drivers/net/ethernet/huawei/hinic/Makefile b/drivers/net/ethernet/huawei/hinic/Makefile index 0575a34..84815f7 100644 --- a/drivers/net/ethernet/huawei/hinic/Makefile +++ b/drivers/net/ethernet/huawei/hinic/Makefile @@ -1,5 +1,5 @@ obj-$(CONFIG_HINIC) += hinic.o hinic-y := hinic_main.o hinic_tx.o hinic_rx.o hinic_port.o hinic_hw_dev.o \ - hinic_hw_io.o hinic_hw_wq.o hinic_hw_mgmt.o hinic_hw_api_cmd.o \ - hinic_hw_eqs.o hinic_hw_if.o + hinic_hw_io.o hinic_hw_qp.o hinic_hw_wq.o hinic_hw_mgmt.o \ + hinic_hw_api_cmd.o hinic_hw_eqs.o hinic_hw_if.o diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h index 2280698..8f59195 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h @@ -137,6 +137,7 @@ #define HINIC_IS_PPF(hwif) (HINIC_FUNC_TYPE(hwif) == HINIC_PPF) #define HINIC_PCI_CFG_REGS_BAR 0 +#define HINIC_PCI_DB_BAR4 #define HINIC_PCIE_ST_DISABLE 0 #define HINIC_PCIE_AT_DISABLE 0 diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_io.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_io.c index 1bf944e..ad12cc7 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_io.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_io.c @@ -13,11 +13,16 @@ * */ +#include #include #include #include #include #include +#include +#include +#include +#include #include "hinic_hw_if.h" #include "hinic_hw_wqe.h" @@ -25,6 +30,76 @@ #include "hinic_hw_qp.h" #include "hinic_hw_io.h" +#define CI_Q_ADDR_SIZE sizeof(u32) + +#define CI_ADDR(base_addr, q_id)((base_addr) + \ +(q_id) * CI_Q_ADDR_SIZE) + +#define CI_TABLE_SIZE(num_qps) ((num_qps) * CI_Q_ADDR_SIZE) + +#define DB_IDX(db, db_base) \ + (((unsigned long)(db) - (unsigned long)(db_base)) / HINIC_DB_PAGE_SIZE) + +static void init_db_area_idx(struct hinic_free_db_area *free_db_area) +{ + int i; + + for (i = 0; i < HINIC_DB_MAX_AREAS; i++) + free_db_area->db_idx[i] = i; + + free_db_area->alloc_pos = 0; + free_db_area->return_pos = HINIC_DB_MAX_AREAS; + + free_db_area->num_free = HINIC_DB_MAX_AREAS; + + sema_init(&free_db_area->idx_lock, 1); +} + +static void __iomem *get_db_area(struct hinic_func_to_io *func_to_io) +{ + struct hinic_free_db_area *free_db_area = &func_to_io->free_db_area; + int pos, idx; + + down(&free_db_area->idx_lock); + + free_db_area->num_free--; + + if (free_db_area->num_free < 0) { + free_db_area->num_free++; + up(&free_db_area->idx_lock); + return ERR_PTR(-ENOMEM); + } + + pos = free_db_area->alloc_pos++; + pos &= HINIC_DB_MAX_AREAS - 1; + + idx = free_db_area->db_idx[pos]; + + free_db_area->db_idx[pos] = -1; + + up(&free_db_area->idx_lock); + + return func_to_io->db_base + idx * HINIC_DB_PAGE_SIZE; +} + +static void return_db_area(struct hinic_func_to_io *func_to_io, + void __iomem *db_base) +{ + struct hinic_free_db_area *free_db_area = &func_to_io->free_db_area; + int pos, idx = DB_IDX(db_base, func_to_io->db_base); + + down(&free_db_area->idx_lock); + + pos = free_db_area->return_pos++; + pos &= HINIC_DB_MAX_AREAS - 1; + + free_db_area->db_idx[pos] = idx; + + free_db_area->num_free++; + + up(&free_db_area->idx_lock); +} + /** * init_qp - Initialize a Queue Pair * @func_to_io: func to io channel that holds the IO components @@ -42,6 +117,7 @@ static int init_qp(struct hinic_func_to_io *func_to_io, { struct hinic_hwif *hwif = func_to_io->hwif; struct pci_dev *pdev = hwif->pdev; + void __iomem *db_base; int err; qp->q_id = q_id; @@ -62,8 +138,42 @@ static int init_qp(struct hinic_func_to_io *func_to_io, goto err_rq_alloc; } + db_base = get_db_area(func_to_io); + if (IS_ERR(db_base)) { + dev_err(&pdev->dev, "Failed to get DB area for SQ\n"); + err = PTR_ERR(db_base); + goto err_get_
[PATCH V6 09/21] net-next/hinic: Add Rx mode and link event handler
Add port management message for setting Rx mode in the card, used for rx_mode netdev operation. The link event handler is used for getting a notification about the link state. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- drivers/net/ethernet/huawei/hinic/hinic_dev.h | 17 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h | 2 + drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c | 118 + drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h | 37 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_if.c | 17 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_if.h | 17 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c | 64 - drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h | 28 +++ drivers/net/ethernet/huawei/hinic/hinic_main.c| 284 ++ drivers/net/ethernet/huawei/hinic/hinic_port.c| 92 +++ drivers/net/ethernet/huawei/hinic/hinic_port.h| 66 + 11 files changed, 741 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_dev.h index e54a45c..5c5b4e9 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_dev.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_dev.h @@ -19,19 +19,36 @@ #include #include #include +#include +#include #include "hinic_hw_dev.h" #define HINIC_DRV_NAME "hinic" +enum hinic_flags { + HINIC_LINK_UP = BIT(0), + HINIC_INTF_UP = BIT(1), +}; + +struct hinic_rx_mode_work { + struct work_struct work; + u32 rx_mode; +}; + struct hinic_dev { struct net_device *netdev; struct hinic_hwdev *hwdev; u32 msg_enable; + unsigned intflags; + struct semaphoremgmt_lock; unsigned long *vlan_bitmap; + + struct hinic_rx_mode_work rx_mode_work; + struct workqueue_struct *workq; }; #endif diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h index 52eb89c..1f57301 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h @@ -20,6 +20,8 @@ #define HINIC_CSR_FUNC_ATTR0_ADDR 0x0 #define HINIC_CSR_FUNC_ATTR1_ADDR 0x4 +#define HINIC_CSR_FUNC_ATTR5_ADDR 0x14 + #define HINIC_DMA_ATTR_BASE 0xC80 #define HINIC_ELECTION_BASE 0x4200 diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c index 6bb6c33..75fd6d2 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c @@ -230,6 +230,114 @@ int hinic_port_msg_cmd(struct hinic_hwdev *hwdev, enum hinic_port_cmd cmd, } /** + * hinic_hwdev_cb_register - register callback handler for MGMT events + * @hwdev: the NIC HW device + * @cmd: the mgmt event + * @handle: private data for the handler + * @handler: event handler + **/ +void hinic_hwdev_cb_register(struct hinic_hwdev *hwdev, +enum hinic_mgmt_msg_cmd cmd, void *handle, +void (*handler)(void *handle, void *buf_in, +u16 in_size, void *buf_out, +u16 *out_size)) +{ + struct hinic_hwif *hwif = hwdev->hwif; + struct pci_dev *pdev = hwif->pdev; + struct hinic_pfhwdev *pfhwdev; + struct hinic_nic_cb *nic_cb; + u8 cmd_cb; + + if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) { + dev_err(&pdev->dev, "unsupported PCI Function type\n"); + return; + } + + pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev); + + cmd_cb = cmd - HINIC_MGMT_MSG_CMD_BASE; + nic_cb = &pfhwdev->nic_cb[cmd_cb]; + + nic_cb->handler = handler; + nic_cb->handle = handle; + nic_cb->cb_state = HINIC_CB_ENABLED; +} + +/** + * hinic_hwdev_cb_unregister - unregister callback handler for MGMT events + * @hwdev: the NIC HW device + * @cmd: the mgmt event + **/ +void hinic_hwdev_cb_unregister(struct hinic_hwdev *hwdev, + enum hinic_mgmt_msg_cmd cmd) +{ + struct hinic_hwif *hwif = hwdev->hwif; + struct pci_dev *pdev = hwif->pdev; + struct hinic_pfhwdev *pfhwdev; + struct hinic_nic_cb *nic_cb; + u8 cmd_cb; + + if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) { + dev_err(&pdev->dev, "unsupported PCI Function type\n"); + return; + } + + pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev); + + cmd_cb = cmd - HINIC_MGMT_MSG_CMD_BASE; + nic_cb = &pfhwdev->nic_cb[cmd_cb]; + + nic_cb->cb_state &= ~HINIC_CB_ENABLED; + + while (
[PATCH V6 08/21] net-next/hinic: Add port management commands
Add the port management commands that are sent as management messages. The port management commands are used for netdev operations. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- drivers/net/ethernet/huawei/hinic/Makefile | 4 +- drivers/net/ethernet/huawei/hinic/hinic_dev.h| 4 + drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c | 30 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h | 29 +++ drivers/net/ethernet/huawei/hinic/hinic_main.c | 195 +++- drivers/net/ethernet/huawei/hinic/hinic_port.c | 224 +++ drivers/net/ethernet/huawei/hinic/hinic_port.h | 68 +++ 7 files changed, 551 insertions(+), 3 deletions(-) create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_port.c create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_port.h diff --git a/drivers/net/ethernet/huawei/hinic/Makefile b/drivers/net/ethernet/huawei/hinic/Makefile index beba90a..dbb1b9d 100644 --- a/drivers/net/ethernet/huawei/hinic/Makefile +++ b/drivers/net/ethernet/huawei/hinic/Makefile @@ -1,4 +1,4 @@ obj-$(CONFIG_HINIC) += hinic.o -hinic-y := hinic_main.o hinic_hw_dev.o hinic_hw_mgmt.o hinic_hw_api_cmd.o \ - hinic_hw_eqs.o hinic_hw_if.o +hinic-y := hinic_main.o hinic_port.o hinic_hw_dev.o hinic_hw_mgmt.o \ + hinic_hw_api_cmd.o hinic_hw_eqs.o hinic_hw_if.o diff --git a/drivers/net/ethernet/huawei/hinic/hinic_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_dev.h index 6c2c896..e54a45c 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_dev.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_dev.h @@ -18,6 +18,7 @@ #include #include +#include #include "hinic_hw_dev.h" @@ -28,6 +29,9 @@ struct hinic_dev { struct hinic_hwdev *hwdev; u32 msg_enable; + + struct semaphoremgmt_lock; + unsigned long *vlan_bitmap; }; #endif diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c index d430e60..6bb6c33 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c @@ -200,6 +200,36 @@ static void disable_msix(struct hinic_hwdev *hwdev) } /** + * hinic_port_msg_cmd - send port msg to mgmt + * @hwdev: the NIC HW device + * @cmd: the port command + * @buf_in: input buffer + * @in_size: input size + * @buf_out: output buffer + * @out_size: returned output size + * + * Return 0 - Success, negative - Failure + **/ +int hinic_port_msg_cmd(struct hinic_hwdev *hwdev, enum hinic_port_cmd cmd, + void *buf_in, u16 in_size, void *buf_out, u16 *out_size) +{ + struct hinic_hwif *hwif = hwdev->hwif; + struct pci_dev *pdev = hwif->pdev; + struct hinic_pfhwdev *pfhwdev; + + if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) { + dev_err(&pdev->dev, "unsupported PCI Function type\n"); + return -EINVAL; + } + + pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev); + + return hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_L2NIC, cmd, +buf_in, in_size, buf_out, out_size, +HINIC_MGMT_MSG_SYNC); +} + +/** * init_pfhwdev - Initialize the extended components of PF * @pfhwdev: the HW device for PF * diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h index feb60138..ee9e76a 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h @@ -30,6 +30,31 @@ struct hinic_cap { u16 num_qps; }; +enum hinic_port_cmd { + HINIC_PORT_CMD_CHANGE_MTU = 2, + + HINIC_PORT_CMD_ADD_VLAN = 3, + HINIC_PORT_CMD_DEL_VLAN = 4, + + HINIC_PORT_CMD_SET_MAC = 9, + HINIC_PORT_CMD_GET_MAC = 10, + HINIC_PORT_CMD_DEL_MAC = 11, + + HINIC_PORT_CMD_SET_RX_MODE = 12, + + HINIC_PORT_CMD_GET_LINK_STATE = 24, + + HINIC_PORT_CMD_SET_PORT_STATE = 41, + + HINIC_PORT_CMD_FWCTXT_INIT = 69, + + HINIC_PORT_CMD_SET_FUNC_STATE = 93, + + HINIC_PORT_CMD_GET_GLOBAL_QPN = 102, + + HINIC_PORT_CMD_GET_CAP = 170, +}; + struct hinic_hwdev { struct hinic_hwif *hwif; struct msix_entry *msix_entries; @@ -45,6 +70,10 @@ struct hinic_pfhwdev { struct hinic_pf_to_mgmt pf_to_mgmt; }; +int hinic_port_msg_cmd(struct hinic_hwdev *hwdev, enum hinic_port_cmd cmd, + void *buf_in, u16 in_size, void *buf_out, + u16 *out_size); + struct hinic_hwdev *hinic_init_hwdev(struct pci_dev *pdev); void hinic_free_hwdev(struct hinic_hwdev *hwdev); diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.
[PATCH V6 07/21] net-next/hinic: Add aeqs
Handle aeq elements that are accumulated on the aeq by calling the registered handler for the specific event. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h | 49 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c | 464 ++- drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.h | 81 drivers/net/ethernet/huawei/hinic/hinic_hw_if.c | 91 + drivers/net/ethernet/huawei/hinic/hinic_hw_if.h | 46 +++ 5 files changed, 729 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h index ebbf054..52eb89c 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h @@ -65,4 +65,53 @@ #define HINIC_CSR_API_CMD_STATUS_ADDR(idx) \ (HINIC_CSR_API_CMD_BASE + 0x30 + (idx) * HINIC_CSR_API_CMD_STRIDE) +/* MSI-X registers */ +#define HINIC_CSR_MSIX_CTRL_BASE0x2000 +#define HINIC_CSR_MSIX_CNT_BASE 0x2004 + +#define HINIC_CSR_MSIX_STRIDE 0x8 + +#define HINIC_CSR_MSIX_CTRL_ADDR(idx) \ + (HINIC_CSR_MSIX_CTRL_BASE + (idx) * HINIC_CSR_MSIX_STRIDE) + +#define HINIC_CSR_MSIX_CNT_ADDR(idx)\ + (HINIC_CSR_MSIX_CNT_BASE + (idx) * HINIC_CSR_MSIX_STRIDE) + +/* EQ registers */ +#define HINIC_AEQ_MTT_OFF_BASE_ADDR 0x200 + +#define HINIC_EQ_MTT_OFF_STRIDE 0x40 + +#define HINIC_CSR_AEQ_MTT_OFF(id) \ + (HINIC_AEQ_MTT_OFF_BASE_ADDR + (id) * HINIC_EQ_MTT_OFF_STRIDE) + +#define HINIC_CSR_EQ_PAGE_OFF_STRIDE8 + +#define HINIC_CSR_AEQ_HI_PHYS_ADDR_REG(q_id, pg_num)\ + (HINIC_CSR_AEQ_MTT_OFF(q_id) + \ +(pg_num) * HINIC_CSR_EQ_PAGE_OFF_STRIDE) + +#define HINIC_CSR_AEQ_LO_PHYS_ADDR_REG(q_id, pg_num)\ + (HINIC_CSR_AEQ_MTT_OFF(q_id) + \ +(pg_num) * HINIC_CSR_EQ_PAGE_OFF_STRIDE + 4) + +#define HINIC_AEQ_CTRL_0_ADDR_BASE 0xE00 +#define HINIC_AEQ_CTRL_1_ADDR_BASE 0xE04 +#define HINIC_AEQ_CONS_IDX_ADDR_BASE0xE08 +#define HINIC_AEQ_PROD_IDX_ADDR_BASE0xE0C + +#define HINIC_EQ_OFF_STRIDE 0x80 + +#define HINIC_CSR_AEQ_CTRL_0_ADDR(idx) \ + (HINIC_AEQ_CTRL_0_ADDR_BASE + (idx) * HINIC_EQ_OFF_STRIDE) + +#define HINIC_CSR_AEQ_CTRL_1_ADDR(idx) \ + (HINIC_AEQ_CTRL_1_ADDR_BASE + (idx) * HINIC_EQ_OFF_STRIDE) + +#define HINIC_CSR_AEQ_CONS_IDX_ADDR(idx)\ + (HINIC_AEQ_CONS_IDX_ADDR_BASE + (idx) * HINIC_EQ_OFF_STRIDE) + +#define HINIC_CSR_AEQ_PROD_IDX_ADDR(idx)\ + (HINIC_AEQ_PROD_IDX_ADDR_BASE + (idx) * HINIC_EQ_OFF_STRIDE) + #endif diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c index a099d20..a53d5b3 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c @@ -13,17 +13,74 @@ * */ +#include #include #include #include #include #include +#include +#include +#include +#include +#include +#include +#include "hinic_hw_csr.h" #include "hinic_hw_if.h" #include "hinic_hw_eqs.h" #define HINIC_EQS_WQ_NAME "hinic_eqs" +#define GET_EQ_NUM_PAGES(eq, pg_size) \ + (ALIGN((eq)->q_len * (eq)->elem_size, pg_size) / (pg_size)) + +#define GET_EQ_NUM_ELEMS_IN_PG(eq, pg_size) ((pg_size) / (eq)->elem_size) + +#define EQ_CONS_IDX_REG_ADDR(eq)HINIC_CSR_AEQ_CONS_IDX_ADDR((eq)->q_id) +#define EQ_PROD_IDX_REG_ADDR(eq)HINIC_CSR_AEQ_PROD_IDX_ADDR((eq)->q_id) + +#define EQ_HI_PHYS_ADDR_REG(eq, pg_num) \ + HINIC_CSR_AEQ_HI_PHYS_ADDR_REG((eq)->q_id, pg_num) + +#define EQ_LO_PHYS_ADDR_REG(eq, pg_num) \ + HINIC_CSR_AEQ_LO_PHYS_ADDR_REG((eq)->q_id, pg_num) + +#define GET_EQ_ELEMENT(eq, idx) \ + ((eq)->virt_addr[(idx) / (eq)->num_elem_in_pg] + \ +(((idx) & ((eq)->num_elem_in_pg - 1)) * (eq)->elem_size)) + +#define GET_AEQ_ELEM(eq, idx) ((struct hinic_aeq_elem *) \ + GET_EQ_ELEMENT(eq, idx)) + +#define GET_CURR_AEQ_ELEM(eq) GET_AEQ_ELEM(eq, (eq)->cons_idx) + +#define PAGE_IN_4K(page_size) ((page_size) >> 12) +#define EQ_SET_HW_PAGE_SIZE_VAL(eq) (ilog2(PAGE_IN_4K((eq)->page_size))) + +#define ELEMENT_SIZE_IN_32B(eq) (((eq)->elem_size) >> 5) +#define EQ_SET_HW_ELEM_SIZE_VAL(eq) (ilog2(ELEMENT_SIZE_IN_32B(eq))) + +#define EQ_MAX_PAGES8 + +#define aeq_to_aeqs(eq) \ + container_of((eq) - (eq)->q_id, struct hinic_aeqs, aeq[0]) + +#define work_to_aeq_work(work) \ + container_
[PATCH V6 06/21] net-next/hinic: Add api cmd commands
Add the api cmd commands for sending management messages to the nic. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- .../net/ethernet/huawei/hinic/hinic_hw_api_cmd.c | 329 - .../net/ethernet/huawei/hinic/hinic_hw_api_cmd.h | 65 drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h | 6 + 3 files changed, 398 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c index b44ddf2..d0145c6 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c @@ -25,7 +25,9 @@ #include #include #include +#include #include +#include #include "hinic_hw_csr.h" #include "hinic_hw_if.h" @@ -45,14 +47,313 @@ #define API_CMD_BUF_SIZE2048 +/* Sizes of the members in hinic_api_cmd_cell */ +#define API_CMD_CELL_DESC_SIZE 8 +#define API_CMD_CELL_DATA_ADDR_SIZE 8 + +#define API_CMD_CELL_ALIGNMENT 8 + #define API_CMD_TIMEOUT 1000 +#define MASKED_IDX(chain, idx) ((idx) & ((chain)->num_cells - 1)) + +#define SIZE_8BYTES(size) (ALIGN((size), 8) >> 3) +#define SIZE_4BYTES(size) (ALIGN((size), 4) >> 2) + +#define RD_DMA_ATTR_DEFAULT 0 +#define WR_DMA_ATTR_DEFAULT 0 + +enum api_cmd_data_format { + SGE_DATA = 1, /* cell data is passed by hw address */ +}; + +enum api_cmd_type { + API_CMD_WRITE = 0, +}; + +enum api_cmd_bypass { + NO_BYPASS = 0, + BYPASS = 1, +}; + enum api_cmd_xor_chk_level { XOR_CHK_DIS = 0, XOR_CHK_ALL = 3, }; +static u8 xor_chksum_set(void *data) +{ + int idx; + u8 *val, checksum = 0; + + val = data; + + for (idx = 0; idx < 7; idx++) + checksum ^= val[idx]; + + return checksum; +} + +static void set_prod_idx(struct hinic_api_cmd_chain *chain) +{ + enum hinic_api_cmd_chain_type chain_type = chain->chain_type; + struct hinic_hwif *hwif = chain->hwif; + u32 hw_prod_idx_addr, prod_idx; + + hw_prod_idx_addr = HINIC_CSR_API_CMD_CHAIN_PI_ADDR(chain_type); + prod_idx = hinic_hwif_read_reg(hwif, hw_prod_idx_addr); + + prod_idx = HINIC_API_CMD_PI_CLEAR(prod_idx, IDX); + + prod_idx |= HINIC_API_CMD_PI_SET(chain->prod_idx, IDX); + + hinic_hwif_write_reg(hwif, hw_prod_idx_addr, prod_idx); +} + +static u32 get_hw_cons_idx(struct hinic_api_cmd_chain *chain) +{ + u32 addr, val; + + addr = HINIC_CSR_API_CMD_STATUS_ADDR(chain->chain_type); + val = hinic_hwif_read_reg(chain->hwif, addr); + + return HINIC_API_CMD_STATUS_GET(val, CONS_IDX); +} + +/** + * chain_busy - check if the chain is still processing last requests + * @chain: chain to check + * + * Return 0 - Success, negative - Failure + **/ +static int chain_busy(struct hinic_api_cmd_chain *chain) +{ + struct hinic_hwif *hwif = chain->hwif; + struct pci_dev *pdev = hwif->pdev; + u32 prod_idx; + + switch (chain->chain_type) { + case HINIC_API_CMD_WRITE_TO_MGMT_CPU: + chain->cons_idx = get_hw_cons_idx(chain); + prod_idx = chain->prod_idx; + + /* check for a space for a new command */ + if (chain->cons_idx == MASKED_IDX(chain, prod_idx + 1)) { + dev_err(&pdev->dev, "API CMD chain %d is busy\n", + chain->chain_type); + return -EBUSY; + } + break; + + default: + dev_err(&pdev->dev, "Unknown API CMD Chain type\n"); + break; + } + + return 0; +} + +/** + * get_cell_data_size - get the data size of a specific cell type + * @type: chain type + * + * Return the data(Desc + Address) size in the cell + **/ +static u8 get_cell_data_size(enum hinic_api_cmd_chain_type type) +{ + u8 cell_data_size = 0; + + switch (type) { + case HINIC_API_CMD_WRITE_TO_MGMT_CPU: + cell_data_size = ALIGN(API_CMD_CELL_DESC_SIZE + + API_CMD_CELL_DATA_ADDR_SIZE, + API_CMD_CELL_ALIGNMENT); + break; + default: + break; + } + + return cell_data_size; +} + +/** + * prepare_cell_ctrl - prepare the ctrl of the cell for the command + * @cell_ctrl: the control of the cell to set the control value into it + * @data_size: the size of the data in the cell + **/ +static void prepare_cell_ctrl(u64 *cell_ctrl, u16 data_size) +{ + u8 chksum; + u64 ctrl; + + ctrl = HINIC_API_CMD_CELL_CTRL_SET(SIZE_8BYTES(data_size), DATA_SZ) | + HINIC_API_CMD_CELL_CTRL_SET(RD_DMA_ATTR_DEFAULT, RD_DMA_ATTR) | + HINIC_API_CMD_CELL_CTRL_SET(WR_DMA_ATTR_DEFAULT, WR_DMA_ATTR); + + chksum = xor_chks
[PATCH V6 03/21] net-next/hinic: Initialize api cmd resources
Initialize api cmd resources as part of management initialization. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- drivers/net/ethernet/huawei/hinic/Makefile | 4 +- .../net/ethernet/huawei/hinic/hinic_hw_api_cmd.c | 446 + .../net/ethernet/huawei/hinic/hinic_hw_api_cmd.h | 102 + drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c | 10 + drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h | 3 + 5 files changed, 563 insertions(+), 2 deletions(-) create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.h diff --git a/drivers/net/ethernet/huawei/hinic/Makefile b/drivers/net/ethernet/huawei/hinic/Makefile index 717ad71..beba90a 100644 --- a/drivers/net/ethernet/huawei/hinic/Makefile +++ b/drivers/net/ethernet/huawei/hinic/Makefile @@ -1,4 +1,4 @@ obj-$(CONFIG_HINIC) += hinic.o -hinic-y := hinic_main.o hinic_hw_dev.o hinic_hw_mgmt.o hinic_hw_eqs.o \ - hinic_hw_if.o +hinic-y := hinic_main.o hinic_hw_dev.o hinic_hw_mgmt.o hinic_hw_api_cmd.o \ + hinic_hw_eqs.o hinic_hw_if.o diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c new file mode 100644 index 000..4291f8e --- /dev/null +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c @@ -0,0 +1,446 @@ +/* + * Huawei HiNIC PCI Express Linux driver + * Copyright(c) 2017 Huawei Technologies Co., Ltd + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hinic_hw_if.h" +#include "hinic_hw_api_cmd.h" + +#define API_CHAIN_NUM_CELLS 32 + +#define API_CMD_CELL_SIZE_SHIFT 6 +#define API_CMD_CELL_SIZE_MIN (BIT(API_CMD_CELL_SIZE_SHIFT)) + +#define API_CMD_CELL_SIZE(cell_size)\ + (((cell_size) >= API_CMD_CELL_SIZE_MIN) ? \ +(1 << (fls(cell_size - 1))) : API_CMD_CELL_SIZE_MIN) + +#define API_CMD_BUF_SIZE2048 + +/** + * api_cmd_chain_hw_init - initialize the chain in the HW + * @chain: the API CMD specific chain to initialize in HW + * + * Return 0 - Success, negative - Failure + **/ +static int api_cmd_chain_hw_init(struct hinic_api_cmd_chain *chain) +{ + /* should be implemented */ + return 0; +} + +/** + * free_cmd_buf - free the dma buffer of API CMD command + * @chain: the API CMD specific chain of the cmd + * @cell_idx: the cell index of the cmd + **/ +static void free_cmd_buf(struct hinic_api_cmd_chain *chain, int cell_idx) +{ + struct hinic_api_cmd_cell_ctxt *cell_ctxt; + struct hinic_hwif *hwif = chain->hwif; + struct pci_dev *pdev = hwif->pdev; + + cell_ctxt = &chain->cell_ctxt[cell_idx]; + + dma_free_coherent(&pdev->dev, API_CMD_BUF_SIZE, + cell_ctxt->api_cmd_vaddr, + cell_ctxt->api_cmd_paddr); +} + +/** + * alloc_cmd_buf - allocate a dma buffer for API CMD command + * @chain: the API CMD specific chain for the cmd + * @cell: the cell in the HW for the cmd + * @cell_idx: the index of the cell + * + * Return 0 - Success, negative - Failure + **/ +static int alloc_cmd_buf(struct hinic_api_cmd_chain *chain, +struct hinic_api_cmd_cell *cell, int cell_idx) +{ + struct hinic_api_cmd_cell_ctxt *cell_ctxt; + struct hinic_hwif *hwif = chain->hwif; + struct pci_dev *pdev = hwif->pdev; + dma_addr_t cmd_paddr; + u8 *cmd_vaddr; + int err = 0; + + cmd_vaddr = dma_zalloc_coherent(&pdev->dev, API_CMD_BUF_SIZE, + &cmd_paddr, GFP_KERNEL); + if (!cmd_vaddr) { + dev_err(&pdev->dev, "Failed to allocate API CMD DMA memory\n"); + return -ENOMEM; + } + + cell_ctxt = &chain->cell_ctxt[cell_idx]; + + cell_ctxt->api_cmd_vaddr = cmd_vaddr; + cell_ctxt->api_cmd_paddr = cmd_paddr; + + /* set the cmd DMA address in the cell */ + switch (chain->chain_type) { + case HINIC_API_CMD_WRITE_TO_MGMT_CPU: + /* The data in the HW should be in Big Endian Format */ + cell->write.hw_cmd_paddr = cpu_to_be64(cmd_paddr); + break; + + default: + dev_err(&pdev->dev, "Unsupported API CMD chain type\n"); + free_cmd_buf(chain, cell_idx); + err = -EINVAL; + break; + } + +
[PATCH V6 05/21] net-next/hinic: Add management messages
Add the management messages for sending to api cmd and add the asynchronous event handler for the completion of the messages. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- .../net/ethernet/huawei/hinic/hinic_hw_api_cmd.c | 35 ++ .../net/ethernet/huawei/hinic/hinic_hw_api_cmd.h | 3 + drivers/net/ethernet/huawei/hinic/hinic_hw_if.h| 5 + drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c | 439 - drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h | 59 +++ 5 files changed, 538 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c index 234ede9..b44ddf2 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c @@ -54,6 +54,41 @@ enum api_cmd_xor_chk_level { }; /** + * api_cmd - API CMD command + * @chain: chain for the command + * @dest: destination node on the card that will receive the command + * @cmd: command data + * @size: the command size + * + * Return 0 - Success, negative - Failure + **/ +static int api_cmd(struct hinic_api_cmd_chain *chain, + enum hinic_node_id dest, u8 *cmd, u16 cmd_size) +{ + /* should be implemented */ + return -EINVAL; +} + +/** + * hinic_api_cmd_write - Write API CMD command + * @chain: chain for write command + * @dest: destination node on the card that will receive the command + * @cmd: command data + * @size: the command size + * + * Return 0 - Success, negative - Failure + **/ +int hinic_api_cmd_write(struct hinic_api_cmd_chain *chain, + enum hinic_node_id dest, u8 *cmd, u16 size) +{ + /* Verify the chain type */ + if (chain->chain_type == HINIC_API_CMD_WRITE_TO_MGMT_CPU) + return api_cmd(chain, dest, cmd, size); + + return -EINVAL; +} + +/** * api_cmd_hw_restart - restart the chain in the HW * @chain: the API CMD specific chain to restart * diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.h index 0c83b80..e8865d6 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.h @@ -132,6 +132,9 @@ struct hinic_api_cmd_chain { struct hinic_api_cmd_cell *curr_node; }; +int hinic_api_cmd_write(struct hinic_api_cmd_chain *chain, + enum hinic_node_id dest, u8 *cmd, u16 size); + int hinic_api_cmd_init(struct hinic_api_cmd_chain **chain, struct hinic_hwif *hwif); diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h index b6d9850..98623d6 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h @@ -93,6 +93,7 @@ #define HINIC_HWIF_NUM_IRQS(hwif) ((hwif)->attr.num_irqs) #define HINIC_HWIF_FUNC_IDX(hwif) ((hwif)->attr.func_idx) #define HINIC_HWIF_PCI_INTF(hwif) ((hwif)->attr.pci_intf_idx) +#define HINIC_HWIF_PF_IDX(hwif) ((hwif)->attr.pf_idx) #define HINIC_FUNC_TYPE(hwif) ((hwif)->attr.func_type) #define HINIC_IS_PF(hwif) (HINIC_FUNC_TYPE(hwif) == HINIC_PF) @@ -127,6 +128,10 @@ enum hinic_mod_type { HINIC_MOD_MAX = 15 }; +enum hinic_node_id { + HINIC_NODE_ID_MGMT = 21, +}; + struct hinic_func_attr { u16 func_idx; u8 pf_idx; diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c index f914bc7..147c404 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c @@ -16,6 +16,12 @@ #include #include #include +#include +#include +#include +#include +#include +#include #include "hinic_hw_if.h" #include "hinic_hw_eqs.h" @@ -23,9 +29,267 @@ #include "hinic_hw_mgmt.h" #include "hinic_hw_dev.h" +#define SYNC_MSG_ID_MASK0x1FF + +#define SYNC_MSG_ID(pf_to_mgmt) ((pf_to_mgmt)->sync_msg_id) + +#define SYNC_MSG_ID_INC(pf_to_mgmt) (SYNC_MSG_ID(pf_to_mgmt) = \ + ((SYNC_MSG_ID(pf_to_mgmt) + 1) & \ +SYNC_MSG_ID_MASK)) + +#define MSG_SZ_IS_VALID(in_size)((in_size) <= MAX_MSG_LEN) + +#define MGMT_MSG_LEN_MIN20 +#define MGMT_MSG_LEN_STEP 16 +#define MGMT_MSG_RSVD_FOR_DEV 8 + +#define SEGMENT_LEN 48 + +#define MAX_PF_MGMT_BUF_SIZE2048 + +/* Data should be SEG LEN size aligned */ +#define MAX_MSG_LEN 2016 + +#define MSG_NOT_RESP0x + +#define MGMT_MSG_TIMEOUT1000 + #define mgmt_to_pfhwdev(pf_mgmt)\ container_of(pf_mgmt, struct hinic_pfhwdev, pf_to_mgmt) +enu
[PATCH V6 00/21] Huawei HiNIC Ethernet Driver
The patch-set contains the support of the HiNIC Ethernet driver for hinic family of PCIE Network Interface Cards. The Huawei's PCIE HiNIC card is a new Ethernet card and hence there was a need of a new driver. The current driver is meant to be used for the Physical Function and there would soon be a support for Virtual Function and more features once the basic PF driver has been accepted. Changes V5 -> V6: 1. Fix cover letter Message-Id Changes V4 -> V5: 1. Remove select_queue NOP - David Miller comment https://lkml.org/lkml/2017/8/16/625 Changes V3 -> V4: 1. Reverse christmas tree order - David Miller comment https://lkml.org/lkml/2017/8/3/862 Changes V2 -> V3: 1. Replace dev_ functions by netif_ functions - Joe Perches comment https://lkml.org/lkml/2017/7/19/424 2. Fix the driver directory in MAINTAINERS file - Sergei Shtylyov comment https://lkml.org/lkml/2017/7/19/615 3. Add a newline at the end of Makefile - David Miller comment https://lkml.org/lkml/2017/7/19/1345 4. Return a pointer as a val instead of in arg - Francois Romieu comment https://lkml.org/lkml/2017/7/19/1319 5. Change the error labels to err_xyz - Francois Romieu comment https://lkml.org/lkml/2017/7/19/1319 6. Remove check of Func Type in free function - Francois Romieu comment https://lkml.org/lkml/2017/7/19/1319 7. Remove !netdev check in remove function - Francois Romieu comment https://lkml.org/lkml/2017/7/19/1319 8. Use module_pci_driver - Francois Romieu comment https://lkml.org/lkml/2017/7/19/1319 9. Move the PCI device ID to the .c file - Francois Romieu comment https://lkml.org/lkml/2017/7/19/1319 10. Remove void * to avoid passing wrong ptr - Francois Romieu comment https://lkml.org/lkml/2017/7/19/1319 Changes V1 -> V2: 1. remove driver verstion - Andrew Lunn comment https://lkml.org/lkml/2017/7/12/372 2. replace kzalloc by devm_kzalloc for short clean - Andrew Lunn comment https://lkml.org/lkml/2017/7/12/372 3. replace pr_ functions by dev_ functions - Andrew Lunn comment https://lkml.org/lkml/2017/7/12/375 4. seperate last patch by moving ops to a new patch - Andrew Lunn comment https://lkml.org/lkml/2017/7/12/377 Aviad Krawczyk (21): net-next/hinic: Initialize hw interface net-next/hinic: Initialize hw device components net-next/hinic: Initialize api cmd resources net-next/hinic: Initialize api cmd hw net-next/hinic: Add management messages net-next/hinic: Add api cmd commands net-next/hinic: Add aeqs net-next/hinic: Add port management commands net-next/hinic: Add Rx mode and link event handler net-next/hinic: Add logical Txq and Rxq net-next/hinic: Add wq net-next/hinic: Add qp resources net-next/hinic: Set qp context net-next/hinic: Initialize cmdq net-next/hinic: Add ceqs net-next/hinic: Add cmdq commands net-next/hinic: Add cmdq completion handler net-next/hinic: Add Rx handler net-next/hinic: Add Tx operation net-next/hinic: Add ethtool and stats net-next/hinic: Add netpoll Documentation/networking/hinic.txt | 125 +++ MAINTAINERS|7 + drivers/net/ethernet/Kconfig |1 + drivers/net/ethernet/Makefile |1 + drivers/net/ethernet/huawei/Kconfig| 19 + drivers/net/ethernet/huawei/Makefile |5 + drivers/net/ethernet/huawei/hinic/Kconfig | 13 + drivers/net/ethernet/huawei/hinic/Makefile |6 + drivers/net/ethernet/huawei/hinic/hinic_common.c | 80 ++ drivers/net/ethernet/huawei/hinic/hinic_common.h | 38 + drivers/net/ethernet/huawei/hinic/hinic_dev.h | 64 ++ .../net/ethernet/huawei/hinic/hinic_hw_api_cmd.c | 977 + .../net/ethernet/huawei/hinic/hinic_hw_api_cmd.h | 208 drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c | 946 + drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.h | 187 drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h | 149 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c | 1045 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h | 239 + drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c | 888 drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.h | 265 + drivers/net/ethernet/huawei/hinic/hinic_hw_if.c| 352 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_if.h| 272 + drivers/net/ethernet/huawei/hinic/hinic_hw_io.c| 533 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_io.h| 97 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c | 597 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h | 153 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c| 892 drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h| 180 .../net/ethernet/huawei/hinic/hinic_hw_qp_ctxt.h | 214 +++
[PATCH V6 04/21] net-next/hinic: Initialize api cmd hw
Update the hardware about api cmd resources and initialize it. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- .../net/ethernet/huawei/hinic/hinic_hw_api_cmd.c | 173 - .../net/ethernet/huawei/hinic/hinic_hw_api_cmd.h | 38 + drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h | 26 3 files changed, 236 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c index 4291f8e..234ede9 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c @@ -13,6 +13,7 @@ * */ +#include #include #include #include @@ -21,8 +22,12 @@ #include #include #include +#include +#include +#include #include +#include "hinic_hw_csr.h" #include "hinic_hw_if.h" #include "hinic_hw_api_cmd.h" @@ -35,8 +40,157 @@ (((cell_size) >= API_CMD_CELL_SIZE_MIN) ? \ (1 << (fls(cell_size - 1))) : API_CMD_CELL_SIZE_MIN) +#define API_CMD_CELL_SIZE_VAL(size) \ + ilog2((size) >> API_CMD_CELL_SIZE_SHIFT) + #define API_CMD_BUF_SIZE2048 +#define API_CMD_TIMEOUT 1000 + +enum api_cmd_xor_chk_level { + XOR_CHK_DIS = 0, + + XOR_CHK_ALL = 3, +}; + +/** + * api_cmd_hw_restart - restart the chain in the HW + * @chain: the API CMD specific chain to restart + * + * Return 0 - Success, negative - Failure + **/ +static int api_cmd_hw_restart(struct hinic_api_cmd_chain *chain) +{ + struct hinic_hwif *hwif = chain->hwif; + int err = -ETIMEDOUT; + unsigned long end; + u32 reg_addr, val; + + /* Read Modify Write */ + reg_addr = HINIC_CSR_API_CMD_CHAIN_REQ_ADDR(chain->chain_type); + val = hinic_hwif_read_reg(hwif, reg_addr); + + val = HINIC_API_CMD_CHAIN_REQ_CLEAR(val, RESTART); + val |= HINIC_API_CMD_CHAIN_REQ_SET(1, RESTART); + + hinic_hwif_write_reg(hwif, reg_addr, val); + + end = jiffies + msecs_to_jiffies(API_CMD_TIMEOUT); + do { + val = hinic_hwif_read_reg(hwif, reg_addr); + + if (!HINIC_API_CMD_CHAIN_REQ_GET(val, RESTART)) { + err = 0; + break; + } + + msleep(20); + } while (time_before(jiffies, end)); + + return err; +} + +/** + * api_cmd_ctrl_init - set the control register of a chain + * @chain: the API CMD specific chain to set control register for + **/ +static void api_cmd_ctrl_init(struct hinic_api_cmd_chain *chain) +{ + struct hinic_hwif *hwif = chain->hwif; + u32 reg_addr, ctrl; + u16 cell_size; + + /* Read Modify Write */ + reg_addr = HINIC_CSR_API_CMD_CHAIN_CTRL_ADDR(chain->chain_type); + + cell_size = API_CMD_CELL_SIZE_VAL(chain->cell_size); + + ctrl = hinic_hwif_read_reg(hwif, reg_addr); + + ctrl = HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, RESTART_WB_STAT) & + HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, XOR_ERR) & + HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, AEQE_EN) & + HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, XOR_CHK_EN) & + HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, CELL_SIZE); + + ctrl |= HINIC_API_CMD_CHAIN_CTRL_SET(1, XOR_ERR) | + HINIC_API_CMD_CHAIN_CTRL_SET(XOR_CHK_ALL, XOR_CHK_EN) | + HINIC_API_CMD_CHAIN_CTRL_SET(cell_size, CELL_SIZE); + + hinic_hwif_write_reg(hwif, reg_addr, ctrl); +} + +/** + * api_cmd_set_status_addr - set the status address of a chain in the HW + * @chain: the API CMD specific chain to set in HW status address for + **/ +static void api_cmd_set_status_addr(struct hinic_api_cmd_chain *chain) +{ + struct hinic_hwif *hwif = chain->hwif; + u32 addr, val; + + addr = HINIC_CSR_API_CMD_STATUS_HI_ADDR(chain->chain_type); + val = upper_32_bits(chain->wb_status_paddr); + hinic_hwif_write_reg(hwif, addr, val); + + addr = HINIC_CSR_API_CMD_STATUS_LO_ADDR(chain->chain_type); + val = lower_32_bits(chain->wb_status_paddr); + hinic_hwif_write_reg(hwif, addr, val); +} + +/** + * api_cmd_set_num_cells - set the number cells of a chain in the HW + * @chain: the API CMD specific chain to set in HW the number of cells for + **/ +static void api_cmd_set_num_cells(struct hinic_api_cmd_chain *chain) +{ + struct hinic_hwif *hwif = chain->hwif; + u32 addr, val; + + addr = HINIC_CSR_API_CMD_CHAIN_NUM_CELLS_ADDR(chain->chain_type); + val = chain->num_cells; + hinic_hwif_write_reg(hwif, addr, val); +} + +/** + * api_cmd_head_init - set the head of a chain in the HW + * @chain: the API CMD specific chain to set in HW the head for + **/ +static void api_cmd_head_init(struct hinic_api_cmd_chain *chain) +{ + struct hinic_hwif *hwif = chain->hwif; + u32 addr, val; + + addr = HINIC_C
[PATCH V6 01/21] net-next/hinic: Initialize hw interface
Initialize hw interface as part of the nic initialization for accessing hw. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- Documentation/networking/hinic.txt | 125 ++ drivers/net/ethernet/Kconfig | 1 + drivers/net/ethernet/Makefile| 1 + drivers/net/ethernet/huawei/Kconfig | 19 +++ drivers/net/ethernet/huawei/Makefile | 5 + drivers/net/ethernet/huawei/hinic/Kconfig| 13 ++ drivers/net/ethernet/huawei/hinic/Makefile | 3 + drivers/net/ethernet/huawei/hinic/hinic_dev.h| 33 drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h | 36 drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c | 201 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h | 42 + drivers/net/ethernet/huawei/hinic/hinic_hw_if.c | 208 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_if.h | 160 + drivers/net/ethernet/huawei/hinic/hinic_main.c | 195 + 14 files changed, 1042 insertions(+) create mode 100644 Documentation/networking/hinic.txt create mode 100644 drivers/net/ethernet/huawei/Kconfig create mode 100644 drivers/net/ethernet/huawei/Makefile create mode 100644 drivers/net/ethernet/huawei/hinic/Kconfig create mode 100644 drivers/net/ethernet/huawei/hinic/Makefile create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_dev.h create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_csr.h create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_if.c create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_hw_if.h create mode 100644 drivers/net/ethernet/huawei/hinic/hinic_main.c diff --git a/Documentation/networking/hinic.txt b/Documentation/networking/hinic.txt new file mode 100644 index 000..989366a --- /dev/null +++ b/Documentation/networking/hinic.txt @@ -0,0 +1,125 @@ +Linux Kernel Driver for Huawei Intelligent NIC(HiNIC) family + + +Overview: += +HiNIC is a network interface card for the Data Center Area. + +The driver supports a range of link-speed devices (10GbE, 25GbE, 40GbE, etc.). +The driver supports also a negotiated and extendable feature set. + +Some HiNIC devices support SR-IOV. This driver is used for Physical Function +(PF). + +HiNIC devices support MSI-X interrupt vector for each Tx/Rx queue and +adaptive interrupt moderation. + +HiNIC devices support also various offload features such as checksum offload, +TCP Transmit Segmentation Offload(TSO), Receive-Side Scaling(RSS) and +LRO(Large Receive Offload). + + +Supported PCI vendor ID/device IDs: +=== + +19e5:1822 - HiNIC PF + + +Driver Architecture and Source Code: + + +hinic_dev - Implement a Logical Network device that is independent from +specific HW details about HW data structure formats. + +hinic_hwdev - Implement the HW details of the device and include the components +for accessing the PCI NIC. + +hinic_hwdev contains the following components: +=== + +HW Interface: += + +The interface for accessing the pci device (DMA memory and PCI BARs). +(hinic_hw_if.c, hinic_hw_if.h) + +Configuration Status Registers Area that describes the HW Registers on the +configuration and status BAR0. (hinic_hw_csr.h) + +MGMT components: + + +Asynchronous Event Queues(AEQs) - The event queues for receiving messages from +the MGMT modules on the cards. (hinic_hw_eqs.c, hinic_hw_eqs.h) + +Application Programmable Interface commands(API CMD) - Interface for sending +MGMT commands to the card. (hinic_hw_api_cmd.c, hinic_hw_api_cmd.h) + +Management (MGMT) - the PF to MGMT channel that uses API CMD for sending MGMT +commands to the card and receives notifications from the MGMT modules on the +card by AEQs. Also set the addresses of the IO CMDQs in HW. +(hinic_hw_mgmt.c, hinic_hw_mgmt.h) + +IO components: +== + +Completion Event Queues(CEQs) - The completion Event Queues that describe IO +tasks that are finished. (hinic_hw_eqs.c, hinic_hw_eqs.h) + +Work Queues(WQ) - Contain the memory and operations for use by CMD queues and +the Queue Pairs. The WQ is a Memory Block in a Page. The Block contains +pointers to Memory Areas that are the Memory for the Work Queue Elements(WQEs). +(hinic_hw_wq.c, hinic_hw_wq.h) + +Command Queues(CMDQ) - The queues for sending commands for IO management and is +used to set the QPs addresses in HW. The commands completion events are +accumulated on the CEQ that is configured to receive the CMDQ completion events. +(hinic_hw_cmdq.c, hinic_hw_cmdq.h) + +Queue Pairs(QPs) - The HW Receive and Send queues for Receiving and Transmitting +Data. (hinic_hw_qp.c, hini
Re: [net-next PATCH 07/10] bpf: add access to sock fields and pkt data from sk_skb programs
On 08/17/2017 07:42 AM, Alexei Starovoitov wrote: On 8/15/17 10:33 PM, John Fastabend wrote: +static int sk_skb_prologue(struct bpf_insn *insn_buf, bool direct_write, + const struct bpf_prog *prog) +{ +struct bpf_insn *insn = insn_buf; + +if (!direct_write) +return 0; + +/* if (!skb->cloned) + * goto start; + * + * (Fast-path, otherwise approximation that we might be + * a clone, do the rest in helper.) + */ iirc we're doing something similar in other prologue generator? can be consolidated? Jup, with tc. I'll fix this one so the two can be consolidated. Cheers, Daniel
Re: [PATCH net] PCI: fix the return value for the pci_find_pcie_root_port()
On 2017/8/17 18:51, Thierry Reding wrote: > On Thu, Aug 17, 2017 at 10:25:30AM +0800, Ding Tianhong wrote: >> The pci_find_pcie_root_port() would return NULL if the given >> dev is already a Root Port, it looks like unfriendly to the >> PCIe Root Port device, Thierry and Bjorn suggest to let this >> function return the given dev under this circumstances. >> >> Fixes: 0e405232871d6 ("PCI: fix oops when try to find Root Port for a PCI >> device") >> Suggested-by: Thierry Reding >> Suggested-by: Bjorn Helgaas >> Signed-off-by: Thierry Reding >> Signed-off-by: Ding Tianhong >> --- >> drivers/pci/pci.c | 2 +- >> 1 file changed, 1 insertion(+), 1 deletion(-) >> >> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c >> index 7e2022f..352bb53 100644 >> --- a/drivers/pci/pci.c >> +++ b/drivers/pci/pci.c >> @@ -514,7 +514,7 @@ struct resource *pci_find_resource(struct pci_dev *dev, >> struct resource *res) >> */ >> struct pci_dev *pci_find_pcie_root_port(struct pci_dev *dev) >> { >> -struct pci_dev *bridge, *highest_pcie_bridge = NULL; >> +struct pci_dev *bridge, *highest_pcie_bridge = dev; >> >> bridge = pci_upstream_bridge(dev); >> while (bridge && pci_is_pcie(bridge)) { > > I think this should actually be this change on top of a revert of commit > 0e405232871d6 ("PCI: fix oops when try to find Root Port for a PCI > device"). After the above change, the previous fix will have a redundant > check because highest_pcie_bridge will never be NULL. > > Let me send out that version to clarify what I mean. > Hi Thierry: The patch ("PCI: fix oops when try to find Root Port for a PCI device") has been merge to the linus mainline tree before you found this deficiencies Regards Tianhong > Thierry >
Re: [PATCH net-next 2/3] vsock: fix vsock_dequeue/enqueue_accept race
> On Aug 16, 2017, at 12:15 AM, Dexuan Cui wrote: > > > With the current code, when vsock_dequeue_accept() is removing a sock > from the list, nothing prevents vsock_enqueue_accept() from adding a new > sock into the list concurrently. We should add a lock to protect the list. > For the VMCI socket transport, we always lock the sockets before calling into vsock_enqueue_accept and af_vsock.c locks the socket before calling vsock_dequeue_accept, so from our point of view these operations are already protected, but with finer granularity than a single global lock. As far as I can see, the virtio transport also locks the socket before calling vsock_enqueue_accept, so they should be fine with the current version as well, but Stefan can comment on that. Thanks, Jorgen
Re: [PATCH net] net: sched: fix NULL pointer dereference when action calls some targets
On Thu, Aug 17, 2017 at 11:24:00PM +1200, Xin Long wrote: > On Thu, Aug 17, 2017 at 10:33 PM, Pablo Neira Ayuso > wrote: > > On Thu, Aug 17, 2017 at 12:02:20PM +0200, Pablo Neira Ayuso wrote: > >> On Wed, Aug 16, 2017 at 08:39:44PM +1200, Xin Long wrote: > >> > On Wed, Aug 9, 2017 at 7:33 AM, Cong Wang > >> > wrote: > >> > > On Mon, Aug 7, 2017 at 7:33 PM, Xin Long wrote: > >> > >> On Tue, Aug 8, 2017 at 9:15 AM, Cong Wang > >> > >> wrote: > >> > >>> This looks like a completely API burden? > >> > >> netfilter xt targets are not really compatible with netsched action. > >> > >> I've got to say, the patch is just a way to make checkentry return > >> > >> false and avoid panic. like [1] said > >> > > > >> > > I don't doubt you fix a crash, I am thinking if we can > >> > > "fix" the API instead of fixing the caller. > >> > Hi, Cong, > >> > > >> > For now, I don't think it's possible to change APIs or some of their > >> > targets > >> > for the panic caused by action xt calling. > >> > > >> > The common way should be fixed in net_sched side. > >> > > >> > Given that the issue is very easy to triggered, > >> > let's wait for netfilter's replies for another few days, > >> > otherwise I will repost the fix, agree ? > >> > >> Please, post the workaround so the kernel doesn't crash anymore. > >> > >> This is going to be very hard to fix, it's broken since the very > >> beginning... > > > > Wait a second, you could rename par->nft_compat to par->no_entry. From > > net/sched/ you can set this to 1, so the entry checks are ignored. > > > > I'm refering to patch 55917a21d0cc0 > > par->nft_compat wasn't used to ignore the entry checks, if we rename it > as no_entry, some other targets still needs to update. like the ones in > this patch's changelog: > ECN: ecn_tg_check() > TPROXY: tproxy_tg4_check() > > which means these two checks will be ignored for nft as well, that is > not what we want. > As nft has e4.ip.proto and e4.ip.invflags being set which net/sched > gets nothing. they are still different. I see, then just fix this crash. It's been known among people that the number of extensions that act_ipt supports is limited. Thanks.
Re: [PATCH 1/6] bridge: learn dst metadata in FDB
On Thu, Aug 17, 2017 at 02:39:43PM +0300, Nikolay Aleksandrov wrote: > On 17/08/17 14:03, David Lamparter wrote: > > On Wed, Aug 16, 2017 at 11:38:06PM +0300, Nikolay Aleksandrov wrote: > >> On 16/08/17 20:01, David Lamparter wrote: > >> and hitting the fast path for everyone in a few different places for a > >> feature that the majority will not use does not sound acceptable to > >> me. We've been trying hard to optimize it, trying to avoid additional > >> cache lines, removing tests and keeping special cases to a minimum. > > > > skb->dst is on the same cacheline as skb->len. > > fdb->md_dst is on the same cacheline as fdb->dst. > > Both will be 0 in a lot of cases, so this should be two null checks on > > data that is hot in the cache. Are you sure this is an actual problem? > > > > Sure - no, I haven't benchmarked it, but I don't see skb->len being on > the same cache line as _skb_refdst assuming 64 byte cache lines. > But again any special cases, in my opinion, should be handled on their own, > it is both about the fast path and the code complexity that they bring in. (separate thread) [cut] > > I really hope you're not suggesting the entire MDB with IPv4 & IPv6 > > snooping be duplicated into both VPLS and mac80211? > > Code can always be shared if there are more users, no need to stuff > everything in the bridge, The MDB code is far from trivial, has several configuration knobs, and even sends its own queries if configured to do so. It can also use quite a bit of memory of there's a nontrivial number of multicast groups. I *really* think it shouldn't be duplicated. > but I'm not that familiar with this case, once patches are out I can > comment further. I've pushed my hacks to: https://github.com/eqvinox/vpls-linux-kernel/commits/mdb-hack (top two commits) THIS IS ABSOLUTELY A PROOF OF CONCEPT. It doesn't un-learn dst metadata, it probably leaks buckets, and it may kill your cat. (I haven't pushed my attempts at mac80211, because I haven't gotten anywhere useful there just yet.) > >> As you've noted this is only an RFC so I will not point out every issue, > >> but there seems > >> to be a major problem with br_fdb_update(), note that it runs without any > >> locks except RCU. > > > > Right, Thanks! ... I only thought about concurrent access, forgetting > > about concurrent modification... I'll replace it with an xchg I think. > > (No need for a lock that way) > > I think you can still lose references to a dst that way, what if someone > changes the > dst you read before the xchg and you xchg it ? The dst to be released is the return from (atomic) xchg, not the value read earlier for comparison. This can happen in parallel, but apart from a little extra churn in the update case it has no ill effects. If someone changes it in the meantime, they have new dst information for the fdb entry, and so do we. With xchg'ing it, either one of the updates will stick and the other will be properly released. Considering that there is no correct ordering here (either packet could be processed a nanosecond later or earlier), this is perfectly fine as an outcome. -David
Re: [PATCH V4 net-next 21/21] net-next/hinic: Add select_queue and netpoll
Hi David, Fixed in V6. In V5 patch-set there was a problem in cover-letter msg-id. Thanks, Aviad On 8/16/2017 9:47 PM, David Miller wrote: > From: Aviad Krawczyk > Date: Wed, 16 Aug 2017 20:03:06 +0800 > >> +static u16 hinic_select_queue(struct net_device *netdev, struct sk_buff >> *skb, >> + void *accel_priv, >> + select_queue_fallback_t fallback) >> +{ >> +u16 qid; >> + >> +if (skb_rx_queue_recorded(skb)) >> +qid = skb_get_rx_queue(skb); >> +else >> +qid = fallback(netdev, skb); >> + >> +return qid; >> +} > > This is a NOP, do not implement this function unless you absolutely need to > do something custom in your driver, and you do not. > > . >
Re: 100% CPU load when generating traffic to destination network that nexthop is not reachable
Hi Wondering if someone have idea how to optimise this ? From reali life perspective it is really important for optimising this behavior cause imagine situation - just normal situation with linux acting as a router: Lets say we have Linux router with connected 3 customers and one upstream - and have some situation with ddos 1. There is comming ddos traffic from upstream (and lets say we are handling this ddos on our forwarding router with 50% cpu load) to our router and router is forwarding this traffic to some customer (remember we have 3 customers - one is getting ddos now dirested to some of his ip) 2. Customer X is getting ddos - his router is 100% cpu load (cause low end hardware or 100% load on up-link. 3. Customer X router is not responding or some watchdog restarted it - or customer X disabled router for security reasons 4. After fdb expires on our service router - two other customers start to have problems cause our router goes from 50% to 100% on all cores - and everybody experiencing now packet drops and bandwidth drops And this does'nt need to be ddos - it can be many servers connected by linux router and one server will push some udp stream (iptv or other filesystem syncing protocol) to the other via forwarding linux router - if receiving server will goes down and dissapear from arp all other streams that are forwarded by linux router will suffer from this. W dniu 2017-08-16 o 12:07, Paweł Staszewski pisze: Hi Patch applied - but no big change - from 0.7Mpps per vlan to 1.2Mpps per vlan previously(without patch) 100% cpu load: bwm-ng v0.6.1 (probing every 0.500s), press 'h' for help input: /proc/net/dev type: rate | iface Rx TxTotal == vlan1002:0.00 P/s 1.99 P/s 1.99 P/s vlan1001:0.00 P/s717227.12 P/s 717227.12 P/s enp175s0f0: 2713679.25 P/s 0.00 P/s 2713679.25 P/s vlan1000:0.00 P/s716145.44 P/s 716145.44 P/s -- total: 2713679.25 P/s 1433374.50 P/s 4147054.00 P/s With patch (100% cpu load a little better pps performance) bwm-ng v0.6.1 (probing every 1.000s), press 'h' for help input: /proc/net/dev type: rate | iface Rx TxTotal == vlan1002:0.00 P/s 1.00 P/s 1.00 P/s vlan1001:0.00 P/s 1202161.50 P/s 1202161.50 P/s enp175s0f0: 3699864.50 P/s 0.00 P/s 3699864.50 P/s vlan1000:0.00 P/s 1196870.38 P/s 1196870.38 P/s -- total: 3699864.50 P/s 2399033.00 P/s 6098897.50 P/s perf top attached below: 1.90% 0.00% ksoftirqd/39[kernel.vmlinux] [k] run_ksoftirqd | --1.90%--run_ksoftirqd | --1.90%--__softirqentry_text_start | --1.90%--net_rx_action | --1.90%--mlx5e_napi_poll | --1.89%--mlx5e_poll_rx_cq | --1.88%--mlx5e_handle_rx_cqe | --1.85%--napi_gro_receive | --1.85%--netif_receive_skb_internal | --1.85%--__netif_receive_skb | --1.85%--__netif_receive_skb_core | --1.85%--ip_rcv | --1.85%--ip_rcv_finish | --1.83%--ip_forward | --1.82%--ip_forward_finish | --1.82%--ip_output | --1.82%--ip_finish_output | --1.82%--ip_finish_output2 | --1.79%--neigh_resolve_output | --1.77%--neigh_event_send | --1.77%--__neigh_event_send | --1.74%--_raw_write_lock_bh | --1.74%--queued_write_lock queued_write_lock_slowpath | --1.70%--queued_spin_lock_slowpath 1.90% 0.00% ksoftirqd/34[kernel.vmlinux] [k] __softirqentry_text_start | ---__softirqentry_text_start | --1.90%--net_rx_action | --1.90%--mlx5e_napi_poll | --1.89%--mlx5e_poll_rx_cq | --1.88%--mlx5e_handle_rx_cqe | --1.86%--napi_gro_receive | --1.85%--netif_receive_skb_internal | --1.85%--__netif_receive_skb | --1.85%--__netif_receive_skb_core | --1.85%--ip_rcv | --1.85%--ip_rcv_finish | --1.83%--ip_forward | --1.82%--ip_forward_finish | --1.82%--ip_output | --1.82%--ip_finish_output | --1.82%--ip_finish
Re: [PATCH V6 21/21] net-next/hinic: Add netpoll
Hello. On 08/17/2017 03:25 PM, Aviad Krawczyk wrote: Add more netdev operation - netpoll. Signed-off-by: Aviad Krawczyk Signed-off-by: Zhao Chen --- MAINTAINERS| 7 +++ drivers/net/ethernet/huawei/hinic/hinic_main.c | 20 2 files changed, 27 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 0e967b3..8f9ea9b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6240,6 +6240,13 @@ L: linux-in...@vger.kernel.org S:Maintained F:drivers/input/touchscreen/htcpen.c +HUAWEI ETHERNET DRIVER +M: Aviad Krawczyk +L: netdev@vger.kernel.org +S: Supported +F: Documentation/networking/hinic.txt +F: drivers/net/ethernet/huawei/hinic/ + Sorry for not asking this question before: how is the new MAINTAINERS record related to the netpoll support? This should be in a separate patch. [...] MBR, Sergei
[PATCH net-next] bpf: fix liveness propagation to parent in spilled stack slots
Using parent->regs[] when propagating REG_LIVE_READ for spilled regs doesn't work since parent->regs[] denote the set of normal registers but not spilled ones. Propagate to the correct regs. Fixes: dc503a8ad984 ("bpf/verifier: track liveness for pruning") Reported-by: Dan Carpenter Signed-off-by: Daniel Borkmann Acked-by: Edward Cree --- kernel/bpf/verifier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 958ba84..40f669d 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -3460,7 +3460,7 @@ static bool do_propagate_liveness(const struct bpf_verifier_state *state, if (parent->spilled_regs[i].live & REG_LIVE_READ) continue; if (state->spilled_regs[i].live == REG_LIVE_READ) { - parent->regs[i].live |= REG_LIVE_READ; + parent->spilled_regs[i].live |= REG_LIVE_READ; touched = true; } } -- 1.9.3
Re: [PATCH V6 21/21] net-next/hinic: Add netpoll
Will be fixed in V7 Thanks On 8/17/2017 3:57 PM, Sergei Shtylyov wrote: > Hello. > > On 08/17/2017 03:25 PM, Aviad Krawczyk wrote: > >> Add more netdev operation - netpoll. >> >> Signed-off-by: Aviad Krawczyk >> Signed-off-by: Zhao Chen >> --- >> MAINTAINERS| 7 +++ >> drivers/net/ethernet/huawei/hinic/hinic_main.c | 20 >> 2 files changed, 27 insertions(+) >> >> diff --git a/MAINTAINERS b/MAINTAINERS >> index 0e967b3..8f9ea9b 100644 >> --- a/MAINTAINERS >> +++ b/MAINTAINERS >> @@ -6240,6 +6240,13 @@ L:linux-in...@vger.kernel.org >> S:Maintained >> F:drivers/input/touchscreen/htcpen.c >> +HUAWEI ETHERNET DRIVER >> +M:Aviad Krawczyk >> +L:netdev@vger.kernel.org >> +S:Supported >> +F:Documentation/networking/hinic.txt >> +F:drivers/net/ethernet/huawei/hinic/ >> + > >Sorry for not asking this question before: how is the new MAINTAINERS > record related to the netpoll support? This should be in a separate patch. > > [...] > > MBR, Sergei > > . >
Re: [PATCH 1/6] bridge: learn dst metadata in FDB
On 17/08/17 15:45, David Lamparter wrote: > On Thu, Aug 17, 2017 at 02:39:43PM +0300, Nikolay Aleksandrov wrote: >> On 17/08/17 14:03, David Lamparter wrote: >>> On Wed, Aug 16, 2017 at 11:38:06PM +0300, Nikolay Aleksandrov wrote: On 16/08/17 20:01, David Lamparter wrote: and hitting the fast path for everyone in a few different places for a feature that the majority will not use does not sound acceptable to me. We've been trying hard to optimize it, trying to avoid additional cache lines, removing tests and keeping special cases to a minimum. >>> >>> skb->dst is on the same cacheline as skb->len. >>> fdb->md_dst is on the same cacheline as fdb->dst. >>> Both will be 0 in a lot of cases, so this should be two null checks on >>> data that is hot in the cache. Are you sure this is an actual problem? >>> >> >> Sure - no, I haven't benchmarked it, but I don't see skb->len being on >> the same cache line as _skb_refdst assuming 64 byte cache lines. >> But again any special cases, in my opinion, should be handled on their own, >> it is both about the fast path and the code complexity that they bring in. > > (separate thread) > > [cut] >>> I really hope you're not suggesting the entire MDB with IPv4 & IPv6 >>> snooping be duplicated into both VPLS and mac80211? >> >> Code can always be shared if there are more users, no need to stuff >> everything in the bridge, > > The MDB code is far from trivial, has several configuration knobs, and > even sends its own queries if configured to do so. It can also use > quite a bit of memory of there's a nontrivial number of multicast > groups. I *really* think it shouldn't be duplicated. > >> but I'm not that familiar with this case, once patches are out I can >> comment further. > > I've pushed my hacks to: > https://github.com/eqvinox/vpls-linux-kernel/commits/mdb-hack > (top two commits) > > THIS IS ABSOLUTELY A PROOF OF CONCEPT. It doesn't un-learn dst > metadata, it probably leaks buckets, and it may kill your cat. > (I haven't pushed my attempts at mac80211, because I haven't gotten > anywhere useful there just yet.) > As you've noted this is only an RFC so I will not point out every issue, but there seems to be a major problem with br_fdb_update(), note that it runs without any locks except RCU. >>> >>> Right, Thanks! ... I only thought about concurrent access, forgetting >>> about concurrent modification... I'll replace it with an xchg I think. >>> (No need for a lock that way) >> >> I think you can still lose references to a dst that way, what if someone >> changes the >> dst you read before the xchg and you xchg it ? > > The dst to be released is the return from (atomic) xchg, not the value > read earlier for comparison. This can happen in parallel, but apart > from a little extra churn in the update case it has no ill effects. > > If someone changes it in the meantime, they have new dst information for > the fdb entry, and so do we. With xchg'ing it, either one of the > updates will stick and the other will be properly released. Considering > that there is no correct ordering here (either packet could be processed > a nanosecond later or earlier), this is perfectly fine as an outcome. Yep right you are, my bad. > > > -David >
[PATCH net-next] bpf: no need to nullify ri->map in xdp_do_redirect
We are guaranteed to have a NULL ri->map in this branch since we test for it earlier, so we don't need to reset it here. Signed-off-by: Daniel Borkmann --- net/core/filter.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/core/filter.c b/net/core/filter.c index e9f8dce..ea3ca34 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -2568,7 +2568,6 @@ int xdp_do_redirect(struct net_device *dev, struct xdp_buff *xdp, fwd = dev_get_by_index_rcu(dev_net(dev), index); ri->ifindex = 0; - ri->map = NULL; if (unlikely(!fwd)) { bpf_warn_invalid_xdp_redirect(index); return -EINVAL; -- 1.9.3
LL,
Dear friend, I am Barrister Wilson, I want you to work with me as a foreign partner also as family members or close relatives to my late client who deposited USD$14.3Million dollars in a bank here my country before his death, and a nationality of your country, The bank has given me notice as his Lawyer who sign and witness everything to present the next of kin of the fund or the money will be confiscated if i fail, I need your immediate reply to enable me send more Detailed information about this project to you. Thanks Danis Wilson.
Re: TCP fast retransmit issues
On 28/07/17 08:27, Willy Tarreau wrote: > I didn't want to suggest names but since you did it first ;-) Indeed it's > mostly on the same device that I've been bothered a lot by their annoying > randomization. I used to know by memory the exact command to type to disable > it, but I don't anymore (something along "no randomization"). https://supportforums.cisco.com/document/48551/single-tcp-flow-performance-firewall-services-module-fwsm#TCP_Sequence_Number_Randomization_and_SACK https://supportcenter.checkpoint.com/supportcenter/portal?eventSubmit_doGoviewsolutiondetails=&solutionid=sk74640 -- Cheers, Jeremy
[PATCH] net: ibm: ibmvnic: constify vio_device_id
vio_device_id are not supposed to change at runtime. All functions working with vio_device_id provided by work with const vio_device_id. So mark the non-const structs as const. Signed-off-by: Arvind Yadav --- drivers/net/ethernet/ibm/ibmvnic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index a3e6946..d5372b5 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -3859,7 +3859,7 @@ static int ibmvnic_resume(struct device *dev) return 0; } -static struct vio_device_id ibmvnic_device_table[] = { +static const struct vio_device_id ibmvnic_device_table[] = { {"network", "IBM,vnic"}, {"", "" } }; -- 2.7.4