forked from TencentOS/TencentOS-kernel
driver: update bnxt_en driver to 1.10.1-216.1.92.0
Signed-off-by: Zhiping Du <zhipingdu@tencent.com>
This commit is contained in:
parent
b0e23ef723
commit
4a019c19d4
|
|
@ -0,0 +1,339 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that 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.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,3 +1,871 @@
|
|||
obj-$(CONFIG_BNXT) += bnxt_en.o
|
||||
#!/usr/bin/make
|
||||
# Makefile for building Linux Broadcom Gigabit ethernet driver as a module.
|
||||
# $id$
|
||||
KVER=
|
||||
ifeq ($(KVER),)
|
||||
KVER=$(shell uname -r)
|
||||
endif
|
||||
|
||||
bnxt_en-y := bnxt.o bnxt_sriov.o bnxt_ethtool.o bnxt_dcb.o bnxt_ulp.o bnxt_xdp.o bnxt_vfr.o bnxt_tc.o
|
||||
__ARCH=$(shell uname -m)
|
||||
|
||||
# PREFIX may be set by the RPM build to set the effective root.
|
||||
PREFIX=
|
||||
ifeq ($(shell ls /lib/modules/$(KVER)/build > /dev/null 2>&1 && echo build),)
|
||||
# SuSE source RPMs
|
||||
_KVER=$(shell echo $(KVER) | cut -d "-" -f1,2)
|
||||
_KFLA=$(shell echo $(KVER) | cut -d "-" -f3)
|
||||
_ARCH=$(shell file -b /lib/modules/$(shell uname -r)/build | cut -d "/" -f5)
|
||||
ifeq ($(_ARCH),)
|
||||
_ARCH=$(__ARCH)
|
||||
endif
|
||||
ifeq ($(shell ls /usr/src/linux-$(_KVER)-obj > /dev/null 2>&1 && echo linux),)
|
||||
ifeq ($(shell ls /usr/src/kernels/$(KVER)-$(__ARCH) > /dev/null 2>&1 && echo linux),)
|
||||
LINUX=
|
||||
else
|
||||
LINUX=/usr/src/kernels/$(KVER)-$(__ARCH)
|
||||
LINUXSRC=$(LINUX)
|
||||
endif
|
||||
else
|
||||
LINUX=/usr/src/linux-$(_KVER)-obj/$(_ARCH)/$(_KFLA)
|
||||
LINUXSRC=/usr/src/linux-$(_KVER)
|
||||
endif
|
||||
else
|
||||
LINUX=/lib/modules/$(KVER)/build
|
||||
ifeq ($(shell ls /lib/modules/$(KVER)/source > /dev/null 2>&1 && echo source),)
|
||||
LINUXSRC=$(LINUX)
|
||||
else
|
||||
LINUXSRC=/lib/modules/$(KVER)/source
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(KDIR),)
|
||||
LINUX=$(KDIR)
|
||||
LINUXSRC=$(LINUX)
|
||||
endif
|
||||
|
||||
ifeq ($(shell ls $(LINUXSRC)/include/uapi/linux > /dev/null 2>&1 && echo uapi),)
|
||||
UAPI=
|
||||
else
|
||||
UAPI=uapi
|
||||
endif
|
||||
|
||||
ifeq ($(BCMMODDIR),)
|
||||
ifeq ($(shell ls /lib/modules/$(KVER)/updates > /dev/null 2>&1 && echo 1),1)
|
||||
BCMMODDIR=/lib/modules/$(KVER)/updates
|
||||
else
|
||||
ifeq ($(shell grep -q "search.*[[:space:]]updates" /etc/depmod.conf > /dev/null 2>&1 && echo 1),1)
|
||||
BCMMODDIR=/lib/modules/$(KVER)/updates
|
||||
else
|
||||
ifeq ($(shell grep -q "search.*[[:space:]]updates" /etc/depmod.d/* > /dev/null 2>&1 && echo 1),1)
|
||||
BCMMODDIR=/lib/modules/$(KVER)/updates
|
||||
else
|
||||
BCMMODDIR=/lib/modules/$(KVER)/kernel/drivers/net
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "pci_enable_msix_range" $(LINUXSRC)/include/linux/pci.h),)
|
||||
DISTRO_CFLAG = -DHAVE_MSIX_RANGE
|
||||
else
|
||||
DISTRO_CFLAG =
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "msix_cap" $(LINUXSRC)/include/linux/pci.h),)
|
||||
ifeq ($(shell grep -o "pci_dev_rh1" $(LINUXSRC)/include/linux/pci.h),)
|
||||
DISTRO_CFLAG += -DHAVE_MSIX_CAP
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "module_pci_driver" $(LINUXSRC)/include/linux/pci.h),)
|
||||
DISTRO_CFLAG += -DHAVE_MODULE_PCI_DRIVER
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -so "GENL_ID_GENERATE" $(LINUXSRC)/include/uapi/linux/genetlink.h),)
|
||||
DISTRO_CFLAG += -DHAVE_GENL_ID_GENERATE
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep "genl_register_family_with_ops" $(LINUXSRC)/include/net/genetlink.h),)
|
||||
DISTRO_CFLAG += -DHAVE_GENL_REG_FAMILY_WITH_OPS
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -A 8 "genl_family {" $(LINUXSRC)/include/net/genetlink.h | grep -o "struct nla_policy"),)
|
||||
DISTRO_CFLAG += -DHAVE_GENL_POLICY
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep "hlist_for_each_entry_safe" $(LINUXSRC)/include/linux/list.h | grep "tpos" > /dev/null 2>&1 && echo tpos),)
|
||||
DISTRO_CFLAG += -DHAVE_OLD_HLIST
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "csum_level" $(LINUXSRC)/include/linux/skbuff.h),)
|
||||
DISTRO_CFLAG += -DHAVE_CSUM_LEVEL
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "build_skb" $(LINUXSRC)/include/linux/skbuff.h),)
|
||||
DISTRO_CFLAG += -DHAVE_BUILD_SKB
|
||||
ifneq ($(shell grep "build_skb" $(LINUXSRC)/include/linux/skbuff.h | grep "int frag_size" > /dev/null 2>&1 && echo frag_size),)
|
||||
DISTRO_CFLAG += -DHAVE_NEW_BUILD_SKB
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "inner_network_offset" $(LINUXSRC)/include/linux/skbuff.h),)
|
||||
DISTRO_CFLAG += -DHAVE_INNER_NETWORK_OFFSET
|
||||
endif
|
||||
|
||||
ifeq ($(shell grep -o "skb_frag_size" $(LINUXSRC)/include/linux/skbuff.h),)
|
||||
DISTRO_CFLAG += -DNO_SKB_FRAG_SIZE
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -so "n_proto" $(LINUXSRC)/include/net/flow_keys.h),)
|
||||
DISTRO_CFLAG += -DHAVE_N_PROTO
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -so "flow_keys" $(LINUXSRC)/include/net/flow_keys.h),)
|
||||
DISTRO_CFLAG += -DHAVE_FLOW_KEYS
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "skb_get_hash_raw" $(LINUXSRC)/include/linux/skbuff.h),)
|
||||
DISTRO_CFLAG += -DHAVE_GET_HASH_RAW
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "PKT_HASH_TYPE" $(LINUXSRC)/include/linux/skbuff.h),)
|
||||
DISTRO_CFLAG += -DHAVE_SKB_HASH_TYPE
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "SKB_GSO_UDP_TUNNEL_CSUM" $(LINUXSRC)/include/linux/skbuff.h),)
|
||||
DISTRO_CFLAG += -DHAVE_SKB_GSO_UDP_TUNNEL_CSUM
|
||||
else
|
||||
ifneq ($(shell grep -o "SKB_GSO_UDP_TUNNEL" $(LINUXSRC)/include/linux/skbuff.h),)
|
||||
DISTRO_CFLAG += -DHAVE_SKB_GSO_UDP_TUNNEL
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "skb_frag_page" $(LINUXSRC)/include/linux/skbuff.h),)
|
||||
DISTRO_CFLAG += -DHAVE_SKB_FRAG_PAGE
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "skb_frag_off_add" $(LINUXSRC)/include/linux/skbuff.h),)
|
||||
DISTRO_CFLAG += -DHAVE_SKB_FRAG_ACCESSORS
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep "skb_checksum_none_assert" $(LINUXSRC)/include/linux/skbuff.h > /dev/null 2>&1 && echo skb_cs_none_assert),)
|
||||
DISTRO_CFLAG += -DHAVE_SKB_CHECKSUM_NONE_ASSERT
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "xmit_more" $(LINUXSRC)/include/linux/skbuff.h),)
|
||||
DISTRO_CFLAG += -DHAVE_SKB_XMIT_MORE
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -so "min_tx_rate" $(LINUXSRC)/include/$(UAPI)/linux/if_link.h),)
|
||||
DISTRO_CFLAG += -DHAVE_IFLA_TX_RATE
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -so "IFLA_XDP_PROG_ID" $(LINUXSRC)/include/$(UAPI)/linux/if_link.h),)
|
||||
DISTRO_CFLAG += -DHAVE_IFLA_XDP_PROG_ID
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "dma_set_mask_and_coherent" $(LINUXSRC)/include/linux/dma-mapping.h),)
|
||||
DISTRO_CFLAG += -DHAVE_SET_MASK_AND_COHERENT
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "dma_set_coherent_mask" $(LINUXSRC)/include/linux/dma-mapping.h),)
|
||||
DISTRO_CFLAG += -DHAVE_SET_COHERENT_MASK
|
||||
endif
|
||||
|
||||
ifneq ($(shell ls $(LINUXSRC)/include/linux/dma-attrs.h > /dev/null 2>&1 && echo dma_attrs),)
|
||||
DISTRO_CFLAG += -DHAVE_DMA_ATTRS_H
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "dma_map_page_attrs" $(LINUXSRC)/include/linux/dma-mapping.h),)
|
||||
DISTRO_CFLAG += -DHAVE_DMA_MAP_PAGE_ATTRS
|
||||
else
|
||||
ifneq ($(shell grep -so "dma_map_page_attrs" $(LINUXSRC)/include/asm-generic/dma-mapping-common.h),)
|
||||
DISTRO_CFLAG += -DHAVE_DMA_MAP_PAGE_ATTRS
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "dma_zalloc_coherent" $(LINUXSRC)/include/linux/dma-mapping.h),)
|
||||
DISTRO_CFLAG += -DHAVE_DMA_ZALLOC_COHERENT
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "ndo_add_vxlan_port" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_NDO_ADD_VXLAN
|
||||
ifneq ($(shell grep -so "vxlan_get_rx_port" $(LINUXSRC)/include/net/vxlan.h),)
|
||||
DISTRO_CFLAG += -DHAVE_VXLAN_GET_RX_PORT
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "ndo_udp_tunnel_add" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_NDO_UDP_TUNNEL
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "struct dev_addr_list" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_DEV_ADDR_LIST
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep "netif_set_real_num_tx" $(LINUXSRC)/include/linux/netdevice.h > /dev/null 2>&1 && echo real_tx),)
|
||||
DISTRO_CFLAG += -DHAVE_NETIF_SET_REAL_NUM_TX
|
||||
else
|
||||
DISTRO_CFLAG += -DVOID_NETIF_SET_NUM_TX
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep "netif_set_real_num_tx" $(LINUXSRC)/include/linux/netdevice.h | grep void > /dev/null 2>&1 && echo netif_set_real),)
|
||||
DISTRO_CFLAG += -DVOID_NETIF_SET_NUM_TX
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "netdev_tx_sent_queue" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_NETDEV_TX_QUEUE_CTRL
|
||||
endif
|
||||
|
||||
ifneq ($(shell ls $(LINUXSRC)/include/net/flow_dissector.h > /dev/null 2>&1 && echo flow),)
|
||||
DISTRO_CFLAG += -DNEW_FLOW_KEYS -DHAVE_FLOW_KEYS
|
||||
ifneq ($(shell grep -so "static inline bool skb_flow_dissect_flow_keys" $(LINUXSRC)/include/linux/skbuff.h),)
|
||||
ifneq ($(shell grep -A 2 "static inline bool skb_flow_dissect_flow_keys" $(LINUXSRC)/include/linux/skbuff.h | grep -o "unsigned int flags"),)
|
||||
DISTRO_CFLAG += -DHAVE_NEW_FLOW_DISSECTOR_WITH_FLAGS
|
||||
endif
|
||||
ifneq ($(shell grep -o "FLOW_DIS_ENCAPSULATION" $(LINUXSRC)/include/net/flow_dissector.h),)
|
||||
DISTRO_CFLAG += -DHAVE_NEW_FLOW_DISSECTOR
|
||||
endif
|
||||
endif
|
||||
ifneq ($(shell grep -o "flow_hash_from_keys" $(LINUXSRC)/include/net/flow_dissector.h),)
|
||||
DISTRO_CFLAG += -DHAVE_FLOW_HASH_FROM_KEYS
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell ls $(LINUXSRC)/include/net/flow_offload.h > /dev/null 2>&1 && echo flow_offload),)
|
||||
DISTRO_CFLAG += -DHAVE_FLOW_OFFLOAD_H
|
||||
ifneq ($(shell grep -so "struct flow_cls_offload" $(LINUXSRC)/include/net/flow_offload.h),)
|
||||
DISTRO_CFLAG += -DHAVE_TC_FLOW_CLS_OFFLOAD
|
||||
endif
|
||||
ifneq ($(shell grep -o "flow_block_cb_setup_simple" $(LINUXSRC)/include/net/flow_offload.h),)
|
||||
DISTRO_CFLAG += -DHAVE_SETUP_TC_BLOCK_HELPER
|
||||
endif
|
||||
ifneq ($(shell grep -o "__flow_indr_block_cb_register" $(LINUXSRC)/include/net/flow_offload.h),)
|
||||
DISTRO_CFLAG += -DHAVE_FLOW_INDR_BLOCK_CB
|
||||
endif
|
||||
ifneq ($(shell grep -o "FLOW_ACTION_POLICE" $(LINUXSRC)/include/net/flow_offload.h),)
|
||||
DISTRO_CFLAG += -DHAVE_FLOW_ACTION_POLICE
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell ls $(LINUXSRC)/include/net/udp_tunnel.h > /dev/null 2>&1 && echo udp_tunnel),)
|
||||
DISTRO_CFLAG += -DHAVE_UDP_TUNNEL_H
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "ether_addr_equal" $(LINUXSRC)/include/linux/etherdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_ETHER_ADDR_EQUAL
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "ether_addr_copy" $(LINUXSRC)/include/linux/etherdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_ETHER_ADDR_COPY
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "eth_broadcast_addr" $(LINUXSRC)/include/linux/etherdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_ETH_BROADCAST_ADDR
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "eth_get_headlen" $(LINUXSRC)/include/linux/etherdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_ETH_GET_HEADLEN
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "eth_hw_addr_random" $(LINUXSRC)/include/linux/etherdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_ETH_HW_ADDR_RANDOM
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -s "eth_get_headlen" $(LINUXSRC)/include/linux/etherdevice.h | grep -o "struct net_device"),)
|
||||
DISTRO_CFLAG += -DHAVE_ETH_GET_HEADLEN_NEW
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "get_rxnfc" $(LINUXSRC)/include/linux/ethtool.h),)
|
||||
DISTRO_CFLAG += -DHAVE_RXNFC
|
||||
ifneq ($(shell grep -A 2 "get_rxnfc" $(LINUXSRC)/include/linux/ethtool.h | grep -o "void"),)
|
||||
DISTRO_CFLAG += -DHAVE_RXNFC_VOID
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "get_rxfh_key_size" $(LINUXSRC)/include/linux/ethtool.h),)
|
||||
ifneq ($(shell grep -o "ETH_RSS_HASH_TOP" $(LINUXSRC)/include/linux/ethtool.h),)
|
||||
DISTRO_CFLAG += -DHAVE_GET_RXFH_KEY_SIZE
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "(\*set_rxfh)" $(LINUXSRC)/include/linux/ethtool.h),)
|
||||
DISTRO_CFLAG += -DHAVE_SET_RXFH
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "get_rxfh_indir_size" $(LINUXSRC)/include/linux/ethtool.h),)
|
||||
DISTRO_CFLAG += -DHAVE_RXFH_INDIR_SIZE
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "set_phys_id" $(LINUXSRC)/include/linux/ethtool.h),)
|
||||
DISTRO_CFLAG += -DHAVE_SET_PHYS_ID
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -so "ETHTOOL_LINK_MODE_25000baseCR_Full_BIT" $(LINUXSRC)/include/$(UAPI)/linux/ethtool.h),)
|
||||
ifeq ($(shell grep -o "^struct new_ethtool_ops {" $(LINUXSRC)/include/linux/ethtool.h),)
|
||||
DISTRO_CFLAG += -DHAVE_ETHTOOL_GLINKSETTINGS_25G
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -so "ethtool_tcpip6_spec" $(LINUXSRC)/include/$(UAPI)/linux/ethtool.h),)
|
||||
DISTRO_CFLAG += -DHAVE_ETHTOOL_IP6_SPEC
|
||||
endif
|
||||
|
||||
ifeq ($(shell grep -o "rx_cpu_rmap" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DNO_NETDEV_CPU_RMAP
|
||||
else
|
||||
ifneq ($(shell grep -o "irq_run_affinity_notifiers" $(LINUXSRC)/include/linux/interrupt.h),)
|
||||
DISTRO_CFLAG += -DNO_NETDEV_CPU_RMAP
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "hw_features" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
ifeq ($(shell grep -o "get_netdev_hw_features" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DNETDEV_HW_FEATURES
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "netdev_notifier_info_to_dev" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_NETDEV_NOTIFIER_INFO_TO_DEV
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep "register_netdevice_notifier_rh" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_REGISTER_NETDEVICE_NOTIFIER_RH
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "hw_enc_features" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DNETDEV_HW_ENC_FEATURES
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "sriov_configure" $(LINUXSRC)/include/linux/pci.h),)
|
||||
DISTRO_CFLAG += -DPCIE_SRIOV_CONFIGURE
|
||||
ifneq ($(shell grep -A 2 "pci_driver_rh" $(LINUXSRC)/include/linux/pci.h | \
|
||||
grep -o "sriov_configure"),)
|
||||
DISTRO_CFLAG += -DSRIOV_CONF_DEF_IN_PCI_DRIVER_RH
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "pci_vfs_assigned" $(LINUXSRC)/include/linux/pci.h),)
|
||||
DISTRO_CFLAG += -DHAVE_PCI_VFS_ASSIGNED
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "pci_num_vf" $(LINUXSRC)/include/linux/pci.h),)
|
||||
DISTRO_CFLAG += -DHAVE_PCI_NUM_VF
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "ndo_fix_features" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
ifeq ($(shell grep -o "net_device_ops_ext" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DNETDEV_FEATURE_CONTROL
|
||||
endif
|
||||
ifneq ($(shell grep -o "net_device_ops_extended" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DNETDEV_FEATURE_CONTROL
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "ndo_rx_flow_steer" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
ifeq ($(shell grep -o "netdev_rfs_info" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DNETDEV_RX_FLOW_STEER
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "ndo_busy_poll" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
ifeq ($(shell grep -o "net_device_extended" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DNETDEV_BUSY_POLL
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "ndo_get_stats64" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
ifeq ($(shell grep -o "net_device_ops_ext" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DNETDEV_GET_STATS64
|
||||
endif
|
||||
ifneq ($(shell grep -o "net_device_ops_extended" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DNETDEV_GET_STATS64
|
||||
endif
|
||||
ifneq ($(shell grep "ndo_get_stats64" $(LINUXSRC)/include/linux/netdevice.h | grep -o "void"),)
|
||||
DISTRO_CFLAG += -DNETDEV_GET_STATS64_VOID
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "ndo_get_vf_config" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_NDO_GET_VF_CONFIG
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -A 2 "ndo_bridge_getlink" $(LINUXSRC)/include/linux/netdevice.h | grep -o "nlflags"),)
|
||||
ifneq ($(shell grep -A 3 "ndo_dflt_bridge_getlink" $(LINUXSRC)/include/linux/rtnetlink.h | grep -o "filter_mask"),)
|
||||
DISTRO_CFLAG += -DHAVE_NDO_BRIDGE_GETLINK
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -A 4 "ndo_bridge_setlink" $(LINUXSRC)/include/linux/netdevice.h | grep -o "netlink_ext_ack"),)
|
||||
DISTRO_CFLAG += -DHAVE_NDO_BRIDGE_SETLINK_EXTACK
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "ndo_set_vf_link_state" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
ifeq ($(shell grep -o "net_device_ops_ext" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_NDO_SET_VF_LINK_STATE
|
||||
endif
|
||||
ifneq ($(shell grep -o "net_device_ops_extended" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_NDO_SET_VF_LINK_STATE
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "ndo_set_vf_spoofchk" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
ifeq ($(shell grep -o "net_device_ops_ext" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_VF_SPOOFCHK
|
||||
endif
|
||||
ifneq ($(shell grep -o "net_device_ops_extended" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_VF_SPOOFCHK
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -A 1 "ndo_set_vf_vlan" $(LINUXSRC)/include/linux/netdevice.h | grep -o "proto"),)
|
||||
ifeq ($(shell grep -o "RH_KABI_EXTEND(struct net_device_ops_extended extended)" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DNEW_NDO_SET_VF_VLAN
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "ndo_set_vf_vlan_rh73" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_NDO_SET_VF_VLAN_RH73
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "ndo_set_vf_trust" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
ifeq ($(shell grep -o "net_device_ops_ext" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_NDO_SET_VF_TRUST
|
||||
endif
|
||||
ifneq ($(shell grep -A 3 "net_device_ops_extended" $(LINUXSRC)/include/linux/netdevice.h | grep -o "ndo_set_vf_trust"),)
|
||||
DISTRO_CFLAG += -DHAVE_NDO_SET_VF_TRUST
|
||||
DISTRO_CFLAG += -DHAVE_NDO_SET_VF_TRUST_RH
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "ndo_set_vf_queues" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
ifeq ($(shell grep -o "net_device_ops_ext" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_NDO_SET_VF_QUEUES
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "ndo_change_mtu_rh74" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_NDO_CHANGE_MTU_RH74
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "RH_KABI_USE_P(16, struct net_device_extended \*extended)" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_NET_DEVICE_EXT
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "RH_KABI_EXTEND(struct net_device_ops_extended extended)" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
ifneq ($(shell grep -o "ndo_get_phys_port_name" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_EXT_GET_PHYS_PORT_NAME
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "ndo_setup_tc_rh72" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_NDO_SETUP_TC_RH72
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "(\*ndo_setup_tc_rh)" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_NDO_SETUP_TC_RH
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "tc_setup_cb_egdev_call" $(LINUXSRC)/include/net/act_api.h),)
|
||||
DISTRO_CFLAG += -DHAVE_TC_CB_EGDEV
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "ndo_setup_tc" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_SETUP_TC
|
||||
ifneq ($(shell grep -o "struct tc_to_netdev" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_TC_TO_NETDEV
|
||||
ifneq ($(shell grep -o "struct tc_mqprio_qopt" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_MQPRIO_QOPT
|
||||
endif
|
||||
ifneq ($(shell grep -A 1 "ndo_setup_tc" $(LINUXSRC)/include/linux/netdevice.h | grep -o "u32 chain_index"),)
|
||||
DISTRO_CFLAG += -DHAVE_CHAIN_INDEX
|
||||
endif
|
||||
endif
|
||||
ifneq ($(shell grep -o "enum tc_setup_type" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_TC_SETUP_TYPE
|
||||
endif
|
||||
ifneq ($(shell grep -so "tc_cls_flower_offload" $(LINUXSRC)/include/net/pkt_cls.h),)
|
||||
DISTRO_CFLAG += -DHAVE_TC_CLS_FLOWER_OFFLOAD
|
||||
endif
|
||||
ifneq ($(shell grep -o "TC_SETUP_BLOCK" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_TC_SETUP_BLOCK
|
||||
endif
|
||||
ifneq ($(shell grep -o "TC_SETUP_QDISC_MQPRIO" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_TC_SETUP_QDISC_MQPRIO
|
||||
endif
|
||||
ifneq ($(shell grep -so "tcf_mirred_dev" $(LINUXSRC)/include/net/tc_act/tc_mirred.h),)
|
||||
DISTRO_CFLAG += -DHAVE_TCF_MIRRED_DEV
|
||||
endif
|
||||
ifneq ($(shell grep -so "tc_cls_can_offload_and_chain0" $(LINUXSRC)/include/net/pkt_cls.h),)
|
||||
DISTRO_CFLAG += -DHAVE_TC_CLS_CAN_OFFLOAD_AND_CHAIN0
|
||||
endif
|
||||
ifneq ($(shell grep -s -A 2 "tcf_block_cb_register" $(LINUXSRC)/include/net/pkt_cls.h | grep -o "netlink_ext_ack"),)
|
||||
DISTRO_CFLAG += -DHAVE_TC_CB_REG_EXTACK
|
||||
endif
|
||||
ifneq ($(shell grep -so "tcf_exts_for_each_action" $(LINUXSRC)/include/net/pkt_cls.h),)
|
||||
DISTRO_CFLAG += -DHAVE_TC_EXTS_FOR_ACTION
|
||||
endif
|
||||
ifneq ($(shell grep -s -A 3 "struct tc_cls_matchall_offload" $(LINUXSRC)/include/net/pkt_cls.h | grep -o "flow_rule"),)
|
||||
DISTRO_CFLAG += -DHAVE_TC_MATCHALL_FLOW_RULE
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -so "FLOW_DISSECTOR_KEY_ICMP" $(LINUXSRC)/include/net/flow_dissector.h),)
|
||||
DISTRO_CFLAG += -DHAVE_FLOW_DISSECTOR_KEY_ICMP
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -so "rhashtable" $(LINUXSRC)/include/linux/rhashtable.h),)
|
||||
DISTRO_CFLAG += -DHAVE_RHASHTABLE
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -so "tcf_exts_to_list" $(LINUXSRC)/include/net/pkt_cls.h),)
|
||||
DISTRO_CFLAG += -DHAVE_TCF_EXTS_TO_LIST
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -so "tcf_exts_stats_update" $(LINUXSRC)/include/net/pkt_cls.h),)
|
||||
DISTRO_CFLAG += -DHAVE_TCF_STATS_UPDATE
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -so "tcf_exts_has_actions" $(LINUXSRC)/include/net/pkt_cls.h),)
|
||||
DISTRO_CFLAG += -DHAVE_TCF_EXTS_HAS_ACTIONS
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -so "is_tcf_tunnel_set" $(LINUXSRC)/include/net/tc_act/tc_tunnel_key.h),)
|
||||
DISTRO_CFLAG += -DHAVE_TCF_TUNNEL
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "netdev_get_num_tc" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_GET_NUM_TC
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -so "netdev_features_t" $(LINUXSRC)/include/linux/netdev_features.h || \
|
||||
grep -o "netdev_features_t" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_NETDEV_FEATURES_T
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "ndo_fix_features" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_NDO_FIX_FEATURES
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "netif_set_real_num_rx" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_NETIF_SET_REAL_NUM_RX
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "netif_get_num_default_rss_queues" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_NETIF_GET_DEFAULT_RSS
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "ndo_vlan_rx_register" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_VLAN_RX_REGISTER
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "ndo_get_port_parent_id" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_NDO_GET_PORT_PARENT_ID
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "net_device_ops_extended" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
ifneq ($(shell grep -o "ndo_xdp_xmit" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_EXT_NDO_XDP_XMIT
|
||||
endif
|
||||
else ifneq ($(shell grep -o "ndo_xdp" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_NDO_XDP
|
||||
ifneq ($(shell grep -o "ndo_bpf" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_NDO_BPF
|
||||
endif
|
||||
ifneq ($(shell ls $(LINUXSRC)/include/net/bpf_trace.h > /dev/null 2>&1 && echo bpf_trace),)
|
||||
DISTRO_CFLAG += -DHAVE_BPF_TRACE
|
||||
endif
|
||||
ifneq ($(shell grep -o "xdp_set_data_meta_invalid" $(LINUXSRC)/include/linux/filter.h),)
|
||||
DISTRO_CFLAG += -DHAVE_XDP_SET_DATA_META_INVALID
|
||||
endif
|
||||
ifneq ($(shell grep -o "void bpf_prog_add" $(LINUXSRC)/include/linux/bpf.h),)
|
||||
DISTRO_CFLAG += -DHAVE_VOID_BPF_PROG_ADD
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -so "enum xdp_action" $(LINUXSRC)/include/uapi/linux/bpf.h),)
|
||||
DISTRO_CFLAG += -DHAVE_XDP_ACTION
|
||||
endif
|
||||
ifneq ($(shell grep -so "XDP_REDIRECT" $(LINUXSRC)/include/uapi/linux/bpf.h),)
|
||||
DISTRO_CFLAG += -DHAVE_XDP_REDIRECT
|
||||
endif
|
||||
ifneq ($(shell grep -so "struct xdp_frame" $(LINUXSRC)/include/net/xdp.h),)
|
||||
DISTRO_CFLAG += -DHAVE_XDP_FRAME
|
||||
endif
|
||||
ifneq ($(shell grep -so "enum xdp_mem_type" $(LINUXSRC)/include/net/xdp.h),)
|
||||
DISTRO_CFLAG += -DHAVE_XDP_MEM_TYPE
|
||||
endif
|
||||
ifneq ($(shell grep -so "struct xdp_rxq_info" $(LINUXSRC)/include/net/xdp.h),)
|
||||
DISTRO_CFLAG += -DHAVE_XDP_RXQ_INFO
|
||||
ifneq ($(shell grep -o "xdp_rxq_info_is_reg" $(LINUXSRC)/include/net/xdp.h),)
|
||||
DISTRO_CFLAG += -DHAVE_XDP_RXQ_INFO_IS_REG
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -so "page_pool_release_page" $(LINUXSRC)/include/net/page_pool.h),)
|
||||
DISTRO_CFLAG += -DHAVE_PAGE_POOL_RELEASE_PAGE
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "netdev_name" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_NETDEV_NAME
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "netdev_update_features" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_NETDEV_UPDATE_FEATURES
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "napi_hash_add" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_NAPI_HASH_ADD
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "napi_hash_del" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_NAPI_HASH_DEL
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep "napi_complete_done" $(LINUXSRC)/include/linux/netdevice.h | grep -o "bool"),)
|
||||
DISTRO_CFLAG += -DHAVE_NEW_NAPI_COMPLETE_DONE
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "min_mtu" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_MIN_MTU
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "prog_attached" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_PROG_ATTACHED
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "netdev_xmit_more" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_NETDEV_XMIT_MORE
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -A 1 "ndo_tx_timeout" $(LINUXSRC)/include/linux/netdevice.h | grep -o txqueue),)
|
||||
DISTRO_CFLAG += -DHAVE_NDO_TX_TIMEOUT_QUEUE
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "netpoll_poll_dev" $(LINUXSRC)/include/linux/netpoll.h),)
|
||||
DISTRO_CFLAG += -DHAVE_NETPOLL_POLL_DEV
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "prandom_bytes" $(LINUXSRC)/include/linux/random.h),)
|
||||
DISTRO_CFLAG += -DHAVE_PRANDOM_BYTES
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "tcp_v6_check" $(LINUXSRC)/include/net/ip6_checksum.h),)
|
||||
DISTRO_CFLAG += -DHAVE_TCP_V6_CHECK
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "usleep_range" $(LINUXSRC)/include/linux/delay.h),)
|
||||
DISTRO_CFLAG += -DHAVE_USLEEP_RANGE
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "vzalloc" $(LINUXSRC)/include/linux/vmalloc.h),)
|
||||
DISTRO_CFLAG += -DHAVE_VZALLOC
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "kmalloc_array" $(LINUXSRC)/include/linux/slab.h),)
|
||||
DISTRO_CFLAG += -DHAVE_KMALLOC_ARRAY
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "pcie_capability_read_word" $(LINUXSRC)/include/linux/pci.h),)
|
||||
DISTRO_CFLAG += -DHAVE_PCIE_CAPABILITY_READ_WORD
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "pcie_link_width" $(LINUXSRC)/include/linux/pci.h),)
|
||||
DISTRO_CFLAG += -DHAVE_PCI_LINK_WIDTH
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "PCIE_SPEED_2_5GT" $(LINUXSRC)/include/linux/pci.h),)
|
||||
DISTRO_CFLAG += -DHAVE_PCIE_BUS_SPEED
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "pci_is_bridge" $(LINUXSRC)/include/linux/pci.h),)
|
||||
DISTRO_CFLAG += -DHAVE_PCI_IS_BRIDGE
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "pci_upstream_bridge" $(LINUXSRC)/include/linux/pci.h),)
|
||||
DISTRO_CFLAG += -DHAVE_PCI_UPSTREAM_BRIDGE
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "pcie_print_link_status" $(LINUXSRC)/include/linux/pci.h),)
|
||||
DISTRO_CFLAG += -DHAVE_PCI_PRINT_LINK_STATUS
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "_genl_register_family_with_ops_grps" $(LINUXSRC)/include/net/genetlink.h),)
|
||||
DISTRO_CFLAG += -DHAVE_GENL_REG_OPS_GRPS
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "pci_physfn" $(LINUXSRC)/include/linux/pci.h),)
|
||||
DISTRO_CFLAG += -DHAVE_PCI_PHYSFN
|
||||
endif
|
||||
|
||||
ifneq ($(shell ls $(LINUXSRC)/include/$(UAPI)/linux/net_tstamp.h > /dev/null 2>&1 && echo net_tstamp),)
|
||||
ifneq ($(shell ls $(LINUXSRC)/include/linux/timecounter.h > /dev/null 2>&1 && echo timecounter),)
|
||||
ifneq ($(shell ls $(LINUXSRC)/include/linux/timekeeping.h > /dev/null 2>&1 && echo timekeeping),)
|
||||
ifneq ($(shell grep -o "HWTSTAMP_FILTER_PTP_V2_EVENT" $(LINUXSRC)/include/$(UAPI)/linux/net_tstamp.h),)
|
||||
DISTRO_CFLAG += -DHAVE_IEEE1588_SUPPORT
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "time64_to_tm" $(LINUXSRC)/include/linux/time.h),)
|
||||
DISTRO_CFLAG += -DHAVE_TIME64
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "timer_setup" $(LINUXSRC)/include/linux/timer.h),)
|
||||
DISTRO_CFLAG += -DHAVE_TIMER_SETUP
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -s "devlink_ops" $(LINUXSRC)/include/net/devlink.h),)
|
||||
DISTRO_CFLAG += -DHAVE_DEVLINK
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -s "devlink_param" $(LINUXSRC)/include/net/devlink.h),)
|
||||
DISTRO_CFLAG += -DHAVE_DEVLINK_PARAM
|
||||
ifneq ($(shell grep -s -A 2 "int (\*validate)" $(LINUXSRC)/include/net/devlink.h | grep "struct netlink_ext_ack \*extack"),)
|
||||
DISTRO_CFLAG += -DHAVE_DEVLINK_VALIDATE_NEW
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -s -A 7 "devlink_port_attrs" $(LINUXSRC)/include/net/devlink.h | grep -o "netdev_phys_item_id"),)
|
||||
DISTRO_CFLAG += -DHAVE_DEVLINK_PORT_ATTRS
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -s "ndo_get_devlink_port" $(LINUXSRC)/include/net/devlink.h),)
|
||||
DISTRO_CFLAG += -DHAVE_NDO_DEVLINK_PORT
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -s "devlink_port_params_register" $(LINUXSRC)/include/net/devlink.h),)
|
||||
DISTRO_CFLAG += -DHAVE_DEVLINK_PORT_PARAM
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -s "devlink_params_publish" $(LINUXSRC)/include/net/devlink.h),)
|
||||
DISTRO_CFLAG += -DHAVE_DEVLINK_PARAM_PUBLISH
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -s -A 1 "eswitch_mode_set" $(LINUXSRC)/include/net/devlink.h | grep -o "netlink_ext_ack"),)
|
||||
DISTRO_CFLAG += -DHAVE_ESWITCH_MODE_SET_EXTACK
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -so "DEVLINK_PARAM_GENERIC_ID_IGNORE_ARI" $(LINUXSRC)/include/net/devlink.h),)
|
||||
DISTRO_CFLAG += -DHAVE_IGNORE_ARI
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -so "info_get" $(LINUXSRC)/include/net/devlink.h),)
|
||||
DISTRO_CFLAG += -DHAVE_DEVLINK_INFO
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -so "flash_update" $(LINUXSRC)/include/net/devlink.h),)
|
||||
DISTRO_CFLAG += -DHAVE_DEVLINK_FLASH_UPDATE
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -so "devlink_flash_update_status_notify" $(LINUXSRC)/include/net/devlink.h),)
|
||||
DISTRO_CFLAG += -DHAVE_DEVLINK_FLASH_UPDATE_STATUS
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -so "struct devlink_health_reporter" $(LINUXSRC)/include/net/devlink.h),)
|
||||
DISTRO_CFLAG += -DHAVE_DEVLINK_HEALTH_REPORT
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -so "devlink_health_reporter_state_update" $(LINUXSRC)/include/net/devlink.h),)
|
||||
DISTRO_CFLAG += -DHAVE_DEVLINK_HEALTH_REPORTER_STATE_UPDATE
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -s -A 1 "(*recover)" $(LINUXSRC)/include/net/devlink.h | grep netlink_ext_ack),)
|
||||
DISTRO_CFLAG += -DHAVE_DEVLINK_HEALTH_REPORT_EXTACK
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -so "devlink_health_reporter_recovery_done" $(LINUXSRC)/include/net/devlink.h),)
|
||||
DISTRO_CFLAG += -DHAVE_DEVLINK_HEALTH_REPORTER_RECOVERY_DONE
|
||||
endif
|
||||
|
||||
# Check if the file exists or not
|
||||
ifneq ($(shell grep -s "switchdev_ops" $(LINUXSRC)/include/net/switchdev.h),)
|
||||
DISTRO_CFLAG += -DHAVE_SWITCHDEV
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -s "METADATA_HW_PORT_MUX" $(LINUXSRC)/include/net/dst_metadata.h),)
|
||||
DISTRO_CFLAG += -DHAVE_METADATA_HW_PORT_MUX
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -so "(*ieee_delapp)" $(LINUXSRC)/include/net/dcbnl.h),)
|
||||
DISTRO_CFLAG += -DHAVE_IEEE_DELAPP
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o cpumask_local_spread $(LINUXSRC)/include/linux/cpumask.h),)
|
||||
DISTRO_CFLAG += -DHAVE_CPUMASK_LOCAL_SPREAD
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o cpumask_set_cpu_local_first $(LINUXSRC)/include/linux/cpumask.h),)
|
||||
DISTRO_CFLAG += -DHAVE_CPUMASK_LOCAL_FIRST
|
||||
endif
|
||||
|
||||
ifeq ($(shell grep -so "ETH_RESET_AP" $(LINUXSRC)/include/$(UAPI)/linux/ethtool.h),)
|
||||
DISTRO_CFLAG += -DNO_ETH_RESET_AP
|
||||
endif
|
||||
|
||||
ifneq ($(shell ls $(LINUXSRC)/include/linux/dim.h > /dev/null 2>&1 && echo dim),)
|
||||
DISTRO_CFLAG += -DHAVE_DIM
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o simple_open $(LINUXSRC)/include/linux/fs.h),)
|
||||
DISTRO_CFLAG += -DHAVE_SIMPLE_OPEN
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o hwmon_device_register_with_groups $(LINUXSRC)/include/linux/hwmon.h),)
|
||||
DISTRO_CFLAG += -DHAVE_NEW_HWMON_API
|
||||
endif
|
||||
|
||||
EXTRA_CFLAGS += ${DISTRO_CFLAG} -g -DCHIMP_FW -D__LINUX -DCONFIG_BNXT_SRIOV -DCONFIG_BNXT_DCB -DCONFIG_BNXT_FLASHDEV -DHSI_DBG_DISABLE -DCONFIG_BNXT_LFC
|
||||
|
||||
cflags-y += $(EXTRA_CFLAGS)
|
||||
|
||||
BCM_DRV = bnxt_en.ko
|
||||
ifneq ($(KERNELRELEASE),)
|
||||
|
||||
LINUX_VER=$(shell echo $(KVER) | cut -d "." -f1)
|
||||
ifeq ($(shell expr $(LINUX_VER) \>= 5), 1)
|
||||
BNXT_DBGFS_OBJ = bnxt_debugfs.o
|
||||
else
|
||||
BNXT_DBGFS_OBJ = bnxt_debugfs_cpt.o
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_BNXT) += bnxt_en.o
|
||||
bnxt_en-y := bnxt.o bnxt_ethtool.o bnxt_sriov.o bnxt_dcb.o bnxt_ulp.o bnxt_xdp.o bnxt_ptp.o bnxt_vfr.o bnxt_tc.o bnxt_devlink.o bnxt_lfc.o bnxt_netlink.o bnxt_dim.o $(BNXT_DBGFS_OBJ) #decode_hsi.o
|
||||
|
||||
else
|
||||
|
||||
default:
|
||||
ifeq ($(CROSS_COMPILE),)
|
||||
make -C $(LINUX) M=$(shell pwd) modules
|
||||
else ifneq ($(CROSS_COMPILE),)
|
||||
make -C $(LINUXSRC) M=$(shell pwd) modules CROSS_COMPILE=$(CROSS_COMPILE) ARCH=$(ARCH)
|
||||
endif
|
||||
|
||||
yocto_all:
|
||||
$(MAKE) -C $(LINUXSRC) M=$(shell pwd)
|
||||
|
||||
modules_install:
|
||||
$(MAKE) -C $(LINUXSRC) M=$(shell pwd) modules_install
|
||||
|
||||
endif
|
||||
|
||||
install: default
|
||||
@if [ "$(KDIR)" != "" ]; then \
|
||||
echo "Cannot use install with KDIR option"; exit 2;\
|
||||
fi
|
||||
mkdir -p $(PREFIX)$(BCMMODDIR);
|
||||
install -m 444 $(BCM_DRV) $(PREFIX)$(BCMMODDIR);
|
||||
@if [ "$(PREFIX)" = "" ]; then /sbin/depmod -a ;\
|
||||
else echo " *** Run '/sbin/depmod -a' to update the module database.";\
|
||||
fi
|
||||
|
||||
.PHONEY: all clean install
|
||||
|
||||
clean:
|
||||
-rm -f bnxt.o bnxt.mod.c bnxt.mod.o .bnxt.*.cmd *.cmd *.markers *.order *.symvers decode_hsi.o .decode_*
|
||||
-rm -rf .tmp_versions
|
||||
-rm -rf bnxt_en.o bnxt_en.ko bnxt_en.mod.o bnxt_en.mod.c .bnxt_en.* bnxt_sriov.o .bnxt_sriov.* bnxt_ethtool.o .bnxt_ethtool.* bnxt_dcb.o .bnxt_dcb.* bnxt_ulp.o .bnxt_ulp.* bnxt_ptp.o .bnxt_ptp.* bnxt_xdp.o .bnxt_xdp.* bnxt_lfc.o .bnxt_lfc.*
|
||||
-rm -rf bnxt_vfr.o .bnxt_vfr.* bnxt_tc.o .bnxt_tc.* bnxt_devlink.o .bnxt_devlink.* bnxt_netlink.o .bnxt_netlink.*
|
||||
-rm -rf bnxt_dim.o .bnxt_dim.* bnxt_debugfs*.o .bnxt_debugfs*
|
||||
-rm -f Module.markers Module.symvers modules.order
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,68 @@
|
|||
/* Broadcom NetXtreme-C/E network driver.
|
||||
*
|
||||
* Copyright (c) 2018 Broadcom Inc
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef BNXT_COREDUMP_H
|
||||
#define BNXT_COREDUMP_H
|
||||
|
||||
#if defined(ETHTOOL_GET_DUMP_FLAG) && !defined(GET_ETHTOOL_OP_EXT)
|
||||
struct bnxt_coredump_segment_hdr {
|
||||
__u8 signature[4];
|
||||
__le32 component_id;
|
||||
__le32 segment_id;
|
||||
__le32 flags;
|
||||
__u8 low_version;
|
||||
__u8 high_version;
|
||||
__le16 function_id;
|
||||
__le32 offset;
|
||||
__le32 length;
|
||||
__le32 status;
|
||||
__le32 duration;
|
||||
__le32 data_offset;
|
||||
__le32 instance;
|
||||
__le32 rsvd[5];
|
||||
};
|
||||
|
||||
struct bnxt_coredump_record {
|
||||
__u8 signature[4];
|
||||
__le32 flags;
|
||||
__u8 low_version;
|
||||
__u8 high_version;
|
||||
__u8 asic_state;
|
||||
__u8 rsvd0[5];
|
||||
char system_name[32];
|
||||
__le16 year;
|
||||
__le16 month;
|
||||
__le16 day;
|
||||
__le16 hour;
|
||||
__le16 minute;
|
||||
__le16 second;
|
||||
__le16 utc_bias;
|
||||
__le16 rsvd1;
|
||||
char commandline[256];
|
||||
__le32 total_segments;
|
||||
__le32 os_ver_major;
|
||||
__le32 os_ver_minor;
|
||||
__le32 rsvd2;
|
||||
char os_name[32];
|
||||
__le16 end_year;
|
||||
__le16 end_month;
|
||||
__le16 end_day;
|
||||
__le16 end_hour;
|
||||
__le16 end_minute;
|
||||
__le16 end_second;
|
||||
__le16 end_utc_bias;
|
||||
__le32 asic_id1;
|
||||
__le32 asic_id2;
|
||||
__le32 coredump_status;
|
||||
__u8 ioctl_low_version;
|
||||
__u8 ioctl_high_version;
|
||||
__le16 rsvd3[313];
|
||||
};
|
||||
#endif /* defined(ETHTOOL_GET_DUMP_FLAG) && !defined(GET_ETHTOOL_OP_EXT) */
|
||||
#endif
|
||||
|
|
@ -15,17 +15,32 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <rdma/ib_verbs.h>
|
||||
#include "bnxt_compat.h"
|
||||
#include "bnxt_hsi.h"
|
||||
#include "bnxt.h"
|
||||
#include "bnxt_dcb.h"
|
||||
|
||||
#ifdef CONFIG_BNXT_DCB
|
||||
static int bnxt_queue_to_tc(struct bnxt *bp, u8 queue_id)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < bp->max_tc; i++) {
|
||||
if (bp->q_info[i].queue_id == queue_id) {
|
||||
for (j = 0; j < bp->max_tc; j++) {
|
||||
if (bp->tc_to_qidx[j] == i)
|
||||
return j;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int bnxt_hwrm_queue_pri2cos_cfg(struct bnxt *bp, struct ieee_ets *ets)
|
||||
{
|
||||
struct hwrm_queue_pri2cos_cfg_input req = {0};
|
||||
int rc = 0, i;
|
||||
u8 *pri2cos;
|
||||
int i;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_PRI2COS_CFG, -1, -1);
|
||||
req.flags = cpu_to_le32(QUEUE_PRI2COS_CFG_REQ_FLAGS_PATH_BIDIR |
|
||||
|
|
@ -33,13 +48,15 @@ static int bnxt_hwrm_queue_pri2cos_cfg(struct bnxt *bp, struct ieee_ets *ets)
|
|||
|
||||
pri2cos = &req.pri0_cos_queue_id;
|
||||
for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
|
||||
u8 qidx;
|
||||
|
||||
req.enables |= cpu_to_le32(
|
||||
QUEUE_PRI2COS_CFG_REQ_ENABLES_PRI0_COS_QUEUE_ID << i);
|
||||
|
||||
pri2cos[i] = bp->q_info[ets->prio_tc[i]].queue_id;
|
||||
qidx = bp->tc_to_qidx[ets->prio_tc[i]];
|
||||
pri2cos[i] = bp->q_info[qidx].queue_id;
|
||||
}
|
||||
rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
return rc;
|
||||
return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
}
|
||||
|
||||
static int bnxt_hwrm_queue_pri2cos_qcfg(struct bnxt *bp, struct ieee_ets *ets)
|
||||
|
|
@ -55,17 +72,15 @@ static int bnxt_hwrm_queue_pri2cos_qcfg(struct bnxt *bp, struct ieee_ets *ets)
|
|||
rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
if (!rc) {
|
||||
u8 *pri2cos = &resp->pri0_cos_queue_id;
|
||||
int i, j;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
|
||||
u8 queue_id = pri2cos[i];
|
||||
int tc;
|
||||
|
||||
for (j = 0; j < bp->max_tc; j++) {
|
||||
if (bp->q_info[j].queue_id == queue_id) {
|
||||
ets->prio_tc[i] = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
tc = bnxt_queue_to_tc(bp, queue_id);
|
||||
if (tc >= 0)
|
||||
ets->prio_tc[i] = tc;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&bp->hwrm_cmd_lock);
|
||||
|
|
@ -77,17 +92,19 @@ static int bnxt_hwrm_queue_cos2bw_cfg(struct bnxt *bp, struct ieee_ets *ets,
|
|||
{
|
||||
struct hwrm_queue_cos2bw_cfg_input req = {0};
|
||||
struct bnxt_cos2bw_cfg cos2bw;
|
||||
int rc = 0, i;
|
||||
void *data;
|
||||
int i;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_COS2BW_CFG, -1, -1);
|
||||
data = &req.unused_0;
|
||||
for (i = 0; i < max_tc; i++, data += sizeof(cos2bw) - 4) {
|
||||
for (i = 0; i < max_tc; i++) {
|
||||
u8 qidx = bp->tc_to_qidx[i];
|
||||
|
||||
req.enables |= cpu_to_le32(
|
||||
QUEUE_COS2BW_CFG_REQ_ENABLES_COS_QUEUE_ID0_VALID << i);
|
||||
QUEUE_COS2BW_CFG_REQ_ENABLES_COS_QUEUE_ID0_VALID <<
|
||||
qidx);
|
||||
|
||||
memset(&cos2bw, 0, sizeof(cos2bw));
|
||||
cos2bw.queue_id = bp->q_info[i].queue_id;
|
||||
cos2bw.queue_id = bp->q_info[qidx].queue_id;
|
||||
if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_STRICT) {
|
||||
cos2bw.tsa =
|
||||
QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_TSA_ASSIGN_SP;
|
||||
|
|
@ -103,14 +120,14 @@ static int bnxt_hwrm_queue_cos2bw_cfg(struct bnxt *bp, struct ieee_ets *ets,
|
|||
cpu_to_le32((ets->tc_tx_bw[i] * 100) |
|
||||
BW_VALUE_UNIT_PERCENT1_100);
|
||||
}
|
||||
data = &req.unused_0 + qidx * (sizeof(cos2bw) - 4);
|
||||
memcpy(data, &cos2bw.queue_id, sizeof(cos2bw) - 4);
|
||||
if (i == 0) {
|
||||
if (qidx == 0) {
|
||||
req.queue_id0 = cos2bw.queue_id;
|
||||
req.unused_0 = 0;
|
||||
}
|
||||
}
|
||||
rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
return rc;
|
||||
return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
}
|
||||
|
||||
static int bnxt_hwrm_queue_cos2bw_qcfg(struct bnxt *bp, struct ieee_ets *ets)
|
||||
|
|
@ -132,66 +149,81 @@ static int bnxt_hwrm_queue_cos2bw_qcfg(struct bnxt *bp, struct ieee_ets *ets)
|
|||
|
||||
data = &resp->queue_id0 + offsetof(struct bnxt_cos2bw_cfg, queue_id);
|
||||
for (i = 0; i < bp->max_tc; i++, data += sizeof(cos2bw) - 4) {
|
||||
int j;
|
||||
int tc;
|
||||
|
||||
memcpy(&cos2bw.queue_id, data, sizeof(cos2bw) - 4);
|
||||
if (i == 0)
|
||||
cos2bw.queue_id = resp->queue_id0;
|
||||
|
||||
for (j = 0; j < bp->max_tc; j++) {
|
||||
if (bp->q_info[j].queue_id != cos2bw.queue_id)
|
||||
continue;
|
||||
if (cos2bw.tsa ==
|
||||
QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_TSA_ASSIGN_SP) {
|
||||
ets->tc_tsa[j] = IEEE_8021QAZ_TSA_STRICT;
|
||||
} else {
|
||||
ets->tc_tsa[j] = IEEE_8021QAZ_TSA_ETS;
|
||||
ets->tc_tx_bw[j] = cos2bw.bw_weight;
|
||||
}
|
||||
tc = bnxt_queue_to_tc(bp, cos2bw.queue_id);
|
||||
if (tc < 0)
|
||||
continue;
|
||||
|
||||
if (cos2bw.tsa ==
|
||||
QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_TSA_ASSIGN_SP) {
|
||||
ets->tc_tsa[tc] = IEEE_8021QAZ_TSA_STRICT;
|
||||
} else {
|
||||
ets->tc_tsa[tc] = IEEE_8021QAZ_TSA_ETS;
|
||||
ets->tc_tx_bw[tc] = cos2bw.bw_weight;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&bp->hwrm_cmd_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bnxt_hwrm_queue_cfg(struct bnxt *bp, unsigned int lltc_mask)
|
||||
static int bnxt_queue_remap(struct bnxt *bp, unsigned int lltc_mask)
|
||||
{
|
||||
struct hwrm_queue_cfg_input req = {0};
|
||||
int i;
|
||||
unsigned long qmap = 0;
|
||||
int max = bp->max_tc;
|
||||
int i, j, rc;
|
||||
|
||||
if (netif_running(bp->dev))
|
||||
bnxt_tx_disable(bp);
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_CFG, -1, -1);
|
||||
req.flags = cpu_to_le32(QUEUE_CFG_REQ_FLAGS_PATH_BIDIR);
|
||||
req.enables = cpu_to_le32(QUEUE_CFG_REQ_ENABLES_SERVICE_PROFILE);
|
||||
|
||||
/* Configure lossless queues to lossy first */
|
||||
req.service_profile = QUEUE_CFG_REQ_SERVICE_PROFILE_LOSSY;
|
||||
for (i = 0; i < bp->max_tc; i++) {
|
||||
if (BNXT_LLQ(bp->q_info[i].queue_profile)) {
|
||||
req.queue_id = cpu_to_le32(bp->q_info[i].queue_id);
|
||||
hwrm_send_message(bp, &req, sizeof(req),
|
||||
HWRM_CMD_TIMEOUT);
|
||||
bp->q_info[i].queue_profile =
|
||||
QUEUE_CFG_REQ_SERVICE_PROFILE_LOSSY;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now configure desired queues to lossless */
|
||||
req.service_profile = QUEUE_CFG_REQ_SERVICE_PROFILE_LOSSLESS;
|
||||
for (i = 0; i < bp->max_tc; i++) {
|
||||
/* Assign lossless TCs first */
|
||||
for (i = 0, j = 0; i < max; ) {
|
||||
if (lltc_mask & (1 << i)) {
|
||||
req.queue_id = cpu_to_le32(bp->q_info[i].queue_id);
|
||||
hwrm_send_message(bp, &req, sizeof(req),
|
||||
HWRM_CMD_TIMEOUT);
|
||||
bp->q_info[i].queue_profile =
|
||||
QUEUE_CFG_REQ_SERVICE_PROFILE_LOSSLESS;
|
||||
if (BNXT_LLQ(bp->q_info[j].queue_profile)) {
|
||||
bp->tc_to_qidx[i] = j;
|
||||
__set_bit(j, &qmap);
|
||||
i++;
|
||||
}
|
||||
j++;
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
for (i = 0, j = 0; i < max; i++) {
|
||||
if (lltc_mask & (1 << i))
|
||||
continue;
|
||||
j = find_next_zero_bit(&qmap, max, j);
|
||||
bp->tc_to_qidx[i] = j;
|
||||
__set_bit(j, &qmap);
|
||||
j++;
|
||||
}
|
||||
|
||||
if (netif_running(bp->dev)) {
|
||||
bnxt_close_nic(bp, false, false);
|
||||
rc = bnxt_open_nic(bp, false, false);
|
||||
if (rc) {
|
||||
netdev_warn(bp->dev, "failed to open NIC, rc = %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
if (netif_running(bp->dev))
|
||||
bnxt_tx_enable(bp);
|
||||
if (bp->ieee_ets) {
|
||||
int tc = netdev_get_num_tc(bp->dev);
|
||||
|
||||
if (!tc)
|
||||
tc = 1;
|
||||
rc = bnxt_hwrm_queue_cos2bw_cfg(bp, bp->ieee_ets, tc);
|
||||
if (rc) {
|
||||
netdev_warn(bp->dev, "failed to config BW, rc = %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
rc = bnxt_hwrm_queue_pri2cos_cfg(bp, bp->ieee_ets);
|
||||
if (rc) {
|
||||
netdev_warn(bp->dev, "failed to config prio, rc = %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -201,8 +233,7 @@ static int bnxt_hwrm_queue_pfc_cfg(struct bnxt *bp, struct ieee_pfc *pfc)
|
|||
struct ieee_ets *my_ets = bp->ieee_ets;
|
||||
unsigned int tc_mask = 0, pri_mask = 0;
|
||||
u8 i, pri, lltc_count = 0;
|
||||
bool need_q_recfg = false;
|
||||
int rc;
|
||||
bool need_q_remap = false;
|
||||
|
||||
if (!my_ets)
|
||||
return -EINVAL;
|
||||
|
|
@ -221,23 +252,23 @@ static int bnxt_hwrm_queue_pfc_cfg(struct bnxt *bp, struct ieee_pfc *pfc)
|
|||
if (lltc_count > bp->max_lltc)
|
||||
return -EINVAL;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_PFCENABLE_CFG, -1, -1);
|
||||
req.flags = cpu_to_le32(pri_mask);
|
||||
rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
for (i = 0; i < bp->max_tc; i++) {
|
||||
if (tc_mask & (1 << i)) {
|
||||
if (!BNXT_LLQ(bp->q_info[i].queue_profile))
|
||||
need_q_recfg = true;
|
||||
u8 qidx = bp->tc_to_qidx[i];
|
||||
|
||||
if (!BNXT_LLQ(bp->q_info[qidx].queue_profile)) {
|
||||
need_q_remap = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (need_q_recfg)
|
||||
rc = bnxt_hwrm_queue_cfg(bp, tc_mask);
|
||||
if (need_q_remap)
|
||||
bnxt_queue_remap(bp, tc_mask);
|
||||
|
||||
return rc;
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_PFCENABLE_CFG, -1, -1);
|
||||
req.flags = cpu_to_le32(pri_mask);
|
||||
return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
}
|
||||
|
||||
static int bnxt_hwrm_queue_pfc_qcfg(struct bnxt *bp, struct ieee_pfc *pfc)
|
||||
|
|
@ -278,12 +309,11 @@ static int bnxt_hwrm_set_dcbx_app(struct bnxt *bp, struct dcb_app *app,
|
|||
|
||||
n = IEEE_8021QAZ_MAX_TCS;
|
||||
data_len = sizeof(*data) + sizeof(*fw_app) * n;
|
||||
data = dma_alloc_coherent(&bp->pdev->dev, data_len, &mapping,
|
||||
GFP_KERNEL);
|
||||
data = dma_zalloc_coherent(&bp->pdev->dev, data_len, &mapping,
|
||||
GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(data, 0, data_len);
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &get, HWRM_FW_GET_STRUCTURED_DATA, -1, -1);
|
||||
get.dest_data_addr = cpu_to_le64(mapping);
|
||||
get.structure_id = cpu_to_le16(STRUCT_HDR_STRUCT_ID_DCBX_APP);
|
||||
|
|
@ -340,14 +370,66 @@ static int bnxt_hwrm_set_dcbx_app(struct bnxt *bp, struct dcb_app *app,
|
|||
set.data_len = cpu_to_le16(sizeof(*data) + sizeof(*fw_app) * n);
|
||||
set.hdr_cnt = 1;
|
||||
rc = hwrm_send_message(bp, &set, sizeof(set), HWRM_CMD_TIMEOUT);
|
||||
if (rc)
|
||||
rc = -EIO;
|
||||
|
||||
set_app_exit:
|
||||
dma_free_coherent(&bp->pdev->dev, data_len, data, mapping);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bnxt_hwrm_queue_dscp_qcaps(struct bnxt *bp)
|
||||
{
|
||||
struct hwrm_queue_dscp_qcaps_output *resp = bp->hwrm_cmd_resp_addr;
|
||||
struct hwrm_queue_dscp_qcaps_input req = {0};
|
||||
int rc;
|
||||
|
||||
bp->max_dscp_value = 0;
|
||||
if (bp->hwrm_spec_code < 0x10800 || BNXT_VF(bp))
|
||||
return 0;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_DSCP_QCAPS, -1, -1);
|
||||
mutex_lock(&bp->hwrm_cmd_lock);
|
||||
rc = _hwrm_send_message_silent(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
if (!rc) {
|
||||
bp->max_dscp_value = (1 << resp->num_dscp_bits) - 1;
|
||||
if (bp->max_dscp_value < 0x3f)
|
||||
bp->max_dscp_value = 0;
|
||||
}
|
||||
|
||||
mutex_unlock(&bp->hwrm_cmd_lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bnxt_hwrm_queue_dscp2pri_cfg(struct bnxt *bp, struct dcb_app *app,
|
||||
bool add)
|
||||
{
|
||||
struct hwrm_queue_dscp2pri_cfg_input req = {0};
|
||||
struct bnxt_dscp2pri_entry *dscp2pri;
|
||||
dma_addr_t mapping;
|
||||
int rc;
|
||||
|
||||
if (bp->hwrm_spec_code < 0x10800)
|
||||
return 0;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_DSCP2PRI_CFG, -1, -1);
|
||||
dscp2pri = dma_alloc_coherent(&bp->pdev->dev, sizeof(*dscp2pri),
|
||||
&mapping, GFP_KERNEL);
|
||||
if (!dscp2pri)
|
||||
return -ENOMEM;
|
||||
|
||||
req.src_data_addr = cpu_to_le64(mapping);
|
||||
dscp2pri->dscp = app->protocol;
|
||||
if (add)
|
||||
dscp2pri->mask = 0x3f;
|
||||
else
|
||||
dscp2pri->mask = 0;
|
||||
dscp2pri->pri = app->priority;
|
||||
req.entry_cnt = cpu_to_le16(1);
|
||||
rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
dma_free_coherent(&bp->pdev->dev, sizeof(*dscp2pri), dscp2pri,
|
||||
mapping);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bnxt_ets_validate(struct bnxt *bp, struct ieee_ets *ets, u8 *tc)
|
||||
{
|
||||
int total_ets_bw = 0;
|
||||
|
|
@ -379,7 +461,10 @@ static int bnxt_ets_validate(struct bnxt *bp, struct ieee_ets *ets, u8 *tc)
|
|||
if (total_ets_bw > 100)
|
||||
return -EINVAL;
|
||||
|
||||
*tc = max_tc + 1;
|
||||
if (max_tc >= bp->max_tc)
|
||||
*tc = bp->max_tc;
|
||||
else
|
||||
*tc = max_tc + 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -514,25 +599,43 @@ static int bnxt_dcbnl_ieee_setpfc(struct net_device *dev, struct ieee_pfc *pfc)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int bnxt_dcbnl_ieee_dscp_app_prep(struct bnxt *bp, struct dcb_app *app)
|
||||
{
|
||||
if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP) {
|
||||
if (!bp->max_dscp_value)
|
||||
return -ENOTSUPP;
|
||||
if (app->protocol > bp->max_dscp_value)
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bnxt_dcbnl_ieee_setapp(struct net_device *dev, struct dcb_app *app)
|
||||
{
|
||||
struct bnxt *bp = netdev_priv(dev);
|
||||
int rc = -EINVAL;
|
||||
int rc;
|
||||
|
||||
if (!(bp->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) ||
|
||||
!(bp->dcbx_cap & DCB_CAP_DCBX_HOST))
|
||||
return -EINVAL;
|
||||
|
||||
rc = bnxt_dcbnl_ieee_dscp_app_prep(bp, app);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = dcb_ieee_setapp(dev, app);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if ((app->selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE &&
|
||||
app->protocol == ETH_P_IBOE) ||
|
||||
app->protocol == ETH_P_ROCE) ||
|
||||
(app->selector == IEEE_8021QAZ_APP_SEL_DGRAM &&
|
||||
app->protocol == ROCE_V2_UDP_DPORT))
|
||||
rc = bnxt_hwrm_set_dcbx_app(bp, app, true);
|
||||
|
||||
if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP)
|
||||
rc = bnxt_hwrm_queue_dscp2pri_cfg(bp, app, true);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
@ -545,15 +648,22 @@ static int bnxt_dcbnl_ieee_delapp(struct net_device *dev, struct dcb_app *app)
|
|||
!(bp->dcbx_cap & DCB_CAP_DCBX_HOST))
|
||||
return -EINVAL;
|
||||
|
||||
rc = bnxt_dcbnl_ieee_dscp_app_prep(bp, app);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = dcb_ieee_delapp(dev, app);
|
||||
if (rc)
|
||||
return rc;
|
||||
if ((app->selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE &&
|
||||
app->protocol == ETH_P_IBOE) ||
|
||||
app->protocol == ETH_P_ROCE) ||
|
||||
(app->selector == IEEE_8021QAZ_APP_SEL_DGRAM &&
|
||||
app->protocol == ROCE_V2_UDP_DPORT))
|
||||
rc = bnxt_hwrm_set_dcbx_app(bp, app, false);
|
||||
|
||||
if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP)
|
||||
rc = bnxt_hwrm_queue_dscp2pri_cfg(bp, app, false);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
@ -573,7 +683,7 @@ static u8 bnxt_dcbnl_setdcbx(struct net_device *dev, u8 mode)
|
|||
return 1;
|
||||
|
||||
if (mode & DCB_CAP_DCBX_HOST) {
|
||||
if (BNXT_VF(bp) || (bp->flags & BNXT_FLAG_FW_LLDP_AGENT))
|
||||
if (BNXT_VF(bp) || (bp->fw_cap & BNXT_FW_CAP_LLDP_AGENT))
|
||||
return 1;
|
||||
|
||||
/* only support IEEE */
|
||||
|
|
@ -602,13 +712,15 @@ static const struct dcbnl_rtnl_ops dcbnl_ops = {
|
|||
|
||||
void bnxt_dcb_init(struct bnxt *bp)
|
||||
{
|
||||
bp->dcbx_cap = 0;
|
||||
if (bp->hwrm_spec_code < 0x10501)
|
||||
return;
|
||||
|
||||
bnxt_hwrm_queue_dscp_qcaps(bp);
|
||||
bp->dcbx_cap = DCB_CAP_DCBX_VER_IEEE;
|
||||
if (BNXT_PF(bp) && !(bp->flags & BNXT_FLAG_FW_LLDP_AGENT))
|
||||
if (BNXT_PF(bp) && !(bp->fw_cap & BNXT_FW_CAP_LLDP_AGENT))
|
||||
bp->dcbx_cap |= DCB_CAP_DCBX_HOST;
|
||||
else if (bp->flags & BNXT_FLAG_FW_DCBX_AGENT)
|
||||
else if (bp->fw_cap & BNXT_FW_CAP_DCBX_AGENT)
|
||||
bp->dcbx_cap |= DCB_CAP_DCBX_LLD_MANAGED;
|
||||
bp->dev->dcbnl_ops = &dcbnl_ops;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,11 +33,19 @@ struct bnxt_cos2bw_cfg {
|
|||
u8 unused;
|
||||
};
|
||||
|
||||
struct bnxt_dscp2pri_entry {
|
||||
u8 dscp;
|
||||
u8 mask;
|
||||
u8 pri;
|
||||
};
|
||||
|
||||
#define BNXT_LLQ(q_profile) \
|
||||
((q_profile) == QUEUE_QPORTCFG_RESP_QUEUE_ID0_SERVICE_PROFILE_LOSSLESS)
|
||||
((q_profile) == QUEUE_QPORTCFG_RESP_QUEUE_ID0_SERVICE_PROFILE_LOSSLESS_ROCE)
|
||||
#define BNXT_CNPQ(q_profile) \
|
||||
((q_profile) == QUEUE_QPORTCFG_RESP_QUEUE_ID0_SERVICE_PROFILE_LOSSY_ROCE_CNP)
|
||||
|
||||
#define HWRM_STRUCT_DATA_SUBTYPE_HOST_OPERATIONAL 0x0300
|
||||
|
||||
void bnxt_dcb_init(struct bnxt *bp);
|
||||
void bnxt_dcb_free(struct bnxt *bp);
|
||||
void bnxt_dcb_init(struct bnxt *);
|
||||
void bnxt_dcb_free(struct bnxt *);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,115 @@
|
|||
/* Broadcom NetXtreme-C/E network driver.
|
||||
*
|
||||
* Copyright (c) 2017-2018 Broadcom Limited
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include "bnxt_hsi.h"
|
||||
#include "bnxt_compat.h"
|
||||
#ifdef HAVE_DIM
|
||||
#include <linux/dim.h>
|
||||
#else
|
||||
#include "bnxt_dim.h"
|
||||
#endif
|
||||
#include "bnxt.h"
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
||||
static struct dentry *bnxt_debug_mnt;
|
||||
|
||||
static ssize_t debugfs_dim_read(struct file *filep,
|
||||
char __user *buffer,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct dim *dim = filep->private_data;
|
||||
int len;
|
||||
char *buf;
|
||||
|
||||
if (*ppos)
|
||||
return 0;
|
||||
if (!dim)
|
||||
return -ENODEV;
|
||||
buf = kasprintf(GFP_KERNEL,
|
||||
"state = %d\n" \
|
||||
"profile_ix = %d\n" \
|
||||
"mode = %d\n" \
|
||||
"tune_state = %d\n" \
|
||||
"steps_right = %d\n" \
|
||||
"steps_left = %d\n" \
|
||||
"tired = %d\n",
|
||||
dim->state,
|
||||
dim->profile_ix,
|
||||
dim->mode,
|
||||
dim->tune_state,
|
||||
dim->steps_right,
|
||||
dim->steps_left,
|
||||
dim->tired);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
if (count < strlen(buf)) {
|
||||
kfree(buf);
|
||||
return -ENOSPC;
|
||||
}
|
||||
len = simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf));
|
||||
kfree(buf);
|
||||
return len;
|
||||
}
|
||||
|
||||
static const struct file_operations debugfs_dim_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = simple_open,
|
||||
.read = debugfs_dim_read,
|
||||
};
|
||||
|
||||
static void debugfs_dim_ring_init(struct dim *dim, int ring_idx,
|
||||
struct dentry *dd)
|
||||
{
|
||||
static char qname[16];
|
||||
|
||||
snprintf(qname, 10, "%d", ring_idx);
|
||||
debugfs_create_file(qname, 0600, dd, dim, &debugfs_dim_fops);
|
||||
}
|
||||
|
||||
void bnxt_debug_dev_init(struct bnxt *bp)
|
||||
{
|
||||
const char *pname = pci_name(bp->pdev);
|
||||
struct dentry *dir;
|
||||
int i;
|
||||
|
||||
bp->debugfs_pdev = debugfs_create_dir(pname, bnxt_debug_mnt);
|
||||
dir = debugfs_create_dir("dim", bp->debugfs_pdev);
|
||||
|
||||
/* create files for each rx ring */
|
||||
for (i = 0; i < bp->cp_nr_rings; i++) {
|
||||
struct bnxt_cp_ring_info *cpr = &bp->bnapi[i]->cp_ring;
|
||||
|
||||
if (cpr && bp->bnapi[i]->rx_ring)
|
||||
debugfs_dim_ring_init(&cpr->dim, i, dir);
|
||||
}
|
||||
}
|
||||
|
||||
void bnxt_debug_dev_exit(struct bnxt *bp)
|
||||
{
|
||||
if (bp) {
|
||||
debugfs_remove_recursive(bp->debugfs_pdev);
|
||||
bp->debugfs_pdev = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void bnxt_debug_init(void)
|
||||
{
|
||||
bnxt_debug_mnt = debugfs_create_dir("bnxt_en", NULL);
|
||||
}
|
||||
|
||||
void bnxt_debug_exit(void)
|
||||
{
|
||||
debugfs_remove_recursive(bnxt_debug_mnt);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_DEBUG_FS */
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
/* Broadcom NetXtreme-C/E network driver.
|
||||
*
|
||||
* Copyright (c) 2017-2018 Broadcom Limited
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include "bnxt_hsi.h"
|
||||
#include "bnxt.h"
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
void bnxt_debug_init(void);
|
||||
void bnxt_debug_exit(void);
|
||||
void bnxt_debug_dev_init(struct bnxt *bp);
|
||||
void bnxt_debug_dev_exit(struct bnxt *bp);
|
||||
#else
|
||||
static inline void bnxt_debug_init(void) {}
|
||||
static inline void bnxt_debug_exit(void) {}
|
||||
static inline void bnxt_debug_dev_init(struct bnxt *bp) {}
|
||||
static inline void bnxt_debug_dev_exit(struct bnxt *bp) {}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
/* Broadcom NetXtreme-C/E network driver.
|
||||
*
|
||||
* Copyright (c) 2017-2018 Broadcom Limited
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include "bnxt_hsi.h"
|
||||
#include "bnxt_compat.h"
|
||||
#ifdef HAVE_DIM
|
||||
#include <linux/dim.h>
|
||||
#else
|
||||
#include "bnxt_dim.h"
|
||||
#endif
|
||||
#include "bnxt.h"
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
||||
static struct dentry *bnxt_debug_mnt;
|
||||
|
||||
static ssize_t debugfs_dim_read(struct file *filep,
|
||||
char __user *buffer,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct dim *dim = filep->private_data;
|
||||
int len;
|
||||
char *buf;
|
||||
|
||||
if (*ppos)
|
||||
return 0;
|
||||
if (!dim)
|
||||
return -ENODEV;
|
||||
buf = kasprintf(GFP_KERNEL,
|
||||
"state = %d\n" \
|
||||
"profile_ix = %d\n" \
|
||||
"mode = %d\n" \
|
||||
"tune_state = %d\n" \
|
||||
"steps_right = %d\n" \
|
||||
"steps_left = %d\n" \
|
||||
"tired = %d\n",
|
||||
dim->state,
|
||||
dim->profile_ix,
|
||||
dim->mode,
|
||||
dim->tune_state,
|
||||
dim->steps_right,
|
||||
dim->steps_left,
|
||||
dim->tired);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
if (count < strlen(buf)) {
|
||||
kfree(buf);
|
||||
return -ENOSPC;
|
||||
}
|
||||
len = simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf));
|
||||
kfree(buf);
|
||||
return len;
|
||||
}
|
||||
|
||||
static const struct file_operations debugfs_dim_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = simple_open,
|
||||
.read = debugfs_dim_read,
|
||||
};
|
||||
|
||||
static struct dentry *debugfs_dim_ring_init(struct dim *dim, int ring_idx,
|
||||
struct dentry *dd)
|
||||
{
|
||||
static char qname[16];
|
||||
|
||||
snprintf(qname, 10, "%d", ring_idx);
|
||||
return debugfs_create_file(qname, 0600, dd,
|
||||
dim, &debugfs_dim_fops);
|
||||
}
|
||||
|
||||
void bnxt_debug_dev_init(struct bnxt *bp)
|
||||
{
|
||||
const char *pname = pci_name(bp->pdev);
|
||||
struct dentry *pdevf;
|
||||
int i;
|
||||
|
||||
bp->debugfs_pdev = debugfs_create_dir(pname, bnxt_debug_mnt);
|
||||
if (bp->debugfs_pdev) {
|
||||
pdevf = debugfs_create_dir("dim", bp->debugfs_pdev);
|
||||
if (!pdevf) {
|
||||
pr_err("failed to create debugfs entry %s/dim\n",
|
||||
pname);
|
||||
return;
|
||||
}
|
||||
bp->debugfs_dim = pdevf;
|
||||
/* create files for each rx ring */
|
||||
for (i = 0; i < bp->cp_nr_rings; i++) {
|
||||
struct bnxt_cp_ring_info *cpr = &bp->bnapi[i]->cp_ring;
|
||||
|
||||
if (cpr && bp->bnapi[i]->rx_ring) {
|
||||
pdevf = debugfs_dim_ring_init(&cpr->dim, i,
|
||||
bp->debugfs_dim);
|
||||
if (!pdevf)
|
||||
pr_err("failed to create debugfs entry %s/dim/%d\n",
|
||||
pname, i);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pr_err("failed to create debugfs entry %s\n", pname);
|
||||
}
|
||||
}
|
||||
|
||||
void bnxt_debug_dev_exit(struct bnxt *bp)
|
||||
{
|
||||
if (bp) {
|
||||
debugfs_remove_recursive(bp->debugfs_pdev);
|
||||
bp->debugfs_pdev = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void bnxt_debug_init(void)
|
||||
{
|
||||
bnxt_debug_mnt = debugfs_create_dir("bnxt_en", NULL);
|
||||
if (!bnxt_debug_mnt)
|
||||
pr_err("failed to init bnxt_en debugfs\n");
|
||||
}
|
||||
|
||||
void bnxt_debug_exit(void)
|
||||
{
|
||||
debugfs_remove_recursive(bnxt_debug_mnt);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_DEBUG_FS */
|
||||
|
|
@ -0,0 +1,815 @@
|
|||
/* Broadcom NetXtreme-C/E network driver.
|
||||
*
|
||||
* Copyright (c) 2017 Broadcom Limited
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/netdevice.h>
|
||||
#if defined(CONFIG_VF_REPS) || defined(HAVE_DEVLINK_PARAM)
|
||||
#include <net/devlink.h>
|
||||
#endif
|
||||
#include "bnxt_compat.h"
|
||||
#include "bnxt_hsi.h"
|
||||
#include "bnxt.h"
|
||||
#include "bnxt_vfr.h"
|
||||
#include "bnxt_devlink.h"
|
||||
#include "bnxt_ethtool.h"
|
||||
|
||||
#if defined(CONFIG_VF_REPS) || defined(HAVE_DEVLINK_PARAM)
|
||||
#ifdef HAVE_DEVLINK_INFO
|
||||
static void bnxt_copy_from_nvm_data(union devlink_param_value *dst,
|
||||
union bnxt_nvm_data *src,
|
||||
int nvm_num_bits, int dl_num_bytes);
|
||||
|
||||
static int bnxt_hwrm_get_nvm_cfg_ver(struct bnxt *bp,
|
||||
union devlink_param_value *nvm_cfg_ver)
|
||||
{
|
||||
struct hwrm_nvm_get_variable_input req = {0};
|
||||
union bnxt_nvm_data *data;
|
||||
dma_addr_t data_dma_addr;
|
||||
int rc;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_NVM_GET_VARIABLE, -1, -1);
|
||||
data = dma_zalloc_coherent(&bp->pdev->dev, sizeof(*data),
|
||||
&data_dma_addr, GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
req.dest_data_addr = cpu_to_le64(data_dma_addr);
|
||||
req.data_len = cpu_to_le16(BNXT_NVM_CFG_VER_BITS);
|
||||
req.option_num = cpu_to_le16(NVM_OFF_NVM_CFG_VER);
|
||||
|
||||
rc = hwrm_send_message_silent(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
if (!rc)
|
||||
bnxt_copy_from_nvm_data(nvm_cfg_ver, data,
|
||||
BNXT_NVM_CFG_VER_BITS,
|
||||
BNXT_NVM_CFG_VER_BYTES);
|
||||
|
||||
dma_free_coherent(&bp->pdev->dev, sizeof(*data), data, data_dma_addr);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bnxt_dl_info_get(struct devlink *dl, struct devlink_info_req *req,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct bnxt *bp = bnxt_get_bp_from_dl(dl);
|
||||
union devlink_param_value nvm_cfg_ver;
|
||||
struct hwrm_ver_get_output *ver_resp;
|
||||
char mgmt_ver[FW_VER_STR_LEN];
|
||||
char roce_ver[FW_VER_STR_LEN];
|
||||
char fw_ver[FW_VER_STR_LEN];
|
||||
char buf[32];
|
||||
int rc;
|
||||
|
||||
rc = devlink_info_driver_name_put(req, DRV_MODULE_NAME);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
sprintf(buf, "%X", bp->chip_num);
|
||||
rc = devlink_info_version_fixed_put(req,
|
||||
DEVLINK_INFO_VERSION_GENERIC_ASIC_ID, buf);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
ver_resp = &bp->ver_resp;
|
||||
sprintf(buf, "%X", ver_resp->chip_rev);
|
||||
rc = devlink_info_version_fixed_put(req,
|
||||
DEVLINK_INFO_VERSION_GENERIC_ASIC_REV, buf);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (BNXT_PF(bp) && (bp->flags & BNXT_FLAG_DSN_VALID)) {
|
||||
sprintf(buf, "%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X",
|
||||
bp->dsn[7], bp->dsn[6], bp->dsn[5], bp->dsn[4],
|
||||
bp->dsn[3], bp->dsn[2], bp->dsn[1], bp->dsn[0]);
|
||||
rc = devlink_info_serial_number_put(req, buf);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (strlen(ver_resp->active_pkg_name)) {
|
||||
rc =
|
||||
devlink_info_version_running_put(req,
|
||||
DEVLINK_INFO_VERSION_GENERIC_FW,
|
||||
ver_resp->active_pkg_name);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (BNXT_PF(bp) && !bnxt_hwrm_get_nvm_cfg_ver(bp, &nvm_cfg_ver)) {
|
||||
u32 ver = nvm_cfg_ver.vu32;
|
||||
|
||||
sprintf(buf, "%X.%X.%X", (ver >> 16) & 0xF, (ver >> 8) & 0xF,
|
||||
ver & 0xF);
|
||||
rc = devlink_info_version_running_put(req,
|
||||
DEVLINK_INFO_VERSION_GENERIC_FW_PSID, buf);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (ver_resp->flags & VER_GET_RESP_FLAGS_EXT_VER_AVAIL) {
|
||||
snprintf(fw_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
|
||||
ver_resp->hwrm_fw_major, ver_resp->hwrm_fw_minor,
|
||||
ver_resp->hwrm_fw_build, ver_resp->hwrm_fw_patch);
|
||||
|
||||
snprintf(mgmt_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
|
||||
ver_resp->mgmt_fw_major, ver_resp->mgmt_fw_minor,
|
||||
ver_resp->mgmt_fw_build, ver_resp->mgmt_fw_patch);
|
||||
|
||||
snprintf(roce_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
|
||||
ver_resp->roce_fw_major, ver_resp->roce_fw_minor,
|
||||
ver_resp->roce_fw_build, ver_resp->roce_fw_patch);
|
||||
} else {
|
||||
snprintf(fw_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
|
||||
ver_resp->hwrm_fw_maj_8b, ver_resp->hwrm_fw_min_8b,
|
||||
ver_resp->hwrm_fw_bld_8b, ver_resp->hwrm_fw_rsvd_8b);
|
||||
|
||||
snprintf(mgmt_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
|
||||
ver_resp->mgmt_fw_maj_8b, ver_resp->mgmt_fw_min_8b,
|
||||
ver_resp->mgmt_fw_bld_8b, ver_resp->mgmt_fw_rsvd_8b);
|
||||
|
||||
snprintf(roce_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
|
||||
ver_resp->roce_fw_maj_8b, ver_resp->roce_fw_min_8b,
|
||||
ver_resp->roce_fw_bld_8b, ver_resp->roce_fw_rsvd_8b);
|
||||
}
|
||||
rc = devlink_info_version_running_put(req,
|
||||
DEVLINK_INFO_VERSION_GENERIC_FW_APP, fw_ver);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (!(bp->flags & BNXT_FLAG_CHIP_P5)) {
|
||||
rc = devlink_info_version_running_put(req,
|
||||
DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, mgmt_ver);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = devlink_info_version_running_put(req,
|
||||
DEVLINK_INFO_VERSION_GENERIC_FW_ROCE, roce_ver);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* HAVE_DEVLINK_INFO */
|
||||
|
||||
#ifdef HAVE_DEVLINK_FLASH_UPDATE
|
||||
static int
|
||||
bnxt_dl_flash_update(struct devlink *dl, const char *filename,
|
||||
const char *region, struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct bnxt *bp = bnxt_get_bp_from_dl(dl);
|
||||
int rc;
|
||||
|
||||
if (region)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!BNXT_PF(bp)) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"flash update not supported from a VF");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
devlink_flash_update_begin_notify(dl);
|
||||
devlink_flash_update_status_notify(dl, "Preparing to flash", region, 0,
|
||||
0);
|
||||
rc = bnxt_flash_package_from_file(bp->dev, filename, 0);
|
||||
if (!rc)
|
||||
devlink_flash_update_status_notify(dl, "Flashing done", region,
|
||||
0, 0);
|
||||
else
|
||||
devlink_flash_update_status_notify(dl, "Flashing failed",
|
||||
region, 0, 0);
|
||||
devlink_flash_update_end_notify(dl);
|
||||
return rc;
|
||||
}
|
||||
#endif /* HAVE_DEVLINK_FLASH_UPDATE */
|
||||
|
||||
#ifdef HAVE_DEVLINK_HEALTH_REPORT
|
||||
static int bnxt_fw_reporter_diagnose(struct devlink_health_reporter *reporter,
|
||||
struct devlink_fmsg *fmsg,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct bnxt *bp = devlink_health_reporter_priv(reporter);
|
||||
u32 val, health_status;
|
||||
int rc;
|
||||
|
||||
if (test_bit(BNXT_STATE_IN_FW_RESET, &bp->state))
|
||||
return 0;
|
||||
|
||||
val = bnxt_fw_health_readl(bp, BNXT_FW_HEALTH_REG);
|
||||
health_status = val & 0xffff;
|
||||
|
||||
if (health_status < BNXT_FW_STATUS_HEALTHY) {
|
||||
rc = devlink_fmsg_string_pair_put(fmsg, "Description",
|
||||
"Not yet completed initialization");
|
||||
if (rc)
|
||||
return rc;
|
||||
} else if (health_status > BNXT_FW_STATUS_HEALTHY) {
|
||||
rc = devlink_fmsg_string_pair_put(fmsg, "Description",
|
||||
"Encountered fatal error and cannot recover");
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (val >> 16) {
|
||||
rc = devlink_fmsg_u32_pair_put(fmsg, "Error code", val >> 16);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
val = bnxt_fw_health_readl(bp, BNXT_FW_RESET_CNT_REG);
|
||||
rc = devlink_fmsg_u32_pair_put(fmsg, "Reset count", val);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct devlink_health_reporter_ops bnxt_dl_fw_reporter_ops = {
|
||||
.name = "fw",
|
||||
.diagnose = bnxt_fw_reporter_diagnose,
|
||||
};
|
||||
|
||||
static int bnxt_fw_reset_recover(struct devlink_health_reporter *reporter,
|
||||
void *priv_ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct bnxt *bp = devlink_health_reporter_priv(reporter);
|
||||
|
||||
if (!priv_ctx)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
bnxt_fw_reset(bp);
|
||||
#ifdef HAVE_DEVLINK_HEALTH_REPORTER_RECOVERY_DONE
|
||||
return -EINPROGRESS;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static const
|
||||
struct devlink_health_reporter_ops bnxt_dl_fw_reset_reporter_ops = {
|
||||
.name = "fw_reset",
|
||||
.recover = bnxt_fw_reset_recover,
|
||||
};
|
||||
|
||||
static int bnxt_fw_fatal_recover(struct devlink_health_reporter *reporter,
|
||||
void *priv_ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct bnxt *bp = devlink_health_reporter_priv(reporter);
|
||||
struct bnxt_fw_reporter_ctx *fw_reporter_ctx = priv_ctx;
|
||||
unsigned long event;
|
||||
|
||||
if (!priv_ctx)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
bp->fw_health->fatal = true;
|
||||
event = fw_reporter_ctx->sp_event;
|
||||
if (event == BNXT_FW_RESET_NOTIFY_SP_EVENT)
|
||||
bnxt_fw_reset(bp);
|
||||
else if (event == BNXT_FW_EXCEPTION_SP_EVENT)
|
||||
bnxt_fw_exception(bp);
|
||||
|
||||
#ifdef HAVE_DEVLINK_HEALTH_REPORTER_RECOVERY_DONE
|
||||
return -EINPROGRESS;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static const
|
||||
struct devlink_health_reporter_ops bnxt_dl_fw_fatal_reporter_ops = {
|
||||
.name = "fw_fatal",
|
||||
.recover = bnxt_fw_fatal_recover,
|
||||
};
|
||||
|
||||
void bnxt_dl_fw_reporters_create(struct bnxt *bp)
|
||||
{
|
||||
struct bnxt_fw_health *health = bp->fw_health;
|
||||
|
||||
if (!bp->dl || !health)
|
||||
return;
|
||||
|
||||
if (!(bp->fw_cap & BNXT_FW_CAP_HOT_RESET) || health->fw_reset_reporter)
|
||||
goto err_recovery;
|
||||
|
||||
health->fw_reset_reporter =
|
||||
devlink_health_reporter_create(bp->dl,
|
||||
&bnxt_dl_fw_reset_reporter_ops,
|
||||
0, true, bp);
|
||||
if (IS_ERR(health->fw_reset_reporter)) {
|
||||
netdev_warn(bp->dev, "Failed to create FW reset health reporter, rc = %ld\n",
|
||||
PTR_ERR(health->fw_reset_reporter));
|
||||
health->fw_reset_reporter = NULL;
|
||||
bp->fw_cap &= ~BNXT_FW_CAP_HOT_RESET;
|
||||
}
|
||||
|
||||
err_recovery:
|
||||
if (!(bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY))
|
||||
return;
|
||||
|
||||
if (!health->fw_reporter) {
|
||||
health->fw_reporter =
|
||||
devlink_health_reporter_create(bp->dl,
|
||||
&bnxt_dl_fw_reporter_ops,
|
||||
0, false, bp);
|
||||
if (IS_ERR(health->fw_reporter)) {
|
||||
netdev_warn(bp->dev, "Failed to create FW health reporter, rc = %ld\n",
|
||||
PTR_ERR(health->fw_reporter));
|
||||
health->fw_reporter = NULL;
|
||||
bp->fw_cap &= ~BNXT_FW_CAP_ERROR_RECOVERY;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (health->fw_fatal_reporter)
|
||||
return;
|
||||
|
||||
health->fw_fatal_reporter =
|
||||
devlink_health_reporter_create(bp->dl,
|
||||
&bnxt_dl_fw_fatal_reporter_ops,
|
||||
0, true, bp);
|
||||
if (IS_ERR(health->fw_fatal_reporter)) {
|
||||
netdev_warn(bp->dev, "Failed to create FW fatal health reporter, rc = %ld\n",
|
||||
PTR_ERR(health->fw_fatal_reporter));
|
||||
health->fw_fatal_reporter = NULL;
|
||||
bp->fw_cap &= ~BNXT_FW_CAP_ERROR_RECOVERY;
|
||||
}
|
||||
}
|
||||
|
||||
void bnxt_dl_fw_reporters_destroy(struct bnxt *bp, bool all)
|
||||
{
|
||||
struct bnxt_fw_health *health = bp->fw_health;
|
||||
|
||||
if (!bp->dl || !health)
|
||||
return;
|
||||
|
||||
if ((all || !(bp->fw_cap & BNXT_FW_CAP_HOT_RESET)) &&
|
||||
health->fw_reset_reporter) {
|
||||
devlink_health_reporter_destroy(health->fw_reset_reporter);
|
||||
health->fw_reset_reporter = NULL;
|
||||
}
|
||||
|
||||
if ((bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY) && !all)
|
||||
return;
|
||||
|
||||
if (health->fw_reporter) {
|
||||
devlink_health_reporter_destroy(health->fw_reporter);
|
||||
health->fw_reporter = NULL;
|
||||
}
|
||||
|
||||
if (health->fw_fatal_reporter) {
|
||||
devlink_health_reporter_destroy(health->fw_fatal_reporter);
|
||||
health->fw_fatal_reporter = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void bnxt_devlink_health_report(struct bnxt *bp, unsigned long event)
|
||||
{
|
||||
struct bnxt_fw_health *fw_health = bp->fw_health;
|
||||
struct bnxt_fw_reporter_ctx fw_reporter_ctx;
|
||||
|
||||
fw_reporter_ctx.sp_event = event;
|
||||
switch (event) {
|
||||
case BNXT_FW_RESET_NOTIFY_SP_EVENT:
|
||||
if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state)) {
|
||||
if (!fw_health->fw_fatal_reporter)
|
||||
return;
|
||||
|
||||
devlink_health_report(fw_health->fw_fatal_reporter,
|
||||
"FW fatal async event received",
|
||||
&fw_reporter_ctx);
|
||||
return;
|
||||
}
|
||||
if (!fw_health->fw_reset_reporter)
|
||||
return;
|
||||
|
||||
devlink_health_report(fw_health->fw_reset_reporter,
|
||||
"FW non-fatal reset event received",
|
||||
&fw_reporter_ctx);
|
||||
return;
|
||||
|
||||
case BNXT_FW_EXCEPTION_SP_EVENT:
|
||||
if (!fw_health->fw_fatal_reporter)
|
||||
return;
|
||||
|
||||
devlink_health_report(fw_health->fw_fatal_reporter,
|
||||
"FW fatal error reported",
|
||||
&fw_reporter_ctx);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void bnxt_dl_health_status_update(struct bnxt *bp, bool healthy)
|
||||
{
|
||||
struct bnxt_fw_health *health = bp->fw_health;
|
||||
u8 state;
|
||||
|
||||
if (healthy)
|
||||
state = DEVLINK_HEALTH_REPORTER_STATE_HEALTHY;
|
||||
else
|
||||
state = DEVLINK_HEALTH_REPORTER_STATE_ERROR;
|
||||
|
||||
if (health->fatal)
|
||||
devlink_health_reporter_state_update(health->fw_fatal_reporter,
|
||||
state);
|
||||
else
|
||||
devlink_health_reporter_state_update(health->fw_reset_reporter,
|
||||
state);
|
||||
|
||||
health->fatal = false;
|
||||
}
|
||||
|
||||
void bnxt_dl_health_recovery_done(struct bnxt *bp)
|
||||
{
|
||||
struct bnxt_fw_health *hlth = bp->fw_health;
|
||||
|
||||
if (hlth->fatal)
|
||||
devlink_health_reporter_recovery_done(hlth->fw_fatal_reporter);
|
||||
else
|
||||
devlink_health_reporter_recovery_done(hlth->fw_reset_reporter);
|
||||
}
|
||||
#endif /* HAVE_DEVLINK_HEALTH_REPORT */
|
||||
|
||||
static const struct devlink_ops bnxt_dl_ops = {
|
||||
#ifdef CONFIG_VF_REPS
|
||||
#ifdef CONFIG_BNXT_SRIOV
|
||||
.eswitch_mode_set = bnxt_dl_eswitch_mode_set,
|
||||
.eswitch_mode_get = bnxt_dl_eswitch_mode_get,
|
||||
#endif /* CONFIG_BNXT_SRIOV */
|
||||
#endif /* CONFIG_VF_REPS */
|
||||
#ifdef HAVE_DEVLINK_INFO
|
||||
.info_get = bnxt_dl_info_get,
|
||||
#endif /* HAVE_DEVLINK_INFO */
|
||||
#ifdef HAVE_DEVLINK_FLASH_UPDATE
|
||||
.flash_update = bnxt_dl_flash_update,
|
||||
#endif /* HAVE_DEVLINK_FLASH_UPDATE */
|
||||
};
|
||||
|
||||
static const struct devlink_ops bnxt_vf_dl_ops = {
|
||||
#ifdef HAVE_DEVLINK_INFO
|
||||
.info_get = bnxt_dl_info_get,
|
||||
#endif /* HAVE_DEVLINK_INFO */
|
||||
};
|
||||
|
||||
#ifdef HAVE_DEVLINK_PARAM
|
||||
enum bnxt_dl_param_id {
|
||||
BNXT_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,
|
||||
BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK,
|
||||
};
|
||||
|
||||
static const struct bnxt_dl_nvm_param nvm_params[] = {
|
||||
{DEVLINK_PARAM_GENERIC_ID_ENABLE_SRIOV, NVM_OFF_ENABLE_SRIOV,
|
||||
BNXT_NVM_SHARED_CFG, 1, 1},
|
||||
#ifdef HAVE_IGNORE_ARI
|
||||
{DEVLINK_PARAM_GENERIC_ID_IGNORE_ARI, NVM_OFF_IGNORE_ARI,
|
||||
BNXT_NVM_SHARED_CFG, 1, 1},
|
||||
{DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX,
|
||||
NVM_OFF_MSIX_VEC_PER_PF_MAX, BNXT_NVM_SHARED_CFG, 10, 4},
|
||||
{DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN,
|
||||
NVM_OFF_MSIX_VEC_PER_PF_MIN, BNXT_NVM_SHARED_CFG, 7, 4},
|
||||
#endif
|
||||
{BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK, NVM_OFF_DIS_GRE_VER_CHECK,
|
||||
BNXT_NVM_SHARED_CFG, 1, 1},
|
||||
};
|
||||
|
||||
static void bnxt_copy_to_nvm_data(union bnxt_nvm_data *dst,
|
||||
union devlink_param_value *src,
|
||||
int nvm_num_bits, int dl_num_bytes)
|
||||
{
|
||||
u32 val32 = 0;
|
||||
|
||||
if (nvm_num_bits == 1) {
|
||||
dst->val8 = src->vbool;
|
||||
return;
|
||||
}
|
||||
if (dl_num_bytes == 4)
|
||||
val32 = src->vu32;
|
||||
else if (dl_num_bytes == 2)
|
||||
val32 = (u32)src->vu16;
|
||||
else if (dl_num_bytes == 1)
|
||||
val32 = (u32)src->vu8;
|
||||
dst->val32 = cpu_to_le32(val32);
|
||||
}
|
||||
|
||||
static void bnxt_copy_from_nvm_data(union devlink_param_value *dst,
|
||||
union bnxt_nvm_data *src,
|
||||
int nvm_num_bits, int dl_num_bytes)
|
||||
{
|
||||
u32 val32;
|
||||
|
||||
if (nvm_num_bits == 1) {
|
||||
dst->vbool = src->val8;
|
||||
return;
|
||||
}
|
||||
val32 = le32_to_cpu(src->val32);
|
||||
if (dl_num_bytes == 4)
|
||||
dst->vu32 = val32;
|
||||
else if (dl_num_bytes == 2)
|
||||
dst->vu16 = (u16)val32;
|
||||
else if (dl_num_bytes == 1)
|
||||
dst->vu8 = (u8)val32;
|
||||
}
|
||||
|
||||
static int bnxt_hwrm_nvm_req(struct bnxt *bp, u32 param_id, void *msg,
|
||||
int msg_len, union devlink_param_value *val)
|
||||
{
|
||||
struct hwrm_nvm_get_variable_input *req = msg;
|
||||
struct bnxt_dl_nvm_param nvm_param;
|
||||
union bnxt_nvm_data *data;
|
||||
dma_addr_t data_dma_addr;
|
||||
int idx = 0, rc, i;
|
||||
|
||||
/* Get/Set NVM CFG parameter is supported only on PFs */
|
||||
if (BNXT_VF(bp))
|
||||
return -EPERM;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(nvm_params); i++) {
|
||||
if (nvm_params[i].id == param_id) {
|
||||
nvm_param = nvm_params[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == ARRAY_SIZE(nvm_params))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (nvm_param.dir_type == BNXT_NVM_PORT_CFG)
|
||||
idx = bp->pf.port_id;
|
||||
else if (nvm_param.dir_type == BNXT_NVM_FUNC_CFG)
|
||||
idx = bp->pf.fw_fid - BNXT_FIRST_PF_FID;
|
||||
|
||||
data = dma_zalloc_coherent(&bp->pdev->dev, sizeof(*data),
|
||||
&data_dma_addr, GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
req->dest_data_addr = cpu_to_le64(data_dma_addr);
|
||||
req->data_len = cpu_to_le16(nvm_param.nvm_num_bits);
|
||||
req->option_num = cpu_to_le16(nvm_param.offset);
|
||||
req->index_0 = cpu_to_le16(idx);
|
||||
if (idx)
|
||||
req->dimensions = cpu_to_le16(1);
|
||||
|
||||
if (req->req_type == cpu_to_le16(HWRM_NVM_SET_VARIABLE)) {
|
||||
bnxt_copy_to_nvm_data(data, val, nvm_param.nvm_num_bits,
|
||||
nvm_param.dl_num_bytes);
|
||||
rc = hwrm_send_message(bp, msg, msg_len, HWRM_CMD_TIMEOUT);
|
||||
} else {
|
||||
rc = hwrm_send_message_silent(bp, msg, msg_len,
|
||||
HWRM_CMD_TIMEOUT);
|
||||
if (!rc) {
|
||||
bnxt_copy_from_nvm_data(val, data,
|
||||
nvm_param.nvm_num_bits,
|
||||
nvm_param.dl_num_bytes);
|
||||
} else {
|
||||
struct hwrm_err_output *resp = bp->hwrm_cmd_resp_addr;
|
||||
|
||||
if (resp->cmd_err ==
|
||||
NVM_GET_VARIABLE_CMD_ERR_CODE_VAR_NOT_EXIST)
|
||||
rc = -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
dma_free_coherent(&bp->pdev->dev, sizeof(*data), data, data_dma_addr);
|
||||
if (rc == -EACCES)
|
||||
netdev_err(bp->dev, "PF does not have admin privileges to modify NVM config\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bnxt_dl_nvm_param_get(struct devlink *dl, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
{
|
||||
struct hwrm_nvm_get_variable_input req = {0};
|
||||
struct bnxt *bp = bnxt_get_bp_from_dl(dl);
|
||||
int rc;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_NVM_GET_VARIABLE, -1, -1);
|
||||
rc = bnxt_hwrm_nvm_req(bp, id, &req, sizeof(req), &ctx->val);
|
||||
if (!rc)
|
||||
if (id == BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK)
|
||||
ctx->val.vbool = !ctx->val.vbool;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bnxt_dl_nvm_param_set(struct devlink *dl, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
{
|
||||
struct hwrm_nvm_set_variable_input req = {0};
|
||||
struct bnxt *bp = bnxt_get_bp_from_dl(dl);
|
||||
|
||||
if (id == BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK)
|
||||
ctx->val.vbool = !ctx->val.vbool;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_NVM_SET_VARIABLE, -1, -1);
|
||||
return bnxt_hwrm_nvm_req(bp, id, &req, sizeof(req), &ctx->val);
|
||||
}
|
||||
|
||||
#ifdef HAVE_IGNORE_ARI
|
||||
static int bnxt_dl_msix_validate(struct devlink *dl, u32 id,
|
||||
union devlink_param_value val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
int max_val = -1;
|
||||
|
||||
if (id == DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX)
|
||||
max_val = BNXT_MSIX_VEC_MAX;
|
||||
|
||||
if (id == DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN)
|
||||
max_val = BNXT_MSIX_VEC_MIN_MAX;
|
||||
|
||||
if (val.vu32 > max_val) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "MSIX value is exceeding the range");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct devlink_param bnxt_dl_params[] = {
|
||||
DEVLINK_PARAM_GENERIC(ENABLE_SRIOV,
|
||||
BIT(DEVLINK_PARAM_CMODE_PERMANENT),
|
||||
bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set,
|
||||
NULL),
|
||||
#ifdef HAVE_IGNORE_ARI
|
||||
DEVLINK_PARAM_GENERIC(IGNORE_ARI,
|
||||
BIT(DEVLINK_PARAM_CMODE_PERMANENT),
|
||||
bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set,
|
||||
NULL),
|
||||
DEVLINK_PARAM_GENERIC(MSIX_VEC_PER_PF_MAX,
|
||||
BIT(DEVLINK_PARAM_CMODE_PERMANENT),
|
||||
bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set,
|
||||
bnxt_dl_msix_validate),
|
||||
DEVLINK_PARAM_GENERIC(MSIX_VEC_PER_PF_MIN,
|
||||
BIT(DEVLINK_PARAM_CMODE_PERMANENT),
|
||||
bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set,
|
||||
bnxt_dl_msix_validate),
|
||||
#endif
|
||||
DEVLINK_PARAM_DRIVER(BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK,
|
||||
"gre_ver_check", DEVLINK_PARAM_TYPE_BOOL,
|
||||
BIT(DEVLINK_PARAM_CMODE_PERMANENT),
|
||||
bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set,
|
||||
NULL),
|
||||
};
|
||||
|
||||
#ifdef HAVE_DEVLINK_PORT_PARAM
|
||||
static const struct devlink_param bnxt_dl_port_params[] = {
|
||||
};
|
||||
#endif
|
||||
#endif /* HAVE_DEVLINK_PARAM */
|
||||
|
||||
static int bnxt_dl_params_register(struct bnxt *bp)
|
||||
{
|
||||
#ifdef HAVE_DEVLINK_PARAM
|
||||
int rc;
|
||||
|
||||
if (bp->hwrm_spec_code < 0x10600)
|
||||
return 0;
|
||||
|
||||
rc = devlink_params_register(bp->dl, bnxt_dl_params,
|
||||
ARRAY_SIZE(bnxt_dl_params));
|
||||
if (rc) {
|
||||
netdev_warn(bp->dev, "devlink_params_register failed. rc=%d",
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
#ifdef HAVE_DEVLINK_PORT_PARAM
|
||||
rc = devlink_port_params_register(&bp->dl_port, bnxt_dl_port_params,
|
||||
ARRAY_SIZE(bnxt_dl_port_params));
|
||||
if (rc) {
|
||||
netdev_err(bp->dev, "devlink_port_params_register failed");
|
||||
devlink_params_unregister(bp->dl, bnxt_dl_params,
|
||||
ARRAY_SIZE(bnxt_dl_params));
|
||||
return rc;
|
||||
}
|
||||
#endif /* HAVE_DEVLINK_PORT_PARAM */
|
||||
devlink_params_publish(bp->dl);
|
||||
#endif /* HAVE_DEVLINK_PARAM */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bnxt_dl_params_unregister(struct bnxt *bp)
|
||||
{
|
||||
#ifdef HAVE_DEVLINK_PARAM
|
||||
if (bp->hwrm_spec_code < 0x10600)
|
||||
return;
|
||||
|
||||
devlink_params_unregister(bp->dl, bnxt_dl_params,
|
||||
ARRAY_SIZE(bnxt_dl_params));
|
||||
#ifdef HAVE_DEVLINK_PORT_PARAM
|
||||
devlink_port_params_unregister(&bp->dl_port, bnxt_dl_port_params,
|
||||
ARRAY_SIZE(bnxt_dl_port_params));
|
||||
#endif /* HAVE_DEVLINK_PORT_PARAM */
|
||||
#endif /* HAVE_DEVLINK_PARAM */
|
||||
}
|
||||
|
||||
int bnxt_dl_register(struct bnxt *bp)
|
||||
{
|
||||
struct devlink *dl;
|
||||
int rc;
|
||||
|
||||
if (BNXT_PF(bp))
|
||||
dl = devlink_alloc(&bnxt_dl_ops, sizeof(struct bnxt_dl));
|
||||
else
|
||||
dl = devlink_alloc(&bnxt_vf_dl_ops, sizeof(struct bnxt_dl));
|
||||
if (!dl) {
|
||||
netdev_warn(bp->dev, "devlink_alloc failed");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
bnxt_link_bp_to_dl(bp, dl);
|
||||
|
||||
#ifdef CONFIG_VF_REPS
|
||||
/* Add switchdev eswitch mode setting, if SRIOV supported */
|
||||
if (pci_find_ext_capability(bp->pdev, PCI_EXT_CAP_ID_SRIOV) &&
|
||||
bp->hwrm_spec_code > 0x10803)
|
||||
bp->eswitch_mode = DEVLINK_ESWITCH_MODE_LEGACY;
|
||||
#endif
|
||||
|
||||
rc = devlink_register(dl, &bp->pdev->dev);
|
||||
if (rc) {
|
||||
netdev_warn(bp->dev, "devlink_register failed. rc=%d", rc);
|
||||
goto err_dl_free;
|
||||
}
|
||||
|
||||
if (!BNXT_PF(bp))
|
||||
return 0;
|
||||
|
||||
#ifdef HAVE_DEVLINK_PORT_PARAM
|
||||
#ifdef HAVE_DEVLINK_PORT_ATTRS
|
||||
devlink_port_attrs_set(&bp->dl_port, DEVLINK_PORT_FLAVOUR_PHYSICAL,
|
||||
bp->pf.port_id, false, 0, bp->dsn,
|
||||
sizeof(bp->dsn));
|
||||
#endif
|
||||
rc = devlink_port_register(dl, &bp->dl_port, bp->pf.port_id);
|
||||
if (rc) {
|
||||
netdev_err(bp->dev, "devlink_port_register failed");
|
||||
goto err_dl_unreg;
|
||||
}
|
||||
#endif /* HAVE_DEVLINK_PORT_PARAM */
|
||||
|
||||
rc = bnxt_dl_params_register(bp);
|
||||
if (rc)
|
||||
goto err_dl_port_unreg;
|
||||
|
||||
return 0;
|
||||
|
||||
err_dl_port_unreg:
|
||||
#ifdef HAVE_DEVLINK_PORT_PARAM
|
||||
devlink_port_unregister(&bp->dl_port);
|
||||
err_dl_unreg:
|
||||
#endif /* HAVE_DEVLINK_PORT_PARAM */
|
||||
devlink_unregister(dl);
|
||||
err_dl_free:
|
||||
bnxt_link_bp_to_dl(bp, NULL);
|
||||
devlink_free(dl);
|
||||
return rc;
|
||||
}
|
||||
|
||||
void bnxt_dl_unregister(struct bnxt *bp)
|
||||
{
|
||||
struct devlink *dl = bp->dl;
|
||||
|
||||
if (!dl)
|
||||
return;
|
||||
|
||||
if (BNXT_PF(bp)) {
|
||||
bnxt_dl_params_unregister(bp);
|
||||
#ifdef HAVE_DEVLINK_PORT_PARAM
|
||||
devlink_port_unregister(&bp->dl_port);
|
||||
#endif
|
||||
}
|
||||
devlink_unregister(dl);
|
||||
devlink_free(dl);
|
||||
}
|
||||
#endif /* CONFIG_VF_REPS || HAVE_DEVLINK_PARAM */
|
||||
|
||||
#ifndef HAVE_DEVLINK_HEALTH_REPORT
|
||||
void bnxt_devlink_health_report(struct bnxt *bp, unsigned long event)
|
||||
{
|
||||
switch (event) {
|
||||
case BNXT_FW_RESET_NOTIFY_SP_EVENT:
|
||||
bnxt_fw_reset(bp);
|
||||
break;
|
||||
case BNXT_FW_EXCEPTION_SP_EVENT:
|
||||
bnxt_fw_exception(bp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bnxt_dl_health_status_update(struct bnxt *bp, bool healthy)
|
||||
{
|
||||
}
|
||||
|
||||
void bnxt_dl_health_recovery_done(struct bnxt *bp)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* HAVE_DEVLINK_HEALTH_REPORT */
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
/* Broadcom NetXtreme-C/E network driver.
|
||||
*
|
||||
* Copyright (c) 2017 Broadcom Limited
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef BNXT_DEVLINK_H
|
||||
#define BNXT_DEVLINK_H
|
||||
|
||||
#if defined(CONFIG_VF_REPS) || defined(HAVE_DEVLINK_PARAM)
|
||||
/* Struct to hold housekeeping info needed by devlink interface */
|
||||
struct bnxt_dl {
|
||||
struct bnxt *bp; /* back ptr to the controlling dev */
|
||||
};
|
||||
|
||||
static inline struct bnxt *bnxt_get_bp_from_dl(struct devlink *dl)
|
||||
{
|
||||
return ((struct bnxt_dl *)devlink_priv(dl))->bp;
|
||||
}
|
||||
|
||||
/* To clear devlink pointer from bp, pass NULL dl */
|
||||
static inline void bnxt_link_bp_to_dl(struct bnxt *bp, struct devlink *dl)
|
||||
{
|
||||
bp->dl = dl;
|
||||
|
||||
/* add a back pointer in dl to bp */
|
||||
if (dl) {
|
||||
struct bnxt_dl *bp_dl = devlink_priv(dl);
|
||||
|
||||
bp_dl->bp = bp;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_DEVLINK_PARAM
|
||||
#define NVM_OFF_MSIX_VEC_PER_PF_MAX 108
|
||||
#define NVM_OFF_MSIX_VEC_PER_PF_MIN 114
|
||||
#define NVM_OFF_IGNORE_ARI 164
|
||||
#define NVM_OFF_DIS_GRE_VER_CHECK 171
|
||||
#define NVM_OFF_ENABLE_SRIOV 401
|
||||
#define NVM_OFF_NVM_CFG_VER 602
|
||||
|
||||
#define BNXT_NVM_CFG_VER_BITS 24
|
||||
#define BNXT_NVM_CFG_VER_BYTES 4
|
||||
|
||||
#define BNXT_MSIX_VEC_MAX 1280
|
||||
#define BNXT_MSIX_VEC_MIN_MAX 128
|
||||
|
||||
union bnxt_nvm_data {
|
||||
u8 val8;
|
||||
__le32 val32;
|
||||
};
|
||||
|
||||
enum bnxt_nvm_dir_type {
|
||||
BNXT_NVM_SHARED_CFG = 40,
|
||||
BNXT_NVM_PORT_CFG,
|
||||
BNXT_NVM_FUNC_CFG,
|
||||
};
|
||||
|
||||
struct bnxt_dl_nvm_param {
|
||||
u16 id;
|
||||
u16 offset;
|
||||
u16 dir_type;
|
||||
u16 nvm_num_bits;
|
||||
u8 dl_num_bytes;
|
||||
};
|
||||
#endif /* HAVE_DEVLINK_PARAM */
|
||||
|
||||
int bnxt_dl_register(struct bnxt *bp);
|
||||
void bnxt_dl_unregister(struct bnxt *bp);
|
||||
|
||||
#else /* CONFIG_VF_REPS || HAVE_DEVLINK_PARAM */
|
||||
|
||||
static inline int bnxt_dl_register(struct bnxt *bp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void bnxt_dl_unregister(struct bnxt *bp)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_VF_REPS || HAVE_DEVLINK_PARAM */
|
||||
void bnxt_devlink_health_report(struct bnxt *bp, unsigned long event);
|
||||
void bnxt_dl_health_status_update(struct bnxt *bp, bool healthy);
|
||||
void bnxt_dl_health_recovery_done(struct bnxt *bp);
|
||||
#ifdef HAVE_DEVLINK_HEALTH_REPORT
|
||||
void bnxt_dl_fw_reporters_create(struct bnxt *bp);
|
||||
void bnxt_dl_fw_reporters_destroy(struct bnxt *bp, bool all);
|
||||
#else
|
||||
static inline void bnxt_dl_fw_reporters_create(struct bnxt *bp)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void bnxt_dl_fw_reporters_destroy(struct bnxt *bp, bool all)
|
||||
{
|
||||
}
|
||||
#endif /* HAVE_DEVLINK_HEALTH_REPORT */
|
||||
#endif /* BNXT_DEVLINK_H */
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/* Broadcom NetXtreme-C/E network driver.
|
||||
*
|
||||
* Copyright (c) 2017-2018 Broadcom Limited
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include "bnxt_compat.h"
|
||||
#ifdef HAVE_DIM
|
||||
#include <linux/dim.h>
|
||||
#else
|
||||
#include "bnxt_dim.h"
|
||||
#endif
|
||||
#include "bnxt_hsi.h"
|
||||
#include "bnxt.h"
|
||||
|
||||
void bnxt_dim_work(struct work_struct *work)
|
||||
{
|
||||
struct dim *dim = container_of(work, struct dim, work);
|
||||
struct bnxt_cp_ring_info *cpr = container_of(dim,
|
||||
struct bnxt_cp_ring_info,
|
||||
dim);
|
||||
struct bnxt_napi *bnapi = container_of(cpr,
|
||||
struct bnxt_napi,
|
||||
cp_ring);
|
||||
struct dim_cq_moder cur_moder =
|
||||
net_dim_get_rx_moderation(dim->mode, dim->profile_ix);
|
||||
|
||||
cpr->rx_ring_coal.coal_ticks = cur_moder.usec;
|
||||
cpr->rx_ring_coal.coal_bufs = cur_moder.pkts;
|
||||
|
||||
bnxt_hwrm_set_ring_coal(bnapi->bp, bnapi);
|
||||
dim->state = DIM_START_MEASURE;
|
||||
}
|
||||
|
|
@ -0,0 +1,379 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Mellanox Technologies. All rights reserved.
|
||||
* Copyright (c) 2017-2018, Broadcom Limited. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef NET_DIM_H
|
||||
#define NET_DIM_H
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
struct dim_cq_moder {
|
||||
u16 usec;
|
||||
u16 pkts;
|
||||
u8 cq_period_mode;
|
||||
};
|
||||
|
||||
struct dim_sample {
|
||||
ktime_t time;
|
||||
u32 pkt_ctr;
|
||||
u32 byte_ctr;
|
||||
u16 event_ctr;
|
||||
};
|
||||
|
||||
struct dim_stats {
|
||||
int ppms; /* packets per msec */
|
||||
int bpms; /* bytes per msec */
|
||||
int epms; /* events per msec */
|
||||
};
|
||||
|
||||
struct dim { /* Adaptive Moderation */
|
||||
u8 state;
|
||||
struct dim_stats prev_stats;
|
||||
struct dim_sample start_sample;
|
||||
struct work_struct work;
|
||||
u8 profile_ix;
|
||||
u8 mode;
|
||||
u8 tune_state;
|
||||
u8 steps_right;
|
||||
u8 steps_left;
|
||||
u8 tired;
|
||||
};
|
||||
|
||||
enum {
|
||||
DIM_CQ_PERIOD_MODE_START_FROM_EQE = 0x0,
|
||||
DIM_CQ_PERIOD_MODE_START_FROM_CQE = 0x1,
|
||||
DIM_CQ_PERIOD_NUM_MODES
|
||||
};
|
||||
|
||||
/* Adaptive moderation logic */
|
||||
enum {
|
||||
DIM_START_MEASURE,
|
||||
DIM_MEASURE_IN_PROGRESS,
|
||||
DIM_APPLY_NEW_PROFILE,
|
||||
};
|
||||
|
||||
enum {
|
||||
DIM_PARKING_ON_TOP,
|
||||
DIM_PARKING_TIRED,
|
||||
DIM_GOING_RIGHT,
|
||||
DIM_GOING_LEFT,
|
||||
};
|
||||
|
||||
enum {
|
||||
DIM_STATS_WORSE,
|
||||
DIM_STATS_SAME,
|
||||
DIM_STATS_BETTER,
|
||||
};
|
||||
|
||||
enum {
|
||||
DIM_STEPPED,
|
||||
DIM_TOO_TIRED,
|
||||
DIM_ON_EDGE,
|
||||
};
|
||||
|
||||
#define NET_DIM_PARAMS_NUM_PROFILES 5
|
||||
/* Adaptive moderation profiles */
|
||||
#define NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE 256
|
||||
#define NET_DIM_DEF_PROFILE_CQE 1
|
||||
#define NET_DIM_DEF_PROFILE_EQE 1
|
||||
|
||||
/* All profiles sizes must be NET_PARAMS_DIM_NUM_PROFILES */
|
||||
#define NET_DIM_EQE_PROFILES { \
|
||||
{1, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
|
||||
{4, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
|
||||
{8, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
|
||||
{32, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
|
||||
{256, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
|
||||
}
|
||||
|
||||
#define NET_DIM_CQE_PROFILES { \
|
||||
{2, 256}, \
|
||||
{8, 128}, \
|
||||
{16, 64}, \
|
||||
{32, 64}, \
|
||||
{64, 64} \
|
||||
}
|
||||
|
||||
static const struct dim_cq_moder
|
||||
profile[DIM_CQ_PERIOD_NUM_MODES][NET_DIM_PARAMS_NUM_PROFILES] = {
|
||||
NET_DIM_EQE_PROFILES,
|
||||
NET_DIM_CQE_PROFILES,
|
||||
};
|
||||
|
||||
static inline struct dim_cq_moder
|
||||
net_dim_get_rx_moderation(u8 cq_period_mode, int ix)
|
||||
{
|
||||
struct dim_cq_moder cq_moder = profile[cq_period_mode][ix];
|
||||
|
||||
cq_moder.cq_period_mode = cq_period_mode;
|
||||
return cq_moder;
|
||||
}
|
||||
|
||||
static inline struct dim_cq_moder
|
||||
net_dim_get_def_rx_moderation(u8 rx_cq_period_mode)
|
||||
{
|
||||
int default_profile_ix;
|
||||
|
||||
if (rx_cq_period_mode == DIM_CQ_PERIOD_MODE_START_FROM_CQE)
|
||||
default_profile_ix = NET_DIM_DEF_PROFILE_CQE;
|
||||
else /* DIM_CQ_PERIOD_MODE_START_FROM_EQE */
|
||||
default_profile_ix = NET_DIM_DEF_PROFILE_EQE;
|
||||
|
||||
return net_dim_get_rx_moderation(rx_cq_period_mode, default_profile_ix);
|
||||
}
|
||||
|
||||
static inline bool dim_on_top(struct dim *dim)
|
||||
{
|
||||
switch (dim->tune_state) {
|
||||
case DIM_PARKING_ON_TOP:
|
||||
case DIM_PARKING_TIRED:
|
||||
return true;
|
||||
case DIM_GOING_RIGHT:
|
||||
return (dim->steps_left > 1) && (dim->steps_right == 1);
|
||||
default: /* DIM_GOING_LEFT */
|
||||
return (dim->steps_right > 1) && (dim->steps_left == 1);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void dim_turn(struct dim *dim)
|
||||
{
|
||||
switch (dim->tune_state) {
|
||||
case DIM_PARKING_ON_TOP:
|
||||
case DIM_PARKING_TIRED:
|
||||
break;
|
||||
case DIM_GOING_RIGHT:
|
||||
dim->tune_state = DIM_GOING_LEFT;
|
||||
dim->steps_left = 0;
|
||||
break;
|
||||
case DIM_GOING_LEFT:
|
||||
dim->tune_state = DIM_GOING_RIGHT;
|
||||
dim->steps_right = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int net_dim_step(struct dim *dim)
|
||||
{
|
||||
if (dim->tired == (NET_DIM_PARAMS_NUM_PROFILES * 2))
|
||||
return DIM_TOO_TIRED;
|
||||
|
||||
switch (dim->tune_state) {
|
||||
case DIM_PARKING_ON_TOP:
|
||||
case DIM_PARKING_TIRED:
|
||||
break;
|
||||
case DIM_GOING_RIGHT:
|
||||
if (dim->profile_ix == (NET_DIM_PARAMS_NUM_PROFILES - 1))
|
||||
return DIM_ON_EDGE;
|
||||
dim->profile_ix++;
|
||||
dim->steps_right++;
|
||||
break;
|
||||
case DIM_GOING_LEFT:
|
||||
if (dim->profile_ix == 0)
|
||||
return DIM_ON_EDGE;
|
||||
dim->profile_ix--;
|
||||
dim->steps_left++;
|
||||
break;
|
||||
}
|
||||
|
||||
dim->tired++;
|
||||
return DIM_STEPPED;
|
||||
}
|
||||
|
||||
static inline void dim_park_on_top(struct dim *dim)
|
||||
{
|
||||
dim->steps_right = 0;
|
||||
dim->steps_left = 0;
|
||||
dim->tired = 0;
|
||||
dim->tune_state = DIM_PARKING_ON_TOP;
|
||||
}
|
||||
|
||||
static inline void dim_park_tired(struct dim *dim)
|
||||
{
|
||||
dim->steps_right = 0;
|
||||
dim->steps_left = 0;
|
||||
dim->tune_state = DIM_PARKING_TIRED;
|
||||
}
|
||||
|
||||
static inline void net_dim_exit_parking(struct dim *dim)
|
||||
{
|
||||
dim->tune_state = dim->profile_ix ? DIM_GOING_LEFT :
|
||||
DIM_GOING_RIGHT;
|
||||
net_dim_step(dim);
|
||||
}
|
||||
|
||||
#define IS_SIGNIFICANT_DIFF(val, ref) \
|
||||
(((100 * abs((val) - (ref))) / (ref)) > 10) /* more than 10% difference */
|
||||
|
||||
static inline int net_dim_stats_compare(struct dim_stats *curr,
|
||||
struct dim_stats *prev)
|
||||
{
|
||||
if (!prev->bpms)
|
||||
return curr->bpms ? DIM_STATS_BETTER :
|
||||
DIM_STATS_SAME;
|
||||
|
||||
if (IS_SIGNIFICANT_DIFF(curr->bpms, prev->bpms))
|
||||
return (curr->bpms > prev->bpms) ? DIM_STATS_BETTER :
|
||||
DIM_STATS_WORSE;
|
||||
|
||||
if (!prev->ppms)
|
||||
return curr->ppms ? DIM_STATS_BETTER :
|
||||
DIM_STATS_SAME;
|
||||
|
||||
if (IS_SIGNIFICANT_DIFF(curr->ppms, prev->ppms))
|
||||
return (curr->ppms > prev->ppms) ? DIM_STATS_BETTER :
|
||||
DIM_STATS_WORSE;
|
||||
|
||||
if (!prev->epms)
|
||||
return DIM_STATS_SAME;
|
||||
|
||||
if (IS_SIGNIFICANT_DIFF(curr->epms, prev->epms))
|
||||
return (curr->epms < prev->epms) ? DIM_STATS_BETTER :
|
||||
DIM_STATS_WORSE;
|
||||
|
||||
return DIM_STATS_SAME;
|
||||
}
|
||||
|
||||
static inline bool net_dim_decision(struct dim_stats *curr_stats,
|
||||
struct dim *dim)
|
||||
{
|
||||
int prev_state = dim->tune_state;
|
||||
int prev_ix = dim->profile_ix;
|
||||
int stats_res;
|
||||
int step_res;
|
||||
|
||||
switch (dim->tune_state) {
|
||||
case DIM_PARKING_ON_TOP:
|
||||
stats_res = net_dim_stats_compare(curr_stats, &dim->prev_stats);
|
||||
if (stats_res != DIM_STATS_SAME)
|
||||
net_dim_exit_parking(dim);
|
||||
break;
|
||||
|
||||
case DIM_PARKING_TIRED:
|
||||
dim->tired--;
|
||||
if (!dim->tired)
|
||||
net_dim_exit_parking(dim);
|
||||
break;
|
||||
|
||||
case DIM_GOING_RIGHT:
|
||||
case DIM_GOING_LEFT:
|
||||
stats_res = net_dim_stats_compare(curr_stats, &dim->prev_stats);
|
||||
if (stats_res != DIM_STATS_BETTER)
|
||||
dim_turn(dim);
|
||||
|
||||
if (dim_on_top(dim)) {
|
||||
dim_park_on_top(dim);
|
||||
break;
|
||||
}
|
||||
|
||||
step_res = net_dim_step(dim);
|
||||
switch (step_res) {
|
||||
case DIM_ON_EDGE:
|
||||
dim_park_on_top(dim);
|
||||
break;
|
||||
case DIM_TOO_TIRED:
|
||||
dim_park_tired(dim);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if ((prev_state != DIM_PARKING_ON_TOP) ||
|
||||
(dim->tune_state != DIM_PARKING_ON_TOP))
|
||||
dim->prev_stats = *curr_stats;
|
||||
|
||||
return dim->profile_ix != prev_ix;
|
||||
}
|
||||
|
||||
static inline void dim_update_sample(u16 event_ctr,
|
||||
u64 packets,
|
||||
u64 bytes,
|
||||
struct dim_sample *s)
|
||||
{
|
||||
s->time = ktime_get();
|
||||
s->pkt_ctr = packets;
|
||||
s->byte_ctr = bytes;
|
||||
s->event_ctr = event_ctr;
|
||||
}
|
||||
|
||||
#define DIM_NEVENTS 320
|
||||
#define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE)
|
||||
#define BIT_GAP(bits, end, start) ((((end) - (start)) + BIT_ULL(bits)) & (BIT_ULL(bits) - 1))
|
||||
|
||||
static inline void dim_calc_stats(struct dim_sample *start,
|
||||
struct dim_sample *end,
|
||||
struct dim_stats *curr_stats)
|
||||
{
|
||||
/* u32 holds up to 71 minutes, should be enough */
|
||||
u32 delta_us = ktime_us_delta(end->time, start->time);
|
||||
u32 npkts = BIT_GAP(BITS_PER_TYPE(u32), end->pkt_ctr, start->pkt_ctr);
|
||||
u32 nbytes = BIT_GAP(BITS_PER_TYPE(u32), end->byte_ctr,
|
||||
start->byte_ctr);
|
||||
|
||||
if (!delta_us)
|
||||
return;
|
||||
|
||||
curr_stats->ppms = DIV_ROUND_UP(npkts * USEC_PER_MSEC, delta_us);
|
||||
curr_stats->bpms = DIV_ROUND_UP(nbytes * USEC_PER_MSEC, delta_us);
|
||||
curr_stats->epms = DIV_ROUND_UP(DIM_NEVENTS * USEC_PER_MSEC,
|
||||
delta_us);
|
||||
}
|
||||
|
||||
static inline void net_dim(struct dim *dim,
|
||||
struct dim_sample end_sample)
|
||||
{
|
||||
struct dim_stats curr_stats;
|
||||
u16 nevents;
|
||||
|
||||
switch (dim->state) {
|
||||
case DIM_MEASURE_IN_PROGRESS:
|
||||
nevents = BIT_GAP(BITS_PER_TYPE(u16),
|
||||
end_sample.event_ctr,
|
||||
dim->start_sample.event_ctr);
|
||||
if (nevents < DIM_NEVENTS)
|
||||
break;
|
||||
dim_calc_stats(&dim->start_sample, &end_sample, &curr_stats);
|
||||
if (net_dim_decision(&curr_stats, dim)) {
|
||||
dim->state = DIM_APPLY_NEW_PROFILE;
|
||||
schedule_work(&dim->work);
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
case DIM_START_MEASURE:
|
||||
dim->state = DIM_MEASURE_IN_PROGRESS;
|
||||
break;
|
||||
case DIM_APPLY_NEW_PROFILE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* NET_DIM_H */
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -11,6 +11,11 @@
|
|||
#ifndef BNXT_ETHTOOL_H
|
||||
#define BNXT_ETHTOOL_H
|
||||
|
||||
#if defined(ETHTOOL_GET_DUMP_FLAG) && !defined(GET_ETHTOOL_OP_EXT)
|
||||
#include <linux/time.h>
|
||||
#include <linux/rtc.h>
|
||||
#endif
|
||||
|
||||
struct bnxt_led_cfg {
|
||||
u8 led_id;
|
||||
u8 led_state;
|
||||
|
|
@ -22,6 +27,59 @@ struct bnxt_led_cfg {
|
|||
u8 rsvd;
|
||||
};
|
||||
|
||||
#if defined(ETHTOOL_GET_DUMP_FLAG) && !defined(GET_ETHTOOL_OP_EXT)
|
||||
#define COREDUMP_LIST_BUF_LEN 2048
|
||||
#define COREDUMP_RETRIEVE_BUF_LEN 4096
|
||||
|
||||
struct bnxt_coredump {
|
||||
void *data;
|
||||
int data_size;
|
||||
u16 total_segs;
|
||||
};
|
||||
|
||||
struct bnxt_time {
|
||||
#if defined(HAVE_TIME64)
|
||||
struct tm tm;
|
||||
#elif defined(CONFIG_RTC_LIB) || defined(CONFIG_RTC_LIB_MODULE)
|
||||
struct rtc_time tm;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define BNXT_COREDUMP_BUF_LEN(len) ((len) - sizeof(struct bnxt_coredump_record))
|
||||
|
||||
struct bnxt_hwrm_dbg_dma_info {
|
||||
void *dest_buf;
|
||||
int dest_buf_size;
|
||||
u16 dma_len;
|
||||
u16 seq_off;
|
||||
u16 data_len_off;
|
||||
u16 segs;
|
||||
u32 seg_start;
|
||||
u32 buf_len;
|
||||
};
|
||||
|
||||
struct hwrm_dbg_cmn_input {
|
||||
__le16 req_type;
|
||||
__le16 cmpl_ring;
|
||||
__le16 seq_id;
|
||||
__le16 target_id;
|
||||
__le64 resp_addr;
|
||||
__le64 host_dest_addr;
|
||||
__le32 host_buf_len;
|
||||
};
|
||||
|
||||
struct hwrm_dbg_cmn_output {
|
||||
__le16 error_code;
|
||||
__le16 req_type;
|
||||
__le16 seq_id;
|
||||
__le16 resp_len;
|
||||
u8 flags;
|
||||
#define HWRM_DBG_CMN_FLAGS_MORE 1
|
||||
};
|
||||
|
||||
#define BNXT_CRASH_DUMP_LEN (8 << 20)
|
||||
#endif /* defined(ETHTOOL_GET_DUMP_FLAG) && !defined(GET_ETHTOOL_OP_EXT) */
|
||||
|
||||
#define BNXT_LED_DFLT_ENA \
|
||||
(PORT_LED_CFG_REQ_ENABLES_LED0_ID | \
|
||||
PORT_LED_CFG_REQ_ENABLES_LED0_STATE | \
|
||||
|
|
@ -34,11 +92,18 @@ struct bnxt_led_cfg {
|
|||
#define BNXT_LED_DFLT_ENABLES(x) \
|
||||
cpu_to_le32(BNXT_LED_DFLT_ENA << (BNXT_LED_DFLT_ENA_SHIFT * (x)))
|
||||
|
||||
#define BNXT_FW_RESET_AP 0xfffe
|
||||
#define BNXT_FW_RESET_CHIP 0xffff
|
||||
|
||||
#define BNXT_PXP_REG_LEN 0x3110
|
||||
|
||||
extern const struct ethtool_ops bnxt_ethtool_ops;
|
||||
|
||||
u32 _bnxt_fw_to_ethtool_adv_spds(u16, u8);
|
||||
u32 bnxt_fw_to_ethtool_speed(u16);
|
||||
u16 bnxt_get_fw_auto_link_speeds(u32);
|
||||
int bnxt_flash_package_from_file(struct net_device *dev, const char *filename,
|
||||
u32 install_type);
|
||||
void bnxt_ethtool_init(struct bnxt *bp);
|
||||
void bnxt_ethtool_free(struct bnxt *bp);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
/* Broadcom NetXtreme-C/E network driver.
|
||||
*
|
||||
* Copyright (c) 2016-2017 Broadcom Limited
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef BNXT_EXTRA_VER_H
|
||||
#define BNXT_EXTRA_VER_H
|
||||
|
||||
#define DRV_MODULE_EXTRA_VER "-216.1.92.0"
|
||||
|
||||
#endif
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
/* Broadcom NetXtreme-C/E network driver.
|
||||
*
|
||||
* Copyright (c) 2014-2016 Broadcom Corporation
|
||||
* Copyright (c) 2016-2017 Broadcom Limited
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,835 @@
|
|||
/* Broadcom NetXtreme-C/E network driver.
|
||||
*
|
||||
* Copyright (c) 2017 Broadcom Limited
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
|
||||
#include "bnxt_compat.h"
|
||||
#include "bnxt_hsi.h"
|
||||
#include "bnxt.h"
|
||||
#include "bnxt_ulp.h"
|
||||
#include "bnxt_lfc.h"
|
||||
#include "bnxt_lfc_ioctl.h"
|
||||
|
||||
#ifdef CONFIG_BNXT_LFC
|
||||
|
||||
#define MAX_LFC_OPEN_ULP_DEVICES 32
|
||||
#define PRIME_1 29
|
||||
#define PRIME_2 31
|
||||
|
||||
static struct bnxt_gloabl_dev blfc_global_dev;
|
||||
static struct bnxt_lfc_dev_array blfc_array[MAX_LFC_OPEN_ULP_DEVICES];
|
||||
|
||||
static bool bnxt_lfc_inited;
|
||||
static bool is_domain_available;
|
||||
static int domain_no;
|
||||
static void bnxt_lfc_unreg(struct bnxt_lfc_dev *blfc_dev);
|
||||
|
||||
static int lfc_device_event(struct notifier_block *unused,
|
||||
unsigned long event, void *ptr)
|
||||
{
|
||||
u32 i;
|
||||
struct bnxt_lfc_dev *blfc_dev;
|
||||
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
|
||||
|
||||
switch (event) {
|
||||
case NETDEV_UNREGISTER:
|
||||
for (i = 0; i < MAX_LFC_OPEN_ULP_DEVICES; i++) {
|
||||
mutex_lock(&blfc_global_dev.bnxt_lfc_lock);
|
||||
blfc_dev = blfc_array[i].bnxt_lfc_dev;
|
||||
if (blfc_dev && blfc_dev->ndev == dev) {
|
||||
bnxt_lfc_unreg(blfc_dev);
|
||||
dev_put(blfc_dev->ndev);
|
||||
kfree(blfc_dev);
|
||||
blfc_array[i].bnxt_lfc_dev = NULL;
|
||||
blfc_array[i].taken = 0;
|
||||
mutex_unlock(&blfc_global_dev.bnxt_lfc_lock);
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&blfc_global_dev.bnxt_lfc_lock);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* do nothing */
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct notifier_block lfc_device_notifier = {
|
||||
.notifier_call = lfc_device_event
|
||||
};
|
||||
|
||||
static u32 bnxt_lfc_get_hash_key(u32 bus, u32 devfn)
|
||||
{
|
||||
return ((bus * PRIME_1 + devfn) * PRIME_2) % MAX_LFC_OPEN_ULP_DEVICES;
|
||||
}
|
||||
|
||||
static int32_t bnxt_lfc_probe_and_reg(struct bnxt_lfc_dev *blfc_dev)
|
||||
{
|
||||
int32_t rc;
|
||||
struct pci_dev *pdev = blfc_dev->pdev;
|
||||
|
||||
blfc_dev->bp = netdev_priv(blfc_dev->ndev);
|
||||
if (!blfc_dev->bp->ulp_probe) {
|
||||
BNXT_LFC_ERR(&pdev->dev,
|
||||
"Probe routine not valid\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
blfc_dev->en_dev = blfc_dev->bp->ulp_probe(blfc_dev->ndev);
|
||||
if (IS_ERR(blfc_dev->en_dev)) {
|
||||
BNXT_LFC_ERR(&pdev->dev,
|
||||
"Device probing failed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rtnl_lock();
|
||||
rc = blfc_dev->en_dev->en_ops->bnxt_register_device(blfc_dev->en_dev,
|
||||
BNXT_OTHER_ULP,
|
||||
&blfc_dev->uops,
|
||||
blfc_dev);
|
||||
if (rc) {
|
||||
BNXT_LFC_ERR(&pdev->dev,
|
||||
"Device registration failed\n");
|
||||
rtnl_unlock();
|
||||
return rc;
|
||||
}
|
||||
rtnl_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bnxt_lfc_unreg(struct bnxt_lfc_dev *blfc_dev)
|
||||
{
|
||||
int32_t rc;
|
||||
|
||||
rc = blfc_dev->en_dev->en_ops->bnxt_unregister_device(
|
||||
blfc_dev->en_dev,
|
||||
BNXT_OTHER_ULP);
|
||||
if (rc)
|
||||
BNXT_LFC_ERR(&blfc_dev->pdev->dev,
|
||||
"netdev %p unregister failed!",
|
||||
blfc_dev->ndev);
|
||||
}
|
||||
|
||||
static bool bnxt_lfc_is_valid_pdev(struct pci_dev *pdev)
|
||||
{
|
||||
int32_t idx;
|
||||
|
||||
if (!pdev) {
|
||||
BNXT_LFC_ERR(NULL, "No such PCI device\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pdev->vendor != PCI_VENDOR_ID_BROADCOM) {
|
||||
pci_dev_put(pdev);
|
||||
BNXT_LFC_ERR(NULL, "Not a Broadcom PCI device\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (idx = 0; bnxt_pci_tbl[idx].device != 0; idx++) {
|
||||
if (pdev->device == bnxt_pci_tbl[idx].device) {
|
||||
BNXT_LFC_DEBUG(&pdev->dev, "Found valid PCI device\n");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
pci_dev_put(pdev);
|
||||
BNXT_LFC_ERR(NULL, "PCI device not supported\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
static void bnxt_lfc_init_req_hdr(struct input *req_hdr, u16 req_type,
|
||||
u16 cpr_id, u16 tgt_id)
|
||||
{
|
||||
req_hdr->req_type = cpu_to_le16(req_type);
|
||||
req_hdr->cmpl_ring = cpu_to_le16(cpr_id);
|
||||
req_hdr->target_id = cpu_to_le16(tgt_id);
|
||||
}
|
||||
|
||||
static void bnxt_lfc_prep_fw_msg(struct bnxt_fw_msg *fw_msg, void *msg,
|
||||
int32_t msg_len, void *resp,
|
||||
int32_t resp_max_len,
|
||||
int32_t timeout)
|
||||
{
|
||||
fw_msg->msg = msg;
|
||||
fw_msg->msg_len = msg_len;
|
||||
fw_msg->resp = resp;
|
||||
fw_msg->resp_max_len = resp_max_len;
|
||||
fw_msg->timeout = timeout;
|
||||
}
|
||||
|
||||
static int32_t bnxt_lfc_process_nvm_flush(struct bnxt_lfc_dev *blfc_dev)
|
||||
{
|
||||
int32_t rc = 0;
|
||||
struct bnxt_en_dev *en_dev = blfc_dev->en_dev;
|
||||
|
||||
struct hwrm_nvm_flush_input req = {0};
|
||||
struct hwrm_nvm_flush_output resp = {0};
|
||||
struct bnxt_fw_msg fw_msg;
|
||||
|
||||
bnxt_lfc_init_req_hdr((void *)&req,
|
||||
HWRM_NVM_FLUSH, -1, -1);
|
||||
bnxt_lfc_prep_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp,
|
||||
sizeof(resp), BNXT_NVM_FLUSH_TIMEOUT);
|
||||
rc = en_dev->en_ops->bnxt_send_fw_msg(en_dev, BNXT_OTHER_ULP, &fw_msg);
|
||||
if (rc)
|
||||
BNXT_LFC_ERR(&blfc_dev->pdev->dev,
|
||||
"Failed to send NVM_FLUSH FW msg, rc = 0x%x", rc);
|
||||
return rc;
|
||||
|
||||
}
|
||||
static int32_t bnxt_lfc_process_nvm_get_var_req(struct bnxt_lfc_dev *blfc_dev,
|
||||
struct bnxt_lfc_nvm_get_var_req
|
||||
*nvm_get_var_req)
|
||||
{
|
||||
int32_t rc;
|
||||
uint16_t len_in_bytes;
|
||||
struct pci_dev *pdev = blfc_dev->pdev;
|
||||
struct bnxt_en_dev *en_dev = blfc_dev->en_dev;
|
||||
|
||||
struct hwrm_nvm_get_variable_input req = {0};
|
||||
struct hwrm_nvm_get_variable_output resp = {0};
|
||||
struct bnxt_fw_msg fw_msg;
|
||||
void *dest_data_addr = NULL;
|
||||
dma_addr_t dest_data_dma_addr;
|
||||
|
||||
if (nvm_get_var_req->len_in_bits == 0) {
|
||||
BNXT_LFC_ERR(&blfc_dev->pdev->dev, "Invalid Length\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
len_in_bytes = (nvm_get_var_req->len_in_bits + 7) / 8;
|
||||
dest_data_addr = dma_alloc_coherent(&pdev->dev,
|
||||
len_in_bytes,
|
||||
&dest_data_dma_addr,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (dest_data_addr == NULL) {
|
||||
BNXT_LFC_ERR(&blfc_dev->pdev->dev,
|
||||
"Failed to alloc mem for data\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
bnxt_lfc_init_req_hdr((void *)&req,
|
||||
HWRM_NVM_GET_VARIABLE, -1, -1);
|
||||
req.dest_data_addr = cpu_to_le64(dest_data_dma_addr);
|
||||
req.data_len = cpu_to_le16(nvm_get_var_req->len_in_bits);
|
||||
req.option_num = cpu_to_le16(nvm_get_var_req->option_num);
|
||||
req.dimensions = cpu_to_le16(nvm_get_var_req->dimensions);
|
||||
req.index_0 = cpu_to_le16(nvm_get_var_req->index_0);
|
||||
req.index_1 = cpu_to_le16(nvm_get_var_req->index_1);
|
||||
req.index_2 = cpu_to_le16(nvm_get_var_req->index_2);
|
||||
req.index_3 = cpu_to_le16(nvm_get_var_req->index_3);
|
||||
|
||||
bnxt_lfc_prep_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp,
|
||||
sizeof(resp), DFLT_HWRM_CMD_TIMEOUT);
|
||||
|
||||
rc = en_dev->en_ops->bnxt_send_fw_msg(en_dev, BNXT_OTHER_ULP, &fw_msg);
|
||||
if (rc) {
|
||||
BNXT_LFC_ERR(&blfc_dev->pdev->dev,
|
||||
"Failed to send NVM_GET_VARIABLE FW msg, rc = 0x%x",
|
||||
rc);
|
||||
goto done;
|
||||
}
|
||||
|
||||
rc = copy_to_user(nvm_get_var_req->out_val, dest_data_addr,
|
||||
len_in_bytes);
|
||||
if (rc != 0) {
|
||||
BNXT_LFC_ERR(&blfc_dev->pdev->dev,
|
||||
"Failed to send %d characters to the user\n", rc);
|
||||
rc = -EFAULT;
|
||||
}
|
||||
done:
|
||||
dma_free_coherent(&pdev->dev, (nvm_get_var_req->len_in_bits),
|
||||
dest_data_addr,
|
||||
dest_data_dma_addr);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int32_t bnxt_lfc_process_nvm_set_var_req(struct bnxt_lfc_dev *blfc_dev,
|
||||
struct bnxt_lfc_nvm_set_var_req
|
||||
*nvm_set_var_req)
|
||||
{
|
||||
int32_t rc;
|
||||
uint16_t len_in_bytes;
|
||||
struct pci_dev *pdev = blfc_dev->pdev;
|
||||
struct bnxt_en_dev *en_dev = blfc_dev->en_dev;
|
||||
|
||||
struct hwrm_nvm_set_variable_input req = {0};
|
||||
struct hwrm_nvm_set_variable_output resp = {0};
|
||||
struct bnxt_fw_msg fw_msg;
|
||||
void *src_data_addr = NULL;
|
||||
dma_addr_t src_data_dma_addr;
|
||||
|
||||
if (nvm_set_var_req->len_in_bits == 0) {
|
||||
BNXT_LFC_ERR(&blfc_dev->pdev->dev, "Invalid Length\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
len_in_bytes = (nvm_set_var_req->len_in_bits + 7) / 8;
|
||||
src_data_addr = dma_alloc_coherent(&pdev->dev,
|
||||
len_in_bytes,
|
||||
&src_data_dma_addr,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (src_data_addr == NULL) {
|
||||
BNXT_LFC_ERR(&blfc_dev->pdev->dev,
|
||||
"Failed to alloc mem for data\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
rc = copy_from_user(src_data_addr,
|
||||
nvm_set_var_req->in_val,
|
||||
len_in_bytes);
|
||||
|
||||
if (rc != 0) {
|
||||
BNXT_LFC_ERR(&blfc_dev->pdev->dev,
|
||||
"Failed to send %d bytes from the user\n", rc);
|
||||
rc = -EFAULT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
bnxt_lfc_init_req_hdr((void *)&req,
|
||||
HWRM_NVM_SET_VARIABLE, -1, -1);
|
||||
req.src_data_addr = cpu_to_le64(src_data_dma_addr);
|
||||
req.data_len = cpu_to_le16(nvm_set_var_req->len_in_bits);
|
||||
req.option_num = cpu_to_le16(nvm_set_var_req->option_num);
|
||||
req.dimensions = cpu_to_le16(nvm_set_var_req->dimensions);
|
||||
req.index_0 = cpu_to_le16(nvm_set_var_req->index_0);
|
||||
req.index_1 = cpu_to_le16(nvm_set_var_req->index_1);
|
||||
req.index_2 = cpu_to_le16(nvm_set_var_req->index_2);
|
||||
req.index_3 = cpu_to_le16(nvm_set_var_req->index_3);
|
||||
|
||||
bnxt_lfc_prep_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp,
|
||||
sizeof(resp), DFLT_HWRM_CMD_TIMEOUT);
|
||||
|
||||
rc = en_dev->en_ops->bnxt_send_fw_msg(en_dev, BNXT_OTHER_ULP, &fw_msg);
|
||||
if (rc)
|
||||
BNXT_LFC_ERR(&blfc_dev->pdev->dev,
|
||||
"Failed to send NVM_SET_VARIABLE FW msg, rc = 0x%x", rc);
|
||||
done:
|
||||
dma_free_coherent(&pdev->dev, len_in_bytes,
|
||||
src_data_addr,
|
||||
src_data_dma_addr);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int32_t bnxt_lfc_fill_fw_msg(struct pci_dev *pdev,
|
||||
struct bnxt_fw_msg *fw_msg,
|
||||
struct blfc_fw_msg *msg)
|
||||
{
|
||||
int32_t rc = 0;
|
||||
|
||||
if (copy_from_user(fw_msg->msg,
|
||||
(void __user *)((unsigned long)msg->usr_req),
|
||||
msg->len_req)) {
|
||||
BNXT_LFC_ERR(&pdev->dev, "Failed to copy data from user\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
fw_msg->msg_len = msg->len_req;
|
||||
fw_msg->resp_max_len = msg->len_resp;
|
||||
if (!msg->timeout)
|
||||
fw_msg->timeout = DFLT_HWRM_CMD_TIMEOUT;
|
||||
else
|
||||
fw_msg->timeout = msg->timeout;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int32_t bnxt_lfc_prepare_dma_operations(struct bnxt_lfc_dev *blfc_dev,
|
||||
struct blfc_fw_msg *msg,
|
||||
struct bnxt_fw_msg *fw_msg)
|
||||
{
|
||||
int32_t rc = 0;
|
||||
uint8_t i, num_allocated = 0;
|
||||
void *dma_ptr;
|
||||
|
||||
for (i = 0; i < msg->num_dma_indications; i++) {
|
||||
if (msg->dma[i].length == 0 ||
|
||||
msg->dma[i].length > MAX_DMA_MEM_SIZE) {
|
||||
BNXT_LFC_ERR(&blfc_dev->pdev->dev,
|
||||
"Invalid DMA memory length\n");
|
||||
rc = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
blfc_dev->dma_virt_addr[i] = dma_alloc_coherent(
|
||||
&blfc_dev->pdev->dev,
|
||||
msg->dma[i].length,
|
||||
&blfc_dev->dma_addr[i],
|
||||
GFP_KERNEL);
|
||||
if (!blfc_dev->dma_virt_addr[i]) {
|
||||
BNXT_LFC_ERR(&blfc_dev->pdev->dev,
|
||||
"Failed to allocate memory for data_addr[%d]\n",
|
||||
i);
|
||||
rc = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
num_allocated++;
|
||||
if (!(msg->dma[i].read_or_write)) {
|
||||
if (copy_from_user(blfc_dev->dma_virt_addr[i],
|
||||
(void __user *)(
|
||||
(unsigned long)(msg->dma[i].data)),
|
||||
msg->dma[i].length)) {
|
||||
BNXT_LFC_ERR(&blfc_dev->pdev->dev,
|
||||
"Failed to copy data from user for data_addr[%d]\n",
|
||||
i);
|
||||
rc = -EFAULT;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
dma_ptr = fw_msg->msg + msg->dma[i].offset;
|
||||
|
||||
if ((PTR_ALIGN(dma_ptr, 8) == dma_ptr) &&
|
||||
(msg->dma[i].offset < msg->len_req)) {
|
||||
__le64 *dmap = dma_ptr;
|
||||
|
||||
*dmap = cpu_to_le64(blfc_dev->dma_addr[i]);
|
||||
} else {
|
||||
BNXT_LFC_ERR(&blfc_dev->pdev->dev,
|
||||
"Wrong input parameter\n");
|
||||
rc = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
err:
|
||||
for (i = 0; i < num_allocated; i++)
|
||||
dma_free_coherent(&blfc_dev->pdev->dev,
|
||||
msg->dma[i].length,
|
||||
blfc_dev->dma_virt_addr[i],
|
||||
blfc_dev->dma_addr[i]);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int32_t bnxt_lfc_process_hwrm(struct bnxt_lfc_dev *blfc_dev,
|
||||
struct bnxt_lfc_req *lfc_req)
|
||||
{
|
||||
int32_t rc = 0, i, hwrm_err = 0;
|
||||
struct bnxt_en_dev *en_dev = blfc_dev->en_dev;
|
||||
struct pci_dev *pdev = blfc_dev->pdev;
|
||||
struct bnxt_fw_msg fw_msg;
|
||||
struct blfc_fw_msg msg, *msg2 = NULL;
|
||||
|
||||
if (copy_from_user(&msg,
|
||||
(void __user *)((unsigned long)lfc_req->req.hreq),
|
||||
sizeof(msg))) {
|
||||
BNXT_LFC_ERR(&pdev->dev, "Failed to copy data from user\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (msg.len_req > BNXT_LFC_MAX_HWRM_REQ_LENGTH ||
|
||||
msg.len_resp > BNXT_LFC_MAX_HWRM_RESP_LENGTH) {
|
||||
BNXT_LFC_ERR(&pdev->dev,
|
||||
"Invalid length\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fw_msg.msg = kmalloc(msg.len_req, GFP_KERNEL);
|
||||
if (!fw_msg.msg) {
|
||||
BNXT_LFC_ERR(&pdev->dev,
|
||||
"Failed to allocate input req memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
fw_msg.resp = kmalloc(msg.len_resp, GFP_KERNEL);
|
||||
if (!fw_msg.resp) {
|
||||
BNXT_LFC_ERR(&pdev->dev,
|
||||
"Failed to allocate resp memory\n");
|
||||
rc = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
rc = bnxt_lfc_fill_fw_msg(pdev, &fw_msg, &msg);
|
||||
if (rc) {
|
||||
BNXT_LFC_ERR(&pdev->dev,
|
||||
"Failed to fill the FW data\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (msg.num_dma_indications) {
|
||||
if (msg.num_dma_indications > MAX_NUM_DMA_INDICATIONS) {
|
||||
BNXT_LFC_ERR(&pdev->dev,
|
||||
"Invalid DMA indications\n");
|
||||
rc = -EINVAL;
|
||||
goto err1;
|
||||
}
|
||||
msg2 = kmalloc((sizeof(struct blfc_fw_msg) +
|
||||
(msg.num_dma_indications * sizeof(struct dma_info))),
|
||||
GFP_KERNEL);
|
||||
if (!msg2) {
|
||||
BNXT_LFC_ERR(&pdev->dev,
|
||||
"Failed to allocate memory\n");
|
||||
rc = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
if (copy_from_user((void *)msg2,
|
||||
(void __user *)((unsigned long)lfc_req->req.hreq),
|
||||
(sizeof(struct blfc_fw_msg) +
|
||||
(msg.num_dma_indications *
|
||||
sizeof(struct dma_info))))) {
|
||||
BNXT_LFC_ERR(&pdev->dev,
|
||||
"Failed to copy data from user\n");
|
||||
rc = -EFAULT;
|
||||
goto err;
|
||||
}
|
||||
rc = bnxt_lfc_prepare_dma_operations(blfc_dev, msg2, &fw_msg);
|
||||
if (rc) {
|
||||
BNXT_LFC_ERR(&pdev->dev,
|
||||
"Failed to perform DMA operaions\n");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
hwrm_err = en_dev->en_ops->bnxt_send_fw_msg(en_dev,
|
||||
BNXT_OTHER_ULP, &fw_msg);
|
||||
if (hwrm_err) {
|
||||
struct input *req = fw_msg.msg;
|
||||
|
||||
BNXT_LFC_ERR(&pdev->dev,
|
||||
"Failed to send FW msg type = 0x%x, error = 0x%x",
|
||||
req->req_type, hwrm_err);
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (i = 0; i < msg.num_dma_indications; i++) {
|
||||
if (msg2->dma[i].read_or_write) {
|
||||
if (copy_to_user((void __user *)
|
||||
((unsigned long)msg2->dma[i].data),
|
||||
blfc_dev->dma_virt_addr[i],
|
||||
msg2->dma[i].length)) {
|
||||
BNXT_LFC_ERR(&pdev->dev,
|
||||
"Failed to copy data from user\n");
|
||||
rc = -EFAULT;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
err:
|
||||
for (i = 0; i < msg.num_dma_indications; i++)
|
||||
dma_free_coherent(&pdev->dev, msg2->dma[i].length,
|
||||
blfc_dev->dma_virt_addr[i],
|
||||
blfc_dev->dma_addr[i]);
|
||||
|
||||
if (hwrm_err != -EBUSY && hwrm_err != -E2BIG) {
|
||||
if (copy_to_user((void __user *)((unsigned long)msg.usr_resp),
|
||||
fw_msg.resp,
|
||||
msg.len_resp)) {
|
||||
BNXT_LFC_ERR(&pdev->dev,
|
||||
"Failed to copy data from user\n");
|
||||
rc = -EFAULT;
|
||||
}
|
||||
}
|
||||
err1:
|
||||
kfree(msg2);
|
||||
kfree(fw_msg.msg);
|
||||
fw_msg.msg = NULL;
|
||||
kfree(fw_msg.resp);
|
||||
fw_msg.resp = NULL;
|
||||
/* If HWRM command fails, return the response error code */
|
||||
if (hwrm_err)
|
||||
return hwrm_err;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int32_t bnxt_lfc_process_req(struct bnxt_lfc_dev *blfc_dev,
|
||||
struct bnxt_lfc_req *lfc_req)
|
||||
{
|
||||
int32_t rc;
|
||||
|
||||
switch (lfc_req->hdr.req_type) {
|
||||
case BNXT_LFC_NVM_GET_VAR_REQ:
|
||||
rc = bnxt_lfc_process_nvm_get_var_req(blfc_dev,
|
||||
&lfc_req->req.nvm_get_var_req);
|
||||
break;
|
||||
case BNXT_LFC_NVM_SET_VAR_REQ:
|
||||
rc = bnxt_lfc_process_nvm_set_var_req(blfc_dev,
|
||||
&lfc_req->req.nvm_set_var_req);
|
||||
break;
|
||||
case BNXT_LFC_NVM_FLUSH_REQ:
|
||||
rc = bnxt_lfc_process_nvm_flush(blfc_dev);
|
||||
break;
|
||||
case BNXT_LFC_GENERIC_HWRM_REQ:
|
||||
rc = bnxt_lfc_process_hwrm(blfc_dev, lfc_req);
|
||||
break;
|
||||
default:
|
||||
BNXT_LFC_DEBUG(&blfc_dev->pdev->dev,
|
||||
"No valid request found\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int32_t bnxt_lfc_open(struct inode *inode, struct file *flip)
|
||||
{
|
||||
BNXT_LFC_DEBUG(NULL, "open is called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t bnxt_lfc_read(struct file *filp, char __user *buff,
|
||||
size_t length, loff_t *offset)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static ssize_t bnxt_lfc_write(struct file *filp, const char __user *ubuff,
|
||||
size_t len, loff_t *offset)
|
||||
{
|
||||
struct bnxt_lfc_generic_msg kbuff;
|
||||
|
||||
if (len != sizeof(kbuff)) {
|
||||
BNXT_LFC_ERR(NULL, "Invalid length provided (%zu)\n", len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (copy_from_user(&kbuff, (void __user *)ubuff, len)) {
|
||||
BNXT_LFC_ERR(NULL, "Failed to copy data from user application\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
switch (kbuff.key) {
|
||||
case BNXT_LFC_KEY_DOMAIN_NO:
|
||||
is_domain_available = true;
|
||||
domain_no = kbuff.value;
|
||||
break;
|
||||
default:
|
||||
BNXT_LFC_ERR(NULL, "Invalid Key provided (%u)\n", kbuff.key);
|
||||
return -EINVAL;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static loff_t bnxt_lfc_seek(struct file *filp, loff_t offset, int32_t whence)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void bnxt_lfc_stop(void *handle)
|
||||
{
|
||||
struct bnxt_lfc_dev *blfc_dev_stop = handle;
|
||||
struct bnxt_lfc_dev *blfc_dev = NULL;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_LFC_OPEN_ULP_DEVICES; i++) {
|
||||
blfc_dev = blfc_array[i].bnxt_lfc_dev;
|
||||
if(blfc_dev == blfc_dev_stop) {
|
||||
bnxt_lfc_unreg(blfc_dev);
|
||||
dev_put(blfc_dev->ndev);
|
||||
kfree(blfc_dev);
|
||||
blfc_array[i].bnxt_lfc_dev = NULL;
|
||||
blfc_array[i].taken = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static long bnxt_lfc_ioctl(struct file *flip, unsigned int cmd,
|
||||
unsigned long args)
|
||||
{
|
||||
int32_t rc;
|
||||
struct bnxt_lfc_req temp;
|
||||
struct bnxt_lfc_req *lfc_req;
|
||||
u32 index;
|
||||
struct bnxt_lfc_dev *blfc_dev = NULL;
|
||||
|
||||
rc = copy_from_user(&temp, (void __user *)args, sizeof(struct bnxt_lfc_req));
|
||||
if (rc) {
|
||||
BNXT_LFC_ERR(NULL,
|
||||
"Failed to send %d bytes from the user\n", rc);
|
||||
return -EINVAL;
|
||||
}
|
||||
lfc_req = &temp;
|
||||
|
||||
if (!lfc_req)
|
||||
return -EINVAL;
|
||||
|
||||
switch (cmd) {
|
||||
case BNXT_LFC_REQ:
|
||||
BNXT_LFC_DEBUG(NULL, "BNXT_LFC_REQ called");
|
||||
mutex_lock(&blfc_global_dev.bnxt_lfc_lock);
|
||||
index = bnxt_lfc_get_hash_key(lfc_req->hdr.bus, lfc_req->hdr.devfn);
|
||||
if (blfc_array[index].taken) {
|
||||
if (lfc_req->hdr.devfn != blfc_array[index].bnxt_lfc_dev->devfn ||
|
||||
lfc_req->hdr.bus != blfc_array[index].bnxt_lfc_dev->bus) {
|
||||
/* we have a false hit. Free the older blfc device
|
||||
store the new one */
|
||||
rtnl_lock();
|
||||
bnxt_lfc_unreg(blfc_array[index].bnxt_lfc_dev);
|
||||
dev_put(blfc_array[index].bnxt_lfc_dev->ndev);
|
||||
kfree(blfc_array[index].bnxt_lfc_dev);
|
||||
blfc_array[index].bnxt_lfc_dev = NULL;
|
||||
blfc_array[index].taken = 0;
|
||||
rtnl_unlock();
|
||||
goto not_taken;
|
||||
}
|
||||
blfc_dev = blfc_array[index].bnxt_lfc_dev;
|
||||
}
|
||||
else {
|
||||
not_taken:
|
||||
blfc_dev = kzalloc(sizeof(struct bnxt_lfc_dev), GFP_KERNEL);
|
||||
if (!blfc_dev) {
|
||||
mutex_unlock(&blfc_global_dev.bnxt_lfc_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
blfc_dev->pdev =
|
||||
pci_get_domain_bus_and_slot(
|
||||
((is_domain_available == true) ?
|
||||
domain_no : 0), lfc_req->hdr.bus,
|
||||
lfc_req->hdr.devfn);
|
||||
|
||||
if (bnxt_lfc_is_valid_pdev(blfc_dev->pdev) != true) {
|
||||
mutex_unlock(&blfc_global_dev.bnxt_lfc_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rtnl_lock();
|
||||
blfc_dev->ndev = pci_get_drvdata(blfc_dev->pdev);
|
||||
if (!blfc_dev->ndev) {
|
||||
printk("Driver with provided BDF doesn't exist\n");
|
||||
pci_dev_put(blfc_dev->pdev);
|
||||
rtnl_unlock();
|
||||
mutex_unlock(&blfc_global_dev.bnxt_lfc_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev_hold(blfc_dev->ndev);
|
||||
rtnl_unlock();
|
||||
if (try_module_get(blfc_dev->pdev->driver->driver.owner)) {
|
||||
blfc_dev->uops.ulp_stop = bnxt_lfc_stop;
|
||||
rc = bnxt_lfc_probe_and_reg(blfc_dev);
|
||||
module_put(blfc_dev->pdev->driver->driver.owner);
|
||||
} else {
|
||||
rc = -EINVAL;
|
||||
}
|
||||
pci_dev_put(blfc_dev->pdev);
|
||||
|
||||
if (rc) {
|
||||
dev_put(blfc_dev->ndev);
|
||||
kfree(blfc_dev);
|
||||
is_domain_available = false;
|
||||
mutex_unlock(&blfc_global_dev.bnxt_lfc_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
blfc_dev->bus = lfc_req->hdr.bus;
|
||||
blfc_dev->devfn = lfc_req->hdr.devfn;
|
||||
rtnl_lock();
|
||||
blfc_array[index].bnxt_lfc_dev = blfc_dev;
|
||||
blfc_array[index].taken = 1;
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
rc = bnxt_lfc_process_req(blfc_dev, lfc_req);
|
||||
mutex_unlock(&blfc_global_dev.bnxt_lfc_lock);
|
||||
break;
|
||||
|
||||
default:
|
||||
BNXT_LFC_ERR(NULL, "No Valid IOCTL found\n");
|
||||
return -EINVAL;
|
||||
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int32_t bnxt_lfc_release(struct inode *inode, struct file *filp)
|
||||
{
|
||||
BNXT_LFC_DEBUG(NULL, "release is called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t __init bnxt_lfc_init(void)
|
||||
{
|
||||
int32_t rc;
|
||||
|
||||
rc = alloc_chrdev_region(&blfc_global_dev.d_dev, 0, 1, BNXT_LFC_DEV_NAME);
|
||||
if (rc < 0) {
|
||||
BNXT_LFC_ERR(NULL, "Allocation of char dev region is failed\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
blfc_global_dev.d_class = class_create(THIS_MODULE, BNXT_LFC_DEV_NAME);
|
||||
if (IS_ERR(blfc_global_dev.d_class)) {
|
||||
BNXT_LFC_ERR(NULL, "Class creation is failed\n");
|
||||
unregister_chrdev_region(blfc_global_dev.d_dev, 1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (IS_ERR(device_create(blfc_global_dev.d_class, NULL, blfc_global_dev.d_dev, NULL,
|
||||
BNXT_LFC_DEV_NAME))) {
|
||||
BNXT_LFC_ERR(NULL, "Device creation is failed\n");
|
||||
class_destroy(blfc_global_dev.d_class);
|
||||
unregister_chrdev_region(blfc_global_dev.d_dev, 1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
blfc_global_dev.fops.owner = THIS_MODULE;
|
||||
blfc_global_dev.fops.open = bnxt_lfc_open;
|
||||
blfc_global_dev.fops.read = bnxt_lfc_read;
|
||||
blfc_global_dev.fops.write = bnxt_lfc_write;
|
||||
blfc_global_dev.fops.llseek = bnxt_lfc_seek;
|
||||
blfc_global_dev.fops.unlocked_ioctl = bnxt_lfc_ioctl;
|
||||
blfc_global_dev.fops.release = bnxt_lfc_release;
|
||||
|
||||
cdev_init(&blfc_global_dev.c_dev, &blfc_global_dev.fops);
|
||||
if (cdev_add(&blfc_global_dev.c_dev, blfc_global_dev.d_dev, 1) == -1) {
|
||||
BNXT_LFC_ERR(NULL, "Char device addition is failed\n");
|
||||
device_destroy(blfc_global_dev.d_class, blfc_global_dev.d_dev);
|
||||
class_destroy(blfc_global_dev.d_class);
|
||||
unregister_chrdev_region(blfc_global_dev.d_dev, 1);
|
||||
return -1;
|
||||
}
|
||||
mutex_init(&blfc_global_dev.bnxt_lfc_lock);
|
||||
bnxt_lfc_inited = true;
|
||||
|
||||
memset(blfc_array, 0, sizeof(struct bnxt_lfc_dev_array)
|
||||
* MAX_LFC_OPEN_ULP_DEVICES);
|
||||
|
||||
rc = bnxt_en_register_netdevice_notifier(&lfc_device_notifier);
|
||||
if (rc) {
|
||||
BNXT_LFC_ERR(NULL, "Error on register NETDEV event notifier\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __exit bnxt_lfc_exit(void)
|
||||
{
|
||||
struct bnxt_lfc_dev *blfc_dev;
|
||||
u32 i;
|
||||
if (!bnxt_lfc_inited)
|
||||
return;
|
||||
for (i = 0; i < MAX_LFC_OPEN_ULP_DEVICES; i++) {
|
||||
mutex_lock(&blfc_global_dev.bnxt_lfc_lock);
|
||||
blfc_dev = blfc_array[i].bnxt_lfc_dev;
|
||||
if (blfc_dev) {
|
||||
rtnl_lock();
|
||||
bnxt_lfc_unreg(blfc_dev);
|
||||
blfc_array[i].bnxt_lfc_dev = NULL;
|
||||
blfc_array[i].taken = 0;
|
||||
rtnl_unlock();
|
||||
dev_put(blfc_dev->ndev);
|
||||
kfree(blfc_dev);
|
||||
}
|
||||
mutex_unlock(&blfc_global_dev.bnxt_lfc_lock);
|
||||
}
|
||||
bnxt_en_unregister_netdevice_notifier(&lfc_device_notifier);
|
||||
cdev_del(&blfc_global_dev.c_dev);
|
||||
device_destroy(blfc_global_dev.d_class, blfc_global_dev.d_dev);
|
||||
class_destroy(blfc_global_dev.d_class);
|
||||
unregister_chrdev_region(blfc_global_dev.d_dev, 1);
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
/* Broadcom NetXtreme-C/E network driver.
|
||||
*
|
||||
* Copyright (c) 2017 Broadcom Limited
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef BNXT_LFC_H
|
||||
#define BNXT_LFC_H
|
||||
|
||||
#ifdef CONFIG_BNXT_LFC
|
||||
|
||||
/* Assuming that no HWRM command requires more than 10 DMA address
|
||||
* as input requests.
|
||||
*/
|
||||
#define MAX_NUM_DMA_INDICATIONS 10
|
||||
#define MAX_DMA_MEM_SIZE 0x10000 /*64K*/
|
||||
|
||||
/* To prevent mismatch between bnxtnvm user application and bnxt_lfc
|
||||
* keeping the max. size as 512.
|
||||
*/
|
||||
#define BNXT_LFC_MAX_HWRM_REQ_LENGTH HWRM_MAX_REQ_LEN
|
||||
#define BNXT_LFC_MAX_HWRM_RESP_LENGTH (512)
|
||||
|
||||
#define BNXT_NVM_FLUSH_TIMEOUT ((DFLT_HWRM_CMD_TIMEOUT) * 100)
|
||||
#define BNXT_LFC_DEV_NAME "bnxt_lfc"
|
||||
#define DRV_NAME BNXT_LFC_DEV_NAME
|
||||
|
||||
#define BNXT_LFC_ERR(dev, fmt, arg...) \
|
||||
dev_err(dev, "%s: %s:%d: "fmt "\n", \
|
||||
DRV_NAME, __func__, \
|
||||
__LINE__, ##arg) \
|
||||
|
||||
#define BNXT_LFC_WARN(dev, fmt, arg...) \
|
||||
dev_warn(dev, "%s: %s:%d: "fmt "\n", \
|
||||
DRV_NAME, __func__, \
|
||||
__LINE__, ##arg) \
|
||||
|
||||
#define BNXT_LFC_INFO(dev, fmt, arg...) \
|
||||
dev_info(dev, "%s: %s:%d: "fmt "\n", \
|
||||
DRV_NAME, __func__, \
|
||||
__LINE__, ##arg) \
|
||||
|
||||
#define BNXT_LFC_DEBUG(dev, fmt, arg...) \
|
||||
dev_dbg(dev, "%s: %s:%d: "fmt "\n", \
|
||||
DRV_NAME, __func__, \
|
||||
__LINE__, ##arg) \
|
||||
|
||||
struct bnxt_lfc_dev_array {
|
||||
u32 taken;
|
||||
struct bnxt_lfc_dev *bnxt_lfc_dev;
|
||||
};
|
||||
|
||||
struct bnxt_lfc_dev {
|
||||
struct pci_dev *pdev;
|
||||
struct net_device *ndev;
|
||||
|
||||
struct bnxt *bp;
|
||||
struct bnxt_en_dev *en_dev;
|
||||
|
||||
struct bnxt_ulp_ops uops;
|
||||
u32 bus;
|
||||
u32 devfn;
|
||||
|
||||
/* dma_virt_addr to hold the virtual address
|
||||
* of the DMA memory.
|
||||
*/
|
||||
void *dma_virt_addr[MAX_NUM_DMA_INDICATIONS];
|
||||
/* dma_addr to hold the DMA addresses*/
|
||||
dma_addr_t dma_addr[MAX_NUM_DMA_INDICATIONS];
|
||||
};
|
||||
|
||||
struct bnxt_gloabl_dev {
|
||||
dev_t d_dev;
|
||||
struct class *d_class;
|
||||
struct cdev c_dev;
|
||||
|
||||
struct file_operations fops;
|
||||
|
||||
struct mutex bnxt_lfc_lock;
|
||||
};
|
||||
|
||||
int32_t bnxt_lfc_init(void);
|
||||
void bnxt_lfc_exit(void);
|
||||
|
||||
#else
|
||||
|
||||
static inline int32_t bnxt_lfc_init()
|
||||
{
|
||||
}
|
||||
|
||||
static inline void bnxt_lfc_exit()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
#endif /*BNXT_LFC_H*/
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
/* Broadcom NetXtreme-C/E network driver.
|
||||
*
|
||||
* Copyright (c) 2017 Broadcom Limited
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef BNXT_LFC_IOCTL_H
|
||||
#define BNXT_LFC_IOCTL_H
|
||||
|
||||
#define BNXT_LFC_IOCTL_MAGIC 0x98
|
||||
#define BNXT_LFC_VER 1
|
||||
|
||||
enum bnxt_lfc_req_type {
|
||||
BNXT_LFC_NVM_GET_VAR_REQ = 1,
|
||||
BNXT_LFC_NVM_SET_VAR_REQ,
|
||||
BNXT_LFC_NVM_FLUSH_REQ,
|
||||
BNXT_LFC_GENERIC_HWRM_REQ,
|
||||
};
|
||||
|
||||
struct bnxt_lfc_req_hdr {
|
||||
uint32_t ver;
|
||||
uint32_t bus;
|
||||
uint32_t devfn;
|
||||
enum bnxt_lfc_req_type req_type;
|
||||
};
|
||||
|
||||
struct bnxt_lfc_nvm_get_var_req {
|
||||
uint16_t option_num;
|
||||
uint16_t dimensions;
|
||||
uint16_t index_0;
|
||||
uint16_t index_1;
|
||||
uint16_t index_2;
|
||||
uint16_t index_3;
|
||||
uint16_t len_in_bits;
|
||||
uint8_t __user *out_val;
|
||||
};
|
||||
|
||||
struct bnxt_lfc_nvm_set_var_req {
|
||||
uint16_t option_num;
|
||||
uint16_t dimensions;
|
||||
uint16_t index_0;
|
||||
uint16_t index_1;
|
||||
uint16_t index_2;
|
||||
uint16_t index_3;
|
||||
uint16_t len_in_bits;
|
||||
uint8_t __user *in_val;
|
||||
};
|
||||
|
||||
struct dma_info {
|
||||
__u64 data;
|
||||
/* Based on read_or_write parameter
|
||||
* LFC will either fill or read the
|
||||
* data to or from the user memory
|
||||
*/
|
||||
__u32 length;
|
||||
/* Length of the data for read/write */
|
||||
__u16 offset;
|
||||
/* Offset at which HWRM input structure needs DMA address*/
|
||||
__u8 read_or_write;
|
||||
/* It should be 0 for write and 1 for read */
|
||||
__u8 unused;
|
||||
};
|
||||
|
||||
struct blfc_fw_msg {
|
||||
__u64 usr_req;
|
||||
/* HWRM input structure */
|
||||
__u64 usr_resp;
|
||||
/* HWRM output structure */
|
||||
__u32 len_req;
|
||||
/* HWRM input structure length*/
|
||||
__u32 len_resp;
|
||||
/* HWRM output structure length*/
|
||||
__u32 timeout;
|
||||
/* HWRM command timeout. If 0 then
|
||||
* LFC will provide default timeout
|
||||
*/
|
||||
__u32 num_dma_indications;
|
||||
/* Number of DMA addresses used in HWRM command */
|
||||
struct dma_info dma[0];
|
||||
/* User should allocate it with
|
||||
* (sizeof(struct dma_info) * num_dma_indications)
|
||||
*/
|
||||
};
|
||||
|
||||
|
||||
struct bnxt_lfc_generic_msg {
|
||||
__u8 key;
|
||||
#define BNXT_LFC_KEY_DOMAIN_NO 1
|
||||
__u8 reserved[3];
|
||||
__u32 value;
|
||||
};
|
||||
|
||||
struct bnxt_lfc_req {
|
||||
struct bnxt_lfc_req_hdr hdr;
|
||||
union {
|
||||
struct bnxt_lfc_nvm_get_var_req nvm_get_var_req;
|
||||
struct bnxt_lfc_nvm_set_var_req nvm_set_var_req;
|
||||
__u64 hreq; /* Pointer to "struct blfc_fw_msg" */
|
||||
} req;
|
||||
};
|
||||
|
||||
#define BNXT_LFC_REQ _IOW(BNXT_LFC_IOCTL_MAGIC, 1, struct bnxt_lfc_req)
|
||||
#endif /*BNXT_LFC_IOCTL_H*/
|
||||
|
|
@ -0,0 +1,234 @@
|
|||
/* Broadcom NetXtreme-C/E network driver.
|
||||
*
|
||||
* Copyright (c) 2014-2016 Broadcom Corporation
|
||||
* Copyright (c) 2016-2017 Broadcom Limited
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/pci.h>
|
||||
#include "bnxt_compat.h"
|
||||
#include "bnxt_hsi.h"
|
||||
#include "bnxt_netlink.h"
|
||||
#include "bnxt.h"
|
||||
|
||||
/* attribute policy */
|
||||
static struct nla_policy bnxt_netlink_policy[BNXT_NUM_ATTRS] = {
|
||||
[BNXT_ATTR_PID] = { .type = NLA_U32 },
|
||||
[BNXT_ATTR_IF_INDEX] = { .type = NLA_U32 },
|
||||
[BNXT_ATTR_REQUEST] = { .type = NLA_BINARY },
|
||||
[BNXT_ATTR_RESPONSE] = { .type = NLA_BINARY },
|
||||
};
|
||||
|
||||
static struct genl_family bnxt_netlink_family;
|
||||
|
||||
static int bnxt_parse_attrs(struct nlattr **a, struct bnxt **bp,
|
||||
struct net_device **dev)
|
||||
{
|
||||
pid_t pid;
|
||||
struct net *ns = NULL;
|
||||
const char *drivername;
|
||||
|
||||
if (!a[BNXT_ATTR_PID]) {
|
||||
netdev_err(*dev, "No process ID specified\n");
|
||||
goto err_inval;
|
||||
}
|
||||
pid = nla_get_u32(a[BNXT_ATTR_PID]);
|
||||
ns = get_net_ns_by_pid(pid);
|
||||
if (IS_ERR(ns)) {
|
||||
netdev_err(*dev, "Invalid net namespace for pid %d (err: %ld)\n",
|
||||
pid, PTR_ERR(ns));
|
||||
goto err_inval;
|
||||
}
|
||||
|
||||
if (!a[BNXT_ATTR_IF_INDEX]) {
|
||||
netdev_err(*dev, "No interface index specified\n");
|
||||
goto err_inval;
|
||||
}
|
||||
*dev = dev_get_by_index(ns, nla_get_u32(a[BNXT_ATTR_IF_INDEX]));
|
||||
|
||||
put_net(ns);
|
||||
ns = NULL;
|
||||
if (!*dev) {
|
||||
netdev_err(*dev, "Invalid network interface index %d (err: %ld)\n",
|
||||
nla_get_u32(a[BNXT_ATTR_IF_INDEX]), PTR_ERR(ns));
|
||||
goto err_inval;
|
||||
}
|
||||
if (!(*dev)->dev.parent || !(*dev)->dev.parent->driver ||
|
||||
!(*dev)->dev.parent->driver->name) {
|
||||
netdev_err(*dev, "Unable to get driver name for device %s\n",
|
||||
(*dev)->name);
|
||||
goto err_inval;
|
||||
}
|
||||
drivername = (*dev)->dev.parent->driver->name;
|
||||
if (strcmp(drivername, DRV_MODULE_NAME)) {
|
||||
netdev_err(*dev, "Device %s (%s) is not a %s device!\n",
|
||||
(*dev)->name, drivername, DRV_MODULE_NAME);
|
||||
goto err_inval;
|
||||
}
|
||||
*bp = netdev_priv(*dev);
|
||||
if (!*bp) {
|
||||
netdev_warn((*bp)->dev, "No private data\n");
|
||||
goto err_inval;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_inval:
|
||||
if (ns && !IS_ERR(ns))
|
||||
put_net(ns);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* handler */
|
||||
static int bnxt_netlink_hwrm(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct nlattr **a = info->attrs;
|
||||
int len;
|
||||
struct sk_buff *reply = NULL;
|
||||
struct input *req;
|
||||
struct output *resp;
|
||||
struct bnxt *bp = NULL;
|
||||
int rc = 0;
|
||||
void *hdr;
|
||||
struct net_device *dev = NULL;
|
||||
|
||||
rc = bnxt_parse_attrs(a, &bp, &dev);
|
||||
if (rc)
|
||||
goto err_rc;
|
||||
|
||||
if (!bp) {
|
||||
rc = -EINVAL;
|
||||
goto err_rc;
|
||||
}
|
||||
|
||||
if (!bp->hwrm_cmd_resp_addr) {
|
||||
netdev_warn(bp->dev, "HWRM interface not currently available on %s\n",
|
||||
dev->name);
|
||||
rc = -EINVAL;
|
||||
goto err_rc;
|
||||
}
|
||||
|
||||
if (bp->fw_cap & BNXT_FW_CAP_KONG_MB_CHNL &&
|
||||
!bp->hwrm_cmd_kong_resp_addr) {
|
||||
netdev_warn(bp->dev, "HWRM Kong interface not currently available on %s\n",
|
||||
dev->name);
|
||||
rc = -EINVAL;
|
||||
goto err_rc;
|
||||
}
|
||||
|
||||
if (!a[BNXT_ATTR_REQUEST]) {
|
||||
netdev_warn(bp->dev, "No request specified\n");
|
||||
rc = -EINVAL;
|
||||
goto err_rc;
|
||||
}
|
||||
len = nla_len(a[BNXT_ATTR_REQUEST]);
|
||||
req = nla_data(a[BNXT_ATTR_REQUEST]);
|
||||
|
||||
reply = genlmsg_new(PAGE_SIZE, GFP_KERNEL);
|
||||
if (!reply) {
|
||||
netdev_warn(bp->dev, "Error: genlmsg_new failed\n");
|
||||
rc = -ENOMEM;
|
||||
goto err_rc;
|
||||
}
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, req, req->req_type, -1, -1);
|
||||
mutex_lock(&bp->hwrm_cmd_lock);
|
||||
rc = _hwrm_send_message_silent(bp, req, len, HWRM_CMD_TIMEOUT);
|
||||
if (rc) {
|
||||
/*
|
||||
* Indicate success for the hwrm transport, while letting
|
||||
* the hwrm error be passed back to the netlink caller in
|
||||
* the response message. Caller is responsible for handling
|
||||
* any errors.
|
||||
*
|
||||
* no kernel warnings are logged in this case.
|
||||
*/
|
||||
rc = 0;
|
||||
}
|
||||
hdr = genlmsg_put_reply(reply, info, &bnxt_netlink_family, 0,
|
||||
BNXT_CMD_HWRM);
|
||||
resp = (struct output *)bnxt_get_hwrm_resp_addr(bp, req);
|
||||
if (nla_put(reply, BNXT_ATTR_RESPONSE, resp->resp_len, resp)) {
|
||||
netdev_warn(bp->dev, "No space for response attribte\n");
|
||||
mutex_unlock(&bp->hwrm_cmd_lock);
|
||||
rc = -ENOMEM;
|
||||
goto err_rc;
|
||||
}
|
||||
genlmsg_end(reply, hdr);
|
||||
mutex_unlock(&bp->hwrm_cmd_lock);
|
||||
|
||||
dev_put(dev);
|
||||
dev = NULL;
|
||||
|
||||
return genlmsg_reply(reply, info);
|
||||
|
||||
err_rc:
|
||||
if (reply && !IS_ERR(reply))
|
||||
kfree_skb(reply);
|
||||
if (dev && !IS_ERR(dev))
|
||||
dev_put(dev);
|
||||
|
||||
if (bp)
|
||||
netdev_warn(bp->dev, "returning with error code %d\n", rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* handlers */
|
||||
#if defined(HAVE_GENL_REG_OPS_GRPS) || !defined(HAVE_GENL_REG_FAMILY_WITH_OPS)
|
||||
static const struct genl_ops bnxt_netlink_ops[] = {
|
||||
#else
|
||||
static struct genl_ops bnxt_netlink_ops[] = {
|
||||
#endif
|
||||
{
|
||||
.cmd = BNXT_CMD_HWRM,
|
||||
.flags = GENL_ADMIN_PERM, /* Req's CAP_NET_ADMIN privilege */
|
||||
#ifndef HAVE_GENL_POLICY
|
||||
.policy = bnxt_netlink_policy,
|
||||
#endif
|
||||
.doit = bnxt_netlink_hwrm,
|
||||
.dumpit = NULL,
|
||||
},
|
||||
};
|
||||
|
||||
/* family definition */
|
||||
static struct genl_family bnxt_netlink_family = {
|
||||
#ifdef HAVE_GENL_ID_GENERATE
|
||||
.id = GENL_ID_GENERATE,
|
||||
#endif
|
||||
.hdrsize = 0,
|
||||
.name = BNXT_NL_NAME,
|
||||
.version = BNXT_NL_VER,
|
||||
.maxattr = BNXT_NUM_ATTRS,
|
||||
#ifdef HAVE_GENL_POLICY
|
||||
.policy = bnxt_netlink_policy,
|
||||
#endif
|
||||
#ifndef HAVE_GENL_REG_FAMILY_WITH_OPS
|
||||
.ops = bnxt_netlink_ops,
|
||||
.n_ops = ARRAY_SIZE(bnxt_netlink_ops)
|
||||
#endif
|
||||
};
|
||||
|
||||
int bnxt_nl_register(void)
|
||||
{
|
||||
#ifndef HAVE_GENL_REG_FAMILY_WITH_OPS
|
||||
return genl_register_family(&bnxt_netlink_family);
|
||||
#elif defined(HAVE_GENL_REG_OPS_GRPS)
|
||||
return genl_register_family_with_ops(&bnxt_netlink_family,
|
||||
bnxt_netlink_ops);
|
||||
#else
|
||||
return genl_register_family_with_ops(&bnxt_netlink_family,
|
||||
bnxt_netlink_ops,
|
||||
ARRAY_SIZE(bnxt_netlink_ops));
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bnxt_nl_unregister(void)
|
||||
{
|
||||
return genl_unregister_family(&bnxt_netlink_family);
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/* Broadcom NetXtreme-C/E network driver.
|
||||
*
|
||||
* Copyright (c) 2014-2016 Broadcom Corporation
|
||||
* Copyright (c) 2016-2017 Broadcom Limited
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
#ifndef __BNXT_NETLINK_H__
|
||||
#define __BNXT_NETLINK_H__
|
||||
|
||||
#include <net/genetlink.h>
|
||||
#include <net/netlink.h>
|
||||
|
||||
/* commands */
|
||||
enum {
|
||||
BNXT_CMD_UNSPEC,
|
||||
BNXT_CMD_HWRM,
|
||||
BNXT_NUM_CMDS
|
||||
};
|
||||
#define BNXT_CMD_MAX (BNXT_NUM_CMDS - 1)
|
||||
|
||||
/* attributes */
|
||||
enum {
|
||||
BNXT_ATTR_UNSPEC,
|
||||
BNXT_ATTR_PID,
|
||||
BNXT_ATTR_IF_INDEX,
|
||||
BNXT_ATTR_REQUEST,
|
||||
BNXT_ATTR_RESPONSE,
|
||||
BNXT_NUM_ATTRS
|
||||
};
|
||||
#define BNXT_ATTR_MAX (BNXT_NUM_ATTRS - 1)
|
||||
|
||||
#define BNXT_NL_NAME "bnxt_netlink"
|
||||
#define BNXT_NL_VER 1
|
||||
|
||||
int bnxt_nl_register(void);
|
||||
int bnxt_nl_unregister(void);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
/* Broadcom NetXtreme-C/E network driver.
|
||||
*
|
||||
* Copyright (c) 2014-2016 Broadcom Corporation
|
||||
* Copyright (c) 2016-2017 Broadcom Limited
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -59,8 +60,6 @@ enum bnxt_nvm_directory_type {
|
|||
#define BNX_DIR_ATTR_NO_CHKSUM (1 << 0)
|
||||
#define BNX_DIR_ATTR_PROP_STREAM (1 << 1)
|
||||
|
||||
#define BNX_PKG_LOG_MAX_LENGTH 4096
|
||||
|
||||
enum bnxnvm_pkglog_field_index {
|
||||
BNX_PKG_LOG_FIELD_IDX_INSTALLED_TIMESTAMP = 0,
|
||||
BNX_PKG_LOG_FIELD_IDX_PKG_DESCRIPTION = 1,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,458 @@
|
|||
/* Broadcom NetXtreme-C/E network driver.
|
||||
*
|
||||
* Copyright (c) 2017 Broadcom Limited
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#ifdef HAVE_IEEE1588_SUPPORT
|
||||
#include <linux/ptp_clock_kernel.h>
|
||||
#include <linux/net_tstamp.h>
|
||||
#include <linux/timecounter.h>
|
||||
#include <linux/timekeeping.h>
|
||||
#endif
|
||||
#include "bnxt_compat.h"
|
||||
#include "bnxt_hsi.h"
|
||||
#include "bnxt.h"
|
||||
#include "bnxt_ptp.h"
|
||||
|
||||
#ifdef HAVE_IEEE1588_SUPPORT
|
||||
static int bnxt_ptp_settime(struct ptp_clock_info *ptp_info,
|
||||
const struct timespec64 *ts)
|
||||
{
|
||||
struct bnxt_ptp_cfg *ptp = container_of(ptp_info, struct bnxt_ptp_cfg,
|
||||
ptp_info);
|
||||
u64 ns = timespec64_to_ns(ts);
|
||||
|
||||
ns = timespec64_to_ns(ts);
|
||||
timecounter_init(&ptp->tc, &ptp->cc, ns);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bnxt_ptp_gettime(struct ptp_clock_info *ptp_info,
|
||||
struct timespec64 *ts)
|
||||
{
|
||||
struct bnxt_ptp_cfg *ptp = container_of(ptp_info, struct bnxt_ptp_cfg,
|
||||
ptp_info);
|
||||
u64 ns;
|
||||
|
||||
ns = timecounter_read(&ptp->tc);
|
||||
*ts = ns_to_timespec64(ns);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bnxt_ptp_adjtime(struct ptp_clock_info *ptp_info, s64 delta)
|
||||
{
|
||||
struct bnxt_ptp_cfg *ptp = container_of(ptp_info, struct bnxt_ptp_cfg,
|
||||
ptp_info);
|
||||
|
||||
timecounter_adjtime(&ptp->tc, delta);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bnxt_ptp_adjfreq(struct ptp_clock_info *ptp_info, s32 ppb)
|
||||
{
|
||||
struct bnxt_ptp_cfg *ptp = container_of(ptp_info, struct bnxt_ptp_cfg,
|
||||
ptp_info);
|
||||
s32 period, period1, period2, dif, dif1, dif2;
|
||||
s32 step, best_step = 0, best_period = 0;
|
||||
s32 best_dif = BNXT_MAX_PHC_DRIFT;
|
||||
u32 drift_sign = 1;
|
||||
|
||||
/* Frequency adjustment requires programming 3 values:
|
||||
* 1-bit direction
|
||||
* 5-bit adjustment step in 1 ns unit
|
||||
* 24-bit period in 1 us unit between adjustments
|
||||
*/
|
||||
if (ppb < 0) {
|
||||
ppb = -ppb;
|
||||
drift_sign = 0;
|
||||
}
|
||||
|
||||
if (ppb == 0) {
|
||||
/* no adjustment */
|
||||
best_step = 0;
|
||||
best_period = 0xFFFFFF;
|
||||
} else if (ppb >= BNXT_MAX_PHC_DRIFT) {
|
||||
/* max possible adjustment */
|
||||
best_step = 31;
|
||||
best_period = 1;
|
||||
} else {
|
||||
/* Find the best possible adjustment step and period */
|
||||
for (step = 0; step <= 31; step++) {
|
||||
period1 = step * 1000000 / ppb;
|
||||
period2 = period1 + 1;
|
||||
if (period1 != 0)
|
||||
dif1 = ppb - (step * 1000000 / period1);
|
||||
else
|
||||
dif1 = BNXT_MAX_PHC_DRIFT;
|
||||
if (dif1 < 0)
|
||||
dif1 = -dif1;
|
||||
dif2 = ppb - (step * 1000000 / period2);
|
||||
if (dif2 < 0)
|
||||
dif2 = -dif2;
|
||||
dif = (dif1 < dif2) ? dif1 : dif2;
|
||||
period = (dif1 < dif2) ? period1 : period2;
|
||||
if (dif < best_dif) {
|
||||
best_dif = dif;
|
||||
best_step = step;
|
||||
best_period = period;
|
||||
}
|
||||
}
|
||||
}
|
||||
writel((drift_sign << BNXT_GRCPF_REG_SYNC_TIME_ADJ_SIGN_SFT) |
|
||||
(best_step << BNXT_GRCPF_REG_SYNC_TIME_ADJ_VAL_SFT) |
|
||||
(best_period & BNXT_GRCPF_REG_SYNC_TIME_ADJ_PER_MSK),
|
||||
ptp->bp->bar0 + BNXT_GRCPF_REG_SYNC_TIME_ADJ);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bnxt_ptp_enable(struct ptp_clock_info *ptp,
|
||||
struct ptp_clock_request *rq, int on)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static void bnxt_clr_rx_ts(struct bnxt *bp)
|
||||
{
|
||||
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
|
||||
struct bnxt_pf_info *pf = &bp->pf;
|
||||
u16 port_id;
|
||||
int i = 0;
|
||||
u32 fifo;
|
||||
|
||||
if (!ptp)
|
||||
return;
|
||||
|
||||
port_id = pf->port_id;
|
||||
fifo = readl(bp->bar0 + ptp->rx_mapped_regs[BNXT_PTP_RX_FIFO]);
|
||||
while ((fifo & BNXT_PTP_RX_FIFO_PENDING) && (i < 10)) {
|
||||
writel(1 << port_id, bp->bar0 +
|
||||
ptp->rx_mapped_regs[BNXT_PTP_RX_FIFO_ADV]);
|
||||
fifo = readl(bp->bar0 + ptp->rx_mapped_regs[BNXT_PTP_RX_FIFO]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
static int bnxt_hwrm_ptp_cfg(struct bnxt *bp)
|
||||
{
|
||||
struct hwrm_port_mac_cfg_input req = {0};
|
||||
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
|
||||
u32 flags = 0;
|
||||
|
||||
if (!ptp)
|
||||
return 0;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PORT_MAC_CFG, -1, -1);
|
||||
|
||||
if (ptp->rx_filter)
|
||||
flags |= PORT_MAC_CFG_REQ_FLAGS_PTP_RX_TS_CAPTURE_ENABLE;
|
||||
else
|
||||
flags |= PORT_MAC_CFG_REQ_FLAGS_PTP_RX_TS_CAPTURE_DISABLE;
|
||||
if (ptp->tx_tstamp_en)
|
||||
flags |= PORT_MAC_CFG_REQ_FLAGS_PTP_TX_TS_CAPTURE_ENABLE;
|
||||
else
|
||||
flags |= PORT_MAC_CFG_REQ_FLAGS_PTP_TX_TS_CAPTURE_DISABLE;
|
||||
req.flags = cpu_to_le32(flags);
|
||||
req.enables = cpu_to_le32(
|
||||
PORT_MAC_CFG_REQ_ENABLES_RX_TS_CAPTURE_PTP_MSG_TYPE);
|
||||
req.rx_ts_capture_ptp_msg_type = cpu_to_le16(ptp->rxctl);
|
||||
|
||||
return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
}
|
||||
|
||||
int bnxt_hwtstamp_set(struct net_device *dev, struct ifreq *ifr)
|
||||
{
|
||||
struct bnxt *bp = netdev_priv(dev);
|
||||
struct hwtstamp_config stmpconf;
|
||||
struct bnxt_ptp_cfg *ptp;
|
||||
u16 old_rxctl, new_rxctl;
|
||||
int old_rx_filter, rc;
|
||||
u8 old_tx_tstamp_en;
|
||||
|
||||
ptp = bp->ptp_cfg;
|
||||
if (!ptp)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (copy_from_user(&stmpconf, ifr->ifr_data, sizeof(stmpconf)))
|
||||
return -EFAULT;
|
||||
|
||||
if (stmpconf.flags)
|
||||
return -EINVAL;
|
||||
|
||||
if (stmpconf.tx_type != HWTSTAMP_TX_ON &&
|
||||
stmpconf.tx_type != HWTSTAMP_TX_OFF)
|
||||
return -ERANGE;
|
||||
|
||||
old_rx_filter = ptp->rx_filter;
|
||||
old_rxctl = ptp->rxctl;
|
||||
old_tx_tstamp_en = ptp->tx_tstamp_en;
|
||||
switch (stmpconf.rx_filter) {
|
||||
case HWTSTAMP_FILTER_NONE:
|
||||
new_rxctl = 0;
|
||||
ptp->rx_filter = HWTSTAMP_FILTER_NONE;
|
||||
break;
|
||||
case HWTSTAMP_FILTER_PTP_V2_EVENT:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
|
||||
new_rxctl = BNXT_PTP_MSG_EVENTS;
|
||||
ptp->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
|
||||
break;
|
||||
case HWTSTAMP_FILTER_PTP_V2_SYNC:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
|
||||
new_rxctl = BNXT_PTP_MSG_SYNC;
|
||||
ptp->rx_filter = HWTSTAMP_FILTER_PTP_V2_SYNC;
|
||||
break;
|
||||
case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
|
||||
new_rxctl = BNXT_PTP_MSG_DELAY_REQ;
|
||||
ptp->rx_filter = HWTSTAMP_FILTER_PTP_V2_DELAY_REQ;
|
||||
break;
|
||||
default:
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
if (stmpconf.tx_type == HWTSTAMP_TX_ON)
|
||||
ptp->tx_tstamp_en = 1;
|
||||
else
|
||||
ptp->tx_tstamp_en = 0;
|
||||
|
||||
if (!old_rxctl && new_rxctl) {
|
||||
rc = bnxt_hwrm_ptp_cfg(bp);
|
||||
if (rc)
|
||||
goto ts_set_err;
|
||||
ptp->rxctl = new_rxctl;
|
||||
bnxt_clr_rx_ts(bp);
|
||||
}
|
||||
|
||||
rc = bnxt_hwrm_ptp_cfg(bp);
|
||||
if (rc)
|
||||
goto ts_set_err;
|
||||
|
||||
stmpconf.rx_filter = ptp->rx_filter;
|
||||
return copy_to_user(ifr->ifr_data, &stmpconf, sizeof(stmpconf)) ?
|
||||
-EFAULT : 0;
|
||||
|
||||
ts_set_err:
|
||||
ptp->rx_filter = old_rx_filter;
|
||||
ptp->rxctl = old_rxctl;
|
||||
ptp->tx_tstamp_en = old_tx_tstamp_en;
|
||||
return rc;
|
||||
}
|
||||
|
||||
int bnxt_hwtstamp_get(struct net_device *dev, struct ifreq *ifr)
|
||||
{
|
||||
struct bnxt *bp = netdev_priv(dev);
|
||||
struct hwtstamp_config stmpconf;
|
||||
struct bnxt_ptp_cfg *ptp;
|
||||
|
||||
ptp = bp->ptp_cfg;
|
||||
if (!ptp)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
stmpconf.flags = 0;
|
||||
stmpconf.tx_type = ptp->tx_tstamp_en ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
|
||||
|
||||
stmpconf.rx_filter = ptp->rx_filter;
|
||||
return copy_to_user(ifr->ifr_data, &stmpconf, sizeof(stmpconf)) ?
|
||||
-EFAULT : 0;
|
||||
}
|
||||
|
||||
static int bnxt_map_regs(struct bnxt *bp, u32 *reg_arr, int count, int reg_win)
|
||||
{
|
||||
u32 reg_base = *reg_arr & 0xfffff000;
|
||||
u32 win_off;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if ((reg_arr[i] & 0xfffff000) != reg_base)
|
||||
return -ERANGE;
|
||||
}
|
||||
win_off = BNXT_GRCPF_REG_WINDOW_BASE_OUT + (reg_win - 1) * 4;
|
||||
writel(reg_base, bp->bar0 + win_off);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bnxt_map_ptp_regs(struct bnxt *bp)
|
||||
{
|
||||
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
|
||||
u32 *reg_arr, reg_base;
|
||||
int rc, i;
|
||||
|
||||
reg_arr = ptp->rx_regs;
|
||||
rc = bnxt_map_regs(bp, reg_arr, BNXT_PTP_RX_REGS, 5);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
reg_arr = ptp->tx_regs;
|
||||
rc = bnxt_map_regs(bp, reg_arr, BNXT_PTP_TX_REGS, 6);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
reg_base = ptp->rx_regs[BNXT_PTP_RX_TS_L] & 0xfffff000;
|
||||
for (i = 0; i < BNXT_PTP_RX_REGS; i++)
|
||||
ptp->rx_mapped_regs[i] = 0x5000 + (ptp->rx_regs[i] & 0xfff);
|
||||
|
||||
reg_base = ptp->tx_regs[BNXT_PTP_TX_TS_L] & 0xfffff000;
|
||||
for (i = 0; i < BNXT_PTP_TX_REGS; i++)
|
||||
ptp->tx_mapped_regs[i] = 0x6000 + (ptp->tx_regs[i] & 0xfff);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bnxt_unmap_ptp_regs(struct bnxt *bp)
|
||||
{
|
||||
writel(0, bp->bar0 + BNXT_GRCPF_REG_WINDOW_BASE_OUT + 16);
|
||||
writel(0, bp->bar0 + BNXT_GRCPF_REG_WINDOW_BASE_OUT + 20);
|
||||
}
|
||||
|
||||
static u64 bnxt_cc_read(const struct cyclecounter *cc)
|
||||
{
|
||||
struct bnxt_ptp_cfg *ptp = container_of(cc, struct bnxt_ptp_cfg, cc);
|
||||
struct bnxt *bp = ptp->bp;
|
||||
u64 ns;
|
||||
|
||||
ns = readl(bp->bar0 + BNXT_GRCPF_REG_SYNC_TIME);
|
||||
ns |= (u64)readl(bp->bar0 + BNXT_GRCPF_REG_SYNC_TIME + 4) << 32;
|
||||
return ns;
|
||||
}
|
||||
|
||||
int bnxt_get_tx_ts(struct bnxt *bp, u64 *ts)
|
||||
{
|
||||
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
|
||||
u32 fifo;
|
||||
|
||||
fifo = readl(bp->bar0 + ptp->tx_mapped_regs[BNXT_PTP_TX_FIFO]);
|
||||
if (fifo & BNXT_PTP_TX_FIFO_EMPTY)
|
||||
return -EAGAIN;
|
||||
|
||||
fifo = readl(bp->bar0 + ptp->tx_mapped_regs[BNXT_PTP_TX_FIFO]);
|
||||
*ts = readl(bp->bar0 + ptp->tx_mapped_regs[BNXT_PTP_TX_TS_L]);
|
||||
*ts |= (u64)readl(bp->bar0 + ptp->tx_mapped_regs[BNXT_PTP_TX_TS_H]) <<
|
||||
32;
|
||||
readl(bp->bar0 + ptp->tx_mapped_regs[BNXT_PTP_TX_SEQ]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bnxt_get_rx_ts(struct bnxt *bp, u64 *ts)
|
||||
{
|
||||
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
|
||||
struct bnxt_pf_info *pf = &bp->pf;
|
||||
u16 port_id;
|
||||
u32 fifo;
|
||||
|
||||
if (!ptp)
|
||||
return -ENODEV;
|
||||
|
||||
fifo = readl(bp->bar0 + ptp->rx_mapped_regs[BNXT_PTP_RX_FIFO]);
|
||||
if (!(fifo & BNXT_PTP_RX_FIFO_PENDING))
|
||||
return -EAGAIN;
|
||||
|
||||
port_id = pf->port_id;
|
||||
writel(1 << port_id, bp->bar0 +
|
||||
ptp->rx_mapped_regs[BNXT_PTP_RX_FIFO_ADV]);
|
||||
|
||||
fifo = readl(bp->bar0 + ptp->rx_mapped_regs[BNXT_PTP_RX_FIFO]);
|
||||
if (fifo & BNXT_PTP_RX_FIFO_PENDING) {
|
||||
bnxt_clr_rx_ts(bp);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
*ts = readl(bp->bar0 + ptp->rx_mapped_regs[BNXT_PTP_RX_TS_L]);
|
||||
*ts |= (u64)readl(bp->bar0 + ptp->rx_mapped_regs[BNXT_PTP_RX_TS_H]) <<
|
||||
32;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ptp_clock_info bnxt_ptp_caps = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "bnxt clock",
|
||||
.max_adj = BNXT_MAX_PHC_DRIFT,
|
||||
.n_alarm = 0,
|
||||
.n_ext_ts = 0,
|
||||
.n_per_out = 1,
|
||||
.n_pins = 0,
|
||||
.pps = 0,
|
||||
.adjfreq = bnxt_ptp_adjfreq,
|
||||
.adjtime = bnxt_ptp_adjtime,
|
||||
.gettime64 = bnxt_ptp_gettime,
|
||||
.settime64 = bnxt_ptp_settime,
|
||||
.enable = bnxt_ptp_enable,
|
||||
};
|
||||
|
||||
int bnxt_ptp_init(struct bnxt *bp)
|
||||
{
|
||||
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
|
||||
int rc;
|
||||
|
||||
if (!ptp)
|
||||
return 0;
|
||||
rc = bnxt_map_ptp_regs(bp);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
atomic_set(&ptp->tx_avail, BNXT_MAX_TX_TS);
|
||||
|
||||
memset(&ptp->cc, 0, sizeof(ptp->cc));
|
||||
ptp->cc.read = bnxt_cc_read;
|
||||
ptp->cc.mask = CYCLECOUNTER_MASK(64);
|
||||
ptp->cc.shift = 0;
|
||||
ptp->cc.mult = 1;
|
||||
|
||||
timecounter_init(&ptp->tc, &ptp->cc, ktime_to_ns(ktime_get_real()));
|
||||
|
||||
ptp->ptp_info = bnxt_ptp_caps;
|
||||
ptp->ptp_clock = ptp_clock_register(&ptp->ptp_info, &bp->pdev->dev);
|
||||
if (IS_ERR(ptp->ptp_clock))
|
||||
ptp->ptp_clock = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bnxt_ptp_free(struct bnxt *bp)
|
||||
{
|
||||
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
|
||||
|
||||
if (!ptp)
|
||||
return;
|
||||
|
||||
if (ptp->ptp_clock)
|
||||
ptp_clock_unregister(ptp->ptp_clock);
|
||||
|
||||
ptp->ptp_clock = NULL;
|
||||
bnxt_unmap_ptp_regs(bp);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int bnxt_hwtstamp_set(struct net_device *dev, struct ifreq *ifr)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
int bnxt_hwtstamp_get(struct net_device *dev, struct ifreq *ifr)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
int bnxt_ptp_init(struct bnxt *bp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bnxt_ptp_free(struct bnxt *bp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/* Broadcom NetXtreme-C/E network driver.
|
||||
*
|
||||
* Copyright (c) 2017 Broadcom Limited
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef BNXT_PTP_H
|
||||
#define BNXT_PTP_H
|
||||
|
||||
#define BNXT_MAX_PHC_DRIFT 31000000
|
||||
|
||||
struct bnxt_ptp_cfg {
|
||||
#ifdef HAVE_IEEE1588_SUPPORT
|
||||
struct ptp_clock_info ptp_info;
|
||||
struct ptp_clock *ptp_clock;
|
||||
struct cyclecounter cc;
|
||||
struct timecounter tc;
|
||||
#endif
|
||||
struct bnxt *bp;
|
||||
atomic_t tx_avail;
|
||||
#define BNXT_MAX_TX_TS 1
|
||||
u16 rxctl;
|
||||
#define BNXT_PTP_MSG_SYNC (1 << 0)
|
||||
#define BNXT_PTP_MSG_DELAY_REQ (1 << 1)
|
||||
#define BNXT_PTP_MSG_PDELAY_REQ (1 << 2)
|
||||
#define BNXT_PTP_MSG_PDELAY_RESP (1 << 3)
|
||||
#define BNXT_PTP_MSG_FOLLOW_UP (1 << 8)
|
||||
#define BNXT_PTP_MSG_DELAY_RESP (1 << 9)
|
||||
#define BNXT_PTP_MSG_PDELAY_RESP_FOLLOW_UP (1 << 10)
|
||||
#define BNXT_PTP_MSG_ANNOUNCE (1 << 11)
|
||||
#define BNXT_PTP_MSG_SIGNALING (1 << 12)
|
||||
#define BNXT_PTP_MSG_MANAGEMENT (1 << 13)
|
||||
#define BNXT_PTP_MSG_EVENTS (BNXT_PTP_MSG_SYNC | \
|
||||
BNXT_PTP_MSG_DELAY_REQ | \
|
||||
BNXT_PTP_MSG_PDELAY_REQ | \
|
||||
BNXT_PTP_MSG_PDELAY_RESP)
|
||||
u8 tx_tstamp_en:1;
|
||||
int rx_filter;
|
||||
|
||||
#define BNXT_PTP_RX_TS_L 0
|
||||
#define BNXT_PTP_RX_TS_H 1
|
||||
#define BNXT_PTP_RX_SEQ 2
|
||||
#define BNXT_PTP_RX_FIFO 3
|
||||
#define BNXT_PTP_RX_FIFO_PENDING 0x1
|
||||
#define BNXT_PTP_RX_FIFO_ADV 4
|
||||
#define BNXT_PTP_RX_REGS 5
|
||||
|
||||
#define BNXT_PTP_TX_TS_L 0
|
||||
#define BNXT_PTP_TX_TS_H 1
|
||||
#define BNXT_PTP_TX_SEQ 2
|
||||
#define BNXT_PTP_TX_FIFO 3
|
||||
#define BNXT_PTP_TX_FIFO_EMPTY 0x2
|
||||
#define BNXT_PTP_TX_REGS 4
|
||||
u32 rx_regs[BNXT_PTP_RX_REGS];
|
||||
u32 rx_mapped_regs[BNXT_PTP_RX_REGS];
|
||||
u32 tx_regs[BNXT_PTP_TX_REGS];
|
||||
u32 tx_mapped_regs[BNXT_PTP_TX_REGS];
|
||||
};
|
||||
|
||||
int bnxt_hwtstamp_set(struct net_device *dev, struct ifreq *ifr);
|
||||
int bnxt_hwtstamp_get(struct net_device *dev, struct ifreq *ifr);
|
||||
int bnxt_get_tx_ts(struct bnxt *bp, u64 *ts);
|
||||
int bnxt_get_rx_ts(struct bnxt *bp, u64 *ts);
|
||||
int bnxt_ptp_init(struct bnxt *bp);
|
||||
void bnxt_ptp_free(struct bnxt *bp);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -11,15 +11,58 @@
|
|||
#ifndef BNXT_SRIOV_H
|
||||
#define BNXT_SRIOV_H
|
||||
|
||||
#define BNXT_FWD_RESP_SIZE_ERR(n) \
|
||||
((offsetof(struct hwrm_fwd_resp_input, encap_resp) + n) > \
|
||||
sizeof(struct hwrm_fwd_resp_input))
|
||||
|
||||
#define BNXT_EXEC_FWD_RESP_SIZE_ERR(n) \
|
||||
((offsetof(struct hwrm_exec_fwd_resp_input, encap_request) + n) >\
|
||||
offsetof(struct hwrm_exec_fwd_resp_input, encap_resp_target_id))
|
||||
|
||||
#define BNXT_VF_MIN_RSS_CTX 1
|
||||
#define BNXT_VF_MAX_RSS_CTX 1
|
||||
#define BNXT_VF_MIN_L2_CTX 1
|
||||
#define BNXT_VF_MAX_L2_CTX 4
|
||||
|
||||
#ifdef HAVE_NDO_GET_VF_CONFIG
|
||||
int bnxt_get_vf_config(struct net_device *, int, struct ifla_vf_info *);
|
||||
int bnxt_set_vf_mac(struct net_device *, int, u8 *);
|
||||
#ifdef NEW_NDO_SET_VF_VLAN
|
||||
int bnxt_set_vf_vlan(struct net_device *, int, u16, u8, __be16);
|
||||
#else
|
||||
int bnxt_set_vf_vlan(struct net_device *, int, u16, u8);
|
||||
#endif
|
||||
#ifdef HAVE_IFLA_TX_RATE
|
||||
int bnxt_set_vf_bw(struct net_device *, int, int, int);
|
||||
#else
|
||||
int bnxt_set_vf_bw(struct net_device *, int, int);
|
||||
#endif
|
||||
#ifdef HAVE_NDO_SET_VF_LINK_STATE
|
||||
int bnxt_set_vf_link_state(struct net_device *, int, int);
|
||||
#endif
|
||||
#ifdef HAVE_VF_SPOOFCHK
|
||||
int bnxt_set_vf_spoofchk(struct net_device *, int, bool);
|
||||
#endif
|
||||
#ifdef HAVE_NDO_SET_VF_TRUST
|
||||
int bnxt_set_vf_trust(struct net_device *dev, int vf_id, bool trust);
|
||||
#endif
|
||||
#ifdef HAVE_NDO_SET_VF_QUEUES
|
||||
int bnxt_set_vf_queues(struct net_device *dev, int vf_id, int min_txq,
|
||||
int max_txq, int min_rxq, int max_rxq);
|
||||
#endif
|
||||
#endif
|
||||
int bnxt_sriov_configure(struct pci_dev *pdev, int num_vfs);
|
||||
#ifndef PCIE_SRIOV_CONFIGURE
|
||||
void bnxt_start_sriov(struct bnxt *, int);
|
||||
void bnxt_sriov_init(unsigned int);
|
||||
void bnxt_sriov_exit(void);
|
||||
#endif
|
||||
int bnxt_cfg_hw_sriov(struct bnxt *bp, int *num_vfs, bool reset);
|
||||
void bnxt_sriov_disable(struct bnxt *);
|
||||
void bnxt_hwrm_exec_fwd_req(struct bnxt *);
|
||||
void bnxt_update_vf_mac(struct bnxt *);
|
||||
int bnxt_approve_mac(struct bnxt *, u8 *);
|
||||
int bnxt_approve_mac(struct bnxt *, u8 *, bool);
|
||||
void bnxt_update_vf_vnic(struct bnxt *bp, u32 vf_idx, u32 state);
|
||||
void bnxt_commit_vf_vnic(struct bnxt *bp, u32 vf_idx);
|
||||
bool bnxt_vf_vnic_state_is_up(struct bnxt *bp, u32 vf_idx);
|
||||
#endif
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -12,6 +12,8 @@
|
|||
|
||||
#ifdef CONFIG_BNXT_FLOWER_OFFLOAD
|
||||
|
||||
#include <net/ip_tunnels.h>
|
||||
|
||||
/* Structs used for storing the filter/actions of the TC cmd.
|
||||
*/
|
||||
struct bnxt_tc_l2_key {
|
||||
|
|
@ -21,6 +23,9 @@ struct bnxt_tc_l2_key {
|
|||
__be16 inner_vlan_tci;
|
||||
__be16 ether_type;
|
||||
u8 num_vlans;
|
||||
u8 dir;
|
||||
#define BNXT_DIR_RX 1
|
||||
#define BNXT_DIR_TX 0
|
||||
};
|
||||
|
||||
struct bnxt_tc_l3_key {
|
||||
|
|
@ -50,6 +55,19 @@ struct bnxt_tc_l4_key {
|
|||
};
|
||||
};
|
||||
|
||||
struct bnxt_tc_tunnel_key {
|
||||
struct bnxt_tc_l2_key l2;
|
||||
struct bnxt_tc_l3_key l3;
|
||||
struct bnxt_tc_l4_key l4;
|
||||
__be32 id;
|
||||
};
|
||||
|
||||
#define bnxt_eth_addr_key_mask_invalid(eth_addr, eth_addr_mask) \
|
||||
((is_wildcard(&(eth_addr)[0], ETH_ALEN) && \
|
||||
is_wildcard(&(eth_addr)[ETH_ALEN / 2], ETH_ALEN)) || \
|
||||
(is_wildcard(&(eth_addr_mask)[0], ETH_ALEN) && \
|
||||
is_wildcard(&(eth_addr_mask)[ETH_ALEN / 2], ETH_ALEN)))
|
||||
|
||||
struct bnxt_tc_actions {
|
||||
u32 flags;
|
||||
#define BNXT_TC_ACTION_FLAG_FWD BIT(0)
|
||||
|
|
@ -57,16 +75,30 @@ struct bnxt_tc_actions {
|
|||
#define BNXT_TC_ACTION_FLAG_PUSH_VLAN BIT(3)
|
||||
#define BNXT_TC_ACTION_FLAG_POP_VLAN BIT(4)
|
||||
#define BNXT_TC_ACTION_FLAG_DROP BIT(5)
|
||||
#define BNXT_TC_ACTION_FLAG_TUNNEL_ENCAP BIT(6)
|
||||
#define BNXT_TC_ACTION_FLAG_TUNNEL_DECAP BIT(7)
|
||||
#define BNXT_TC_ACTION_FLAG_L2_REWRITE BIT(8)
|
||||
#define BNXT_TC_ACTION_FLAG_NAT_XLATE BIT(9)
|
||||
|
||||
u16 dst_fid;
|
||||
struct net_device *dst_dev;
|
||||
__be16 push_vlan_tpid;
|
||||
__be16 push_vlan_tci;
|
||||
};
|
||||
|
||||
struct bnxt_tc_flow_stats {
|
||||
u64 packets;
|
||||
u64 bytes;
|
||||
/* tunnel encap */
|
||||
struct ip_tunnel_key tun_encap_key;
|
||||
#define PEDIT_OFFSET_SMAC_LAST_4_BYTES 0x8
|
||||
__be16 l2_rewrite_dmac[3];
|
||||
__be16 l2_rewrite_smac[3];
|
||||
struct {
|
||||
bool src_xlate; /* true => translate src,
|
||||
* false => translate dst
|
||||
* Mutually exclusive, i.e cannot set both
|
||||
*/
|
||||
bool l3_is_ipv4; /* false means L3 is ipv6 */
|
||||
struct bnxt_tc_l3_key l3;
|
||||
struct bnxt_tc_l4_key l4;
|
||||
} nat;
|
||||
};
|
||||
|
||||
struct bnxt_tc_flow {
|
||||
|
|
@ -76,6 +108,16 @@ struct bnxt_tc_flow {
|
|||
#define BNXT_TC_FLOW_FLAGS_IPV6_ADDRS BIT(3)
|
||||
#define BNXT_TC_FLOW_FLAGS_PORTS BIT(4)
|
||||
#define BNXT_TC_FLOW_FLAGS_ICMP BIT(5)
|
||||
#define BNXT_TC_FLOW_FLAGS_TUNL_ETH_ADDRS BIT(6)
|
||||
#define BNXT_TC_FLOW_FLAGS_TUNL_IPV4_ADDRS BIT(7)
|
||||
#define BNXT_TC_FLOW_FLAGS_TUNL_IPV6_ADDRS BIT(8)
|
||||
#define BNXT_TC_FLOW_FLAGS_TUNL_PORTS BIT(9)
|
||||
#define BNXT_TC_FLOW_FLAGS_TUNL_ID BIT(10)
|
||||
#define BNXT_TC_FLOW_FLAGS_TUNNEL (BNXT_TC_FLOW_FLAGS_TUNL_ETH_ADDRS | \
|
||||
BNXT_TC_FLOW_FLAGS_TUNL_IPV4_ADDRS | \
|
||||
BNXT_TC_FLOW_FLAGS_TUNL_IPV6_ADDRS |\
|
||||
BNXT_TC_FLOW_FLAGS_TUNL_PORTS |\
|
||||
BNXT_TC_FLOW_FLAGS_TUNL_ID)
|
||||
|
||||
/* flow applicable to pkts ingressing on this fid */
|
||||
u16 src_fid;
|
||||
|
|
@ -85,6 +127,8 @@ struct bnxt_tc_flow {
|
|||
struct bnxt_tc_l3_key l3_mask;
|
||||
struct bnxt_tc_l4_key l4_key;
|
||||
struct bnxt_tc_l4_key l4_mask;
|
||||
struct ip_tunnel_key tun_key;
|
||||
struct ip_tunnel_key tun_mask;
|
||||
|
||||
struct bnxt_tc_actions actions;
|
||||
|
||||
|
|
@ -93,13 +137,41 @@ struct bnxt_tc_flow {
|
|||
/* previous snap-shot of stats */
|
||||
struct bnxt_tc_flow_stats prev_stats;
|
||||
unsigned long lastused; /* jiffies */
|
||||
/* for calculating delta from prev_stats and
|
||||
* updating prev_stats atomically.
|
||||
*/
|
||||
spinlock_t stats_lock;
|
||||
};
|
||||
|
||||
/* L2 hash table
|
||||
* This data-struct is used for L2-flow table.
|
||||
* The L2 part of a flow is stored in a hash table.
|
||||
/*
|
||||
* Tunnel encap/decap hash table
|
||||
* This table is used to maintain a list of flows that use
|
||||
* the same tunnel encap/decap params (ip_daddrs, vni, udp_dport)
|
||||
* and the FW returned handle.
|
||||
* A separate table is maintained for encap and decap
|
||||
*/
|
||||
struct bnxt_tc_tunnel_node {
|
||||
struct ip_tunnel_key key;
|
||||
struct rhash_head node;
|
||||
|
||||
/* tunnel l2 info */
|
||||
struct bnxt_tc_l2_key l2_info;
|
||||
|
||||
#define INVALID_TUNNEL_HANDLE cpu_to_le32(0xffffffff)
|
||||
/* tunnel handle returned by FW */
|
||||
__le32 tunnel_handle;
|
||||
|
||||
u32 refcount;
|
||||
struct rcu_head rcu;
|
||||
};
|
||||
|
||||
/*
|
||||
* L2 hash table
|
||||
* The same data-struct is used for L2-flow table and L2-tunnel table.
|
||||
* The L2 part of a flow or tunnel is stored in a hash table.
|
||||
* A flow that shares the same L2 key/mask with an
|
||||
* already existing flow must refer to it's flow handle.
|
||||
* already existing flow/tunnel must refer to it's flow handle or
|
||||
* decap_filter_id respectively.
|
||||
*/
|
||||
struct bnxt_tc_l2_node {
|
||||
/* hash key: first 16b of key */
|
||||
|
|
@ -110,12 +182,18 @@ struct bnxt_tc_l2_node {
|
|||
/* a linked list of flows that share the same l2 key */
|
||||
struct list_head common_l2_flows;
|
||||
|
||||
/* number of flows sharing the l2 key */
|
||||
/* number of flows/tunnels sharing the l2 key */
|
||||
u16 refcount;
|
||||
|
||||
struct rcu_head rcu;
|
||||
};
|
||||
|
||||
/* Track if the TC offload API is invoked on an ingress or egress device. */
|
||||
enum {
|
||||
BNXT_TC_DEV_INGRESS = 1,
|
||||
BNXT_TC_DEV_EGRESS = 2
|
||||
};
|
||||
|
||||
struct bnxt_tc_flow_node {
|
||||
/* hash key: provided by TC */
|
||||
unsigned long cookie;
|
||||
|
|
@ -123,29 +201,54 @@ struct bnxt_tc_flow_node {
|
|||
|
||||
struct bnxt_tc_flow flow;
|
||||
|
||||
__le64 ext_flow_handle;
|
||||
__le16 flow_handle;
|
||||
__le32 flow_id;
|
||||
int tc_dev_dir;
|
||||
|
||||
/* L2 node in l2 hashtable that shares flow's l2 key */
|
||||
struct bnxt_tc_l2_node *l2_node;
|
||||
/* for the shared_flows list maintained in l2_node */
|
||||
struct list_head l2_list_node;
|
||||
|
||||
/* tunnel encap related */
|
||||
struct bnxt_tc_tunnel_node *encap_node;
|
||||
|
||||
/* tunnel decap related */
|
||||
struct bnxt_tc_tunnel_node *decap_node;
|
||||
/* L2 node in tunnel-l2 hashtable that shares flow's tunnel l2 key */
|
||||
struct bnxt_tc_l2_node *decap_l2_node;
|
||||
/* for the shared_flows list maintained in tunnel decap l2_node */
|
||||
struct list_head decap_l2_list_node;
|
||||
|
||||
struct rcu_head rcu;
|
||||
};
|
||||
|
||||
#ifdef HAVE_TC_CB_EGDEV
|
||||
int bnxt_tc_setup_flower(struct bnxt *bp, u16 src_fid,
|
||||
struct tc_cls_flower_offload *cls_flower);
|
||||
struct flow_cls_offload *cls_flower,
|
||||
int tc_dev_dir);
|
||||
#else
|
||||
int bnxt_tc_setup_flower(struct bnxt *bp, u16 src_fid,
|
||||
struct flow_cls_offload *cls_flower);
|
||||
#endif
|
||||
|
||||
int bnxt_init_tc(struct bnxt *bp);
|
||||
void bnxt_shutdown_tc(struct bnxt *bp);
|
||||
void bnxt_tc_flow_stats_work(struct bnxt *bp);
|
||||
#if defined(HAVE_TC_MATCHALL_FLOW_RULE) && defined(HAVE_FLOW_ACTION_POLICE)
|
||||
int bnxt_tc_setup_matchall(struct bnxt *bp, u16 src_fid,
|
||||
struct tc_cls_matchall_offload *cls_matchall);
|
||||
#endif
|
||||
|
||||
|
||||
static inline bool bnxt_tc_flower_enabled(struct bnxt *bp)
|
||||
{
|
||||
return bp->tc_info && bp->tc_info->enabled;
|
||||
}
|
||||
|
||||
#else /* CONFIG_BNXT_FLOWER_OFFLOAD */
|
||||
|
||||
static inline int bnxt_tc_setup_flower(struct bnxt *bp, u16 src_fid,
|
||||
struct tc_cls_flower_offload *cls_flower)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int bnxt_init_tc(struct bnxt *bp)
|
||||
{
|
||||
return 0;
|
||||
|
|
@ -154,5 +257,15 @@ static inline int bnxt_init_tc(struct bnxt *bp)
|
|||
static inline void bnxt_shutdown_tc(struct bnxt *bp)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void bnxt_tc_flow_stats_work(struct bnxt *bp)
|
||||
{
|
||||
}
|
||||
|
||||
static inline bool bnxt_tc_flower_enabled(struct bnxt *bp)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif /* CONFIG_BNXT_FLOWER_OFFLOAD */
|
||||
|
||||
#endif /* BNXT_TC_H */
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
/* Broadcom NetXtreme-C/E network driver.
|
||||
*
|
||||
* Copyright (c) 2016 Broadcom Limited
|
||||
* Copyright (c) 2016-2017 Broadcom Limited
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
|
@ -20,6 +21,7 @@
|
|||
#include <asm/byteorder.h>
|
||||
#include <linux/bitmap.h>
|
||||
|
||||
#include "bnxt_compat.h"
|
||||
#include "bnxt_hsi.h"
|
||||
#include "bnxt.h"
|
||||
#include "bnxt_ulp.h"
|
||||
|
|
@ -45,10 +47,8 @@ static int bnxt_register_dev(struct bnxt_en_dev *edev, int ulp_id,
|
|||
|
||||
max_stat_ctxs = bnxt_get_max_func_stat_ctxs(bp);
|
||||
if (max_stat_ctxs <= BNXT_MIN_ROCE_STAT_CTXS ||
|
||||
bp->num_stat_ctxs == max_stat_ctxs)
|
||||
bp->cp_nr_rings == max_stat_ctxs)
|
||||
return -ENOMEM;
|
||||
bnxt_set_max_func_stat_ctxs(bp, max_stat_ctxs -
|
||||
BNXT_MIN_ROCE_STAT_CTXS);
|
||||
}
|
||||
|
||||
atomic_set(&ulp->ref_count, 0);
|
||||
|
|
@ -79,16 +79,11 @@ static int bnxt_unregister_dev(struct bnxt_en_dev *edev, int ulp_id)
|
|||
netdev_err(bp->dev, "ulp id %d not registered\n", ulp_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (ulp_id == BNXT_ROCE_ULP) {
|
||||
unsigned int max_stat_ctxs;
|
||||
if (ulp_id == BNXT_ROCE_ULP && ulp->msix_requested)
|
||||
edev->en_ops->bnxt_free_msix(edev, ulp_id);
|
||||
|
||||
max_stat_ctxs = bnxt_get_max_func_stat_ctxs(bp);
|
||||
bnxt_set_max_func_stat_ctxs(bp, max_stat_ctxs + 1);
|
||||
if (ulp->msix_requested)
|
||||
edev->en_ops->bnxt_free_msix(edev, ulp_id);
|
||||
}
|
||||
if (ulp->max_async_event_id)
|
||||
bnxt_hwrm_func_rgtr_async_events(bp, NULL, 0);
|
||||
bnxt_hwrm_func_drv_rgtr(bp, NULL, 0, true);
|
||||
|
||||
RCU_INIT_POINTER(ulp->ulp_ops, NULL);
|
||||
synchronize_rcu();
|
||||
|
|
@ -101,13 +96,36 @@ static int bnxt_unregister_dev(struct bnxt_en_dev *edev, int ulp_id)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void bnxt_fill_msix_vecs(struct bnxt *bp, struct bnxt_msix_entry *ent)
|
||||
{
|
||||
struct bnxt_en_dev *edev = bp->edev;
|
||||
int num_msix, idx, i;
|
||||
|
||||
num_msix = edev->ulp_tbl[BNXT_ROCE_ULP].msix_requested;
|
||||
idx = edev->ulp_tbl[BNXT_ROCE_ULP].msix_base;
|
||||
for (i = 0; i < num_msix; i++) {
|
||||
ent[i].vector = bp->irq_tbl[idx + i].vector;
|
||||
ent[i].ring_idx = idx + i;
|
||||
if (bp->flags & BNXT_FLAG_CHIP_P5) {
|
||||
ent[i].db_offset = DB_PF_OFFSET_P5;
|
||||
if (BNXT_VF(bp))
|
||||
ent[i].db_offset = DB_VF_OFFSET_P5;
|
||||
} else {
|
||||
ent[i].db_offset = (idx + i) * 0x80;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int bnxt_req_msix_vecs(struct bnxt_en_dev *edev, int ulp_id,
|
||||
struct bnxt_msix_entry *ent, int num_msix)
|
||||
{
|
||||
struct net_device *dev = edev->net;
|
||||
struct bnxt *bp = netdev_priv(dev);
|
||||
struct bnxt_hw_resc *hw_resc;
|
||||
int max_idx, max_cp_rings;
|
||||
int avail_msix, i, idx;
|
||||
int avail_msix, idx;
|
||||
int total_vecs;
|
||||
int rc = 0;
|
||||
|
||||
ASSERT_RTNL();
|
||||
if (ulp_id != BNXT_ROCE_ULP)
|
||||
|
|
@ -116,23 +134,49 @@ static int bnxt_req_msix_vecs(struct bnxt_en_dev *edev, int ulp_id,
|
|||
if (!(bp->flags & BNXT_FLAG_USING_MSIX))
|
||||
return -ENODEV;
|
||||
|
||||
if (edev->ulp_tbl[ulp_id].msix_requested)
|
||||
return -EAGAIN;
|
||||
|
||||
max_cp_rings = bnxt_get_max_func_cp_rings(bp);
|
||||
max_idx = min_t(int, bp->total_irqs, max_cp_rings);
|
||||
avail_msix = max_idx - bp->cp_nr_rings;
|
||||
avail_msix = bnxt_get_avail_msix(bp, num_msix);
|
||||
if (!avail_msix)
|
||||
return -ENOMEM;
|
||||
if (avail_msix > num_msix)
|
||||
avail_msix = num_msix;
|
||||
|
||||
idx = max_idx - avail_msix;
|
||||
for (i = 0; i < avail_msix; i++) {
|
||||
ent[i].vector = bp->irq_tbl[idx + i].vector;
|
||||
ent[i].ring_idx = idx + i;
|
||||
ent[i].db_offset = (idx + i) * 0x80;
|
||||
if (BNXT_NEW_RM(bp)) {
|
||||
idx = bp->cp_nr_rings;
|
||||
} else {
|
||||
max_idx = min_t(int, bp->total_irqs, max_cp_rings);
|
||||
idx = max_idx - avail_msix;
|
||||
}
|
||||
bnxt_set_max_func_irqs(bp, max_idx - avail_msix);
|
||||
bnxt_set_max_func_cp_rings(bp, max_cp_rings - avail_msix);
|
||||
edev->ulp_tbl[ulp_id].msix_base = idx;
|
||||
edev->ulp_tbl[ulp_id].msix_requested = avail_msix;
|
||||
hw_resc = &bp->hw_resc;
|
||||
total_vecs = idx + avail_msix;
|
||||
if (bp->total_irqs < total_vecs ||
|
||||
(BNXT_NEW_RM(bp) && hw_resc->resv_irqs < total_vecs)) {
|
||||
if (netif_running(dev)) {
|
||||
bnxt_close_nic(bp, true, false);
|
||||
rc = bnxt_open_nic(bp, true, false);
|
||||
} else {
|
||||
rc = bnxt_reserve_rings(bp, true);
|
||||
}
|
||||
}
|
||||
if (rc) {
|
||||
edev->ulp_tbl[ulp_id].msix_requested = 0;
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
if (BNXT_NEW_RM(bp)) {
|
||||
int resv_msix;
|
||||
|
||||
resv_msix = hw_resc->resv_irqs - bp->cp_nr_rings;
|
||||
avail_msix = min_t(int, resv_msix, avail_msix);
|
||||
edev->ulp_tbl[ulp_id].msix_requested = avail_msix;
|
||||
}
|
||||
bnxt_fill_msix_vecs(bp, ent);
|
||||
edev->flags |= BNXT_EN_FLAG_MSIX_REQUESTED;
|
||||
return avail_msix;
|
||||
}
|
||||
|
||||
|
|
@ -140,33 +184,50 @@ static int bnxt_free_msix_vecs(struct bnxt_en_dev *edev, int ulp_id)
|
|||
{
|
||||
struct net_device *dev = edev->net;
|
||||
struct bnxt *bp = netdev_priv(dev);
|
||||
int max_cp_rings, msix_requested;
|
||||
|
||||
ASSERT_RTNL();
|
||||
if (ulp_id != BNXT_ROCE_ULP)
|
||||
return -EINVAL;
|
||||
|
||||
max_cp_rings = bnxt_get_max_func_cp_rings(bp);
|
||||
msix_requested = edev->ulp_tbl[ulp_id].msix_requested;
|
||||
bnxt_set_max_func_cp_rings(bp, max_cp_rings + msix_requested);
|
||||
if (!(edev->flags & BNXT_EN_FLAG_MSIX_REQUESTED))
|
||||
return 0;
|
||||
|
||||
edev->ulp_tbl[ulp_id].msix_requested = 0;
|
||||
bnxt_set_max_func_irqs(bp, bp->total_irqs);
|
||||
edev->flags &= ~BNXT_EN_FLAG_MSIX_REQUESTED;
|
||||
if (netif_running(dev) && !(edev->flags & BNXT_EN_FLAG_ULP_STOPPED)) {
|
||||
bnxt_close_nic(bp, true, false);
|
||||
bnxt_open_nic(bp, true, false);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bnxt_subtract_ulp_resources(struct bnxt *bp, int ulp_id)
|
||||
int bnxt_get_ulp_msix_num(struct bnxt *bp)
|
||||
{
|
||||
ASSERT_RTNL();
|
||||
if (bnxt_ulp_registered(bp->edev, ulp_id)) {
|
||||
if (bnxt_ulp_registered(bp->edev, BNXT_ROCE_ULP)) {
|
||||
struct bnxt_en_dev *edev = bp->edev;
|
||||
unsigned int msix_req, max;
|
||||
|
||||
msix_req = edev->ulp_tbl[ulp_id].msix_requested;
|
||||
max = bnxt_get_max_func_cp_rings(bp);
|
||||
bnxt_set_max_func_cp_rings(bp, max - msix_req);
|
||||
max = bnxt_get_max_func_stat_ctxs(bp);
|
||||
bnxt_set_max_func_stat_ctxs(bp, max - 1);
|
||||
return edev->ulp_tbl[BNXT_ROCE_ULP].msix_requested;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bnxt_get_ulp_msix_base(struct bnxt *bp)
|
||||
{
|
||||
if (bnxt_ulp_registered(bp->edev, BNXT_ROCE_ULP)) {
|
||||
struct bnxt_en_dev *edev = bp->edev;
|
||||
|
||||
if (edev->ulp_tbl[BNXT_ROCE_ULP].msix_requested)
|
||||
return edev->ulp_tbl[BNXT_ROCE_ULP].msix_base;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bnxt_get_ulp_stat_ctxs(struct bnxt *bp)
|
||||
{
|
||||
if (bnxt_ulp_registered(bp->edev, BNXT_ROCE_ULP))
|
||||
return BNXT_MIN_ROCE_STAT_CTXS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bnxt_send_msg(struct bnxt_en_dev *edev, int ulp_id,
|
||||
|
|
@ -177,12 +238,15 @@ static int bnxt_send_msg(struct bnxt_en_dev *edev, int ulp_id,
|
|||
struct input *req;
|
||||
int rc;
|
||||
|
||||
if ((ulp_id != BNXT_ROCE_ULP) && bp->fw_reset_state)
|
||||
return -EBUSY;
|
||||
|
||||
mutex_lock(&bp->hwrm_cmd_lock);
|
||||
req = fw_msg->msg;
|
||||
req->resp_addr = cpu_to_le64(bp->hwrm_cmd_resp_dma_addr);
|
||||
rc = _hwrm_send_message(bp, fw_msg->msg, fw_msg->msg_len,
|
||||
fw_msg->timeout);
|
||||
if (!rc) {
|
||||
if (rc != -EBUSY && rc != -E2BIG) {
|
||||
struct output *resp = bp->hwrm_cmd_resp_addr;
|
||||
u32 len = le16_to_cpu(resp->resp_len);
|
||||
|
||||
|
|
@ -214,6 +278,7 @@ void bnxt_ulp_stop(struct bnxt *bp)
|
|||
if (!edev)
|
||||
return;
|
||||
|
||||
edev->flags |= BNXT_EN_FLAG_ULP_STOPPED;
|
||||
for (i = 0; i < BNXT_MAX_ULP; i++) {
|
||||
struct bnxt_ulp *ulp = &edev->ulp_tbl[i];
|
||||
|
||||
|
|
@ -224,7 +289,7 @@ void bnxt_ulp_stop(struct bnxt *bp)
|
|||
}
|
||||
}
|
||||
|
||||
void bnxt_ulp_start(struct bnxt *bp)
|
||||
void bnxt_ulp_start(struct bnxt *bp, int err)
|
||||
{
|
||||
struct bnxt_en_dev *edev = bp->edev;
|
||||
struct bnxt_ulp_ops *ops;
|
||||
|
|
@ -233,6 +298,11 @@ void bnxt_ulp_start(struct bnxt *bp)
|
|||
if (!edev)
|
||||
return;
|
||||
|
||||
edev->flags &= ~BNXT_EN_FLAG_ULP_STOPPED;
|
||||
|
||||
if (err)
|
||||
return;
|
||||
|
||||
for (i = 0; i < BNXT_MAX_ULP; i++) {
|
||||
struct bnxt_ulp *ulp = &edev->ulp_tbl[i];
|
||||
|
||||
|
|
@ -287,6 +357,58 @@ void bnxt_ulp_shutdown(struct bnxt *bp)
|
|||
}
|
||||
}
|
||||
|
||||
void bnxt_ulp_irq_stop(struct bnxt *bp)
|
||||
{
|
||||
struct bnxt_en_dev *edev = bp->edev;
|
||||
struct bnxt_ulp_ops *ops;
|
||||
|
||||
if (!edev || !(edev->flags & BNXT_EN_FLAG_MSIX_REQUESTED))
|
||||
return;
|
||||
|
||||
if (bnxt_ulp_registered(bp->edev, BNXT_ROCE_ULP)) {
|
||||
struct bnxt_ulp *ulp = &edev->ulp_tbl[BNXT_ROCE_ULP];
|
||||
|
||||
if (!ulp->msix_requested)
|
||||
return;
|
||||
|
||||
ops = rtnl_dereference(ulp->ulp_ops);
|
||||
if (!ops || !ops->ulp_irq_stop)
|
||||
return;
|
||||
ops->ulp_irq_stop(ulp->handle);
|
||||
}
|
||||
}
|
||||
|
||||
void bnxt_ulp_irq_restart(struct bnxt *bp, int err)
|
||||
{
|
||||
struct bnxt_en_dev *edev = bp->edev;
|
||||
struct bnxt_ulp_ops *ops;
|
||||
|
||||
if (!edev || !(edev->flags & BNXT_EN_FLAG_MSIX_REQUESTED))
|
||||
return;
|
||||
|
||||
if (bnxt_ulp_registered(bp->edev, BNXT_ROCE_ULP)) {
|
||||
struct bnxt_ulp *ulp = &edev->ulp_tbl[BNXT_ROCE_ULP];
|
||||
struct bnxt_msix_entry *ent = NULL;
|
||||
|
||||
if (!ulp->msix_requested)
|
||||
return;
|
||||
|
||||
ops = rtnl_dereference(ulp->ulp_ops);
|
||||
if (!ops || !ops->ulp_irq_restart)
|
||||
return;
|
||||
|
||||
if (!err) {
|
||||
ent = kcalloc(ulp->msix_requested, sizeof(*ent),
|
||||
GFP_KERNEL);
|
||||
if (!ent)
|
||||
return;
|
||||
bnxt_fill_msix_vecs(bp, ent);
|
||||
}
|
||||
ops->ulp_irq_restart(ulp->handle, ent);
|
||||
kfree(ent);
|
||||
}
|
||||
}
|
||||
|
||||
void bnxt_ulp_async_events(struct bnxt *bp, struct hwrm_async_event_cmpl *cmpl)
|
||||
{
|
||||
u16 event_id = le16_to_cpu(cmpl->event_id);
|
||||
|
|
@ -331,7 +453,7 @@ static int bnxt_register_async_events(struct bnxt_en_dev *edev, int ulp_id,
|
|||
/* Make sure bnxt_ulp_async_events() sees this order */
|
||||
smp_wmb();
|
||||
ulp->max_async_event_id = max_id;
|
||||
bnxt_hwrm_func_rgtr_async_events(bp, events_bmap, max_id + 1);
|
||||
bnxt_hwrm_func_drv_rgtr(bp, events_bmap, max_id + 1, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -361,6 +483,8 @@ struct bnxt_en_dev *bnxt_ulp_probe(struct net_device *dev)
|
|||
edev->flags |= BNXT_EN_FLAG_ROCEV2_CAP;
|
||||
edev->net = dev;
|
||||
edev->pdev = bp->pdev;
|
||||
edev->l2_db_size = bp->db_size;
|
||||
edev->l2_db_size_nc = bp->db_size_nc;
|
||||
bp->edev = edev;
|
||||
}
|
||||
return bp->edev;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* Broadcom NetXtreme-C/E network driver.
|
||||
*
|
||||
* Copyright (c) 2016 Broadcom Limited
|
||||
* Copyright (c) 2016-2017 Broadcom Limited
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -10,6 +10,8 @@
|
|||
#ifndef BNXT_ULP_H
|
||||
#define BNXT_ULP_H
|
||||
|
||||
#include <linux/version.h>
|
||||
|
||||
#define BNXT_ROCE_ULP 0
|
||||
#define BNXT_OTHER_ULP 1
|
||||
#define BNXT_MAX_ULP 2
|
||||
|
|
@ -20,6 +22,15 @@
|
|||
struct hwrm_async_event_cmpl;
|
||||
struct bnxt;
|
||||
|
||||
struct bnxt_msix_entry {
|
||||
u32 vector;
|
||||
u32 ring_idx;
|
||||
u32 db_offset;
|
||||
};
|
||||
|
||||
/* Change BNXT_ULP_VERSION in bnxt.h if any structure or API exposed to
|
||||
* bnxt_re is modified.
|
||||
*/
|
||||
struct bnxt_ulp_ops {
|
||||
/* async_notifier() cannot sleep (in BH context) */
|
||||
void (*ulp_async_notifier)(void *, struct hwrm_async_event_cmpl *);
|
||||
|
|
@ -27,12 +38,8 @@ struct bnxt_ulp_ops {
|
|||
void (*ulp_start)(void *);
|
||||
void (*ulp_sriov_config)(void *, int);
|
||||
void (*ulp_shutdown)(void *);
|
||||
};
|
||||
|
||||
struct bnxt_msix_entry {
|
||||
u32 vector;
|
||||
u32 ring_idx;
|
||||
u32 db_offset;
|
||||
void (*ulp_irq_stop)(void *);
|
||||
void (*ulp_irq_restart)(void *, struct bnxt_msix_entry *);
|
||||
};
|
||||
|
||||
struct bnxt_fw_msg {
|
||||
|
|
@ -49,6 +56,7 @@ struct bnxt_ulp {
|
|||
unsigned long *async_events_bmap;
|
||||
u16 max_async_event_id;
|
||||
u16 msix_requested;
|
||||
u16 msix_base;
|
||||
atomic_t ref_count;
|
||||
};
|
||||
|
||||
|
|
@ -60,8 +68,18 @@ struct bnxt_en_dev {
|
|||
#define BNXT_EN_FLAG_ROCEV2_CAP 0x2
|
||||
#define BNXT_EN_FLAG_ROCE_CAP (BNXT_EN_FLAG_ROCEV1_CAP | \
|
||||
BNXT_EN_FLAG_ROCEV2_CAP)
|
||||
#define BNXT_EN_FLAG_MSIX_REQUESTED 0x4
|
||||
#define BNXT_EN_FLAG_ULP_STOPPED 0x8
|
||||
const struct bnxt_en_ops *en_ops;
|
||||
struct bnxt_ulp ulp_tbl[BNXT_MAX_ULP];
|
||||
int l2_db_size; /* Doorbell BAR size in
|
||||
* bytes mapped by L2
|
||||
* driver.
|
||||
*/
|
||||
int l2_db_size_nc; /* Doorbell BAR size in
|
||||
* bytes mapped as non-
|
||||
* cacheable.
|
||||
*/
|
||||
};
|
||||
|
||||
struct bnxt_en_ops {
|
||||
|
|
@ -84,12 +102,15 @@ static inline bool bnxt_ulp_registered(struct bnxt_en_dev *edev, int ulp_id)
|
|||
return false;
|
||||
}
|
||||
|
||||
void bnxt_subtract_ulp_resources(struct bnxt *bp, int ulp_id);
|
||||
int bnxt_get_ulp_msix_num(struct bnxt *bp);
|
||||
int bnxt_get_ulp_msix_base(struct bnxt *bp);
|
||||
int bnxt_get_ulp_stat_ctxs(struct bnxt *bp);
|
||||
void bnxt_ulp_stop(struct bnxt *bp);
|
||||
void bnxt_ulp_start(struct bnxt *bp);
|
||||
void bnxt_ulp_start(struct bnxt *bp, int err);
|
||||
void bnxt_ulp_sriov_cfg(struct bnxt *bp, int num_vfs);
|
||||
void bnxt_ulp_shutdown(struct bnxt *bp);
|
||||
void bnxt_ulp_irq_stop(struct bnxt *bp);
|
||||
void bnxt_ulp_irq_restart(struct bnxt *bp, int err);
|
||||
void bnxt_ulp_async_events(struct bnxt *bp, struct hwrm_async_event_cmpl *cmpl);
|
||||
struct bnxt_en_dev *bnxt_ulp_probe(struct net_device *dev);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -11,14 +11,18 @@
|
|||
#include <linux/etherdevice.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/jhash.h>
|
||||
#ifdef HAVE_TC_SETUP_TYPE
|
||||
#include <net/pkt_cls.h>
|
||||
#endif
|
||||
|
||||
#include "bnxt_compat.h"
|
||||
#include "bnxt_hsi.h"
|
||||
#include "bnxt.h"
|
||||
#include "bnxt_vfr.h"
|
||||
#include "bnxt_devlink.h"
|
||||
#include "bnxt_tc.h"
|
||||
|
||||
#ifdef CONFIG_BNXT_SRIOV
|
||||
#ifdef CONFIG_VF_REPS
|
||||
|
||||
#define CFA_HANDLE_INVALID 0xffff
|
||||
#define VF_IDX_INVALID 0xffff
|
||||
|
|
@ -63,6 +67,31 @@ static int hwrm_cfa_vfr_free(struct bnxt *bp, u16 vf_idx)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int bnxt_hwrm_vfr_qcfg(struct bnxt *bp, struct bnxt_vf_rep *vf_rep,
|
||||
u16 *max_mtu)
|
||||
{
|
||||
struct hwrm_func_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
|
||||
struct hwrm_func_qcfg_input req = {0};
|
||||
u16 mtu;
|
||||
int rc;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_QCFG, -1, -1);
|
||||
req.fid = bp->pf.vf[vf_rep->vf_idx].fw_fid;
|
||||
|
||||
mutex_lock(&bp->hwrm_cmd_lock);
|
||||
|
||||
rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
if (!rc) {
|
||||
mtu = le16_to_cpu(resp->max_mtu_configured);
|
||||
if (!mtu)
|
||||
*max_mtu = BNXT_MAX_MTU;
|
||||
else
|
||||
*max_mtu = mtu;
|
||||
}
|
||||
mutex_unlock(&bp->hwrm_cmd_lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bnxt_vf_rep_open(struct net_device *dev)
|
||||
{
|
||||
struct bnxt_vf_rep *vf_rep = netdev_priv(dev);
|
||||
|
|
@ -115,21 +144,143 @@ bnxt_vf_rep_get_stats64(struct net_device *dev,
|
|||
stats->tx_bytes = vf_rep->tx_stats.bytes;
|
||||
}
|
||||
|
||||
static int bnxt_vf_rep_setup_tc(struct net_device *dev, enum tc_setup_type type,
|
||||
void *type_data)
|
||||
#ifdef CONFIG_BNXT_FLOWER_OFFLOAD
|
||||
#ifdef HAVE_TC_SETUP_TYPE
|
||||
#ifdef HAVE_TC_SETUP_BLOCK
|
||||
static LIST_HEAD(bnxt_vf_block_cb_list);
|
||||
|
||||
static int bnxt_vf_rep_setup_tc_block_cb(enum tc_setup_type type,
|
||||
void *type_data,
|
||||
void *cb_priv)
|
||||
{
|
||||
struct bnxt_vf_rep *vf_rep = netdev_priv(dev);
|
||||
struct bnxt_vf_rep *vf_rep = cb_priv;
|
||||
struct bnxt *bp = vf_rep->bp;
|
||||
int vf_fid = bp->pf.vf[vf_rep->vf_idx].fw_fid;
|
||||
|
||||
if (!bnxt_tc_flower_enabled(vf_rep->bp) ||
|
||||
!tc_cls_can_offload_and_chain0(bp->dev, type_data))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
switch (type) {
|
||||
case TC_SETUP_CLSFLOWER:
|
||||
#ifdef HAVE_TC_CB_EGDEV
|
||||
return bnxt_tc_setup_flower(bp, vf_fid, type_data,
|
||||
BNXT_TC_DEV_INGRESS);
|
||||
#else
|
||||
return bnxt_tc_setup_flower(bp, vf_fid, type_data);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_TC_MATCHALL_FLOW_RULE) && defined(HAVE_FLOW_ACTION_POLICE)
|
||||
case TC_SETUP_CLSMATCHALL:
|
||||
return bnxt_tc_setup_matchall(bp, vf_fid, type_data);
|
||||
#endif
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_TC_SETUP_BLOCK */
|
||||
|
||||
static int bnxt_vf_rep_setup_tc(struct net_device *dev, enum tc_setup_type type,
|
||||
void *type_data)
|
||||
{
|
||||
struct bnxt_vf_rep *vf_rep = netdev_priv(dev);
|
||||
|
||||
switch (type) {
|
||||
#ifdef HAVE_TC_SETUP_BLOCK
|
||||
case TC_SETUP_BLOCK:
|
||||
return flow_block_cb_setup_simple(type_data,
|
||||
&bnxt_vf_block_cb_list,
|
||||
bnxt_vf_rep_setup_tc_block_cb, vf_rep, vf_rep, true);
|
||||
#else
|
||||
case TC_SETUP_CLSFLOWER: {
|
||||
struct bnxt *bp = vf_rep->bp;
|
||||
int vf_fid = bp->pf.vf[vf_rep->vf_idx].fw_fid;
|
||||
|
||||
#ifdef HAVE_TC_CB_EGDEV
|
||||
return bnxt_tc_setup_flower(bp, vf_fid, type_data,
|
||||
BNXT_TC_DEV_INGRESS);
|
||||
#else
|
||||
return bnxt_tc_setup_flower(bp, vf_fid, type_data);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
#else /* HAVE_TC_SETUP_TYPE */
|
||||
|
||||
#ifdef HAVE_CHAIN_INDEX
|
||||
static int bnxt_vf_rep_setup_tc(struct net_device *dev, u32 handle,
|
||||
u32 chain_index, __be16 proto,
|
||||
struct tc_to_netdev *ntc)
|
||||
#else
|
||||
static int bnxt_vf_rep_setup_tc(struct net_device *dev, u32 handle,
|
||||
__be16 proto, struct tc_to_netdev *ntc)
|
||||
#endif
|
||||
{
|
||||
struct bnxt_vf_rep *vf_rep = netdev_priv(dev);
|
||||
|
||||
if (!bnxt_tc_flower_enabled(vf_rep->bp))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
switch (ntc->type) {
|
||||
case TC_SETUP_CLSFLOWER:
|
||||
#ifdef HAVE_TC_CB_EGDEV
|
||||
return bnxt_tc_setup_flower(vf_rep->bp,
|
||||
bnxt_vf_rep_get_fid(dev),
|
||||
ntc->cls_flower,
|
||||
BNXT_TC_DEV_INGRESS);
|
||||
#else
|
||||
return bnxt_tc_setup_flower(vf_rep->bp,
|
||||
bnxt_vf_rep_get_fid(dev),
|
||||
ntc->cls_flower);
|
||||
#endif
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_TC_SETUP_TYPE */
|
||||
|
||||
#ifdef HAVE_TC_CB_EGDEV
|
||||
static int bnxt_vf_rep_tc_cb_egdev(enum tc_setup_type type, void *type_data,
|
||||
void *cb_priv)
|
||||
{
|
||||
struct bnxt_vf_rep *vf_rep = cb_priv;
|
||||
struct bnxt *bp = vf_rep->bp;
|
||||
int vf_fid = bp->pf.vf[vf_rep->vf_idx].fw_fid;
|
||||
|
||||
if (!bnxt_tc_flower_enabled(vf_rep->bp) ||
|
||||
!tc_cls_can_offload_and_chain0(bp->dev, type_data))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
switch (type) {
|
||||
case TC_SETUP_CLSFLOWER:
|
||||
return bnxt_tc_setup_flower(bp, vf_fid, type_data,
|
||||
BNXT_TC_DEV_EGRESS);
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
#ifdef HAVE_TC_SETUP_TYPE
|
||||
static int bnxt_vf_rep_tc_cb_egdev(enum tc_setup_type type, void *type_data,
|
||||
void *cb_priv)
|
||||
#else
|
||||
static int bnxt_vf_rep_tc_cb_egdev(int type, void *type_data, void *cb_priv)
|
||||
#endif /* HAVE_TC_SETUP_TYPE */
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* HAVE_TC_CB_EGDEV */
|
||||
|
||||
#define bnxt_cb_egdev ((void *)bnxt_vf_rep_tc_cb_egdev)
|
||||
|
||||
#endif /* CONFIG_BNXT_FLOWER_OFFLOAD */
|
||||
|
||||
struct net_device *bnxt_get_vf_rep(struct bnxt *bp, u16 cfa_code)
|
||||
{
|
||||
u16 vf_idx;
|
||||
|
|
@ -145,9 +296,7 @@ struct net_device *bnxt_get_vf_rep(struct bnxt *bp, u16 cfa_code)
|
|||
void bnxt_vf_rep_rx(struct bnxt *bp, struct sk_buff *skb)
|
||||
{
|
||||
struct bnxt_vf_rep *vf_rep = netdev_priv(skb->dev);
|
||||
struct bnxt_vf_rep_stats *rx_stats;
|
||||
|
||||
rx_stats = &vf_rep->rx_stats;
|
||||
vf_rep->rx_stats.bytes += skb->len;
|
||||
vf_rep->rx_stats.packets++;
|
||||
|
||||
|
|
@ -175,6 +324,20 @@ static void bnxt_vf_rep_get_drvinfo(struct net_device *dev,
|
|||
strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version));
|
||||
}
|
||||
|
||||
#ifdef HAVE_NDO_GET_PORT_PARENT_ID
|
||||
static int bnxt_vf_rep_get_port_parent_id(struct net_device *dev,
|
||||
struct netdev_phys_item_id *ppid)
|
||||
{
|
||||
struct bnxt_vf_rep *vf_rep = netdev_priv(dev);
|
||||
|
||||
/* as only PORT_PARENT_ID is supported currently use common code
|
||||
* between PF and VF-rep for now.
|
||||
*/
|
||||
return bnxt_get_port_parent_id(vf_rep->bp->dev, ppid);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int bnxt_vf_rep_port_attr_get(struct net_device *dev,
|
||||
struct switchdev_attr *attr)
|
||||
{
|
||||
|
|
@ -189,20 +352,42 @@ static int bnxt_vf_rep_port_attr_get(struct net_device *dev,
|
|||
static const struct switchdev_ops bnxt_vf_rep_switchdev_ops = {
|
||||
.switchdev_port_attr_get = bnxt_vf_rep_port_attr_get
|
||||
};
|
||||
#endif
|
||||
|
||||
static const struct ethtool_ops bnxt_vf_rep_ethtool_ops = {
|
||||
.get_drvinfo = bnxt_vf_rep_get_drvinfo
|
||||
};
|
||||
|
||||
static const struct net_device_ops bnxt_vf_rep_netdev_ops = {
|
||||
#ifdef HAVE_NDO_SETUP_TC_RH
|
||||
.ndo_size = sizeof(const struct net_device_ops),
|
||||
#endif
|
||||
.ndo_open = bnxt_vf_rep_open,
|
||||
.ndo_stop = bnxt_vf_rep_close,
|
||||
.ndo_start_xmit = bnxt_vf_rep_xmit,
|
||||
.ndo_get_stats64 = bnxt_vf_rep_get_stats64,
|
||||
#ifdef CONFIG_BNXT_FLOWER_OFFLOAD
|
||||
#ifdef HAVE_NDO_SETUP_TC_RH
|
||||
.extended.ndo_setup_tc_rh = bnxt_vf_rep_setup_tc,
|
||||
#else
|
||||
.ndo_setup_tc = bnxt_vf_rep_setup_tc,
|
||||
#endif
|
||||
#endif
|
||||
#ifdef HAVE_NDO_GET_PORT_PARENT_ID
|
||||
.ndo_get_port_parent_id = bnxt_vf_rep_get_port_parent_id,
|
||||
#endif
|
||||
#ifdef HAVE_EXT_GET_PHYS_PORT_NAME
|
||||
.extended.ndo_get_phys_port_name = bnxt_vf_rep_get_phys_port_name
|
||||
#else
|
||||
.ndo_get_phys_port_name = bnxt_vf_rep_get_phys_port_name
|
||||
#endif
|
||||
};
|
||||
|
||||
bool bnxt_dev_is_vf_rep(struct net_device *dev)
|
||||
{
|
||||
return dev->netdev_ops == &bnxt_vf_rep_netdev_ops;
|
||||
}
|
||||
|
||||
/* Called when the parent PF interface is closed:
|
||||
* As the mode transition from SWITCHDEV to LEGACY
|
||||
* happens under the rtnl_lock() this routine is safe
|
||||
|
|
@ -258,8 +443,14 @@ static void __bnxt_vf_reps_destroy(struct bnxt *bp)
|
|||
/* if register_netdev failed, then netdev_ops
|
||||
* would have been set to NULL
|
||||
*/
|
||||
if (vf_rep->dev->netdev_ops)
|
||||
if (vf_rep->dev->netdev_ops) {
|
||||
#ifdef CONFIG_BNXT_FLOWER_OFFLOAD
|
||||
bnxt_unreg_egdev(vf_rep->dev,
|
||||
bnxt_cb_egdev,
|
||||
(void *)vf_rep);
|
||||
#endif
|
||||
unregister_netdev(vf_rep->dev);
|
||||
}
|
||||
free_netdev(vf_rep->dev);
|
||||
}
|
||||
}
|
||||
|
|
@ -321,10 +512,13 @@ static void bnxt_vf_rep_netdev_init(struct bnxt *bp, struct bnxt_vf_rep *vf_rep,
|
|||
struct net_device *dev)
|
||||
{
|
||||
struct net_device *pf_dev = bp->dev;
|
||||
u16 max_mtu;
|
||||
|
||||
dev->netdev_ops = &bnxt_vf_rep_netdev_ops;
|
||||
dev->ethtool_ops = &bnxt_vf_rep_ethtool_ops;
|
||||
#ifndef HAVE_NDO_GET_PORT_PARENT_ID
|
||||
SWITCHDEV_SET_OPS(dev, &bnxt_vf_rep_switchdev_ops);
|
||||
#endif
|
||||
/* Just inherit all the featues of the parent PF as the VF-R
|
||||
* uses the RX/TX rings of the parent PF
|
||||
*/
|
||||
|
|
@ -336,6 +530,15 @@ static void bnxt_vf_rep_netdev_init(struct bnxt *bp, struct bnxt_vf_rep *vf_rep,
|
|||
bnxt_vf_rep_eth_addr_gen(bp->pf.mac_addr, vf_rep->vf_idx,
|
||||
dev->perm_addr);
|
||||
ether_addr_copy(dev->dev_addr, dev->perm_addr);
|
||||
/* Set VF-Rep's max-mtu to the corresponding VF's max-mtu */
|
||||
if (!bnxt_hwrm_vfr_qcfg(bp, vf_rep, &max_mtu))
|
||||
#ifdef HAVE_NET_DEVICE_EXT
|
||||
dev->extended->max_mtu = max_mtu;
|
||||
dev->extended->min_mtu = ETH_ZLEN;
|
||||
#else
|
||||
dev->max_mtu = max_mtu;
|
||||
dev->min_mtu = ETH_ZLEN;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int bnxt_vf_reps_create(struct bnxt *bp)
|
||||
|
|
@ -345,13 +548,16 @@ static int bnxt_vf_reps_create(struct bnxt *bp)
|
|||
struct net_device *dev;
|
||||
int rc, i;
|
||||
|
||||
if (!(bp->flags & BNXT_FLAG_DSN_VALID))
|
||||
return -ENODEV;
|
||||
|
||||
bp->vf_reps = kcalloc(num_vfs, sizeof(vf_rep), GFP_KERNEL);
|
||||
if (!bp->vf_reps)
|
||||
return -ENOMEM;
|
||||
|
||||
/* storage for cfa_code to vf-idx mapping */
|
||||
cfa_code_map = kmalloc(sizeof(*bp->cfa_code_map) * MAX_CFA_CODE,
|
||||
GFP_KERNEL);
|
||||
cfa_code_map = kmalloc_array(MAX_CFA_CODE, sizeof(*bp->cfa_code_map),
|
||||
GFP_KERNEL);
|
||||
if (!cfa_code_map) {
|
||||
rc = -ENOMEM;
|
||||
goto err;
|
||||
|
|
@ -400,6 +606,10 @@ static int bnxt_vf_reps_create(struct bnxt *bp)
|
|||
dev->netdev_ops = NULL;
|
||||
goto err;
|
||||
}
|
||||
#ifdef CONFIG_BNXT_FLOWER_OFFLOAD
|
||||
bnxt_reg_egdev(vf_rep->dev, bnxt_cb_egdev, (void *)vf_rep,
|
||||
vf_rep->vf_idx);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* publish cfa_code_map only after all VF-reps have been initialized */
|
||||
|
|
@ -416,7 +626,7 @@ err:
|
|||
}
|
||||
|
||||
/* Devlink related routines */
|
||||
static int bnxt_dl_eswitch_mode_get(struct devlink *devlink, u16 *mode)
|
||||
int bnxt_dl_eswitch_mode_get(struct devlink *devlink, u16 *mode)
|
||||
{
|
||||
struct bnxt *bp = bnxt_get_bp_from_dl(devlink);
|
||||
|
||||
|
|
@ -424,7 +634,12 @@ static int bnxt_dl_eswitch_mode_get(struct devlink *devlink, u16 *mode)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int bnxt_dl_eswitch_mode_set(struct devlink *devlink, u16 mode)
|
||||
#ifdef HAVE_ESWITCH_MODE_SET_EXTACK
|
||||
int bnxt_dl_eswitch_mode_set(struct devlink *devlink, u16 mode,
|
||||
struct netlink_ext_ack *extack)
|
||||
#else
|
||||
int bnxt_dl_eswitch_mode_set(struct devlink *devlink, u16 mode)
|
||||
#endif
|
||||
{
|
||||
struct bnxt *bp = bnxt_get_bp_from_dl(devlink);
|
||||
int rc = 0;
|
||||
|
|
@ -444,9 +659,14 @@ static int bnxt_dl_eswitch_mode_set(struct devlink *devlink, u16 mode)
|
|||
break;
|
||||
|
||||
case DEVLINK_ESWITCH_MODE_SWITCHDEV:
|
||||
if (bp->hwrm_spec_code < 0x10803) {
|
||||
netdev_warn(bp->dev, "FW does not support SRIOV E-Switch SWITCHDEV mode\n");
|
||||
rc = -ENOTSUPP;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (pci_num_vf(bp->pdev) == 0) {
|
||||
netdev_info(bp->dev,
|
||||
"Enable VFs before setting switchdev mode");
|
||||
netdev_info(bp->dev, "Enable VFs before setting switchdev mode");
|
||||
rc = -EPERM;
|
||||
goto done;
|
||||
}
|
||||
|
|
@ -462,52 +682,4 @@ done:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static const struct devlink_ops bnxt_dl_ops = {
|
||||
.eswitch_mode_set = bnxt_dl_eswitch_mode_set,
|
||||
.eswitch_mode_get = bnxt_dl_eswitch_mode_get
|
||||
};
|
||||
|
||||
int bnxt_dl_register(struct bnxt *bp)
|
||||
{
|
||||
struct devlink *dl;
|
||||
int rc;
|
||||
|
||||
if (!pci_find_ext_capability(bp->pdev, PCI_EXT_CAP_ID_SRIOV))
|
||||
return 0;
|
||||
|
||||
if (bp->hwrm_spec_code < 0x10800) {
|
||||
netdev_warn(bp->dev, "Firmware does not support SR-IOV E-Switch SWITCHDEV mode.\n");
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
dl = devlink_alloc(&bnxt_dl_ops, sizeof(struct bnxt_dl));
|
||||
if (!dl) {
|
||||
netdev_warn(bp->dev, "devlink_alloc failed");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
bnxt_link_bp_to_dl(bp, dl);
|
||||
bp->eswitch_mode = DEVLINK_ESWITCH_MODE_LEGACY;
|
||||
rc = devlink_register(dl, &bp->pdev->dev);
|
||||
if (rc) {
|
||||
bnxt_link_bp_to_dl(bp, NULL);
|
||||
devlink_free(dl);
|
||||
netdev_warn(bp->dev, "devlink_register failed. rc=%d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bnxt_dl_unregister(struct bnxt *bp)
|
||||
{
|
||||
struct devlink *dl = bp->dl;
|
||||
|
||||
if (!dl)
|
||||
return;
|
||||
|
||||
devlink_unregister(dl);
|
||||
devlink_free(dl);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* CONFIG_VF_REPS */
|
||||
|
|
|
|||
|
|
@ -10,35 +10,10 @@
|
|||
#ifndef BNXT_VFR_H
|
||||
#define BNXT_VFR_H
|
||||
|
||||
#ifdef CONFIG_BNXT_SRIOV
|
||||
#ifdef CONFIG_VF_REPS
|
||||
|
||||
#define MAX_CFA_CODE 65536
|
||||
|
||||
/* Struct to hold housekeeping info needed by devlink interface */
|
||||
struct bnxt_dl {
|
||||
struct bnxt *bp; /* back ptr to the controlling dev */
|
||||
};
|
||||
|
||||
static inline struct bnxt *bnxt_get_bp_from_dl(struct devlink *dl)
|
||||
{
|
||||
return ((struct bnxt_dl *)devlink_priv(dl))->bp;
|
||||
}
|
||||
|
||||
/* To clear devlink pointer from bp, pass NULL dl */
|
||||
static inline void bnxt_link_bp_to_dl(struct bnxt *bp, struct devlink *dl)
|
||||
{
|
||||
bp->dl = dl;
|
||||
|
||||
/* add a back pointer in dl to bp */
|
||||
if (dl) {
|
||||
struct bnxt_dl *bp_dl = devlink_priv(dl);
|
||||
|
||||
bp_dl->bp = bp;
|
||||
}
|
||||
}
|
||||
|
||||
int bnxt_dl_register(struct bnxt *bp);
|
||||
void bnxt_dl_unregister(struct bnxt *bp);
|
||||
void bnxt_vf_reps_destroy(struct bnxt *bp);
|
||||
void bnxt_vf_reps_close(struct bnxt *bp);
|
||||
void bnxt_vf_reps_open(struct bnxt *bp);
|
||||
|
|
@ -53,14 +28,18 @@ static inline u16 bnxt_vf_rep_get_fid(struct net_device *dev)
|
|||
return bp->pf.vf[vf_rep->vf_idx].fw_fid;
|
||||
}
|
||||
|
||||
bool bnxt_dev_is_vf_rep(struct net_device *dev);
|
||||
int bnxt_dl_eswitch_mode_get(struct devlink *devlink, u16 *mode);
|
||||
#ifdef HAVE_ESWITCH_MODE_SET_EXTACK
|
||||
int bnxt_dl_eswitch_mode_set(struct devlink *devlink, u16 mode,
|
||||
struct netlink_ext_ack *extack);
|
||||
#else
|
||||
int bnxt_dl_eswitch_mode_set(struct devlink *devlink, u16 mode);
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
static inline int bnxt_dl_register(struct bnxt *bp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void bnxt_dl_unregister(struct bnxt *bp)
|
||||
static inline void bnxt_vf_reps_destroy(struct bnxt *bp)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -85,5 +64,10 @@ static inline u16 bnxt_vf_rep_get_fid(struct net_device *dev)
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_BNXT_SRIOV */
|
||||
|
||||
static inline bool bnxt_dev_is_vf_rep(struct net_device *dev)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif /* CONFIG_VF_REPS */
|
||||
#endif /* BNXT_VFR_H */
|
||||
|
|
|
|||
|
|
@ -12,15 +12,24 @@
|
|||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#ifdef HAVE_NDO_XDP
|
||||
#include <linux/bpf.h>
|
||||
#ifdef HAVE_BPF_TRACE
|
||||
#include <linux/bpf_trace.h>
|
||||
#endif
|
||||
#include <linux/filter.h>
|
||||
#endif
|
||||
#include "bnxt_compat.h"
|
||||
#include "bnxt_hsi.h"
|
||||
#include "bnxt.h"
|
||||
#include "bnxt_xdp.h"
|
||||
#ifdef CONFIG_PAGE_POOL
|
||||
#include <net/page_pool.h>
|
||||
#endif
|
||||
|
||||
void bnxt_xmit_xdp(struct bnxt *bp, struct bnxt_tx_ring_info *txr,
|
||||
dma_addr_t mapping, u32 len, u16 rx_prod)
|
||||
struct bnxt_sw_tx_bd *bnxt_xmit_bd(struct bnxt *bp,
|
||||
struct bnxt_tx_ring_info *txr,
|
||||
dma_addr_t mapping, u32 len)
|
||||
{
|
||||
struct bnxt_sw_tx_bd *tx_buf;
|
||||
struct tx_bd *txbd;
|
||||
|
|
@ -28,8 +37,7 @@ void bnxt_xmit_xdp(struct bnxt *bp, struct bnxt_tx_ring_info *txr,
|
|||
u16 prod;
|
||||
|
||||
prod = txr->tx_prod;
|
||||
tx_buf = &txr->tx_buf_ring[prod];
|
||||
tx_buf->rx_prod = rx_prod;
|
||||
tx_buf = &txr->tx_buf_ring[RING_TX(prod)];
|
||||
|
||||
txbd = &txr->tx_desc_ring[TX_RING(prod)][TX_IDX(prod)];
|
||||
flags = (len << TX_BD_LEN_SHIFT) | (1 << TX_BD_FLAGS_BD_CNT_SHIFT) |
|
||||
|
|
@ -40,30 +48,72 @@ void bnxt_xmit_xdp(struct bnxt *bp, struct bnxt_tx_ring_info *txr,
|
|||
|
||||
prod = NEXT_TX(prod);
|
||||
txr->tx_prod = prod;
|
||||
return tx_buf;
|
||||
}
|
||||
|
||||
#ifdef HAVE_NDO_XDP
|
||||
static void __bnxt_xmit_xdp(struct bnxt *bp, struct bnxt_tx_ring_info *txr,
|
||||
dma_addr_t mapping, u32 len, u16 rx_prod)
|
||||
{
|
||||
struct bnxt_sw_tx_bd *tx_buf;
|
||||
|
||||
tx_buf = bnxt_xmit_bd(bp, txr, mapping, len);
|
||||
tx_buf->rx_prod = rx_prod;
|
||||
tx_buf->action = XDP_TX;
|
||||
}
|
||||
|
||||
#ifdef HAVE_XDP_FRAME
|
||||
static void __bnxt_xmit_xdp_redirect(struct bnxt *bp,
|
||||
struct bnxt_tx_ring_info *txr,
|
||||
dma_addr_t mapping, u32 len,
|
||||
struct xdp_frame *xdpf)
|
||||
{
|
||||
struct bnxt_sw_tx_bd *tx_buf;
|
||||
|
||||
tx_buf = bnxt_xmit_bd(bp, txr, mapping, len);
|
||||
tx_buf->action = XDP_REDIRECT;
|
||||
tx_buf->xdpf = xdpf;
|
||||
dma_unmap_addr_set(tx_buf, mapping, mapping);
|
||||
dma_unmap_len_set(tx_buf, len, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
|
||||
{
|
||||
struct bnxt_tx_ring_info *txr = bnapi->tx_ring;
|
||||
struct bnxt_rx_ring_info *rxr = bnapi->rx_ring;
|
||||
bool rx_doorbell_needed = false;
|
||||
struct bnxt_sw_tx_bd *tx_buf;
|
||||
u16 tx_cons = txr->tx_cons;
|
||||
u16 last_tx_cons = tx_cons;
|
||||
u16 rx_prod;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nr_pkts; i++) {
|
||||
last_tx_cons = tx_cons;
|
||||
tx_buf = &txr->tx_buf_ring[RING_TX(tx_cons)];
|
||||
|
||||
if (tx_buf->action == XDP_REDIRECT) {
|
||||
struct pci_dev *pdev = bp->pdev;
|
||||
|
||||
dma_unmap_single(&pdev->dev,
|
||||
dma_unmap_addr(tx_buf, mapping),
|
||||
dma_unmap_len(tx_buf, len),
|
||||
PCI_DMA_TODEVICE);
|
||||
#ifdef HAVE_XDP_FRAME
|
||||
xdp_return_frame(tx_buf->xdpf);
|
||||
#endif
|
||||
tx_buf->action = 0;
|
||||
tx_buf->xdpf = NULL;
|
||||
} else if (tx_buf->action == XDP_TX) {
|
||||
rx_doorbell_needed = true;
|
||||
last_tx_cons = tx_cons;
|
||||
}
|
||||
tx_cons = NEXT_TX(tx_cons);
|
||||
}
|
||||
txr->tx_cons = tx_cons;
|
||||
if (bnxt_tx_avail(bp, txr) == bp->tx_ring_size) {
|
||||
rx_prod = rxr->rx_prod;
|
||||
} else {
|
||||
tx_buf = &txr->tx_buf_ring[last_tx_cons];
|
||||
rx_prod = tx_buf->rx_prod;
|
||||
if (rx_doorbell_needed) {
|
||||
tx_buf = &txr->tx_buf_ring[RING_TX(last_tx_cons)];
|
||||
bnxt_db_write(bp, &rxr->rx_db, tx_buf->rx_prod);
|
||||
}
|
||||
bnxt_db_write(bp, rxr->rx_doorbell, DB_KEY_RX | rx_prod);
|
||||
}
|
||||
|
||||
/* returns the following:
|
||||
|
|
@ -88,18 +138,24 @@ bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons,
|
|||
return false;
|
||||
|
||||
pdev = bp->pdev;
|
||||
txr = rxr->bnapi->tx_ring;
|
||||
rx_buf = &rxr->rx_buf_ring[cons];
|
||||
offset = bp->rx_offset;
|
||||
|
||||
xdp.data_hard_start = *data_ptr - offset;
|
||||
xdp.data = *data_ptr;
|
||||
xdp.data_end = *data_ptr + *len;
|
||||
orig_data = xdp.data;
|
||||
mapping = rx_buf->mapping - bp->rx_dma_offset;
|
||||
|
||||
dma_sync_single_for_cpu(&pdev->dev, mapping + offset, *len, bp->rx_dir);
|
||||
|
||||
txr = rxr->bnapi->tx_ring;
|
||||
#if XDP_PACKET_HEADROOM
|
||||
xdp.data_hard_start = *data_ptr - offset;
|
||||
#endif
|
||||
xdp.data = *data_ptr;
|
||||
xdp_set_data_meta_invalid(&xdp);
|
||||
xdp.data_end = *data_ptr + *len;
|
||||
#ifdef HAVE_XDP_RXQ_INFO
|
||||
xdp.rxq = &rxr->xdp_rxq;
|
||||
#endif
|
||||
orig_data = xdp.data;
|
||||
|
||||
rcu_read_lock();
|
||||
act = bpf_prog_run_xdp(xdp_prog, &xdp);
|
||||
rcu_read_unlock();
|
||||
|
|
@ -111,10 +167,14 @@ bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons,
|
|||
if (tx_avail != bp->tx_ring_size)
|
||||
*event &= ~BNXT_RX_EVENT;
|
||||
|
||||
#if XDP_PACKET_HEADROOM
|
||||
*len = xdp.data_end - xdp.data;
|
||||
#endif
|
||||
if (orig_data != xdp.data) {
|
||||
#if XDP_PACKET_HEADROOM
|
||||
offset = xdp.data - xdp.data_hard_start;
|
||||
*data_ptr = xdp.data_hard_start + offset;
|
||||
*len = xdp.data_end - xdp.data;
|
||||
#endif
|
||||
}
|
||||
switch (act) {
|
||||
case XDP_PASS:
|
||||
|
|
@ -130,10 +190,38 @@ bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons,
|
|||
*event = BNXT_TX_EVENT;
|
||||
dma_sync_single_for_device(&pdev->dev, mapping + offset, *len,
|
||||
bp->rx_dir);
|
||||
bnxt_xmit_xdp(bp, txr, mapping + offset, *len,
|
||||
__bnxt_xmit_xdp(bp, txr, mapping + offset, *len,
|
||||
NEXT_RX(rxr->rx_prod));
|
||||
bnxt_reuse_rx_data(rxr, cons, page);
|
||||
return true;
|
||||
case XDP_REDIRECT:
|
||||
/* if we are calling this here then we know that the
|
||||
* redirect is coming from a frame received by the
|
||||
* bnxt_en driver.
|
||||
*/
|
||||
dma_unmap_page_attrs(&pdev->dev, mapping,
|
||||
PAGE_SIZE, bp->rx_dir,
|
||||
DMA_ATTR_WEAK_ORDERING);
|
||||
|
||||
/* if we are unable to allocate a new buffer, abort and reuse */
|
||||
if (bnxt_alloc_rx_data(bp, rxr, rxr->rx_prod, GFP_ATOMIC)) {
|
||||
trace_xdp_exception(bp->dev, xdp_prog, act);
|
||||
bnxt_reuse_rx_data(rxr, cons, page);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (xdp_do_redirect(bp->dev, &xdp, xdp_prog)) {
|
||||
trace_xdp_exception(bp->dev, xdp_prog, act);
|
||||
#ifndef CONFIG_PAGE_POOL
|
||||
__free_page(page);
|
||||
#else
|
||||
page_pool_recycle_direct(rxr->page_pool, page);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
*event |= BNXT_REDIRECT_EVENT;
|
||||
break;
|
||||
default:
|
||||
bpf_warn_invalid_xdp_action(act);
|
||||
/* Fall thru */
|
||||
|
|
@ -147,6 +235,57 @@ bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons,
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifdef HAVE_XDP_FRAME
|
||||
int bnxt_xdp_xmit(struct net_device *dev, int num_frames,
|
||||
struct xdp_frame **frames, u32 flags)
|
||||
{
|
||||
struct bnxt *bp = netdev_priv(dev);
|
||||
struct bpf_prog *xdp_prog = READ_ONCE(bp->xdp_prog);
|
||||
struct pci_dev *pdev = bp->pdev;
|
||||
struct bnxt_tx_ring_info *txr;
|
||||
dma_addr_t mapping;
|
||||
int drops = 0;
|
||||
int ring;
|
||||
int i;
|
||||
|
||||
if (!test_bit(BNXT_STATE_OPEN, &bp->state) ||
|
||||
!bp->tx_nr_rings_xdp ||
|
||||
!xdp_prog)
|
||||
return -EINVAL;
|
||||
|
||||
ring = smp_processor_id() % bp->tx_nr_rings_xdp;
|
||||
txr = &bp->tx_ring[ring];
|
||||
|
||||
for (i = 0; i < num_frames; i++) {
|
||||
struct xdp_frame *xdp = frames[i];
|
||||
|
||||
if (!txr || !bnxt_tx_avail(bp, txr) ||
|
||||
!(bp->bnapi[ring]->flags & BNXT_NAPI_FLAG_XDP)) {
|
||||
xdp_return_frame_rx_napi(xdp);
|
||||
drops++;
|
||||
continue;
|
||||
}
|
||||
|
||||
mapping = dma_map_single(&pdev->dev, xdp->data, xdp->len,
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
if (dma_mapping_error(&pdev->dev, mapping)) {
|
||||
xdp_return_frame_rx_napi(xdp);
|
||||
drops++;
|
||||
continue;
|
||||
}
|
||||
__bnxt_xmit_xdp_redirect(bp, txr, mapping, xdp->len, xdp);
|
||||
}
|
||||
|
||||
if (flags & XDP_XMIT_FLUSH) {
|
||||
/* Sync BD data before updating doorbell */
|
||||
wmb();
|
||||
bnxt_db_write(bp, &txr->tx_db, txr->tx_prod);
|
||||
}
|
||||
|
||||
return num_frames - drops;
|
||||
}
|
||||
#endif
|
||||
/* Under rtnl_lock */
|
||||
static int bnxt_xdp_set(struct bnxt *bp, struct bpf_prog *prog)
|
||||
{
|
||||
|
|
@ -197,7 +336,6 @@ static int bnxt_xdp_set(struct bnxt *bp, struct bpf_prog *prog)
|
|||
bp->tx_nr_rings_xdp = tx_xdp;
|
||||
bp->tx_nr_rings = bp->tx_nr_rings_per_tc * tc + tx_xdp;
|
||||
bp->cp_nr_rings = max_t(int, bp->tx_nr_rings, bp->rx_nr_rings);
|
||||
bp->num_stat_ctxs = bp->cp_nr_rings;
|
||||
bnxt_set_tpa_flags(bp);
|
||||
bnxt_set_ring_params(bp);
|
||||
|
||||
|
|
@ -207,7 +345,7 @@ static int bnxt_xdp_set(struct bnxt *bp, struct bpf_prog *prog)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int bnxt_xdp(struct net_device *dev, struct netdev_xdp *xdp)
|
||||
int bnxt_xdp(struct net_device *dev, struct netdev_bpf *xdp)
|
||||
{
|
||||
struct bnxt *bp = netdev_priv(dev);
|
||||
int rc;
|
||||
|
|
@ -217,8 +355,12 @@ int bnxt_xdp(struct net_device *dev, struct netdev_xdp *xdp)
|
|||
rc = bnxt_xdp_set(bp, xdp->prog);
|
||||
break;
|
||||
case XDP_QUERY_PROG:
|
||||
#ifdef HAVE_PROG_ATTACHED
|
||||
xdp->prog_attached = !!bp->xdp_prog;
|
||||
#endif
|
||||
#ifdef HAVE_IFLA_XDP_PROG_ID
|
||||
xdp->prog_id = bp->xdp_prog ? bp->xdp_prog->aux->id : 0;
|
||||
#endif
|
||||
rc = 0;
|
||||
break;
|
||||
default:
|
||||
|
|
@ -227,3 +369,14 @@ int bnxt_xdp(struct net_device *dev, struct netdev_xdp *xdp)
|
|||
}
|
||||
return rc;
|
||||
}
|
||||
#else
|
||||
void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
|
||||
{
|
||||
}
|
||||
|
||||
bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons,
|
||||
void *page, u8 **data_ptr, unsigned int *len, u8 *event)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -10,12 +10,22 @@
|
|||
#ifndef BNXT_XDP_H
|
||||
#define BNXT_XDP_H
|
||||
|
||||
void bnxt_xmit_xdp(struct bnxt *bp, struct bnxt_tx_ring_info *txr,
|
||||
dma_addr_t mapping, u32 len, u16 rx_prod);
|
||||
struct bnxt_sw_tx_bd *bnxt_xmit_bd(struct bnxt *bp,
|
||||
struct bnxt_tx_ring_info *txr,
|
||||
dma_addr_t mapping, u32 len);
|
||||
void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts);
|
||||
#ifdef HAVE_NDO_XDP
|
||||
bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons,
|
||||
struct page *page, u8 **data_ptr, unsigned int *len,
|
||||
u8 *event);
|
||||
int bnxt_xdp(struct net_device *dev, struct netdev_xdp *xdp);
|
||||
|
||||
#else
|
||||
bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons,
|
||||
void *page, u8 **data_ptr, unsigned int *len,
|
||||
u8 *event);
|
||||
#endif
|
||||
int bnxt_xdp(struct net_device *dev, struct netdev_bpf *xdp);
|
||||
#ifdef HAVE_XDP_FRAME
|
||||
int bnxt_xdp_xmit(struct net_device *dev, int num_frames,
|
||||
struct xdp_frame **frames, u32 flags);
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue