]> review.fuel-infra Code Review - packages/trusty/i40e-dkms.git/commitdiff
Version 2.1.26 89/36389/1
authorIvan Suzdal <isuzdal@mirantis.com>
Fri, 1 Sep 2017 14:52:34 +0000 (17:52 +0300)
committerIvan Suzdal <isuzdal@mirantis.com>
Fri, 1 Sep 2017 14:52:43 +0000 (17:52 +0300)
Change-Id: Icf8bba39fdb3fc335e946b1995406c85a56ae56d
Closes-Bug: #1712793

55 files changed:
debian/changelog
i40e-dkms/i40e-1.6.42/COPYING [deleted file]
i40e-dkms/i40e-1.6.42/SUMS [deleted file]
i40e-dkms/i40e-1.6.42/src/i40e_fcoe.c [deleted file]
i40e-dkms/i40e-1.6.42/src/i40e_fcoe.h [deleted file]
i40e-dkms/i40e-1.6.42/src/i40e_virtchnl.h [deleted file]
i40e-dkms/i40e-2.1.26/COPYING [new file with mode: 0644]
i40e-dkms/i40e-2.1.26/README [moved from i40e-dkms/i40e-1.6.42/README with 80% similarity]
i40e-dkms/i40e-2.1.26/SUMS [new file with mode: 0644]
i40e-dkms/i40e-2.1.26/i40e.7 [moved from i40e-dkms/i40e-1.6.42/i40e.7 with 91% similarity]
i40e-dkms/i40e-2.1.26/i40e.spec [moved from i40e-dkms/i40e-1.6.42/i40e.spec with 99% similarity]
i40e-dkms/i40e-2.1.26/pci.updates [moved from i40e-dkms/i40e-1.6.42/pci.updates with 93% similarity]
i40e-dkms/i40e-2.1.26/scripts/dump_tables [moved from i40e-dkms/i40e-1.6.42/scripts/dump_tables with 100% similarity]
i40e-dkms/i40e-2.1.26/scripts/set_irq_affinity [moved from i40e-dkms/i40e-1.6.42/scripts/set_irq_affinity with 100% similarity]
i40e-dkms/i40e-2.1.26/scripts/virt_perf_default [moved from i40e-dkms/i40e-1.6.42/scripts/virt_perf_default with 100% similarity]
i40e-dkms/i40e-2.1.26/src/Makefile [moved from i40e-dkms/i40e-1.6.42/src/Makefile with 98% similarity]
i40e-dkms/i40e-2.1.26/src/Module.supported [moved from i40e-dkms/i40e-1.6.42/src/Module.supported with 100% similarity]
i40e-dkms/i40e-2.1.26/src/common.mk [moved from i40e-dkms/i40e-1.6.42/src/common.mk with 98% similarity]
i40e-dkms/i40e-2.1.26/src/i40e.h [moved from i40e-dkms/i40e-1.6.42/src/i40e.h with 77% similarity]
i40e-dkms/i40e-2.1.26/src/i40e_adminq.c [moved from i40e-dkms/i40e-1.6.42/src/i40e_adminq.c with 98% similarity]
i40e-dkms/i40e-2.1.26/src/i40e_adminq.h [moved from i40e-dkms/i40e-1.6.42/src/i40e_adminq.h with 99% similarity]
i40e-dkms/i40e-2.1.26/src/i40e_adminq_cmd.h [moved from i40e-dkms/i40e-1.6.42/src/i40e_adminq_cmd.h with 92% similarity]
i40e-dkms/i40e-2.1.26/src/i40e_alloc.h [moved from i40e-dkms/i40e-1.6.42/src/i40e_alloc.h with 100% similarity]
i40e-dkms/i40e-2.1.26/src/i40e_client.c [new file with mode: 0644]
i40e-dkms/i40e-2.1.26/src/i40e_client.h [new file with mode: 0644]
i40e-dkms/i40e-2.1.26/src/i40e_common.c [moved from i40e-dkms/i40e-1.6.42/src/i40e_common.c with 87% similarity]
i40e-dkms/i40e-2.1.26/src/i40e_dcb.c [moved from i40e-dkms/i40e-1.6.42/src/i40e_dcb.c with 99% similarity]
i40e-dkms/i40e-2.1.26/src/i40e_dcb.h [moved from i40e-dkms/i40e-1.6.42/src/i40e_dcb.h with 100% similarity]
i40e-dkms/i40e-2.1.26/src/i40e_dcb_nl.c [moved from i40e-dkms/i40e-1.6.42/src/i40e_dcb_nl.c with 100% similarity]
i40e-dkms/i40e-2.1.26/src/i40e_debugfs.c [moved from i40e-dkms/i40e-1.6.42/src/i40e_debugfs.c with 97% similarity]
i40e-dkms/i40e-2.1.26/src/i40e_devids.h [moved from i40e-dkms/i40e-1.6.42/src/i40e_devids.h with 100% similarity]
i40e-dkms/i40e-2.1.26/src/i40e_diag.c [moved from i40e-dkms/i40e-1.6.42/src/i40e_diag.c with 100% similarity]
i40e-dkms/i40e-2.1.26/src/i40e_diag.h [moved from i40e-dkms/i40e-1.6.42/src/i40e_diag.h with 100% similarity]
i40e-dkms/i40e-2.1.26/src/i40e_ethtool.c [moved from i40e-dkms/i40e-1.6.42/src/i40e_ethtool.c with 60% similarity]
i40e-dkms/i40e-2.1.26/src/i40e_helper.h [moved from i40e-dkms/i40e-1.6.42/src/i40e_helper.h with 100% similarity]
i40e-dkms/i40e-2.1.26/src/i40e_hmc.c [moved from i40e-dkms/i40e-1.6.42/src/i40e_hmc.c with 100% similarity]
i40e-dkms/i40e-2.1.26/src/i40e_hmc.h [moved from i40e-dkms/i40e-1.6.42/src/i40e_hmc.h with 100% similarity]
i40e-dkms/i40e-2.1.26/src/i40e_lan_hmc.c [moved from i40e-dkms/i40e-1.6.42/src/i40e_lan_hmc.c with 100% similarity]
i40e-dkms/i40e-2.1.26/src/i40e_lan_hmc.h [moved from i40e-dkms/i40e-1.6.42/src/i40e_lan_hmc.h with 100% similarity]
i40e-dkms/i40e-2.1.26/src/i40e_main.c [moved from i40e-dkms/i40e-1.6.42/src/i40e_main.c with 85% similarity]
i40e-dkms/i40e-2.1.26/src/i40e_nvm.c [moved from i40e-dkms/i40e-1.6.42/src/i40e_nvm.c with 97% similarity]
i40e-dkms/i40e-2.1.26/src/i40e_osdep.h [moved from i40e-dkms/i40e-1.6.42/src/i40e_osdep.h with 95% similarity]
i40e-dkms/i40e-2.1.26/src/i40e_prototype.h [moved from i40e-dkms/i40e-1.6.42/src/i40e_prototype.h with 91% similarity]
i40e-dkms/i40e-2.1.26/src/i40e_ptp.c [moved from i40e-dkms/i40e-1.6.42/src/i40e_ptp.c with 87% similarity]
i40e-dkms/i40e-2.1.26/src/i40e_register.h [moved from i40e-dkms/i40e-1.6.42/src/i40e_register.h with 99% similarity]
i40e-dkms/i40e-2.1.26/src/i40e_status.h [moved from i40e-dkms/i40e-1.6.42/src/i40e_status.h with 100% similarity]
i40e-dkms/i40e-2.1.26/src/i40e_trace.h [new file with mode: 0644]
i40e-dkms/i40e-2.1.26/src/i40e_txrx.c [moved from i40e-dkms/i40e-1.6.42/src/i40e_txrx.c with 78% similarity]
i40e-dkms/i40e-2.1.26/src/i40e_txrx.h [moved from i40e-dkms/i40e-1.6.42/src/i40e_txrx.h with 82% similarity]
i40e-dkms/i40e-2.1.26/src/i40e_type.h [moved from i40e-dkms/i40e-1.6.42/src/i40e_type.h with 86% similarity]
i40e-dkms/i40e-2.1.26/src/i40e_virtchnl_pf.c [moved from i40e-dkms/i40e-1.6.42/src/i40e_virtchnl_pf.c with 70% similarity]
i40e-dkms/i40e-2.1.26/src/i40e_virtchnl_pf.h [moved from i40e-dkms/i40e-1.6.42/src/i40e_virtchnl_pf.h with 87% similarity]
i40e-dkms/i40e-2.1.26/src/kcompat.c [moved from i40e-dkms/i40e-1.6.42/src/kcompat.c with 95% similarity]
i40e-dkms/i40e-2.1.26/src/kcompat.h [moved from i40e-dkms/i40e-1.6.42/src/kcompat.h with 95% similarity]
i40e-dkms/i40e-2.1.26/src/virtchnl.h [new file with mode: 0644]

index be8b0dbb505be9d67d849d39faf6d10b8279235b..45ecd65dc6c16767884fc1c8feb5a466f33a597f 100644 (file)
@@ -1,3 +1,9 @@
+i40e-dkms (2.1.26-1~u14.04+mos1) mos; urgency=low
+
+  * Update to version 2.1.26 (LP: 1712793)
+
+ -- Ivan Suzdal <mos-linux@mirantis.com>  Fri, 01 Sep 2017 17:51:13 +0300
+
 i40e-dkms (1.6.42-1~u14.04+mos1) mos; urgency=low
 
   * Update to version 1.6.42
diff --git a/i40e-dkms/i40e-1.6.42/COPYING b/i40e-dkms/i40e-1.6.42/COPYING
deleted file mode 100644 (file)
index e2fed1b..0000000
+++ /dev/null
@@ -1,344 +0,0 @@
-
-"This software program is licensed subject to the GNU General Public License 
-(GPL). Version 2, June 1991, available at 
-<http://www.gnu.org/licenses/gpl-2.0.html>"
-
-                    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.
diff --git a/i40e-dkms/i40e-1.6.42/SUMS b/i40e-dkms/i40e-1.6.42/SUMS
deleted file mode 100644 (file)
index 3d295fc..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-32879     3 i40e-1.6.42/i40e.7
-55011    50 i40e-1.6.42/README
-45713     7 i40e-1.6.42/pci.updates
-52651    11 i40e-1.6.42/i40e.spec
-02733    18 i40e-1.6.42/COPYING
-47165   364 i40e-1.6.42/src/i40e_register.h
-56893    14 i40e-1.6.42/src/i40e_virtchnl.h
-36073     9 i40e-1.6.42/src/i40e_dcb_nl.c
-28578    76 i40e-1.6.42/src/i40e_adminq_cmd.h
-33761    45 i40e-1.6.42/src/i40e_nvm.c
-52885    51 i40e-1.6.42/src/i40e_type.h
-56103    20 i40e-1.6.42/src/i40e_prototype.h
-25766    55 i40e-1.6.42/src/kcompat.c
-58605     4 i40e-1.6.42/src/i40e_status.h
-07031   168 i40e-1.6.42/src/i40e_common.c
-25757     6 i40e-1.6.42/src/i40e_lan_hmc.h
-25014     2 i40e-1.6.42/src/i40e_diag.h
-27793     4 i40e-1.6.42/src/i40e_fcoe.h
-25701     4 i40e-1.6.42/src/i40e_helper.h
-56270     8 i40e-1.6.42/src/i40e_hmc.h
-65130   139 i40e-1.6.42/src/i40e_ethtool.c
-05858    30 i40e-1.6.42/src/i40e_adminq.c
-24070     2 i40e-1.6.42/src/i40e_devids.h
-13309     5 i40e-1.6.42/src/i40e_diag.c
-32391    36 i40e-1.6.42/src/i40e.h
-16694    17 i40e-1.6.42/src/i40e_txrx.h
-23499    25 i40e-1.6.42/src/i40e_ptp.c
-60199    35 i40e-1.6.42/src/i40e_lan_hmc.c
-15948    27 i40e-1.6.42/src/i40e_dcb.c
-29059   161 i40e-1.6.42/src/kcompat.h
-42183   346 i40e-1.6.42/src/i40e_main.c
-51264     6 i40e-1.6.42/src/Makefile
-41749    48 i40e-1.6.42/src/i40e_fcoe.c
-51731     5 i40e-1.6.42/src/i40e_osdep.h
-03889     3 i40e-1.6.42/src/i40e_alloc.h
-46374    81 i40e-1.6.42/src/i40e_debugfs.c
-44588     1 i40e-1.6.42/src/Module.supported
-39178     6 i40e-1.6.42/src/i40e_virtchnl_pf.h
-19614     5 i40e-1.6.42/src/i40e_adminq.h
-10789    12 i40e-1.6.42/src/common.mk
-06090    80 i40e-1.6.42/src/i40e_virtchnl_pf.c
-49924    92 i40e-1.6.42/src/i40e_txrx.c
-12466     6 i40e-1.6.42/src/i40e_dcb.h
-03386    11 i40e-1.6.42/src/i40e_hmc.c
-33977     7 i40e-1.6.42/scripts/set_irq_affinity
-20875     2 i40e-1.6.42/scripts/dump_tables
-49876     5 i40e-1.6.42/scripts/virt_perf_default
diff --git a/i40e-dkms/i40e-1.6.42/src/i40e_fcoe.c b/i40e-dkms/i40e-1.6.42/src/i40e_fcoe.c
deleted file mode 100644 (file)
index 713210c..0000000
+++ /dev/null
@@ -1,1677 +0,0 @@
-/*******************************************************************************
- *
- * Intel(R) 40-10 Gigabit Ethernet Connection Network Driver
- * Copyright(c) 2013 - 2017 Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- ******************************************************************************/
-
-#ifdef WITH_FCOE
-
-#include <linux/if_ether.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_device.h>
-#include <scsi/fc/fc_fs.h>
-#include <scsi/fc/fc_fip.h>
-#include <scsi/fc/fc_fcoe.h>
-#include <scsi/libfc.h>
-#include <scsi/libfcoe.h>
-
-#include "i40e.h"
-#include "i40e_fcoe.h"
-
-/**
- * i40e_rx_is_fip - returns true if the rx packet type is FIP
- * @ptype: the packet type field from rx descriptor write-back
- **/
-static inline bool i40e_rx_is_fip(u16 ptype)
-{
-       return ptype == I40E_RX_PTYPE_L2_FIP_PAY2;
-}
-
-/**
- * i40e_fcoe_sof_is_class2 - returns true if this is a FC Class 2 SOF
- * @sof: the FCoE start of frame delimiter
- **/
-static inline bool i40e_fcoe_sof_is_class2(u8 sof)
-{
-       return (sof == FC_SOF_I2) || (sof == FC_SOF_N2);
-}
-
-/**
- * i40e_fcoe_sof_is_class3 - returns true if this is a FC Class 3 SOF
- * @sof: the FCoE start of frame delimiter
- **/
-static inline bool i40e_fcoe_sof_is_class3(u8 sof)
-{
-       return (sof == FC_SOF_I3) || (sof == FC_SOF_N3);
-}
-
-/**
- * i40e_fcoe_sof_is_supported - returns true if the FC SOF is supported by HW
- * @sof: the input SOF value from the frame
- **/
-static inline bool i40e_fcoe_sof_is_supported(u8 sof)
-{
-       return i40e_fcoe_sof_is_class2(sof) ||
-              i40e_fcoe_sof_is_class3(sof);
-}
-
-/**
- * i40e_fcoe_fc_sof - pull the SOF from FCoE header in the frame
- * @skb: the frame whose EOF is to be pulled from
- **/
-static inline int i40e_fcoe_fc_sof(struct sk_buff *skb, u8 *sof)
-{
-       *sof = ((struct fcoe_hdr *)skb_network_header(skb))->fcoe_sof;
-
-       if (!i40e_fcoe_sof_is_supported(*sof))
-               return -EINVAL;
-       return 0;
-}
-
-/**
- * i40e_fcoe_eof_is_supported - returns true if the EOF is supported by HW
- * @eof:     the input EOF value from the frame
- **/
-static inline bool i40e_fcoe_eof_is_supported(u8 eof)
-{
-       return (eof == FC_EOF_N) || (eof == FC_EOF_T) ||
-              (eof == FC_EOF_NI) || (eof == FC_EOF_A);
-}
-
-/**
- * i40e_fcoe_fc_eof - pull EOF from FCoE trailer in the frame
- * @skb: the frame whose EOF is to be pulled from
- **/
-static inline int i40e_fcoe_fc_eof(struct sk_buff *skb, u8 *eof)
-{
-       /* the first byte of the last dword is EOF */
-       skb_copy_bits(skb, skb->len - 4, eof, 1);
-
-       if (!i40e_fcoe_eof_is_supported(*eof))
-               return -EINVAL;
-       return 0;
-}
-
-/**
- * i40e_fcoe_ctxt_eof - convert input FC EOF for descriptor programming
- * @eof: the input eof value from the frame
- *
- * The FC EOF is converted to the value understood by HW for descriptor
- * programming. Never call this w/o calling i40e_fcoe_eof_is_supported()
- * first and that already checks for all supported valid eof values.
- **/
-static inline u32 i40e_fcoe_ctxt_eof(u8 eof)
-{
-       switch (eof) {
-       case FC_EOF_N:
-               return I40E_TX_DESC_CMD_L4T_EOFT_EOF_N;
-       case FC_EOF_T:
-               return I40E_TX_DESC_CMD_L4T_EOFT_EOF_T;
-       case FC_EOF_NI:
-               return I40E_TX_DESC_CMD_L4T_EOFT_EOF_NI;
-       case FC_EOF_A:
-               return I40E_TX_DESC_CMD_L4T_EOFT_EOF_A;
-       default:
-               /* Supported valid eof shall be already checked by
-                * calling i40e_fcoe_eof_is_supported() first,
-                * therefore this default case shall never hit.
-                */
-               WARN_ON(1);
-               return -EINVAL;
-       }
-}
-
-/**
- * i40e_fcoe_xid_is_valid - returns true if the exchange id is valid
- * @xid: the exchange id
- **/
-static inline bool i40e_fcoe_xid_is_valid(u16 xid)
-{
-       return (xid != FC_XID_UNKNOWN) && (xid < I40E_FCOE_DDP_MAX);
-}
-
-/**
- * i40e_fcoe_ddp_unmap - unmap the mapped sglist associated
- * @pf: pointer to PF
- * @ddp: sw DDP context
- *
- * Unmap the scatter-gather list associated with the given SW DDP context
- *
- * Returns: data length already ddp-ed in bytes
- *
- **/
-static inline void i40e_fcoe_ddp_unmap(struct i40e_pf *pf,
-                                      struct i40e_fcoe_ddp *ddp)
-{
-       if (test_and_set_bit(__I40E_FCOE_DDP_UNMAPPED, &ddp->flags))
-               return;
-
-       if (ddp->sgl) {
-               dma_unmap_sg(&pf->pdev->dev, ddp->sgl, ddp->sgc,
-                            DMA_FROM_DEVICE);
-               ddp->sgl = NULL;
-               ddp->sgc = 0;
-       }
-
-       if (ddp->pool) {
-               dma_pool_free(ddp->pool, ddp->udl, ddp->udp);
-               ddp->pool = NULL;
-       }
-}
-
-/**
- * i40e_fcoe_ddp_clear - clear the given SW DDP context
- * @ddp - SW DDP context
- **/
-static inline void i40e_fcoe_ddp_clear(struct i40e_fcoe_ddp *ddp)
-{
-       memset(ddp, 0, sizeof(struct i40e_fcoe_ddp));
-       ddp->xid = FC_XID_UNKNOWN;
-       ddp->flags = __I40E_FCOE_DDP_NONE;
-}
-
-/**
- * i40e_fcoe_progid_is_fcoe - check if the prog_id is for FCoE
- * @id: the prog id for the programming status Rx descriptor write-back
- **/
-static inline bool i40e_fcoe_progid_is_fcoe(u8 id)
-{
-       return (id == I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_PROG_STATUS) ||
-              (id == I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_INVL_STATUS);
-}
-
-/**
- * i40e_fcoe_fc_get_xid - get xid from the frame header
- * @fh: the fc frame header
- *
- * In case the incoming frame's exchange is originated from
- * the initiator, then received frame's exchange id is ANDed
- * with fc_cpu_mask bits to get the same cpu on which exchange
- * was originated, otherwise just use the current cpu.
- *
- * Returns ox_id if exchange originator, rx_id if responder
- **/
-static inline u16 i40e_fcoe_fc_get_xid(struct fc_frame_header *fh)
-{
-       u32 f_ctl = ntoh24(fh->fh_f_ctl);
-
-       return (f_ctl & FC_FC_EX_CTX) ?
-               be16_to_cpu(fh->fh_ox_id) :
-               be16_to_cpu(fh->fh_rx_id);
-}
-
-/**
- * i40e_fcoe_fc_frame_header - get fc frame header from skb
- * @skb: packet
- *
- * This checks if there is a VLAN header and returns the data
- * pointer to the start of the fc_frame_header.
- *
- * Returns pointer to the fc_frame_header
- **/
-static inline struct fc_frame_header *i40e_fcoe_fc_frame_header(
-       struct sk_buff *skb)
-{
-       void *fh = skb->data + sizeof(struct fcoe_hdr);
-
-       if (eth_hdr(skb)->h_proto == htons(ETH_P_8021Q))
-               fh += sizeof(struct vlan_hdr);
-
-       return (struct fc_frame_header *)fh;
-}
-
-/**
- * i40e_fcoe_ddp_put - release the DDP context for a given exchange id
- * @netdev: the corresponding net_device
- * @xid: the exchange id that corresponding DDP context will be released
- *
- * This is the implementation of net_device_ops.ndo_fcoe_ddp_done
- * and it is expected to be called by ULD, i.e., FCP layer of libfc
- * to release the corresponding ddp context when the I/O is done.
- *
- * Returns : data length already ddp-ed in bytes
- **/
-static int i40e_fcoe_ddp_put(struct net_device *netdev, u16 xid)
-{
-       struct i40e_netdev_priv *np = netdev_priv(netdev);
-       struct i40e_pf *pf = np->vsi->back;
-       struct i40e_fcoe *fcoe = &pf->fcoe;
-       int len = 0;
-       struct i40e_fcoe_ddp *ddp = &fcoe->ddp[xid];
-
-       if (!fcoe || !ddp)
-               goto out;
-
-       if (test_bit(__I40E_FCOE_DDP_DONE, &ddp->flags))
-               len = ddp->len;
-       i40e_fcoe_ddp_unmap(pf, ddp);
-out:
-       return len;
-}
-
-/**
- * i40e_fcoe_sw_init - sets up the HW for FCoE
- * @pf: pointer to PF
- **/
-void i40e_init_pf_fcoe(struct i40e_pf *pf)
-{
-       struct i40e_hw *hw = &pf->hw;
-       u32 val;
-
-       pf->flags &= ~I40E_FLAG_FCOE_ENABLED;
-       pf->num_fcoe_qps = 0;
-       pf->fcoe_hmc_cntx_num = 0;
-       pf->fcoe_hmc_filt_num = 0;
-
-       if (!pf->hw.func_caps.fcoe) {
-               dev_dbg(&pf->pdev->dev, "FCoE capability is disabled\n");
-               return;
-       }
-
-       if (!pf->hw.func_caps.dcb) {
-               dev_warn(&pf->pdev->dev,
-                        "Hardware is not DCB capable not enabling FCoE.\n");
-               return;
-       }
-
-       /* enable FCoE hash filter */
-       val = i40e_read_rx_ctl(hw, I40E_PFQF_HENA(1));
-       val |= BIT(I40E_FILTER_PCTYPE_FCOE_OX - 32);
-       val |= BIT(I40E_FILTER_PCTYPE_FCOE_RX - 32);
-       val &= I40E_PFQF_HENA_PTYPE_ENA_MASK;
-       i40e_write_rx_ctl(hw, I40E_PFQF_HENA(1), val);
-
-       /* enable flag */
-       pf->flags |= I40E_FLAG_FCOE_ENABLED;
-       pf->num_fcoe_qps = I40E_DEFAULT_FCOE;
-
-       /* Reserve 4K DDP contexts and 20K filter size for FCoE */
-       pf->fcoe_hmc_cntx_num = BIT(I40E_DMA_CNTX_SIZE_4K) *
-                               I40E_DMA_CNTX_BASE_SIZE;
-       pf->fcoe_hmc_filt_num = pf->fcoe_hmc_cntx_num +
-                               BIT(I40E_HASH_FILTER_SIZE_16K) *
-                               I40E_HASH_FILTER_BASE_SIZE;
-
-       /* FCoE object: max 16K filter buckets and 4K DMA contexts */
-       pf->filter_settings.fcoe_filt_num = I40E_HASH_FILTER_SIZE_16K;
-       pf->filter_settings.fcoe_cntx_num = I40E_DMA_CNTX_SIZE_4K;
-
-       /* Setup max frame with FCoE_MTU plus L2 overheads */
-       val = i40e_read_rx_ctl(hw, I40E_GLFCOE_RCTL);
-       val &= ~I40E_GLFCOE_RCTL_MAX_SIZE_MASK;
-       val |= ((FCOE_MTU + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN)
-                << I40E_GLFCOE_RCTL_MAX_SIZE_SHIFT);
-       i40e_write_rx_ctl(hw, I40E_GLFCOE_RCTL, val);
-
-       dev_info(&pf->pdev->dev, "FCoE is supported.\n");
-}
-
-#ifdef CONFIG_DCB
-/**
- * i40e_get_fcoe_tc_map - Return TC map for FCoE APP
- * @pf: pointer to PF
- *
- **/
-u8 i40e_get_fcoe_tc_map(struct i40e_pf *pf)
-{
-       struct i40e_dcb_app_priority_table app;
-       struct i40e_hw *hw = &pf->hw;
-       u8 enabled_tc = 0;
-       u8 tc, i;
-       /* Get the FCoE APP TLV */
-       struct i40e_dcbx_config *dcbcfg = &hw->local_dcbx_config;
-
-       for (i = 0; i < dcbcfg->numapps; i++) {
-               app = dcbcfg->app[i];
-               if (app.selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE &&
-                   app.protocolid == ETH_P_FCOE) {
-                       tc = dcbcfg->etscfg.prioritytable[app.priority];
-                       enabled_tc |= BIT(tc);
-                       break;
-               }
-       }
-
-       /* TC0 if there is no TC defined for FCoE APP TLV */
-       enabled_tc = enabled_tc ? enabled_tc : 0x1;
-
-       return enabled_tc;
-}
-
-#endif
-/**
- * i40e_fcoe_vsi_init - prepares the VSI context for creating a FCoE VSI
- * @vsi: pointer to the associated VSI struct
- * @ctxt: pointer to the associated VSI context to be passed to HW
- *
- * Returns 0 on success or < 0 on error
- **/
-int i40e_fcoe_vsi_init(struct i40e_vsi *vsi, struct i40e_vsi_context *ctxt)
-{
-       struct i40e_aqc_vsi_properties_data *info = &ctxt->info;
-       struct i40e_pf *pf = vsi->back;
-       struct i40e_hw *hw = &pf->hw;
-       u8 enabled_tc = 0x1; /* Default as TC0 */
-
-       if (!(pf->flags & I40E_FLAG_FCOE_ENABLED)) {
-               dev_err(&pf->pdev->dev,
-                       "FCoE is not enabled for this device\n");
-               return -EPERM;
-       }
-
-       /* initialize the hardware for FCoE */
-       ctxt->pf_num = hw->pf_id;
-       ctxt->vf_num = 0;
-       ctxt->uplink_seid = vsi->uplink_seid;
-       ctxt->connection_type = I40E_AQ_VSI_CONN_TYPE_NORMAL;
-       ctxt->flags = I40E_AQ_VSI_TYPE_PF;
-
-       /* FCoE VSI would need the following sections */
-       info->valid_sections |= cpu_to_le16(I40E_AQ_VSI_PROP_QUEUE_OPT_VALID);
-
-       /* FCoE VSI does not need these sections */
-       info->valid_sections &= cpu_to_le16(~(I40E_AQ_VSI_PROP_SECURITY_VALID |
-                                           I40E_AQ_VSI_PROP_VLAN_VALID |
-                                           I40E_AQ_VSI_PROP_CAS_PV_VALID |
-                                           I40E_AQ_VSI_PROP_INGRESS_UP_VALID |
-                                           I40E_AQ_VSI_PROP_EGRESS_UP_VALID));
-
-       if (i40e_is_vsi_uplink_mode_veb(vsi)) {
-               info->valid_sections |=
-                               cpu_to_le16(I40E_AQ_VSI_PROP_SWITCH_VALID);
-               info->switch_id =
-                               cpu_to_le16(I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB);
-       }
-#ifdef CONFIG_DCB
-       enabled_tc = i40e_get_fcoe_tc_map(pf);
-#endif
-       i40e_vsi_setup_queue_map(vsi, ctxt, enabled_tc, true);
-
-       /* set up queue option section: only enable FCoE */
-       info->queueing_opt_flags = I40E_AQ_VSI_QUE_OPT_FCOE_ENA;
-
-       return 0;
-}
-
-/**
- * i40e_fcoe_enable - this is the implementation of ndo_fcoe_enable,
- * indicating the upper FCoE protocol stack is ready to use FCoE
- * offload features.
- *
- * @netdev: pointer to the netdev that FCoE is created on
- *
- * Returns 0 on success
- *
- * in RTNL
- *
- **/
-int i40e_fcoe_enable(struct net_device *netdev)
-{
-       struct i40e_netdev_priv *np = netdev_priv(netdev);
-       struct i40e_vsi *vsi = np->vsi;
-       struct i40e_pf *pf = vsi->back;
-       struct i40e_fcoe *fcoe = &pf->fcoe;
-
-       if (!(pf->flags & I40E_FLAG_FCOE_ENABLED)) {
-               netdev_err(netdev, "HW does not support FCoE.\n");
-               return -ENODEV;
-       }
-
-       if (vsi->type != I40E_VSI_FCOE) {
-               netdev_err(netdev, "interface does not support FCoE.\n");
-               return -EBUSY;
-       }
-
-       atomic_inc(&fcoe->refcnt);
-
-       return 0;
-}
-
-/**
- * i40e_fcoe_disable- disables FCoE for upper FCoE protocol stack.
- * @dev: pointer to the netdev that FCoE is created on
- *
- * Returns 0 on success
- *
- **/
-int i40e_fcoe_disable(struct net_device *netdev)
-{
-       struct i40e_netdev_priv *np = netdev_priv(netdev);
-       struct i40e_vsi *vsi = np->vsi;
-       struct i40e_pf *pf = vsi->back;
-       struct i40e_fcoe *fcoe = &pf->fcoe;
-
-       if (!(pf->flags & I40E_FLAG_FCOE_ENABLED)) {
-               netdev_err(netdev, "device does not support FCoE\n");
-               return -ENODEV;
-       }
-       if (vsi->type != I40E_VSI_FCOE)
-               return -EBUSY;
-
-       if (!atomic_dec_and_test(&fcoe->refcnt))
-               return -EINVAL;
-
-       netdev_info(netdev, "FCoE disabled\n");
-
-       return 0;
-}
-
-/**
- * i40e_fcoe_dma_pool_free - free the per cpu pool for FCoE DDP
- * @fcoe: the FCoE sw object
- * @dev: the device that the pool is associated with
- * @cpu: the cpu for this pool
- *
- **/
-static void i40e_fcoe_dma_pool_free(struct i40e_fcoe *fcoe,
-                                   struct device *dev,
-                                   unsigned int cpu)
-{
-       struct i40e_fcoe_ddp_pool *ddp_pool;
-
-       ddp_pool = per_cpu_ptr(fcoe->ddp_pool, cpu);
-       if (!ddp_pool->pool) {
-               dev_warn(dev, "DDP pool already freed for cpu %d\n", cpu);
-               return;
-       }
-       dma_pool_destroy(ddp_pool->pool);
-       ddp_pool->pool = NULL;
-}
-
-/**
- * i40e_fcoe_dma_pool_create - per cpu pool for FCoE DDP
- * @fcoe: the FCoE sw object
- * @dev: the device that the pool is associated with
- * @cpu: the cpu for this pool
- *
- * Returns 0 on successful or non zero on failure
- *
- **/
-static int i40e_fcoe_dma_pool_create(struct i40e_fcoe *fcoe,
-                                    struct device *dev,
-                                    unsigned int cpu)
-{
-       struct i40e_fcoe_ddp_pool *ddp_pool;
-       struct dma_pool *pool;
-       char pool_name[32];
-
-       ddp_pool = per_cpu_ptr(fcoe->ddp_pool, cpu);
-       if (ddp_pool->pool) {
-               dev_warn(dev, "DDP pool already allocated for cpu %d\n", cpu);
-               return 0;
-       }
-       snprintf(pool_name, sizeof(pool_name), "i40e_fcoe_ddp_%d", cpu);
-       pool = dma_pool_create(pool_name, dev, I40E_FCOE_DDP_PTR_MAX,
-                              I40E_FCOE_DDP_PTR_ALIGN, PAGE_SIZE);
-       if (!pool) {
-               dev_err(dev, "dma_pool_create %s failed\n", pool_name);
-               return -ENOMEM;
-       }
-       ddp_pool->pool = pool;
-       return 0;
-}
-
-/**
- * i40e_fcoe_free_ddp_resources - release FCoE DDP resources
- * @vsi: the vsi FCoE is associated with
- *
- **/
-void i40e_fcoe_free_ddp_resources(struct i40e_vsi *vsi)
-{
-       struct i40e_pf *pf = vsi->back;
-       struct i40e_fcoe *fcoe = &pf->fcoe;
-       int cpu, i;
-
-       /* do nothing if not FCoE VSI */
-       if (vsi->type != I40E_VSI_FCOE)
-               return;
-
-       /* do nothing if no DDP pools were allocated */
-       if (!fcoe->ddp_pool)
-               return;
-
-       for (i = 0; i < I40E_FCOE_DDP_MAX; i++)
-               i40e_fcoe_ddp_put(vsi->netdev, i);
-
-       for_each_possible_cpu(cpu)
-               i40e_fcoe_dma_pool_free(fcoe, &pf->pdev->dev, cpu);
-
-       free_percpu(fcoe->ddp_pool);
-       fcoe->ddp_pool = NULL;
-
-       netdev_info(vsi->netdev, "VSI %d,%d FCoE DDP resources released\n",
-                   vsi->id, vsi->seid);
-}
-
-/**
- * i40e_fcoe_setup_ddp_resources - allocate per cpu DDP resources
- * @vsi: the VSI FCoE is associated with
- *
- * Returns 0 on successful or non zero on failure
- *
- **/
-int i40e_fcoe_setup_ddp_resources(struct i40e_vsi *vsi)
-{
-       struct i40e_pf *pf = vsi->back;
-       struct device *dev = &pf->pdev->dev;
-       struct i40e_fcoe *fcoe = &pf->fcoe;
-       unsigned int cpu;
-       int i;
-
-       if (vsi->type != I40E_VSI_FCOE)
-               return -ENODEV;
-
-       /* do nothing if no DDP pools were allocated */
-       if (fcoe->ddp_pool)
-               return -EEXIST;
-
-       /* allocate per CPU memory to track DDP pools */
-       fcoe->ddp_pool = alloc_percpu(struct i40e_fcoe_ddp_pool);
-       if (!fcoe->ddp_pool) {
-               dev_err(&pf->pdev->dev, "failed to allocate percpu DDP\n");
-               return -ENOMEM;
-       }
-
-       /* allocate pci pool for each cpu */
-       for_each_possible_cpu(cpu) {
-               if (!i40e_fcoe_dma_pool_create(fcoe, dev, cpu))
-                       continue;
-
-               dev_err(dev, "failed to alloc DDP pool on cpu:%d\n", cpu);
-               i40e_fcoe_free_ddp_resources(vsi);
-               return -ENOMEM;
-       }
-
-       /* initialize the sw context */
-       for (i = 0; i < I40E_FCOE_DDP_MAX; i++)
-               i40e_fcoe_ddp_clear(&fcoe->ddp[i]);
-
-       netdev_info(vsi->netdev, "VSI %d,%d FCoE DDP resources allocated\n",
-                   vsi->id, vsi->seid);
-
-       return 0;
-}
-
-/**
- * i40e_fcoe_handle_status - check the Programming Status for FCoE
- * @rx_ring: the Rx ring for this descriptor
- * @rx_desc: the Rx descriptor for Programming Status, not a packet descriptor.
- *
- * Check if this is the Rx Programming Status descriptor write-back for FCoE.
- * This is used to verify if the context/filter programming or invalidation
- * requested by SW to the HW is successful or not and take actions accordingly.
- **/
-void i40e_fcoe_handle_status(struct i40e_ring *rx_ring,
-                            union i40e_rx_desc *rx_desc, u8 prog_id)
-{
-       struct i40e_pf *pf = rx_ring->vsi->back;
-       struct i40e_fcoe *fcoe = &pf->fcoe;
-       struct i40e_fcoe_ddp *ddp;
-       u32 error;
-       u16 xid;
-       u64 qw;
-
-       /* we only care for FCoE here */
-       if (!i40e_fcoe_progid_is_fcoe(prog_id))
-               return;
-
-       xid = le32_to_cpu(rx_desc->wb.qword0.hi_dword.fcoe_param) &
-             (I40E_FCOE_DDP_MAX - 1);
-
-       if (!i40e_fcoe_xid_is_valid(xid))
-               return;
-
-       ddp = &fcoe->ddp[xid];
-       WARN_ON(xid != ddp->xid);
-
-       qw = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
-       error = (qw & I40E_RX_PROG_STATUS_DESC_QW1_ERROR_MASK) >>
-               I40E_RX_PROG_STATUS_DESC_QW1_ERROR_SHIFT;
-
-       /* DDP context programming status: failure or success */
-       if (prog_id == I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_PROG_STATUS) {
-               if (I40E_RX_PROG_FCOE_ERROR_TBL_FULL(error)) {
-                       dev_err(&pf->pdev->dev, "xid %x ddp->xid %x TABLE FULL\n",
-                               xid, ddp->xid);
-                       ddp->prerr |= I40E_RX_PROG_FCOE_ERROR_TBL_FULL_BIT;
-               }
-               if (I40E_RX_PROG_FCOE_ERROR_CONFLICT(error)) {
-                       dev_err(&pf->pdev->dev, "xid %x ddp->xid %x CONFLICT\n",
-                               xid, ddp->xid);
-                       ddp->prerr |= I40E_RX_PROG_FCOE_ERROR_CONFLICT_BIT;
-               }
-       }
-
-       /* DDP context invalidation status: failure or success */
-       if (prog_id == I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_INVL_STATUS) {
-               if (I40E_RX_PROG_FCOE_ERROR_INVLFAIL(error)) {
-                       dev_err(&pf->pdev->dev, "xid %x ddp->xid %x INVALIDATION FAILURE\n",
-                               xid, ddp->xid);
-                       ddp->prerr |= I40E_RX_PROG_FCOE_ERROR_INVLFAIL_BIT;
-               }
-               /* clear the flag so we can retry invalidation */
-               clear_bit(__I40E_FCOE_DDP_ABORTED, &ddp->flags);
-       }
-
-       /* unmap DMA */
-       i40e_fcoe_ddp_unmap(pf, ddp);
-       i40e_fcoe_ddp_clear(ddp);
-}
-
-/**
- * i40e_fcoe_handle_offload - check ddp status and mark it done
- * @adapter: i40e adapter
- * @rx_desc: advanced rx descriptor
- * @skb: the skb holding the received data
- *
- * This checks ddp status.
- *
- * Returns : < 0 indicates an error or not a FCOE ddp, 0 indicates
- * not passing the skb to ULD, > 0 indicates is the length of data
- * being ddped.
- *
- **/
-int i40e_fcoe_handle_offload(struct i40e_ring *rx_ring,
-                            union i40e_rx_desc *rx_desc,
-                            struct sk_buff *skb)
-{
-       struct i40e_pf *pf = rx_ring->vsi->back;
-       struct i40e_fcoe *fcoe = &pf->fcoe;
-       struct fc_frame_header *fh = NULL;
-       struct i40e_fcoe_ddp *ddp = NULL;
-       u32 status, fltstat;
-       u32 error, fcerr;
-       int rc = -EINVAL;
-       u16 ptype;
-       u16 xid;
-       u64 qw;
-
-       /* check this rxd is for programming status */
-       qw = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
-       /* packet descriptor, check packet type */
-       ptype = (qw & I40E_RXD_QW1_PTYPE_MASK) >> I40E_RXD_QW1_PTYPE_SHIFT;
-       if (!i40e_rx_is_fcoe(ptype))
-               goto out_no_ddp;
-
-       error = (qw & I40E_RXD_QW1_ERROR_MASK) >> I40E_RXD_QW1_ERROR_SHIFT;
-       fcerr = (error >> I40E_RX_DESC_ERROR_L3L4E_SHIFT) &
-                I40E_RX_DESC_FCOE_ERROR_MASK;
-
-       /* check stateless offload error */
-       if (unlikely(fcerr == I40E_RX_DESC_ERROR_L3L4E_PROT)) {
-               dev_err(&pf->pdev->dev, "Protocol Error\n");
-               skb->ip_summed = CHECKSUM_NONE;
-       } else {
-               skb->ip_summed = CHECKSUM_UNNECESSARY;
-       }
-
-       /* check hw status on ddp */
-       status = (qw & I40E_RXD_QW1_STATUS_MASK) >> I40E_RXD_QW1_STATUS_SHIFT;
-       fltstat = (status >> I40E_RX_DESC_STATUS_FLTSTAT_SHIFT) &
-                  I40E_RX_DESC_FLTSTAT_FCMASK;
-
-       /* now we are ready to check DDP */
-       fh = i40e_fcoe_fc_frame_header(skb);
-       xid = i40e_fcoe_fc_get_xid(fh);
-       if (!i40e_fcoe_xid_is_valid(xid))
-               goto out_no_ddp;
-
-       /* non DDP normal receive, return to the protocol stack */
-       if (fltstat == I40E_RX_DESC_FLTSTAT_NOMTCH) {
-               dev_info(&pf->pdev->dev, "No DDP, fcerr:0x%x\n", fcerr);
-               goto out_no_ddp;
-       }
-
-       /* do we have a sw ddp context setup ? */
-       ddp = &fcoe->ddp[xid];
-       if (!ddp->sgl)
-               goto out_no_ddp;
-
-       /* fetch xid from hw rxd wb, which should match up the sw ctxt */
-       xid = le16_to_cpu(rx_desc->wb.qword0.lo_dword.mirr_fcoe.fcoe_ctx_id);
-       if (ddp->xid != xid) {
-               dev_err(&pf->pdev->dev, "xid 0x%x does not match ctx_xid 0x%x\n",
-                       ddp->xid, xid);
-               goto out_put_ddp;
-       }
-
-       /* the same exchange has already errored out */
-       if (ddp->fcerr) {
-               dev_err(&pf->pdev->dev, "xid 0x%x fcerr 0x%x reported fcer 0x%x\n",
-                       xid, ddp->fcerr, fcerr);
-               goto out_put_ddp;
-       }
-
-       /* fcoe param is valid by now with correct DDPed length */
-       ddp->len = le32_to_cpu(rx_desc->wb.qword0.hi_dword.fcoe_param);
-       ddp->fcerr = fcerr;
-       /* header posting only, useful only for target mode and debugging */
-       if (fltstat == I40E_RX_DESC_FLTSTAT_DDP) {
-               /* For target mode, we get header of the last packet but it
-                * does not have the FCoE trailer field, i.e., CRC and EOF
-                * Ordered Set since they are offloaded by the HW, so fill
-                * it up correspondingly to allow the packet to pass through
-                * to the upper protocol stack.
-                */
-               u32 f_ctl = ntoh24(fh->fh_f_ctl);
-
-               if ((f_ctl & FC_FC_END_SEQ) &&
-                   (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA)) {
-                       struct fcoe_crc_eof *crc = NULL;
-
-                       crc = (struct fcoe_crc_eof *)skb_put(skb, sizeof(*crc));
-                       crc->fcoe_eof = FC_EOF_T;
-               } else {
-                       /* otherwise, drop the header only frame */
-                       rc = 0;
-                       goto out_no_ddp;
-               }
-       }
-
-out_put_ddp:
-       /* either we got RSP or we have an error, unmap DMA in both cases */
-       i40e_fcoe_ddp_unmap(pf, ddp);
-       if (ddp->len && !ddp->fcerr) {
-               int pkts;
-
-               rc = ddp->len;
-               i40e_fcoe_ddp_clear(ddp);
-               ddp->len = rc;
-               pkts = DIV_ROUND_UP(rc, 2048);
-               rx_ring->stats.bytes += rc;
-               rx_ring->stats.packets += pkts;
-               rx_ring->q_vector->rx.total_bytes += rc;
-               rx_ring->q_vector->rx.total_packets += pkts;
-               set_bit(__I40E_FCOE_DDP_DONE, &ddp->flags);
-       }
-
-out_no_ddp:
-       return rc;
-}
-
-/**
- * i40e_fcoe_ddp_setup - called to set up ddp context
- * @netdev: the corresponding net_device
- * @xid: the exchange id requesting ddp
- * @sgl: the scatter-gather list for this request
- * @sgc: the number of scatter-gather items
- * @target_mode: indicates this is a DDP request for target
- *
- * Returns : 1 for success and 0 for no DDP on this I/O
- **/
-static int i40e_fcoe_ddp_setup(struct net_device *netdev, u16 xid,
-                              struct scatterlist *sgl, unsigned int sgc,
-                              int target_mode)
-{
-       static const unsigned int bufflen = I40E_FCOE_DDP_BUF_MIN;
-       struct i40e_netdev_priv *np = netdev_priv(netdev);
-       struct i40e_fcoe_ddp_pool *ddp_pool;
-       struct i40e_pf *pf = np->vsi->back;
-       struct i40e_fcoe *fcoe = &pf->fcoe;
-       unsigned int i, j, dmacount;
-       struct i40e_fcoe_ddp *ddp;
-       unsigned int firstoff = 0;
-       unsigned int thisoff = 0;
-       unsigned int thislen = 0;
-       struct scatterlist *sg;
-       dma_addr_t addr = 0;
-       unsigned int len;
-
-       if (xid >= I40E_FCOE_DDP_MAX) {
-               dev_warn(&pf->pdev->dev, "xid=0x%x out-of-range\n", xid);
-               return 0;
-       }
-
-       /* no DDP if we are already down or resetting */
-       if (test_bit(__I40E_DOWN, &pf->state) ||
-           test_bit(__I40E_NEEDS_RESTART, &pf->state)) {
-               dev_info(&pf->pdev->dev, "xid=0x%x device in reset/down\n",
-                        xid);
-               return 0;
-       }
-
-       ddp = &fcoe->ddp[xid];
-       if (ddp->sgl) {
-               dev_info(&pf->pdev->dev, "xid 0x%x w/ non-null sgl=%p nents=%d\n",
-                        xid, ddp->sgl, ddp->sgc);
-               return 0;
-       }
-       i40e_fcoe_ddp_clear(ddp);
-
-       if (!fcoe->ddp_pool) {
-               dev_info(&pf->pdev->dev, "No DDP pool, xid 0x%x\n", xid);
-               return 0;
-       }
-
-       ddp_pool = per_cpu_ptr(fcoe->ddp_pool, get_cpu());
-       if (!ddp_pool->pool) {
-               dev_info(&pf->pdev->dev, "No percpu ddp pool, xid 0x%x\n", xid);
-               goto out_noddp;
-       }
-
-       /* setup dma from scsi command sgl */
-       dmacount = dma_map_sg(&pf->pdev->dev, sgl, sgc, DMA_FROM_DEVICE);
-       if (dmacount == 0) {
-               dev_info(&pf->pdev->dev, "dma_map_sg for sgl %p, sgc %d failed\n",
-                        sgl, sgc);
-               goto out_noddp_unmap;
-       }
-
-       /* alloc the udl from our ddp pool */
-       ddp->udl = dma_pool_alloc(ddp_pool->pool, GFP_ATOMIC, &ddp->udp);
-       if (!ddp->udl) {
-               dev_info(&pf->pdev->dev,
-                        "Failed allocated ddp context, xid 0x%x\n", xid);
-               goto out_noddp_unmap;
-       }
-
-       j = 0;
-       ddp->len = 0;
-       for_each_sg(sgl, sg, dmacount, i) {
-               addr = sg_dma_address(sg);
-               len = sg_dma_len(sg);
-               ddp->len += len;
-               while (len) {
-                       /* max number of buffers allowed in one DDP context */
-                       if (j >= I40E_FCOE_DDP_BUFFCNT_MAX) {
-                               dev_info(&pf->pdev->dev,
-                                        "xid=%x:%d,%d,%d:addr=%llx not enough descriptors\n",
-                                        xid, i, j, dmacount, (u64)addr);
-                               goto out_noddp_free;
-                       }
-
-                       /* get the offset of length of current buffer */
-                       thisoff = addr & ((dma_addr_t)bufflen - 1);
-                       thislen = min_t(unsigned int, (bufflen - thisoff), len);
-                       /* all but the 1st buffer (j == 0)
-                        * must be aligned on bufflen
-                        */
-                       if ((j != 0) && (thisoff))
-                               goto out_noddp_free;
-
-                       /* all but the last buffer
-                        * ((i == (dmacount - 1)) && (thislen == len))
-                        * must end at bufflen
-                        */
-                       if (((i != (dmacount - 1)) || (thislen != len)) &&
-                           ((thislen + thisoff) != bufflen))
-                               goto out_noddp_free;
-
-                       ddp->udl[j] = (u64)(addr - thisoff);
-                       /* only the first buffer may have none-zero offset */
-                       if (j == 0)
-                               firstoff = thisoff;
-                       len -= thislen;
-                       addr += thislen;
-                       j++;
-               }
-       }
-       /* only the last buffer may have non-full bufflen */
-       ddp->lastsize = thisoff + thislen;
-       ddp->firstoff = firstoff;
-       ddp->list_len = j;
-       ddp->pool = ddp_pool->pool;
-       ddp->sgl = sgl;
-       ddp->sgc = sgc;
-       ddp->xid = xid;
-       if (target_mode)
-               set_bit(__I40E_FCOE_DDP_TARGET, &ddp->flags);
-       set_bit(__I40E_FCOE_DDP_INITALIZED, &ddp->flags);
-
-       put_cpu();
-       return 1; /* Success */
-
-out_noddp_free:
-       dma_pool_free(ddp->pool, ddp->udl, ddp->udp);
-       i40e_fcoe_ddp_clear(ddp);
-
-out_noddp_unmap:
-       dma_unmap_sg(&pf->pdev->dev, sgl, sgc, DMA_FROM_DEVICE);
-out_noddp:
-       put_cpu();
-       return 0;
-}
-
-/**
- * i40e_fcoe_ddp_get - called to set up ddp context in initiator mode
- * @netdev: the corresponding net_device
- * @xid: the exchange id requesting ddp
- * @sgl: the scatter-gather list for this request
- * @sgc: the number of scatter-gather items
- *
- * This is the implementation of net_device_ops.ndo_fcoe_ddp_setup
- * and is expected to be called from ULD, e.g., FCP layer of libfc
- * to set up ddp for the corresponding xid of the given sglist for
- * the corresponding I/O.
- *
- * Returns : 1 for success and 0 for no ddp
- **/
-static int i40e_fcoe_ddp_get(struct net_device *netdev, u16 xid,
-                            struct scatterlist *sgl, unsigned int sgc)
-{
-       return i40e_fcoe_ddp_setup(netdev, xid, sgl, sgc, 0);
-}
-
-#ifdef HAVE_NETDEV_OPS_FCOE_DDP_TARGET
-/**
- * i40e_fcoe_ddp_target - called to set up ddp context in target mode
- * @netdev: the corresponding net_device
- * @xid: the exchange id requesting ddp
- * @sgl: the scatter-gather list for this request
- * @sgc: the number of scatter-gather items
- *
- * This is the implementation of net_device_ops.ndo_fcoe_ddp_target
- * and is expected to be called from ULD, e.g., FCP layer of libfc
- * to set up ddp for the corresponding xid of the given sglist for
- * the corresponding I/O. The DDP in target mode is a write I/O request
- * from the initiator.
- *
- * Returns : 1 for success and 0 for no ddp
- **/
-static int i40e_fcoe_ddp_target(struct net_device *netdev, u16 xid,
-                               struct scatterlist *sgl, unsigned int sgc)
-{
-       return i40e_fcoe_ddp_setup(netdev, xid, sgl, sgc, 1);
-}
-
-#endif /* HAVE_NETDEV_OPS_FCOE_DDP_TARGET */
-/**
- * i40e_fcoe_program_ddp - programs the HW DDP related descriptors
- * @tx_ring: transmit ring for this packet
- * @skb:     the packet to be sent out
- * @sof: the SOF to indicate class of service
- *
- * Determine if it is READ/WRITE command, and finds out if there is
- * a matching SW DDP context for this command. DDP is applicable
- * only in case of READ if initiator or WRITE in case of
- * responder (via checking XFER_RDY).
- *
- * Note: caller checks sof and ddp sw context
- *
- * Returns : none
- *
- **/
-static void i40e_fcoe_program_ddp(struct i40e_ring *tx_ring,
-                                 struct sk_buff *skb,
-                                 struct i40e_fcoe_ddp *ddp, u8 sof)
-{
-       struct i40e_fcoe_filter_context_desc *filter_desc = NULL;
-       struct i40e_fcoe_queue_context_desc *queue_desc = NULL;
-       struct i40e_fcoe_ddp_context_desc *ddp_desc = NULL;
-       struct i40e_pf *pf = tx_ring->vsi->back;
-       u16 i = tx_ring->next_to_use;
-       struct fc_frame_header *fh;
-       u64 flags_rsvd_lanq = 0;
-       bool target_mode;
-
-       /* check if abort is still pending */
-       if (test_bit(__I40E_FCOE_DDP_ABORTED, &ddp->flags)) {
-               dev_warn(&pf->pdev->dev,
-                        "DDP abort is still pending xid:%hx and ddp->flags:%lx:\n",
-                        ddp->xid, ddp->flags);
-               return;
-       }
-
-       /* set the flag to indicate this is programmed */
-       if (test_and_set_bit(__I40E_FCOE_DDP_PROGRAMMED, &ddp->flags)) {
-               dev_warn(&pf->pdev->dev,
-                        "DDP is already programmed for xid:%hx and ddp->flags:%lx:\n",
-                        ddp->xid, ddp->flags);
-               return;
-       }
-
-       /* Prepare the DDP context descriptor */
-       ddp_desc = I40E_DDP_CONTEXT_DESC(tx_ring, i);
-       i++;
-       if (i == tx_ring->count)
-               i = 0;
-
-       ddp_desc->type_cmd_foff_lsize =
-                               cpu_to_le64(I40E_TX_DESC_DTYPE_DDP_CTX  |
-                               ((u64)I40E_FCOE_DDP_CTX_DESC_BSIZE_4K  <<
-                               I40E_FCOE_DDP_CTX_QW1_CMD_SHIFT)        |
-                               ((u64)ddp->firstoff                    <<
-                               I40E_FCOE_DDP_CTX_QW1_FOFF_SHIFT)       |
-                               ((u64)ddp->lastsize                    <<
-                               I40E_FCOE_DDP_CTX_QW1_LSIZE_SHIFT));
-       ddp_desc->rsvd = cpu_to_le64(0);
-
-       /* target mode needs last packet in the sequence  */
-       target_mode = test_bit(__I40E_FCOE_DDP_TARGET, &ddp->flags);
-       if (target_mode)
-               ddp_desc->type_cmd_foff_lsize |=
-                       cpu_to_le64(I40E_FCOE_DDP_CTX_DESC_LASTSEQH);
-
-       /* Prepare queue_context descriptor */
-       queue_desc = I40E_QUEUE_CONTEXT_DESC(tx_ring, i++);
-       if (i == tx_ring->count)
-               i = 0;
-       queue_desc->dmaindx_fbase = cpu_to_le64(ddp->xid | ((u64)ddp->udp));
-       queue_desc->flen_tph = cpu_to_le64(ddp->list_len |
-                               ((u64)(I40E_FCOE_QUEUE_CTX_DESC_TPHRDESC |
-                               I40E_FCOE_QUEUE_CTX_DESC_TPHDATA) <<
-                               I40E_FCOE_QUEUE_CTX_QW1_TPH_SHIFT));
-
-       /* Prepare filter_context_desc */
-       filter_desc = I40E_FILTER_CONTEXT_DESC(tx_ring, i);
-       i++;
-       if (i == tx_ring->count)
-               i = 0;
-
-       fh = (struct fc_frame_header *)skb_transport_header(skb);
-       filter_desc->param = cpu_to_le32(ntohl(fh->fh_parm_offset));
-       filter_desc->seqn = cpu_to_le16(ntohs(fh->fh_seq_cnt));
-       filter_desc->rsvd_dmaindx = cpu_to_le16(ddp->xid <<
-                               I40E_FCOE_FILTER_CTX_QW0_DMAINDX_SHIFT);
-
-       flags_rsvd_lanq = I40E_FCOE_FILTER_CTX_DESC_CTYP_DDP;
-       flags_rsvd_lanq |= (u64)(target_mode ?
-                       I40E_FCOE_FILTER_CTX_DESC_ENODE_RSP :
-                       I40E_FCOE_FILTER_CTX_DESC_ENODE_INIT);
-
-       flags_rsvd_lanq |= (u64)((sof == FC_SOF_I2 || sof == FC_SOF_N2) ?
-                       I40E_FCOE_FILTER_CTX_DESC_FC_CLASS2 :
-                       I40E_FCOE_FILTER_CTX_DESC_FC_CLASS3);
-
-       flags_rsvd_lanq |= ((u64)skb->queue_mapping <<
-                               I40E_FCOE_FILTER_CTX_QW1_LANQINDX_SHIFT);
-       filter_desc->flags_rsvd_lanq = cpu_to_le64(flags_rsvd_lanq);
-
-       /* By this time, all offload related descriptors has been programmed */
-       tx_ring->next_to_use = i;
-}
-
-/**
- * i40e_fcoe_invalidate_ddp - invalidates DDP in case of abort
- * @tx_ring: transmit ring for this packet
- * @skb: the packet associated w/ this DDP invalidation, i.e., ABTS
- * @ddp: the SW DDP context for this DDP
- *
- * Programs the Tx context descriptor to do DDP invalidation.
- **/
-static void i40e_fcoe_invalidate_ddp(struct i40e_ring *tx_ring,
-                                    struct sk_buff *skb,
-                                    struct i40e_fcoe_ddp *ddp)
-{
-       struct i40e_tx_context_desc *context_desc;
-       int i;
-
-       if (test_and_set_bit(__I40E_FCOE_DDP_ABORTED, &ddp->flags))
-               return;
-
-       i = tx_ring->next_to_use;
-       context_desc = I40E_TX_CTXTDESC(tx_ring, i);
-       i++;
-       if (i == tx_ring->count)
-               i = 0;
-
-       context_desc->tunneling_params = cpu_to_le32(0);
-       context_desc->l2tag2 = cpu_to_le16(0);
-       context_desc->rsvd = cpu_to_le16(0);
-       context_desc->type_cmd_tso_mss = cpu_to_le64(
-               I40E_TX_DESC_DTYPE_FCOE_CTX |
-               (I40E_FCOE_TX_CTX_DESC_OPCODE_DDP_CTX_INVL <<
-               I40E_TXD_CTX_QW1_CMD_SHIFT) |
-               (I40E_FCOE_TX_CTX_DESC_OPCODE_SINGLE_SEND <<
-               I40E_TXD_CTX_QW1_CMD_SHIFT));
-       tx_ring->next_to_use = i;
-
-}
-
-/**
- * i40e_fcoe_handle_ddp - check we should setup or invalidate DDP
- * @tx_ring: transmit ring for this packet
- * @skb: the packet to be sent out
- * @sof: the SOF to indicate class of service
- *
- * Determine if it is ABTS/READ/XFER_RDY, and finds out if there is
- * a matching SW DDP context for this command. DDP is applicable
- * only in case of READ if initiator or WRITE in case of
- * responder (via checking XFER_RDY). In case this is an ABTS, send
- * just invalidate the context.
- **/
-static void i40e_fcoe_handle_ddp(struct i40e_ring *tx_ring,
-                                struct sk_buff *skb, u8 sof)
-{
-       struct i40e_pf *pf = tx_ring->vsi->back;
-       struct i40e_fcoe *fcoe = &pf->fcoe;
-       struct fc_frame_header *fh;
-       struct i40e_fcoe_ddp *ddp;
-       u32 f_ctl;
-       u8 r_ctl;
-       u16 xid;
-
-       fh = (struct fc_frame_header *)skb_transport_header(skb);
-       f_ctl = ntoh24(fh->fh_f_ctl);
-       r_ctl = fh->fh_r_ctl;
-       ddp = NULL;
-
-       if ((r_ctl == FC_RCTL_DD_DATA_DESC) && (f_ctl & FC_FC_EX_CTX)) {
-               /* exchange responder? if so, XFER_RDY for write */
-               xid = ntohs(fh->fh_rx_id);
-               if (i40e_fcoe_xid_is_valid(xid)) {
-                       ddp = &fcoe->ddp[xid];
-                       if ((ddp->xid == xid) &&
-                           (test_bit(__I40E_FCOE_DDP_TARGET, &ddp->flags)))
-                               i40e_fcoe_program_ddp(tx_ring, skb, ddp, sof);
-               }
-       } else if (r_ctl == FC_RCTL_DD_UNSOL_CMD) {
-               /* exchange originator, check READ cmd */
-               xid = ntohs(fh->fh_ox_id);
-               if (i40e_fcoe_xid_is_valid(xid)) {
-                       ddp = &fcoe->ddp[xid];
-                       if ((ddp->xid == xid) &&
-                           (!test_bit(__I40E_FCOE_DDP_TARGET, &ddp->flags)))
-                               i40e_fcoe_program_ddp(tx_ring, skb, ddp, sof);
-               }
-       } else if (r_ctl == FC_RCTL_BA_ABTS) {
-               /* exchange originator, check ABTS */
-               xid = ntohs(fh->fh_ox_id);
-               if (i40e_fcoe_xid_is_valid(xid)) {
-                       ddp = &fcoe->ddp[xid];
-                       if ((ddp->xid == xid) &&
-                           (!test_bit(__I40E_FCOE_DDP_TARGET, &ddp->flags)))
-                               i40e_fcoe_invalidate_ddp(tx_ring, skb, ddp);
-               }
-       }
-}
-
-/**
- * i40e_fcoe_tso - set up FCoE TSO
- * @tx_ring:  ring to send buffer on
- * @first:    pointer to first Tx buffer for xmit
- * @tx_flags: collected send information
- * @hdr_len:  the tso header length
- * @sof: the SOF to indicate class of service
- *
- * Note must already have sof checked to be either class 2 or class 3 before
- * calling this function.
- *
- * Returns 1 to indicate sequence segmentation offload is properly setup
- * or returns 0 to indicate no tso is needed, otherwise returns error
- * code to drop the frame.
- **/
-static int i40e_fcoe_tso(struct i40e_ring *tx_ring,
-                        struct i40e_tx_buffer *first,
-                        u32 tx_flags, u8 *hdr_len, u8 sof)
-{
-       struct sk_buff *skb = first->skb;
-       struct i40e_tx_context_desc *context_desc;
-       u32 cd_type, cd_cmd, cd_tso_len, cd_mss;
-       struct fc_frame_header *fh;
-       u64 cd_type_cmd_tso_mss;
-       u16 gso_segs, gso_size;
-
-       /* must match gso type as FCoE */
-       if (!skb_is_gso(skb))
-               return 0;
-
-       /* is it the expected gso type for FCoE ?*/
-       if (skb_shinfo(skb)->gso_type != SKB_GSO_FCOE) {
-               netdev_err(skb->dev,
-                          "wrong gso type %d:expecting SKB_GSO_FCOE\n",
-                          skb_shinfo(skb)->gso_type);
-               return -EINVAL;
-       }
-
-       /* header and trailer are inserted by hw */
-       *hdr_len = skb_transport_offset(skb) + sizeof(struct fc_frame_header) +
-                  sizeof(struct fcoe_crc_eof);
-
-       /* pull values out of skb_shinfo */
-       gso_size = skb_shinfo(skb)->gso_size;
-       gso_segs = skb_shinfo(skb)->gso_segs;
-
-#ifndef HAVE_NDO_FEATURES_CHECK
-       /* too small a TSO segment size causes hw problems */
-       if (gso_size < 64) {
-               gso_size = 64;
-               gso_segs = DIV_ROUND_UP(skb->len - *hdr_len, 64);
-       }
-#endif
-       /* update gso size and bytecount with header size */
-       first->gso_segs = gso_segs;
-       first->bytecount += (first->gso_segs - 1) * *hdr_len;
-
-       /* check sof to decide a class 2 or 3 TSO */
-       if (likely(i40e_fcoe_sof_is_class3(sof)))
-               cd_cmd = I40E_FCOE_TX_CTX_DESC_OPCODE_TSO_FC_CLASS3;
-       else
-               cd_cmd = I40E_FCOE_TX_CTX_DESC_OPCODE_TSO_FC_CLASS2;
-
-       /* param field valid? */
-       fh = (struct fc_frame_header *)skb_transport_header(skb);
-       if (fh->fh_f_ctl[2] & FC_FC_REL_OFF)
-               cd_cmd |= I40E_FCOE_TX_CTX_DESC_RELOFF;
-
-       /* fill the field values */
-       cd_type = I40E_TX_DESC_DTYPE_FCOE_CTX;
-       cd_tso_len = skb->len - *hdr_len;
-       cd_mss = gso_size;
-       cd_type_cmd_tso_mss =
-               ((u64)cd_type  << I40E_TXD_CTX_QW1_DTYPE_SHIFT)     |
-               ((u64)cd_cmd     << I40E_TXD_CTX_QW1_CMD_SHIFT)     |
-               ((u64)cd_tso_len << I40E_TXD_CTX_QW1_TSO_LEN_SHIFT) |
-               ((u64)cd_mss     << I40E_TXD_CTX_QW1_MSS_SHIFT);
-
-       /* grab the next descriptor */
-       context_desc = I40E_TX_CTXTDESC(tx_ring, tx_ring->next_to_use);
-       tx_ring->next_to_use++;
-       if (tx_ring->next_to_use == tx_ring->count)
-               tx_ring->next_to_use = 0;
-
-       context_desc->tunneling_params = 0;
-       context_desc->l2tag2 = cpu_to_le16((tx_flags & I40E_TX_FLAGS_VLAN_MASK)
-                                           >> I40E_TX_FLAGS_VLAN_SHIFT);
-       context_desc->type_cmd_tso_mss = cpu_to_le64(cd_type_cmd_tso_mss);
-
-       return 1;
-}
-
-/**
- * i40e_fcoe_tx_map - build the tx descriptor
- * @tx_ring:  ring to send buffer on
- * @skb:      send buffer
- * @first:    first buffer info buffer to use
- * @tx_flags: collected send information
- * @hdr_len:  ptr to the size of the packet header
- * @eof:      the frame eof value
- *
- * Note, for FCoE, sof and eof are already checked
- **/
-static void i40e_fcoe_tx_map(struct i40e_ring *tx_ring,
-                            struct sk_buff *skb,
-                            struct i40e_tx_buffer *first,
-                            u32 tx_flags, u8 hdr_len, u8 eof)
-{
-       u32 td_offset = 0;
-       u32 td_cmd = 0;
-       u32 maclen;
-
-       /* insert CRC */
-       td_cmd = I40E_TX_DESC_CMD_ICRC;
-
-       /* setup MACLEN */
-       maclen = skb_network_offset(skb);
-       if (tx_flags & I40E_TX_FLAGS_SW_VLAN)
-               maclen += sizeof(struct vlan_hdr);
-
-       if (skb->protocol == htons(ETH_P_FCOE)) {
-               /* for FCoE, maclen should exclude ether type */
-               maclen -= 2;
-               /* setup type as FCoE and EOF insertion */
-               td_cmd |= (I40E_TX_DESC_CMD_FCOET | i40e_fcoe_ctxt_eof(eof));
-               /* setup FCoELEN and FCLEN */
-               td_offset |= ((((sizeof(struct fcoe_hdr) + 2) >> 2) <<
-                               I40E_TX_DESC_LENGTH_IPLEN_SHIFT) |
-                             ((sizeof(struct fc_frame_header) >> 2) <<
-                               I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT));
-               /* trim to exclude trailer */
-               pskb_trim(skb, skb->len - sizeof(struct fcoe_crc_eof));
-       }
-
-       /* MACLEN is ether header length in words not bytes */
-       td_offset |= (maclen >> 1) << I40E_TX_DESC_LENGTH_MACLEN_SHIFT;
-
-       i40e_tx_map(tx_ring, skb, first, tx_flags, hdr_len, td_cmd, td_offset);
-}
-
-/**
- * i40e_fcoe_set_skb_header - adjust skb header point for FIP/FCoE/FC
- * @skb: the skb to be adjusted
- *
- * Returns true if this skb is a FCoE/FIP or VLAN carried FCoE/FIP and then
- * adjusts the skb header pointers correspondingly. Otherwise, returns false.
- **/
-static inline int i40e_fcoe_set_skb_header(struct sk_buff *skb)
-{
-       __be16 protocol = skb->protocol;
-
-       skb_reset_mac_header(skb);
-       skb->mac_len = sizeof(struct ethhdr);
-       if (protocol == htons(ETH_P_8021Q)) {
-               struct vlan_ethhdr *veth = (struct vlan_ethhdr *)eth_hdr(skb);
-
-               protocol = veth->h_vlan_encapsulated_proto;
-               skb->mac_len += sizeof(struct vlan_hdr);
-       }
-
-       /* FCoE or FIP only */
-       if ((protocol != htons(ETH_P_FIP)) &&
-           (protocol != htons(ETH_P_FCOE)))
-               return -EINVAL;
-
-       /* set header to L2 of FCoE/FIP */
-       skb_set_network_header(skb, skb->mac_len);
-       if (protocol == htons(ETH_P_FIP))
-               return 0;
-
-       /* set header to L3 of FC */
-       skb_set_transport_header(skb, skb->mac_len + sizeof(struct fcoe_hdr));
-       return 0;
-}
-
-/**
- * i40e_fcoe_xmit_frame - transmit buffer
- * @skb:     send buffer
- * @netdev:  the fcoe netdev
- *
- * Returns 0 if sent, else an error code
- **/
-static netdev_tx_t i40e_fcoe_xmit_frame(struct sk_buff *skb,
-                                       struct net_device *netdev)
-{
-       struct i40e_netdev_priv *np = netdev_priv(skb->dev);
-       struct i40e_vsi *vsi = np->vsi;
-       struct i40e_ring *tx_ring = vsi->tx_rings[skb->queue_mapping];
-       struct i40e_tx_buffer *first;
-       u32 tx_flags = 0;
-       int fso, count;
-       u8 hdr_len = 0;
-       u8 sof = 0;
-       u8 eof = 0;
-
-       if (i40e_fcoe_set_skb_header(skb))
-               goto out_drop;
-
-       count = i40e_xmit_descriptor_count(skb);
-       if (i40e_chk_linearize(skb, count)) {
-               if (__skb_linearize(skb))
-                       goto out_drop;
-               count = i40e_txd_use_count(skb->len);
-               tx_ring->tx_stats.tx_linearize++;
-       }
-
-       /* need: 1 descriptor per page * PAGE_SIZE/I40E_MAX_DATA_PER_TXD,
-        *       + 1 desc for skb_head_len/I40E_MAX_DATA_PER_TXD,
-        *       + 4 desc gap to avoid the cache line where head is,
-        *       + 1 desc for context descriptor,
-        * otherwise try next time
-        */
-       if (i40e_maybe_stop_tx(tx_ring, count + 4 + 1)) {
-               tx_ring->tx_stats.tx_busy++;
-               return NETDEV_TX_BUSY;
-       }
-
-       /* prepare the xmit flags */
-       if (i40e_tx_prepare_vlan_flags(skb, tx_ring, &tx_flags))
-               goto out_drop;
-
-       /* record the location of the first descriptor for this packet */
-       first = &tx_ring->tx_bi[tx_ring->next_to_use];
-       first->skb = skb;
-       first->bytecount = skb->len;
-       first->gso_segs = 1;
-
-       /* FIP is a regular L2 traffic w/o offload */
-       if (skb->protocol == htons(ETH_P_FIP))
-               goto out_send;
-
-       /* check sof and eof, only supports FC Class 2 or 3 */
-       if (i40e_fcoe_fc_sof(skb, &sof) || i40e_fcoe_fc_eof(skb, &eof)) {
-               netdev_err(netdev, "SOF/EOF error:%02x - %02x\n", sof, eof);
-               goto out_drop;
-       }
-
-       /* always do FCCRC for FCoE */
-       tx_flags |= I40E_TX_FLAGS_FCCRC;
-
-       /* check we should do sequence offload */
-       fso = i40e_fcoe_tso(tx_ring, first, tx_flags, &hdr_len, sof);
-       if (fso < 0)
-               goto out_drop;
-       else if (fso)
-               tx_flags |= I40E_TX_FLAGS_FSO;
-       else
-               i40e_fcoe_handle_ddp(tx_ring, skb, sof);
-
-out_send:
-       /* send out the packet */
-       i40e_fcoe_tx_map(tx_ring, skb, first, tx_flags, hdr_len, eof);
-
-       i40e_maybe_stop_tx(tx_ring, DESC_NEEDED);
-       return NETDEV_TX_OK;
-
-out_drop:
-       dev_kfree_skb_any(first->skb);
-       first->skb = NULL;
-       return NETDEV_TX_OK;
-}
-
-/**
- * i40e_fcoe_change_mtu - NDO callback to change the Maximum Transfer Unit
- * @netdev: network interface device structure
- * @new_mtu: new value for maximum frame size
- *
- * Returns error as operation not permitted
- *
- **/
-static int i40e_fcoe_change_mtu(struct net_device *netdev, int new_mtu)
-{
-       netdev_warn(netdev, "MTU change is not supported on FCoE interfaces\n");
-       return -EPERM;
-}
-
-#ifdef HAVE_NDO_SET_FEATURES
-/**
- * i40e_fcoe_set_features - set the netdev feature flags
- * @netdev: ptr to the netdev being adjusted
- * @features: the feature set that the stack is suggesting
- *
- **/
-#ifdef HAVE_RHEL6_NET_DEVICE_OPS_EXT
-static int i40e_fcoe_set_features(struct net_device *netdev, u32 features)
-#else
-static int i40e_fcoe_set_features(struct net_device *netdev,
-                            netdev_features_t features)
-#endif
-{
-       struct i40e_netdev_priv *np = netdev_priv(netdev);
-       struct i40e_vsi *vsi = np->vsi;
-
-#ifdef NETIF_F_HW_VLAN_CTAG_RX
-       if (features & NETIF_F_HW_VLAN_CTAG_RX)
-               i40e_vlan_stripping_enable(vsi);
-#else
-       if (features & NETIF_F_HW_VLAN_RX)
-               i40e_vlan_stripping_enable(vsi);
-#endif
-       else
-               i40e_vlan_stripping_disable(vsi);
-
-       return 0;
-}
-
-#endif /* HAVE_NDO_SET_FEATURES */
-
-#ifdef HAVE_NET_DEVICE_OPS
-static const struct net_device_ops i40e_fcoe_netdev_ops = {
-       .ndo_open               = i40e_open,
-       .ndo_stop               = i40e_close,
-#ifdef HAVE_NDO_GET_STATS64
-       .ndo_get_stats64        = i40e_get_netdev_stats_struct,
-#else
-       .ndo_get_stats          = i40e_get_netdev_stats_struct,
-#endif
-       .ndo_set_rx_mode        = i40e_set_rx_mode,
-       .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_mac_address    = i40e_set_mac,
-       .ndo_change_mtu         = i40e_fcoe_change_mtu,
-#if defined(HAVE_PTP_1588_CLOCK)
-       .ndo_do_ioctl           = i40e_ioctl,
-#endif
-       .ndo_tx_timeout         = i40e_tx_timeout,
-       .ndo_vlan_rx_add_vid    = i40e_vlan_rx_add_vid,
-       .ndo_vlan_rx_kill_vid   = i40e_vlan_rx_kill_vid,
-#ifdef HAVE_SETUP_TC
-#ifdef NETIF_F_HW_TC
-       .ndo_setup_tc           = __i40e_setup_tc,
-#else
-       .ndo_setup_tc           = i40e_setup_tc,
-#endif
-#endif /* HAVE_SETUP_TC */
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       .ndo_poll_controller    = i40e_netpoll,
-#endif
-       .ndo_start_xmit         = i40e_fcoe_xmit_frame,
-       .ndo_fcoe_enable        = i40e_fcoe_enable,
-       .ndo_fcoe_disable       = i40e_fcoe_disable,
-       .ndo_fcoe_ddp_setup     = i40e_fcoe_ddp_get,
-       .ndo_fcoe_ddp_done      = i40e_fcoe_ddp_put,
-#ifdef HAVE_NETDEV_OPS_FCOE_DDP_TARGET
-       .ndo_fcoe_ddp_target    = i40e_fcoe_ddp_target,
-#endif
-#ifdef HAVE_RHEL6_NET_DEVICE_OPS_EXT
-};
-
-/* RHEL6 keeps these operations in a separate structure */
-static const struct net_device_ops_ext i40e_fcoe_netdev_ops_ext = {
-       .size = sizeof(struct net_device_ops_ext),
-#endif /* HAVE_RHEL6_NET_DEVICE_OPS_EXT */
-#ifdef HAVE_NDO_SET_FEATURES
-       .ndo_set_features       = i40e_fcoe_set_features,
-#endif /* HAVE_NDO_SET_FEATURES */
-};
-#endif /* HAVE_NET_DEVICE_OPS */
-
-/* fcoe network device type */
-static struct device_type fcoe_netdev_type = {
-       .name = "fcoe",
-};
-
-/**
- * i40e_fcoe_config_netdev - prepares the VSI context for creating a FCoE VSI
- * @vsi: pointer to the associated VSI struct
- * @ctxt: pointer to the associated VSI context to be passed to HW
- *
- * Returns 0 on success or < 0 on error
- **/
-void i40e_fcoe_config_netdev(struct net_device *netdev, struct i40e_vsi *vsi)
-{
-       struct i40e_hw *hw = &vsi->back->hw;
-       struct i40e_pf *pf = vsi->back;
-#ifdef HAVE_RHEL6_NET_DEVICE_OPS_EXT
-       u32 hw_features;
-#endif
-
-       if (vsi->type != I40E_VSI_FCOE)
-               return;
-
-#ifdef NETIF_F_HW_VLAN_CTAG_RX
-       netdev->features = (NETIF_F_HW_VLAN_CTAG_TX |
-                           NETIF_F_HW_VLAN_CTAG_RX |
-                           NETIF_F_HW_VLAN_CTAG_FILTER);
-
-       netdev->vlan_features = netdev->features;
-       netdev->vlan_features &= ~(NETIF_F_HW_VLAN_CTAG_TX |
-                                  NETIF_F_HW_VLAN_CTAG_RX |
-                                  NETIF_F_HW_VLAN_CTAG_FILTER);
-#else
-       netdev->features = (NETIF_F_HW_VLAN_TX |
-                           NETIF_F_HW_VLAN_RX |
-                           NETIF_F_HW_VLAN_FILTER);
-
-       netdev->vlan_features = netdev->features & ~(NETIF_F_HW_VLAN_TX |
-                                                    NETIF_F_HW_VLAN_RX |
-                                                    NETIF_F_HW_VLAN_FILTER);
-#endif
-       netdev->fcoe_ddp_xid = I40E_FCOE_DDP_MAX - 1;
-       netdev->features |= NETIF_F_ALL_FCOE;
-       netdev->vlan_features |= NETIF_F_ALL_FCOE;
-#ifdef HAVE_NDO_SET_FEATURES
-#ifdef HAVE_RHEL6_NET_DEVICE_OPS_EXT
-       hw_features = get_netdev_hw_features(netdev);
-       hw_features |= netdev->features;
-       set_netdev_hw_features(netdev, hw_features);
-#else
-       netdev->hw_features |= netdev->features;
-#endif
-#endif
-#ifdef IFF_UNICAST_FLT
-       netdev->priv_flags |= IFF_UNICAST_FLT;
-#endif
-#ifdef IFF_SUPP_NOFCS
-       netdev->priv_flags |= IFF_SUPP_NOFCS;
-#endif
-
-       strlcpy(netdev->name, "fcoe%d", IFNAMSIZ-1);
-       netdev->mtu = FCOE_MTU;
-       SET_NETDEV_DEV(netdev, &pf->pdev->dev);
-       SET_NETDEV_DEVTYPE(netdev, &fcoe_netdev_type);
-#ifdef HAVE_NETDEV_PORT
-       /* set different dev_port value 1 for FCoE netdev than the default
-        * zero dev_port value for PF netdev, this helps biosdevname user
-        * tool to differentiate them correctly while both attached to the
-        * same PCI function.
-        */
-       netdev->dev_port = 1;
-#endif
-       spin_lock_bh(&vsi->mac_filter_hash_lock);
-       i40e_add_mac_filter(vsi, hw->mac.san_addr);
-       i40e_add_mac_filter(vsi, (u8[6]) FC_FCOE_FLOGI_MAC);
-       i40e_add_mac_filter(vsi, FIP_ALL_FCOE_MACS);
-       i40e_add_mac_filter(vsi, FIP_ALL_ENODE_MACS);
-       spin_unlock_bh(&vsi->mac_filter_hash_lock);
-
-       /* use san mac */
-       ether_addr_copy(netdev->dev_addr, hw->mac.san_addr);
-#ifdef ETHTOOL_GPERMADDR
-       ether_addr_copy(netdev->perm_addr, hw->mac.san_addr);
-#endif
-#ifdef HAVE_NET_DEVICE_OPS
-       /* fcoe netdev ops */
-       netdev->netdev_ops = &i40e_fcoe_netdev_ops;
-#endif
-}
-
-/**
- * i40e_fcoe_vsi_setup - allocate and set up FCoE VSI
- * @pf: the PF that VSI is associated with
- *
- **/
-void i40e_fcoe_vsi_setup(struct i40e_pf *pf)
-{
-       struct i40e_vsi *vsi;
-       u16 seid;
-       int i;
-
-       if (!(pf->flags & I40E_FLAG_FCOE_ENABLED))
-               return;
-
-       for (i = 0; i < pf->num_alloc_vsi; i++) {
-               vsi = pf->vsi[i];
-               if (vsi && vsi->type == I40E_VSI_FCOE) {
-                       dev_warn(&pf->pdev->dev,
-                                "FCoE VSI already created\n");
-                       return;
-               }
-       }
-
-       seid = pf->vsi[pf->lan_vsi]->seid;
-       vsi = i40e_vsi_setup(pf, I40E_VSI_FCOE, seid, 0);
-       if (vsi) {
-               dev_dbg(&pf->pdev->dev,
-                       "Successfully created FCoE VSI seid %d id %d uplink_seid %d PF seid %d\n",
-                       vsi->seid, vsi->id, vsi->uplink_seid, seid);
-       } else {
-               dev_info(&pf->pdev->dev, "Failed to create FCoE VSI\n");
-       }
-}
-#endif /* WITH_FCOE */
diff --git a/i40e-dkms/i40e-1.6.42/src/i40e_fcoe.h b/i40e-dkms/i40e-1.6.42/src/i40e_fcoe.h
deleted file mode 100644 (file)
index 5bc0f24..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-/*******************************************************************************
- *
- * Intel(R) 40-10 Gigabit Ethernet Connection Network Driver
- * Copyright(c) 2013 - 2017 Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- ******************************************************************************/
-
-#ifndef _I40E_FCOE_H_
-#define _I40E_FCOE_H_
-
-/* FCoE HW context helper macros */
-#define I40E_DDP_CONTEXT_DESC(R, i)     \
-       (&(((struct i40e_fcoe_ddp_context_desc *)((R)->desc))[i]))
-
-#define I40E_QUEUE_CONTEXT_DESC(R, i)   \
-       (&(((struct i40e_fcoe_queue_context_desc *)((R)->desc))[i]))
-
-#define I40E_FILTER_CONTEXT_DESC(R, i)  \
-       (&(((struct i40e_fcoe_filter_context_desc *)((R)->desc))[i]))
-
-/* receive queue descriptor filter status for FCoE */
-#define I40E_RX_DESC_FLTSTAT_FCMASK    0x3
-#define I40E_RX_DESC_FLTSTAT_NOMTCH    0x0     /* no ddp context match */
-#define I40E_RX_DESC_FLTSTAT_NODDP     0x1     /* no ddp due to error */
-#define I40E_RX_DESC_FLTSTAT_DDP       0x2     /* DDPed payload, post header */
-#define I40E_RX_DESC_FLTSTAT_FCPRSP    0x3     /* FCP_RSP */
-
-/* receive queue descriptor error codes for FCoE */
-#define I40E_RX_DESC_FCOE_ERROR_MASK           \
-       (I40E_RX_DESC_ERROR_L3L4E_PROT |        \
-        I40E_RX_DESC_ERROR_L3L4E_FC |          \
-        I40E_RX_DESC_ERROR_L3L4E_DMAC_ERR |    \
-        I40E_RX_DESC_ERROR_L3L4E_DMAC_WARN)
-
-/* receive queue descriptor programming error */
-#define I40E_RX_PROG_FCOE_ERROR_TBL_FULL(e)    \
-       (((e) >> I40E_RX_PROG_STATUS_DESC_FCOE_TBL_FULL_SHIFT) & 0x1)
-
-#define I40E_RX_PROG_FCOE_ERROR_CONFLICT(e)    \
-       (((e) >> I40E_RX_PROG_STATUS_DESC_FCOE_CONFLICT_SHIFT) & 0x1)
-
-#define I40E_RX_PROG_FCOE_ERROR_TBL_FULL_BIT   \
-       BIT(I40E_RX_PROG_STATUS_DESC_FCOE_TBL_FULL_SHIFT)
-#define I40E_RX_PROG_FCOE_ERROR_CONFLICT_BIT   \
-       BIT(I40E_RX_PROG_STATUS_DESC_FCOE_CONFLICT_SHIFT)
-
-#define I40E_RX_PROG_FCOE_ERROR_INVLFAIL(e)    \
-       I40E_RX_PROG_FCOE_ERROR_CONFLICT(e)
-#define I40E_RX_PROG_FCOE_ERROR_INVLFAIL_BIT   \
-       I40E_RX_PROG_FCOE_ERROR_CONFLICT_BIT
-
-/* FCoE DDP related definitions */
-#define I40E_FCOE_MIN_XID      0x0000  /* the min xid supported by fcoe_sw */
-#define I40E_FCOE_MAX_XID      0x0FFF  /* the max xid supported by fcoe_sw */
-#define I40E_FCOE_DDP_BUFFCNT_MAX      512     /* 9 bits bufcnt */
-#define I40E_FCOE_DDP_PTR_ALIGN                16
-#define I40E_FCOE_DDP_PTR_MAX  (I40E_FCOE_DDP_BUFFCNT_MAX * sizeof(dma_addr_t))
-#define I40E_FCOE_DDP_BUF_MIN  4096
-#define I40E_FCOE_DDP_MAX      2048
-#define I40E_FCOE_FILTER_CTX_QW1_PCTYPE_SHIFT  8
-
-/* supported netdev features for FCoE */
-#define I40E_FCOE_NETIF_FEATURES (NETIF_F_ALL_FCOE | \
-       NETIF_F_HW_VLAN_CTAG_TX | \
-       NETIF_F_HW_VLAN_CTAG_RX | \
-       NETIF_F_HW_VLAN_CTAG_FILTER)
-
-/* DDP context flags */
-enum i40e_fcoe_ddp_flags {
-       __I40E_FCOE_DDP_NONE = 1,
-       __I40E_FCOE_DDP_TARGET,
-       __I40E_FCOE_DDP_INITALIZED,
-       __I40E_FCOE_DDP_PROGRAMMED,
-       __I40E_FCOE_DDP_DONE,
-       __I40E_FCOE_DDP_ABORTED,
-       __I40E_FCOE_DDP_UNMAPPED,
-};
-
-/* DDP SW context struct */
-struct i40e_fcoe_ddp {
-       int len;
-       u16 xid;
-       u16 firstoff;
-       u16 lastsize;
-       u16 list_len;
-       u8 fcerr;
-       u8 prerr;
-       unsigned long flags;
-       unsigned int sgc;
-       struct scatterlist *sgl;
-       dma_addr_t udp;
-       u64 *udl;
-       struct dma_pool *pool;
-
-};
-
-struct i40e_fcoe_ddp_pool {
-       struct dma_pool *pool;
-};
-
-struct i40e_fcoe {
-       unsigned long mode;
-       atomic_t refcnt;
-       struct i40e_fcoe_ddp_pool __percpu *ddp_pool;
-       struct i40e_fcoe_ddp ddp[I40E_FCOE_DDP_MAX];
-};
-
-#endif /* _I40E_FCOE_H_ */
diff --git a/i40e-dkms/i40e-1.6.42/src/i40e_virtchnl.h b/i40e-dkms/i40e-1.6.42/src/i40e_virtchnl.h
deleted file mode 100644 (file)
index fc82c08..0000000
+++ /dev/null
@@ -1,411 +0,0 @@
-/*******************************************************************************
- *
- * Intel(R) 40-10 Gigabit Ethernet Connection Network Driver
- * Copyright(c) 2013 - 2017 Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- ******************************************************************************/
-
-#ifndef _I40E_VIRTCHNL_H_
-#define _I40E_VIRTCHNL_H_
-
-#include "i40e_type.h"
-
-/* Description:
- * This header file describes the VF-PF communication protocol used
- * by the various i40e drivers.
- *
- * Admin queue buffer usage:
- * desc->opcode is always i40e_aqc_opc_send_msg_to_pf
- * flags, retval, datalen, and data addr are all used normally.
- * Firmware copies the cookie fields when sending messages between the PF and
- * VF, but uses all other fields internally. Due to this limitation, we
- * must send all messages as "indirect", i.e. using an external buffer.
- *
- * All the vsi indexes are relative to the VF. Each VF can have maximum of
- * three VSIs. All the queue indexes are relative to the VSI.  Each VF can
- * have a maximum of sixteen queues for all of its VSIs.
- *
- * The PF is required to return a status code in v_retval for all messages
- * except RESET_VF, which does not require any response. The return value is of
- * i40e_status_code type, defined in the i40e_type.h.
- *
- * In general, VF driver initialization should roughly follow the order of these
- * opcodes. The VF driver must first validate the API version of the PF driver,
- * then request a reset, then get resources, then configure queues and
- * interrupts. After these operations are complete, the VF driver may start
- * its queues, optionally add MAC and VLAN filters, and process traffic.
- */
-
-/* Opcodes for VF-PF communication. These are placed in the v_opcode field
- * of the virtchnl_msg structure.
- */
-enum i40e_virtchnl_ops {
-/* The PF sends status change events to VFs using
- * the I40E_VIRTCHNL_OP_EVENT opcode.
- * VFs send requests to the PF using the other ops.
- */
-       I40E_VIRTCHNL_OP_UNKNOWN = 0,
-       I40E_VIRTCHNL_OP_VERSION = 1, /* must ALWAYS be 1 */
-       I40E_VIRTCHNL_OP_RESET_VF = 2,
-       I40E_VIRTCHNL_OP_GET_VF_RESOURCES = 3,
-       I40E_VIRTCHNL_OP_CONFIG_TX_QUEUE = 4,
-       I40E_VIRTCHNL_OP_CONFIG_RX_QUEUE = 5,
-       I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES = 6,
-       I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP = 7,
-       I40E_VIRTCHNL_OP_ENABLE_QUEUES = 8,
-       I40E_VIRTCHNL_OP_DISABLE_QUEUES = 9,
-       I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS = 10,
-       I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS = 11,
-       I40E_VIRTCHNL_OP_ADD_VLAN = 12,
-       I40E_VIRTCHNL_OP_DEL_VLAN = 13,
-       I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE = 14,
-       I40E_VIRTCHNL_OP_GET_STATS = 15,
-       I40E_VIRTCHNL_OP_FCOE = 16,
-       I40E_VIRTCHNL_OP_EVENT = 17, /* must ALWAYS be 17 */
-       I40E_VIRTCHNL_OP_CONFIG_RSS_KEY = 23,
-       I40E_VIRTCHNL_OP_CONFIG_RSS_LUT = 24,
-       I40E_VIRTCHNL_OP_GET_RSS_HENA_CAPS = 25,
-       I40E_VIRTCHNL_OP_SET_RSS_HENA = 26,
-
-};
-
-/* Virtual channel message descriptor. This overlays the admin queue
- * descriptor. All other data is passed in external buffers.
- */
-
-struct i40e_virtchnl_msg {
-       u8 pad[8];                       /* AQ flags/opcode/len/retval fields */
-       enum i40e_virtchnl_ops v_opcode; /* avoid confusion with desc->opcode */
-       i40e_status v_retval;  /* ditto for desc->retval */
-       u32 vfid;                        /* used by PF when sending to VF */
-};
-
-/* Message descriptions and data structures.*/
-
-/* I40E_VIRTCHNL_OP_VERSION
- * VF posts its version number to the PF. PF responds with its version number
- * in the same format, along with a return code.
- * Reply from PF has its major/minor versions also in param0 and param1.
- * If there is a major version mismatch, then the VF cannot operate.
- * If there is a minor version mismatch, then the VF can operate but should
- * add a warning to the system log.
- *
- * This enum element MUST always be specified as == 1, regardless of other
- * changes in the API. The PF must always respond to this message without
- * error regardless of version mismatch.
- */
-#define I40E_VIRTCHNL_VERSION_MAJOR            1
-#define I40E_VIRTCHNL_VERSION_MINOR            1
-#define I40E_VIRTCHNL_VERSION_MINOR_NO_VF_CAPS 0
-
-struct i40e_virtchnl_version_info {
-       u32 major;
-       u32 minor;
-};
-
-/* I40E_VIRTCHNL_OP_RESET_VF
- * VF sends this request to PF with no parameters
- * PF does NOT respond! VF driver must delay then poll VFGEN_RSTAT register
- * until reset completion is indicated. The admin queue must be reinitialized
- * after this operation.
- *
- * When reset is complete, PF must ensure that all queues in all VSIs associated
- * with the VF are stopped, all queue configurations in the HMC are set to 0,
- * and all MAC and VLAN filters (except the default MAC address) on all VSIs
- * are cleared.
- */
-
-/* I40E_VIRTCHNL_OP_GET_VF_RESOURCES
- * Version 1.0 VF sends this request to PF with no parameters
- * Version 1.1 VF sends this request to PF with u32 bitmap of its capabilities
- * PF responds with an indirect message containing
- * i40e_virtchnl_vf_resource and one or more
- * i40e_virtchnl_vsi_resource structures.
- */
-
-struct i40e_virtchnl_vsi_resource {
-       u16 vsi_id;
-       u16 num_queue_pairs;
-       enum i40e_vsi_type vsi_type;
-       u16 qset_handle;
-       u8 default_mac_addr[ETH_ALEN];
-};
-/* VF offload flags */
-#define I40E_VIRTCHNL_VF_OFFLOAD_L2            0x00000001
-#define I40E_VIRTCHNL_VF_OFFLOAD_IWARP         0x00000002
-#define I40E_VIRTCHNL_VF_OFFLOAD_FCOE          0x00000004
-#define I40E_VIRTCHNL_VF_OFFLOAD_RSS_AQ                0x00000008
-#define I40E_VIRTCHNL_VF_OFFLOAD_RSS_REG       0x00000010
-#define I40E_VIRTCHNL_VF_OFFLOAD_WB_ON_ITR     0x00000020
-#define I40E_VIRTCHNL_VF_OFFLOAD_VLAN          0x00010000
-#define I40E_VIRTCHNL_VF_OFFLOAD_RX_POLLING    0x00020000
-#define I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2 0x00040000
-#define I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF                0X00080000
-#define I40E_VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM    0X00100000
-
-#define I40E_VF_BASE_MODE_OFFLOADS (I40E_VIRTCHNL_VF_OFFLOAD_L2 | \
-                                   I40E_VIRTCHNL_VF_OFFLOAD_VLAN | \
-                                   I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF)
-
-struct i40e_virtchnl_vf_resource {
-       u16 num_vsis;
-       u16 num_queue_pairs;
-       u16 max_vectors;
-       u16 max_mtu;
-
-       u32 vf_offload_flags;
-       u32 rss_key_size;
-       u32 rss_lut_size;
-
-       struct i40e_virtchnl_vsi_resource vsi_res[1];
-};
-
-/* I40E_VIRTCHNL_OP_CONFIG_TX_QUEUE
- * VF sends this message to set up parameters for one TX queue.
- * External data buffer contains one instance of i40e_virtchnl_txq_info.
- * PF configures requested queue and returns a status code.
- */
-
-/* Tx queue config info */
-struct i40e_virtchnl_txq_info {
-       u16 vsi_id;
-       u16 queue_id;
-       u16 ring_len;           /* number of descriptors, multiple of 8 */
-       u16 headwb_enabled;
-       u64 dma_ring_addr;
-       u64 dma_headwb_addr;
-};
-
-/* I40E_VIRTCHNL_OP_CONFIG_RX_QUEUE
- * VF sends this message to set up parameters for one RX queue.
- * External data buffer contains one instance of i40e_virtchnl_rxq_info.
- * PF configures requested queue and returns a status code.
- */
-
-/* Rx queue config info */
-struct i40e_virtchnl_rxq_info {
-       u16 vsi_id;
-       u16 queue_id;
-       u32 ring_len;           /* number of descriptors, multiple of 32 */
-       u16 hdr_size;
-       u16 splithdr_enabled;
-       u32 databuffer_size;
-       u32 max_pkt_size;
-       u64 dma_ring_addr;
-       enum i40e_hmc_obj_rx_hsplit_0 rx_split_pos;
-};
-
-/* I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES
- * VF sends this message to set parameters for all active TX and RX queues
- * associated with the specified VSI.
- * PF configures queues and returns status.
- * If the number of queues specified is greater than the number of queues
- * associated with the VSI, an error is returned and no queues are configured.
- */
-struct i40e_virtchnl_queue_pair_info {
-       /* NOTE: vsi_id and queue_id should be identical for both queues. */
-       struct i40e_virtchnl_txq_info txq;
-       struct i40e_virtchnl_rxq_info rxq;
-};
-
-struct i40e_virtchnl_vsi_queue_config_info {
-       u16 vsi_id;
-       u16 num_queue_pairs;
-       struct i40e_virtchnl_queue_pair_info qpair[1];
-};
-
-/* I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP
- * VF uses this message to map vectors to queues.
- * The rxq_map and txq_map fields are bitmaps used to indicate which queues
- * are to be associated with the specified vector.
- * The "other" causes are always mapped to vector 0.
- * PF configures interrupt mapping and returns status.
- */
-struct i40e_virtchnl_vector_map {
-       u16 vsi_id;
-       u16 vector_id;
-       u16 rxq_map;
-       u16 txq_map;
-       u16 rxitr_idx;
-       u16 txitr_idx;
-};
-
-struct i40e_virtchnl_irq_map_info {
-       u16 num_vectors;
-       struct i40e_virtchnl_vector_map vecmap[1];
-};
-
-/* I40E_VIRTCHNL_OP_ENABLE_QUEUES
- * I40E_VIRTCHNL_OP_DISABLE_QUEUES
- * VF sends these message to enable or disable TX/RX queue pairs.
- * The queues fields are bitmaps indicating which queues to act upon.
- * (Currently, we only support 16 queues per VF, but we make the field
- * u32 to allow for expansion.)
- * PF performs requested action and returns status.
- */
-struct i40e_virtchnl_queue_select {
-       u16 vsi_id;
-       u16 pad;
-       u32 rx_queues;
-       u32 tx_queues;
-};
-
-/* I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS
- * VF sends this message in order to add one or more unicast or multicast
- * address filters for the specified VSI.
- * PF adds the filters and returns status.
- */
-
-/* I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS
- * VF sends this message in order to remove one or more unicast or multicast
- * filters for the specified VSI.
- * PF removes the filters and returns status.
- */
-
-struct i40e_virtchnl_ether_addr {
-       u8 addr[ETH_ALEN];
-       u8 pad[2];
-};
-
-struct i40e_virtchnl_ether_addr_list {
-       u16 vsi_id;
-       u16 num_elements;
-       struct i40e_virtchnl_ether_addr list[1];
-};
-
-/* I40E_VIRTCHNL_OP_ADD_VLAN
- * VF sends this message to add one or more VLAN tag filters for receives.
- * PF adds the filters and returns status.
- * If a port VLAN is configured by the PF, this operation will return an
- * error to the VF.
- */
-
-/* I40E_VIRTCHNL_OP_DEL_VLAN
- * VF sends this message to remove one or more VLAN tag filters for receives.
- * PF removes the filters and returns status.
- * If a port VLAN is configured by the PF, this operation will return an
- * error to the VF.
- */
-
-struct i40e_virtchnl_vlan_filter_list {
-       u16 vsi_id;
-       u16 num_elements;
-       u16 vlan_id[1];
-};
-
-/* I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE
- * VF sends VSI id and flags.
- * PF returns status code in retval.
- * Note: we assume that broadcast accept mode is always enabled.
- */
-struct i40e_virtchnl_promisc_info {
-       u16 vsi_id;
-       u16 flags;
-};
-
-#define I40E_FLAG_VF_UNICAST_PROMISC   0x00000001
-#define I40E_FLAG_VF_MULTICAST_PROMISC 0x00000002
-
-/* I40E_VIRTCHNL_OP_GET_STATS
- * VF sends this message to request stats for the selected VSI. VF uses
- * the i40e_virtchnl_queue_select struct to specify the VSI. The queue_id
- * field is ignored by the PF.
- *
- * PF replies with struct i40e_eth_stats in an external buffer.
- */
-
-/* I40E_VIRTCHNL_OP_CONFIG_RSS_KEY
- * I40E_VIRTCHNL_OP_CONFIG_RSS_LUT
- * VF sends these messages to configure RSS. Only supported if both PF
- * and VF drivers set the I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF bit during
- * configuration negotiation. If this is the case, then the rss fields in
- * the vf resource struct are valid.
- * Both the key and LUT are initialized to 0 by the PF, meaning that
- * RSS is effectively disabled until set up by the VF.
- */
-struct i40e_virtchnl_rss_key {
-       u16 vsi_id;
-       u16 key_len;
-       u8 key[1];         /* RSS hash key, packed bytes */
-};
-
-struct i40e_virtchnl_rss_lut {
-       u16 vsi_id;
-       u16 lut_entries;
-       u8 lut[1];        /* RSS lookup table*/
-};
-
-/* I40E_VIRTCHNL_OP_GET_RSS_HENA_CAPS
- * I40E_VIRTCHNL_OP_SET_RSS_HENA
- * VF sends these messages to get and set the hash filter enable bits for RSS.
- * By default, the PF sets these to all possible traffic types that the
- * hardware supports. The VF can query this value if it wants to change the
- * traffic types that are hashed by the hardware.
- * Traffic types are defined in the i40e_filter_pctype enum in i40e_type.h
- */
-struct i40e_virtchnl_rss_hena {
-       u64 hena;
-};
-
-/* I40E_VIRTCHNL_OP_EVENT
- * PF sends this message to inform the VF driver of events that may affect it.
- * No direct response is expected from the VF, though it may generate other
- * messages in response to this one.
- */
-enum i40e_virtchnl_event_codes {
-       I40E_VIRTCHNL_EVENT_UNKNOWN = 0,
-       I40E_VIRTCHNL_EVENT_LINK_CHANGE,
-       I40E_VIRTCHNL_EVENT_RESET_IMPENDING,
-       I40E_VIRTCHNL_EVENT_PF_DRIVER_CLOSE,
-};
-#define I40E_PF_EVENT_SEVERITY_INFO            0
-#define I40E_PF_EVENT_SEVERITY_CERTAIN_DOOM    255
-
-struct i40e_virtchnl_pf_event {
-       enum i40e_virtchnl_event_codes event;
-       union {
-               struct {
-                       enum i40e_aq_link_speed link_speed;
-                       bool link_status;
-               } link_event;
-       } event_data;
-
-       int severity;
-};
-
-/* VF reset states - these are written into the RSTAT register:
- * I40E_VFGEN_RSTAT1 on the PF
- * I40E_VFGEN_RSTAT on the VF
- * When the PF initiates a reset, it writes 0
- * When the reset is complete, it writes 1
- * When the PF detects that the VF has recovered, it writes 2
- * VF checks this register periodically to determine if a reset has occurred,
- * then polls it to know when the reset is complete.
- * If either the PF or VF reads the register while the hardware
- * is in a reset state, it will return DEADBEEF, which, when masked
- * will result in 3.
- */
-enum i40e_vfr_states {
-       I40E_VFR_INPROGRESS = 0,
-       I40E_VFR_COMPLETED,
-       I40E_VFR_VFACTIVE,
-       I40E_VFR_UNKNOWN,
-};
-
-#endif /* _I40E_VIRTCHNL_H_ */
diff --git a/i40e-dkms/i40e-2.1.26/COPYING b/i40e-dkms/i40e-2.1.26/COPYING
new file mode 100644 (file)
index 0000000..53f1178
--- /dev/null
@@ -0,0 +1,339 @@
+
+"This software program is licensed subject to the GNU General Public License
+(GPL). Version 2, June 1991, available at
+<http://www.fsf.org/copyleft/gpl.html>"
+
+GNU General Public License
+
+Version 2, June 1991
+
+Copyright (C) 1989, 1991 Free Software Foundation, Inc. 
+59 Temple Place - Suite 330, Boston, MA  02111-1307, 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 Library 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.
+
+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 an idea of what it does.
+Copyright (C) yyyy  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., 59
+Temple Place - Suite 330, Boston, MA  02111-1307, 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 Library General Public
+License instead of this License.
similarity index 80%
rename from i40e-dkms/i40e-1.6.42/README
rename to i40e-dkms/i40e-2.1.26/README
index 3774b4e4ec3b0dd2b8cd5d4d62023e3ddcdac5e9..948900a0cc22e4cf076750f6deb4e5844027ce00 100644 (file)
@@ -4,13 +4,14 @@ i40e Linux* Base Driver for the Intel(R) XL710 Ethernet Controller Family
 
 ===============================================================================
 
-November 28, 2016
+June 21, 2017
 
 ===============================================================================
 
 Contents
 --------
 
+- Important Notes
 - Overview
 - Identifying Your Adapter
 - Building and Installation
@@ -59,7 +60,6 @@ VLAN tagging. This configuration allows unexpected, and potentially malicious,
 frames to be dropped.
 
 
-
 Overview
 --------
 
@@ -94,12 +94,26 @@ The driver information previously displayed in the /proc file system is not
 supported in this release.
 
 
+NOTE: 1 Gb devices based on the Intel(R) Ethernet Controller X722 do not
+support the following features:
+  * Data Center Bridging (DCB)
+  * QOS
+  * VMQ
+  * SR-IOV
+  * Task Encapsulation offload (VxLAN, NVGRE)
+  * Energy Efficient Ethernet (EEE)
+  * Auto-media detect
+
+
+
 
 Identifying Your Adapter
 ------------------------
 The driver in this release is compatible with devices based on the following:
   * Intel(R) Ethernet Controller X710
   * Intel(R) Ethernet Controller XL710
+  * Intel(R) Ethernet Controller X722
+
   * Intel(R) Ethernet Controller XXV710
 
 
@@ -118,47 +132,20 @@ http://www.intel.com/support
 
 SFP+ and QSFP+ Devices:
 
-NOTE:
+For information about supported media, follow the link below:
+  http://www.intel.com/content/dam/www/public/us/en/documents/
+  release-notes/xl710-ethernet-controller-feature-matrix.pdf
+NOTES:
 * Some Intel branded network adapters based on the X710/XL710 controller
-  may only support Intel branded modules for 40Gbps and 10Gbps. For other
-  connections based on the X710/XL710 controller, support is dependent on
-  your system board. Please see your vendor for details. Intel recommends
-  using Intel optics; other modules may function but are not validated by
-  Intel. Contact Intel for supported media types.
-
-Supplier       Type                                            Part Numbers
-SR Modules
-  Intel                DUAL RATE 1G/10G SFP+ SR (bailed)               E10GSFPSR
-LR Modules
-  Intel                DUAL RATE 1G/10G SFP+ LR (bailed)               E10GSFPLR
-1G SFP Modules
-  The following is a list of 3rd party SFP modules that have received some
-  testing. Not all modules are applicable to all devices.
-  Finisar      1000BASE-T SFP          FCLF-8251-3
-  Kinnex A     1000BASE-T SFP          XSFP-T-RJ12-0101-DLL
-  Avago                1000BASE-T SFP          ABCU-5710RZ
-QSFP+ Modules
-  Intel                TRIPLE RATE 1G/10G/40G QSFP+ SR (bailed)        E40GQSFPSR
-  Intel                TRIPLE RATE 1G/10G/40G QSFP+ LR (bailed)        E40GQSFPLR
-  QSFP+ 1G speed is not supported on XL710 based devices.
-SFP+ and QSFP+ Direct Attach Cables
-  X710/XL710 based SFP+/QSFP+ adapters support passive SFP+/QSFP+ Direct
-  Attach cables. Intel recommends using Intel(R) Ethernet SFP+/QSFP+ Twinaxial
-  Cables . Other cables may function but are not validated by Intel. Contact
-  Intel for supported media types.
-  X710 based SFP+ adapters support all passive and active limiting direct
-  attach cables that comply with SFF-8431 v4.1 and SFF-8472 v10.4
-  specifications.
-  Intel(R) Ethernet SFP+ Twinaxial Cable       XDACBL1M, XDACBL3M, XDACBL5M
-  Intel(R) Ethernet QSFP+ Breakout Cable       X4DACBL1, X4DACBL3, X4DACBL5
-  Intel(R) Ethernet QSFP+ Twinaxial Cable      XLDACBL1, XLDACBL3, XLDACBL5
-
-SFP+ Devices for XXV710-Based Adapters
---------------------------------------
-  Intel(R) Ethernet SFP28 SR Optic             E25GSFP28SR
-  Intel(R) Ethernet SFP28 Twinaxial Cable      XXVDACBL1M, XXVDACBL2M, XXVDACBL3M
-  Intel(R) Ethernet QSFP28 to SFP28 Twinaxial  XXV4DACBL1M, XXV4DACBL2M, XXV4DACBL3M
-  Breakout Cable
+  only support Intel branded modules. On these adapters, other modules
+  are not supported and will not function.
+* For connections based on the X710/XL710 controller, support is
+  dependent on your system board. Please see your vendor for details.
+* In all cases Intel recommends using Intel optics; other modules may
+  function but are not validated by Intel. Contact Intel for supported
+  media types.
+* In systems that do not have adequate airflow to cool the adapter and
+  optical modules, you must use high temperature optical modules.
 
 
 ================================================================================
@@ -260,7 +247,9 @@ Valid Range:
 
 
 NOTE: This parameter is only used on kernel 3.7.x and below. On kernel 3.8.x
-and above, use sysfs to enable VFs. For example:
+and above, use sysfs to enable VFs. Also, for Red Hat distributions,
+this parameter is only used on version 6.6 and older. For version 6.7 and
+newer, use sysfs. For example:
 #echo $num_vf_enabled > /sys/class/net/$dev/device/sriov_numvfs        //enable VFs
 #echo 0 > /sys/class/net/$dev/device/sriov_numvfs      //disable VFs
 
@@ -343,7 +332,7 @@ to set the VF to promiscuous mode.
   #ip link set eth2 promisc on
     Where eth2 is a VF interface in the VM
   For promiscuous Multicast:
-  #ip link set eth2 allmulti on
+  #ip link set eth2 allmulticast on
     Where eth2 is a VF interface in the VM
 
     NOTE: By default, the ethtool priv-flag vf-true-promisc-support is set to 
@@ -362,7 +351,7 @@ to set the VF to promiscuous mode.
 Now add a VLAN interface on the VF interface.
   #ip link add link eth2 name eth2.100 type vlan id 100
 
-Note that the order in which you set the VF?to promiscuous mode and add
+Note that the order in which you set the VF to promiscuous mode and add
 the VLAN interface does not matter (you can do either first). The end result
 in this example is that the VF will get all traffic that is tagged with
 VLAN 100.
@@ -385,6 +374,7 @@ NOTES:
 
   - An included script (set_irq_affinity) automates setting the IRQ to
     CPU affinity.
+
   - The Linux i40e driver supports the following flow types: IPv4, TCPv4, and
     UDPv4. For a given flow type, it supports valid combinations of
     IP addresses (source or destination) and UDP/TCP ports (source and 
@@ -448,40 +438,93 @@ ethtool, which also can be used to verify whether ATR rules still exist.
 
 Sideband Perfect Filters
 ------------------------
-Sideband Perfect Filters is an interface for loading the filter table that
-funnels all flow into queue_0 unless an alternative queue is specified
-using "action." If action is used, any flow that matches the filter criteria
-will be directed to the appropriate queue. Rules may be deleted from the
-table. This is done via
 
-  ethtool -U ethX delete N
-
-  where N is the rule number to be deleted, as specified in the loc value in
-  the filter add command.
-
-  If the queue is defined as -1, the filter drops matching packets. To account
-  for Sideband filter matches, the fdir_sb_match stats in ethtool can be used.
-
-  In addition, rx-N.rx_packets shows the number of packets processed by the
-  Nth queue.
-
-NOTES:
-Receive Packet Steering (RPS) and Receive Flow Steering (RFS) are not compatible
-with Flow Director. If Flow Director is enabled, these will be disabled.
-
-The VLAN field for Flow Director is not explicitly supported in the i40e
-driver.
-
-When filter rules are added from Sideband or ATR and the Flow Director filter
-table is full, the ATR rule is turned off by the driver. Subsequently, the
-Sideband filter rule is then turned off. When space becomes available in the
-filter table through filter rule deletion (i.e., an ATR rule or Sideband rule
-is deleted), the Sideband and ATR rule additions are turned back on.
-
-Occasionally, when the filter table is full, you will notice HW errors when
-you try to add new rules. The i40e driver will call for a filter flush and
-sideband filter list replay. This will help flush any stale ATR rules and
-create space.
+Sideband Perfect Filters are used to direct traffic that matches specified
+characteristics. They are enabled through ethtool's ntuple interface.
+To add a new filter use the following command:
+  ethtool -U <device> flow-type <type> src-ip <ip> dst-ip <ip> src-port <port>
+dst-port <port> action <queue>
+Where:
+  <device> - the ethernet device to program
+  <type> - can be ip4, tcp4, udp4, or sctp4
+  <ip> - the ip address to match on
+  <port> - the port number to match on
+  <queue> - the queue to direct traffic towards (-1 discards the matched traffic)
+Use the following command to display all of the active filters:
+  ethtool -u <device>
+Use the following command to delete a filter:
+  ethtool -U <device> delete <N>
+<N> is the filter id displayed when printing all the active filters, and may
+also have been specified using "loc <N>" when adding the filter.
+
+The following example matches TCP traffic sent from 192.168.0.1, port 5300,
+directed to 192.168.0.5, port 80, and sends it to queue 7:
+  ethtool -U enp130s0 flow-type tcp4 src-ip 192.168.0.1 dst-ip 192.168.0.5
+  src-port 5300 dst-port 7 action 7
+
+For each flow-type, the programmed filters must all have the same matching
+input set. For example, issuing the following two commands is acceptable:
+  ethtool -U enp130s0 flow-type ip4 src-ip 192.168.0.1 src-port 5300 action 7
+  ethtool -U enp130s0 flow-type ip4 src-ip 192.168.0.5 src-port 55 action 10
+Issuing the next two commands, however, is not acceptable, since the first
+specifies scr-ip and the second specifies dst-ip:
+  ethtool -U enp130s0 flow-type ip4 src-ip 192.168.0.1 src-port 5300 action 7
+  ethtool -U enp130s0 flow-type ip4 dst-ip 192.168.0.5 src-port 55 action 10
+The second command will fail with an error. You may program multiple filters
+with the same fields, using different values, but, on one device, you may not
+program two tcp4 filters with different matching fields.
+
+Matching on a sub-portion of a field is not supported by the i40e driver,
+thus partial mask fields are not supported.
+
+The driver also supports matching user-defined data within the packet payload.
+This flexible data is specified using the "user-def" field of the ethtool
+command in the following way:
++----------------------------+--------------------------+
+| 31    28    24    20    16 | 15    12    8    4    0  |
++----------------------------+--------------------------+
+| offset into packet payload | 2 bytes of flexible data |
++----------------------------+--------------------------+
+
+For example,
+  ... user-def 0x4FFFF ...
+
+tells the filter to look 4 bytes into the payload and match that value against
+0xFFFF. The offset is based on the beginning of the payload, and not the
+beginning of the packet. Thus
+
+  flow-type tcp4 ... user-def 0x8BEAF ...
+
+would match TCP/IPv4 packets which have the value 0xBEAF 8 bytes into the TCP/IPv4 payload.
+
+Note that ICMP headers are parsed as 4 bytes of header and 4 bytes of payload.
+Thus to match the first byte of the payload, you must actually add 4 bytes
+to the offset. Also note that ip4 filters match both ICMP frames as well as
+raw (unknown) ip4 frames, where the payload will be the L3 payload of the
+IP4 frame.
+
+The maximum offset is 64. The hardware will only read up to 64 bytes of data
+from the payload. The offset must be even because the flexible data is 2 bytes
+long and must be aligned to byte 0 of the packet payload.
+
+The user-defined flexible offset is also considered part of the input set and
+cannot be programmed separately for multiple filters of the same type. However,
+the flexible data is not part of the input set and multiple filters may use the
+same offset but match against different data.
+
+To create filters that direct traffic to a specific Virtual Function, use the
+?action" parameter. Specify the action as a 64 bit value, where the lower 32
+bits represents the queue number, while the next 8 bits represent which VF.
+Note that 0 is the PF, so the VF identifier is offset by 1. For example:
+
+  ... action 0x800000002 ...
+
+specifies to direct traffic to Virtual Function 7 (8 minus 1) into queue 2 of
+that VF.
+
+Note that these filters will not break internal routing rules, and will not
+route traffic that otherwise would not have been sent to the specified Virtual
+Function.
 
 
 Cloud Filter Support
@@ -501,7 +544,7 @@ NOTES:
   - The "action -1" option, which drops matching packets in regular Flow
     Director filters, is not available to drop packets when used with 
     cloud filters.
-  - For IPv4 and ether flow-types, cloud filters cannot be used for TCP?or
+  - For IPv4 and ether flow-types, cloud filters cannot be used for TCP or
     UDP filters.
   - Cloud filters can be used as a method for implementing queue splitting in
     the PF.
@@ -520,44 +563,45 @@ The following filters are supported:
   L3 filters
     Application Destination IP
 
-Use ethtool's flow director and user defined (user-def) options to define
-cloud filters for tunneled packets (VF) and L3 filters for non-tunneled
-packets (PF or VF). In this case, the user-def field specifies that a cloud
-filter is being programmed instead of a Flow Director filter. Note that this
-is not the same as setting filters using a user-defined pattern and offset,
-which requires using the mask ('m') parameter in conjunction with the user-def
-field (see the Intel Ethernet Flow Director section in this document).
+Cloud filters are specified using ethtool's ntuple interface, but the driver
+uses user-def to determine whether to treat the filter as a cloud filter or a
+regular filter. To enable a cloud filter, set the highest bit of the user-def
+field, "user-def 0x8000000000000000" to enable the cloud features described
+below. This specifies to the driver to treat the filter specially and not treat
+it like the regular filters described above. Note that cloud filters also read
+the other bits in the user-def field separately so you cannot use the flexible
+data feature described above.
 
 For regular Flow Director filters:
 
-  - No user-def specified or upper 32 bits of user-def is all 0s
+  - No user-def specified or highest bit (bit 63) is 0
 
   Example:
 
-    ethtool -N p258p1 flow-type ip4 src-ip 192.168.1.108 dst-ip 192.168.1.109 /
-    action 6 loc 3
+    ethtool -U enp130s0 flow-type ip4 src-ip 192.168.0.1 dst-ip 192.168.0.109
+    action 6 loc
 
 For L3 filters (non-tunneled packets):
 
-  - "user-def 0xffffffff00000002" (no Tenant ID/VNI specified in the upper
-    32 bits of the user-def field and send to VF id 2)
+  - "user-def 0x8000000000000000" (no Tenant ID/VNI specified in remaining
+    bits of the user-def field)
   - Only L3 parameters (src-IP, dst-IP) are considered
 
   Example:
 
-    ethtool -N p4p2 flow-type ip4 src-ip 192.168.42.13 dst-ip 192.168.42.33 /
-    src-port 12344 dst-port 12344 user-def 0xffffffff00000001 loc 3
+    ethtool -U enp130s0 flow-type ip4 src-ip 192.168.42.13 dst-ip 192.168.42.33 /
+    src-port 12344 dst-port 12344 user-def 0x8000000000000000 action /
+    0x200000000 loc 3
       Redirect traffic coming from 192.168.42.13 port 12344 with destination
-      192.168.42.33 port 12344 into VF id 1, and call this ?rule 3?
+      192.168.42.33 port 12344 into VF id 1, and call this "rule 3"
 
 For cloud filters (tunneled packets):
 
   - All other filters, including where Tenant ID/VNI is specified.
-  - The upper 32 bits of the user def field can carry the tenant ID/VNI
-    if specified or required.
-  - The lower 32 bits of the 'user-def' field can be used to specify the
-    VF ID. If the ID is greater than the maximum number of VFs currently
-    enabled then the ID will default back to the main VSI.
+  - The lower 32 bits of the user-def field can carry the tenant ID/VNI
+    if required.
+  - The VF can be specified using the "action" field, just as regular filters
+    described in the Flow director Filter section above.
   - Cloud filters can be defined with inner MAC, outer MAC, inner IP address,
      inner VLAN, and VNI as part of the cloud tuple. Cloud filters filter on
     destination (not source) MAC and IP. The destination and source MAC
@@ -568,22 +612,12 @@ For cloud filters (tunneled packets):
 
   Example:
 
-    ethtool -N p4p2 flow-type ip4 src-ip 192.168.42.13 dst-ip 192.168.42.33 /
-    src-port 12344 dst-port 12344 user-def 0x0000000001 loc 38
+    ethtool -U enp130s0 flow-type ip4 src-ip 192.168.42.13 dst-ip 192.168.42.33 /
+    src-port 12344 dst-port 12344 user-def 0x8000000000000022 loc 38 action /
+    0x200000000
       Redirect traffic on VXLAN using tunnel id 34 (hex 0x22) coming from
       192.168.42.13 port 12344 with destination 192.168.42.33 port 12344 into
       VF id 1, and call this "rule 38"
-      NOTE: If the VF id given is larger than the number of active VFs (e.g.
-      if you set num_vfs to 8 and use VF id 12 in the ethtool command) the
-      traffic will be redirected to the PF rather than to the VF.
-
-To see the list of filters currently present:
-    ethtool <-u|-n> ethX
-      NOTE: For cloud filters in which the specified VF is greater than
-      the number of VFs supported, the cloud filter will send traffic
-      to the PF. However, the driver does not store the specified VF
-      number, so in this case the ethtool -n command will display
-      0xffff for the VF number.
 
 
 ================================================================================
@@ -626,6 +660,9 @@ Use the ifconfig command to increase the MTU size. For example, enter the
 following where <x> is the interface number:
 
    ifconfig eth<x> mtu 9000 up
+Alternatively, you can use the ip command as follows:
+   ip link set mtu 9000 dev eth<x>
+   ip link set up dev eth<x>
 
 This setting is not saved across reboots. The setting change can be made
 permanent by adding 'MTU=9000' to the file:
@@ -635,7 +672,7 @@ permanent by adding 'MTU=9000' to the file:
 
 
 NOTES:
-- The maximum MTU setting for Jumbo Frames is 9706. This value coincides
+- The maximum MTU setting for Jumbo Frames is 9702. This value coincides
   with the maximum Jumbo Frames size of 9728 bytes.
 - This driver will attempt to use multiple page sized buffers to receive
   each jumbo packet. This should help to avoid buffer starvation issues
@@ -736,7 +773,7 @@ Flow Control is disabled by default.
 Use ethtool to change the flow control settings.
 
 ethtool:
-ethtool -A eth? autoneg off rx on tx on
+ethtool -s eth? autoneg off rx on tx on
 
 
 
@@ -826,61 +863,6 @@ consume 100% of a port's bandwidth (should it be available). The sum of
 all the values for Maximum Bandwidth is not restricted, because no more than
 100% of a port's bandwidth can ever be used.
 
-Once the initial configuration is complete, you can set different
-bandwidth allocations on each function as follows:
-1. Make a new directory named /config
-2. edit etc/fstab to include:
-
-       configfs /config configfs defaults
-
-3. Mount /config
-4. Load (or reload) the i40e driver
-5. Make a new directory under config/i40e for each partition upon which you
-   wish to configure the bandwidth.
-6. The following files will appear under the config/partition directory:
-   - max_bw
-   - min_bw
-   - commit
-   - ports
-   - partitions
-   read from max_bw to get display the current maximum bandwidth setting.
-   write to max_bw to set the maximum bandwidth for this function.
-   read from min_bw to display the current minimum bandwidth setting.
-   Write to min_bw to set the minimum bandwidth for this function.
-   Write a '1' to commit to save your changes.
-
-Notes: -commit is write only. Attempting to read it will result in an
-        error.
-       -Writing to commit is only supported on the first function of
-        a given port. Writing to a subsequent function will result in an
-        error.
-       -Oversubscribing the minimum bandwidth is not supported. The underlying
-        device's NVM will set the minimum bandwidth to supported values in an
-        indeterminate manner. Remove all of the directories under config and
-        reload them to see what the actual values are.
-       -To unload the driver you must first remove the directories created in
-        step 5, above.
-
-Example of Setting the minimum and maximum bandwidth (assume there are four
-function on the port eth6-eth9, and that eth6 is the first function on
-the port):
-
- # mkdir /config/eth6
- # mkdir /config/eth7
- # mkdir /config/eth8
- # mkdir /config/eth9
-
- # echo 50 > /config/eth6/min_bw
- # echo 100 > /config/eth6/max_bw
- # echo 20 > /config/eth7/min_bw
- # echo 100 > /config/eth7/max_bw
- # echo 20 > /config/eth8/min_bw
- # echo 100 > /config/eth8/max_bw
- # echo 10 > /config/eth9/min_bw
- # echo 25 > /config/eth9/max_bw
-
- # echo 1 > /config/eth6/commit
-
 
 Data Center Bridging (DCB)
 --------------------------
@@ -938,6 +920,11 @@ Driver defaults are meant to fit a wide variety of workloads, but if further
 optimization is required we recommend experimenting with the following
 settings.
 
+NOTE: For better performance when processing small (64B) frame sizes,
+try enabling Hyper threading in the BIOS in order to increase the number
+of logical cores in the system and subsequently increase the number of
+queues available to the adapter.
+
 Virtualized Environments:
 
 1. Disable XPS on both ends by using the included virt_perf_default script
@@ -1003,6 +990,47 @@ Known Issues/Troubleshooting
 ----------------------------
 
 
+ip link show command shows incorrect VF MAC if VF MAC was set from VF side
+--------------------------------------------------------------------------
+
+Executing the command "ip link show" only shows MAC addresses if they
+are set by the PF. Otherwise, it shows all zeros.
+
+This is expected behavior. The PF driver is passing zeroes to the VF
+driver that the VF driver can generate its own random MAC address and report
+it to the guest OS. Without this feature, some guest operating systems
+will incorrectly assign the VF a new interface name each time they reboot.
+
+
+SSL error (No such file) when installing driver on Ubuntu 14.04
+---------------------------------------------------------------
+When installing the driver on Ubuntu 14.04, you may get an SSL error stating
+"no such file or directory." This issue does not affect driver installation
+or performance and can be ignored.
+
+
+IPv6/UDP checksum offload does not work on some older kernels
+-------------------------------------------------------------
+Some distributions with older kernels do not properly enable IPv6/UDP
+checksum offload. To use IPv6 checksum offload, it may be necessary to
+upgrade to a newer kernel.
+
+
+Poor performance when using VXLAN encapsulation
+-----------------------------------------------
+When using VXLAN encapsulation on Red Hat Enterprise Linux 7.2 and 7.3,
+you may experience poor performance due to limitations in the kernel on
+these OS releases. To resolve this issue, upgrade your kernel.
+
+
+Driver Buffer Overflow Fix
+--------------------------
+
+The fix to resolve CVE-2016-8105, referenced in Intel SA-00069
+https://security-center.intel.com/advisory.aspx?intelid=INTEL-SA-00069
+&languageid=en-fr, is included in this and future versions of the driver.
+
+
 depmod warning messages about unknown symbol during installation
 ----------------------------------------------------------------
 
@@ -1177,22 +1205,13 @@ appears to be the only remedy.
 Rx Page Allocation Errors
 -------------------------
 
-'Page allocation failure. order:0' errors may occur under stress with kernels
-2.6.25 and newer. This is caused by the way the Linux kernel reports this
+'Page allocation failure. order:0' errors may occur under stress.
+with kernels 2.6.25 and newer.
+This is caused by the way the Linux kernel reports this
 stressed condition.
 
 
 
-Disable GRO when routing/bridging
----------------------------------
-
-Due to a known kernel issue, GRO must be turned off when routing/bridging. GRO
-can be turned off via ethtool.
-ethtool -K ethX gro off
-
-where ethX is the ethernet interface being modified.
-
-
 Lower than expected performance
 -------------------------------
 
@@ -1236,15 +1255,21 @@ Intel XL710-based controllers.
 Unable to obtain DHCP lease on boot with RedHat
 -----------------------------------------------
 
-For configurations where the auto-negotiation process takes more than 5
+In configurations where the auto-negotiation process takes more than 5
 seconds, the boot script may fail with the following message:
 "ethX: failed. No link present. Check cable?"
 
-If this error appears even though the presence of a link can be confirmed
-using ethtool ethX, try setting "LINKDELAY=5" in
-/etc/sysconfig/network-scripts/ifcfg-ethX.
+This error may occur even though the presence of link can be confirmed using
+ethtool ethx. In this case, try setting "LINKDELAY=30" in
+/etc/sysconfig/network-scripts/ifdfg-ethx.
+
+The same issue can occur during a network boot (via PXE) on RedHat
+distributions that use the dracut script:
+"Warning: No carrier detected on interface <interface_name>"
 
-NOTE: Link time can take up to 30 seconds. Adjust LINKDELAY value accordingly.
+In this case add "rd.net.timeout.carrier=30" at the kernel command line.
+
+NOTE: Link time can vary. Adjust LINKDELAY value accordingly.
 
 Alternatively, NetworkManager can be used to configure the interfaces, which
 avoids the set timeout. For configuration instructions of NetworkManager
@@ -1296,16 +1321,15 @@ St - Fifth Floor, Boston, MA 02110-1301 USA.
 The full GNU General Public License is included in this distribution in the
 file called "COPYING".
 
-Copyright(c) 2014-2016 Intel Corporation.
+Copyright(c) 2014-2017 Intel Corporation.
 ================================================================================
 
 
-
 Trademarks
 ----------
 
-Intel, Itanium, and Pentium are trademarks or registered trademarks of Intel
-Corporation or its subsidiaries in the United States and other countries.
+Intel and Itanium are trademarks or registered trademarks of Intel
+Corporation or its subsidiaries in the United States and/or other countries.
 
 * Other names and brands may be claimed as the property of others.
 
diff --git a/i40e-dkms/i40e-2.1.26/SUMS b/i40e-dkms/i40e-2.1.26/SUMS
new file mode 100644 (file)
index 0000000..0bc6b87
--- /dev/null
@@ -0,0 +1,48 @@
+23200     3 i40e-2.1.26/i40e.7
+41054    52 i40e-2.1.26/README
+42709     7 i40e-2.1.26/pci.updates
+23863    11 i40e-2.1.26/i40e.spec
+43521    19 i40e-2.1.26/COPYING
+11661   364 i40e-2.1.26/src/i40e_register.h
+36073     9 i40e-2.1.26/src/i40e_dcb_nl.c
+00545    82 i40e-2.1.26/src/i40e_adminq_cmd.h
+39134    46 i40e-2.1.26/src/i40e_nvm.c
+27049    47 i40e-2.1.26/src/i40e_type.h
+28147    22 i40e-2.1.26/src/i40e_prototype.h
+62648    57 i40e-2.1.26/src/kcompat.c
+58605     4 i40e-2.1.26/src/i40e_status.h
+38420   189 i40e-2.1.26/src/i40e_common.c
+25757     6 i40e-2.1.26/src/i40e_lan_hmc.h
+25014     2 i40e-2.1.26/src/i40e_diag.h
+25701     4 i40e-2.1.26/src/i40e_helper.h
+56270     8 i40e-2.1.26/src/i40e_hmc.h
+43670    23 i40e-2.1.26/src/i40e_client.c
+02605   177 i40e-2.1.26/src/i40e_ethtool.c
+35141     7 i40e-2.1.26/src/i40e_trace.h
+27367    30 i40e-2.1.26/src/i40e_adminq.c
+24070     2 i40e-2.1.26/src/i40e_devids.h
+13309     5 i40e-2.1.26/src/i40e_diag.c
+58300    36 i40e-2.1.26/src/i40e.h
+14892    19 i40e-2.1.26/src/i40e_txrx.h
+15513    23 i40e-2.1.26/src/virtchnl.h
+25383    27 i40e-2.1.26/src/i40e_ptp.c
+60199    35 i40e-2.1.26/src/i40e_lan_hmc.c
+22894    27 i40e-2.1.26/src/i40e_dcb.c
+64920   168 i40e-2.1.26/src/kcompat.h
+18552   366 i40e-2.1.26/src/i40e_main.c
+12661     7 i40e-2.1.26/src/i40e_client.h
+06581     6 i40e-2.1.26/src/Makefile
+38484     4 i40e-2.1.26/src/i40e_osdep.h
+03889     3 i40e-2.1.26/src/i40e_alloc.h
+27559    80 i40e-2.1.26/src/i40e_debugfs.c
+44588     1 i40e-2.1.26/src/Module.supported
+22387     6 i40e-2.1.26/src/i40e_virtchnl_pf.h
+58955     5 i40e-2.1.26/src/i40e_adminq.h
+28000    12 i40e-2.1.26/src/common.mk
+60958    93 i40e-2.1.26/src/i40e_virtchnl_pf.c
+32557   101 i40e-2.1.26/src/i40e_txrx.c
+12466     6 i40e-2.1.26/src/i40e_dcb.h
+03386    11 i40e-2.1.26/src/i40e_hmc.c
+33977     7 i40e-2.1.26/scripts/set_irq_affinity
+20875     2 i40e-2.1.26/scripts/dump_tables
+49876     5 i40e-2.1.26/scripts/virt_perf_default
similarity index 91%
rename from i40e-dkms/i40e-1.6.42/i40e.7
rename to i40e-dkms/i40e-2.1.26/i40e.7
index 50d2a86ab402a019a60d01f557ee69e69a0f50ee..2205b7e815f9649cf83fce77ab57ac7a92b1b69c 100644 (file)
@@ -5,7 +5,7 @@
 .\" * Other names and brands may be claimed as the property of others.
 .\"
 .
-.TH i40e 1 "December 10, 2015"
+.TH i40e 1 "May 3, 2017"
 .SH NAME
 i40e \-This file describes the Linux* Base Driver
 for the Intel Ethernet Controller XL710 Family of Controllers.
@@ -37,10 +37,13 @@ Use the ifconfig command to increase the MTU size. For example, enter the
 following where <x> is the interface number:
 
    ifconfig eth<x> mtu 9000 up
+Alternatively, you can use the ip command as follows:
+   ip link set mtu 9000 dev eth<x>
+   ip link set up dev eth<x>
 
 .LP
 NOTES:
-- The maximum MTU setting for Jumbo Frames is 9706. This value coincides
+- The maximum MTU setting for Jumbo Frames is 9702. This value coincides
   with the maximum Jumbo Frames size of 9728 bytes.
 - This driver will attempt to use multiple page sized buffers to receive
   each jumbo packet. This should help to avoid buffer starvation issues
similarity index 99%
rename from i40e-dkms/i40e-1.6.42/i40e.spec
rename to i40e-dkms/i40e-2.1.26/i40e.spec
index ce974b6744e922009c3450f30c27a64d60344b9e..e043254b336729bf2601309d0d7235848133fa6b 100644 (file)
@@ -1,6 +1,6 @@
 Name: i40e
 Summary: Intel(R) 40-10 Gigabit Ethernet Connection Network Driver
-Version: 1.6.42
+Version: 2.1.26
 Release: 1
 Source: %{name}-%{version}.tar.gz
 Vendor: Intel Corporation
similarity index 93%
rename from i40e-dkms/i40e-1.6.42/pci.updates
rename to i40e-dkms/i40e-2.1.26/pci.updates
index c2f8c06fed1b6c584b83b9572aaa3d6350e7b9e1..5e178aa718bc4cc4c81096c511fcec578c60b67a 100644 (file)
                8086 000a  Ethernet Controller X710 for 10GbE SFP+
                8086 000b  Ethernet Server Adapter X710-DA2 for OCP
                8086 000d  Ethernet Controller X710 for 10GbE SFP+
+               8086 000e  Ethernet Server Adapter OCP X710-2
                8086 4005  Ethernet Controller X710 for 10GbE SFP+
                8086 4006  Ethernet Controller X710 for 10GbE SFP+
+               8086 4007  Ethernet Controller X710 for 10GbE SFP+
        1574  Ethernet Controller XL710 Emulation
        1580  Ethernet Controller XL710 for 40GbE backplane
        1581  Ethernet Controller X710 for 10GbE backplane
                8086 0001  Ethernet Converged Network Adapter X710-T4
                8086 0002  Ethernet Converged Network Adapter X710-T4
                8086 0003  Ethernet Converged Network Adapter X710-T
-               8086 00A0  Ethernet Converged Network Adapter X710-T4
+               8086 00a0  Ethernet Converged Network Adapter X710-T4
        158a  Ethernet Controller XXV710 for 25GbE backplane
+               8086 0000  Ethernet Controller XXV710 for 25GbE backplane
+               8086 000a  Ethernet 25G 2P XXV710 Mezz
        158b  Ethernet Controller XXV710 for 25GbE SFP28
                8086 0000  Ethernet Network Adapter XXV710
                8086 0001  Ethernet Network Adapter XXV710-2
                8086 0004  Ethernet Network Adapter XXV710-1
                8086 0007  Ethernet Network Adapter OCP XXV710-1
                8086 0008  Ethernet Network Adapter OCP XXV710-1
+               8086 0009  Ethernet 25G 2P XXV710 Adapter
+               8086 4001  Ethernet Network Adapter XXV710-2
        37ce  Ethernet Connection X722 for 10GbE backplane
                1590 0215  Ethernet 10Gb 2-port 568i Adapter
                17aa 4023  Ethernet Connection X722 for 10GbE backplane
        37cf  Ethernet Connection X722 for 10GbE QSFP+
        37d0  Ethernet Connection X722 for 10GbE SFP+
-               17aa 4020  Ethernet Connection X722 for 10GbE SFP+
-               17aa 4021  Ethernet Connection X722 for 10GbE SFP+
-               17aa 4022  Ethernet Connection X722 for 10GbE SFP+
        37d1  Ethernet Connection X722 for 1GbE
                1590 0216  Ethernet 1Gb 2-port 368i Adapter
                1590 0217  Ethernet 1Gb 2-port 368FLR-MMT Adapter
+               1590 0247  Ethernet 1Gb 4-port 369i Adapter
                17aa 4020  Ethernet Connection X722 for 1GbE
                17aa 4021  Ethernet Connection X722 for 1GbE
+               17aa 4022  Ethernet Connection X722 for 1GbE
        37d2  Ethernet Connection X722 for 10GBASE-T
                1590 0218  Ethernet 10Gb 2-port 568FLR-MMT Adapter
-               1590 0219  Ethernet 10Gb 2-port 568FLR-MMSFP+ Adapter
                17aa 4020  Ethernet Connection X722 for 10GBASE-T
                17aa 4021  Ethernet Connection X722 for 10GBASE-T
-               17aa 4022  Ethernet Connection X722 for 10GBASE-T
        37d3  Ethernet Connection X722 for 10GbE SFP+
+               1590 0219  Ethernet 10Gb 2-port 568FLR-MMSFP+ Adapter
+               17aa 4020  Ethernet Connection X722 for 10GbE SFP+
+               17aa 4021  Ethernet Connection X722 for 10GbE SFP+
similarity index 98%
rename from i40e-dkms/i40e-1.6.42/src/Makefile
rename to i40e-dkms/i40e-2.1.26/src/Makefile
index a190706bd2a8db8be89c70aea5a561a04c733ef1..f653b7140ca8a9266c898d3ff251daec29ca0d85 100644 (file)
@@ -27,6 +27,9 @@ ifneq ($(KERNELRELEASE),)
 # Makefile for the Intel(R) 40-10 Gigabit Ethernet Connection Network Driver
 #
 
+ccflags-y += -I$(src)
+subdir-ccflags-y += -I$(src)
+
 obj-$(CONFIG_I40E) += i40e.o
 
 i40e-y := i40e_main.o \
@@ -40,10 +43,10 @@ i40e-y := i40e_main.o \
        i40e_diag.o \
        i40e_txrx.o \
        i40e_ptp.o \
+       i40e_client.o \
        i40e_virtchnl_pf.o
 
 i40e-$(CONFIG_DCB) += i40e_dcb.o i40e_dcb_nl.o
-i40e-$(CONFIG_FCOE:m=y) += i40e_fcoe.o
 i40e-y += kcompat.o
 
 else   # ifneq($(KERNELRELEASE),)
similarity index 98%
rename from i40e-dkms/i40e-1.6.42/src/common.mk
rename to i40e-dkms/i40e-2.1.26/src/common.mk
index 0a4ec77d2b2573e571a4f6e39fa0e28a1b8730ab..87c13db7dd012c49872623a2384bf37ceba13b2e 100644 (file)
@@ -276,8 +276,8 @@ endif
 # KBUILD_OUTPUT #
 #################
 
-# Only set KBUILD_OUTPUT if KOBJ differs from KSRC
-ifneq (${KSRC},${KOBJ})
+# Only set KBUILD_OUTPUT if the real paths of KOBJ and KSRC differ
+ifneq ($(call readlink,${KSRC}),$(call readlink,${KOBJ}))
 export KBUILD_OUTPUT ?= ${KOBJ}
 endif
 
similarity index 77%
rename from i40e-dkms/i40e-1.6.42/src/i40e.h
rename to i40e-dkms/i40e-2.1.26/src/i40e.h
index 81119bce4f522da85abe8ca1f0863ee64bc11a9e..3b9b11c926038d7aba58d0c4b1858032b94e2e5d 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/string.h>
 #include <linux/in.h>
 #include <linux/ip.h>
+#include <linux/sctp.h>
 #include <linux/pkt_sched.h>
 #include <linux/ipv6.h>
 #include <net/checksum.h>
 #endif /* HAVE_PTP_1588_CLOCK */
 #include "i40e_type.h"
 #include "i40e_prototype.h"
-#ifdef I40E_FCOE
-#include "i40e_fcoe.h"
-#endif
-#include "i40e_virtchnl.h"
+#include "i40e_client.h"
+#include "virtchnl.h"
 #include "i40e_virtchnl_pf.h"
 #include "i40e_txrx.h"
 #include "i40e_dcb.h"
 
 /* Useful i40e defaults */
-#define I40E_MAX_VEB           16
+#define I40E_MAX_VEB                   16
 
 #define I40E_MAX_NUM_DESCRIPTORS       4096
 #define I40E_MAX_CSR_SPACE             (4 * 1024 * 1024 - 64 * 1024)
 #define I40E_MIN_VSI_ALLOC             83 /* LAN, ATR, FCOE, 64 VF, 16 VMDQ */
 /* max 16 qps */
 #define i40e_default_queues_per_vmdq(pf) \
-               (((pf)->flags & I40E_FLAG_RSS_AQ_CAPABLE) ? 4 : 1)
+               (((pf)->hw_features & I40E_HW_RSS_AQ_CAPABLE) ? 4 : 1)
 #define I40E_DEFAULT_QUEUES_PER_VF     4
+#define I40E_MAX_VF_QUEUES             16
 #define I40E_DEFAULT_QUEUES_PER_TC     1 /* should be a power of 2 */
 #define i40e_pf_get_max_q_per_tc(pf) \
-               (((pf)->flags & I40E_FLAG_128_QP_RSS_CAPABLE) ? 128 : 64)
+               (((pf)->hw_features & I40E_HW_128_QP_RSS_CAPABLE) ? 128 : 64)
 #define I40E_FDIR_RING                 0
 #define I40E_FDIR_RING_COUNT           32
-#ifdef I40E_FCOE
-#define I40E_DEFAULT_FCOE              8 /* default number of QPs for FCoE */
-#define I40E_MINIMUM_FCOE              1 /* minimum number of QPs for FCoE */
-#endif /* I40E_FCOE */
 #define I40E_MAX_AQ_BUF_SIZE           4096
 #define I40E_AQ_LEN                    256
 #define I40E_AQ_WORK_LIMIT             66 /* max number of VFs + a little */
 #define I40E_QUEUE_WAIT_RETRY_LIMIT    10
 #define I40E_INT_NAME_STR_LEN          (IFNAMSIZ + 16)
 
-#ifdef HAVE_ETHTOOL_GET_SSET_COUNT
-/* Ethtool Private Flags */
-#define I40E_PRIV_FLAGS_MFP_FLAG               BIT(0)
-#define I40E_PRIV_FLAGS_LINKPOLL_FLAG          BIT(1)
-#define I40E_PRIV_FLAGS_FD_ATR                 BIT(2)
-#define I40E_PRIV_FLAGS_VEB_STATS              BIT(3)
-#define I40E_PRIV_FLAGS_HW_ATR_EVICT           BIT(4)
-#define I40E_PRIV_FLAGS_TRUE_PROMISC_SUPPORT   BIT(5)
-#endif
-
 #define I40E_NVM_VERSION_LO_SHIFT      0
 #define I40E_NVM_VERSION_LO_MASK       (0xff << I40E_NVM_VERSION_LO_SHIFT)
 #define I40E_NVM_VERSION_HI_SHIFT      12
        (I40E_AQ_PHY_DEBUG_DISABLE_LINK_FW | \
        I40E_AQ_PHY_DEBUG_DISABLE_ALL_LINK_FW)
 
+#define I40E_OEM_EETRACK_ID            0xffffffff
+#define I40E_OEM_GEN_SHIFT             24
+#define I40E_OEM_SNAP_MASK             0x00ff0000
+#define I40E_OEM_SNAP_SHIFT            16
+#define I40E_OEM_RELEASE_MASK          0x0000ffff
+
 /* The values in here are decimal coded as hex as is the case in the NVM map*/
 #define I40E_CURRENT_NVM_VERSION_HI    0x2
 #define I40E_CURRENT_NVM_VERSION_LO    0x40
 
-#define I40E_RX_DESC(R, i)             \
+#define I40E_RX_DESC(R, i)     \
        (&(((union i40e_32byte_rx_desc *)((R)->desc))[i]))
-#define I40E_TX_DESC(R, i)             \
+#define I40E_TX_DESC(R, i)     \
        (&(((struct i40e_tx_desc *)((R)->desc))[i]))
-#define I40E_TX_CTXTDESC(R, i)         \
+#define I40E_TX_CTXTDESC(R, i) \
        (&(((struct i40e_tx_context_desc *)((R)->desc))[i]))
-#define I40E_TX_FDIRDESC(R, i)         \
+#define I40E_TX_FDIRDESC(R, i) \
        (&(((struct i40e_filter_program_desc *)((R)->desc))[i]))
 
 /* default to trying for four seconds */
@@ -152,12 +144,12 @@ enum i40e_state_t {
        __I40E_CONFIG_BUSY,
        __I40E_CONFIG_DONE,
        __I40E_DOWN,
-       __I40E_NEEDS_RESTART,
        __I40E_SERVICE_SCHED,
        __I40E_ADMINQ_EVENT_PENDING,
        __I40E_MDD_EVENT_PENDING,
        __I40E_VFLR_EVENT_PENDING,
        __I40E_RESET_RECOVERY_PENDING,
+       __I40E_MISC_IRQ_REQUESTED,
        __I40E_RESET_INTR_RECEIVED,
        __I40E_REINIT_REQUESTED,
        __I40E_PF_RESET_REQUESTED,
@@ -165,16 +157,29 @@ enum i40e_state_t {
        __I40E_GLOBAL_RESET_REQUESTED,
        __I40E_EMP_RESET_REQUESTED,
        __I40E_EMP_RESET_INTR_RECEIVED,
-       __I40E_FILTER_OVERFLOW_PROMISC,
        __I40E_SUSPENDED,
        __I40E_BAD_EEPROM,
        __I40E_DEBUG_MODE,
        __I40E_DOWN_REQUESTED,
        __I40E_FD_FLUSH_REQUESTED,
        __I40E_RESET_FAILED,
-       __I40E_PORT_TX_SUSPENDED,
+       __I40E_PORT_SUSPENDED,
        __I40E_PTP_TX_IN_PROGRESS,
        __I40E_VF_DISABLE,
+       /* This must be last as it determines the size of the BITMAP */
+       __I40E_STATE_SIZE__,
+};
+
+/* VSI state flags */
+enum i40e_vsi_state_t {
+       __I40E_VSI_DOWN,
+       __I40E_VSI_NEEDS_RESTART,
+       __I40E_VSI_SYNCING_FILTERS,
+       __I40E_VSI_OVERFLOW_PROMISC,
+       __I40E_VSI_REINIT_REQUESTED,
+       __I40E_VSI_DOWN_REQUESTED,
+       /* This must be last as it determines the size of the BITMAP */
+       __I40E_VSI_STATE_SIZE__,
 };
 
 enum i40e_interrupt_policy {
@@ -188,12 +193,13 @@ struct i40e_lump_tracking {
        u16 search_hint;
        u16 list[0];
 #define I40E_PILE_VALID_BIT  0x8000
+#define I40E_IWARP_IRQ_PILE_ID  (I40E_PILE_VALID_BIT - 2)
 };
 
 #define I40E_DEFAULT_ATR_SAMPLE_RATE   20
 #define I40E_FDIR_MAX_RAW_PACKET_SIZE  512
-#define I40E_MAX_PARSE_BYTE            480
 #define I40E_TCPIP_DUMMY_PACKET_LEN    54
+#define I40E_SCTPIP_DUMMY_PACKET_LEN   46
 #define I40E_UDPIP_DUMMY_PACKET_LEN    42
 #define I40E_IP_DUMMY_PACKET_LEN       34
 #define I40E_FDIR_BUFFER_FULL_MARGIN   10
@@ -218,25 +224,39 @@ enum i40e_fd_stat_idx {
 #define I40E_FD_ATR_TUNNEL_STAT_IDX(pf_id) \
                        (I40E_FD_STAT_PF_IDX(pf_id) + I40E_FD_STAT_ATR_TUNNEL)
 
+/* The following structure contains the data parsed from the user-defined
+ * field of the ethtool_rx_flow_spec structure.
+ */
+struct i40e_rx_flow_userdef {
+       bool cloud_filter;
+       bool tenant_id_valid;
+       u32 tenant_id;
+       bool tunnel_type_valid;
+       u8 tunnel_type;
+       bool flex_filter;
+       u16 flex_word;
+       u16 flex_offset;
+};
+
 struct i40e_fdir_filter {
        struct hlist_node fdir_node;
        /* filter input set */
        u8 flow_type;
        u8 ip4_proto;
        /* TX packet view of src and dst */
-       __be32 dst_ip[4];
-       __be32 src_ip[4];
+       __be32 dst_ip;
+       __be32 src_ip;
        __be16 src_port;
        __be16 dst_port;
        __be32 sctp_v_tag;
-#define I40E_MAX_FLEX_FILTER           8
-       __be16 flex_bytes[I40E_MAX_FLEX_FILTER];
-       __be16 flex_mask[I40E_MAX_FLEX_FILTER];
-       u64 flex_mask_bit;
+
+       /* Flexible data to match within the packet payload */
+       __be16 flex_word;
+       u16 flex_offset;
+       bool flex_filter;
 
        /* filter control */
        u16 q_index;
-       u8  flex_off;
        u8  pctype;
        u16 dest_vsi;
        u8  dest_ctl;
@@ -331,11 +351,56 @@ struct i40e_udp_port_config {
                                       I40E_PRTQF_FLX_PIT_FSIZE_MASK) >> \
                                       I40E_PRTQF_FLX_PIT_FSIZE_SHIFT)
 
+#define I40E_MAX_FLEX_SRC_OFFSET 0x1F
+
+/* macros related to GLQF_ORT */
+#define I40E_ORT_SET_IDX(idx)          (((idx) << \
+                                         I40E_GLQF_ORT_PIT_INDX_SHIFT) & \
+                                        I40E_GLQF_ORT_PIT_INDX_MASK)
+
+#define I40E_ORT_SET_COUNT(count)      (((count) << \
+                                         I40E_GLQF_ORT_FIELD_CNT_SHIFT) & \
+                                        I40E_GLQF_ORT_FIELD_CNT_MASK)
+
+#define I40E_ORT_SET_PAYLOAD(payload)  (((payload) << \
+                                         I40E_GLQF_ORT_FLX_PAYLOAD_SHIFT) & \
+                                        I40E_GLQF_ORT_FLX_PAYLOAD_MASK)
+
+#define I40E_ORT_PREP_VAL(idx, count, payload) (I40E_ORT_SET_IDX(idx) | \
+                                               I40E_ORT_SET_COUNT(count) | \
+                                               I40E_ORT_SET_PAYLOAD(payload))
+
+#define I40E_L3_GLQF_ORT_IDX           34
+#define I40E_L4_GLQF_ORT_IDX           35
+
+/* Flex PIT register index */
+#define I40E_FLEX_PIT_IDX_START_L2     0
+#define I40E_FLEX_PIT_IDX_START_L3     3
+#define I40E_FLEX_PIT_IDX_START_L4     6
+
+#define I40E_FLEX_PIT_TABLE_SIZE       3
+
+#define I40E_FLEX_DEST_UNUSED          63
+
+#define I40E_FLEX_INDEX_ENTRIES                8
+
+/* Flex MASK to disable all flexible entries */
+#define I40E_FLEX_INPUT_MASK   (I40E_FLEX_50_MASK | I40E_FLEX_51_MASK | \
+                                I40E_FLEX_52_MASK | I40E_FLEX_53_MASK | \
+                                I40E_FLEX_54_MASK | I40E_FLEX_55_MASK | \
+                                I40E_FLEX_56_MASK | I40E_FLEX_57_MASK)
+
+struct i40e_flex_pit {
+       struct list_head list;
+       u16 src_offset;
+       u8 pit_index;
+};
+
 /* struct that defines the Ethernet device */
 struct i40e_pf {
        struct pci_dev *pdev;
        struct i40e_hw hw;
-       unsigned long state;
+       DECLARE_BITMAP(state, __I40E_STATE_SIZE__);
        struct msix_entry *msix_entries;
        bool fc_autoneg_status;
 
@@ -345,12 +410,11 @@ struct i40e_pf {
        u16 num_vmdq_msix;         /* num queue vectors per vmdq pool */
        u16 num_req_vfs;           /* num VFs requested for this VF */
        u16 num_vf_qps;            /* num queue pairs per VF */
-#ifdef I40E_FCOE
-       u16 num_fcoe_qps;          /* num fcoe queues this PF has set up */
-       u16 num_fcoe_msix;         /* num queue vectors per fcoe pool */
-#endif /* I40E_FCOE */
        u16 num_lan_qps;           /* num lan queues this PF has set up */
        u16 num_lan_msix;          /* num queue vectors for the base PF vsi */
+       u16 num_fdsb_msix;         /* num queue vectors for sideband Fdir */
+       u16 num_iwarp_msix;        /* num of iwarp vectors for this PF */
+       int iwarp_base_vector;
        int queues_left;           /* queues left unclaimed */
        u16 alloc_rss_size;        /* allocated RSS queues */
        u16 rss_size_max;          /* HW defined max RSS queues */
@@ -365,7 +429,6 @@ struct i40e_pf {
        u32 fd_flush_cnt;
        u32 fd_add_err;
        u32 fd_atr_cnt;
-       u32 fd_tcp_rule;
 
        /* Book-keeping of side-band filter count per flow-type.
         * This is used to detect and handle input set changes for
@@ -375,34 +438,14 @@ struct i40e_pf {
        u16 fd_udp4_filter_cnt;
        u16 fd_sctp4_filter_cnt;
        u16 fd_ip4_filter_cnt;
-       u16 fd_flex_filter_cnt;
-
-/* Destination word in field vector for flexible payload */
-#define I40E_FLEX_DEST_L4              50
-#define I40E_FLEX_DEST_L3              53
-#define I40E_FLEX_DEST_UNUSED          63
-
-/* Flex PIT register index */
-#define I40E_FLEX_PIT_IDX_START_L4     6
-#define I40E_FLEX_PIT_IDX_START_L3     3
-#define I40E_FLEX_PIT_IDX_START_L2     0
 
-/* GLQF ORT index based on L2/L3/L4 type and values */
-#define I40E_L4_GLQF_ORT_IDX           35
-#define I40E_L3_GLQF_ORT_IDX           34
-#define I40E_L2_GLQF_ORT_IDX           33
-#define I40E_L4_GLQF_ORT_VAL           0x000000E6UL
-#define I40E_L3_GLQF_ORT_VAL           0x000000E3UL
-#define I40E_L2_GLQF_ORT_VAL           0x000000E0UL
-
-/* Max number of flexible payload based flow supported */
-#define I40E_MAX_FLEX_FLOW             8
-#define I40E_MAX_FLEX_PIT_REG          9
-#define I40E_MAX_SRC_WORD_OFFSET       32
-       u64 fd_tcp4_input_set;
-       u64 fd_udp4_input_set;
-       u64 fd_sctp4_input_set;
-       u64 fd_ip4_input_set;
+       /* Flexible filter table values that need to be programmed into
+        * hardware, which expects L3 and L4 to be programmed separately. We
+        * need to ensure that the values are in ascended order and don't have
+        * duplicates, so we track each L3 and L4 values in separate lists.
+        */
+       struct list_head l3_flex_pit_list;
+       struct list_head l4_flex_pit_list;
 
        struct i40e_udp_port_config udp_ports[I40E_MAX_PF_UDP_OFFLOAD_PORTS];
        u16 pending_udp_bitmap;
@@ -420,69 +463,64 @@ struct i40e_pf {
        struct timer_list service_timer;
        struct work_struct service_task;
 
+       u64 hw_features;
+#define I40E_HW_RSS_AQ_CAPABLE                 BIT_ULL(0)
+#define I40E_HW_128_QP_RSS_CAPABLE             BIT_ULL(1)
+#define I40E_HW_ATR_EVICT_CAPABLE              BIT_ULL(2)
+#define I40E_HW_WB_ON_ITR_CAPABLE              BIT_ULL(3)
+#define I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE    BIT_ULL(4)
+#define I40E_HW_NO_PCI_LINK_CHECK              BIT_ULL(5)
+#define I40E_HW_100M_SGMII_CAPABLE             BIT_ULL(6)
+#define I40E_HW_NO_DCB_SUPPORT                 BIT_ULL(7)
+#define I40E_HW_USE_SET_LLDP_MIB               BIT_ULL(8)
+#define I40E_HW_GENEVE_OFFLOAD_CAPABLE         BIT_ULL(9)
+#define I40E_HW_PTP_L4_CAPABLE                 BIT_ULL(10)
+#define I40E_HW_WOL_MC_MAGIC_PKT_WAKE          BIT_ULL(11)
+#define I40E_HW_MPLS_HDR_OFFLOAD_CAPABLE       BIT_ULL(12)
+#define I40E_HW_HAVE_CRT_RETIMER               BIT_ULL(13)
+#define I40E_HW_OUTER_UDP_CSUM_CAPABLE         BIT_ULL(14)
+#define I40E_HW_PHY_CONTROLS_LEDS              BIT_ULL(15)
+#define I40E_HW_STOP_FW_LLDP                   BIT_ULL(16)
+#define I40E_HW_PORT_ID_VALID                  BIT_ULL(17)
+#define I40E_HW_RESTART_AUTONEG                        BIT_ULL(18)
+
        u64 flags;
-#define I40E_FLAG_RX_CSUM_ENABLED              BIT_ULL(1)
-#define I40E_FLAG_MSI_ENABLED                  BIT_ULL(2)
-#define I40E_FLAG_MSIX_ENABLED                 BIT_ULL(3)
-#define I40E_FLAG_RSS_ENABLED                  BIT_ULL(6)
-#define I40E_FLAG_VMDQ_ENABLED                 BIT_ULL(7)
-#define I40E_FLAG_FDIR_REQUIRES_REINIT         BIT_ULL(8)
-#define I40E_FLAG_NEED_LINK_UPDATE             BIT_ULL(9)
-#ifdef I40E_FCOE
-#define I40E_FLAG_FCOE_ENABLED                 BIT_ULL(11)
-#endif /* I40E_FCOE */
-#define I40E_FLAG_IN_NETPOLL                   BIT_ULL(12)
-#define I40E_FLAG_CLEAN_ADMINQ                 BIT_ULL(14)
-#define I40E_FLAG_FILTER_SYNC                  BIT_ULL(15)
-#define I40E_FLAG_PROCESS_MDD_EVENT            BIT_ULL(17)
-#define I40E_FLAG_PROCESS_VFLR_EVENT           BIT_ULL(18)
-#define I40E_FLAG_SRIOV_ENABLED                        BIT_ULL(19)
-#define I40E_FLAG_DCB_ENABLED                  BIT_ULL(20)
-#define I40E_FLAG_FD_SB_ENABLED                        BIT_ULL(21)
-#define I40E_FLAG_FD_ATR_ENABLED               BIT_ULL(22)
+#define I40E_FLAG_RX_CSUM_ENABLED              BIT_ULL(0)
+#define I40E_FLAG_MSI_ENABLED                  BIT_ULL(1)
+#define I40E_FLAG_MSIX_ENABLED                 BIT_ULL(2)
+#define I40E_FLAG_RSS_ENABLED                  BIT_ULL(3)
+#define I40E_FLAG_VMDQ_ENABLED                 BIT_ULL(4)
+#define I40E_FLAG_FILTER_SYNC                  BIT_ULL(5)
+#define I40E_FLAG_SRIOV_ENABLED                        BIT_ULL(6)
+#define I40E_FLAG_DCB_CAPABLE                  BIT_ULL(7)
+#define I40E_FLAG_DCB_ENABLED                  BIT_ULL(8)
+#define I40E_FLAG_FD_SB_ENABLED                        BIT_ULL(9)
+#define I40E_FLAG_FD_ATR_ENABLED               BIT_ULL(10)
+#define I40E_FLAG_FD_SB_AUTO_DISABLED          BIT_ULL(11)
+#define I40E_FLAG_FD_ATR_AUTO_DISABLED         BIT_ULL(12)
+#define I40E_FLAG_MFP_ENABLED                  BIT_ULL(13)
+#define I40E_FLAG_UDP_FILTER_SYNC              BIT_ULL(14)
+#define I40E_FLAG_HW_ATR_EVICT_ENABLED         BIT_ULL(15)
+#define I40E_FLAG_VEB_MODE_ENABLED             BIT_ULL(16)
+#define I40E_FLAG_VEB_STATS_ENABLED            BIT_ULL(17)
+#define I40E_FLAG_LINK_POLLING_ENABLED         BIT_ULL(18)
+#define I40E_FLAG_TRUE_PROMISC_SUPPORT         BIT_ULL(19)
+#define I40E_FLAG_TEMP_LINK_POLLING            BIT_ULL(20)
+#define I40E_FLAG_LEGACY_RX                    BIT_ULL(21)
 #ifdef HAVE_PTP_1588_CLOCK
-#define I40E_FLAG_PTP                          BIT_ULL(25)
+#define I40E_FLAG_PTP                          BIT_ULL(22)
 #endif /* HAVE_PTP_1588_CLOCK */
-#define I40E_FLAG_MFP_ENABLED                  BIT_ULL(26)
-#define I40E_FLAG_UDP_FILTER_SYNC              BIT_ULL(27)
-#define I40E_FLAG_PORT_ID_VALID                        BIT_ULL(28)
-#define I40E_FLAG_DCB_CAPABLE                  BIT_ULL(29)
-#define I40E_FLAG_RSS_AQ_CAPABLE               BIT_ULL(31)
-#define I40E_FLAG_HW_ATR_EVICT_CAPABLE         BIT_ULL(32)
-#define I40E_FLAG_OUTER_UDP_CSUM_CAPABLE       BIT_ULL(33)
-#define I40E_FLAG_128_QP_RSS_CAPABLE           BIT_ULL(34)
-#define I40E_FLAG_WB_ON_ITR_CAPABLE            BIT_ULL(35)
-#define I40E_FLAG_VEB_STATS_ENABLED            BIT_ULL(37)
-#define I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE  BIT_ULL(38)
-#define I40E_FLAG_LINK_POLLING_ENABLED         BIT_ULL(39)
-#define I40E_FLAG_VEB_MODE_ENABLED             BIT_ULL(40)
-#define I40E_FLAG_GENEVE_OFFLOAD_CAPABLE       BIT_ULL(41)
-#define I40E_FLAG_NO_PCI_LINK_CHECK            BIT_ULL(42)
-#define I40E_FLAG_100M_SGMII_CAPABLE           BIT_ULL(43)
-#define I40E_FLAG_RESTART_AUTONEG              BIT_ULL(44)
-#define I40E_FLAG_NO_DCB_SUPPORT               BIT_ULL(45)
-#define I40E_FLAG_USE_SET_LLDP_MIB             BIT_ULL(46)
-#define I40E_FLAG_STOP_FW_LLDP                 BIT_ULL(47)
-#define I40E_FLAG_PHY_CONTROLS_LEDS            BIT_ULL(48)
-#define I40E_FLAG_MPLS_HDR_OFFLOAD_CAPABLE     BIT_ULL(49)
-#define I40E_FLAG_TRUE_PROMISC_SUPPORT         BIT_ULL(50)
-#define I40E_FLAG_HAVE_CRT_RETIMER             BIT_ULL(51)
-#define I40E_FLAG_PTP_L4_CAPABLE               BIT_ULL(52)
-#define I40E_FLAG_TEMP_LINK_POLLING            BIT_ULL(56)
+#define I40E_FLAG_IWARP_ENABLED                        BIT_ULL(23)
+#define I40E_FLAG_SERVICE_CLIENT_REQUESTED     BIT_ULL(24)
+#define I40E_FLAG_CLIENT_L2_CHANGE             BIT_ULL(25)
+#define I40E_FLAG_CLIENT_RESET                 BIT_ULL(26)
+#define I40E_FLAG_LINK_DOWN_ON_CLOSE_ENABLED   BIT_ULL(27)
+#define I40E_FLAG_SOURCE_PRUNING_DISABLED       BIT_ULL(28)
 
        /* flag to enable/disable vf base mode support */
        bool vf_base_mode_only;
-       /* Tracks features that are disabled due to hw limitations.
-       * If a bit is set here, it means that the corresponding
-       * bit in the 'flags' field is cleared i.e that feature
-       * is disabled
-       */
-       u64 hw_disabled_flags;
-
-#ifdef I40E_FCOE
-       struct i40e_fcoe fcoe;
 
-#endif /* I40E_FCOE */
+       struct i40e_client_instance *cinst;
        bool stat_offsets_loaded;
        struct i40e_hw_port_stats stats;
        struct i40e_hw_port_stats stats_offsets;
@@ -537,17 +575,18 @@ struct i40e_pf {
         */
        u16 dcbx_cap;
 
-       u32 fcoe_hmc_filt_num;
-       u32 fcoe_hmc_cntx_num;
        struct i40e_filter_control_settings filter_settings;
 #ifdef HAVE_PTP_1588_CLOCK
 
        struct ptp_clock *ptp_clock;
        struct ptp_clock_info ptp_caps;
        struct sk_buff *ptp_tx_skb;
+       unsigned long ptp_tx_start;
        struct hwtstamp_config tstamp_config;
        struct mutex tmreg_lock; /* Used to protect the SYSTIME registers. */
        u64 ptp_base_adj;
+       u32 tx_hwtstamp_timeouts;
+       u32 tx_hwtstamp_skipped;
        u32 rx_hwtstamp_cleared;
        u32 latch_event_flags;
        spinlock_t ptp_rx_lock; /* Used to protect Rx timestamp registers. */
@@ -565,6 +604,9 @@ struct i40e_pf {
        u64 rx_udp_cso;
        u64 rx_sctp_cso;
        u64 rx_ip4_cso;
+       u64 hw_csum_rx_vxlan;
+       u64 hw_csum_rx_geneve;
+       u64 hw_csum_rx_outer;
        u64 rx_tcp_cso_err;
        u64 rx_udp_cso_err;
        u64 rx_sctp_cso_err;
@@ -609,6 +651,22 @@ struct i40e_mac_filter {
        enum i40e_filter_state state;
 };
 
+/* Wrapper structure to keep track of filters while we are preparing to send
+ * firmware commands. We cannot send firmware commands while holding a
+ * spinlock, since it might sleep. To avoid this, we wrap the added filters in
+ * a separate structure, which will track the state change and update the real
+ * filter while under lock. We can't simply hold the filters in a separate
+ * list, as this opens a window for a race condition when adding new MAC
+ * addresses to all VLANs, or when adding new VLANs to all MAC addresses.
+ */
+struct i40e_new_mac_filter {
+       struct hlist_node hlist;
+       struct i40e_mac_filter *f;
+
+       /* Track future changes to state separately */
+       enum i40e_filter_state state;
+};
+
 struct i40e_veb {
        struct i40e_pf *pf;
        u16 idx;
@@ -645,10 +703,10 @@ struct i40e_vsi {
        bool stat_offsets_loaded;
 
        u32 current_netdev_flags;
-       unsigned long state;
+       DECLARE_BITMAP(state, __I40E_VSI_STATE_SIZE__);
 #define I40E_VSI_FLAG_FILTER_CHANGED   BIT(0)
 #define I40E_VSI_FLAG_VEB_OWNER                BIT(1)
-       unsigned long flags;
+       u64 flags;
 
        /* Per VSI lock to protect elements/hash (MAC filter) */
        spinlock_t mac_filter_hash_lock;
@@ -666,16 +724,10 @@ struct i40e_vsi {
 #endif
        struct i40e_eth_stats eth_stats;
        struct i40e_eth_stats eth_stats_offsets;
-#ifdef I40E_FCOE
-       struct i40e_fcoe_stats fcoe_stats;
-       struct i40e_fcoe_stats fcoe_stats_offsets;
-       bool fcoe_stat_offsets_loaded;
-#endif
        u32 tx_restart;
        u32 tx_busy;
        u64 tx_linearize;
        u64 tx_force_wb;
-       u64 tx_lost_interrupt;
        u32 rx_buf_failed;
        u32 rx_page_failed;
 
@@ -735,12 +787,15 @@ struct i40e_vsi {
        struct kobject *kobj;   /* sysfs object */
        bool current_isup;      /* Sync 'link up' logging */
        enum i40e_aq_link_speed current_speed;  /* Sync link speed logging */
+
+       void *priv;     /* client driver data reference. */
        bool block_tx_timeout;
 
        /* VSI specific handlers */
        irqreturn_t (*irq_handler)(int irq, void *data);
 #ifdef ETHTOOL_GRXRINGS
 #endif
+
 } ____cacheline_internodealigned_in_smp;
 
 struct i40e_netdev_priv {
@@ -761,10 +816,8 @@ struct i40e_q_vector {
 
        u8 num_ringpairs;       /* total number of ring pairs in vector */
 
-#ifdef HAVE_IRQ_AFFINITY_HINT
-       cpumask_t affinity_mask;
-#endif
 #ifdef HAVE_IRQ_AFFINITY_NOTIFY
+       cpumask_t affinity_mask;
        struct irq_affinity_notify affinity_notify;
 #endif
 
@@ -789,22 +842,36 @@ static inline char *i40e_nvm_version_str(struct i40e_hw *hw)
 {
        static char buf[32];
        u32 full_ver;
-       u8 ver, patch;
-       u16 build;
 
        full_ver = hw->nvm.oem_ver;
-       ver = (u8)(full_ver >> I40E_OEM_VER_SHIFT);
-       build = (u16)((full_ver >> I40E_OEM_VER_BUILD_SHIFT) &
-                I40E_OEM_VER_BUILD_MASK);
-       patch = (u8)(full_ver & I40E_OEM_VER_PATCH_MASK);
-
-       snprintf(buf, sizeof(buf),
-                "%x.%02x 0x%x %d.%d.%d",
-                (hw->nvm.version & I40E_NVM_VERSION_HI_MASK) >>
-                       I40E_NVM_VERSION_HI_SHIFT,
-                (hw->nvm.version & I40E_NVM_VERSION_LO_MASK) >>
-                       I40E_NVM_VERSION_LO_SHIFT,
-                hw->nvm.eetrack, ver, build, patch);
+
+       if (hw->nvm.eetrack == I40E_OEM_EETRACK_ID) {
+               u8 gen, snap;
+               u16 release;
+
+               gen = (u8)(full_ver >> I40E_OEM_GEN_SHIFT);
+               snap = (u8)((full_ver & I40E_OEM_SNAP_MASK) >>
+                       I40E_OEM_SNAP_SHIFT);
+               release = (u16)(full_ver & I40E_OEM_RELEASE_MASK);
+
+               snprintf(buf, sizeof(buf), "%x.%x.%x", gen, snap, release);
+       } else {
+               u8 ver, patch;
+               u16 build;
+
+               ver = (u8)(full_ver >> I40E_OEM_VER_SHIFT);
+               build = (u16)((full_ver >> I40E_OEM_VER_BUILD_SHIFT) &
+                        I40E_OEM_VER_BUILD_MASK);
+               patch = (u8)(full_ver & I40E_OEM_VER_PATCH_MASK);
+
+               snprintf(buf, sizeof(buf),
+                        "%x.%02x 0x%x %d.%d.%d",
+                        (hw->nvm.version & I40E_NVM_VERSION_HI_MASK) >>
+                               I40E_NVM_VERSION_HI_SHIFT,
+                        (hw->nvm.version & I40E_NVM_VERSION_LO_MASK) >>
+                               I40E_NVM_VERSION_LO_SHIFT,
+                        hw->nvm.eetrack, ver, build, patch);
+       }
 
        return buf;
 }
@@ -829,21 +896,6 @@ static inline void i40e_vsi_setup_irqhandler(struct i40e_vsi *vsi,
        vsi->irq_handler = irq_handler;
 }
 
-/**
- * i40e_rx_is_programming_status - check for programming status descriptor
- * @qw: the first quad word of the program status descriptor
- *
- * The value of in the descriptor length field indicate if this
- * is a programming status descriptor for flow director or FCoE
- * by the value of I40E_RX_PROG_STATUS_DESC_LENGTH, otherwise
- * it is a packet descriptor.
- **/
-static inline bool i40e_rx_is_programming_status(u64 qw)
-{
-       return I40E_RX_PROG_STATUS_DESC_LENGTH ==
-               (qw >> I40E_RX_PROG_STATUS_DESC_LENGTH_SHIFT);
-}
-
 /**
  * i40e_get_fd_cnt_all - get the total FD filter space available
  * @pf: pointer to the PF struct
@@ -887,7 +939,7 @@ static inline void i40e_write_fd_input_set(struct i40e_pf *pf,
        i40e_write_rx_ctl(&pf->hw, I40E_PRTQF_FD_INSET(addr, 1),
                          (u32)(val >> 32));
        i40e_write_rx_ctl(&pf->hw, I40E_PRTQF_FD_INSET(addr, 0),
-                         (u32)val);
+                         (u32)(val & 0xFFFFFFFFULL));
 }
 
 /* needed by i40e_ethtool.c */
@@ -896,12 +948,13 @@ void i40e_down(struct i40e_vsi *vsi);
 extern char i40e_driver_name[];
 extern const char i40e_driver_version_str[];
 void i40e_do_reset_safe(struct i40e_pf *pf, u32 reset_flags);
-void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags);
+void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags, bool lock_acquired);
 int i40e_config_rss(struct i40e_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size);
 int i40e_get_rss(struct i40e_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size);
 void i40e_fill_rss_lut(struct i40e_pf *pf, u8 *lut,
                       u16 rss_table_size, u16 rss_size);
 struct i40e_vsi *i40e_find_vsi_from_id(struct i40e_pf *pf, u16 id);
+struct i40e_vsi *i40e_find_vsi_from_seid(struct i40e_pf *pf, u16 seid);
 /**
  * i40e_find_vsi_by_type - Find and return Flow Director VSI
  * @pf: PF to search for VSI
@@ -933,18 +986,6 @@ int i40e_fetch_switch_configuration(struct i40e_pf *pf,
 
 int i40e_add_del_fdir(struct i40e_vsi *vsi,
                      struct i40e_fdir_filter *input, bool add);
-/**
- * i40e_is_flex_filter - returns true if input filter is flex filter
- * @input: pointer to fdir filter
- *
- * This function determines based on user input (user-def N m )
- * if it can be classified as flex filter or not.
- **/
-static inline bool i40e_is_flex_filter(struct i40e_fdir_filter *input)
-{
-       return (input && (!input->flex_bytes[2]) && input->flex_bytes[3] &&
-               (input->flex_mask[3] != cpu_to_be16(~0))) ? true : false;
-}
 void i40e_fdir_check_and_reenable(struct i40e_pf *pf);
 u32 i40e_get_current_fd_count(struct i40e_pf *pf);
 u32 i40e_get_cur_guaranteed_fd_count(struct i40e_pf *pf);
@@ -967,14 +1008,14 @@ int i40e_vsi_setup_rx_resources(struct i40e_vsi *vsi);
 int i40e_vsi_setup_tx_resources(struct i40e_vsi *vsi);
 int i40e_vsi_config_tc(struct i40e_vsi *vsi, u8 enabled_tc);
 int i40e_vsi_request_irq_msix(struct i40e_vsi *vsi, char *basename);
-#ifdef I40E_FCOE
-void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi,
-                             struct i40e_vsi_context *ctxt,
-                             u8 enabled_tc, bool is_add);
-#endif
 void i40e_service_event_schedule(struct i40e_pf *pf);
+void i40e_notify_client_of_vf_msg(struct i40e_vsi *vsi, u32 vf_id,
+                                 u8 *msg, u16 len);
+
 int i40e_vsi_start_rings(struct i40e_vsi *vsi);
 void i40e_vsi_stop_rings(struct i40e_vsi *vsi);
+void i40e_vsi_stop_rings_no_wait(struct  i40e_vsi *vsi);
+int i40e_vsi_wait_queues_disabled(struct i40e_vsi *vsi);
 void i40e_quiesce_vsi(struct i40e_vsi *vsi);
 void i40e_unquiesce_vsi(struct i40e_vsi *vsi);
 void i40e_pf_quiesce_all_vsi(struct i40e_pf *pf);
@@ -1003,6 +1044,15 @@ static inline void i40e_dbg_pf_exit(struct i40e_pf *pf) {}
 static inline void i40e_dbg_init(void) {}
 static inline void i40e_dbg_exit(void) {}
 #endif /* CONFIG_DEBUG_FS*/
+/* needed by client drivers */
+int i40e_lan_add_device(struct i40e_pf *pf);
+int i40e_lan_del_device(struct i40e_pf *pf);
+void i40e_client_subtask(struct i40e_pf *pf);
+void i40e_notify_client_of_l2_param_changes(struct i40e_vsi *vsi);
+void i40e_notify_client_of_netdev_close(struct i40e_vsi *vsi, bool reset);
+void i40e_notify_client_of_vf_enable(struct i40e_pf *pf, u32 num_vfs);
+void i40e_notify_client_of_vf_reset(struct i40e_pf *pf, u32 vf_id);
+int i40e_vf_client_capable(struct i40e_pf *pf, u32 vf_id);
 /**
  * i40e_irq_dynamic_enable - Enable default interrupt generation settings
  * @vsi: pointer to a vsi
@@ -1026,36 +1076,7 @@ static inline void i40e_irq_dynamic_enable(struct i40e_vsi *vsi, int vector)
 
 void i40e_irq_dynamic_disable_icr0(struct i40e_pf *pf);
 void i40e_irq_dynamic_enable_icr0(struct i40e_pf *pf, bool clearpba);
-#ifdef I40E_FCOE
-#ifdef HAVE_NDO_GET_STATS64
-struct rtnl_link_stats64 *i40e_get_netdev_stats_struct(
-                                            struct net_device *netdev,
-                                            struct rtnl_link_stats64 *storage);
-#else
-struct net_device_stats *i40e_get_netdev_stats_struct(
-                                                    struct net_device *netdev);
-#endif
-int i40e_set_mac(struct net_device *netdev, void *p);
-void i40e_set_rx_mode(struct net_device *netdev);
-#endif
 int i40e_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
-#ifdef I40E_FCOE
-void i40e_tx_timeout(struct net_device *netdev);
-#ifdef HAVE_INT_NDO_VLAN_RX_ADD_VID
-#ifdef NETIF_F_HW_VLAN_CTAG_RX
-int i40e_vlan_rx_add_vid(struct net_device *netdev,
-                        __always_unused __be16 proto, u16 vid);
-int i40e_vlan_rx_kill_vid(struct net_device *netdev,
-                         __always_unused __be16 proto, u16 vid);
-#else
-int i40e_vlan_rx_add_vid(struct net_device *netdev, u16 vid);
-int i40e_vlan_rx_kill_vid(struct net_device *netdev, u16 vid);
-#endif
-#else
-void i40e_vlan_rx_add_vid(struct net_device *netdev, u16 vid);
-void i40e_vlan_rx_kill_vid(struct net_device *netdev, u16 vid);
-#endif
-#endif
 int i40e_open(struct net_device *netdev);
 int i40e_close(struct net_device *netdev);
 int i40e_vsi_open(struct i40e_vsi *vsi);
@@ -1069,29 +1090,6 @@ struct i40e_mac_filter *i40e_add_mac_filter(struct i40e_vsi *vsi,
 int i40e_del_mac_filter(struct i40e_vsi *vsi, const u8 *macaddr);
 bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi);
 struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, const u8 *macaddr);
-#ifdef I40E_FCOE
-#ifdef NETIF_F_HW_TC
-int __i40e_setup_tc(struct net_device *netdev, u32 handle, __be16 proto,
-                   struct tc_to_netdev *tc);
-#else
-int i40e_setup_tc(struct net_device *netdev, u8 tc);
-#endif
-void i40e_netpoll(struct net_device *netdev);
-int i40e_fcoe_enable(struct net_device *netdev);
-int i40e_fcoe_disable(struct net_device *netdev);
-int i40e_fcoe_vsi_init(struct i40e_vsi *vsi, struct i40e_vsi_context *ctxt);
-u8 i40e_get_fcoe_tc_map(struct i40e_pf *pf);
-void i40e_fcoe_config_netdev(struct net_device *netdev, struct i40e_vsi *vsi);
-void i40e_fcoe_vsi_setup(struct i40e_pf *pf);
-void i40e_init_pf_fcoe(struct i40e_pf *pf);
-int i40e_fcoe_setup_ddp_resources(struct i40e_vsi *vsi);
-void i40e_fcoe_free_ddp_resources(struct i40e_vsi *vsi);
-int i40e_fcoe_handle_offload(struct i40e_ring *rx_ring,
-                            union i40e_rx_desc *rx_desc,
-                            struct sk_buff *skb);
-void i40e_fcoe_handle_status(struct i40e_ring *rx_ring,
-                            union i40e_rx_desc *rx_desc, u8 prog_id);
-#endif /* I40E_FCOE */
 void i40e_vlan_stripping_enable(struct i40e_vsi *vsi);
 #ifdef CONFIG_DCB
 #ifdef HAVE_DCBNL_IEEE
@@ -1106,7 +1104,8 @@ bool i40e_dcb_need_reconfig(struct i40e_pf *pf,
                            struct i40e_dcbx_config *new_cfg);
 #endif /* CONFIG_DCB */
 #ifdef HAVE_PTP_1588_CLOCK
-void i40e_ptp_rx_hang(struct i40e_vsi *vsi);
+void i40e_ptp_rx_hang(struct i40e_pf *pf);
+void i40e_ptp_tx_hang(struct i40e_pf *pf);
 void i40e_ptp_tx_hwtstamp(struct i40e_pf *pf);
 void i40e_ptp_rx_hwtstamp(struct i40e_pf *pf, struct sk_buff *skb, u8 index);
 void i40e_ptp_set_increment(struct i40e_pf *pf);
@@ -1121,4 +1120,5 @@ i40e_status i40e_get_partition_bw_setting(struct i40e_pf *pf);
 i40e_status i40e_set_partition_bw_setting(struct i40e_pf *pf);
 i40e_status i40e_commit_partition_bw_setting(struct i40e_pf *pf);
 void i40e_print_link_message(struct i40e_vsi *vsi, bool isup);
+const char *i40e_tunnel_name(struct i40e_udp_port_config *port);
 #endif /* _I40E_H_ */
similarity index 98%
rename from i40e-dkms/i40e-1.6.42/src/i40e_adminq.c
rename to i40e-dkms/i40e-2.1.26/src/i40e_adminq.c
index caf8427f5a8b0ff33a58ab191431cf7eb4fbf08e..b28a2704057cfb3c08999eb69e2ee0578c589c50 100644 (file)
@@ -622,6 +622,18 @@ i40e_status i40e_init_adminq(struct i40e_hw *hw)
                           &oem_lo);
        hw->nvm.oem_ver = ((u32)oem_hi << 16) | oem_lo;
 
+       /* The ability to RX (not drop) 802.1ad frames was added in API 1.7 */
+       if ((hw->aq.api_maj_ver > 1) ||
+           ((hw->aq.api_maj_ver == 1) &&
+            (hw->aq.api_min_ver >= 7)))
+               hw->flags |= I40E_HW_FLAG_802_1AD_CAPABLE;
+
+       if (hw->mac.type ==  I40E_MAC_XL710 &&
+           hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR &&
+           hw->aq.api_min_ver >= I40E_MINOR_VER_GET_LINK_INFO_XL710) {
+               hw->flags |= I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE;
+       }
+
        if (hw->aq.api_maj_ver > I40E_FW_API_VERSION_MAJOR) {
                ret_code = I40E_ERR_FIRMWARE_API_VERSION;
                goto init_adminq_free_arq;
@@ -877,8 +889,8 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw,
                         */
                        if (i40e_asq_done(hw))
                                break;
-                       usleep_range(1000, 2000);
-                       total_delay++;
+                       udelay(50);
+                       total_delay += 50;
                } while (total_delay < hw->aq.asq_cmd_timeout);
        }
 
similarity index 99%
rename from i40e-dkms/i40e-1.6.42/src/i40e_adminq.h
rename to i40e-dkms/i40e-2.1.26/src/i40e_adminq.h
index ec5a00929dfdc23a7851bd2c067e7f9e77bc8caf..e6739d33c7e99a2101655536e85c31b151a436cf 100644 (file)
@@ -148,7 +148,7 @@ static INLINE int i40e_aq_rc_to_posix(int aq_ret, int aq_rc)
 
 /* general information */
 #define I40E_AQ_LARGE_BUF      512
-#define I40E_ASQ_CMD_TIMEOUT   250  /* msecs */
+#define I40E_ASQ_CMD_TIMEOUT   250000  /* usecs */
 
 void i40e_fill_default_direct_cmd_desc(struct i40e_aq_desc *desc,
                                       u16 opcode);
similarity index 92%
rename from i40e-dkms/i40e-1.6.42/src/i40e_adminq_cmd.h
rename to i40e-dkms/i40e-2.1.26/src/i40e_adminq_cmd.h
index 6a9a14a3cc0158f34e690e26114fed1e1791936a..5522cc498a34c6778fafa2b818433e832a455803 100644 (file)
  */
 
 #define I40E_FW_API_VERSION_MAJOR      0x0001
-#define I40E_FW_API_VERSION_MINOR      0x0005
+#define I40E_FW_API_VERSION_MINOR_X722 0x0005
+#define I40E_FW_API_VERSION_MINOR_X710 0x0007
+
+#define I40E_FW_MINOR_VERSION(_h) ((_h)->mac.type == I40E_MAC_XL710 ? \
+                                       I40E_FW_API_VERSION_MINOR_X710 : \
+                                       I40E_FW_API_VERSION_MINOR_X722)
+
+/* API version 1.7 implements additional link and PHY-specific APIs  */
+#define I40E_MINOR_VER_GET_LINK_INFO_XL710 0x0007
 
 struct i40e_aq_desc {
        __le16 flags;
@@ -184,10 +192,15 @@ enum i40e_admin_queue_opc {
        i40e_aqc_opc_add_cloud_filters          = 0x025C,
        i40e_aqc_opc_remove_cloud_filters       = 0x025D,
        i40e_aqc_opc_clear_wol_switch_filters   = 0x025E,
+       i40e_aqc_opc_replace_cloud_filters      = 0x025F,
 
        i40e_aqc_opc_add_mirror_rule    = 0x0260,
        i40e_aqc_opc_delete_mirror_rule = 0x0261,
 
+       /* Dynamic Device Personalization */
+       i40e_aqc_opc_write_personalization_profile      = 0x0270,
+       i40e_aqc_opc_get_personalization_profile_list   = 0x0271,
+
        /* DCB commands */
        i40e_aqc_opc_dcb_ignore_pfc     = 0x0301,
        i40e_aqc_opc_dcb_updated        = 0x0302,
@@ -232,6 +245,8 @@ enum i40e_admin_queue_opc {
        i40e_aqc_opc_set_phy_debug              = 0x0622,
        i40e_aqc_opc_upload_ext_phy_fm          = 0x0625,
        i40e_aqc_opc_run_phy_activity           = 0x0626,
+       i40e_aqc_opc_set_phy_register           = 0x0628,
+       i40e_aqc_opc_get_phy_register           = 0x0629,
 
        /* NVM commands */
        i40e_aqc_opc_nvm_read                   = 0x0701,
@@ -762,8 +777,24 @@ struct i40e_aqc_set_switch_config {
 /* flags used for both fields below */
 #define I40E_AQ_SET_SWITCH_CFG_PROMISC         0x0001
 #define I40E_AQ_SET_SWITCH_CFG_L2_FILTER       0x0002
+#define I40E_AQ_SET_SWITCH_CFG_HW_ATR_EVICT    0x0004
        __le16  valid_flags;
-       u8      reserved[12];
+       /* The ethertype in switch_tag is dropped on ingress and used
+        * internally by the switch. Set this to zero for the default
+        * of 0x88a8 (802.1ad). Should be zero for firmware API
+        * versions lower than 1.7.
+        */
+       __le16  switch_tag;
+       /* The ethertypes in first_tag and second_tag are used to
+        * match the outer and inner VLAN tags (respectively) when HW
+        * double VLAN tagging is enabled via the set port parameters
+        * AQ command. Otherwise these are both ignored. Set them to
+        * zero for their defaults of 0x8100 (802.1Q). Should be zero
+        * for firmware API versions lower than 1.7.
+        */
+       __le16  first_tag;
+       __le16  second_tag;
+       u8      reserved[6];
 };
 
 I40E_CHECK_CMD_LENGTH(i40e_aqc_set_switch_config);
@@ -1316,7 +1347,9 @@ struct i40e_aqc_add_remove_cloud_filters {
 #define I40E_AQC_ADD_CLOUD_CMD_SEID_NUM_SHIFT  0
 #define I40E_AQC_ADD_CLOUD_CMD_SEID_NUM_MASK   (0x3FF << \
                                        I40E_AQC_ADD_CLOUD_CMD_SEID_NUM_SHIFT)
-       u8      reserved2[4];
+       u8      big_buffer_flag;
+#define I40E_AQC_ADD_REM_CLOUD_CMD_BIG_BUFFER  1
+       u8      reserved2[3];
        __le32  addr_high;
        __le32  addr_low;
 };
@@ -1353,6 +1386,7 @@ struct i40e_aqc_add_remove_cloud_filters_element_data {
 #define I40E_AQC_ADD_CLOUD_FILTER_IMAC                 0x000A
 #define I40E_AQC_ADD_CLOUD_FILTER_OMAC_TEN_ID_IMAC     0x000B
 #define I40E_AQC_ADD_CLOUD_FILTER_IIP                  0x000C
+/* 0x0010 to 0x0017 is for custom filters */
 
 #define I40E_AQC_ADD_CLOUD_FLAGS_TO_QUEUE              0x0080
 #define I40E_AQC_ADD_CLOUD_VNK_SHIFT                   6
@@ -1387,6 +1421,46 @@ struct i40e_aqc_add_remove_cloud_filters_element_data {
        u8      response_reserved[7];
 };
 
+/* i40e_aqc_add_rm_cloud_filt_elem_ext is used when
+ * I40E_AQC_ADD_REM_CLOUD_CMD_BIG_BUFFER flag is set. refer to
+ * DCR288
+ */
+struct i40e_aqc_add_rm_cloud_filt_elem_ext {
+       struct i40e_aqc_add_remove_cloud_filters_element_data element;
+       u16     general_fields[32];
+#define I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD0   0
+#define I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1   1
+#define I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD2   2
+#define I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0   3
+#define I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1   4
+#define I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2   5
+#define I40E_AQC_ADD_CLOUD_FV_FLU_0X12_WORD0   6
+#define I40E_AQC_ADD_CLOUD_FV_FLU_0X12_WORD1   7
+#define I40E_AQC_ADD_CLOUD_FV_FLU_0X12_WORD2   8
+#define I40E_AQC_ADD_CLOUD_FV_FLU_0X13_WORD0   9
+#define I40E_AQC_ADD_CLOUD_FV_FLU_0X13_WORD1   10
+#define I40E_AQC_ADD_CLOUD_FV_FLU_0X13_WORD2   11
+#define I40E_AQC_ADD_CLOUD_FV_FLU_0X14_WORD0   12
+#define I40E_AQC_ADD_CLOUD_FV_FLU_0X14_WORD1   13
+#define I40E_AQC_ADD_CLOUD_FV_FLU_0X14_WORD2   14
+#define I40E_AQC_ADD_CLOUD_FV_FLU_0X16_WORD0   15
+#define I40E_AQC_ADD_CLOUD_FV_FLU_0X16_WORD1   16
+#define I40E_AQC_ADD_CLOUD_FV_FLU_0X16_WORD2   17
+#define I40E_AQC_ADD_CLOUD_FV_FLU_0X16_WORD3   18
+#define I40E_AQC_ADD_CLOUD_FV_FLU_0X16_WORD4   19
+#define I40E_AQC_ADD_CLOUD_FV_FLU_0X16_WORD5   20
+#define I40E_AQC_ADD_CLOUD_FV_FLU_0X16_WORD6   21
+#define I40E_AQC_ADD_CLOUD_FV_FLU_0X16_WORD7   22
+#define I40E_AQC_ADD_CLOUD_FV_FLU_0X17_WORD0   23
+#define I40E_AQC_ADD_CLOUD_FV_FLU_0X17_WORD1   24
+#define I40E_AQC_ADD_CLOUD_FV_FLU_0X17_WORD2   25
+#define I40E_AQC_ADD_CLOUD_FV_FLU_0X17_WORD3   26
+#define I40E_AQC_ADD_CLOUD_FV_FLU_0X17_WORD4   27
+#define I40E_AQC_ADD_CLOUD_FV_FLU_0X17_WORD5   28
+#define I40E_AQC_ADD_CLOUD_FV_FLU_0X17_WORD6   29
+#define I40E_AQC_ADD_CLOUD_FV_FLU_0X17_WORD7   30
+};
+
 struct i40e_aqc_remove_cloud_filters_completion {
        __le16 perfect_ovlan_used;
        __le16 perfect_ovlan_free;
@@ -1398,6 +1472,54 @@ struct i40e_aqc_remove_cloud_filters_completion {
 
 I40E_CHECK_CMD_LENGTH(i40e_aqc_remove_cloud_filters_completion);
 
+/* Replace filter Command 0x025F
+ * uses the i40e_aqc_replace_cloud_filters,
+ * and the generic indirect completion structure
+ */
+struct i40e_filter_data {
+       u8 filter_type;
+       u8 input[3];
+};
+
+struct i40e_aqc_replace_cloud_filters_cmd {
+       u8      valid_flags;
+#define I40E_AQC_REPLACE_L1_FILTER             0x0
+#define I40E_AQC_REPLACE_CLOUD_FILTER          0x1
+#define I40E_AQC_GET_CLOUD_FILTERS             0x2
+#define I40E_AQC_MIRROR_CLOUD_FILTER           0x4
+#define I40E_AQC_HIGH_PRIORITY_CLOUD_FILTER    0x8
+       u8      old_filter_type;
+       u8      new_filter_type;
+       u8      tr_bit;
+       u8      reserved[4];
+       __le32 addr_high;
+       __le32 addr_low;
+};
+
+struct i40e_aqc_replace_cloud_filters_cmd_buf {
+       u8      data[32];
+/* Filter type INPUT codes*/
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_ENTRIES_MAX   3
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED     (1 << 7UL)
+
+/* Field Vector offsets */
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_MAC_DA             0
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG_ETH           6
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG               7
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_VLAN               8
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG_OVLAN         9
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG_IVLAN         10
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TUNNLE_KEY         11
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_IMAC               12
+/* big FLU */
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_IP_DA              14
+/* big FLU */
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_OIP_DA             15
+
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_INNER_VLAN         37
+       struct i40e_filter_data filters[8];
+};
+
 /* Add Mirror Rule (indirect or direct 0x0260)
  * Delete Mirror Rule (indirect or direct 0x0261)
  * note: some rule types (4,5) do not use an external buffer.
@@ -1433,6 +1555,36 @@ struct i40e_aqc_add_delete_mirror_rule_completion {
 
 I40E_CHECK_CMD_LENGTH(i40e_aqc_add_delete_mirror_rule_completion);
 
+/* Dynamic Device Personalization */
+struct i40e_aqc_write_personalization_profile {
+       u8      flags;
+       u8      reserved[3];
+       __le32  profile_track_id;
+       __le32  addr_high;
+       __le32  addr_low;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_write_personalization_profile);
+
+struct i40e_aqc_write_ddp_resp {
+       __le32 error_offset;
+       __le32 error_info;
+       __le32 addr_high;
+       __le32 addr_low;
+};
+
+struct i40e_aqc_get_applied_profiles {
+       u8      flags;
+#define I40E_AQC_GET_DDP_GET_CONF      0x1
+#define I40E_AQC_GET_DDP_GET_RDPU_CONF 0x2
+       u8      rsv[3];
+       __le32  reserved;
+       __le32  addr_high;
+       __le32  addr_low;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_get_applied_profiles);
+
 /* DCB 0x03xx*/
 
 /* PFC Ignore (direct 0x0301)
@@ -1694,6 +1846,8 @@ enum i40e_aq_phy_type {
        I40E_PHY_TYPE_10GBASE_CR1_CU            = 0xB,
        I40E_PHY_TYPE_10GBASE_AOC               = 0xC,
        I40E_PHY_TYPE_40GBASE_AOC               = 0xD,
+       I40E_PHY_TYPE_UNRECOGNIZED              = 0xE,
+       I40E_PHY_TYPE_UNSUPPORTED               = 0xF,
        I40E_PHY_TYPE_100BASE_TX                = 0x11,
        I40E_PHY_TYPE_1000BASE_T                = 0x12,
        I40E_PHY_TYPE_10GBASE_T                 = 0x13,
@@ -1712,7 +1866,12 @@ enum i40e_aq_phy_type {
        I40E_PHY_TYPE_25GBASE_CR                = 0x20,
        I40E_PHY_TYPE_25GBASE_SR                = 0x21,
        I40E_PHY_TYPE_25GBASE_LR                = 0x22,
-       I40E_PHY_TYPE_MAX
+       I40E_PHY_TYPE_25GBASE_AOC               = 0x23,
+       I40E_PHY_TYPE_25GBASE_ACC               = 0x24,
+       I40E_PHY_TYPE_MAX,
+       I40E_PHY_TYPE_NOT_SUPPORTED_HIGH_TEMP   = 0xFD,
+       I40E_PHY_TYPE_EMPTY                     = 0xFE,
+       I40E_PHY_TYPE_DEFAULT                   = 0xFF,
 };
 
 #define I40E_LINK_SPEED_100MB_SHIFT    0x1
@@ -1769,6 +1928,8 @@ struct i40e_aq_get_phy_abilities_resp {
 #define I40E_AQ_PHY_TYPE_EXT_25G_CR    0x02
 #define I40E_AQ_PHY_TYPE_EXT_25G_SR    0x04
 #define I40E_AQ_PHY_TYPE_EXT_25G_LR    0x08
+#define I40E_AQ_PHY_TYPE_EXT_25G_AOC   0x10
+#define I40E_AQ_PHY_TYPE_EXT_25G_ACC   0x20
        u8      fec_cfg_curr_mod_ext_info;
 #define I40E_AQ_ENABLE_FEC_KR          0x01
 #define I40E_AQ_ENABLE_FEC_RS          0x02
@@ -1803,11 +1964,11 @@ struct i40e_aq_set_phy_config { /* same bits as above in all */
        u8      low_power_ctrl;
        u8      phy_type_ext;
        u8      fec_config;
-#define I40E_AQ_SET_FEC_ABILITY_KR     (1 << 0)
-#define I40E_AQ_SET_FEC_ABILITY_RS     (1 << 1)
-#define I40E_AQ_SET_FEC_REQUEST_KR     (1 << 2)
-#define I40E_AQ_SET_FEC_REQUEST_RS     (1 << 3)
-#define I40E_AQ_SET_FEC_AUTO           (1 << 4)
+#define I40E_AQ_SET_FEC_ABILITY_KR     BIT(0)
+#define I40E_AQ_SET_FEC_ABILITY_RS     BIT(1)
+#define I40E_AQ_SET_FEC_REQUEST_KR     BIT(2)
+#define I40E_AQ_SET_FEC_REQUEST_RS     BIT(3)
+#define I40E_AQ_SET_FEC_AUTO           BIT(4)
 #define I40E_AQ_PHY_FEC_CONFIG_SHIFT   0x0
 #define I40E_AQ_PHY_FEC_CONFIG_MASK    (0x1F << I40E_AQ_PHY_FEC_CONFIG_SHIFT)
        u8      reserved;
@@ -1898,19 +2059,31 @@ struct i40e_aqc_get_link_status {
 #define I40E_AQ_25G_SERDES_UCODE_ERR   0X04
 #define I40E_AQ_25G_NIMB_UCODE_ERR     0X05
        u8      loopback; /* use defines from i40e_aqc_set_lb_mode */
+/* Since firmware API 1.7 loopback field keeps power class info as well */
+#define I40E_AQ_LOOPBACK_MASK          0x07
+#define I40E_AQ_PWR_CLASS_SHIFT_LB     6
+#define I40E_AQ_PWR_CLASS_MASK_LB      (0x03 << I40E_AQ_PWR_CLASS_SHIFT_LB)
        __le16  max_frame_size;
        u8      config;
 #define I40E_AQ_CONFIG_FEC_KR_ENA      0x01
 #define I40E_AQ_CONFIG_FEC_RS_ENA      0x02
 #define I40E_AQ_CONFIG_CRC_ENA         0x04
 #define I40E_AQ_CONFIG_PACING_MASK     0x78
-       u8      power_desc;
+       union {
+               struct {
+                       u8      power_desc;
 #define I40E_AQ_LINK_POWER_CLASS_1     0x00
 #define I40E_AQ_LINK_POWER_CLASS_2     0x01
 #define I40E_AQ_LINK_POWER_CLASS_3     0x02
 #define I40E_AQ_LINK_POWER_CLASS_4     0x03
 #define I40E_AQ_PWR_CLASS_MASK         0x03
-       u8      reserved[4];
+                       u8      reserved[4];
+               };
+               struct {
+                       u8      link_type[4];
+                       u8      link_type_ext;
+               };
+       };
 };
 
 I40E_CHECK_CMD_LENGTH(i40e_aqc_get_link_status);
@@ -1993,6 +2166,22 @@ struct i40e_aqc_run_phy_activity {
 
 I40E_CHECK_CMD_LENGTH(i40e_aqc_run_phy_activity);
 
+/* Set PHY Register command (0x0628) */
+/* Get PHY Register command (0x0629) */
+struct i40e_aqc_phy_register_access {
+       u8      phy_interface;
+#define I40E_AQ_PHY_REG_ACCESS_INTERNAL        0
+#define I40E_AQ_PHY_REG_ACCESS_EXTERNAL        1
+#define I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE 2
+       u8      dev_addres;
+       u8      reserved1[2];
+       u32     reg_address;
+       u32     reg_value;
+       u8      reserved2[4];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_phy_register_access);
+
 /* NVM Read command (indirect 0x0701)
  * NVM Erase commands (direct 0x0702)
  * NVM Update commands (indirect 0x0703)
diff --git a/i40e-dkms/i40e-2.1.26/src/i40e_client.c b/i40e-dkms/i40e-2.1.26/src/i40e_client.c
new file mode 100644 (file)
index 0000000..ebad3fb
--- /dev/null
@@ -0,0 +1,825 @@
+/*******************************************************************************
+ *
+ * Intel(R) 40-10 Gigabit Ethernet Connection Network Driver
+ * Copyright(c) 2013 - 2017 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ ******************************************************************************/
+
+#include <linux/list.h>
+#include <linux/errno.h>
+
+#include "i40e.h"
+#include "i40e_prototype.h"
+#include "i40e_client.h"
+
+static const char i40e_client_interface_version_str[] = I40E_CLIENT_VERSION_STR;
+static struct i40e_client *registered_client;
+static LIST_HEAD(i40e_devices);
+static DEFINE_MUTEX(i40e_device_mutex);
+
+static int i40e_client_virtchnl_send(struct i40e_info *ldev,
+                                    struct i40e_client *client,
+                                    u32 vf_id, u8 *msg, u16 len);
+
+static int i40e_client_setup_qvlist(struct i40e_info *ldev,
+                                   struct i40e_client *client,
+                                   struct i40e_qvlist_info *qvlist_info);
+
+static void i40e_client_request_reset(struct i40e_info *ldev,
+                                     struct i40e_client *client,
+                                     u32 reset_level);
+
+static int i40e_client_update_vsi_ctxt(struct i40e_info *ldev,
+                                      struct i40e_client *client,
+                                      bool is_vf, u32 vf_id,
+                                      u32 flag, u32 valid_flag);
+
+static struct i40e_ops i40e_lan_ops = {
+       .virtchnl_send = i40e_client_virtchnl_send,
+       .setup_qvlist = i40e_client_setup_qvlist,
+       .request_reset = i40e_client_request_reset,
+       .update_vsi_ctxt = i40e_client_update_vsi_ctxt,
+};
+
+/**
+ * i40e_client_get_params - Get the params that can change at runtime
+ * @vsi: the VSI with the message
+ * @param: clinet param struct
+ *
+ **/
+static
+int i40e_client_get_params(struct i40e_vsi *vsi, struct i40e_params *params)
+{
+       struct i40e_dcbx_config *dcb_cfg = &vsi->back->hw.local_dcbx_config;
+       int i = 0;
+
+       for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) {
+               u8 tc = dcb_cfg->etscfg.prioritytable[i];
+               u16 qs_handle;
+
+               /* If TC is not enabled for VSI use TC0 for UP */
+               if (!(vsi->tc_config.enabled_tc & BIT(tc)))
+                       tc = 0;
+
+               qs_handle = le16_to_cpu(vsi->info.qs_handle[tc]);
+               params->qos.prio_qos[i].tc = tc;
+               params->qos.prio_qos[i].qs_handle = qs_handle;
+               if (qs_handle == I40E_AQ_VSI_QS_HANDLE_INVALID) {
+                       dev_err(&vsi->back->pdev->dev, "Invalid queue set handle for TC = %d, vsi id = %d\n",
+                               tc, vsi->id);
+                       return -EINVAL;
+               }
+       }
+
+       params->mtu = vsi->netdev->mtu;
+       return 0;
+}
+
+/**
+ * i40e_notify_client_of_vf_msg - call the client vf message callback
+ * @vsi: the VSI with the message
+ * @vf_id: the absolute VF id that sent the message
+ * @msg: message buffer
+ * @len: length of the message
+ *
+ * If there is a client to this VSI, call the client
+ **/
+void
+i40e_notify_client_of_vf_msg(struct i40e_vsi *vsi, u32 vf_id, u8 *msg, u16 len)
+{
+       struct i40e_pf *pf = vsi->back;
+       struct i40e_client_instance *cdev = pf->cinst;
+
+       if (!cdev || !cdev->client)
+               return;
+       if (!cdev->client->ops || !cdev->client->ops->virtchnl_receive) {
+               dev_dbg(&pf->pdev->dev,
+                       "Cannot locate client instance virtual channel receive routine\n");
+               return;
+       }
+       if (!test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state)) {
+               dev_dbg(&pf->pdev->dev, "Client is not open, abort virtchnl_receive\n");
+               return;
+       }
+       cdev->client->ops->virtchnl_receive(&cdev->lan_info, cdev->client,
+                                           vf_id, msg, len);
+}
+
+/**
+ * i40e_notify_client_of_l2_param_changes - call the client notify callback
+ * @vsi: the VSI with l2 param changes
+ *
+ * If there is a client to this VSI, call the client
+ **/
+void i40e_notify_client_of_l2_param_changes(struct i40e_vsi *vsi)
+{
+       struct i40e_pf *pf = vsi->back;
+       struct i40e_client_instance *cdev = pf->cinst;
+       struct i40e_params params;
+
+       if (!cdev || !cdev->client)
+               return;
+       if (!cdev->client->ops || !cdev->client->ops->l2_param_change) {
+               dev_dbg(&vsi->back->pdev->dev,
+                       "Cannot locate client instance l2_param_change routine\n");
+               return;
+       }
+       if (!test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state)) {
+               dev_dbg(&vsi->back->pdev->dev, "Client is not open, abort l2 param change\n");
+               return;
+       }
+       memset(&params, 0, sizeof(params));
+       i40e_client_get_params(vsi, &params);
+       memcpy(&cdev->lan_info.params, &params, sizeof(struct i40e_params));
+       cdev->client->ops->l2_param_change(&cdev->lan_info, cdev->client,
+                                          &params);
+}
+
+/**
+ * i40e_client_release_qvlist - release MSI-X vector mapping for client
+ * @ldev: pointer to L2 context.
+ *
+ **/
+static void i40e_client_release_qvlist(struct i40e_info *ldev)
+{
+       struct i40e_qvlist_info *qvlist_info = ldev->qvlist_info;
+       u32 i;
+
+       if (!ldev->qvlist_info)
+               return;
+
+       for (i = 0; i < qvlist_info->num_vectors; i++) {
+               struct i40e_pf *pf = ldev->pf;
+               struct i40e_qv_info *qv_info;
+               u32 reg_idx;
+
+               qv_info = &qvlist_info->qv_info[i];
+               if (!qv_info)
+                       continue;
+               reg_idx = I40E_PFINT_LNKLSTN(qv_info->v_idx - 1);
+               wr32(&pf->hw, reg_idx, I40E_PFINT_LNKLSTN_FIRSTQ_INDX_MASK);
+       }
+       kfree(ldev->qvlist_info);
+       ldev->qvlist_info = NULL;
+}
+
+/**
+ * i40e_notify_client_of_netdev_close - call the client close callback
+ * @vsi: the VSI with netdev closed
+ * @reset: true when close called due to a reset pending
+ *
+ * If there is a client to this netdev, call the client with close
+ **/
+void i40e_notify_client_of_netdev_close(struct i40e_vsi *vsi, bool reset)
+{
+       struct i40e_pf *pf = vsi->back;
+       struct i40e_client_instance *cdev = pf->cinst;
+
+       if (!cdev || !cdev->client)
+               return;
+       if (!cdev->client->ops || !cdev->client->ops->close) {
+               dev_dbg(&vsi->back->pdev->dev,
+                       "Cannot locate client instance close routine\n");
+               return;
+       }
+       cdev->client->ops->close(&cdev->lan_info, cdev->client, reset);
+       clear_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state);
+       i40e_client_release_qvlist(&cdev->lan_info);
+}
+
+/**
+ * i40e_notify_client_of_vf_reset - call the client vf reset callback
+ * @pf: PF device pointer
+ * @vf_id: asolute id of VF being reset
+ *
+ * If there is a client attached to this PF, notify when a VF is reset
+ **/
+void i40e_notify_client_of_vf_reset(struct i40e_pf *pf, u32 vf_id)
+{
+       struct i40e_client_instance *cdev = pf->cinst;
+
+       if (!cdev || !cdev->client)
+               return;
+       if (!cdev->client->ops || !cdev->client->ops->vf_reset) {
+               dev_dbg(&pf->pdev->dev,
+                       "Cannot locate client instance VF reset routine\n");
+               return;
+       }
+       if (!test_bit(__I40E_CLIENT_INSTANCE_OPENED,  &cdev->state)) {
+               dev_dbg(&pf->pdev->dev, "Client is not open, abort vf-reset\n");
+               return;
+       }
+       cdev->client->ops->vf_reset(&cdev->lan_info, cdev->client, vf_id);
+}
+
+/**
+ * i40e_notify_client_of_vf_enable - call the client vf notification callback
+ * @pf: PF device pointer
+ * @num_vfs: the number of VFs currently enabled, 0 for disable
+ *
+ * If there is a client attached to this PF, call its VF notification routine
+ **/
+void i40e_notify_client_of_vf_enable(struct i40e_pf *pf, u32 num_vfs)
+{
+       struct i40e_client_instance *cdev = pf->cinst;
+
+       if (!cdev || !cdev->client)
+               return;
+       if (!cdev->client->ops || !cdev->client->ops->vf_enable) {
+               dev_dbg(&pf->pdev->dev,
+                       "Cannot locate client instance VF enable routine\n");
+               return;
+       }
+       if (!test_bit(__I40E_CLIENT_INSTANCE_OPENED,
+                     &cdev->state)) {
+               dev_dbg(&pf->pdev->dev, "Client is not open, abort vf-enable\n");
+               return;
+       }
+       cdev->client->ops->vf_enable(&cdev->lan_info, cdev->client, num_vfs);
+}
+
+/**
+ * i40e_vf_client_capable - ask the client if it likes the specified VF
+ * @pf: PF device pointer
+ * @vf_id: the VF in question
+ *
+ * If there is a client of the specified type attached to this PF, call
+ * its vf_capable routine
+ **/
+int i40e_vf_client_capable(struct i40e_pf *pf, u32 vf_id)
+{
+       struct i40e_client_instance *cdev = pf->cinst;
+       int capable = false;
+
+       if (!cdev || !cdev->client)
+               goto out;
+       if (!cdev->client->ops || !cdev->client->ops->vf_capable) {
+               dev_dbg(&pf->pdev->dev,
+                       "Cannot locate client instance VF capability routine\n");
+               goto out;
+       }
+       if (!test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state))
+               goto out;
+
+       capable = cdev->client->ops->vf_capable(&cdev->lan_info,
+                                               cdev->client,
+                                               vf_id);
+out:
+       return capable;
+}
+
+/**
+ * i40e_client_add_instance - add a client instance struct to the instance list
+ * @pf: pointer to the board struct
+ * @client: pointer to a client struct in the client list.
+ * @existing: if there was already an existing instance
+ *
+ **/
+static void i40e_client_add_instance(struct i40e_pf *pf)
+{
+       struct i40e_client_instance *cdev = NULL;
+       struct netdev_hw_addr *mac = NULL;
+       struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi];
+
+       if (!registered_client || pf->cinst)
+               return;
+
+       cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
+       if (!cdev)
+               return;
+
+       cdev->lan_info.pf = (void *)pf;
+       cdev->lan_info.netdev = vsi->netdev;
+       cdev->lan_info.pcidev = pf->pdev;
+       cdev->lan_info.fid = pf->hw.pf_id;
+       cdev->lan_info.ftype = I40E_CLIENT_FTYPE_PF;
+       cdev->lan_info.hw_addr = pf->hw.hw_addr;
+       cdev->lan_info.ops = &i40e_lan_ops;
+       cdev->lan_info.version.major = I40E_CLIENT_VERSION_MAJOR;
+       cdev->lan_info.version.minor = I40E_CLIENT_VERSION_MINOR;
+       cdev->lan_info.version.build = I40E_CLIENT_VERSION_BUILD;
+       cdev->lan_info.fw_maj_ver = pf->hw.aq.fw_maj_ver;
+       cdev->lan_info.fw_min_ver = pf->hw.aq.fw_min_ver;
+       cdev->lan_info.fw_build = pf->hw.aq.fw_build;
+       set_bit(__I40E_CLIENT_INSTANCE_NONE, &cdev->state);
+
+       if (i40e_client_get_params(vsi, &cdev->lan_info.params)) {
+               kfree(cdev);
+               cdev = NULL;
+               return;
+       }
+
+       cdev->lan_info.msix_count = pf->num_iwarp_msix;
+       cdev->lan_info.msix_entries = &pf->msix_entries[pf->iwarp_base_vector];
+
+       mac = list_first_entry(&cdev->lan_info.netdev->dev_addrs.list,
+                              struct netdev_hw_addr, list);
+       if (mac)
+               ether_addr_copy(cdev->lan_info.lanmac, mac->addr);
+       else
+               dev_err(&pf->pdev->dev, "MAC address list is empty!\n");
+
+       cdev->client = registered_client;
+       pf->cinst = cdev;
+}
+
+/**
+ * i40e_client_del_instance - removes a client instance from the list
+ * @pf: pointer to the board struct
+ *
+ **/
+static
+void i40e_client_del_instance(struct i40e_pf *pf)
+{
+       kfree(pf->cinst);
+       pf->cinst = NULL;
+}
+
+/**
+ * i40e_client_subtask - client maintenance work
+ * @pf: board private structure
+ **/
+void i40e_client_subtask(struct i40e_pf *pf)
+{
+       struct i40e_client *client = registered_client;
+       struct i40e_client_instance *cdev;
+       struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi];
+       int ret = 0;
+
+       if (!(pf->flags & I40E_FLAG_SERVICE_CLIENT_REQUESTED))
+               return;
+       pf->flags &= ~I40E_FLAG_SERVICE_CLIENT_REQUESTED;
+       cdev = pf->cinst;
+
+       /* If we're down or resetting, just bail */
+       if (test_bit(__I40E_DOWN, pf->state) ||
+           test_bit(__I40E_CONFIG_BUSY, pf->state))
+               return;
+
+       if (!client || !cdev)
+               return;
+
+       /* Here we handle client opens. If the client is down, but
+        * the netdev is up, then open the client.
+        */
+       if (!test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state)) {
+               if (!test_bit(__I40E_VSI_DOWN, vsi->state) &&
+                   client->ops && client->ops->open) {
+                       set_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state);
+                       ret = client->ops->open(&cdev->lan_info, client);
+                       if (ret) {
+                               /* Remove failed client instance */
+                               clear_bit(__I40E_CLIENT_INSTANCE_OPENED,
+                                         &cdev->state);
+                               i40e_client_del_instance(pf);
+                       }
+               }
+       } else {
+       /* Likewise for client close. If the client is up, but the netdev
+        * is down, then close the client.
+        */
+               if (test_bit(__I40E_VSI_DOWN, vsi->state) &&
+                   client->ops && client->ops->close) {
+                       clear_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state);
+                       client->ops->close(&cdev->lan_info, client, false);
+                       i40e_client_release_qvlist(&cdev->lan_info);
+               }
+       }
+}
+
+/**
+ * i40e_lan_add_device - add a lan device struct to the list of lan devices
+ * @pf: pointer to the board struct
+ *
+ * Returns 0 on success or none 0 on error
+ **/
+int i40e_lan_add_device(struct i40e_pf *pf)
+{
+       struct i40e_device *ldev;
+       int ret = 0;
+
+       mutex_lock(&i40e_device_mutex);
+       list_for_each_entry(ldev, &i40e_devices, list) {
+               if (ldev->pf == pf) {
+                       ret = -EEXIST;
+                       goto out;
+               }
+       }
+       ldev = kzalloc(sizeof(*ldev), GFP_KERNEL);
+       if (!ldev) {
+               ret = -ENOMEM;
+               goto out;
+       }
+       ldev->pf = pf;
+       INIT_LIST_HEAD(&ldev->list);
+       list_add(&ldev->list, &i40e_devices);
+       dev_info(&pf->pdev->dev, "Added LAN device PF%d bus=0x%02x dev=0x%02x func=0x%02x\n",
+                pf->hw.pf_id, pf->hw.bus.bus_id,
+                pf->hw.bus.device, pf->hw.bus.func);
+
+       /* If a client has already been registered, we need to add an instance
+        * of it to our new LAN device.
+        */
+       if (registered_client)
+               i40e_client_add_instance(pf);
+
+       /* Since in some cases register may have happened before a device gets
+        * added, we can schedule a subtask to go initiate the clients if
+        * they can be launched at probe time.
+        */
+       pf->flags |= I40E_FLAG_SERVICE_CLIENT_REQUESTED;
+       i40e_service_event_schedule(pf);
+
+out:
+       mutex_unlock(&i40e_device_mutex);
+       return ret;
+}
+
+/**
+ * i40e_lan_del_device - removes a lan device from the device list
+ * @pf: pointer to the board struct
+ *
+ * Returns 0 on success or non-0 on error
+ **/
+int i40e_lan_del_device(struct i40e_pf *pf)
+{
+       struct i40e_device *ldev, *tmp;
+       int ret = -ENODEV;
+
+       /* First, remove any client instance. */
+       i40e_client_del_instance(pf);
+
+       mutex_lock(&i40e_device_mutex);
+       list_for_each_entry_safe(ldev, tmp, &i40e_devices, list) {
+               if (ldev->pf == pf) {
+                       dev_info(&pf->pdev->dev, "Deleted LAN device PF%d bus=0x%02x dev=0x%02x func=0x%02x\n",
+                                pf->hw.pf_id, pf->hw.bus.bus_id,
+                                pf->hw.bus.device, pf->hw.bus.func);
+                       list_del(&ldev->list);
+                       kfree(ldev);
+                       ret = 0;
+                       break;
+               }
+       }
+
+       mutex_unlock(&i40e_device_mutex);
+       return ret;
+}
+
+/**
+ * i40e_client_release - release client specific resources
+ * @client: pointer to the registered client
+ *
+ **/
+static void i40e_client_release(struct i40e_client *client)
+{
+       struct i40e_client_instance *cdev;
+       struct i40e_device *ldev;
+       struct i40e_pf *pf;
+
+       mutex_lock(&i40e_device_mutex);
+       list_for_each_entry(ldev, &i40e_devices, list) {
+               pf = ldev->pf;
+               cdev = pf->cinst;
+               if (!cdev)
+                       continue;
+
+               while (test_and_set_bit(__I40E_SERVICE_SCHED,
+                                       pf->state))
+                       usleep_range(500, 1000);
+
+               if (test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state)) {
+                       if (client->ops && client->ops->close)
+                               client->ops->close(&cdev->lan_info, client,
+                                                  false);
+                       i40e_client_release_qvlist(&cdev->lan_info);
+                       clear_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state);
+
+                       dev_warn(&pf->pdev->dev,
+                                "Client %s instance for PF id %d closed\n",
+                                client->name, pf->hw.pf_id);
+               }
+               /* delete the client instance */
+               i40e_client_del_instance(pf);
+               dev_info(&pf->pdev->dev, "Deleted client instance of Client %s\n",
+                        client->name);
+               clear_bit(__I40E_SERVICE_SCHED, pf->state);
+       }
+       mutex_unlock(&i40e_device_mutex);
+}
+
+/**
+ * i40e_client_prepare - prepare client specific resources
+ * @client: pointer to the registered client
+ *
+ **/
+static void i40e_client_prepare(struct i40e_client *client)
+{
+       struct i40e_device *ldev;
+       struct i40e_pf *pf;
+
+       mutex_lock(&i40e_device_mutex);
+       list_for_each_entry(ldev, &i40e_devices, list) {
+               pf = ldev->pf;
+               i40e_client_add_instance(pf);
+               /* Start the client subtask */
+               pf->flags |= I40E_FLAG_SERVICE_CLIENT_REQUESTED;
+               i40e_service_event_schedule(pf);
+       }
+       mutex_unlock(&i40e_device_mutex);
+}
+
+/**
+ * i40e_client_virtchnl_send - TBD
+ * @ldev: pointer to L2 context
+ * @client: Client pointer
+ * @vf_id: absolute VF identifier
+ * @msg: message buffer
+ * @len: length of message buffer
+ *
+ * Return 0 on success or < 0 on error
+ **/
+static int i40e_client_virtchnl_send(struct i40e_info *ldev,
+                                    struct i40e_client *client,
+                                    u32 vf_id, u8 *msg, u16 len)
+{
+       struct i40e_pf *pf = ldev->pf;
+       struct i40e_hw *hw = &pf->hw;
+       i40e_status err;
+
+       err = i40e_aq_send_msg_to_vf(hw, vf_id, VIRTCHNL_OP_IWARP,
+                                    I40E_SUCCESS, msg, len, NULL);
+       if (err)
+               dev_err(&pf->pdev->dev, "Unable to send iWarp message to VF, error %d, aq status %d\n",
+                       err, hw->aq.asq_last_status);
+
+       return err;
+}
+
+/**
+ * i40e_client_setup_qvlist
+ * @ldev: pointer to L2 context.
+ * @client: Client pointer.
+ * @qv_info: queue and vector list
+ *
+ * Return 0 on success or < 0 on error
+ **/
+static int i40e_client_setup_qvlist(struct i40e_info *ldev,
+                                   struct i40e_client *client,
+                                   struct i40e_qvlist_info *qvlist_info)
+{
+       struct i40e_pf *pf = ldev->pf;
+       struct i40e_hw *hw = &pf->hw;
+       struct i40e_qv_info *qv_info;
+       u32 v_idx, i, reg_idx, reg;
+       u32 size;
+
+       size = sizeof(struct i40e_qvlist_info) +
+              (sizeof(struct i40e_qv_info) * (qvlist_info->num_vectors - 1));
+       ldev->qvlist_info = kzalloc(size, GFP_KERNEL);
+       if (!ldev->qvlist_info)
+               return -ENOMEM;
+       ldev->qvlist_info->num_vectors = qvlist_info->num_vectors;
+
+       for (i = 0; i < qvlist_info->num_vectors; i++) {
+               qv_info = &qvlist_info->qv_info[i];
+               if (!qv_info)
+                       continue;
+               v_idx = qv_info->v_idx;
+
+               /* Validate vector id belongs to this client */
+               if ((v_idx >= (pf->iwarp_base_vector + pf->num_iwarp_msix)) ||
+                   (v_idx < pf->iwarp_base_vector))
+                       goto err;
+
+               ldev->qvlist_info->qv_info[i] = *qv_info;
+               reg_idx = I40E_PFINT_LNKLSTN(v_idx - 1);
+
+               if (qv_info->ceq_idx == I40E_QUEUE_INVALID_IDX) {
+                       /* Special case - No CEQ mapped on this vector */
+                       wr32(hw, reg_idx, I40E_PFINT_LNKLSTN_FIRSTQ_INDX_MASK);
+               } else {
+                       reg = (qv_info->ceq_idx &
+                              I40E_PFINT_LNKLSTN_FIRSTQ_INDX_MASK) |
+                              (I40E_QUEUE_TYPE_PE_CEQ <<
+                              I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_SHIFT);
+                       wr32(hw, reg_idx, reg);
+
+                       reg = (I40E_PFINT_CEQCTL_CAUSE_ENA_MASK |
+                              (v_idx << I40E_PFINT_CEQCTL_MSIX_INDX_SHIFT) |
+                              (qv_info->itr_idx <<
+                               I40E_PFINT_CEQCTL_ITR_INDX_SHIFT) |
+                              (I40E_QUEUE_END_OF_LIST <<
+                               I40E_PFINT_CEQCTL_NEXTQ_INDX_SHIFT));
+                       wr32(hw, I40E_PFINT_CEQCTL(qv_info->ceq_idx), reg);
+               }
+               if (qv_info->aeq_idx != I40E_QUEUE_INVALID_IDX) {
+                       reg = (I40E_PFINT_AEQCTL_CAUSE_ENA_MASK |
+                              (v_idx << I40E_PFINT_AEQCTL_MSIX_INDX_SHIFT) |
+                              (qv_info->itr_idx <<
+                               I40E_PFINT_AEQCTL_ITR_INDX_SHIFT));
+
+                       wr32(hw, I40E_PFINT_AEQCTL, reg);
+               }
+       }
+       /* Mitigate sync problems with iwarp VF driver */
+       i40e_flush(hw);
+       return 0;
+err:
+       kfree(ldev->qvlist_info);
+       ldev->qvlist_info = NULL;
+       return -EINVAL;
+}
+
+/**
+ * i40e_client_request_reset
+ * @ldev: pointer to L2 context.
+ * @client: Client pointer.
+ * @level: reset level
+ **/
+static void i40e_client_request_reset(struct i40e_info *ldev,
+                                     struct i40e_client *client,
+                                     u32 reset_level)
+{
+       struct i40e_pf *pf = ldev->pf;
+
+       switch (reset_level) {
+       case I40E_CLIENT_RESET_LEVEL_PF:
+               set_bit(__I40E_PF_RESET_REQUESTED, pf->state);
+               break;
+       case I40E_CLIENT_RESET_LEVEL_CORE:
+               set_bit(__I40E_PF_RESET_REQUESTED, pf->state);
+               break;
+       default:
+               dev_warn(&pf->pdev->dev,
+                        "Client for PF id %d requested an unsupported reset: %d.\n",
+                        pf->hw.pf_id, reset_level);
+               break;
+       }
+
+       i40e_service_event_schedule(pf);
+}
+
+/**
+ * i40e_client_update_vsi_ctxt
+ * @ldev: pointer to L2 context.
+ * @client: Client pointer.
+ * @is_vf: if this for the VF
+ * @vf_id: if is_vf true this carries the vf_id
+ * @flag: Any device level setting that needs to be done for PE
+ * @valid_flag: Bits in this match up and enable changing of flag bits
+ *
+ * Return 0 on success or < 0 on error
+ **/
+static int i40e_client_update_vsi_ctxt(struct i40e_info *ldev,
+                                      struct i40e_client *client,
+                                      bool is_vf, u32 vf_id,
+                                      u32 flag, u32 valid_flag)
+{
+       struct i40e_pf *pf = ldev->pf;
+       struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi];
+       struct i40e_vsi_context ctxt;
+       bool update = true;
+       i40e_status err;
+
+       /* TODO: for now do not allow setting VF's VSI setting */
+       if (is_vf)
+               return -EINVAL;
+
+       ctxt.seid = pf->main_vsi_seid;
+       ctxt.pf_num = pf->hw.pf_id;
+       err = i40e_aq_get_vsi_params(&pf->hw, &ctxt, NULL);
+       ctxt.flags = I40E_AQ_VSI_TYPE_PF;
+       if (err) {
+               dev_info(&pf->pdev->dev,
+                        "couldn't get PF vsi config, err %s aq_err %s\n",
+                        i40e_stat_str(&pf->hw, err),
+                        i40e_aq_str(&pf->hw,
+                                    pf->hw.aq.asq_last_status));
+               return -ENOENT;
+       }
+
+       if ((valid_flag & I40E_CLIENT_VSI_FLAG_TCP_PACKET_ENABLE) &&
+           (flag & I40E_CLIENT_VSI_FLAG_TCP_PACKET_ENABLE)) {
+               ctxt.info.valid_sections =
+                       cpu_to_le16(I40E_AQ_VSI_PROP_QUEUE_OPT_VALID);
+               ctxt.info.queueing_opt_flags |= I40E_AQ_VSI_QUE_OPT_TCP_ENA;
+       } else if ((valid_flag & I40E_CLIENT_VSI_FLAG_TCP_PACKET_ENABLE) &&
+                 !(flag & I40E_CLIENT_VSI_FLAG_TCP_PACKET_ENABLE)) {
+               ctxt.info.valid_sections =
+                       cpu_to_le16(I40E_AQ_VSI_PROP_QUEUE_OPT_VALID);
+               ctxt.info.queueing_opt_flags &= ~I40E_AQ_VSI_QUE_OPT_TCP_ENA;
+       } else {
+               update = false;
+               dev_warn(&pf->pdev->dev,
+                        "Client for PF id %d request an unsupported Config: %x.\n",
+                        pf->hw.pf_id, flag);
+       }
+
+       if (update) {
+               err = i40e_aq_update_vsi_params(&vsi->back->hw, &ctxt, NULL);
+               if (err) {
+                       dev_info(&pf->pdev->dev,
+                                "update VSI ctxt for PE failed, err %s aq_err %s\n",
+                                i40e_stat_str(&pf->hw, err),
+                                i40e_aq_str(&pf->hw,
+                                            pf->hw.aq.asq_last_status));
+               }
+       }
+       return err;
+}
+
+/**
+ * i40e_register_client - Register a i40e client driver with the L2 driver
+ * @client: pointer to the i40e_client struct
+ *
+ * Returns 0 on success or non-0 on error
+ **/
+int i40e_register_client(struct i40e_client *client)
+{
+       int ret = 0;
+
+       if (!client) {
+               ret = -EIO;
+               goto out;
+       }
+
+       if (strlen(client->name) == 0) {
+               pr_info("i40e: Failed to register client with no name\n");
+               ret = -EIO;
+               goto out;
+       }
+
+       if (registered_client) {
+               pr_info("i40e: Client %s has already been registered!\n",
+                       client->name);
+               ret = -EEXIST;
+               goto out;
+       }
+
+       if ((client->version.major != I40E_CLIENT_VERSION_MAJOR) ||
+           (client->version.minor != I40E_CLIENT_VERSION_MINOR)) {
+               pr_info("i40e: Failed to register client %s due to mismatched client interface version\n",
+                       client->name);
+               pr_info("Client is using version: %02d.%02d.%02d while LAN driver supports %s\n",
+                       client->version.major, client->version.minor,
+                       client->version.build,
+                       i40e_client_interface_version_str);
+               ret = -EIO;
+               goto out;
+       }
+
+       registered_client = client;
+
+       i40e_client_prepare(client);
+
+       pr_info("i40e: Registered client %s\n", client->name);
+out:
+       return ret;
+}
+EXPORT_SYMBOL(i40e_register_client);
+
+/**
+ * i40e_unregister_client - Unregister a i40e client driver with the L2 driver
+ * @client: pointer to the i40e_client struct
+ *
+ * Returns 0 on success or non-0 on error
+ **/
+int i40e_unregister_client(struct i40e_client *client)
+{
+       int ret = 0;
+
+       if (registered_client != client) {
+               pr_info("i40e: Client %s has not been registered\n",
+                       client->name);
+               ret = -ENODEV;
+               goto out;
+       }
+       registered_client = NULL;
+       /* When a unregister request comes through we would have to send
+        * a close for each of the client instances that were opened.
+        * client_release function is called to handle this.
+        */
+       i40e_client_release(client);
+
+       pr_info("i40e: Unregistered client %s\n", client->name);
+out:
+       return ret;
+}
+EXPORT_SYMBOL(i40e_unregister_client);
diff --git a/i40e-dkms/i40e-2.1.26/src/i40e_client.h b/i40e-dkms/i40e-2.1.26/src/i40e_client.h
new file mode 100644 (file)
index 0000000..4f02e5b
--- /dev/null
@@ -0,0 +1,224 @@
+/*******************************************************************************
+ *
+ * Intel(R) 40-10 Gigabit Ethernet Connection Network Driver
+ * Copyright(c) 2013 - 2017 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ ******************************************************************************/
+
+#ifndef _I40E_CLIENT_H_
+#define _I40E_CLIENT_H_
+
+#define I40E_CLIENT_STR_LENGTH 10
+
+/* Client interface version should be updated anytime there is a change in the
+ * existing APIs or data structures.
+ */
+#define I40E_CLIENT_VERSION_MAJOR 0
+#define I40E_CLIENT_VERSION_MINOR 01
+#define I40E_CLIENT_VERSION_BUILD 00
+#define I40E_CLIENT_VERSION_STR     \
+       __stringify(I40E_CLIENT_VERSION_MAJOR) "." \
+       __stringify(I40E_CLIENT_VERSION_MINOR) "." \
+       __stringify(I40E_CLIENT_VERSION_BUILD)
+
+struct i40e_client_version {
+       u8 major;
+       u8 minor;
+       u8 build;
+       u8 rsvd;
+};
+
+enum i40e_client_state {
+       __I40E_CLIENT_NULL,
+       __I40E_CLIENT_REGISTERED
+};
+
+enum i40e_client_instance_state {
+       __I40E_CLIENT_INSTANCE_NONE,
+       __I40E_CLIENT_INSTANCE_OPENED,
+};
+
+struct i40e_ops;
+struct i40e_client;
+
+/* HW does not define a type value for AEQ; only for RX/TX and CEQ.
+ * In order for us to keep the interface simple, SW will define a
+ * unique type value for AEQ.
+ */
+#define I40E_QUEUE_TYPE_PE_AEQ  0x80
+#define I40E_QUEUE_INVALID_IDX 0xFFFF
+
+struct i40e_qv_info {
+       u32 v_idx; /* msix_vector */
+       u16 ceq_idx;
+       u16 aeq_idx;
+       u8 itr_idx;
+};
+
+struct i40e_qvlist_info {
+       u32 num_vectors;
+       struct i40e_qv_info qv_info[1];
+};
+
+#define I40E_CLIENT_MSIX_ALL 0xFFFFFFFF
+
+/* set of LAN parameters useful for clients managed by LAN */
+
+/* Struct to hold per priority info */
+struct i40e_prio_qos_params {
+       u16 qs_handle; /* qs handle for prio */
+       u8 tc; /* TC mapped to prio */
+       u8 reserved;
+};
+
+#define I40E_CLIENT_MAX_USER_PRIORITY        8
+/* Struct to hold Client QoS */
+struct i40e_qos_params {
+       struct i40e_prio_qos_params prio_qos[I40E_CLIENT_MAX_USER_PRIORITY];
+};
+
+struct i40e_params {
+       struct i40e_qos_params qos;
+       u16 mtu;
+};
+
+/* Structure to hold Lan device info for a client device */
+struct i40e_info {
+       struct i40e_client_version version;
+       u8 lanmac[6];
+       struct net_device *netdev;
+       struct pci_dev *pcidev;
+       u8 __iomem *hw_addr;
+       u8 fid; /* function id, PF id or VF id */
+#define I40E_CLIENT_FTYPE_PF 0
+#define I40E_CLIENT_FTYPE_VF 1
+       u8 ftype; /* function type, PF or VF */
+       void *pf;
+
+       /* All L2 params that could change during the life span of the PF
+        * and needs to be communicated to the client when they change
+        */
+       struct i40e_qvlist_info *qvlist_info;
+       struct i40e_params params;
+       struct i40e_ops *ops;
+
+       u16 msix_count;  /* number of msix vectors*/
+       /* Array down below will be dynamically allocated based on msix_count */
+       struct msix_entry *msix_entries;
+       u16 itr_index; /* Which ITR index the PE driver is suppose to use */
+       u16 fw_maj_ver;                 /* firmware major version */
+       u16 fw_min_ver;                 /* firmware minor version */
+       u32 fw_build;                   /* firmware build number */
+};
+
+#define I40E_CLIENT_RESET_LEVEL_PF   1
+#define I40E_CLIENT_RESET_LEVEL_CORE 2
+#define I40E_CLIENT_VSI_FLAG_TCP_PACKET_ENABLE  BIT(1)
+
+struct i40e_ops {
+       /* setup_q_vector_list enables queues with a particular vector */
+       int (*setup_qvlist)(struct i40e_info *ldev, struct i40e_client *client,
+                           struct i40e_qvlist_info *qv_info);
+
+       int (*virtchnl_send)(struct i40e_info *ldev, struct i40e_client *client,
+                            u32 vf_id, u8 *msg, u16 len);
+
+       /* If the PE Engine is unresponsive, RDMA driver can request a reset.
+        * The level helps determine the level of reset being requested.
+        */
+       void (*request_reset)(struct i40e_info *ldev,
+                             struct i40e_client *client, u32 level);
+
+       /* API for the RDMA driver to set certain VSI flags that control
+        * PE Engine.
+        */
+       int (*update_vsi_ctxt)(struct i40e_info *ldev,
+                              struct i40e_client *client,
+                              bool is_vf, u32 vf_id,
+                              u32 flag, u32 valid_flag);
+};
+
+struct i40e_client_ops {
+       /* Should be called from register_client() or whenever PF is ready
+        * to create a specific client instance.
+        */
+       int (*open)(struct i40e_info *ldev, struct i40e_client *client);
+
+       /* Should be called when netdev is unavailable or when unregister
+        * call comes in. If the close is happenening due to a reset being
+        * triggered set the reset bit to true.
+        */
+       void (*close)(struct i40e_info *ldev, struct i40e_client *client,
+                     bool reset);
+
+       /* called when some l2 managed parameters changes - mtu */
+       void (*l2_param_change)(struct i40e_info *ldev,
+                               struct i40e_client *client,
+                               struct i40e_params *params);
+
+       int (*virtchnl_receive)(struct i40e_info *ldev,
+                               struct i40e_client *client, u32 vf_id,
+                               u8 *msg, u16 len);
+
+       /* called when a VF is reset by the PF */
+       void (*vf_reset)(struct i40e_info *ldev,
+                        struct i40e_client *client, u32 vf_id);
+
+       /* called when the number of VFs changes */
+       void (*vf_enable)(struct i40e_info *ldev,
+                         struct i40e_client *client, u32 num_vfs);
+
+       /* returns true if VF is capable of specified offload */
+       int (*vf_capable)(struct i40e_info *ldev,
+                         struct i40e_client *client, u32 vf_id);
+};
+
+/* Client device */
+struct i40e_client_instance {
+       struct list_head list;
+       struct i40e_info lan_info;
+       struct i40e_client *client;
+       unsigned long  state;
+};
+
+struct i40e_client {
+       struct list_head list;          /* list of registered clients */
+       char name[I40E_CLIENT_STR_LENGTH];
+       struct i40e_client_version version;
+       unsigned long state;            /* client state */
+       atomic_t ref_cnt;  /* Count of all the client devices of this kind */
+       u32 flags;
+#define I40E_CLIENT_FLAGS_LAUNCH_ON_PROBE      BIT(0)
+#define I40E_TX_FLAGS_NOTIFY_OTHER_EVENTS      BIT(2)
+       u8 type;
+#define I40E_CLIENT_IWARP 0
+       /* client ops provided by the client */
+       const struct i40e_client_ops *ops;
+};
+
+static inline bool i40e_client_is_registered(struct i40e_client *client)
+{
+       return test_bit(__I40E_CLIENT_REGISTERED, &client->state);
+}
+
+/* used by clients */
+int i40e_register_client(struct i40e_client *client);
+int i40e_unregister_client(struct i40e_client *client);
+
+#endif /* _I40E_CLIENT_H_ */
similarity index 87%
rename from i40e-dkms/i40e-1.6.42/src/i40e_common.c
rename to i40e-dkms/i40e-2.1.26/src/i40e_common.c
index 49ce425139d20045a148286442d77b30a498f9a3..0e864bd63992854d4a31c0a9c15ca38648b7dfd8 100644 (file)
@@ -24,7 +24,7 @@
 #include "i40e_type.h"
 #include "i40e_adminq.h"
 #include "i40e_prototype.h"
-#include "i40e_virtchnl.h"
+#include "virtchnl.h"
 
 /**
  * i40e_set_mac_type - Sets MAC type
@@ -295,13 +295,14 @@ void i40e_debug_aq(struct i40e_hw *hw, enum i40e_debug_mask mask, void *desc,
                   void *buffer, u16 buf_len)
 {
        struct i40e_aq_desc *aq_desc = (struct i40e_aq_desc *)desc;
-       u16 len = LE16_TO_CPU(aq_desc->datalen);
        u8 *buf = (u8 *)buffer;
-       u16 i = 0;
+       u16 len;
 
        if ((!(mask & hw->debug_mask)) || (desc == NULL))
                return;
 
+       len = LE16_TO_CPU(aq_desc->datalen);
+
        i40e_debug(hw, mask,
                   "AQ CMD: opcode 0x%04X, flags 0x%04X, datalen 0x%04X, retval 0x%04X\n",
                   LE16_TO_CPU(aq_desc->opcode),
@@ -323,12 +324,18 @@ void i40e_debug_aq(struct i40e_hw *hw, enum i40e_debug_mask mask, void *desc,
                if (buf_len < len)
                        len = buf_len;
                /* write the full 16-byte chunks */
-               for (i = 0; i < (len - 16); i += 16)
-                       i40e_debug(hw, mask, "\t0x%04X  %16ph\n", i, buf + i);
-               /* write whatever's left over without overrunning the buffer */
-               if (i < len)
-                       i40e_debug(hw, mask, "\t0x%04X  %*ph\n",
-                                            i, len - i, buf + i);
+               if (hw->debug_mask & mask) {
+                       char prefix[27];
+
+                       snprintf(prefix, sizeof(prefix),
+                                "i40e %02x:%02x.%x: \t0x",
+                                hw->bus.bus_id,
+                                hw->bus.device,
+                                hw->bus.func);
+
+                       print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_OFFSET,
+                                      16, 1, buf, len, false);
+               }
        }
 }
 
@@ -1077,34 +1084,6 @@ void i40e_pre_tx_queue_cfg(struct i40e_hw *hw, u32 queue, bool enable)
 
        wr32(hw, I40E_GLLAN_TXPRE_QDIS(reg_block), reg_val);
 }
-#ifdef I40E_FCOE
-
-/**
- * i40e_get_san_mac_addr - get SAN MAC address
- * @hw: pointer to the HW structure
- * @mac_addr: pointer to SAN MAC address
- *
- * Reads the adapter's SAN MAC address from NVM
- **/
-i40e_status i40e_get_san_mac_addr(struct i40e_hw *hw,
-                                           u8 *mac_addr)
-{
-       struct i40e_aqc_mac_address_read_data addrs;
-       i40e_status status;
-       u16 flags = 0;
-
-       status = i40e_aq_mac_address_read(hw, &flags, &addrs, NULL);
-       if (status)
-               return status;
-
-       if (flags & I40E_AQC_SAN_ADDR_VALID)
-               ether_addr_copy(mac_addr, addrs.pf_san_mac);
-       else
-               status = I40E_ERR_INVALID_MAC_ADDR;
-
-       return status;
-}
-#endif
 
 /**
  *  i40e_read_pba_string - Reads part number string from EEPROM
@@ -1197,6 +1176,8 @@ static enum i40e_media_type i40e_get_media_type(struct i40e_hw *hw)
        case I40E_PHY_TYPE_40GBASE_AOC:
        case I40E_PHY_TYPE_10GBASE_AOC:
        case I40E_PHY_TYPE_25GBASE_CR:
+       case I40E_PHY_TYPE_25GBASE_AOC:
+       case I40E_PHY_TYPE_25GBASE_ACC:
                media = I40E_MEDIA_TYPE_DA;
                break;
        case I40E_PHY_TYPE_1000BASE_KX:
@@ -1279,6 +1260,8 @@ i40e_status i40e_pf_reset(struct i40e_hw *hw)
         * we don't need to do the PF Reset
         */
        if (!cnt) {
+               u32 reg2 = 0;
+
                reg = rd32(hw, I40E_PFGEN_CTRL);
                wr32(hw, I40E_PFGEN_CTRL,
                     (reg | I40E_PFGEN_CTRL_PFSWR_MASK));
@@ -1286,6 +1269,12 @@ i40e_status i40e_pf_reset(struct i40e_hw *hw)
                        reg = rd32(hw, I40E_PFGEN_CTRL);
                        if (!(reg & I40E_PFGEN_CTRL_PFSWR_MASK))
                                break;
+                       reg2 = rd32(hw, I40E_GLGEN_RSTAT);
+                       if (reg2 & I40E_GLGEN_RSTAT_DEVSTATE_MASK) {
+                               hw_dbg(hw, "Core reset upcoming.\n");
+                               hw_dbg(hw, "I40E_GLGEN_RSTAT = 0x%x\n", reg2);
+                               return I40E_ERR_NOT_READY;
+                       }
                        usleep_range(1000, 2000);
                }
                if (reg & I40E_PFGEN_CTRL_PFSWR_MASK) {
@@ -1590,8 +1579,15 @@ i40e_status i40e_aq_get_phy_capabilities(struct i40e_hw *hw,
                status = I40E_ERR_UNKNOWN_PHY;
 
        if (report_init) {
-               hw->phy.phy_types = LE32_TO_CPU(abilities->phy_type);
-               hw->phy.phy_types |= ((u64)abilities->phy_type_ext << 32);
+               if (hw->mac.type ==  I40E_MAC_XL710 &&
+                   hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR &&
+                   hw->aq.api_min_ver >= I40E_MINOR_VER_GET_LINK_INFO_XL710) {
+                       status = i40e_aq_get_link_info(hw, true, NULL, NULL);
+               } else {
+                       hw->phy.phy_types = LE32_TO_CPU(abilities->phy_type);
+                       hw->phy.phy_types |=
+                                       ((u64)abilities->phy_type_ext << 32);
+               }
        }
 
        return status;
@@ -1816,7 +1812,7 @@ i40e_status i40e_aq_get_link_info(struct i40e_hw *hw,
        hw_link_info->fec_info = resp->config & (I40E_AQ_CONFIG_FEC_KR_ENA |
                                                 I40E_AQ_CONFIG_FEC_RS_ENA);
        hw_link_info->ext_info = resp->ext_info;
-       hw_link_info->loopback = resp->loopback;
+       hw_link_info->loopback = resp->loopback & I40E_AQ_LOOPBACK_MASK;
        hw_link_info->max_frame_size = LE16_TO_CPU(resp->max_frame_size);
        hw_link_info->pacing = resp->config & I40E_AQ_CONFIG_PACING_MASK;
 
@@ -1847,6 +1843,12 @@ i40e_status i40e_aq_get_link_info(struct i40e_hw *hw,
             hw->aq.fw_min_ver < 40)) && hw_link_info->phy_type == 0xE)
                hw_link_info->phy_type = I40E_PHY_TYPE_10GBASE_SFPP_CU;
 
+       if (hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR &&
+           hw->aq.api_min_ver >= 7) {
+               hw->phy.phy_types = LE32_TO_CPU(*(__le32 *)resp->link_type);
+               hw->phy.phy_types |= ((u64)resp->link_type_ext << 32);
+       }
+
        /* save link status information */
        if (link)
                i40e_memcpy(link, hw_link_info, sizeof(*hw_link_info),
@@ -2423,7 +2425,11 @@ i40e_status i40e_aq_set_switch_config(struct i40e_hw *hw,
                                          i40e_aqc_opc_set_switch_config);
        scfg->flags = CPU_TO_LE16(flags);
        scfg->valid_flags = CPU_TO_LE16(valid_flags);
-
+       if (hw->flags & I40E_HW_FLAG_802_1AD_CAPABLE) {
+               scfg->switch_tag = CPU_TO_LE16(hw->switch_tag);
+               scfg->first_tag = CPU_TO_LE16(hw->first_tag);
+               scfg->second_tag = CPU_TO_LE16(hw->second_tag);
+       }
        status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
 
        return status;
@@ -2561,6 +2567,10 @@ i40e_status i40e_update_link_info(struct i40e_hw *hw)
                if (status)
                        return status;
 
+               hw->phy.link_info.req_fec_info =
+                       abilities.fec_cfg_curr_mod_ext_info &
+                       (I40E_AQ_REQUEST_FEC_KR | I40E_AQ_REQUEST_FEC_RS);
+
                i40e_memcpy(hw->phy.link_info.module_type, &abilities.module_type,
                        sizeof(hw->phy.link_info.module_type), I40E_NONDMA_TO_NONDMA);
        }
@@ -3547,16 +3557,8 @@ static void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff,
        if (p->fcoe)
                i40e_debug(hw, I40E_DEBUG_ALL, "device is FCoE capable\n");
 
-#ifdef I40E_FCOE_ENA
-       /* Software override ensuring FCoE is disabled if npar or mfp
-        * mode because it is not supported in these modes.
-        */
-       if (p->npar_enable || p->flex10_enable)
-               p->fcoe = false;
-#else
        /* Always disable FCoE if compiled without the I40E_FCOE_ENA flag */
        p->fcoe = false;
-#endif
 
        /* count the enabled ports (aka the "not disabled" ports) */
        hw->num_ports = 0;
@@ -3919,11 +3921,15 @@ i40e_status i40e_aq_start_stop_dcbx(struct i40e_hw *hw,
 /**
  * i40e_aq_add_udp_tunnel
  * @hw: pointer to the hw struct
- * @udp_port: the UDP port to add
+ * @udp_port: the UDP port to add in Host byte order
  * @header_len: length of the tunneling header length in DWords
  * @protocol_index: protocol index type
  * @filter_index: pointer to filter index
  * @cmd_details: pointer to command details structure or NULL
+ *
+ * Note: Firmware expects the udp_port value to be in Little Endian format,
+ * and this function will call CPU_TO_LE16 to convert from Host byte order to
+ * Little Endian order.
  **/
 i40e_status i40e_aq_add_udp_tunnel(struct i40e_hw *hw,
                                u16 udp_port, u8 protocol_index,
@@ -4611,6 +4617,59 @@ i40e_status i40e_aq_add_cloud_filters(struct i40e_hw *hw,
        return status;
 }
 
+/**
+ * i40e_aq_add_cloud_filters_big_buffer
+ * @hw: pointer to the hardware structure
+ * @seid: VSI seid to add cloud filters from
+ * @filters: Buffer which contains the filters in big buffer to be added
+ * @filter_count: number of filters contained in the buffer
+ *
+ * Set the cloud filters for a given VSI.  The contents of the
+ * i40e_aqc_add_rm_cloud_filt_elem_ext are filled in by the caller of
+ * the function.
+ *
+ **/
+i40e_status i40e_aq_add_cloud_filters_big_buffer(struct i40e_hw *hw,
+       u16 seid,
+       struct i40e_aqc_add_rm_cloud_filt_elem_ext *filters,
+       u8 filter_count)
+{
+       struct i40e_aq_desc desc;
+       struct i40e_aqc_add_remove_cloud_filters *cmd =
+       (struct i40e_aqc_add_remove_cloud_filters *)&desc.params.raw;
+       i40e_status status;
+       u16 buff_len;
+       int i;
+
+       i40e_fill_default_direct_cmd_desc(&desc,
+                                         i40e_aqc_opc_add_cloud_filters);
+
+       buff_len = filter_count * sizeof(*filters);
+       desc.datalen = CPU_TO_LE16(buff_len);
+       desc.flags |= CPU_TO_LE16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD));
+       cmd->num_filters = filter_count;
+       cmd->seid = CPU_TO_LE16(seid);
+       cmd->big_buffer_flag = I40E_AQC_ADD_REM_CLOUD_CMD_BIG_BUFFER;
+
+       /* adjust Geneve VNI for HW issue */
+       for (i = 0; i < filter_count; i++) {
+               u16 tnl_type;
+               u32 ti;
+
+               tnl_type = (LE16_TO_CPU(filters[i].element.flags) &
+                          I40E_AQC_ADD_CLOUD_TNL_TYPE_MASK) >>
+                          I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT;
+               if (tnl_type == I40E_AQC_ADD_CLOUD_TNL_TYPE_GENEVE) {
+                       ti = LE32_TO_CPU(filters[i].element.tenant_id);
+                       filters[i].element.tenant_id = CPU_TO_LE32(ti << 8);
+               }
+       }
+
+       status = i40e_asq_send_command(hw, &desc, filters, buff_len, NULL);
+
+       return status;
+}
+
 /**
  * i40e_aq_remove_cloud_filters
  * @hw: pointer to the hardware structure
@@ -4624,9 +4683,9 @@ i40e_status i40e_aq_add_cloud_filters(struct i40e_hw *hw,
  *
  **/
 i40e_status i40e_aq_remove_cloud_filters(struct i40e_hw *hw,
-               u16 seid,
-               struct i40e_aqc_add_remove_cloud_filters_element_data *filters,
-               u8 filter_count)
+       u16 seid,
+       struct i40e_aqc_add_remove_cloud_filters_element_data *filters,
+       u8 filter_count)
 {
        struct i40e_aq_desc desc;
        struct i40e_aqc_add_remove_cloud_filters *cmd =
@@ -4650,6 +4709,102 @@ i40e_status i40e_aq_remove_cloud_filters(struct i40e_hw *hw,
        return status;
 }
 
+/**
+ * i40e_aq_remove_cloud_filters_big_buffer
+ * @hw: pointer to the hardware structure
+ * @seid: VSI seid to remove cloud filters from
+ * @filters: Buffer which contains the filters in big buffer to be removed
+ * @filter_count: number of filters contained in the buffer
+ *
+ * Remove the cloud filters for a given VSI.  The contents of the
+ * i40e_aqc_add_rm_cloud_filt_elem_ext are filled in by the caller of
+ * the function.
+ *
+ **/
+i40e_status i40e_aq_remove_cloud_filters_big_buffer(
+       struct i40e_hw *hw,
+       u16 seid,
+       struct i40e_aqc_add_rm_cloud_filt_elem_ext *filters,
+       u8 filter_count)
+{
+       struct i40e_aq_desc desc;
+       struct i40e_aqc_add_remove_cloud_filters *cmd =
+       (struct i40e_aqc_add_remove_cloud_filters *)&desc.params.raw;
+       i40e_status status;
+       u16 buff_len;
+       int i;
+
+       i40e_fill_default_direct_cmd_desc(&desc,
+                                         i40e_aqc_opc_remove_cloud_filters);
+
+       buff_len = filter_count * sizeof(*filters);
+       desc.datalen = CPU_TO_LE16(buff_len);
+       desc.flags |= CPU_TO_LE16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD));
+       cmd->num_filters = filter_count;
+       cmd->seid = CPU_TO_LE16(seid);
+       cmd->big_buffer_flag = I40E_AQC_ADD_REM_CLOUD_CMD_BIG_BUFFER;
+
+       /* adjust Geneve VNI for HW issue */
+       for (i = 0; i < filter_count; i++) {
+               u16 tnl_type;
+               u32 ti;
+
+               tnl_type = (LE16_TO_CPU(filters[i].element.flags) &
+                          I40E_AQC_ADD_CLOUD_TNL_TYPE_MASK) >>
+                          I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT;
+               if (tnl_type == I40E_AQC_ADD_CLOUD_TNL_TYPE_GENEVE) {
+                       ti = LE32_TO_CPU(filters[i].element.tenant_id);
+                       filters[i].element.tenant_id = CPU_TO_LE32(ti << 8);
+               }
+       }
+
+       status = i40e_asq_send_command(hw, &desc, filters, buff_len, NULL);
+
+       return status;
+}
+
+/**
+ * i40e_aq_replace_cloud_filters - Replace cloud filter command
+ * @hw: pointer to the hw struct
+ * @filters: pointer to the i40e_aqc_replace_cloud_filter_cmd struct
+ * @cmd_buf: pointer to the i40e_aqc_replace_cloud_filter_cmd_buf struct
+ *
+ **/
+enum
+i40e_status_code i40e_aq_replace_cloud_filters(struct i40e_hw *hw,
+       struct i40e_aqc_replace_cloud_filters_cmd *filters,
+       struct i40e_aqc_replace_cloud_filters_cmd_buf *cmd_buf)
+{
+       struct i40e_aq_desc desc;
+       struct i40e_aqc_replace_cloud_filters_cmd *cmd =
+               (struct i40e_aqc_replace_cloud_filters_cmd *)&desc.params.raw;
+       i40e_status status = I40E_SUCCESS;
+       int i = 0;
+
+       i40e_fill_default_direct_cmd_desc(&desc,
+                                         i40e_aqc_opc_replace_cloud_filters);
+
+       desc.datalen = CPU_TO_LE16(32);
+       desc.flags |= CPU_TO_LE16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD));
+       cmd->old_filter_type = filters->old_filter_type;
+       cmd->new_filter_type = filters->new_filter_type;
+       cmd->valid_flags = filters->valid_flags;
+       cmd->tr_bit = filters->tr_bit;
+
+       status = i40e_asq_send_command(hw, &desc, cmd_buf,
+               sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf),  NULL);
+
+       /* for get cloud filters command */
+       for (i = 0; i < 32; i += 4) {
+               cmd_buf->filters[i / 4].filter_type = cmd_buf->data[i];
+               cmd_buf->filters[i / 4].input[0] = cmd_buf->data[i + 1];
+               cmd_buf->filters[i / 4].input[1] = cmd_buf->data[i + 2];
+               cmd_buf->filters[i / 4].input[2] = cmd_buf->data[i + 3];
+       }
+
+       return status;
+}
+
 /**
  * i40e_aq_alternate_read
  * @hw: pointer to the hardware structure
@@ -5290,24 +5445,38 @@ i40e_status i40e_led_get_phy(struct i40e_hw *hw, u16 *led_addr,
        u16 temp_addr;
        u8 port_num;
        u32 i;
-
-       temp_addr = I40E_PHY_LED_PROV_REG_1;
-       i = rd32(hw, I40E_PFGEN_PORTNUM);
-       port_num = (u8)(i & I40E_PFGEN_PORTNUM_PORT_NUM_MASK);
-       phy_addr = i40e_get_phy_address(hw, port_num);
-
-       for (gpio_led_port = 0; gpio_led_port < 3; gpio_led_port++,
-            temp_addr++) {
-               status = i40e_read_phy_register_clause45(hw,
+       u32 reg_val_aq;
+
+       if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) {
+               status =
+                     i40e_aq_get_phy_register(hw,
+                                              I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
+                                              I40E_PHY_COM_REG_PAGE,
+                                              I40E_PHY_LED_PROV_REG_1,
+                                              &reg_val_aq, NULL);
+               if (status)
+                       return status;
+               *val = (u16)reg_val_aq;
+       } else {
+               temp_addr = I40E_PHY_LED_PROV_REG_1;
+               i = rd32(hw, I40E_PFGEN_PORTNUM);
+               port_num = (u8)(i & I40E_PFGEN_PORTNUM_PORT_NUM_MASK);
+               phy_addr = i40e_get_phy_address(hw, port_num);
+
+               for (gpio_led_port = 0; gpio_led_port < 3; gpio_led_port++,
+                    temp_addr++) {
+                       status =
+                        i40e_read_phy_register_clause45(hw,
                                                         I40E_PHY_COM_REG_PAGE,
                                                         temp_addr, phy_addr,
                                                         &reg_val);
-               if (status)
-                       return status;
-               *val = reg_val;
-               if (reg_val & I40E_PHY_LED_LINK_MODE_MASK) {
-                       *led_addr = temp_addr;
-                       break;
+                       if (status)
+                               return status;
+                       *val = reg_val;
+                       if (reg_val & I40E_PHY_LED_LINK_MODE_MASK) {
+                               *led_addr = temp_addr;
+                               break;
+                       }
                }
        }
        return status;
@@ -5325,51 +5494,115 @@ i40e_status i40e_led_set_phy(struct i40e_hw *hw, bool on,
                                       u16 led_addr, u32 mode)
 {
        i40e_status status = I40E_SUCCESS;
-       u16 led_ctl = 0;
-       u16 led_reg = 0;
+       u32 led_ctl = 0;
+       u32 led_reg = 0;
        u8 phy_addr = 0;
        u8 port_num;
        u32 i;
 
-       i = rd32(hw, I40E_PFGEN_PORTNUM);
-       port_num = (u8)(i & I40E_PFGEN_PORTNUM_PORT_NUM_MASK);
-       phy_addr = i40e_get_phy_address(hw, port_num);
-       status = i40e_read_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
-                                                led_addr, phy_addr, &led_reg);
+       if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) {
+               status =
+                     i40e_aq_get_phy_register(hw,
+                                              I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
+                                              I40E_PHY_COM_REG_PAGE,
+                                              I40E_PHY_LED_PROV_REG_1,
+                                              &led_reg, NULL);
+       } else {
+               i = rd32(hw, I40E_PFGEN_PORTNUM);
+               port_num = (u8)(i & I40E_PFGEN_PORTNUM_PORT_NUM_MASK);
+               phy_addr = i40e_get_phy_address(hw, port_num);
+               status = i40e_read_phy_register_clause45(hw,
+                                                        I40E_PHY_COM_REG_PAGE,
+                                                        led_addr, phy_addr,
+                                                        (u16 *)&led_reg);
+       }
        if (status)
                return status;
        led_ctl = led_reg;
        if (led_reg & I40E_PHY_LED_LINK_MODE_MASK) {
                led_reg = 0;
-               status = i40e_write_phy_register_clause45(hw,
-                                                         I40E_PHY_COM_REG_PAGE,
-                                                         led_addr, phy_addr,
-                                                         led_reg);
+               if (hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR &&
+                   hw->aq.api_min_ver >= I40E_MINOR_VER_GET_LINK_INFO_XL710) {
+                       status = i40e_aq_set_phy_register(hw,
+                                       I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
+                                       I40E_PHY_COM_REG_PAGE,
+                                       I40E_PHY_LED_PROV_REG_1,
+                                       led_reg, NULL);
+               } else {
+                       status = i40e_write_phy_register_clause45(hw,
+                                                       I40E_PHY_COM_REG_PAGE,
+                                                       led_addr, phy_addr,
+                                                       (u16)led_reg);
+               }
                if (status)
                        return status;
        }
-       status = i40e_read_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
-                                                led_addr, phy_addr, &led_reg);
+       if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) {
+               status =
+                     i40e_aq_get_phy_register(hw,
+                                              I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
+                                              I40E_PHY_COM_REG_PAGE,
+                                              I40E_PHY_LED_PROV_REG_1,
+                                              &led_reg, NULL);
+       } else {
+               status = i40e_read_phy_register_clause45(hw,
+                                                        I40E_PHY_COM_REG_PAGE,
+                                                        led_addr, phy_addr,
+                                                        (u16 *)&led_reg);
+       }
        if (status)
                goto restore_config;
        if (on)
                led_reg = I40E_PHY_LED_MANUAL_ON;
        else
                led_reg = 0;
-       status = i40e_write_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
-                                                 led_addr, phy_addr, led_reg);
+
+       if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) {
+               status =
+                     i40e_aq_set_phy_register(hw,
+                                              I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
+                                              I40E_PHY_COM_REG_PAGE,
+                                              I40E_PHY_LED_PROV_REG_1,
+                                              led_reg, NULL);
+       } else {
+               status =
+                   i40e_write_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
+                                                    led_addr, phy_addr,
+                                                    (u16)led_reg);
+       }
        if (status)
                goto restore_config;
        if (mode & I40E_PHY_LED_MODE_ORIG) {
                led_ctl = (mode & I40E_PHY_LED_MODE_MASK);
-               status = i40e_write_phy_register_clause45(hw,
-                                                I40E_PHY_COM_REG_PAGE,
-                                                led_addr, phy_addr, led_ctl);
+               if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) {
+                       status = i40e_aq_set_phy_register(hw,
+                                       I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
+                                       I40E_PHY_COM_REG_PAGE,
+                                       I40E_PHY_LED_PROV_REG_1,
+                                       led_ctl, NULL);
+               } else {
+                       status = i40e_write_phy_register_clause45(hw,
+                                                        I40E_PHY_COM_REG_PAGE,
+                                                        led_addr, phy_addr,
+                                                        (u16)led_ctl);
+               }
        }
        return status;
 restore_config:
-       status = i40e_write_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
-                                                 led_addr, phy_addr, led_ctl);
+       if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) {
+               status =
+                     i40e_aq_set_phy_register(hw,
+                                              I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
+                                              I40E_PHY_COM_REG_PAGE,
+                                              I40E_PHY_LED_PROV_REG_1,
+                                              led_ctl, NULL);
+       } else {
+               status =
+                       i40e_write_phy_register_clause45(hw,
+                                                        I40E_PHY_COM_REG_PAGE,
+                                                        led_addr, phy_addr,
+                                                        (u16)led_ctl);
+       }
        return status;
 }
 
@@ -5419,7 +5652,9 @@ u32 i40e_read_rx_ctl(struct i40e_hw *hw, u32 reg_addr)
        int retry = 5;
        u32 val = 0;
 
-       use_register = (hw->aq.api_maj_ver == 1) && (hw->aq.api_min_ver < 5);
+       use_register = (((hw->aq.api_maj_ver == 1) &&
+                       (hw->aq.api_min_ver < 5)) ||
+                       (hw->mac.type == I40E_MAC_X722));
        if (!use_register) {
 do_retry:
                status = i40e_aq_rx_ctl_read_register(hw, reg_addr, &val, NULL);
@@ -5478,7 +5713,9 @@ void i40e_write_rx_ctl(struct i40e_hw *hw, u32 reg_addr, u32 reg_val)
        bool use_register;
        int retry = 5;
 
-       use_register = (hw->aq.api_maj_ver == 1) && (hw->aq.api_min_ver < 5);
+       use_register = (((hw->aq.api_maj_ver == 1) &&
+                       (hw->aq.api_min_ver < 5)) ||
+                       (hw->mac.type == I40E_MAC_X722));
        if (!use_register) {
 do_retry:
                status = i40e_aq_rx_ctl_write_register(hw, reg_addr,
@@ -5495,6 +5732,75 @@ do_retry:
                wr32(hw, reg_addr, reg_val);
 }
 
+/**
+ * i40e_aq_set_phy_register
+ * @hw: pointer to the hw struct
+ * @phy_select: select which phy should be accessed
+ * @dev_addr: PHY device address
+ * @reg_addr: PHY register address
+ * @reg_val: new register value
+ * @cmd_details: pointer to command details structure or NULL
+ *
+ * Write the external PHY register.
+ **/
+i40e_status i40e_aq_set_phy_register(struct i40e_hw *hw,
+                               u8 phy_select, u8 dev_addr,
+                               u32 reg_addr, u32 reg_val,
+                               struct i40e_asq_cmd_details *cmd_details)
+{
+       struct i40e_aq_desc desc;
+       struct i40e_aqc_phy_register_access *cmd =
+               (struct i40e_aqc_phy_register_access *)&desc.params.raw;
+       i40e_status status;
+
+       i40e_fill_default_direct_cmd_desc(&desc,
+                                         i40e_aqc_opc_set_phy_register);
+
+       cmd->phy_interface = phy_select;
+       cmd->dev_addres = dev_addr;
+       cmd->reg_address = reg_addr;
+       cmd->reg_value = reg_val;
+
+       status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
+
+       return status;
+}
+
+/**
+ * i40e_aq_get_phy_register
+ * @hw: pointer to the hw struct
+ * @phy_select: select which phy should be accessed
+ * @dev_addr: PHY device address
+ * @reg_addr: PHY register address
+ * @reg_val: read register value
+ * @cmd_details: pointer to command details structure or NULL
+ *
+ * Read the external PHY register.
+ **/
+i40e_status i40e_aq_get_phy_register(struct i40e_hw *hw,
+                               u8 phy_select, u8 dev_addr,
+                               u32 reg_addr, u32 *reg_val,
+                               struct i40e_asq_cmd_details *cmd_details)
+{
+       struct i40e_aq_desc desc;
+       struct i40e_aqc_phy_register_access *cmd =
+               (struct i40e_aqc_phy_register_access *)&desc.params.raw;
+       i40e_status status;
+
+       i40e_fill_default_direct_cmd_desc(&desc,
+                                         i40e_aqc_opc_get_phy_register);
+
+       cmd->phy_interface = phy_select;
+       cmd->dev_addres = dev_addr;
+       cmd->reg_address = reg_addr;
+
+       status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
+       if (!status)
+               *reg_val = cmd->reg_value;
+
+       return status;
+}
+
 /**
  * i40e_aq_set_arp_proxy_config
  * @hw: pointer to the HW structure
@@ -5522,7 +5828,7 @@ i40e_status i40e_aq_set_arp_proxy_config(struct i40e_hw *hw,
                                  CPU_TO_LE32(upper_32_bits((u64)proxy_config));
        desc.params.external.addr_low =
                                  CPU_TO_LE32(lower_32_bits((u64)proxy_config));
-       desc.datalen = sizeof(struct i40e_aqc_arp_proxy_data);
+       desc.datalen = CPU_TO_LE16(sizeof(struct i40e_aqc_arp_proxy_data));
 
        status = i40e_asq_send_command(hw, &desc, proxy_config,
                                       sizeof(struct i40e_aqc_arp_proxy_data),
@@ -5559,7 +5865,7 @@ i40e_status i40e_aq_set_ns_proxy_table_entry(struct i40e_hw *hw,
                CPU_TO_LE32(upper_32_bits((u64)ns_proxy_table_entry));
        desc.params.external.addr_low =
                CPU_TO_LE32(lower_32_bits((u64)ns_proxy_table_entry));
-       desc.datalen = sizeof(struct i40e_aqc_ns_proxy_data);
+       desc.datalen = CPU_TO_LE16(sizeof(struct i40e_aqc_ns_proxy_data));
 
        status = i40e_asq_send_command(hw, &desc, ns_proxy_table_entry,
                                       sizeof(struct i40e_aqc_ns_proxy_data),
@@ -5622,7 +5928,7 @@ i40e_status i40e_aq_set_clear_wol_filter(struct i40e_hw *hw,
        cmd->valid_flags = CPU_TO_LE16(valid_flags);
 
        buff_len = sizeof(*filter);
-       desc.datalen = buff_len;
+       desc.datalen = CPU_TO_LE16(buff_len);
 
        desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_BUF);
        desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_RD);
@@ -5684,3 +5990,421 @@ i40e_status i40e_aq_clear_all_wol_filters(struct i40e_hw *hw,
        return status;
 }
 
+/**
+ * i40e_aq_write_ddp - Write dynamic device personalization (ddp)
+ * @hw: pointer to the hw struct
+ * @buff: command buffer (size in bytes = buff_size)
+ * @buff_size: buffer size in bytes
+ * @track_id: package tracking id
+ * @error_offset: returns error offset
+ * @error_info: returns error information
+ * @cmd_details: pointer to command details structure or NULL
+ **/
+enum
+i40e_status_code i40e_aq_write_ddp(struct i40e_hw *hw, void *buff,
+                                  u16 buff_size, u32 track_id,
+                                  u32 *error_offset, u32 *error_info,
+                                  struct i40e_asq_cmd_details *cmd_details)
+{
+       struct i40e_aq_desc desc;
+       struct i40e_aqc_write_personalization_profile *cmd =
+               (struct i40e_aqc_write_personalization_profile *)
+               &desc.params.raw;
+       struct i40e_aqc_write_ddp_resp *resp;
+       i40e_status status;
+
+       i40e_fill_default_direct_cmd_desc(&desc,
+                                 i40e_aqc_opc_write_personalization_profile);
+
+       desc.flags |= CPU_TO_LE16(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD);
+       if (buff_size > I40E_AQ_LARGE_BUF)
+               desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB);
+
+       desc.datalen = CPU_TO_LE16(buff_size);
+
+       cmd->profile_track_id = CPU_TO_LE32(track_id);
+
+       status = i40e_asq_send_command(hw, &desc, buff, buff_size, cmd_details);
+       if (!status) {
+               resp = (struct i40e_aqc_write_ddp_resp *)&desc.params.raw;
+               if (error_offset)
+                       *error_offset = LE32_TO_CPU(resp->error_offset);
+               if (error_info)
+                       *error_info = LE32_TO_CPU(resp->error_info);
+       }
+
+       return status;
+}
+
+/**
+ * i40e_aq_get_ddp_list - Read dynamic device personalization (ddp)
+ * @hw: pointer to the hw struct
+ * @buff: command buffer (size in bytes = buff_size)
+ * @buff_size: buffer size in bytes
+ * @cmd_details: pointer to command details structure or NULL
+ **/
+enum
+i40e_status_code i40e_aq_get_ddp_list(struct i40e_hw *hw, void *buff,
+                                     u16 buff_size, u8 flags,
+                                     struct i40e_asq_cmd_details *cmd_details)
+{
+       struct i40e_aq_desc desc;
+       struct i40e_aqc_get_applied_profiles *cmd =
+               (struct i40e_aqc_get_applied_profiles *)&desc.params.raw;
+       i40e_status status;
+
+       i40e_fill_default_direct_cmd_desc(&desc,
+                         i40e_aqc_opc_get_personalization_profile_list);
+
+       desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_BUF);
+       if (buff_size > I40E_AQ_LARGE_BUF)
+               desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB);
+       desc.datalen = CPU_TO_LE16(buff_size);
+
+       cmd->flags = flags;
+
+       status = i40e_asq_send_command(hw, &desc, buff, buff_size, cmd_details);
+
+       return status;
+}
+
+/**
+ * i40e_find_segment_in_package
+ * @segment_type: the segment type to search for (i.e., SEGMENT_TYPE_I40E)
+ * @pkg_hdr: pointer to the package header to be searched
+ *
+ * This function searches a package file for a particular segment type. On
+ * success it returns a pointer to the segment header, otherwise it will
+ * return NULL.
+ **/
+struct i40e_generic_seg_header *
+i40e_find_segment_in_package(u32 segment_type,
+                            struct i40e_package_header *pkg_hdr)
+{
+       struct i40e_generic_seg_header *segment;
+       u32 i;
+
+       /* Search all package segments for the requested segment type */
+       for (i = 0; i < pkg_hdr->segment_count; i++) {
+               segment =
+                       (struct i40e_generic_seg_header *)((u8 *)pkg_hdr +
+                        pkg_hdr->segment_offset[i]);
+
+               if (segment->type == segment_type)
+                       return segment;
+       }
+
+       return NULL;
+}
+
+/* Get section table in profile */
+#define I40E_SECTION_TABLE(profile, sec_tbl)                           \
+       do {                                                            \
+               struct i40e_profile_segment *p = (profile);             \
+               u32 count;                                              \
+               u32 *nvm;                                               \
+               count = p->device_table_count;                          \
+               nvm = (u32 *)&p->device_table[count];                   \
+               sec_tbl = (struct i40e_section_table *)&nvm[nvm[0] + 1]; \
+       } while (0)
+
+/* Get section header in profile */
+#define I40E_SECTION_HEADER(profile, offset)                           \
+       (struct i40e_profile_section_header *)((u8 *)(profile) + (offset))
+
+/**
+ * i40e_find_section_in_profile
+ * @section_type: the section type to search for (i.e., SECTION_TYPE_NOTE)
+ * @profile: pointer to the i40e segment header to be searched
+ *
+ * This function searches i40e segment for a particular section type. On
+ * success it returns a pointer to the section header, otherwise it will
+ * return NULL.
+ **/
+struct i40e_profile_section_header *
+i40e_find_section_in_profile(u32 section_type,
+                            struct i40e_profile_segment *profile)
+{
+       struct i40e_profile_section_header *sec;
+       struct i40e_section_table *sec_tbl;
+       u32 sec_off;
+       u32 i;
+
+       if (profile->header.type != SEGMENT_TYPE_I40E)
+               return NULL;
+
+       I40E_SECTION_TABLE(profile, sec_tbl);
+
+       for (i = 0; i < sec_tbl->section_count; i++) {
+               sec_off = sec_tbl->section_offset[i];
+               sec = I40E_SECTION_HEADER(profile, sec_off);
+               if (sec->section.type == section_type)
+                       return sec;
+       }
+
+       return NULL;
+}
+
+/**
+ * i40e_ddp_exec_aq_section - Execute generic AQ for DDP
+ * @hw: pointer to the hw struct
+ * @aq: command buffer containing all data to execute AQ
+ **/
+static enum
+i40e_status_code i40e_ddp_exec_aq_section(struct i40e_hw *hw,
+                                         struct i40e_profile_aq_section *aq)
+{
+       i40e_status status;
+       struct i40e_aq_desc desc;
+       u8 *msg = NULL;
+       u16 msglen;
+
+       i40e_fill_default_direct_cmd_desc(&desc, aq->opcode);
+       desc.flags |= CPU_TO_LE16(aq->flags);
+       i40e_memcpy(desc.params.raw, aq->param, sizeof(desc.params.raw),
+                   I40E_NONDMA_TO_NONDMA);
+
+       msglen = aq->datalen;
+       if (msglen) {
+               desc.flags |= CPU_TO_LE16((u16)(I40E_AQ_FLAG_BUF |
+                                               I40E_AQ_FLAG_RD));
+               if (msglen > I40E_AQ_LARGE_BUF)
+                       desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB);
+               desc.datalen = CPU_TO_LE16(msglen);
+               msg = &aq->data[0];
+       }
+
+       status = i40e_asq_send_command(hw, &desc, msg, msglen, NULL);
+
+       if (status != I40E_SUCCESS) {
+               i40e_debug(hw, I40E_DEBUG_PACKAGE,
+                          "unable to exec DDP AQ opcode %u, error %d\n",
+                          aq->opcode, status);
+               return status;
+       }
+
+       /* copy returned desc to aq_buf */
+       i40e_memcpy(aq->param, desc.params.raw, sizeof(desc.params.raw),
+                   I40E_NONDMA_TO_NONDMA);
+
+       return I40E_SUCCESS;
+}
+
+/**
+ * i40e_validate_profile
+ * @hw: pointer to the hardware structure
+ * @profile: pointer to the profile segment of the package to be validated
+ * @track_id: package tracking id
+ * @rollback: flag if the profile is for rollback.
+ *
+ * Validates supported devices and profile's sections.
+ */
+static enum i40e_status_code
+i40e_validate_profile(struct i40e_hw *hw, struct i40e_profile_segment *profile,
+                     u32 track_id, bool rollback)
+{
+       struct i40e_profile_section_header *sec = NULL;
+       i40e_status status = I40E_SUCCESS;
+       struct i40e_section_table *sec_tbl;
+       u32 vendor_dev_id;
+       u32 dev_cnt;
+       u32 sec_off;
+       u32 i;
+
+       if (track_id == I40E_DDP_TRACKID_INVALID) {
+               i40e_debug(hw, I40E_DEBUG_PACKAGE, "Invalid track_id\n");
+               return I40E_NOT_SUPPORTED;
+       }
+
+       dev_cnt = profile->device_table_count;
+       for (i = 0; i < dev_cnt; i++) {
+               vendor_dev_id = profile->device_table[i].vendor_dev_id;
+               if ((vendor_dev_id >> 16) == PCI_VENDOR_ID_INTEL &&
+                   hw->device_id == (vendor_dev_id & 0xFFFF))
+                       break;
+       }
+       if (dev_cnt && (i == dev_cnt)) {
+               i40e_debug(hw, I40E_DEBUG_PACKAGE,
+                          "Device doesn't support DDP\n");
+               return I40E_ERR_DEVICE_NOT_SUPPORTED;
+       }
+
+       I40E_SECTION_TABLE(profile, sec_tbl);
+
+       /* Validate sections types */
+       for (i = 0; i < sec_tbl->section_count; i++) {
+               sec_off = sec_tbl->section_offset[i];
+               sec = I40E_SECTION_HEADER(profile, sec_off);
+               if (rollback) {
+                       if (sec->section.type == SECTION_TYPE_MMIO ||
+                           sec->section.type == SECTION_TYPE_AQ ||
+                           sec->section.type == SECTION_TYPE_RB_AQ) {
+                               i40e_debug(hw, I40E_DEBUG_PACKAGE,
+                                          "Not a roll-back package\n");
+                               return I40E_NOT_SUPPORTED;
+                       }
+               } else {
+                       if (sec->section.type == SECTION_TYPE_RB_AQ ||
+                           sec->section.type == SECTION_TYPE_RB_MMIO) {
+                               i40e_debug(hw, I40E_DEBUG_PACKAGE,
+                                          "Not an original package\n");
+                               return I40E_NOT_SUPPORTED;
+                       }
+               }
+       }
+
+       return status;
+}
+
+/**
+ * i40e_write_profile
+ * @hw: pointer to the hardware structure
+ * @profile: pointer to the profile segment of the package to be downloaded
+ * @track_id: package tracking id
+ *
+ * Handles the download of a complete package.
+ */
+enum i40e_status_code
+i40e_write_profile(struct i40e_hw *hw, struct i40e_profile_segment *profile,
+                  u32 track_id)
+{
+       i40e_status status = I40E_SUCCESS;
+       struct i40e_section_table *sec_tbl;
+       struct i40e_profile_section_header *sec = NULL;
+       struct i40e_profile_aq_section *ddp_aq;
+       u32 section_size = 0;
+       u32 offset = 0, info = 0;
+       u32 sec_off;
+       u32 i;
+
+       status = i40e_validate_profile(hw, profile, track_id, false);
+       if (status)
+               return status;
+
+       I40E_SECTION_TABLE(profile, sec_tbl);
+
+       for (i = 0; i < sec_tbl->section_count; i++) {
+               sec_off = sec_tbl->section_offset[i];
+               sec = I40E_SECTION_HEADER(profile, sec_off);
+               /* Process generic admin command */
+               if (sec->section.type == SECTION_TYPE_AQ) {
+                       ddp_aq = (struct i40e_profile_aq_section *)&sec[1];
+                       status = i40e_ddp_exec_aq_section(hw, ddp_aq);
+                       if (status) {
+                               i40e_debug(hw, I40E_DEBUG_PACKAGE,
+                                          "Failed to execute aq: section %d, opcode %u\n",
+                                          i, ddp_aq->opcode);
+                               break;
+                       }
+                       sec->section.type = SECTION_TYPE_RB_AQ;
+               }
+
+               /* Skip any non-mmio sections */
+               if (sec->section.type != SECTION_TYPE_MMIO)
+                       continue;
+
+               section_size = sec->section.size +
+                       sizeof(struct i40e_profile_section_header);
+
+               /* Write MMIO section */
+               status = i40e_aq_write_ddp(hw, (void *)sec, (u16)section_size,
+                                          track_id, &offset, &info, NULL);
+               if (status) {
+                       i40e_debug(hw, I40E_DEBUG_PACKAGE,
+                                  "Failed to write profile: section %d, offset %d, info %d\n",
+                                  i, offset, info);
+                       break;
+               }
+       }
+       return status;
+}
+
+/**
+ * i40e_rollback_profile
+ * @hw: pointer to the hardware structure
+ * @profile: pointer to the profile segment of the package to be removed
+ * @track_id: package tracking id
+ *
+ * Rolls back previously loaded package.
+ */
+enum i40e_status_code
+i40e_rollback_profile(struct i40e_hw *hw, struct i40e_profile_segment *profile,
+                     u32 track_id)
+{
+       struct i40e_profile_section_header *sec = NULL;
+       i40e_status status = I40E_SUCCESS;
+       struct i40e_section_table *sec_tbl;
+       u32 offset = 0, info = 0;
+       u32 section_size = 0;
+       u32 sec_off;
+       int i;
+
+       status = i40e_validate_profile(hw, profile, track_id, true);
+       if (status)
+               return status;
+
+       I40E_SECTION_TABLE(profile, sec_tbl);
+
+       /* For rollback write sections in reverse */
+       for (i = sec_tbl->section_count - 1; i >= 0; i--) {
+               sec_off = sec_tbl->section_offset[i];
+               sec = I40E_SECTION_HEADER(profile, sec_off);
+
+               /* Skip any non-rollback sections */
+               if (sec->section.type != SECTION_TYPE_RB_MMIO)
+                       continue;
+
+               section_size = sec->section.size +
+                       sizeof(struct i40e_profile_section_header);
+
+               /* Write roll-back MMIO section */
+               status = i40e_aq_write_ddp(hw, (void *)sec, (u16)section_size,
+                                          track_id, &offset, &info, NULL);
+               if (status) {
+                       i40e_debug(hw, I40E_DEBUG_PACKAGE,
+                                  "Failed to write profile: section %d, offset %d, info %d\n",
+                                  i, offset, info);
+                       break;
+               }
+       }
+       return status;
+}
+
+/**
+ * i40e_add_pinfo_to_list
+ * @hw: pointer to the hardware structure
+ * @profile: pointer to the profile segment of the package
+ * @profile_info_sec: buffer for information section
+ * @track_id: package tracking id
+ *
+ * Register a profile to the list of loaded profiles.
+ */
+enum i40e_status_code
+i40e_add_pinfo_to_list(struct i40e_hw *hw,
+                      struct i40e_profile_segment *profile,
+                      u8 *profile_info_sec, u32 track_id)
+{
+       i40e_status status = I40E_SUCCESS;
+       struct i40e_profile_section_header *sec = NULL;
+       struct i40e_profile_info *pinfo;
+       u32 offset = 0, info = 0;
+
+       sec = (struct i40e_profile_section_header *)profile_info_sec;
+       sec->tbl_size = 1;
+       sec->data_end = sizeof(struct i40e_profile_section_header) +
+                       sizeof(struct i40e_profile_info);
+       sec->section.type = SECTION_TYPE_INFO;
+       sec->section.offset = sizeof(struct i40e_profile_section_header);
+       sec->section.size = sizeof(struct i40e_profile_info);
+       pinfo = (struct i40e_profile_info *)(profile_info_sec +
+                                            sec->section.offset);
+       pinfo->track_id = track_id;
+       pinfo->version = profile->version;
+       pinfo->op = I40E_DDP_ADD_TRACKID;
+       i40e_memcpy(pinfo->name, profile->name, I40E_DDP_NAME_SIZE,
+                   I40E_NONDMA_TO_NONDMA);
+
+       status = i40e_aq_write_ddp(hw, (void *)sec, sec->data_end,
+                                  track_id, &offset, &info, NULL);
+       return status;
+}
similarity index 99%
rename from i40e-dkms/i40e-1.6.42/src/i40e_dcb.c
rename to i40e-dkms/i40e-2.1.26/src/i40e_dcb.c
index f0988e9c5dde0b55e824146dd4e541ef508c40b5..5e874954f8c65945c399c3b8ffadd0c75d61ad57 100644 (file)
@@ -386,6 +386,8 @@ static void i40e_parse_cee_app_tlv(struct i40e_cee_feat_tlv *tlv,
        dcbcfg->numapps = length / sizeof(*app);
        if (!dcbcfg->numapps)
                return;
+       if (dcbcfg->numapps > I40E_DCBX_MAX_APPS)
+               dcbcfg->numapps = I40E_DCBX_MAX_APPS;
 
        for (i = 0; i < dcbcfg->numapps; i++) {
                u8 up, selector;
similarity index 97%
rename from i40e-dkms/i40e-1.6.42/src/i40e_debugfs.c
rename to i40e-dkms/i40e-2.1.26/src/i40e_debugfs.c
index c1c23bb2a3d719fc8e1abfc0e653724cd1d2c0aa..3033c849a927f6e81ba5b6b19058b75375bc2e1e 100644 (file)
@@ -139,7 +139,7 @@ static void i40e_dbg_dump_vsi_filters(struct i40e_pf *pf, struct i40e_vsi *vsi)
        }
        dev_info(&pf->pdev->dev, "    active_filters %u, promisc_threshold %u, overflow promisc %s\n",
                 vsi->active_filters, vsi->promisc_threshold,
-                (test_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state) ?
+                (test_bit(__I40E_VSI_OVERFLOW_PROMISC, vsi->state) ?
                  "ON" : "OFF"));
 }
 
@@ -215,9 +215,12 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid)
                 "    vlgrp: & = %p\n", vsi->active_vlans);
 #endif /* HAVE_VLAN_RX_REGISTER */
        dev_info(&pf->pdev->dev,
-                "    state = %li flags = 0x%08lx, netdev_registered = %i, current_netdev_flags = 0x%04x\n",
-                vsi->state, vsi->flags,
-                vsi->netdev_registered, vsi->current_netdev_flags);
+                "    flags = 0x%016llx, netdev_registered = %i, current_netdev_flags = 0x%04x\n",
+                vsi->flags, vsi->netdev_registered, vsi->current_netdev_flags);
+       for (i = 0; i < BITS_TO_LONGS(__I40E_VSI_STATE_SIZE__); i++)
+               dev_info(&pf->pdev->dev,
+                        "    state[%d] = %08lx\n",
+                        i, vsi->state[i]);
        if (vsi == pf->vsi[pf->lan_vsi])
                dev_info(&pf->pdev->dev, "    MAC address: %pM SAN MAC: %pM Port MAC: %pM\n",
                         pf->hw.mac.addr,
@@ -323,8 +326,8 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid)
                         rx_ring->netdev,
                         rx_ring->rx_bi);
                dev_info(&pf->pdev->dev,
-                        "    rx_rings[%i]: state = %li, queue_index = %d, reg_idx = %d\n",
-                        i, rx_ring->state,
+                        "    rx_rings[%i]: state = %lu, queue_index = %d, reg_idx = %d\n",
+                        i, *rx_ring->state,
                         rx_ring->queue_index,
                         rx_ring->reg_idx);
                dev_info(&pf->pdev->dev,
@@ -380,8 +383,8 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid)
                         tx_ring->netdev,
                         tx_ring->tx_bi);
                dev_info(&pf->pdev->dev,
-                        "    tx_rings[%i]: state = %li, queue_index = %d, reg_idx = %d\n",
-                        i, tx_ring->state,
+                        "    tx_rings[%i]: state = %lu, queue_index = %d, reg_idx = %d\n",
+                        i, *tx_ring->state,
                         tx_ring->queue_index,
                         tx_ring->reg_idx);
                dev_info(&pf->pdev->dev,
@@ -536,25 +539,6 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid)
                         vsi->bw_ets_limit_credits[i],
                         vsi->bw_ets_max_quanta[i]);
        }
-#ifdef I40E_FCOE
-       if (vsi->type == I40E_VSI_FCOE) {
-               dev_info(&pf->pdev->dev,
-                        "    fcoe_stats: rx_packets = %llu, rx_dwords = %llu, rx_dropped = %llu\n",
-                        vsi->fcoe_stats.rx_fcoe_packets,
-                        vsi->fcoe_stats.rx_fcoe_dwords,
-                        vsi->fcoe_stats.rx_fcoe_dropped);
-               dev_info(&pf->pdev->dev,
-                        "    fcoe_stats: tx_packets = %llu, tx_dwords = %llu\n",
-                        vsi->fcoe_stats.tx_fcoe_packets,
-                        vsi->fcoe_stats.tx_fcoe_dwords);
-               dev_info(&pf->pdev->dev,
-                        "    fcoe_stats: bad_crc = %llu, last_error = %llu\n",
-                        vsi->fcoe_stats.fcoe_bad_fccrc,
-                        vsi->fcoe_stats.fcoe_last_error);
-               dev_info(&pf->pdev->dev, "    fcoe_stats: ddp_count = %llu\n",
-                        vsi->fcoe_stats.fcoe_ddp_count);
-       }
-#endif
 }
 
 /**
@@ -1039,20 +1023,19 @@ static inline void i40e_dbg_dump_fdir_filter(struct i40e_pf *pf,
        dev_info(&pf->pdev->dev, "fdir filter %d:\n", f->fd_id);
        dev_info(&pf->pdev->dev, "    flow_type=%d ip4_proto=%d\n",
                 f->flow_type, f->ip4_proto);
-       dev_info(&pf->pdev->dev, "    dst_ip[0]= %pi4  dst_port=%d\n",
-                f->dst_ip, f->dst_port);
-       dev_info(&pf->pdev->dev, "    src_ip[0]= %pi4  src_port=%d\n",
-                f->src_ip, f->src_port);
-       dev_info(&pf->pdev->dev, "    sctp_v_tag=%d q_index=%d flex_off=%d\n",
-                f->sctp_v_tag, f->q_index, f->flex_off);
+       dev_info(&pf->pdev->dev, "    dst_ip= %pi4  dst_port=%d\n",
+                &f->dst_ip, f->dst_port);
+       dev_info(&pf->pdev->dev, "    src_ip= %pi4  src_port=%d\n",
+                &f->src_ip, f->src_port);
+       dev_info(&pf->pdev->dev, "    sctp_v_tag=%d q_index=%d\n",
+                f->sctp_v_tag, f->q_index);
+       if (f->flex_filter)
+               dev_info(&pf->pdev->dev, "    flex_word=%04x flex_offset=%d\n",
+                        f->flex_word, f->flex_offset);
        dev_info(&pf->pdev->dev, "    pctype=%d dest_vsi=%d dest_ctl=%d\n",
                 f->pctype, f->dest_vsi, f->dest_ctl);
        dev_info(&pf->pdev->dev, "    fd_status=%d cnt_index=%d\n",
                 f->fd_status, f->cnt_index);
-       if (i40e_is_flex_filter(f))
-               dev_info(&pf->pdev->dev, "    pattern(user-def N)=%u offset_in_payload(user-def m)=%u\n",
-                        be16_to_cpu(f->flex_bytes[3]),
-                        (u16)~(be16_to_cpu(f->flex_mask[3])));
 }
 
 /**
@@ -1391,7 +1374,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
                        struct i40e_dcbx_config *d_cfg =
                                                &pf->hw.desired_dcbx_config;
                        int i, ret;
-                       u32 switch_id;
+                       u16 switch_id;
 
                        bw_data = kzalloc(sizeof(
                                    struct i40e_aqc_query_port_ets_config_resp),
@@ -1403,7 +1386,8 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
 
                        vsi = pf->vsi[pf->lan_vsi];
                        switch_id =
-                               vsi->info.switch_id & I40E_AQ_VSI_SW_ID_MASK;
+                               le16_to_cpu(vsi->info.switch_id) &
+                                           I40E_AQ_VSI_SW_ID_MASK;
 
                        ret = i40e_aq_query_port_ets_config(&pf->hw,
                                                            switch_id,
@@ -1538,17 +1522,6 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
                        dev_info(&pf->pdev->dev, "msg_enable = 0x%08x\n",
                                 pf->msg_enable);
                }
-       } else if (strncmp(cmd_buf, "pfr", 3) == 0) {
-               dev_info(&pf->pdev->dev, "debugfs: forcing PFR\n");
-               i40e_do_reset_safe(pf, BIT(__I40E_PF_RESET_REQUESTED));
-
-       } else if (strncmp(cmd_buf, "corer", 5) == 0) {
-               dev_info(&pf->pdev->dev, "debugfs: forcing CoreR\n");
-               i40e_do_reset_safe(pf, BIT(__I40E_CORE_RESET_REQUESTED));
-
-       } else if (strncmp(cmd_buf, "globr", 5) == 0) {
-               dev_info(&pf->pdev->dev, "debugfs: forcing GlobR\n");
-               i40e_do_reset_safe(pf, BIT(__I40E_GLOBAL_RESET_REQUESTED));
        } else if (strncmp(cmd_buf, "defport on", 10) == 0) {
                dev_info(&pf->pdev->dev, "debugfs: forcing PFR with defport enabled\n");
                pf->cur_promisc = true;
@@ -1557,7 +1530,6 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
                dev_info(&pf->pdev->dev, "debugfs: forcing PFR with defport disabled\n");
                pf->cur_promisc = false;
                i40e_do_reset_safe(pf, BIT(__I40E_PF_RESET_REQUESTED));
-
        } else if (strncmp(cmd_buf, "clear_stats", 11) == 0) {
                if (strncmp(&cmd_buf[12], "vsi", 3) == 0) {
                        cnt = sscanf(&cmd_buf[15], "%i", &vsi_seid);
@@ -1596,7 +1568,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
                struct i40e_aq_desc *desc;
                i40e_status ret;
 
-               desc = kzalloc(sizeof(struct i40e_aq_desc), GFP_KERNEL);
+               desc = kzalloc(sizeof(*desc), GFP_KERNEL);
                if (!desc)
                        goto command_write_done;
                cnt = sscanf(&cmd_buf[11],
@@ -1644,7 +1616,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
                u16 buffer_len;
                u8 *buff;
 
-               desc = kzalloc(sizeof(struct i40e_aq_desc), GFP_KERNEL);
+               desc = kzalloc(sizeof(*desc), GFP_KERNEL);
                if (!desc)
                        goto command_write_done;
                cnt = sscanf(&cmd_buf[20],
@@ -2233,9 +2205,6 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
                dev_info(&pf->pdev->dev, "  write <reg> <value>\n");
                dev_info(&pf->pdev->dev, "  clear_stats vsi [seid]\n");
                dev_info(&pf->pdev->dev, "  clear_stats port\n");
-               dev_info(&pf->pdev->dev, "  pfr\n");
-               dev_info(&pf->pdev->dev, "  corer\n");
-               dev_info(&pf->pdev->dev, "  globr\n");
                dev_info(&pf->pdev->dev, "  defport on\n");
                dev_info(&pf->pdev->dev, "  defport off\n");
                dev_info(&pf->pdev->dev, "  send aq_cmd <flags> <opcode> <datalen> <retval> <cookie_h> <cookie_l> <param0> <param1> <param2> <param3>\n");
@@ -2374,7 +2343,7 @@ static ssize_t i40e_dbg_netdev_ops_write(struct file *filp,
                } else if (!vsi->netdev) {
                        dev_info(&pf->pdev->dev, "tx_timeout: no netdev for VSI %d\n",
                                 vsi_seid);
-               } else if (test_bit(__I40E_DOWN, &vsi->state)) {
+               } else if (test_bit(__I40E_VSI_DOWN, vsi->state)) {
                        dev_info(&pf->pdev->dev, "tx_timeout: VSI %d not UP\n",
                                 vsi_seid);
                } else if (rtnl_trylock()) {
similarity index 60%
rename from i40e-dkms/i40e-1.6.42/src/i40e_ethtool.c
rename to i40e-dkms/i40e-2.1.26/src/i40e_ethtool.c
index b800252360fd633d1e200ba22b671b5b76c2689c..8d6e04e8ee7a04e19aa3d4196e64ce9e205f308d 100644 (file)
@@ -97,7 +97,6 @@ static const struct i40e_stats i40e_gstrings_misc_stats[] = {
        I40E_VSI_STAT("rx_unknown_protocol", eth_stats.rx_unknown_protocol),
        I40E_VSI_STAT("tx_linearize", tx_linearize),
        I40E_VSI_STAT("tx_force_wb", tx_force_wb),
-       I40E_VSI_STAT("tx_lost_interrupt", tx_lost_interrupt),
        I40E_VSI_STAT("rx_alloc_fail", rx_buf_failed),
        I40E_VSI_STAT("rx_pg_alloc_fail", rx_page_failed),
 };
@@ -112,7 +111,7 @@ static const struct i40e_stats i40e_gstrings_misc_stats[] = {
  * The PF_STATs are appended to the netdev stats only when ethtool -S
  * is queried on the base PF netdev, not on the VMDq or FCoE netdev.
  */
-static struct i40e_stats i40e_gstrings_stats[] = {
+static const struct i40e_stats i40e_gstrings_stats[] = {
        I40E_PF_STAT("rx_bytes", stats.eth.rx_bytes),
        I40E_PF_STAT("tx_bytes", stats.eth.tx_bytes),
        I40E_PF_STAT("rx_unicast", stats.eth.rx_unicast),
@@ -156,7 +155,9 @@ static struct i40e_stats i40e_gstrings_stats[] = {
        I40E_PF_STAT("VF_admin_queue_requests", vf_aq_requests),
        I40E_PF_STAT("arq_overflows", arq_overflows),
 #ifdef HAVE_PTP_1588_CLOCK
+       I40E_PF_STAT("tx_hwtstamp_timeouts", tx_hwtstamp_timeouts),
        I40E_PF_STAT("rx_hwtstamp_cleared", rx_hwtstamp_cleared),
+       I40E_PF_STAT("tx_hwtstamp_skipped", tx_hwtstamp_skipped),
 #endif /* HAVE_PTP_1588_CLOCK */
        I40E_PF_STAT("fdir_flush_cnt", fd_flush_cnt),
        I40E_PF_STAT("fdir_atr_match", stats.fd_atr_match),
@@ -174,6 +175,9 @@ static struct i40e_stats i40e_gstrings_stats[] = {
        I40E_PF_STAT("rx_udp_cso", rx_udp_cso),
        I40E_PF_STAT("rx_sctp_cso", rx_sctp_cso),
        I40E_PF_STAT("rx_ip4_cso", rx_ip4_cso),
+       I40E_PF_STAT("rx_csum_offload_vxlan", hw_csum_rx_vxlan),
+       I40E_PF_STAT("rx_csum_offload_geneve", hw_csum_rx_geneve),
+       I40E_PF_STAT("rx_csum_offload_outer", hw_csum_rx_outer),
        I40E_PF_STAT("rx_tcp_cso_error", rx_tcp_cso_err),
        I40E_PF_STAT("rx_udp_cso_error", rx_udp_cso_err),
        I40E_PF_STAT("rx_sctp_cso_error", rx_sctp_cso_err),
@@ -187,19 +191,6 @@ static struct i40e_stats i40e_gstrings_stats[] = {
        I40E_PF_STAT("rx_lpi_count", stats.rx_lpi_count),
 };
 
-#ifdef I40E_FCOE
-static const struct i40e_stats i40e_gstrings_fcoe_stats[] = {
-       I40E_VSI_STAT("fcoe_bad_fccrc", fcoe_stats.fcoe_bad_fccrc),
-       I40E_VSI_STAT("rx_fcoe_dropped", fcoe_stats.rx_fcoe_dropped),
-       I40E_VSI_STAT("rx_fcoe_packets", fcoe_stats.rx_fcoe_packets),
-       I40E_VSI_STAT("rx_fcoe_dwords", fcoe_stats.rx_fcoe_dwords),
-       I40E_VSI_STAT("fcoe_ddp_count", fcoe_stats.fcoe_ddp_count),
-       I40E_VSI_STAT("fcoe_last_error", fcoe_stats.fcoe_last_error),
-       I40E_VSI_STAT("tx_fcoe_packets", fcoe_stats.tx_fcoe_packets),
-       I40E_VSI_STAT("tx_fcoe_dwords", fcoe_stats.tx_fcoe_dwords),
-};
-
-#endif /* I40E_FCOE */
 #define I40E_QUEUE_STATS_LEN(n) \
        (((struct i40e_netdev_priv *)netdev_priv((n)))->vsi->num_queue_pairs \
            * 2 /* Tx and Rx together */                                     \
@@ -207,17 +198,9 @@ static const struct i40e_stats i40e_gstrings_fcoe_stats[] = {
 #define I40E_GLOBAL_STATS_LEN  ARRAY_SIZE(i40e_gstrings_stats)
 #define I40E_NETDEV_STATS_LEN   ARRAY_SIZE(i40e_gstrings_net_stats)
 #define I40E_MISC_STATS_LEN    ARRAY_SIZE(i40e_gstrings_misc_stats)
-#ifdef I40E_FCOE
-#define I40E_FCOE_STATS_LEN    ARRAY_SIZE(i40e_gstrings_fcoe_stats)
-#define I40E_VSI_STATS_LEN(n)  (I40E_NETDEV_STATS_LEN + \
-                                I40E_FCOE_STATS_LEN + \
-                                I40E_MISC_STATS_LEN + \
-                                I40E_QUEUE_STATS_LEN((n)))
-#else
 #define I40E_VSI_STATS_LEN(n)   (I40E_NETDEV_STATS_LEN + \
                                 I40E_MISC_STATS_LEN + \
                                 I40E_QUEUE_STATS_LEN((n)))
-#endif /* I40E_FCOE */
 #define I40E_PFC_STATS_LEN ( \
                (FIELD_SIZEOF(struct i40e_pf, stats.priority_xoff_rx) + \
                 FIELD_SIZEOF(struct i40e_pf, stats.priority_xon_rx) + \
@@ -256,26 +239,45 @@ static const char i40e_gstrings_test[][ETH_GSTRING_LEN] = {
 #define I40E_TEST_LEN (sizeof(i40e_gstrings_test) / ETH_GSTRING_LEN)
 
 #endif /* ETHTOOL_TEST */
-static int i40e_del_cloud_filter_ethtool(struct i40e_pf *pf,
-                                        struct ethtool_rxnfc *cmd);
 
 #ifdef HAVE_ETHTOOL_GET_SSET_COUNT
-static const char i40e_priv_flags_strings[][ETH_GSTRING_LEN] = {
-       "MFP",
-       "LinkPolling",
-       "flow-director-atr",
-       "veb-stats",
-       "hw-atr-eviction",
+struct i40e_priv_flags {
+       char flag_string[ETH_GSTRING_LEN];
+       u64 flag;
+       bool read_only;
+};
+
+#define I40E_PRIV_FLAG(_name, _flag, _read_only) { \
+       .flag_string = _name, \
+       .flag = _flag, \
+       .read_only = _read_only, \
+}
+
+static const struct i40e_priv_flags i40e_gstrings_priv_flags[] = {
+       /* NOTE: MFP setting cannot be changed */
+       I40E_PRIV_FLAG("MFP", I40E_FLAG_MFP_ENABLED, 1),
+       I40E_PRIV_FLAG("LinkPolling", I40E_FLAG_LINK_POLLING_ENABLED, 0),
+       I40E_PRIV_FLAG("flow-director-atr", I40E_FLAG_FD_ATR_ENABLED, 0),
+       I40E_PRIV_FLAG("veb-stats", I40E_FLAG_VEB_STATS_ENABLED, 0),
+       I40E_PRIV_FLAG("hw-atr-eviction", I40E_FLAG_HW_ATR_EVICT_ENABLED, 0),
+       I40E_PRIV_FLAG("link-down-on-close",
+                      I40E_FLAG_LINK_DOWN_ON_CLOSE_ENABLED, 0),
+#ifdef HAVE_SWIOTLB_SKIP_CPU_SYNC
+       I40E_PRIV_FLAG("legacy-rx", I40E_FLAG_LEGACY_RX, 0),
+#endif
+       I40E_PRIV_FLAG("disable-source-pruning",
+                      I40E_FLAG_SOURCE_PRUNING_DISABLED, 0),
 };
 
-#define I40E_PRIV_FLAGS_STR_LEN ARRAY_SIZE(i40e_priv_flags_strings)
+#define I40E_PRIV_FLAGS_STR_LEN ARRAY_SIZE(i40e_gstrings_priv_flags)
 
 /* Private flags with a global effect, restricted to PF 0 */
-static const char i40e_gl_priv_flags_strings[][ETH_GSTRING_LEN] = {
-       "vf-true-promisc-support",
+static const struct i40e_priv_flags i40e_gl_gstrings_priv_flags[] = {
+       I40E_PRIV_FLAG("vf-true-promisc-support",
+                      I40E_FLAG_TRUE_PROMISC_SUPPORT, 0),
 };
 
-#define I40E_GL_PRIV_FLAGS_STR_LEN ARRAY_SIZE(i40e_gl_priv_flags_strings)
+#define I40E_GL_PRIV_FLAGS_STR_LEN ARRAY_SIZE(i40e_gl_gstrings_priv_flags)
 
 #endif /* HAVE_ETHTOOL_GET_SSET_COUNT */
 /**
@@ -310,7 +312,7 @@ static void i40e_phy_type_to_ethtool(struct i40e_pf *pf, u32 *supported,
                *advertising |= ADVERTISED_Autoneg;
                if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB)
                        *advertising |= ADVERTISED_1000baseT_Full;
-               if (pf->flags & I40E_FLAG_100M_SGMII_CAPABLE) {
+               if (pf->hw_features & I40E_HW_100M_SGMII_CAPABLE) {
                        *supported |= SUPPORTED_100baseT_Full;
                        *advertising |= ADVERTISED_100baseT_Full;
                }
@@ -319,13 +321,13 @@ static void i40e_phy_type_to_ethtool(struct i40e_pf *pf, u32 *supported,
            phy_types & I40E_CAP_PHY_TYPE_XFI ||
            phy_types & I40E_CAP_PHY_TYPE_SFI ||
            phy_types & I40E_CAP_PHY_TYPE_10GBASE_SFPP_CU ||
-           phy_types & I40E_CAP_PHY_TYPE_10GBASE_AOC)
+           phy_types & I40E_CAP_PHY_TYPE_10GBASE_AOC) {
                *supported |= SUPPORTED_10000baseT_Full;
-       if (phy_types & I40E_CAP_PHY_TYPE_10GBASE_CR1_CU ||
-           phy_types & I40E_CAP_PHY_TYPE_10GBASE_CR1 ||
-           phy_types & I40E_CAP_PHY_TYPE_10GBASE_T ||
-           phy_types & I40E_CAP_PHY_TYPE_10GBASE_SR ||
-           phy_types & I40E_CAP_PHY_TYPE_10GBASE_LR) {
+               if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB) {
+                       *advertising |= ADVERTISED_10000baseT_Full;
+               }
+       }
+       if (phy_types & I40E_CAP_PHY_TYPE_10GBASE_T) {
                *supported |= SUPPORTED_Autoneg |
                             SUPPORTED_10000baseT_Full;
                *advertising |= ADVERTISED_Autoneg;
@@ -351,10 +353,7 @@ static void i40e_phy_type_to_ethtool(struct i40e_pf *pf, u32 *supported,
                if (hw_link_info->requested_speeds & I40E_LINK_SPEED_100MB)
                        *advertising |= ADVERTISED_100baseT_Full;
        }
-       if (phy_types & I40E_CAP_PHY_TYPE_1000BASE_T ||
-           phy_types & I40E_CAP_PHY_TYPE_1000BASE_SX ||
-           phy_types & I40E_CAP_PHY_TYPE_1000BASE_LX ||
-           phy_types & I40E_CAP_PHY_TYPE_1000BASE_T_OPTICAL) {
+       if (phy_types & I40E_CAP_PHY_TYPE_1000BASE_T) {
                *supported |= SUPPORTED_Autoneg |
                             SUPPORTED_1000baseT_Full;
                *advertising |= ADVERTISED_Autoneg;
@@ -379,12 +378,12 @@ static void i40e_phy_type_to_ethtool(struct i40e_pf *pf, u32 *supported,
                        *advertising |= ADVERTISED_20000baseKR2_Full;
        }
        if (phy_types & I40E_CAP_PHY_TYPE_10GBASE_KR) {
-               if (!(pf->flags & I40E_FLAG_HAVE_CRT_RETIMER))
+               if (!(pf->hw_features & I40E_HW_HAVE_CRT_RETIMER))
                        *supported |= SUPPORTED_10000baseKR_Full |
                                      SUPPORTED_Autoneg;
                *advertising |= ADVERTISED_Autoneg;
                if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB)
-                       if (!(pf->flags & I40E_FLAG_HAVE_CRT_RETIMER))
+                       if (!(pf->hw_features & I40E_HW_HAVE_CRT_RETIMER))
                                *advertising |= ADVERTISED_10000baseKR_Full;
        }
        if (phy_types & I40E_CAP_PHY_TYPE_10GBASE_KX4) {
@@ -395,18 +394,28 @@ static void i40e_phy_type_to_ethtool(struct i40e_pf *pf, u32 *supported,
                        *advertising |= ADVERTISED_10000baseKX4_Full;
        }
        if (phy_types & I40E_CAP_PHY_TYPE_1000BASE_KX) {
-               if (!(pf->flags & I40E_FLAG_HAVE_CRT_RETIMER))
+               if (!(pf->hw_features & I40E_HW_HAVE_CRT_RETIMER))
                        *supported |= SUPPORTED_1000baseKX_Full |
                                      SUPPORTED_Autoneg;
                *advertising |= ADVERTISED_Autoneg;
                if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB)
-                       if (!(pf->flags & I40E_FLAG_HAVE_CRT_RETIMER))
+                       if (!(pf->hw_features & I40E_HW_HAVE_CRT_RETIMER))
                                *advertising |= ADVERTISED_1000baseKX_Full;
        }
+       /* Older kernels, that do not use ETHTOOL_GLINKSETTINGS should at least
+        * report Autoneg capability
+        */
        if (phy_types & I40E_CAP_PHY_TYPE_25GBASE_KR ||
            phy_types & I40E_CAP_PHY_TYPE_25GBASE_CR ||
            phy_types & I40E_CAP_PHY_TYPE_25GBASE_SR ||
-           phy_types & I40E_CAP_PHY_TYPE_25GBASE_LR) {
+           phy_types & I40E_CAP_PHY_TYPE_25GBASE_LR ||
+           phy_types & I40E_CAP_PHY_TYPE_10GBASE_SR ||
+           phy_types & I40E_CAP_PHY_TYPE_10GBASE_LR ||
+           phy_types & I40E_CAP_PHY_TYPE_10GBASE_CR1 ||
+           phy_types & I40E_CAP_PHY_TYPE_10GBASE_CR1_CU ||
+           phy_types & I40E_CAP_PHY_TYPE_1000BASE_SX ||
+           phy_types & I40E_CAP_PHY_TYPE_1000BASE_LX ||
+           phy_types & I40E_CAP_PHY_TYPE_1000BASE_T_OPTICAL) {
                *supported |= SUPPORTED_Autoneg;
                *advertising |= ADVERTISED_Autoneg;
        }
@@ -504,7 +513,7 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw,
                                  SUPPORTED_1000baseT_Full;
                if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB)
                        ecmd->advertising |= ADVERTISED_1000baseT_Full;
-               if (pf->flags & I40E_FLAG_100M_SGMII_CAPABLE) {
+               if (pf->hw_features & I40E_HW_100M_SGMII_CAPABLE) {
                        ecmd->supported |= SUPPORTED_100baseT_Full;
                        if (hw_link_info->requested_speeds &
                            I40E_LINK_SPEED_100MB)
@@ -707,6 +716,7 @@ static int i40e_set_settings(struct net_device *netdev,
        struct ethtool_cmd safe_ecmd;
        i40e_status status = 0;
        bool change = false;
+       int timeout = 50;
        int err = 0;
        u8 autoneg;
        u32 advertise;
@@ -774,14 +784,20 @@ static int i40e_set_settings(struct net_device *netdev,
        if (memcmp(ecmd, &safe_ecmd, sizeof(struct ethtool_cmd)))
                return -EOPNOTSUPP;
 
-       while (test_bit(__I40E_CONFIG_BUSY, &vsi->state))
+       while (test_and_set_bit(__I40E_CONFIG_BUSY, pf->state)) {
+               timeout--;
+               if (!timeout)
+                       return -EBUSY;
                usleep_range(1000, 2000);
+       }
 
        /* Get the current phy config */
        status = i40e_aq_get_phy_capabilities(hw, false, false, &abilities,
                                              NULL);
-       if (status)
-               return -EAGAIN;
+       if (status) {
+               err = -EAGAIN;
+               goto done;
+       }
 
        /* Copy abilities to config in case autoneg is not
         * set below
@@ -796,7 +812,8 @@ static int i40e_set_settings(struct net_device *netdev,
                        /* If autoneg is not supported, return error */
                        if (!(safe_ecmd.supported & SUPPORTED_Autoneg)) {
                                netdev_info(netdev, "Autoneg not supported on this phy\n");
-                               return -EINVAL;
+                               err = -EINVAL;
+                               goto done;
                        }
                        /* Autoneg is allowed to change */
                        config.abilities = abilities.abilities |
@@ -813,7 +830,8 @@ static int i40e_set_settings(struct net_device *netdev,
                            hw->phy.link_info.phy_type !=
                            I40E_PHY_TYPE_10GBASE_T) {
                                netdev_info(netdev, "Autoneg cannot be disabled on this phy\n");
-                               return -EINVAL;
+                               err = -EINVAL;
+                               goto done;
                        }
                        /* Autoneg is allowed to change */
                        config.abilities = abilities.abilities &
@@ -822,8 +840,10 @@ static int i40e_set_settings(struct net_device *netdev,
                }
        }
 
-       if (advertise & ~safe_ecmd.supported)
-               return -EINVAL;
+       if (advertise & ~safe_ecmd.supported) {
+               err = -EINVAL;
+               goto done;
+       }
 
        if (advertise & ADVERTISED_100baseT_Full)
                config.link_speed |= I40E_LINK_SPEED_100MB;
@@ -879,7 +899,8 @@ static int i40e_set_settings(struct net_device *netdev,
                        netdev_info(netdev, "Set phy config failed, err %s aq_err %s\n",
                                    i40e_stat_str(hw, status),
                                    i40e_aq_str(hw, hw->aq.asq_last_status));
-                       return -EAGAIN;
+                       err = -EAGAIN;
+                       goto done;
                }
 
                status = i40e_update_link_info(hw);
@@ -892,114 +913,841 @@ static int i40e_set_settings(struct net_device *netdev,
                netdev_info(netdev, "Nothing changed, exiting without setting anything.\n");
        }
 
+done:
+       clear_bit(__I40E_CONFIG_BUSY, pf->state);
+
        return err;
 }
 
-static int i40e_nway_reset(struct net_device *netdev)
+#ifdef ETHTOOL_GLINKSETTINGS
+#define ETHTOOL_LINK_MODE_MASK_U32  \
+       DIV_ROUND_UP(__ETHTOOL_LINK_MODE_MASK_NBITS, 32)
+
+/**
+ * ethtool_link_ksettings_clear_link_mode - unset a bit in link_ksettings
+ * link mode mask
+ *   @ptr : pointer to ethtool_link_ksettings
+ *   @name : one of supported, advertising or lp_advertising
+ *   @mode : one of ETHTOOL_LINK_MODE_*_BIT
+ * (not atomic and no bounds checking)
+ **/
+#define ethtool_link_ksettings_clear_link_mode(ptr, name, mode)           \
+       __clear_bit(ETHTOOL_LINK_MODE_ ## mode ## _BIT, (ptr)->link_modes.name)
+
+/**
+ * i40e_get_link_settings_link_down - Get the Link settings when link is down
+ * @hw: hw structure
+ * @ksettings: ethtool command to fill in
+ * @pf: pointer to physical function struct
+ *
+ * Reports link settings that can be determined when link is down
+ **/
+static void i40e_get_link_settings_link_down(struct i40e_hw *hw,
+                                      struct ethtool_link_ksettings *ksettings,
+                                      struct i40e_pf *pf)
 {
-       /* restart autonegotiation */
-       struct i40e_netdev_priv *np = netdev_priv(netdev);
-       struct i40e_pf *pf = np->vsi->back;
-       struct i40e_hw *hw = &pf->hw;
-       bool link_up = hw->phy.link_info.link_info & I40E_AQ_LINK_UP;
-       i40e_status ret = 0;
+       struct i40e_link_status *hw_link_info = &pf->hw.phy.link_info;
+       u64 phy_types = pf->hw.phy.phy_types;
 
-       ret = i40e_aq_set_link_restart_an(hw, link_up, NULL);
-       if (ret) {
-               netdev_info(netdev, "link restart failed, err %s aq_err %s\n",
-                           i40e_stat_str(hw, ret),
-                           i40e_aq_str(hw, hw->aq.asq_last_status));
-               return -EIO;
+       i40e_phy_type_to_ethtool(pf, (u32 *)&ksettings->link_modes.supported[0],
+                                (u32 *)&ksettings->link_modes.advertising[0]);
+#ifdef HAVE_ETHTOOL_25G_BITS
+       /* need to add 25G PHY types */
+       if (phy_types & I40E_CAP_PHY_TYPE_25GBASE_KR) {
+               ethtool_link_ksettings_add_link_mode(ksettings, supported,
+                                                    25000baseKR_Full);
+               if (hw_link_info->requested_speeds & I40E_LINK_SPEED_25GB)
+                       ethtool_link_ksettings_add_link_mode(ksettings,
+                                                            advertising,
+                                                            25000baseKR_Full);
+       }
+       if (phy_types & I40E_CAP_PHY_TYPE_25GBASE_CR) {
+               ethtool_link_ksettings_add_link_mode(ksettings, supported,
+                                                    25000baseCR_Full);
+               if (hw_link_info->requested_speeds & I40E_LINK_SPEED_25GB)
+                       ethtool_link_ksettings_add_link_mode(ksettings,
+                                                            advertising,
+                                                            25000baseCR_Full);
+       }
+       if (phy_types & I40E_CAP_PHY_TYPE_25GBASE_SR ||
+           phy_types & I40E_CAP_PHY_TYPE_25GBASE_LR) {
+               ethtool_link_ksettings_add_link_mode(ksettings, supported,
+                                                    25000baseSR_Full);
+               if (hw_link_info->requested_speeds & I40E_LINK_SPEED_25GB)
+                       ethtool_link_ksettings_add_link_mode(ksettings,
+                                                            advertising,
+                                                            25000baseSR_Full);
+       }
+       if (phy_types & I40E_CAP_PHY_TYPE_25GBASE_AOC ||
+           phy_types & I40E_CAP_PHY_TYPE_25GBASE_ACC) {
+               ethtool_link_ksettings_add_link_mode(ksettings, supported,
+                                                    25000baseCR_Full);
+               if (hw_link_info->requested_speeds & I40E_LINK_SPEED_25GB)
+                       ethtool_link_ksettings_add_link_mode(ksettings,
+                                                            advertising,
+                                                            25000baseCR_Full);
+       }
+#endif /* HAVE_ETHTOOL_25G_BITS */
+#ifdef HAVE_ETHTOOL_NEW_10G_BITS
+       /* need to add new 10G PHY types */
+       if (phy_types & I40E_CAP_PHY_TYPE_10GBASE_CR1 ||
+           phy_types & I40E_CAP_PHY_TYPE_10GBASE_CR1_CU) {
+               ethtool_link_ksettings_add_link_mode(ksettings, supported,
+                                                    10000baseCR_Full);
+               if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB)
+                       ethtool_link_ksettings_add_link_mode(ksettings,
+                                                            advertising,
+                                                            10000baseCR_Full);
        }
-
-       return 0;
+       if (phy_types & I40E_CAP_PHY_TYPE_10GBASE_SR) {
+               ethtool_link_ksettings_add_link_mode(ksettings, supported,
+                                                    10000baseSR_Full);
+               if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB)
+                       ethtool_link_ksettings_add_link_mode(ksettings,
+                                                            advertising,
+                                                            10000baseSR_Full);
+       }
+       if (phy_types & I40E_CAP_PHY_TYPE_10GBASE_LR) {
+               ethtool_link_ksettings_add_link_mode(ksettings, supported,
+                                                    10000baseLR_Full);
+               if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB)
+                       ethtool_link_ksettings_add_link_mode(ksettings,
+                                                            advertising,
+                                                            10000baseLR_Full);
+       }
+       if (phy_types & I40E_CAP_PHY_TYPE_1000BASE_SX ||
+           phy_types & I40E_CAP_PHY_TYPE_1000BASE_LX ||
+           phy_types & I40E_CAP_PHY_TYPE_1000BASE_T_OPTICAL) {
+               ethtool_link_ksettings_add_link_mode(ksettings, supported,
+                                                    1000baseX_Full);
+               if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB)
+                       ethtool_link_ksettings_add_link_mode(ksettings,
+                                                            advertising,
+                                                            1000baseX_Full);
+       }
+#else
+       /* need to keep backward compatibility with older kernels */
+       if (phy_types & I40E_CAP_PHY_TYPE_10GBASE_CR1 ||
+           phy_types & I40E_CAP_PHY_TYPE_10GBASE_CR1_CU ||
+           phy_types & I40E_CAP_PHY_TYPE_10GBASE_SR ||
+           phy_types & I40E_CAP_PHY_TYPE_10GBASE_LR) {
+               ethtool_link_ksettings_add_link_mode(ksettings, supported,
+                                                    10000baseT_Full);
+               if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB)
+                       ethtool_link_ksettings_add_link_mode(ksettings,
+                                                            advertising,
+                                                            10000baseT_Full);
+       }
+       if (phy_types & I40E_CAP_PHY_TYPE_1000BASE_SX ||
+           phy_types & I40E_CAP_PHY_TYPE_1000BASE_LX ||
+           phy_types & I40E_CAP_PHY_TYPE_1000BASE_T_OPTICAL) {
+               ethtool_link_ksettings_add_link_mode(ksettings, supported,
+                                                    1000baseT_Full);
+               if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB)
+                       ethtool_link_ksettings_add_link_mode(ksettings,
+                                                            advertising,
+                                                            1000baseT_Full);
+       }
+#endif /* HAVE_ETHTOOL_NEW_10G_BITS */
+       ksettings->base.speed = SPEED_UNKNOWN;
+       ksettings->base.duplex = DUPLEX_UNKNOWN;
 }
 
 /**
- * i40e_get_pauseparam -  Get Flow Control status
- * Return tx/rx-pause status
+ * i40e_get_link_settings_link_up - Get Link info and duplex settings
+ * @hw: hw structure
+ * @ksettings: ethtool structure to fill in
+ * @netdev: network interface device structure
+ * @pf: pointer to physical function struct
  **/
-static void i40e_get_pauseparam(struct net_device *netdev,
-                               struct ethtool_pauseparam *pause)
+static void i40e_get_link_settings_link_up(struct i40e_hw *hw,
+                                          struct ethtool_link_ksettings *ks,
+                                          struct net_device *netdev,
+                                          struct i40e_pf *pf)
 {
-       struct i40e_netdev_priv *np = netdev_priv(netdev);
-       struct i40e_pf *pf = np->vsi->back;
-       struct i40e_hw *hw = &pf->hw;
-       struct i40e_dcbx_config *dcbx_cfg = &hw->local_dcbx_config;
+       struct i40e_link_status *hw_link_info = &hw->phy.link_info;
+       u32 link_speed = hw_link_info->link_speed;
+       struct ethtool_link_ksettings cap_ksettings;
+       int idx;
 
-       pause->autoneg = hw->phy.link_info.an_info & I40E_AQ_AN_COMPLETED;
+       /* Initialize supported and advertised settings based on phy settings */
+       switch (hw_link_info->phy_type) {
+       case I40E_PHY_TYPE_40GBASE_CR4:
+       case I40E_PHY_TYPE_40GBASE_CR4_CU:
+               ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    40000baseCR4_Full);
+               ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
+               ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                    40000baseCR4_Full);
+               break;
+       case I40E_PHY_TYPE_XLAUI:
+       case I40E_PHY_TYPE_XLPPI:
+       case I40E_PHY_TYPE_40GBASE_AOC:
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    40000baseCR4_Full);
+               break;
+       case I40E_PHY_TYPE_40GBASE_SR4:
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    40000baseSR4_Full);
+               break;
+       case I40E_PHY_TYPE_40GBASE_LR4:
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    40000baseLR4_Full);
+               break;
+       case I40E_PHY_TYPE_25GBASE_SR:
+       case I40E_PHY_TYPE_25GBASE_LR:
+       case I40E_PHY_TYPE_10GBASE_SR:
+       case I40E_PHY_TYPE_10GBASE_LR:
+       case I40E_PHY_TYPE_1000BASE_SX:
+       case I40E_PHY_TYPE_1000BASE_LX:
+               ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
+               ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
+#ifdef HAVE_ETHTOOL_25G_BITS
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    25000baseSR_Full);
+               ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                    25000baseSR_Full);
+#endif /* HAVE_ETHTOOL_25G_BITS */
+#ifdef HAVE_ETHTOOL_NEW_10G_BITS
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    10000baseSR_Full);
+               ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                    10000baseSR_Full);
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    10000baseLR_Full);
+               ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                    10000baseLR_Full);
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    1000baseX_Full);
+               ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                    1000baseX_Full);
+#endif /* HAVE_ETHTOOL_NEW_10G_BITS */
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    10000baseT_Full);
+               if (hw_link_info->module_type[2] &
+                   I40E_MODULE_TYPE_1000BASE_SX ||
+                   hw_link_info->module_type[2] &
+                   I40E_MODULE_TYPE_1000BASE_LX) {
+                       ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                            1000baseT_Full);
+                       if (hw_link_info->requested_speeds &
+                           I40E_LINK_SPEED_1GB)
+                               ethtool_link_ksettings_add_link_mode(ks,
+                                                               advertising,
+                                                               1000baseT_Full);
+               }
+               if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB)
+                       ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                            10000baseT_Full);
+               break;
+       case I40E_PHY_TYPE_10GBASE_T:
+       case I40E_PHY_TYPE_1000BASE_T:
+       case I40E_PHY_TYPE_100BASE_TX:
+               ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    10000baseT_Full);
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    1000baseT_Full);
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    100baseT_Full);
+               ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
+               if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB)
+                       ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                            10000baseT_Full);
+               if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB)
+                       ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                            1000baseT_Full);
+               if (hw_link_info->requested_speeds & I40E_LINK_SPEED_100MB)
+                       ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                            100baseT_Full);
+               break;
+       case I40E_PHY_TYPE_1000BASE_T_OPTICAL:
+               ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    1000baseT_Full);
+               ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
+               ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                    1000baseT_Full);
+               break;
+       case I40E_PHY_TYPE_10GBASE_CR1_CU:
+       case I40E_PHY_TYPE_10GBASE_CR1:
+               ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    10000baseT_Full);
+               ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
+               ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                    10000baseT_Full);
+               break;
+       case I40E_PHY_TYPE_XAUI:
+       case I40E_PHY_TYPE_XFI:
+       case I40E_PHY_TYPE_SFI:
+       case I40E_PHY_TYPE_10GBASE_SFPP_CU:
+       case I40E_PHY_TYPE_10GBASE_AOC:
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    10000baseT_Full);
+               if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB)
+                       ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                            10000baseT_Full);
+               break;
+       case I40E_PHY_TYPE_SGMII:
+               ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    1000baseT_Full);
+               if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB)
+                       ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                            1000baseT_Full);
+               if (pf->hw_features & I40E_HW_100M_SGMII_CAPABLE) {
+                       ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                            100baseT_Full);
+                       if (hw_link_info->requested_speeds &
+                           I40E_LINK_SPEED_100MB)
+                               ethtool_link_ksettings_add_link_mode(ks,
+                                                                advertising,
+                                                                100baseT_Full);
+               }
+               break;
+       case I40E_PHY_TYPE_40GBASE_KR4:
+       case I40E_PHY_TYPE_25GBASE_KR:
+       case I40E_PHY_TYPE_20GBASE_KR2:
+       case I40E_PHY_TYPE_10GBASE_KR:
+       case I40E_PHY_TYPE_10GBASE_KX4:
+       case I40E_PHY_TYPE_1000BASE_KX:
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    40000baseKR4_Full);
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    20000baseKR2_Full);
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    10000baseKR_Full);
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    10000baseKX4_Full);
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    1000baseKX_Full);
+               ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
+               ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                    40000baseKR4_Full);
+               ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                    20000baseKR2_Full);
+               ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                    10000baseKR_Full);
+               ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                    10000baseKX4_Full);
+               ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                    1000baseKX_Full);
+               ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
+#ifdef HAVE_ETHTOOL_25G_BITS
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    25000baseKR_Full);
+               ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                    25000baseKR_Full);
+#endif /* HAVE_ETHTOOL_25G_BITS */
+               break;
+       case I40E_PHY_TYPE_25GBASE_CR:
+               ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
+               ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
+#ifdef HAVE_ETHTOOL_25G_BITS
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    25000baseCR_Full);
+               ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                    25000baseCR_Full);
+#endif /* HAVE_ETHTOOL_25G_BITS */
+               break;
+       case I40E_PHY_TYPE_25GBASE_AOC:
+       case I40E_PHY_TYPE_25GBASE_ACC:
+               ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
+               ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
+#ifdef HAVE_ETHTOOL_25G_BITS
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    25000baseCR_Full);
+
+               ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                    25000baseCR_Full);
+#endif /* HAVE_ETHTOOL_25G_BITS */
+#ifdef HAVE_ETHTOOL_NEW_10G_BITS
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    10000baseCR_Full);
+               ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                    10000baseCR_Full);
+#endif /* HAVE_ETHTOOL_NEW_10G_BITS */
+               break;
+       default:
+               /* if we got here and link is up something bad is afoot */
+               netdev_info(netdev,
+                           "WARNING: Link is up but PHY type 0x%x is not recognized.\n",
+                           hw_link_info->phy_type);
+       }
 
-       /* PFC enabled so report LFC as off */
-       if (dcbx_cfg->pfc.pfcenable) {
-               pause->rx_pause = 0;
-               pause->tx_pause = 0;
-               return;
+       /* Now that we've worked out everything that could be supported by the
+        * current phy type, get what is supported by the NVM and and them to
+        * get what is truly supported
+        */
+       memset(&cap_ksettings, 0, sizeof(struct ethtool_link_ksettings));
+       cap_ksettings.base.cmd = ks->base.cmd;
+       cap_ksettings.base.link_mode_masks_nwords =
+                                          ks->base.link_mode_masks_nwords;
+       i40e_get_link_settings_link_down(hw, &cap_ksettings, pf);
+
+       for (idx = 0; idx < ETHTOOL_LINK_MODE_MASK_U32; idx++) {
+               ks->base.link_mode_masks[idx] &=
+                                       cap_ksettings.base.link_mode_masks[idx];
+               ks->base.link_mode_masks[idx + ETHTOOL_LINK_MODE_MASK_U32] &=
+                                       cap_ksettings.base.link_mode_masks[idx +
+                                       ETHTOOL_LINK_MODE_MASK_U32];
        }
 
-       if (hw->fc.current_mode == I40E_FC_RX_PAUSE) {
-               pause->rx_pause = 1;
-       } else if (hw->fc.current_mode == I40E_FC_TX_PAUSE) {
-               pause->tx_pause = 1;
-       } else if (hw->fc.current_mode == I40E_FC_FULL) {
-               pause->rx_pause = 1;
-               pause->tx_pause = 1;
+       /* Set speed and duplex */
+       switch (link_speed) {
+       case I40E_LINK_SPEED_40GB:
+               ks->base.speed = SPEED_40000;
+               break;
+       case I40E_LINK_SPEED_25GB:
+               ks->base.speed = SPEED_25000;
+               break;
+       case I40E_LINK_SPEED_20GB:
+               ks->base.speed = SPEED_20000;
+               break;
+       case I40E_LINK_SPEED_10GB:
+               ks->base.speed = SPEED_10000;
+               break;
+       case I40E_LINK_SPEED_1GB:
+               ks->base.speed = SPEED_1000;
+               break;
+       case I40E_LINK_SPEED_100MB:
+               ks->base.speed = SPEED_100;
+               break;
+       default:
+               break;
        }
+       ks->base.duplex = DUPLEX_FULL;
 }
 
 /**
- * i40e_set_pauseparam - Set Flow Control parameter
+ * i40e_get_link_settings - Get Link Speed and Duplex settings
  * @netdev: network interface device structure
- * @pause: return tx/rx flow control status
+ * @ksettings: ethtool command
+ *
+ * Reports speed/duplex settings based on media_type
  **/
-static int i40e_set_pauseparam(struct net_device *netdev,
-                              struct ethtool_pauseparam *pause)
+static int i40e_get_link_settings(struct net_device *netdev,
+                                 struct ethtool_link_ksettings *ks)
 {
        struct i40e_netdev_priv *np = netdev_priv(netdev);
        struct i40e_pf *pf = np->vsi->back;
-       struct i40e_vsi *vsi = np->vsi;
        struct i40e_hw *hw = &pf->hw;
        struct i40e_link_status *hw_link_info = &hw->phy.link_info;
-       struct i40e_dcbx_config *dcbx_cfg = &hw->local_dcbx_config;
        bool link_up = hw_link_info->link_info & I40E_AQ_LINK_UP;
-       i40e_status status;
-       u8 aq_failures;
-       int err = 0;
+       struct ethtool_link_settings *settings = &ks->base;
 
-       /* Changing the port's flow control is not supported if this isn't the
-        * port's controlling PF
-        */
-       if (hw->partition_id != 1) {
-               i40e_partition_setting_complaint(pf);
-               return -EOPNOTSUPP;
-       }
+       ethtool_link_ksettings_zero_link_mode(ks, supported);
+       ethtool_link_ksettings_zero_link_mode(ks, advertising);
 
-       if (vsi != pf->vsi[pf->lan_vsi])
-               return -EOPNOTSUPP;
+       if (link_up)
+               i40e_get_link_settings_link_up(hw, ks, netdev, pf);
+       else
+               i40e_get_link_settings_link_down(hw, ks, pf);
 
-       if (pause->autoneg != (hw_link_info->an_info & I40E_AQ_AN_COMPLETED)) {
-               netdev_info(netdev, "To change autoneg please use: ethtool -s <dev> autoneg <on|off>\n");
-               return -EOPNOTSUPP;
-       }
+       /* Now set the settings that don't rely on link being up/down */
+       /* Set autoneg settings */
+       settings->autoneg = (hw_link_info->an_info & I40E_AQ_AN_COMPLETED ?
+                         AUTONEG_ENABLE : AUTONEG_DISABLE);
 
-       /* If we have link and don't have autoneg */
-       if (!test_bit(__I40E_DOWN, &pf->state) &&
-           !(hw_link_info->an_info & I40E_AQ_AN_COMPLETED)) {
-               /* Send message that it might not necessarily work*/
-               netdev_info(netdev, "Autoneg did not complete so changing settings may not result in an actual change.\n");
+       /* Set media type settings */
+       switch (hw->phy.media_type) {
+       case I40E_MEDIA_TYPE_BACKPLANE:
+               ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
+               ethtool_link_ksettings_add_link_mode(ks, supported, Backplane);
+               ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
+               ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                    Backplane);
+               settings->port = PORT_NONE;
+               break;
+       case I40E_MEDIA_TYPE_BASET:
+               ethtool_link_ksettings_add_link_mode(ks, supported, TP);
+               ethtool_link_ksettings_add_link_mode(ks, advertising, TP);
+               settings->port = PORT_TP;
+               break;
+       case I40E_MEDIA_TYPE_DA:
+       case I40E_MEDIA_TYPE_CX4:
+               ethtool_link_ksettings_add_link_mode(ks, supported, FIBRE);
+               ethtool_link_ksettings_add_link_mode(ks, advertising, FIBRE);
+               settings->port = PORT_DA;
+               break;
+       case I40E_MEDIA_TYPE_FIBER:
+               ethtool_link_ksettings_add_link_mode(ks, supported, FIBRE);
+               settings->port = PORT_FIBRE;
+               break;
+       case I40E_MEDIA_TYPE_UNKNOWN:
+       default:
+               settings->port = PORT_OTHER;
+               break;
        }
 
-       if (dcbx_cfg->pfc.pfcenable) {
-               netdev_info(netdev,
-                        "Priority flow control enabled. Cannot set link flow control.\n");
-               return -EOPNOTSUPP;
-       }
+       /* Set flow control settings */
+       ethtool_link_ksettings_add_link_mode(ks, supported, Pause);
 
-       if (pause->rx_pause && pause->tx_pause)
-               hw->fc.requested_mode = I40E_FC_FULL;
-       else if (pause->rx_pause && !pause->tx_pause)
-               hw->fc.requested_mode = I40E_FC_RX_PAUSE;
-       else if (!pause->rx_pause && pause->tx_pause)
-               hw->fc.requested_mode = I40E_FC_TX_PAUSE;
+       switch (hw->fc.requested_mode) {
+       case I40E_FC_FULL:
+               ethtool_link_ksettings_add_link_mode(ks, advertising, Pause);
+               break;
+       case I40E_FC_TX_PAUSE:
+               ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                    Asym_Pause);
+               break;
+       case I40E_FC_RX_PAUSE:
+               ethtool_link_ksettings_add_link_mode(ks, advertising, Pause);
+               ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                    Asym_Pause);
+               break;
+       default:
+               ethtool_link_ksettings_clear_link_mode(ks, advertising, Pause);
+               ethtool_link_ksettings_clear_link_mode(ks, advertising,
+                                                      Asym_Pause);
+               break;
+       }
+       return 0;
+}
+
+/**
+ * i40e_set_link_settings - Set Speed and Duplex
+ * @netdev: network interface device structure
+ * @ksettings_passed: ethtool command
+ *
+ * Set speed/duplex per media_types advertised/forced
+ **/
+static int i40e_set_link_settings(struct net_device *netdev,
+                         const struct ethtool_link_ksettings *ksettings_passed)
+{
+       struct i40e_netdev_priv *np = netdev_priv(netdev);
+       struct i40e_aq_get_phy_abilities_resp abilities;
+       struct i40e_aq_set_phy_config config;
+       struct i40e_pf *pf = np->vsi->back;
+       struct i40e_vsi *vsi = np->vsi;
+       struct i40e_hw *hw = &pf->hw;
+       struct ethtool_link_ksettings safe_ksettings;
+       i40e_status status = 0;
+       bool autoneg_changed = false;
+       int timeout = 50;
+       int err = 0;
+       u8 autoneg;
+       struct ethtool_link_ksettings ksettings_real, *ksettings;
+       u32 advertise[ETHTOOL_LINK_MODE_MASK_U32];
+
+       ksettings = &ksettings_real;
+       memcpy(ksettings,
+              ksettings_passed,
+              sizeof(struct ethtool_link_ksettings));
+
+       /* Changing port settings is not supported if this isn't the
+        * port's controlling PF
+        */
+       if (hw->partition_id != 1) {
+               i40e_partition_setting_complaint(pf);
+               return -EOPNOTSUPP;
+       }
+       if (vsi != pf->vsi[pf->lan_vsi])
+               return -EOPNOTSUPP;
+       if (hw->phy.media_type != I40E_MEDIA_TYPE_BASET &&
+           hw->phy.media_type != I40E_MEDIA_TYPE_FIBER &&
+           hw->phy.media_type != I40E_MEDIA_TYPE_BACKPLANE &&
+           hw->phy.media_type != I40E_MEDIA_TYPE_DA &&
+           hw->phy.link_info.link_info & I40E_AQ_LINK_UP)
+               return -EOPNOTSUPP;
+       if (hw->device_id == I40E_DEV_ID_KX_B ||
+           hw->device_id == I40E_DEV_ID_KX_C ||
+           hw->device_id == I40E_DEV_ID_20G_KR2 ||
+           hw->device_id == I40E_DEV_ID_20G_KR2_A) {
+               netdev_info(netdev,
+                           "Changing settings is not supported on backplane.\n");
+               return -EOPNOTSUPP;
+       }
+
+       /* get our own copy of the bits to check against */
+       memset(&safe_ksettings, 0, sizeof(struct ethtool_link_ksettings));
+       safe_ksettings.base.cmd                    = ksettings->base.cmd;
+       safe_ksettings.base.link_mode_masks_nwords =
+               ksettings->base.link_mode_masks_nwords;
+       i40e_get_link_settings(netdev, &safe_ksettings);
+
+       /* save autoneg and speed out of ksettings */
+       autoneg = ksettings->base.autoneg;
+       memcpy((void *)advertise,
+              &ksettings->base.link_mode_masks[ETHTOOL_LINK_MODE_MASK_U32],
+              sizeof(advertise));
+
+       /* set autoneg and speed back to what they currently are */
+       ksettings->base.autoneg = safe_ksettings.base.autoneg;
+       memcpy((void *)ksettings->link_modes.advertising,
+              safe_ksettings.link_modes.advertising,
+              sizeof(advertise));
+
+       /* If ksettings and safe_ksettings are not the same now, then they are
+        * trying to set something that we do not support
+        */
+       if (memcmp(ksettings, &safe_ksettings,
+                  sizeof(struct ethtool_link_settings)))
+               return -EOPNOTSUPP;
+
+       while (test_and_set_bit(__I40E_CONFIG_BUSY, pf->state)) {
+               timeout--;
+               if (!timeout)
+                       return -EBUSY;
+               usleep_range(1000, 2000);
+       }
+
+       /* Get the current phy config */
+       status = i40e_aq_get_phy_capabilities(hw, false, false, &abilities,
+                                             NULL);
+       if (status) {
+               err = -EAGAIN;
+               goto done;
+       }
+
+       /* Copy abilities to config in case autoneg is not
+        * set below
+        */
+       memset(&config, 0, sizeof(struct i40e_aq_set_phy_config));
+       config.abilities = abilities.abilities;
+
+       /* Check autoneg */
+       if (autoneg == AUTONEG_ENABLE) {
+               /* If autoneg was not already enabled */
+               if (!(hw->phy.link_info.an_info & I40E_AQ_AN_COMPLETED)) {
+                       /* If autoneg is not supported, return error */
+                       if (!(safe_ksettings.link_modes.supported[0] &
+                             SUPPORTED_Autoneg)) {
+                               netdev_info(netdev,
+                                           "Autoneg not supported on this phy\n");
+                               err = -EINVAL;
+                               goto done;
+                       }
+                       /* Autoneg is allowed to change */
+                       config.abilities = abilities.abilities |
+                                          I40E_AQ_PHY_ENABLE_AN;
+                       autoneg_changed = true;
+               }
+       } else {
+               /* If autoneg is currently enabled */
+               if (hw->phy.link_info.an_info & I40E_AQ_AN_COMPLETED) {
+                       /* If autoneg is supported 10GBASE_T is the only phy
+                        * that can disable it, so otherwise return error
+                        */
+                       if (safe_ksettings.link_modes.supported[0] &
+                           SUPPORTED_Autoneg &&
+                           hw->phy.link_info.phy_type !=
+                           I40E_PHY_TYPE_10GBASE_T) {
+                               netdev_info(netdev,
+                                           "Autoneg cannot be disabled on this phy\n");
+                               err = -EINVAL;
+                               goto done;
+                       }
+                       /* Autoneg is allowed to change */
+                       config.abilities = abilities.abilities &
+                                          ~I40E_AQ_PHY_ENABLE_AN;
+                       autoneg_changed = true;
+               }
+       }
+       if (advertise[0] & ADVERTISED_100baseT_Full)
+               config.link_speed |= I40E_LINK_SPEED_100MB;
+       if (advertise[0] & ADVERTISED_1000baseT_Full ||
+           advertise[0] & ADVERTISED_1000baseKX_Full)
+               config.link_speed |= I40E_LINK_SPEED_1GB;
+       if (advertise[0] & ADVERTISED_10000baseT_Full ||
+           advertise[0] & ADVERTISED_10000baseKX4_Full ||
+           advertise[0] & ADVERTISED_10000baseKR_Full)
+               config.link_speed |= I40E_LINK_SPEED_10GB;
+#ifdef HAVE_ETHTOOL_NEW_10G_BITS
+       if (ethtool_link_ksettings_test_link_mode(ksettings_passed, advertising,
+                                                 1000baseX_Full))
+               config.link_speed |= I40E_LINK_SPEED_1GB;
+
+       if (ethtool_link_ksettings_test_link_mode(ksettings_passed, advertising,
+                                                 10000baseCR_Full) ||
+           ethtool_link_ksettings_test_link_mode(ksettings_passed, advertising,
+                                                 10000baseKR_Full) ||
+           ethtool_link_ksettings_test_link_mode(ksettings_passed, advertising,
+                                                 10000baseSR_Full))
+               config.link_speed |= I40E_LINK_SPEED_10GB;
+#endif /* HAVE_ETHTOOL_NEW_10G_BITS */
+       if (advertise[0] & ADVERTISED_20000baseKR2_Full)
+               config.link_speed |= I40E_LINK_SPEED_20GB;
+#ifdef HAVE_ETHTOOL_25G_BITS
+       if (ethtool_link_ksettings_test_link_mode(ksettings_passed, advertising,
+                                                 25000baseCR_Full) ||
+           ethtool_link_ksettings_test_link_mode(ksettings_passed, advertising,
+                                                 25000baseKR_Full) ||
+           ethtool_link_ksettings_test_link_mode(ksettings_passed, advertising,
+                                                 25000baseSR_Full))
+               config.link_speed |= I40E_LINK_SPEED_25GB;
+#endif /* HAVE_ETHTOOL_25G_BITS */
+       if (advertise[0] & ADVERTISED_40000baseKR4_Full ||
+           advertise[0] & ADVERTISED_40000baseCR4_Full ||
+           advertise[0] & ADVERTISED_40000baseSR4_Full ||
+           advertise[0] & ADVERTISED_40000baseLR4_Full)
+               config.link_speed |= I40E_LINK_SPEED_40GB;
+
+       /* If speed didn't get set, set it to what it currently is.
+        * This is needed because if advertise is 0 (as it is when autoneg
+        * is disabled) then speed won't get set.
+        */
+       if (!config.link_speed)
+               config.link_speed = abilities.link_speed;
+       if (autoneg_changed || (abilities.link_speed != config.link_speed)) {
+               /* copy over the rest of the abilities */
+               config.phy_type = abilities.phy_type;
+               config.phy_type_ext = abilities.phy_type_ext;
+               config.eee_capability = abilities.eee_capability;
+               config.eeer = abilities.eeer_val;
+               config.low_power_ctrl = abilities.d3_lpan;
+               config.fec_config = abilities.fec_cfg_curr_mod_ext_info &
+                                   I40E_AQ_PHY_FEC_CONFIG_MASK;
+
+               /* save the requested speeds */
+               hw->phy.link_info.requested_speeds = config.link_speed;
+               /* set link and auto negotiation so changes take effect */
+               config.abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
+               /* If link is up put link down */
+               if (hw->phy.link_info.link_info & I40E_AQ_LINK_UP) {
+                       /* Tell the OS link is going down, the link will go
+                        * back up when fw says it is ready asynchronously
+                        */
+                       i40e_print_link_message(vsi, false);
+                       netif_carrier_off(netdev);
+                       netif_tx_stop_all_queues(netdev);
+               }
+
+               /* make the aq call */
+               status = i40e_aq_set_phy_config(hw, &config, NULL);
+               if (status) {
+                       netdev_info(netdev,
+                                   "Set phy config failed, err %s aq_err %s\n",
+                                   i40e_stat_str(hw, status),
+                                   i40e_aq_str(hw, hw->aq.asq_last_status));
+                       err = -EAGAIN;
+                       goto done;
+               }
+               status = i40e_update_link_info(hw);
+               if (status)
+                       netdev_dbg(netdev,
+                                  "Updating link info failed with err %s aq_err %s\n",
+                                  i40e_stat_str(hw, status),
+                                  i40e_aq_str(hw, hw->aq.asq_last_status));
+       } else {
+               netdev_info(netdev,
+                           "Nothing changed, exiting without setting anything.\n");
+       }
+
+done:
+       clear_bit(__I40E_CONFIG_BUSY, pf->state);
+
+       return err;
+}
+
+#endif /* ETHTOOL_GLINKSETTINGS */
+static int i40e_nway_reset(struct net_device *netdev)
+{
+       /* restart autonegotiation */
+       struct i40e_netdev_priv *np = netdev_priv(netdev);
+       struct i40e_pf *pf = np->vsi->back;
+       struct i40e_hw *hw = &pf->hw;
+       bool link_up = hw->phy.link_info.link_info & I40E_AQ_LINK_UP;
+       i40e_status ret = 0;
+
+       ret = i40e_aq_set_link_restart_an(hw, link_up, NULL);
+       if (ret) {
+               netdev_info(netdev, "link restart failed, err %s aq_err %s\n",
+                           i40e_stat_str(hw, ret),
+                           i40e_aq_str(hw, hw->aq.asq_last_status));
+               return -EIO;
+       }
+
+       return 0;
+}
+
+/**
+ * i40e_get_pauseparam -  Get Flow Control status
+ * Return tx/rx-pause status
+ **/
+static void i40e_get_pauseparam(struct net_device *netdev,
+                               struct ethtool_pauseparam *pause)
+{
+       struct i40e_netdev_priv *np = netdev_priv(netdev);
+       struct i40e_pf *pf = np->vsi->back;
+       struct i40e_hw *hw = &pf->hw;
+       struct i40e_dcbx_config *dcbx_cfg = &hw->local_dcbx_config;
+
+       pause->autoneg = hw->phy.link_info.an_info & I40E_AQ_AN_COMPLETED;
+
+       /* PFC enabled so report LFC as off */
+       if (dcbx_cfg->pfc.pfcenable) {
+               pause->rx_pause = 0;
+               pause->tx_pause = 0;
+               return;
+       }
+
+       if (hw->fc.current_mode == I40E_FC_RX_PAUSE) {
+               pause->rx_pause = 1;
+       } else if (hw->fc.current_mode == I40E_FC_TX_PAUSE) {
+               pause->tx_pause = 1;
+       } else if (hw->fc.current_mode == I40E_FC_FULL) {
+               pause->rx_pause = 1;
+               pause->tx_pause = 1;
+       }
+}
+
+/**
+ * i40e_set_pauseparam - Set Flow Control parameter
+ * @netdev: network interface device structure
+ * @pause: return tx/rx flow control status
+ **/
+static int i40e_set_pauseparam(struct net_device *netdev,
+                              struct ethtool_pauseparam *pause)
+{
+       struct i40e_netdev_priv *np = netdev_priv(netdev);
+       struct i40e_pf *pf = np->vsi->back;
+       struct i40e_vsi *vsi = np->vsi;
+       struct i40e_hw *hw = &pf->hw;
+       struct i40e_link_status *hw_link_info = &hw->phy.link_info;
+       struct i40e_dcbx_config *dcbx_cfg = &hw->local_dcbx_config;
+       bool link_up = hw_link_info->link_info & I40E_AQ_LINK_UP;
+       i40e_status status;
+       u8 aq_failures;
+       int err = 0;
+
+       /* Changing the port's flow control is not supported if this isn't the
+        * port's controlling PF
+        */
+       if (hw->partition_id != 1) {
+               i40e_partition_setting_complaint(pf);
+               return -EOPNOTSUPP;
+       }
+
+       if (vsi != pf->vsi[pf->lan_vsi])
+               return -EOPNOTSUPP;
+
+       if (pause->autoneg != (hw_link_info->an_info & I40E_AQ_AN_COMPLETED)) {
+               netdev_info(netdev, "To change autoneg please use: ethtool -s <dev> autoneg <on|off>\n");
+               return -EOPNOTSUPP;
+       }
+
+       /* If we have link and don't have autoneg */
+       if (!test_bit(__I40E_DOWN, pf->state) &&
+           !(hw_link_info->an_info & I40E_AQ_AN_COMPLETED)) {
+               /* Send message that it might not necessarily work*/
+               netdev_info(netdev, "Autoneg did not complete so changing settings may not result in an actual change.\n");
+       }
+
+       if (dcbx_cfg->pfc.pfcenable) {
+               netdev_info(netdev,
+                        "Priority flow control enabled. Cannot set link flow control.\n");
+               return -EOPNOTSUPP;
+       }
+
+       if (pause->rx_pause && pause->tx_pause)
+               hw->fc.requested_mode = I40E_FC_FULL;
+       else if (pause->rx_pause && !pause->tx_pause)
+               hw->fc.requested_mode = I40E_FC_RX_PAUSE;
+       else if (!pause->rx_pause && pause->tx_pause)
+               hw->fc.requested_mode = I40E_FC_TX_PAUSE;
        else if (!pause->rx_pause && !pause->tx_pause)
                hw->fc.requested_mode = I40E_FC_NONE;
        else
@@ -1034,10 +1782,10 @@ static int i40e_set_pauseparam(struct net_device *netdev,
                err = -EAGAIN;
        }
 
-       if (!test_bit(__I40E_DOWN, &pf->state)) {
+       if (!test_bit(__I40E_DOWN, pf->state)) {
                /* Give it a little more time to try to come back */
                msleep(75);
-               if (!test_bit(__I40E_DOWN, &pf->state))
+               if (!test_bit(__I40E_DOWN, pf->state))
                        return i40e_nway_reset(netdev);
        }
 
@@ -1160,7 +1908,7 @@ static int i40e_set_flags(struct net_device *netdev, u32 data)
        need_reset = i40e_set_ntuple(pf, netdev->features);
 #endif /* ETHTOOL_GRXRINGS */
        if (need_reset)
-               i40e_do_reset(pf, BIT(__I40E_PF_RESET_REQUESTED));
+               i40e_do_reset(pf, BIT(__I40E_PF_RESET_REQUESTED), true);
 
        return 0;
 }
@@ -1252,8 +2000,8 @@ static int i40e_get_eeprom(struct net_device *netdev,
                /* make sure it is the right magic for NVMUpdate */
                if ((eeprom->magic >> 16) != hw->device_id)
                        errno = -EINVAL;
-               else if (test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state) ||
-                        test_bit(__I40E_RESET_INTR_RECEIVED, &pf->state))
+               else if (test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state) ||
+                        test_bit(__I40E_RESET_INTR_RECEIVED, pf->state))
                        errno = -EBUSY;
                else
                        ret_val = i40e_nvmupd_command(hw, cmd, bytes, &errno);
@@ -1359,8 +2107,8 @@ static int i40e_set_eeprom(struct net_device *netdev,
        /* check for NVMUpdate access method */
        else if (!eeprom->magic || (eeprom->magic >> 16) != hw->device_id)
                errno = -EINVAL;
-       else if (test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state) ||
-                test_bit(__I40E_RESET_INTR_RECEIVED, &pf->state))
+       else if (test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state) ||
+                test_bit(__I40E_RESET_INTR_RECEIVED, pf->state))
                errno = -EBUSY;
        else
                ret_val = i40e_nvmupd_command(hw, cmd, bytes, &errno);
@@ -1418,9 +2166,11 @@ static int i40e_set_ringparam(struct net_device *netdev,
 {
        struct i40e_ring *tx_rings = NULL, *rx_rings = NULL;
        struct i40e_netdev_priv *np = netdev_priv(netdev);
+       struct i40e_hw *hw = &np->vsi->back->hw;
        struct i40e_vsi *vsi = np->vsi;
        struct i40e_pf *pf = vsi->back;
        u32 new_rx_count, new_tx_count;
+       int timeout = 50;
        int i, err = 0;
 
        if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
@@ -1445,8 +2195,12 @@ static int i40e_set_ringparam(struct net_device *netdev,
            (new_rx_count == vsi->rx_rings[0]->count))
                return 0;
 
-       while (test_and_set_bit(__I40E_CONFIG_BUSY, &pf->state))
+       while (test_and_set_bit(__I40E_CONFIG_BUSY, pf->state)) {
+               timeout--;
+               if (!timeout)
+                       return -EBUSY;
                usleep_range(1000, 2000);
+       }
 
        if (!netif_running(vsi->netdev)) {
                /* simple case - set for the next time the netdev is started */
@@ -1510,10 +2264,6 @@ static int i40e_set_ringparam(struct net_device *netdev,
                }
 
                for (i = 0; i < vsi->num_queue_pairs; i++) {
-                       /* this is to allow wr32 to have something to write to
-                        * during early allocation of rx buffers
-                        */
-                       u32 __iomem faketail = 0;
                        struct i40e_ring *ring;
                        u16 unused;
 
@@ -1525,7 +2275,10 @@ static int i40e_set_ringparam(struct net_device *netdev,
                         */
                        rx_rings[i].desc = NULL;
                        rx_rings[i].rx_bi = NULL;
-                       rx_rings[i].tail = (u8 __iomem *)&faketail;
+                       /* this is to allow wr32 to have something to write to
+                        * during early allocation of Rx buffers
+                        */
+                       rx_rings[i].tail = hw->hw_addr + I40E_PRTGEN_STATUS;
                        err = i40e_setup_rx_descriptors(&rx_rings[i]);
                        if (err)
                                goto rx_unwind;
@@ -1595,7 +2348,7 @@ free_tx:
        }
 
 done:
-       clear_bit(__I40E_CONFIG_BUSY, &pf->state);
+       clear_bit(__I40E_CONFIG_BUSY, pf->state);
 
        return err;
 }
@@ -1677,13 +2430,6 @@ static void i40e_get_ethtool_stats(struct net_device *netdev,
                data[i++] = (i40e_gstrings_misc_stats[j].sizeof_stat ==
                            sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
        }
-#ifdef I40E_FCOE
-       for (j = 0; j < I40E_FCOE_STATS_LEN; j++) {
-               p = (char *)vsi + i40e_gstrings_fcoe_stats[j].stat_offset;
-               data[i++] = (i40e_gstrings_fcoe_stats[j].sizeof_stat ==
-                       sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
-       }
-#endif
        rcu_read_lock();
        for (j = 0; j < vsi->num_queue_pairs; j++) {
                tx_ring = ACCESS_ONCE(vsi->tx_rings[j]);
@@ -1779,13 +2525,6 @@ static void i40e_get_strings(struct net_device *netdev, u32 stringset,
                                 i40e_gstrings_misc_stats[i].stat_string);
                        p += ETH_GSTRING_LEN;
                }
-#ifdef I40E_FCOE
-               for (i = 0; i < I40E_FCOE_STATS_LEN; i++) {
-                       snprintf(p, ETH_GSTRING_LEN, "%s",
-                                i40e_gstrings_fcoe_stats[i].stat_string);
-                       p += ETH_GSTRING_LEN;
-               }
-#endif
                for (i = 0; i < vsi->num_queue_pairs; i++) {
                        snprintf(p, ETH_GSTRING_LEN, "tx-%u.tx_packets", i);
                        p += ETH_GSTRING_LEN;
@@ -1851,12 +2590,18 @@ static void i40e_get_strings(struct net_device *netdev, u32 stringset,
                break;
 #ifdef HAVE_ETHTOOL_GET_SSET_COUNT
        case ETH_SS_PRIV_FLAGS:
-               memcpy(data, i40e_priv_flags_strings,
-                      I40E_PRIV_FLAGS_STR_LEN * ETH_GSTRING_LEN);
-               data += I40E_PRIV_FLAGS_STR_LEN * ETH_GSTRING_LEN;
-               if (pf->hw.pf_id == 0)
-                       memcpy(data, i40e_gl_priv_flags_strings,
-                              I40E_GL_PRIV_FLAGS_STR_LEN * ETH_GSTRING_LEN);
+               for (i = 0; i < I40E_PRIV_FLAGS_STR_LEN; i++) {
+                       snprintf(p, ETH_GSTRING_LEN, "%s",
+                                i40e_gstrings_priv_flags[i].flag_string);
+                       p += ETH_GSTRING_LEN;
+               }
+               if (pf->hw.pf_id != 0)
+                       break;
+               for (i = 0; i < I40E_GL_PRIV_FLAGS_STR_LEN; i++) {
+                       snprintf(p, ETH_GSTRING_LEN, "%s",
+                                i40e_gl_gstrings_priv_flags[i].flag_string);
+                       p += ETH_GSTRING_LEN;
+               }
                break;
 #endif
        default:
@@ -1894,7 +2639,7 @@ static int i40e_get_ts_info(struct net_device *dev,
                           BIT(HWTSTAMP_FILTER_PTP_V2_L2_SYNC) |
                           BIT(HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ);
 
-       if (pf->flags & I40E_FLAG_PTP_L4_CAPABLE)
+       if (pf->hw_features & I40E_HW_PTP_L4_CAPABLE)
                info->rx_filters |= BIT(HWTSTAMP_FILTER_PTP_V1_L4_SYNC) |
                                    BIT(HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) |
                                    BIT(HWTSTAMP_FILTER_PTP_V2_EVENT) |
@@ -1991,7 +2736,7 @@ static inline bool i40e_active_vfs(struct i40e_pf *pf)
        int i;
 
        for (i = 0; i < pf->num_alloc_vfs; i++)
-               if (test_bit(I40E_VF_STAT_ACTIVE, &vfs[i].vf_states))
+               if (test_bit(I40E_VF_STATE_ACTIVE, &vfs[i].vf_states))
                        return true;
        return false;
 }
@@ -2012,7 +2757,7 @@ static void i40e_diag_test(struct net_device *netdev,
                /* Offline tests */
                netif_info(pf, drv, netdev, "offline testing starting\n");
 
-               set_bit(__I40E_TESTING, &pf->state);
+               set_bit(__I40E_TESTING, pf->state);
 
                if (i40e_active_vfs(pf) || i40e_active_vmdqs(pf)) {
                        dev_warn(&pf->pdev->dev,
@@ -2022,7 +2767,7 @@ static void i40e_diag_test(struct net_device *netdev,
                        data[I40E_ETH_TEST_INTR]        = 1;
                        data[I40E_ETH_TEST_LINK]        = 1;
                        eth_test->flags |= ETH_TEST_FL_FAILED;
-                       clear_bit(__I40E_TESTING, &pf->state);
+                       clear_bit(__I40E_TESTING, pf->state);
                        goto skip_ol_tests;
                }
 
@@ -2036,7 +2781,7 @@ static void i40e_diag_test(struct net_device *netdev,
                         * link then the following link test would have
                         * to be moved to before the reset
                         */
-                       i40e_do_reset(pf, BIT(__I40E_PF_RESET_REQUESTED));
+                       i40e_do_reset(pf, BIT(__I40E_PF_RESET_REQUESTED), true);
 
                if (i40e_link_test(netdev, &data[I40E_ETH_TEST_LINK]))
                        eth_test->flags |= ETH_TEST_FL_FAILED;
@@ -2051,8 +2796,8 @@ static void i40e_diag_test(struct net_device *netdev,
                if (i40e_reg_test(netdev, &data[I40E_ETH_TEST_REG]))
                        eth_test->flags |= ETH_TEST_FL_FAILED;
 
-               clear_bit(__I40E_TESTING, &pf->state);
-               i40e_do_reset(pf, BIT(__I40E_PF_RESET_REQUESTED));
+               clear_bit(__I40E_TESTING, pf->state);
+               i40e_do_reset(pf, BIT(__I40E_PF_RESET_REQUESTED), true);
 
                if (if_running)
                        i40e_open(netdev);
@@ -2146,35 +2891,38 @@ static int i40e_set_phys_id(struct net_device *netdev,
 
        switch (state) {
        case ETHTOOL_ID_ACTIVE:
-               if (!(pf->flags & I40E_FLAG_PHY_CONTROLS_LEDS)) {
+               if (!(pf->hw_features & I40E_HW_PHY_CONTROLS_LEDS)) {
                        pf->led_status = i40e_led_get(hw);
                } else {
-                       i40e_aq_set_phy_debug(hw, I40E_PHY_DEBUG_ALL, NULL);
+                       if (!(hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE))
+                               i40e_aq_set_phy_debug(hw, I40E_PHY_DEBUG_ALL,
+                                                     NULL);
                        ret = i40e_led_get_phy(hw, &temp_status,
                                               &pf->phy_led_val);
                        pf->led_status = temp_status;
                }
                return blink_freq;
        case ETHTOOL_ID_ON:
-               if (!(pf->flags & I40E_FLAG_PHY_CONTROLS_LEDS))
+               if (!(pf->hw_features & I40E_HW_PHY_CONTROLS_LEDS))
                        i40e_led_set(hw, 0xf, false);
                else
                        ret = i40e_led_set_phy(hw, true, pf->led_status, 0);
                break;
        case ETHTOOL_ID_OFF:
-               if (!(pf->flags & I40E_FLAG_PHY_CONTROLS_LEDS))
+               if (!(pf->hw_features & I40E_HW_PHY_CONTROLS_LEDS))
                        i40e_led_set(hw, 0x0, false);
                else
                        ret = i40e_led_set_phy(hw, false, pf->led_status, 0);
                break;
        case ETHTOOL_ID_INACTIVE:
-               if (!(pf->flags & I40E_FLAG_PHY_CONTROLS_LEDS)) {
+               if (!(pf->hw_features & I40E_HW_PHY_CONTROLS_LEDS)) {
                        i40e_led_set(hw, pf->led_status, false);
                } else {
                        ret = i40e_led_set_phy(hw, false, pf->led_status,
                                               (pf->phy_led_val |
                                               I40E_PHY_LED_MODE_ORIG));
-                       i40e_aq_set_phy_debug(hw, 0, NULL);
+                       if (!(hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE))
+                               i40e_aq_set_phy_debug(hw, 0, NULL);
                }
                break;
        default:
@@ -2195,7 +2943,7 @@ static int i40e_phys_id(struct net_device *netdev, u32 data)
        u16 temp_status;
        int i;
 
-       if (!(pf->flags & I40E_FLAG_PHY_CONTROLS_LEDS)) {
+       if (!(pf->hw_features & I40E_HW_PHY_CONTROLS_LEDS)) {
                pf->led_status = i40e_led_get(hw);
        } else {
                ret = i40e_led_get_phy(hw, &temp_status,
@@ -2208,18 +2956,18 @@ static int i40e_phys_id(struct net_device *netdev, u32 data)
 
        /* 10GBaseT PHY controls led's through PHY, not MAC */
        for (i = 0; i < (data * 1000); i += 400) {
-               if (!(pf->flags & I40E_FLAG_PHY_CONTROLS_LEDS))
+               if (!(pf->hw_features & I40E_HW_PHY_CONTROLS_LEDS))
                        i40e_led_set(hw, 0xF, false);
                else
                        ret = i40e_led_set_phy(hw, true, pf->led_status, 0);
                msleep_interruptible(200);
-               if (!(pf->flags & I40E_FLAG_PHY_CONTROLS_LEDS))
+               if (!(pf->hw_features & I40E_HW_PHY_CONTROLS_LEDS))
                        i40e_led_set(hw, 0x0, false);
                else
                        ret = i40e_led_set_phy(hw, false, pf->led_status, 0);
                msleep_interruptible(200);
        }
-       if (!(pf->flags & I40E_FLAG_PHY_CONTROLS_LEDS))
+       if (!(pf->hw_features & I40E_HW_PHY_CONTROLS_LEDS))
                i40e_led_set(hw, pf->led_status, false);
        else
                ret = i40e_led_set_phy(hw, false, pf->led_status,
@@ -2381,14 +3129,29 @@ static int __i40e_set_coalesce(struct net_device *netdev,
                               int queue)
 {
        struct i40e_netdev_priv *np = netdev_priv(netdev);
+       u16 intrl_reg, cur_rx_itr, cur_tx_itr;
        struct i40e_vsi *vsi = np->vsi;
        struct i40e_pf *pf = vsi->back;
-       u16 intrl_reg;
        int i;
 
        if (ec->tx_max_coalesced_frames_irq || ec->rx_max_coalesced_frames_irq)
                vsi->work_limit = ec->tx_max_coalesced_frames_irq;
 
+       if (queue < 0) {
+               cur_rx_itr = vsi->rx_rings[0]->rx_itr_setting;
+               cur_tx_itr = vsi->tx_rings[0]->tx_itr_setting;
+       } else if (queue < vsi->num_queue_pairs) {
+               cur_rx_itr = vsi->rx_rings[queue]->rx_itr_setting;
+               cur_tx_itr = vsi->tx_rings[queue]->tx_itr_setting;
+       } else {
+               netif_info(pf, drv, netdev, "Invalid queue value, queue range is 0 - %d\n",
+                          vsi->num_queue_pairs - 1);
+               return -EINVAL;
+       }
+
+       cur_tx_itr &= ~I40E_ITR_DYNAMIC;
+       cur_rx_itr &= ~I40E_ITR_DYNAMIC;
+
        /* tx_coalesce_usecs_high is ignored, use rx-usecs-high instead */
        if (ec->tx_coalesce_usecs_high != vsi->int_rate_limit) {
                netif_info(pf, drv, netdev, "tx-usecs-high is not used, please program rx-usecs-high\n");
@@ -2401,15 +3164,34 @@ static int __i40e_set_coalesce(struct net_device *netdev,
                return -EINVAL;
        }
 
-       if (ec->rx_coalesce_usecs == 0) {
-               if (ec->use_adaptive_rx_coalesce)
-                       netif_info(pf, drv, netdev, "rx-usecs=0, need to disable adaptive-rx for a complete disable\n");
-       } else if ((ec->rx_coalesce_usecs < (I40E_MIN_ITR << 1)) ||
-                  (ec->rx_coalesce_usecs > (I40E_MAX_ITR << 1))) {
+       if (ec->rx_coalesce_usecs != cur_rx_itr &&
+           ec->use_adaptive_rx_coalesce) {
+               netif_info(pf, drv, netdev, "RX interrupt moderation cannot be changed if adaptive-rx is enabled.\n");
+               return -EINVAL;
+       }
+
+       if (ec->rx_coalesce_usecs > (I40E_MAX_ITR << 1)) {
                netif_info(pf, drv, netdev, "Invalid value, rx-usecs range is 0-8160\n");
                return -EINVAL;
        }
 
+       if (ec->tx_coalesce_usecs != cur_tx_itr &&
+           ec->use_adaptive_tx_coalesce) {
+               netif_info(pf, drv, netdev, "TX interrupt moderation cannot be changed if adaptive-tx is enabled.\n");
+               return -EINVAL;
+       }
+
+       if (ec->tx_coalesce_usecs > (I40E_MAX_ITR << 1)) {
+               netif_info(pf, drv, netdev, "Invalid value, tx-usecs range is 0-8160\n");
+               return -EINVAL;
+       }
+
+       if (ec->use_adaptive_rx_coalesce && !cur_rx_itr)
+               ec->rx_coalesce_usecs = I40E_MIN_ITR << 1;
+
+       if (ec->use_adaptive_tx_coalesce && !cur_tx_itr)
+               ec->tx_coalesce_usecs = I40E_MIN_ITR << 1;
+
        intrl_reg = i40e_intrl_usec_to_reg(ec->rx_coalesce_usecs_high);
        vsi->int_rate_limit = INTRL_REG_TO_USEC(intrl_reg);
        if (vsi->int_rate_limit != ec->rx_coalesce_usecs_high) {
@@ -2417,27 +3199,14 @@ static int __i40e_set_coalesce(struct net_device *netdev,
                           vsi->int_rate_limit);
        }
 
-       if (ec->tx_coalesce_usecs == 0) {
-               if (ec->use_adaptive_tx_coalesce)
-                       netif_info(pf, drv, netdev, "tx-usecs=0, need to disable adaptive-tx for a complete disable\n");
-       } else if ((ec->tx_coalesce_usecs < (I40E_MIN_ITR << 1)) ||
-                  (ec->tx_coalesce_usecs > (I40E_MAX_ITR << 1))) {
-               netif_info(pf, drv, netdev, "Invalid value, tx-usecs range is 0-8160\n");
-               return -EINVAL;
-       }
-
        /* rx and tx usecs has per queue value. If user doesn't specify the
         * queue, apply to all queues.
         */
        if (queue < 0) {
                for (i = 0; i < vsi->num_queue_pairs; i++)
                        i40e_set_itr_per_queue(vsi, ec, i);
-       } else if (queue < vsi->num_queue_pairs) {
-               i40e_set_itr_per_queue(vsi, ec, queue);
        } else {
-               netif_info(pf, drv, netdev, "Invalid queue value, queue range is 0 - %d\n",
-                          vsi->num_queue_pairs - 1);
-               return -EINVAL;
+               i40e_set_itr_per_queue(vsi, ec, queue);
        }
 
        return 0;
@@ -2564,6 +3333,144 @@ static int i40e_get_rss_hash_opts(struct i40e_pf *pf, struct ethtool_rxnfc *cmd)
        return 0;
 }
 
+/* i40e_check_mask - Check whether a mask field is set
+ * @mask: the full mask value
+ * @field; mask of the field to check
+ *
+ * If the given mask is fully set, return positive value. If the mask for the
+ * field is fully unset, return zero. Otherwise return a negative error code.
+ */
+static int i40e_check_mask(u64 mask, u64 field)
+{
+       u64 value = mask & field;
+
+       if (value == field)
+               return 1;
+       else if (!value)
+               return 0;
+       else
+               return -1;
+}
+
+/* i40e_parse_rx_flow_user_data - Deconstruct user-defined data
+ * @fsp: pointer to rx flow specification
+ * @data: pointer to userdef data structure for storage
+ *
+ * Read the user-defined data and deconstruct the value into a structure. No
+ * other code should read the user-defined data, so as to ensure that every
+ * place consistently reads the value correctly.
+ *
+ * The user-defined field is a 64bit Big Endian format value, which we
+ * deconstruct by reading bits or bit fields from it. Single bit flags shall
+ * be defined starting from the highest bits, while small bit field values
+ * shall be defined starting from the lowest bits.
+ *
+ * Returns 0 if the data is valid, and non-zero if the userdef data is invalid
+ * and the filter should be rejected. The data structure will always be
+ * modified even if FLOW_EXT is not set.
+
+ *
+ */
+static int i40e_parse_rx_flow_user_data(struct ethtool_rx_flow_spec *fsp,
+                                       struct i40e_rx_flow_userdef *data)
+{
+       u64 value, mask;
+       int valid;
+
+       /* Zero memory first so it's always consistent. */
+       memset(data, 0, sizeof(*data));
+
+       if (!(fsp->flow_type & FLOW_EXT))
+               return 0;
+
+       value = be64_to_cpu(*((__be64 *)fsp->h_ext.data));
+       mask = be64_to_cpu(*((__be64 *)fsp->m_ext.data));
+
+#define I40E_USERDEF_CLOUD_FILTER      BIT_ULL(63)
+#define I40E_USERDEF_TENANT_ID         GENMASK_ULL(23, 0)
+#define I40E_USERDEF_TUNNEL_TYPE       GENMASK_ULL(31, 24)
+
+#define I40E_USERDEF_FLEX_WORD         GENMASK_ULL(15, 0)
+#define I40E_USERDEF_FLEX_OFFSET       GENMASK_ULL(31, 16)
+#define I40E_USERDEF_FLEX_FILTER       GENMASK_ULL(31, 0)
+
+       if ((mask & I40E_USERDEF_CLOUD_FILTER) &&
+           (value & I40E_USERDEF_CLOUD_FILTER))
+               data->cloud_filter = true;
+
+       if (data->cloud_filter) {
+               /* These fields are only valid if this is a cloud filter */
+               valid = i40e_check_mask(mask, I40E_USERDEF_TENANT_ID);
+               if (valid < 0) {
+                       return -EINVAL;
+               } else if (valid) {
+                       data->tenant_id = value & I40E_USERDEF_TENANT_ID;
+                       data->tenant_id_valid = true;
+               }
+
+               valid = i40e_check_mask(mask, I40E_USERDEF_TUNNEL_TYPE);
+               if (valid < 0) {
+                       return -EINVAL;
+               } else if (valid) {
+                       data->tunnel_type =
+                               (value & I40E_USERDEF_TUNNEL_TYPE) >> 24;
+                       data->tunnel_type_valid = true;
+               }
+       } else {
+               /* These fields are only valid if this isn't a cloud filter */
+               valid = i40e_check_mask(mask, I40E_USERDEF_FLEX_FILTER);
+               if (valid < 0) {
+                       return -EINVAL;
+               } else if (valid) {
+                       data->flex_word = value & I40E_USERDEF_FLEX_WORD;
+                       data->flex_offset =
+                               (value & I40E_USERDEF_FLEX_OFFSET) >> 16;
+                       data->flex_filter = true;
+               }
+       }
+
+       return 0;
+}
+
+/* i40e_fill_rx_flow_user_data - Fill in user-defined data field
+ * @fsp: pointer to rx_flow specification
+ *
+ * Reads the userdef data structure and properly fills in the user defined
+ * fields of the rx_flow_spec.
+ */
+static void i40e_fill_rx_flow_user_data(struct ethtool_rx_flow_spec *fsp,
+                                       struct i40e_rx_flow_userdef *data)
+{
+       u64 value = 0, mask = 0;
+
+       if (data->cloud_filter) {
+               value |= I40E_USERDEF_CLOUD_FILTER;
+               mask |= I40E_USERDEF_CLOUD_FILTER;
+
+               if (data->tenant_id_valid) {
+                       value |= data->tenant_id;
+                       mask |= I40E_USERDEF_TENANT_ID;
+               }
+
+               if (data->tunnel_type_valid) {
+                       value |= (u64)data->tunnel_type << 24;
+                       mask |= I40E_USERDEF_TUNNEL_TYPE;
+               }
+       } else {
+               if (data->flex_filter) {
+                       value |= data->flex_word;
+                       value |= (u64)data->flex_offset << 16;
+                       mask |= I40E_USERDEF_FLEX_FILTER;
+               }
+       }
+
+       if (value || mask)
+               fsp->flow_type |= FLOW_EXT;
+
+       *((__be64 *)fsp->h_ext.data) = cpu_to_be64(value);
+       *((__be64 *)fsp->m_ext.data) = cpu_to_be64(mask);
+}
+
 /**
  * i40e_get_rx_filter_ids - Populates the rule count of a command
  * @pf: Pointer to the physical function struct
@@ -2626,8 +3533,11 @@ static int i40e_get_ethtool_fdir_entry(struct i40e_pf *pf,
 {
        struct ethtool_rx_flow_spec *fsp =
                        (struct ethtool_rx_flow_spec *)&cmd->fs;
+       struct i40e_rx_flow_userdef userdef = {0};
        struct i40e_fdir_filter *rule = NULL;
        struct hlist_node *node2;
+       u64 input_set;
+       u16 index;
 
        hlist_for_each_entry_safe(rule, node2,
                                  &pf->fdir_filter_list, fdir_node) {
@@ -2645,13 +3555,53 @@ static int i40e_get_ethtool_fdir_entry(struct i40e_pf *pf,
                fsp->m_u.usr_ip4_spec.proto = 0;
        }
 
-       /* Reverse the src and dest notion, since the HW views them from
-        * Tx perspective where as the user expects it from Rx filter view.
-        */
-       fsp->h_u.tcp_ip4_spec.psrc = rule->dst_port;
-       fsp->h_u.tcp_ip4_spec.pdst = rule->src_port;
-       fsp->h_u.tcp_ip4_spec.ip4src = rule->dst_ip[0];
-       fsp->h_u.tcp_ip4_spec.ip4dst = rule->src_ip[0];
+       /* Reverse the src and dest notion, since the HW views them from
+        * Tx perspective where as the user expects it from Rx filter view.
+        */
+       fsp->h_u.tcp_ip4_spec.psrc = rule->dst_port;
+       fsp->h_u.tcp_ip4_spec.pdst = rule->src_port;
+       fsp->h_u.tcp_ip4_spec.ip4src = rule->dst_ip;
+       fsp->h_u.tcp_ip4_spec.ip4dst = rule->src_ip;
+
+       switch (rule->flow_type) {
+       case SCTP_V4_FLOW:
+               index = I40E_FILTER_PCTYPE_NONF_IPV4_SCTP;
+               break;
+       case TCP_V4_FLOW:
+               index = I40E_FILTER_PCTYPE_NONF_IPV4_TCP;
+               break;
+       case UDP_V4_FLOW:
+               index = I40E_FILTER_PCTYPE_NONF_IPV4_UDP;
+               break;
+       case IP_USER_FLOW:
+               index = I40E_FILTER_PCTYPE_NONF_IPV4_OTHER;
+               break;
+       default:
+               /* If we have stored a filter with a flow type not listed here
+                * it is almost certainly a driver bug. WARN(), and then
+                * assign the input_set as if all fields are enabled to avoid
+                * reading unassigned memory.
+                */
+               WARN(1, "Missing input set index for flow_type %d\n",
+                    rule->flow_type);
+               input_set = 0xFFFFFFFFFFFFFFFFULL;
+               goto no_input_set;
+       }
+
+       input_set = i40e_read_fd_input_set(pf, index);
+
+no_input_set:
+       if (input_set & I40E_L3_SRC_MASK)
+               fsp->m_u.tcp_ip4_spec.ip4src = htonl(0xFFFF);
+
+       if (input_set & I40E_L3_DST_MASK)
+               fsp->m_u.tcp_ip4_spec.ip4dst = htonl(0xFFFF);
+
+       if (input_set & I40E_L4_SRC_MASK)
+               fsp->m_u.tcp_ip4_spec.psrc = htons(0xFFFFFFFF);
+
+       if (input_set & I40E_L4_DST_MASK)
+               fsp->m_u.tcp_ip4_spec.pdst = htons(0xFFFFFFFF);
 
        if (rule->dest_ctl == I40E_FILTER_PROGRAM_DESC_DEST_DROP_PACKET)
                fsp->ring_cookie = RX_CLS_FLOW_DISC;
@@ -2663,24 +3613,24 @@ static int i40e_get_ethtool_fdir_entry(struct i40e_pf *pf,
 
                vsi = i40e_find_vsi_from_id(pf, rule->dest_vsi);
                if (vsi && vsi->type == I40E_VSI_SRIOV) {
-                       fsp->h_ext.data[1] = cpu_to_be32(vsi->vf_id);
-                       fsp->m_ext.data[1] = cpu_to_be32(0x1);
+                       /* VFs are zero-indexed by the driver, but ethtool
+                        * expects them to be one-indexed, so add one here
+                        */
+                       u64 ring_vf = vsi->vf_id + 1;
+
+                       ring_vf <<= ETHTOOL_RX_FLOW_SPEC_RING_VF_OFF;
+                       fsp->ring_cookie |= ring_vf;
                }
        }
 
-       /* Present the value of user-def as part of get filters */
-       if (i40e_is_flex_filter(rule)) {
-               u32 flex_temp;
-
-               flex_temp = (be16_to_cpu(rule->flex_bytes[3]) << 16) |
-                            be16_to_cpu(rule->flex_bytes[2]);
-               fsp->h_ext.data[1] = cpu_to_be32(flex_temp);
-               flex_temp = (be16_to_cpu(rule->flex_mask[3]) << 16) |
-                            be16_to_cpu(rule->flex_mask[2]);
-               fsp->m_ext.data[1] = cpu_to_be32(flex_temp);
-               fsp->flow_type |= FLOW_EXT;
+       if (rule->flex_filter) {
+               userdef.flex_filter = true;
+               userdef.flex_word = be16_to_cpu(rule->flex_word);
+               userdef.flex_offset = rule->flex_offset;
        }
 
+       i40e_fill_rx_flow_user_data(fsp, &userdef);
+
        return 0;
 }
 
@@ -2701,9 +3651,8 @@ static int i40e_get_cloud_filter_entry(struct i40e_pf *pf,
                        (struct ethtool_rx_flow_spec *)&cmd->fs;
        static const u8 mac_broadcast[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
        struct i40e_cloud_filter *rule, *filter = NULL;
+       struct i40e_rx_flow_userdef userdef = {0};
        struct hlist_node *node2;
-       __be32 tena;
-       int i;
 
        hlist_for_each_entry_safe(rule, node2,
                                  &pf->cloud_filter_list, cloud_node) {
@@ -2722,35 +3671,41 @@ static int i40e_get_cloud_filter_entry(struct i40e_pf *pf,
                return -ENOENT;
        }
 
-       /* check for VF as a cloud filter target */
-       for (i = 0; i < pf->num_alloc_vsi; i++) {
-               if (!pf->vsi[i] || pf->vsi[i]->seid != filter->seid)
-                       continue;
+       userdef.cloud_filter = true;
 
-               if (pf->vsi[i]->type == I40E_VSI_SRIOV)
-                       fsp->h_ext.data[1] = cpu_to_be32(pf->vsi[i]->vf_id);
-               else if (pf->vsi[i]->type == I40E_VSI_MAIN)
-                       fsp->h_ext.data[1] = cpu_to_be32(0xffff);
-               break;
+       fsp->ring_cookie = filter->queue_id;
+       if (filter->seid != pf->vsi[pf->lan_vsi]->seid) {
+               struct i40e_vsi *vsi;
+
+               vsi = i40e_find_vsi_from_seid(pf, filter->seid);
+               if (vsi && vsi->type == I40E_VSI_SRIOV) {
+                       /* VFs are zero-indexed by the driver, but ethtool
+                        * expects them to be one-indexed, so add one here
+                        */
+                       u64 ring_vf = vsi->vf_id + 1;
+
+                       ring_vf <<= ETHTOOL_RX_FLOW_SPEC_RING_VF_OFF;
+                       fsp->ring_cookie |= ring_vf;
+               }
        }
 
        ether_addr_copy(fsp->h_u.ether_spec.h_dest, filter->outer_mac);
        ether_addr_copy(fsp->h_u.ether_spec.h_source, filter->inner_mac);
 
-       tena = cpu_to_be32(filter->tenant_id);
-       memcpy(&fsp->h_ext.data[0], &tena, sizeof(tena));
-
-       fsp->ring_cookie = filter->queue_id;
        if (filter->flags & I40E_CLOUD_FIELD_OMAC)
                ether_addr_copy(fsp->m_u.ether_spec.h_dest, mac_broadcast);
        if (filter->flags & I40E_CLOUD_FIELD_IMAC)
                ether_addr_copy(fsp->m_u.ether_spec.h_source, mac_broadcast);
        if (filter->flags & I40E_CLOUD_FIELD_IVLAN)
                fsp->h_ext.vlan_tci = filter->inner_vlan;
-       if (filter->flags & I40E_CLOUD_FIELD_TEN_ID)
-               *(__be32 *)&fsp->h_ext.data[0] = cpu_to_be32(filter->tenant_id);
-       else
-               *(__be32 *)&fsp->h_ext.data[0] = cpu_to_be32(~0);
+       if (filter->flags & I40E_CLOUD_FIELD_TEN_ID) {
+               userdef.tenant_id_valid = true;
+               userdef.tenant_id = filter->tenant_id;
+       }
+       if (filter->tunnel_type != I40E_CLOUD_TNL_TYPE_NONE) {
+               userdef.tunnel_type_valid = true;
+               userdef.tunnel_type = filter->tunnel_type;
+       }
 
        if (filter->flags & I40E_CLOUD_FIELD_IIP) {
                fsp->flow_type = IP_USER_FLOW;
@@ -2760,6 +3715,8 @@ static int i40e_get_cloud_filter_entry(struct i40e_pf *pf,
                fsp->flow_type = ETHER_FLOW;
        }
 
+       i40e_fill_rx_flow_user_data(fsp, &userdef);
+
        fsp->flow_type |= FLOW_EXT;
 
        return 0;
@@ -2895,22 +3852,22 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc)
        switch (nfc->flow_type) {
        case TCP_V4_FLOW:
                flow_pctype = I40E_FILTER_PCTYPE_NONF_IPV4_TCP;
-               if (pf->flags & I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE)
+               if (pf->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE)
                        hena |=
                          BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK);
                break;
        case TCP_V6_FLOW:
                flow_pctype = I40E_FILTER_PCTYPE_NONF_IPV6_TCP;
-               if (pf->flags & I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE)
+               if (pf->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE)
                        hena |=
                          BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK);
-               if (pf->flags & I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE)
+               if (pf->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE)
                        hena |=
                          BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK);
                break;
        case UDP_V4_FLOW:
                flow_pctype = I40E_FILTER_PCTYPE_NONF_IPV4_UDP;
-               if (pf->flags & I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE)
+               if (pf->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE)
                        hena |=
                          BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) |
                          BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP);
@@ -2919,7 +3876,7 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc)
                break;
        case UDP_V6_FLOW:
                flow_pctype = I40E_FILTER_PCTYPE_NONF_IPV6_UDP;
-               if (pf->flags & I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE)
+               if (pf->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE)
                        hena |=
                          BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) |
                          BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP);
@@ -2977,163 +3934,306 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc)
 }
 
 /**
- * i40e_handle_flex_filter_del - Update FD_INSET upon deletion of flex filter
- * @vsi: Pointer to the targeted VSI
- * @flow_type: Type of flow
- * @flex_mask_bit: Bit index used in INSET register
+ * i40e_cloud_filter_mask2flags- Convert cloud filter details to filter type
+ * @pf: pointer to the physical function struct
+ * @fsp: RX flow classification rules
+ * @flags: Resultant combination of all the fields to decide the tuple
+ *
+ * The general trick in setting these flags is that if the mask field for
+ * a value is non-zero, then the field itself was set to something, so we
+ * use this to tell us what has been selected.
  *
- * This function updates FD_INSET for flex filter if filter (using flex bytes)
- * count (based on flow_type) reaches zero.
+ * Returns 0 if a valid filter type was identified.
  **/
-static void i40e_handle_flex_filter_del(struct i40e_vsi *vsi,
-                                       u8 flow_type,
-                                       u64 flex_mask_bit)
+static int i40e_cloud_filter_mask2flags(struct i40e_pf *pf,
+                                       struct ethtool_rx_flow_spec *fsp,
+                                       struct i40e_rx_flow_userdef *userdef,
+                                       u8 *flags)
 {
-       u8 idx;
-       u64 val = 0;
-       u64 *input_set = NULL;
-       int flex_filter_cnt = 0;
-       u32 fsize = 0, src = 0;
-       struct hlist_node *node2;
-       struct i40e_fdir_filter *rule;
-       struct i40e_pf *pf = vsi->back;
-       bool clean_flex_pit = false;
-       bool update_flex_pit6 = false;
-       bool update_flex_pit7 = false;
-       u32 flex_pit6 = 0, flex_pit7 = 0;
-       u8 pit_idx = I40E_FLEX_PIT_IDX_START_L4;
-       u64 dest_word_l4, dest_word6, dest_word7;
-
-       switch (flow_type & ~FLOW_EXT) {
-       case TCP_V4_FLOW:
-               idx = I40E_FILTER_PCTYPE_NONF_IPV4_TCP;
-               input_set = &pf->fd_tcp4_input_set;
-               break;
+       u8 i = 0;
 
-       case UDP_V4_FLOW:
-               idx = I40E_FILTER_PCTYPE_NONF_IPV4_UDP;
-               input_set = &pf->fd_udp4_input_set;
+       *flags = 0;
+
+       switch (fsp->flow_type & ~FLOW_EXT) {
+       case ETHER_FLOW:
+               /* use is_broadcast and is_zero to check for all 0xf or 0 */
+               if (is_broadcast_ether_addr(fsp->m_u.ether_spec.h_dest)) {
+                       i |= I40E_CLOUD_FIELD_OMAC;
+               } else if (is_zero_ether_addr(fsp->m_u.ether_spec.h_dest)) {
+                       i &= ~I40E_CLOUD_FIELD_OMAC;
+               } else {
+                       dev_info(&pf->pdev->dev, "Bad ether dest mask %pM\n",
+                                fsp->m_u.ether_spec.h_dest);
+                       return I40E_ERR_CONFIG;
+               }
+
+               if (is_broadcast_ether_addr(fsp->m_u.ether_spec.h_source)) {
+                       i |= I40E_CLOUD_FIELD_IMAC;
+               } else if (is_zero_ether_addr(fsp->m_u.ether_spec.h_source)) {
+                       i &= ~I40E_CLOUD_FIELD_IMAC;
+               } else {
+                       dev_info(&pf->pdev->dev, "Bad ether source mask %pM\n",
+                                fsp->m_u.ether_spec.h_source);
+                       return I40E_ERR_CONFIG;
+               }
                break;
 
        case IP_USER_FLOW:
-               idx = I40E_FILTER_PCTYPE_NONF_IPV4_OTHER;
-               input_set = &pf->fd_ip4_input_set;
-               pit_idx = I40E_FLEX_PIT_IDX_START_L3;
-               clean_flex_pit = true;
+               if (fsp->m_u.usr_ip4_spec.ip4dst == cpu_to_be32(0xffffffff)) {
+                       i |= I40E_CLOUD_FIELD_IIP;
+               } else if (!fsp->m_u.usr_ip4_spec.ip4dst) {
+                       i &= ~I40E_CLOUD_FIELD_IIP;
+               } else {
+                       dev_info(&pf->pdev->dev, "Bad ip dst mask 0x%08x\n",
+                                be32_to_cpu(fsp->m_u.usr_ip4_spec.ip4dst));
+                       return I40E_ERR_CONFIG;
+               }
                break;
 
        default:
-               return;
+               return I40E_ERR_CONFIG;
+       }
+
+       switch (be16_to_cpu(fsp->m_ext.vlan_tci)) {
+       case 0xffff:
+               if (fsp->h_ext.vlan_tci & cpu_to_be16(~0x7fff)) {
+                       dev_info(&pf->pdev->dev, "Bad vlan %u\n",
+                                be16_to_cpu(fsp->h_ext.vlan_tci));
+                       return I40E_ERR_CONFIG;
+               }
+               i |= I40E_CLOUD_FIELD_IVLAN;
+               break;
+       case 0:
+               i &= ~I40E_CLOUD_FIELD_IVLAN;
+               break;
+       default:
+               dev_info(&pf->pdev->dev, "Bad vlan mask %u\n",
+                        be16_to_cpu(fsp->m_ext.vlan_tci));
+               return I40E_ERR_CONFIG;
        }
 
-       /* To support TCP/UDP flow simultaneously, update either all
-        * relevant register or only needed.
+       /* We already know that we're a cloud filter, so we don't need to
+        * re-check that.
         */
-       if (pit_idx == I40E_FLEX_PIT_IDX_START_L4) {
-               flex_pit6 = i40e_read_rx_ctl(&pf->hw,
-                                            I40E_PRTQF_FLX_PIT(pit_idx));
-               flex_pit7 = i40e_read_rx_ctl(&pf->hw,
-                                            I40E_PRTQF_FLX_PIT(pit_idx + 1));
-               if ((!flex_pit6) || (!flex_pit7))
-                       return;
+       if (userdef->tenant_id_valid) {
+               if (userdef->tenant_id == 0)
+                       i &= ~I40E_CLOUD_FIELD_TEN_ID;
+               else
+                       i |= I40E_CLOUD_FIELD_TEN_ID;
+       }
 
-               dest_word7 = I40E_FLEX_PIT_GET_DST(flex_pit7);
-               dest_word6 = I40E_FLEX_PIT_GET_DST(flex_pit6);
-               /* If dest_word7 or dest_word6 is UNUSED, it is safe to clear
-                * all relevant register
-                */
-               if ((dest_word6 == I40E_FLEX_DEST_UNUSED) ||
-                   (dest_word7 == I40E_FLEX_DEST_UNUSED)) {
-                       clean_flex_pit = true;
-               } else {
-                       /* Which dest word is used based on 'flex_mask_bit' */
-                       dest_word_l4 = I40E_FLEX_DEST_L4;
-                       if (flex_mask_bit & I40E_FLEX_51_MASK)
-                               dest_word_l4++;
-                        /* Otherwise figure out which register needs update */
-                       if (dest_word6 == dest_word_l4)
-                               update_flex_pit6 = true;
-                       else if (dest_word7 == dest_word_l4)
-                               update_flex_pit7 = true;
-               }
+       *flags = i;
+       return I40E_SUCCESS;
+}
+
+/* i40e_add_cloud_filter_ethtool needs i40e_del_fdir_ethtool() */
+static int i40e_del_fdir_entry(struct i40e_vsi *vsi,
+                              struct ethtool_rxnfc *cmd);
+
+/**
+ * i40e_add_cloud_filter_ethtool - Add cloud filter
+ * @pf: pointer to the physical function struct
+ * @cmd: The command to get or set Rx flow classification rules
+ *
+ * Add cloud filter for a specific flow spec.
+ * Returns 0 if the filter were successfully added.
+ **/
+static int i40e_add_cloud_filter_ethtool(struct i40e_vsi *vsi,
+                                        struct ethtool_rxnfc *cmd,
+                                        struct i40e_rx_flow_userdef *userdef)
+{
+       struct i40e_cloud_filter *rule, *parent, *filter = NULL;
+       struct ethtool_rx_flow_spec *fsp;
+       u16 dest_seid = 0, q_index = 0;
+       struct i40e_pf *pf = vsi->back;
+       struct hlist_node *node2;
+       u32 ring, vf;
+       u8 flags = 0;
+       int ret;
+
+       if (!(pf->flags & I40E_FLAG_FD_SB_ENABLED))
+               return -EOPNOTSUPP;
+
+       if (pf->flags & I40E_FLAG_MFP_ENABLED)
+               return -EOPNOTSUPP;
+
+       if (test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state) ||
+           test_bit(__I40E_RESET_INTR_RECEIVED, pf->state))
+               return -EBUSY;
+
+       fsp = (struct ethtool_rx_flow_spec *)&cmd->fs;
+
+       /* The ring_cookie is a mask of queue index and VF id we wish to
+        * target. This is the same for regular flow director filters.
+        */
+       if (fsp->ring_cookie == RX_CLS_FLOW_DISC) {
+               dev_warn(&pf->pdev->dev, "Cloud filters do not support the drop action.\n");
+               return -EOPNOTSUPP;
+       }
+
+       ring = ethtool_get_flow_spec_ring(fsp->ring_cookie);
+       vf = ethtool_get_flow_spec_ring_vf(fsp->ring_cookie);
+
+       if (!vf) {
+               if (ring >= vsi->num_queue_pairs)
+                       return -EINVAL;
+               dest_seid = vsi->id;
+       } else {
+               /* VFs are zero-indexed, so we subtract one here */
+               vf--;
+
+               if (vf >= pf->num_alloc_vfs)
+                       return -EINVAL;
+               if (ring >= pf->vf[vf].num_queue_pairs)
+                       return -EINVAL;
+               dest_seid = pf->vsi[pf->vf[vf].lan_vsi_idx]->seid;
+       }
+       q_index = ring;
+
+       ret = i40e_cloud_filter_mask2flags(pf, fsp, userdef, &flags);
+       if (ret || !flags) {
+               dev_info(&pf->pdev->dev, "Invalid mask config, flags = %d\n",
+                        flags);
+               return -EINVAL;
        }
 
+       /* if filter exists with same id, delete the old one */
+       parent = NULL;
        hlist_for_each_entry_safe(rule, node2,
-                                 &pf->fdir_filter_list, fdir_node) {
-               if (i40e_is_flex_filter(rule) && (rule->flow_type == flow_type))
-                       flex_filter_cnt++;
+                                 &pf->cloud_filter_list, cloud_node) {
+               /* filter exists with the id */
+               if (rule->id == fsp->location)
+                       filter = rule;
+
+               /* bail out if we've passed the likely location in the list */
+               if (rule->id >= fsp->location)
+                       break;
+
+               /* track where we left off */
+               parent = rule;
+       }
+       if (filter && (filter->id == fsp->location)) {
+               /* found it in the cloud list, so remove it */
+               ret = i40e_add_del_cloud_filter(pf, filter, false);
+               if (ret && (pf->hw.aq.asq_last_status != I40E_AQ_RC_ENOENT)) {
+                       dev_info(&pf->pdev->dev,
+                                "fail to delete old cloud filter, err %s, aq_err %s\n",
+                                i40e_stat_str(&pf->hw, ret),
+                                i40e_aq_str(&pf->hw,
+                                            pf->hw.aq.asq_last_status));
+                       return i40e_aq_rc_to_posix(ret,
+                                                  pf->hw.aq.asq_last_status);
+               }
+               hlist_del(&filter->cloud_node);
+               kfree(filter);
+               pf->num_cloud_filters--;
+       } else {
+               /* not in the cloud list, so check the PF's fdir list */
+               (void)i40e_del_fdir_entry(pf->vsi[pf->lan_vsi], cmd);
        }
 
-       /* Do not update value of input set register if flow based flex filter
-        * (flow director filter which utilize bytes from payload as part of
-        * input set) count is non-zero
-        */
-       if (flex_filter_cnt)
-               return;
+       filter = kzalloc(sizeof(*filter), GFP_KERNEL);
+       if (!filter)
+               return -ENOMEM;
 
-       /* Read flow specific input set register */
-       val = i40e_read_fd_input_set(pf, idx);
-       if (!(val & flex_mask_bit))
-               return;
+       switch (fsp->flow_type & ~FLOW_EXT) {
+       case ETHER_FLOW:
+               ether_addr_copy(filter->outer_mac,
+                               fsp->h_u.ether_spec.h_dest);
+               ether_addr_copy(filter->inner_mac,
+                               fsp->h_u.ether_spec.h_source);
+               break;
+
+       case IP_USER_FLOW:
+               if (flags & I40E_CLOUD_FIELD_TEN_ID) {
+                       dev_info(&pf->pdev->dev, "Tenant id not allowed for ip filter\n");
+                       kfree(filter);
+                       return I40E_ERR_CONFIG;
+               }
+               filter->inner_ip[0] = fsp->h_u.usr_ip4_spec.ip4dst;
+               break;
+
+       default:
+               dev_info(&pf->pdev->dev, "unknown flow type 0x%x\n",
+                        (fsp->flow_type & ~FLOW_EXT));
+               kfree(filter);
+               return I40E_ERR_CONFIG;
+       }
+
+       if (userdef->tenant_id_valid)
+               filter->tenant_id = userdef->tenant_id;
+       else
+               filter->tenant_id = 0;
+       if (userdef->tunnel_type_valid)
+               filter->tunnel_type = userdef->tunnel_type;
+       else
+               filter->tunnel_type = I40E_CLOUD_TNL_TYPE_NONE;
+
+       filter->id = fsp->location;
+       filter->seid = dest_seid;
+       filter->queue_id = q_index;
+       filter->flags = flags;
+       filter->inner_vlan = fsp->h_ext.vlan_tci;
+
+       ret = i40e_add_del_cloud_filter(pf, filter, true);
+       if (ret) {
+               kfree(filter);
+               dev_info(&pf->pdev->dev,
+                        "fail to add cloud filter, err %s aq_err %s\n",
+                        i40e_stat_str(&pf->hw, ret),
+                        i40e_aq_str(&pf->hw,
+                                    pf->hw.aq.asq_last_status));
+               return i40e_aq_rc_to_posix(ret, pf->hw.aq.asq_last_status);
+       }
+
+       /* add filter to the ordered list */
+       INIT_HLIST_NODE(&filter->cloud_node);
+       if (parent)
+               hlist_add_behind(&filter->cloud_node, &parent->cloud_node);
+       else
+               hlist_add_head(&filter->cloud_node, &pf->cloud_filter_list);
+       pf->num_cloud_filters++;
 
-       /* Update bit mask as needed */
-       val &= ~flex_mask_bit;
+       return 0;
+}
 
-       /* Write flow specific input set register */
-       i40e_write_fd_input_set(pf, idx, val);
+/**
+ * i40e_del_cloud_filter_ethtool - del vxlan filter
+ * @pf: pointer to the physical function struct
+ * @cmd: RX flow classification rules
+ *
+ * Delete vxlan filter for a specific flow spec.
+ * Returns 0 if the filter was successfully deleted.
+ **/
+static int i40e_del_cloud_filter_ethtool(struct i40e_pf *pf,
+                                        struct ethtool_rxnfc *cmd)
+{
+       struct i40e_cloud_filter *rule, *filter = NULL;
+       struct ethtool_rx_flow_spec *fsp;
+       struct hlist_node *node2;
 
-       /* Update values of FLX_PIT registers */
-       if (clean_flex_pit) {
-               for (idx = pit_idx; idx < (pit_idx + 3); idx++)
-                       i40e_write_rx_ctl(&pf->hw, I40E_PRTQF_FLX_PIT(idx), 0);
+       fsp = (struct ethtool_rx_flow_spec *)&cmd->fs;
+       hlist_for_each_entry_safe(rule, node2,
+                                 &pf->cloud_filter_list, cloud_node) {
+               /* filter found */
+               if (rule->id == fsp->location)
+                       filter = rule;
 
-               /* Time to reset value of input set based on flow-type */
-               if (!*input_set) {
-                       i40e_write_fd_input_set(pf, idx, *input_set);
-                       *input_set = 0;
-               }
-       } else if (update_flex_pit6) {
-               fsize = I40E_FLEX_PIT_GET_FSIZE(flex_pit6);
-               src = I40E_FLEX_PIT_GET_SRC(flex_pit6);
-       } else if (update_flex_pit7) {
-               fsize = I40E_FLEX_PIT_GET_FSIZE(flex_pit7);
-               src = I40E_FLEX_PIT_GET_SRC(flex_pit7);
-               pit_idx++;
+               /* bail out if we've passed the likely location in the list */
+               if (rule->id >= fsp->location)
+                       break;
        }
+       if (!filter)
+               return -ENOENT;
 
-       if (fsize)
-               i40e_write_rx_ctl(&pf->hw, I40E_PRTQF_FLX_PIT(pit_idx),
-                                 I40E_FLEX_PREP_VAL(I40E_FLEX_DEST_UNUSED,
-                                                    fsize, src));
-}
+       /* remove filter from the list even if failed to remove from device */
+       (void)i40e_add_del_cloud_filter(pf, filter, false);
+       hlist_del(&filter->cloud_node);
+       kfree(filter);
+       pf->num_cloud_filters--;
 
-/**
- * i40e_match_fdir_input_set - Match a new filter against an existing one
- * @rule: The filter already added
- * @input: The new filter to comapre against
- *
- * Returns true if the two input set match
- **/
-static bool i40e_match_fdir_input_set(struct i40e_fdir_filter *rule,
-                                     struct i40e_fdir_filter *input)
-{
-       if ((rule->dst_ip[0] != input->dst_ip[0]) ||
-           (rule->src_ip[0] != input->src_ip[0]) ||
-           (rule->dst_port != input->dst_port) ||
-           (rule->src_port != input->src_port) ||
-           (rule->flow_type != input->flow_type) ||
-           (rule->ip4_proto != input->ip4_proto) ||
-           (rule->sctp_v_tag != input->sctp_v_tag))
-               return false;
-
-       /* handle flex_filter, decide based upon pattern equality */
-       if (i40e_is_flex_filter(rule) &&
-           (rule->flex_bytes[3] != input->flex_bytes[3]))
-               return false;
-
-       return true;
+       return 0;
 }
-
 /**
  * i40e_update_ethtool_fdir_entry - Updates the fdir filter entry
  * @vsi: Pointer to the targeted VSI
@@ -3167,32 +4267,23 @@ static int i40e_update_ethtool_fdir_entry(struct i40e_vsi *vsi,
 
        /* is there is an old rule occupying our target filter slot? */
        if (rule && (rule->fd_id == sw_idx)) {
-
-               /* if this is an identical rule, don't change anything */
-               if (input && i40e_match_fdir_input_set(rule, input))
-                       return 0;
-
-               /* remove the list entry because we're either deleting
-                * the old rule or we're replacing it with a new rule
+               /* Remove this rule, since we're either deleting it, or
+                * replacing it.
                 */
                err = i40e_add_del_fdir(vsi, rule, false);
                hlist_del(&rule->fdir_node);
                pf->fdir_pf_active_filters--;
 
-               /* Was it flex filter and deemed for deletion */
-               if (i40e_is_flex_filter(rule) && (!input))
-                       i40e_handle_flex_filter_del(vsi, rule->flow_type,
-                                                   rule->flex_mask_bit);
                kfree(rule);
        }
 
-       /* If no input this was a delete, err should be 0 if a rule was
-        * successfully found and removed from the list else -ENOENT
+       /* If we weren't given an input, this is a delete, so just return the
+        * error code indicating if there was an entry at the requested slot.
         */
        if (!input)
                return err;
 
-       /* initialize node and set software index */
+       /* Otherwise, install the new rule as requested */
        INIT_HLIST_NODE(&input->fdir_node);
 
        /* add filter to the ordered list */
@@ -3207,6 +4298,68 @@ static int i40e_update_ethtool_fdir_entry(struct i40e_vsi *vsi,
        return 0;
 }
 
+/** i40e_prune_flex_pit_list - Cleanup unused entries in FLX_PIT table
+ * @pf: pointer to PF structure
+ *
+ * This function searches the list of filters and determines which FLX_PIT
+ * entries are still required. It will prune any entries which are no longer
+ * in use after the deletion.
+ */
+static void i40e_prune_flex_pit_list(struct i40e_pf *pf)
+{
+       struct i40e_flex_pit *entry, *tmp;
+       struct i40e_fdir_filter *rule;
+
+       /* First, we'll check the l3 table */
+       list_for_each_entry_safe(entry, tmp, &pf->l3_flex_pit_list, list) {
+               bool found = false;
+
+               hlist_for_each_entry(rule, &pf->fdir_filter_list, fdir_node) {
+                       if (rule->flow_type != IP_USER_FLOW)
+                               continue;
+                       if (rule->flex_filter &&
+                           rule->flex_offset == entry->src_offset) {
+                               found = true;
+                               break;
+                       }
+               }
+
+               /* If we didn't find the filter, then we can prune this entry
+                * from the list.
+                */
+               if (!found) {
+                       list_del(&entry->list);
+                       kfree(entry);
+               }
+       }
+
+       /* Followed by the L4 table */
+       list_for_each_entry_safe(entry, tmp, &pf->l4_flex_pit_list, list) {
+               bool found = false;
+
+               hlist_for_each_entry(rule, &pf->fdir_filter_list, fdir_node) {
+                       /* Skip this filter if it's L3, since we already
+                        * checked those in the above loop
+                        */
+                       if (rule->flow_type == IP_USER_FLOW)
+                               continue;
+                       if (rule->flex_filter &&
+                           rule->flex_offset == entry->src_offset) {
+                               found = true;
+                               break;
+                       }
+               }
+
+               /* If we didn't find the filter, then we can prune this entry
+                * from the list.
+                */
+               if (!found) {
+                       list_del(&entry->list);
+                       kfree(entry);
+               }
+       }
+}
+
 /**
  * i40e_del_fdir_entry - Deletes a Flow Director filter entry
  * @vsi: Pointer to the targeted VSI
@@ -3225,921 +4378,823 @@ static int i40e_del_fdir_entry(struct i40e_vsi *vsi,
        struct i40e_pf *pf = vsi->back;
        int ret = 0;
 
-       if (test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state) ||
-           test_bit(__I40E_RESET_INTR_RECEIVED, &pf->state))
+       if (test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state) ||
+           test_bit(__I40E_RESET_INTR_RECEIVED, pf->state))
                return -EBUSY;
 
-       if (test_bit(__I40E_FD_FLUSH_REQUESTED, &pf->state))
+       if (test_bit(__I40E_FD_FLUSH_REQUESTED, pf->state))
                return -EBUSY;
 
        ret = i40e_update_ethtool_fdir_entry(vsi, NULL, fsp->location);
 
+       i40e_prune_flex_pit_list(pf);
+
        i40e_fdir_check_and_reenable(pf);
        return ret;
 }
 
-/**
- * i40e_program_flex_filter - Program flex filter
- *
- * @vsi: pointer to the targeted VSI
- * @flex_pit: value prepared to be written into flex PIT register
- * @flex_pit6: flex pit[6] register value
- * @offset_in_words: offset in packet (unit word)
- * @src_word_off: user specified offset in words
- * @dest_word: word location to be used in field vector
- * @pit_idx: PIT register index
- * @ort_idx: ORT register index
- * @ort_val: value to be written in ORT register
+/* i40e_unused_pit_index - Find an unused PIT index for given list
+ * @pf: the PF data structure
  *
- * This function programs relevant FLX_PIT registers, shuffles/updates the
- * value as needed to support simultaneous flows (such as TCP4/UDP4/IP4).
- **/
-static int i40e_program_flex_filter(struct i40e_vsi *vsi, u32 flex_pit,
-                                   u32 flex_pit6, u32 offset_in_words,
-                                   u32 src_word_off, u32 dest_word,
-                                   u32 pit_idx, u32 ort_idx, u32 ort_val)
+ * Find the first unused flexible PIT index entry. We search both the L3 and
+ * L4 flexible PIT lists so that the returned index is unique and unused by
+ * either currently programmed L3 or L4 filters. We use a bit field as storage
+ * to track which indexes are already used.
+ */
+static u8 i40e_unused_pit_index(struct i40e_pf *pf)
 {
-       struct i40e_pf *pf;
-       u32 curr_src_off = 0, curr_fsize = 0, fsize = 0;
-
-       pf = vsi->back;
-
-       /* Program starting FLX_PIT register */
-       if (!flex_pit6) {
-               i40e_write_rx_ctl(&pf->hw,
-                                 I40E_PRTQF_FLX_PIT(pit_idx), flex_pit);
-       } else {
-               /* This is needed to support simultaneous flex filter for flow
-                * types TCP4 and UDP4.
-                * Program FLX_PIT[6] and FLX_PIT[7] correctly, if needed
-                * program the value read from FLX_PIT6 into register FLX_PIT7,
-                * adjust value for FLX_PIT6 if required.
-                */
-               curr_src_off = I40E_FLEX_PIT_GET_SRC(flex_pit6);
-               curr_fsize = I40E_FLEX_PIT_GET_FSIZE(flex_pit6);
-
-               if (offset_in_words == curr_src_off) {
-                       netif_err(pf, drv, vsi->netdev,
-                                 "Filter exist whose offset w.r.t it's payload matches with the filter being added. This breaks device programming rules, hence unsupported\n");
-                       return -EINVAL;
-               } else if (offset_in_words < curr_src_off) {
-                       /* Program value of FLX_PIT6 into
-                        * FLX_PIT7 and reprogram PIT6 with
-                        * modified value and program PIT8
-                        * as per rule
-                        */
-
-                       /* Adjust FSIZE of FLX_PIT[6]*/
-                       fsize = curr_src_off - offset_in_words;
-
-                       /* Program FLX_PIT[6] */
-                       i40e_write_rx_ctl(&pf->hw, I40E_PRTQF_FLX_PIT(pit_idx),
-                                         I40E_FLEX_PREP_VAL(dest_word,
-                                                            fsize,
-                                                            src_word_off));
-                       /* Save value of FLX_PIT6, to be written into
-                        * FLX_PIT[7]
-                        */
-                       flex_pit = flex_pit6;
-
-                       /* Make sure src_word_off is correct for last
-                        * FLX_PIT register in this case
-                        */
-                       offset_in_words = curr_src_off + curr_fsize;
-               } else {
-                       /* Make sure src_word_off is correct for last
-                        * FLX_PIT register in this case
-                        */
-                       offset_in_words = offset_in_words +
-                                         I40E_FLEX_PIT_GET_FSIZE(flex_pit);
-               }
+       unsigned long available_index = 0xFF;
+       struct i40e_flex_pit *entry;
 
-               /* Program FLX_PIT[7] */
-               pit_idx++;
-               i40e_write_rx_ctl(&pf->hw, I40E_PRTQF_FLX_PIT(pit_idx),
-                                 flex_pit);
-               goto program_last_flx_pit;
-       }
-
-       /* Propgram FLX_PIT register:
-        * FLX_PIT[3] for L3 flow and FLX_PIT[7] for L4 flow
+       /* We need to make sure that the new index isn't in use by either L3
+        * or L4 filters so that IP_USER_FLOW filters can program both L3 and
+        * L4 to use the same index.
         */
-       pit_idx++;
-       offset_in_words++;
-       i40e_write_rx_ctl(&pf->hw, I40E_PRTQF_FLX_PIT(pit_idx),
-                         I40E_FLEX_PREP_VAL(I40E_FLEX_DEST_UNUSED,
-                                            1, offset_in_words));
-       /* Update before label because in other case, where jump
-        * is taken, values are updated correctly
-        */
-       offset_in_words++;
-
-program_last_flx_pit:
-       /* FLX_PIT[8] in case of L4 flow or FLX_PIT[3] in case of L3 flow */
-       pit_idx++;
-       i40e_write_rx_ctl(&pf->hw, I40E_PRTQF_FLX_PIT(pit_idx),
-                         I40E_FLEX_PREP_VAL(I40E_FLEX_DEST_UNUSED,
-                                            1, offset_in_words));
-       i40e_write_rx_ctl(&pf->hw, I40E_GLQF_ORT(ort_idx), ort_val);
-
-       return 0;
-}
-
-/**
- * i40e_validate_flex_filter_params - Validate flex filter params (user-def)
- * @vsi: pointer to the targeted VSI
- * @input: pointer to filter
- * @offset: offset in packet
- * @header_len: Header len based on flow-type
- * @mask: inset mask for flex filter
- * @flow_based_cnt: flex filter count based on flow-type
- * @word_offset_in_payload: offset in unit words w.r.t payload
- *
- * This function validates 'offset' (mask) to make sure it satisfies device
- * programming rule.
- **/
-static int i40e_validate_flex_filter_params(struct i40e_vsi *vsi,
-                                           struct i40e_fdir_filter *input,
-                                           u16 offset, u16 header_len,
-                                           u64 *mask, u16 *flow_based_cnt,
-                                           u32 word_offset_in_payload)
-{
-       struct i40e_pf *pf;
-       struct hlist_node *node2;
-       struct i40e_fdir_filter *rule;
-       u16 existing_mask, specified_mask;
 
-       pf = vsi->back;
-
-       /* 'offset' needs to be within 0...480 bytes */
-       if (offset >= I40E_MAX_PARSE_BYTE) {
-               netif_err(pf, drv, vsi->netdev, "Max valid offset in unit word is %u, user passed %u\n",
-                         I40E_MAX_PARSE_BYTE, offset);
-               return -EINVAL;
-       }
-
-       /* 'offset' shall not be somewhere within header (L2/L3/L4) */
-       if (offset < header_len) {
-               netif_err(pf, drv, vsi->netdev, "Specified offset (%u) is referring to bytes in headers (bytes 0-%u), it should be somewhere in payload.\n",
-                         offset, header_len);
-               return -EINVAL;
-       }
-
-       /* Check for word boundary */
-       if (offset & 0x1) {
-               netif_err(pf, drv, vsi->netdev, "User specified mask address %u rounded down to word boundary %lu\n",
-                         offset, sizeof(u16));
-               return -EINVAL;
-       }
-
-       if (word_offset_in_payload >= I40E_MAX_SRC_WORD_OFFSET) {
-               netif_err(pf, drv, vsi->netdev, "Max. allowed bytes in payload are %u, but user specified offset %u\n",
-                         (I40E_MAX_SRC_WORD_OFFSET << 1),
-                         word_offset_in_payload);
-               return -EINVAL;
-       }
+       list_for_each_entry(entry, &pf->l4_flex_pit_list, list)
+               clear_bit(entry->pit_index, &available_index);
 
-       /* Does filter with flex byte for given flow-type exist and if offset
-        * (aka flex mask) of that existing filter is different, it is
-        * considered change in input set mask.
-        * Since we are allowing only one mask (aka offset) for each flow type,
-        * flag an error and fail the call.
-        */
-       hlist_for_each_entry_safe(rule, node2,
-                                 &pf->fdir_filter_list, fdir_node) {
-               if (!i40e_is_flex_filter(rule))
-                       continue;
-               existing_mask = ~(be16_to_cpu(rule->flex_mask[3]));
-               specified_mask = ~(be16_to_cpu(input->flex_mask[3]));
-               if (rule->flow_type == input->flow_type) {
-                       if (existing_mask != specified_mask) {
-                               /* This is like change in INPUT set mask
-                                * (aka 'offset') when used flex payload for
-                                * a given flow-type.
-                                */
-                               netif_err(pf, drv, vsi->netdev,
-                                         "Previous flex filter(ID: %u) exists for flow-type %u whose flex mask (aka 'offset'): %u is different from current mask :%u specified. Please delete previous flex filter and try again.\n",
-                                         input->fd_id,
-                                         input->flow_type & ~FLOW_EXT,
-                                         existing_mask, specified_mask);
-                               return -EINVAL;
-                       }
-                       /* Keep track of flex filter cnt per flow */
-                       (*flow_based_cnt)++;
-                       *mask = rule->flex_mask_bit;
-               }
-       }
+       list_for_each_entry(entry, &pf->l3_flex_pit_list, list)
+               clear_bit(entry->pit_index, &available_index);
 
-       return 0;
+       return find_first_bit(&available_index, 8);
 }
 
-/**
- * i40e_handle_input_set - Detect and handle input set changes
- * @vsi: pointer to the targeted VSI
- * @fsp: pointer to RX flow classification spec
- * @input: pointer to filter
+/* i40e_find_flex_offset - Find an existing flex src_offset
+ * @flex_pit_list: L3 or L4 flex PIT list
+ * @src_offset: new src_offset to find
  *
- * Reads register, detect change in input set based on existing register
- * value and what user has passed. Update input set mask register if needed.
- **/
-static int i40e_handle_input_set(struct i40e_vsi *vsi,
-                                struct ethtool_rx_flow_spec *fsp,
-                                struct i40e_fdir_filter *input)
+ * Searches the flex_pit_list for an existing offset. If no offset is
+ * currently programmed, then this will return an ERR_PTR if there is no space
+ * to add a new offset, otherwise it returns NULL.
+ */
+static
+struct i40e_flex_pit *i40e_find_flex_offset(struct list_head *flex_pit_list,
+                                           u16 src_offset)
 {
-       u8 idx;
-       u64 val = 0;
-       int ret = 0;
-       u16 flow_based_filter_cnt = 0;
-       u32 fsize = 1;
-       u32 flex_pit6 = 0;
-       u64 *input_set = NULL;
-       u16 offset = 0, header_len = 0;
-       bool inset_mask_change = false;
-       u16 flex_flow_based_filter_cnt = 0;
-       u32 dest_word = I40E_FLEX_DEST_L4;
-       u32 ort_idx = I40E_L4_GLQF_ORT_IDX;
-       u32 ort_val = I40E_L4_GLQF_ORT_VAL;
-       u64 flex_mask_bit = I40E_FLEX_50_MASK;
-       u32 pit_idx = I40E_FLEX_PIT_IDX_START_L4;
-       u32 src_word_off = 0, offset_in_words = 0, flex_pit = 0;
-       struct i40e_pf *pf;
-       u32 dest_ip_addr = 0;
-       struct hlist_node *node2;
-       struct i40e_cloud_filter *cloud_rule;
-
-       if (unlikely(!vsi))
-               return -EINVAL;
+       struct i40e_flex_pit *entry;
+       int size = 0;
 
-       pf = vsi->back;
-       switch (fsp->flow_type & ~FLOW_EXT) {
-       case TCP_V4_FLOW:
-               idx = I40E_FILTER_PCTYPE_NONF_IPV4_TCP;
-               header_len = I40E_TCPIP_DUMMY_PACKET_LEN;
-               input_set = &pf->fd_tcp4_input_set;
-               flow_based_filter_cnt = pf->fd_tcp4_filter_cnt;
-               break;
-
-       case UDP_V4_FLOW:
-               idx = I40E_FILTER_PCTYPE_NONF_IPV4_UDP;
-               header_len = I40E_UDPIP_DUMMY_PACKET_LEN;
-               input_set = &pf->fd_udp4_input_set;
-               flow_based_filter_cnt = pf->fd_udp4_filter_cnt;
-               break;
-
-       case IP_USER_FLOW:
-               idx = I40E_FILTER_PCTYPE_NONF_IPV4_OTHER;
-               header_len = I40E_IP_DUMMY_PACKET_LEN;
-               dest_word = I40E_FLEX_DEST_L3;
-               pit_idx = I40E_FLEX_PIT_IDX_START_L3;
-               flex_mask_bit = I40E_FLEX_53_MASK;
-               input_set = &pf->fd_ip4_input_set;
-               ort_idx = I40E_L3_GLQF_ORT_IDX;
-               ort_val = I40E_L3_GLQF_ORT_VAL;
-               flow_based_filter_cnt = pf->fd_ip4_filter_cnt;
-               break;
-
-       /* Extend this in future for SCTP4, IPV6, IPV6(TCP/UDP/SCTP), and  L2 */
-       default:
-               /* for all other flow types */
-               return 0;
-       }
-
-       /* Always read current value from device */
-       val = i40e_read_fd_input_set(pf, idx);
-
-       /* Save once (default value read from device)
-        * It is used upon ntuple off/on and when all filters are deleted
-        * for a given flow.
-        */
-       if (!*input_set)
-               *input_set = val;
-
-       if (!i40e_is_flex_filter(input))
-               goto skip_flex_payload;
-
-       /* Treating mask as 'offset' in packet */
-       offset = ~(be16_to_cpu(input->flex_mask[3]));
-
-       /* zero based word index relative to start of payload */
-       src_word_off = (offset - header_len) >> 1;
-       offset_in_words = src_word_off;
-
-       /* Validate user-def params, specifically mask */
-       ret = i40e_validate_flex_filter_params(vsi, input, offset, header_len,
-                                              &flex_mask_bit,
-                                              &flex_flow_based_filter_cnt,
-                                              src_word_off);
-       if (ret)
-               return ret;
-
-       /* zero based word index relative to start of payload */
-       src_word_off = (offset - header_len) >> 1;
-       offset_in_words = src_word_off;
-
-       /* To avoid reading for L3 flows */
-       if (pit_idx == I40E_FLEX_PIT_IDX_START_L4)
-               flex_pit6 = i40e_read_rx_ctl(&pf->hw,
-                                            I40E_PRTQF_FLX_PIT(pit_idx));
-
-       /* Only applicable for L4 flow and only when FLX_PIT6 is valid */
-       if (flex_pit6 && (pit_idx == I40E_FLEX_PIT_IDX_START_L4)) {
-               if (flex_flow_based_filter_cnt) {
-                       if (flex_mask_bit == I40E_FLEX_51_MASK)
-                               /* Use next dest-word in field vector to be in
-                                * sync with flex_mask_bit
-                                */
-                               dest_word++;
-               } else {
-                       /* Use next dest-word in field vector */
-                       dest_word++;
-                       /* likewise update mask bit */
-                       flex_mask_bit = I40E_FLEX_51_MASK;
-               }
-       }
-
-       /* Store which FLEX WORD being used. Useful during delete filter */
-       input->flex_mask_bit = flex_mask_bit;
-
-       /* Prep value for FLX_PIT register */
-       flex_pit = I40E_FLEX_PREP_VAL(dest_word, fsize, src_word_off);
-
-       /* Do we have cloud filter which has at least one destination
-        * IP address (applicable only in case of tunnel) as part of
-        * input set? This is unsupported configuration in the context of
-        * filter with flexible payload
-        */
-       hlist_for_each_entry_safe(cloud_rule, node2,
-                                 &pf->cloud_filter_list, cloud_node) {
-               dest_ip_addr = be32_to_cpu(cloud_rule->inner_ip[0]);
-               if (dest_ip_addr) {
-                       netif_err(pf, drv, vsi->netdev,
-                                 "Previous cloud filter exist with at least one destination IP address %pI4 as part of input set. Please delete that cloud filter (ID: %u) and try again\n",
-                                 &dest_ip_addr, cloud_rule->id);
-                       return -EINVAL;
-               }
-       }
-
-       /* Set correponsing bit in input set mask register, and mark change */
-       if (!(val & flex_mask_bit)) {
-               inset_mask_change = true;
-               val |= flex_mask_bit;
-       }
-
-skip_flex_payload:
-       /* Default input set (TCP/UDP/SCTP) contains following
-        * fields: srcip + dest ip + src port + dest port
-        * For SCTP, there is one extra field, "verification tag"
+       /* Search for the src_offset first. If we find a matching entry
+        * already programmed, we can simply re-use it.
         */
-       if (val & I40E_L3_SRC_MASK) {
-               if (!fsp->h_u.tcp_ip4_spec.ip4src) {
-                       val &= ~I40E_L3_SRC_MASK;
-                       inset_mask_change = true;
-               }
-       } else {
-               if (fsp->h_u.tcp_ip4_spec.ip4src) {
-                       val |= I40E_L3_SRC_MASK;
-                       inset_mask_change = true;
-               }
-       }
-       if (val & I40E_L3_DST_MASK) {
-               if (!fsp->h_u.tcp_ip4_spec.ip4dst) {
-                       val &= ~I40E_L3_DST_MASK;
-                       inset_mask_change = true;
-               }
-       } else {
-               if (fsp->h_u.tcp_ip4_spec.ip4dst) {
-                       val |= I40E_L3_DST_MASK;
-                       inset_mask_change = true;
-               }
-       }
-       if (val & I40E_L4_SRC_MASK) {
-               if (!fsp->h_u.tcp_ip4_spec.psrc) {
-                       val &= ~I40E_L4_SRC_MASK;
-                       inset_mask_change = true;
-               }
-       } else {
-               if (fsp->h_u.tcp_ip4_spec.psrc) {
-                       val |= I40E_L4_SRC_MASK;
-                       inset_mask_change = true;
-               }
-       }
-       if (val & I40E_L4_DST_MASK) {
-               if (!fsp->h_u.tcp_ip4_spec.pdst) {
-                       val &= ~I40E_L4_DST_MASK;
-                       inset_mask_change = true;
-               }
-       } else {
-               if (fsp->h_u.tcp_ip4_spec.pdst) {
-                       val |= I40E_L4_DST_MASK;
-                       inset_mask_change = true;
-               }
+       list_for_each_entry(entry, flex_pit_list, list) {
+               size++;
+               if (entry->src_offset == src_offset)
+                       return entry;
        }
 
-       /* Handle the scenario where previous input set mask for given
-        * flow-type indicates usage of flex payload, whereas current
-        * filter being added is not using flexible payload.
-        * In another words, changing from tuple which had flex bytes as part of
-        * tuple to tuples where no flex bytes are used.
-        *
-        * Extend following check as more FLEX_5x_MASK are used.
+       /* If we haven't found an entry yet, then the provided src offset has
+        * not yet been programmed. We will program the src offset later on,
+        * but we need to indicate whether there is enough space to do so
+        * here. We'll make use of ERR_PTR for this purpose.
         */
-       if (val & (I40E_FLEX_50_MASK | I40E_FLEX_51_MASK |
-           I40E_FLEX_52_MASK | I40E_FLEX_53_MASK)) {
-               if (!i40e_is_flex_filter(input))
-                       inset_mask_change = true;
-       }
-
-       if (!inset_mask_change)
-               return 0;
-
-       if (pf->flags & I40E_FLAG_MFP_ENABLED) {
-               netif_err(pf, drv, vsi->netdev, "Change of input set is not supported when MFP mode is enabled\n");
-               return -EOPNOTSUPP;
-       }
-       if (flex_flow_based_filter_cnt || flow_based_filter_cnt) {
-               netif_err(pf, drv, vsi->netdev, "Change of input set is not supported when there are existing filters(%u) for specified flow-type: %u. Please delete them and re-try\n",
-                         (flex_flow_based_filter_cnt) ?
-                         flex_flow_based_filter_cnt : flow_based_filter_cnt,
-                         fsp->flow_type & ~FLOW_EXT);
-               return -EOPNOTSUPP;
-       }
+       if (size >= I40E_FLEX_PIT_TABLE_SIZE)
+               return ERR_PTR(-ENOSPC);
 
-       if (I40E_DEBUG_FD & pf->hw.debug_mask)
-               netif_info(pf, drv, vsi->netdev, "FD_INSET mask is changing to 0x%016llx\n",
-                          val);
-
-       /* Program FLX_PIT registers to support flex filter */
-       if (flex_pit) {
-               ret = i40e_program_flex_filter(vsi, flex_pit, flex_pit6,
-                                              offset_in_words, src_word_off,
-                                              dest_word, pit_idx,
-                                              ort_idx, ort_val);
-               if (ret)
-                       return ret;
-       }
-
-       /* Update input mask register since input set mask changed */
-       i40e_write_fd_input_set(pf, idx, val);
-
-       netif_info(pf, drv, vsi->netdev, "Input set mask has been changed. Please note that, it affects specified interface and any other related/derived interfaces\n");
-
-       return 0;
+       return NULL;
 }
 
-/**
- * i40e_add_fdir_ethtool - Add/Remove Flow Director filters
- * @vsi: pointer to the targeted VSI
- * @cmd: command to get or set RX flow classification rules
+/* i40e_add_flex_offset - Add src_offset to flex PIT table list
+ * @flex_pit_list: L3 or L4 flex PIT list
+ * @src_offset: new src_offset to add
+ * @pit_index: the PIT index to program
  *
- * Add Flow Director filters for a specific flow spec based on their
- * protocol.  Returns 0 if the filters were successfully added.
- **/
-static int i40e_add_fdir_ethtool(struct i40e_vsi *vsi,
-                                struct ethtool_rxnfc *cmd)
+ * This function programs the new src_offset to the list. It is expected that
+ * i40e_find_flex_offset has already been tried and returned NULL, indicating
+ * that this offset is not programmed, and that the list has enough space to
+ * store another offset.
+ *
+ * Returns 0 on success, and negative value on error.
+ */
+static int i40e_add_flex_offset(struct list_head *flex_pit_list,
+                               u16 src_offset,
+                               u8 pit_index)
 {
-       struct ethtool_rx_flow_spec *fsp;
-       struct i40e_fdir_filter *input;
-       struct i40e_pf *pf;
-       int ret = -EINVAL;
-       u16 vf_id;
-
-       if (!vsi)
-               return -EINVAL;
-       pf = vsi->back;
-
-       if (!(pf->flags & I40E_FLAG_FD_SB_ENABLED))
-               return -EOPNOTSUPP;
-
-       if (pf->hw_disabled_flags & I40E_FLAG_FD_SB_ENABLED)
-               return -ENOSPC;
-
-       if (test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state) ||
-           test_bit(__I40E_RESET_INTR_RECEIVED, &pf->state))
-               return -EBUSY;
-
-       if (test_bit(__I40E_FD_FLUSH_REQUESTED, &pf->state))
-               return -EBUSY;
-
-       fsp = (struct ethtool_rx_flow_spec *)&cmd->fs;
-       if (fsp->location >= (pf->hw.func_caps.fd_filters_best_effort +
-                             pf->hw.func_caps.fd_filters_guaranteed)) {
-               return -EINVAL;
-       }
-
-       if ((fsp->ring_cookie != RX_CLS_FLOW_DISC) &&
-           (fsp->ring_cookie >= vsi->num_queue_pairs))
-               return -EINVAL;
+       struct i40e_flex_pit *new_pit, *entry;
 
-       input = kzalloc(sizeof(*input), GFP_KERNEL);
-       if (!input)
+       new_pit = kzalloc(sizeof(*entry), GFP_KERNEL);
+       if (!new_pit)
                return -ENOMEM;
 
-       if (fsp->ring_cookie == RX_CLS_FLOW_DISC)
-               input->dest_ctl = I40E_FILTER_PROGRAM_DESC_DEST_DROP_PACKET;
-       else
-               input->dest_ctl =
-                            I40E_FILTER_PROGRAM_DESC_DEST_DIRECT_PACKET_QINDEX;
-
-       input->fd_id = fsp->location;
-       input->q_index = fsp->ring_cookie;
-       input->flex_off = 0;
-       input->pctype = 0;
-       input->dest_vsi = vsi->id;
-       input->fd_status = I40E_FILTER_PROGRAM_DESC_FD_STATUS_FD_ID;
-       input->cnt_index  = I40E_FD_SB_STAT_IDX(pf->hw.pf_id);
-       input->flow_type = fsp->flow_type & ~FLOW_EXT;
-       input->ip4_proto = fsp->h_u.usr_ip4_spec.proto;
-
-       /* Reverse the src and dest notion, since the HW expects them to be from
-        * Tx perspective where as the input from user is from Rx filter view.
-        */
-       input->dst_port = fsp->h_u.tcp_ip4_spec.psrc;
-       input->src_port = fsp->h_u.tcp_ip4_spec.pdst;
-       input->dst_ip[0] = fsp->h_u.tcp_ip4_spec.ip4src;
-       input->src_ip[0] = fsp->h_u.tcp_ip4_spec.ip4dst;
-
-       /* Deciding factor, whether it is flex filter or filter for VF
-        * is value of 'mask' (user-def N m)
-        * If mask is specified then treat it as flex filter
-        * otherwise this filter is for VF.
-        * This distinction is needed due to overloading usage of
-        * user-def field.
-        */
-       if (fsp->m_ext.data[1] == cpu_to_be32(~0)) {
-               vf_id = be32_to_cpu(fsp->h_ext.data[1]);
-               if (vf_id >= pf->num_alloc_vfs) {
-                       netif_info(pf, drv, vsi->netdev,
-                                  "Invalid VF id %d\n", vf_id);
-                       goto free_input;
-               }
-               /* Find vsi id from vf id and override dest vsi */
-               input->dest_vsi = pf->vf[vf_id].lan_vsi_id;
-               if (input->q_index >= pf->vf[vf_id].num_queue_pairs) {
-                       netif_info(pf, drv, vsi->netdev,
-                                  "Invalid queue id %d for VF %d\n",
-                                  input->q_index, vf_id);
-                       goto free_input;
-               }
-       } else {
-               /* flex filter is supported only for main VSI */
-               if (vsi->type != I40E_VSI_MAIN) {
-                       netif_err(pf, drv, vsi->netdev,
-                                 "Unsupported interface type for adding filter using user-defs\n");
-                       goto free_input;
-               }
-
-               /* initialized to known values */
-               input->flex_bytes[2] = 0;
-               input->flex_bytes[3] = 0;
-               input->flex_mask[2] = 0;
-               input->flex_mask[3] = 0;
-               if ((fsp->h_ext.data[0] == cpu_to_be32(0x0)) &&
-                   (fsp->h_ext.data[1] != cpu_to_be32(~0))) {
-                       u16 flex_temp;
-
-                       flex_temp = be32_to_cpu(fsp->h_ext.data[1]);
-                       input->flex_bytes[2] = cpu_to_be16(flex_temp);
-                       if (input->flex_bytes[2]) {
-                               netif_err(pf, drv, vsi->netdev,
-                                         "Only one word is supported for flex filter\n");
-                               goto free_input;
-                       }
-                       /* Store only relevant section of user-defs */
-                       flex_temp = be32_to_cpu(fsp->h_ext.data[1]) >> 16;
-                       input->flex_bytes[3] = cpu_to_be16(flex_temp);
-                       flex_temp = be32_to_cpu(fsp->m_ext.data[1]) >> 16;
-                       input->flex_mask[3] = cpu_to_be16(flex_temp);
+       new_pit->src_offset = src_offset;
+       new_pit->pit_index = pit_index;
+
+       /* We need to insert this item such that the list is sorted by
+        * src_offset in ascending order.
+        */
+       list_for_each_entry(entry, flex_pit_list, list) {
+               if (new_pit->src_offset < entry->src_offset) {
+                       list_add_tail(&new_pit->list, &entry->list);
+                       return 0;
                }
-       }
 
-       /*  Detect and handle change for input set mask */
-       ret = i40e_handle_input_set(vsi, fsp, input);
-       if (ret) {
-               netif_err(pf, drv, vsi->netdev, "Unable to handle change in input set mask\n");
-               goto free_input;
-       }
+               /* If we found an entry with our offset already programmed we
+                * can simply return here, after freeing the memory. However,
+                * if the pit_index does not match we need to report an error.
+                */
+               if (new_pit->src_offset == entry->src_offset) {
+                       int err = 0;
 
-       ret = i40e_add_del_fdir(vsi, input, true);
-free_input:
-       if (ret)
-               kfree(input);
-       else {
-               (void)i40e_del_cloud_filter_ethtool(pf, cmd);
-               i40e_update_ethtool_fdir_entry(vsi, input, fsp->location);
+                       /* If the PIT index is not the same we can't re-use
+                        * the entry, so we must report an error.
+                        */
+                       if (new_pit->pit_index != entry->pit_index)
+                               err = -EINVAL;
+
+                       kfree(new_pit);
+                       return err;
+               }
        }
 
-       return ret;
+       /* If we reached here, then we haven't yet added the item. This means
+        * that we should add the item at the end of the list.
+        */
+       list_add_tail(&new_pit->list, flex_pit_list);
+       return 0;
 }
 
 /**
- * i40e_cloud_filter_mask2flags- Convert cloud filter details to filter type
- * @pf: pointer to the physical function struct
- * @fsp: RX flow classification rules
- * @flags: Resultant combination of all the fields to decide the tuple
+ * __i40e_reprogram_flex_pit - Re-program specific FLX_PIT table
+ * @pf: Pointer to the PF structure
+ * @flex_pit_list: list of flexible src offsets in use
+ * #flex_pit_start: index to first entry for this section of the table
  *
- * The general trick in setting these flags is that if the mask field for
- * a value is non-zero, then the field itself was set to something, so we
- * use this to tell us what has been selected.
+ * In order to handle flexible data, the hardware uses a table of values
+ * called the FLX_PIT table. This table is used to indicate which sections of
+ * the input correspond to what PIT index values. Unfortunately, hardware is
+ * very restrictive about programming this table. Entries must be ordered by
+ * src_offset in ascending order, without duplicates. Additionally, unused
+ * entries must be set to the unused index value, and must have valid size and
+ * length according to the src_offset ordering.
  *
- * Returns 0 if a valid filter type was identified.
+ * This function will reprogram the FLX_PIT register from a book-keeping
+ * structure that we guarantee is already ordered correctly, and has no more
+ * than 3 entries.
+ *
+ * To make things easier, we only support flexible values of one word length,
+ * rather than allowing variable length flexible values.
  **/
-static int i40e_cloud_filter_mask2flags(struct i40e_pf *pf,
-                                       struct ethtool_rx_flow_spec *fsp,
-                                       u8 *flags)
+static void __i40e_reprogram_flex_pit(struct i40e_pf *pf,
+                                     struct list_head *flex_pit_list,
+                                     int flex_pit_start)
 {
-       u32 tenant_id;
-       u8 i = 0;
-
-       *flags = 0;
+       struct i40e_flex_pit *entry = NULL;
+       u16 last_offset = 0;
+       int i = 0, j = 0;
 
-       switch (fsp->flow_type & ~FLOW_EXT) {
-       case ETHER_FLOW:
-               /* use is_broadcast and is_zero to check for all 0xf or 0 */
-               if (is_broadcast_ether_addr(fsp->m_u.ether_spec.h_dest)) {
-                       i |= I40E_CLOUD_FIELD_OMAC;
-               } else if (is_zero_ether_addr(fsp->m_u.ether_spec.h_dest)) {
-                       i &= ~I40E_CLOUD_FIELD_OMAC;
-               } else {
-                       dev_info(&pf->pdev->dev, "Bad ether dest mask %pM\n",
-                                fsp->m_u.ether_spec.h_dest);
-                       return I40E_ERR_CONFIG;
+       /* First, loop over the list of flex PIT entries, and reprogram the
+        * registers.
+        */
+       list_for_each_entry(entry, flex_pit_list, list) {
+               /* We have to be careful when programming values for the
+                * largest SRC_OFFSET value. It is possible that adding
+                * additional empty values at the end would overflow the space
+                * for the SRC_OFFSET in the FLX_PIT register. To avoid this,
+                * we check here and add the empty values prior to adding the
+                * largest value.
+                *
+                * To determine this, we will use a loop from i+1 to 3, which
+                * will determine whether the unused entries would have valid
+                * SRC_OFFSET. Note that there cannot be extra entries past
+                * this value, because the only valid values would have been
+                * larger than I40E_MAX_FLEX_SRC_OFFSET, and thus would not
+                * have been added to the list in the first place.
+                */
+               for (j = i + 1; j < 3; j++) {
+                       u16 offset = entry->src_offset + j;
+                       int index = flex_pit_start + i;
+                       u32 value = I40E_FLEX_PREP_VAL(I40E_FLEX_DEST_UNUSED,
+                                                      1,
+                                                      offset - 3);
+
+                       if (offset > I40E_MAX_FLEX_SRC_OFFSET) {
+                               i40e_write_rx_ctl(&pf->hw,
+                                                 I40E_PRTQF_FLX_PIT(index),
+                                                 value);
+                               i++;
+                       }
                }
 
-               if (is_broadcast_ether_addr(fsp->m_u.ether_spec.h_source)) {
-                       i |= I40E_CLOUD_FIELD_IMAC;
-               } else if (is_zero_ether_addr(fsp->m_u.ether_spec.h_source)) {
-                       i &= ~I40E_CLOUD_FIELD_IMAC;
-               } else {
-                       dev_info(&pf->pdev->dev, "Bad ether source mask %pM\n",
-                                fsp->m_u.ether_spec.h_source);
-                       return I40E_ERR_CONFIG;
-               }
-               break;
+               /* Now, we can program the actual value into the table */
+               i40e_write_rx_ctl(&pf->hw,
+                                 I40E_PRTQF_FLX_PIT(flex_pit_start + i),
+                                 I40E_FLEX_PREP_VAL(entry->pit_index + 50,
+                                                    1,
+                                                    entry->src_offset));
+               i++;
+       }
+
+       /* In order to program the last entries in the table, we need to
+        * determine the valid offset. If the list is empty, we'll just start
+        * with 0. Otherwise, we'll start with the last item offset and add 1.
+        * This ensures that all entries have valid sizes. If we don't do this
+        * correctly, the hardware will disable flexible field parsing.
+        */
+       if (!list_empty(flex_pit_list))
+               last_offset = list_prev_entry(entry, list)->src_offset + 1;
 
-       case IP_USER_FLOW:
-               if (fsp->m_u.usr_ip4_spec.ip4dst == cpu_to_be32(0xffffffff)) {
-                       i |= I40E_CLOUD_FIELD_IIP;
-               } else if (!fsp->m_u.usr_ip4_spec.ip4dst) {
-                       i &= ~I40E_CLOUD_FIELD_IIP;
-               } else {
-                       dev_info(&pf->pdev->dev, "Bad ip dst mask 0x%08x\n",
-                                be32_to_cpu(fsp->m_u.usr_ip4_spec.ip4dst));
-                       return I40E_ERR_CONFIG;
-               }
-               break;
+       for (; i < 3; i++, last_offset++) {
+               i40e_write_rx_ctl(&pf->hw,
+                                 I40E_PRTQF_FLX_PIT(flex_pit_start + i),
+                                 I40E_FLEX_PREP_VAL(I40E_FLEX_DEST_UNUSED,
+                                                    1,
+                                                    last_offset));
+       }
+}
+
+/**
+ * i40e_reprogram_flex_pit - Reprogram all FLX_PIT tables after input set change
+ * @pf: pointer to the PF structure
+ *
+ * This function reprograms both the L3 and L4 FLX_PIT tables. See the
+ * internal helper function for implementation details.
+ */
+static void i40e_reprogram_flex_pit(struct i40e_pf *pf)
+{
+       __i40e_reprogram_flex_pit(pf, &pf->l3_flex_pit_list,
+                                 I40E_FLEX_PIT_IDX_START_L3);
+
+       __i40e_reprogram_flex_pit(pf, &pf->l4_flex_pit_list,
+                                 I40E_FLEX_PIT_IDX_START_L4);
+
+       /* We also need to program the L3 and L4 GLQF ORT register */
+       i40e_write_rx_ctl(&pf->hw,
+                         I40E_GLQF_ORT(I40E_L3_GLQF_ORT_IDX),
+                         I40E_ORT_PREP_VAL(I40E_FLEX_PIT_IDX_START_L3,
+                                           3, 1));
+
+       i40e_write_rx_ctl(&pf->hw,
+                         I40E_GLQF_ORT(I40E_L4_GLQF_ORT_IDX),
+                         I40E_ORT_PREP_VAL(I40E_FLEX_PIT_IDX_START_L4,
+                                           3, 1));
+}
 
+/**
+ * i40e_flow_str - Converts a flow_type into a human readable string
+ * @flow_type: the flow type from a flow specification
+ *
+ * Currently only flow types we support are included here, and the string
+ * value attempts to match what ethtool would use to configure this flow type.
+ **/
+static const char *i40e_flow_str(struct ethtool_rx_flow_spec *fsp)
+{
+       switch (fsp->flow_type & ~FLOW_EXT) {
+       case TCP_V4_FLOW:
+               return "tcp4";
+       case UDP_V4_FLOW:
+               return "udp4";
+       case SCTP_V4_FLOW:
+               return "sctp4";
+       case IP_USER_FLOW:
+               return "ip4";
        default:
-               return I40E_ERR_CONFIG;
+               return "unknown";
        }
+}
 
-       switch (be16_to_cpu(fsp->m_ext.vlan_tci)) {
-       case 0xffff:
-               if (fsp->h_ext.vlan_tci & cpu_to_be16(~0x7fff)) {
-                       dev_info(&pf->pdev->dev, "Bad vlan %u\n",
-                                be16_to_cpu(fsp->h_ext.vlan_tci));
-                       return I40E_ERR_CONFIG;
-               }
-               i |= I40E_CLOUD_FIELD_IVLAN;
-               break;
+/* i40e_pit_index_to_mask - Return the FLEX mask for a given PIT index
+ * @pit_index: PIT index to convert
+ *
+ * Returns the mask for a given PIT index. Will return 0 if the pit_index is
+ * of range.
+ */
+static u64 i40e_pit_index_to_mask(int pit_index)
+{
+       switch (pit_index) {
        case 0:
-               i &= ~I40E_CLOUD_FIELD_IVLAN;
-               break;
+               return I40E_FLEX_50_MASK;
+       case 1:
+               return I40E_FLEX_51_MASK;
+       case 2:
+               return I40E_FLEX_52_MASK;
+       case 3:
+               return I40E_FLEX_53_MASK;
+       case 4:
+               return I40E_FLEX_54_MASK;
+       case 5:
+               return I40E_FLEX_55_MASK;
+       case 6:
+               return I40E_FLEX_56_MASK;
+       case 7:
+               return I40E_FLEX_57_MASK;
        default:
-               dev_info(&pf->pdev->dev, "Bad vlan mask %u\n",
-                        be16_to_cpu(fsp->m_ext.vlan_tci));
-               return I40E_ERR_CONFIG;
+               return 0;
        }
+}
 
-       /* we already know that the user-def field was set, that's how we
-        * got here, so we don't need to check that.  However, we need to
-        * see if 0xffffffff or a non-zero three-byte tenant id was set.
-        */
-       tenant_id = be32_to_cpu(fsp->h_ext.data[0]);
-       if (tenant_id == 0xffffffff || tenant_id == 0) {
-               i &= ~I40E_CLOUD_FIELD_TEN_ID;
-       } else if (tenant_id & 0x00ffffff) {
-               i |= I40E_CLOUD_FIELD_TEN_ID;
-       } else {
-               dev_info(&pf->pdev->dev, "Bad tenant/vxlan id %d\n", tenant_id);
-               return I40E_ERR_CONFIG;
-       }
+/**
+ * i40e_print_input_set - Show changes between two input sets
+ * @vsi: the vsi being configured
+ * @old: the old input set
+ * @new: the new input set
+ *
+ * Print the difference between old and new input sets by showing which series
+ * of words are toggled on or off. Only displays the bits we actually support
+ * changing.
+ **/
+static void i40e_print_input_set(struct i40e_vsi *vsi, u64 old, u64 new)
+{
+       struct i40e_pf *pf = vsi->back;
+       bool old_value, new_value;
+       int i;
 
-       *flags = i;
-       return I40E_SUCCESS;
+       old_value = !!(old & I40E_L3_SRC_MASK);
+       new_value = !!(new & I40E_L3_SRC_MASK);
+       if (old_value != new_value)
+               netif_info(pf, drv, vsi->netdev, "L3 source address: %s -> %s\n",
+                          old_value ? "ON" : "OFF",
+                          new_value ? "ON" : "OFF");
+
+       old_value = !!(old & I40E_L3_DST_MASK);
+       new_value = !!(new & I40E_L3_DST_MASK);
+       if (old_value != new_value)
+               netif_info(pf, drv, vsi->netdev, "L3 destination address: %s -> %s\n",
+                          old_value ? "ON" : "OFF",
+                          new_value ? "ON" : "OFF");
+
+       old_value = !!(old & I40E_L4_SRC_MASK);
+       new_value = !!(new & I40E_L4_SRC_MASK);
+       if (old_value != new_value)
+               netif_info(pf, drv, vsi->netdev, "L4 source port: %s -> %s\n",
+                          old_value ? "ON" : "OFF",
+                          new_value ? "ON" : "OFF");
+
+       old_value = !!(old & I40E_L4_DST_MASK);
+       new_value = !!(new & I40E_L4_DST_MASK);
+       if (old_value != new_value)
+               netif_info(pf, drv, vsi->netdev, "L4 destination port: %s -> %s\n",
+                          old_value ? "ON" : "OFF",
+                          new_value ? "ON" : "OFF");
+
+       old_value = !!(old & I40E_VERIFY_TAG_MASK);
+       new_value = !!(new & I40E_VERIFY_TAG_MASK);
+       if (old_value != new_value)
+               netif_info(pf, drv, vsi->netdev, "SCTP verification tag: %s -> %s\n",
+                          old_value ? "ON" : "OFF",
+                          new_value ? "ON" : "OFF");
+
+       /* Show change of flexible filter entries */
+       for (i = 0; i < I40E_FLEX_INDEX_ENTRIES; i++) {
+               u64 flex_mask = i40e_pit_index_to_mask(i);
+
+               old_value = !!(old & flex_mask);
+               new_value = !!(new & flex_mask);
+               if (old_value != new_value)
+                       netif_info(pf, drv, vsi->netdev, "FLEX index %d: %s -> %s\n",
+                                  i,
+                                  old_value ? "ON" : "OFF",
+                                  new_value ? "ON" : "OFF");
+       }
+
+       netif_info(pf, drv, vsi->netdev, "  Current input set: %0llx\n",
+                  old);
+       netif_info(pf, drv, vsi->netdev, "Requested input set: %0llx\n",
+                  new);
 }
 
 /**
- * i40e_add_cloud_filter_ethtool - Add cloud filter
- * @pf: pointer to the physical function struct
- * @cmd: The command to get or set Rx flow classification rules
+ * i40e_check_fdir_input_set - Check that a given rx_flow_spec mask is valid
+ * @vsi: pointer to the targeted VSI
+ * @fsp: pointer to Rx flow specification
+ * @userdef: userdefined data from flow specification
  *
- * Add cloud filter for a specific flow spec.
- * Returns 0 if the filter were successfully added.
+ * Ensures that a given ethtool_rx_flow_spec has a valid mask. Some support
+ * for partial matches exists with a few limitations. First, hardware only
+ * supports masking by word boundary (2 bytes) and not per individual bit.
+ * Second, hardware is limited to using one mask for a flow type and cannot
+ * use a separate mask for each filter.
+ *
+ * To support these limitations, if we already have a configured filter for
+ * the specified type, this function enforces that new filters of the type
+ * match the configured input set. Otherwise, if we do not have a filter of
+ * the specified type, we allow the input set to be updated to match the
+ * desired filter.
+ *
+ * To help ensure that administrators understand why filters weren't displayed
+ * as supported, we print a diagnostic message displaying how the input set
+ * would change and warning to delete the preexisting filters if required.
+ *
+ * Returns 0 on successful input set match, and a negative return code on
+ * failure.
  **/
-static int i40e_add_cloud_filter_ethtool(struct i40e_pf *pf,
-                                        struct ethtool_rxnfc *cmd)
+static int i40e_check_fdir_input_set(struct i40e_vsi *vsi,
+                                    struct ethtool_rx_flow_spec *fsp,
+                                    struct i40e_rx_flow_userdef *userdef)
 {
-       struct i40e_cloud_filter *rule, *parent, *filter = NULL;
-       struct ethtool_rx_flow_spec *fsp;
-       struct hlist_node *node2;
-       struct i40e_vsi *dst_vsi;
-       u16 vf_id, vsi_idx;
-       u8 flags = 0;
-       int ret;
+       struct i40e_pf *pf = vsi->back;
+       struct ethtool_tcpip4_spec *tcp_ip4_spec;
+       struct ethtool_usrip4_spec *usr_ip4_spec;
+       u64 current_mask, new_mask;
+       bool new_flex_offset = false;
+       bool flex_l3 = false;
+       u16 *fdir_filter_count;
+       u16 index, src_offset = 0;
+       u8 pit_index = 0;
+       int err;
 
-       if (!(pf->flags & I40E_FLAG_FD_SB_ENABLED))
+       switch (fsp->flow_type & ~FLOW_EXT) {
+       case SCTP_V4_FLOW:
+               index = I40E_FILTER_PCTYPE_NONF_IPV4_SCTP;
+               fdir_filter_count = &pf->fd_sctp4_filter_cnt;
+               break;
+       case TCP_V4_FLOW:
+               index = I40E_FILTER_PCTYPE_NONF_IPV4_TCP;
+               fdir_filter_count = &pf->fd_tcp4_filter_cnt;
+               break;
+       case UDP_V4_FLOW:
+               index = I40E_FILTER_PCTYPE_NONF_IPV4_UDP;
+               fdir_filter_count = &pf->fd_udp4_filter_cnt;
+               break;
+       case IP_USER_FLOW:
+               index = I40E_FILTER_PCTYPE_NONF_IPV4_OTHER;
+               fdir_filter_count = &pf->fd_ip4_filter_cnt;
+               flex_l3 = true;
+               break;
+       default:
                return -EOPNOTSUPP;
+       }
 
-       if (test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state) ||
-           test_bit(__I40E_RESET_INTR_RECEIVED, &pf->state))
-               return -EBUSY;
+       /* Read the current input set from register memory. */
+       current_mask = i40e_read_fd_input_set(pf, index);
+       new_mask = current_mask;
 
-       fsp = (struct ethtool_rx_flow_spec *)&cmd->fs;
-       if (fsp->m_ext.data[1] == cpu_to_be32(0xffffffff)) {
-               vf_id = (u16)be32_to_cpu(fsp->h_ext.data[1]);
-               /* if Vf id >= num_vfs, program a filter for PF Main VSI */
-               if (vf_id >= pf->num_alloc_vfs) {
-                       dev_info(&pf->pdev->dev,
-                                "Out of range vf_id %d, adding the cloud filter to PF\n",
-                                vf_id);
-                       dst_vsi = pf->vsi[pf->lan_vsi];
-               } else {
-                       vsi_idx = pf->vf[vf_id].lan_vsi_idx;
-                       dst_vsi = pf->vsi[vsi_idx];
-                       if (!dst_vsi) {
-                               dev_info(&pf->pdev->dev,
-                                        "Invalid vf_id %d\n", vf_id);
-                               return -EINVAL;
-                       }
-               }
-       } else if (!fsp->m_ext.data[1]) {
-               dst_vsi = pf->vsi[pf->lan_vsi];
-       } else {
-               return -EINVAL;
-       }
+       /* Determine, if any, the required changes to the input set in order
+        * to support the provided mask.
+        *
+        * Hardware only supports masking at word (2 byte) granularity and does
+        * not support full bitwise masking. This implementation simplifies
+        * even further and only supports fully enabled or fully disabled
+        * masks for each field, even though we could split the ip4src and
+        * ip4dst fields.
+        */
+       switch (fsp->flow_type & ~FLOW_EXT) {
+       case SCTP_V4_FLOW:
+               new_mask &= ~I40E_VERIFY_TAG_MASK;
+               /* Fall through */
+       case TCP_V4_FLOW:
+       case UDP_V4_FLOW:
+               tcp_ip4_spec = &fsp->m_u.tcp_ip4_spec;
 
-       if (fsp->ring_cookie == ~0) {
-               dev_info(&pf->pdev->dev, "No drop option for cloud filters\n");
-               return -EINVAL;
-       } else if (fsp->ring_cookie >= dst_vsi->num_queue_pairs) {
-               dev_info(&pf->pdev->dev,
-                        "Invalid queue_id %llu\n", fsp->ring_cookie);
-               return -EINVAL;
-       }
+               /* IPv4 source address */
+               if (tcp_ip4_spec->ip4src == htonl(0xFFFFFFFF))
+                       new_mask |= I40E_L3_SRC_MASK;
+               else if (!tcp_ip4_spec->ip4src)
+                       new_mask &= ~I40E_L3_SRC_MASK;
+               else
+                       return -EOPNOTSUPP;
 
-       ret = i40e_cloud_filter_mask2flags(pf, fsp, &flags);
-       if (ret || !flags) {
-               dev_info(&pf->pdev->dev, "Invalid mask config, flags = %d\n",
-                        flags);
-               return -EINVAL;
-       }
+               /* IPv4 destination address */
+               if (tcp_ip4_spec->ip4dst == htonl(0xFFFFFFFF))
+                       new_mask |= I40E_L3_DST_MASK;
+               else if (!tcp_ip4_spec->ip4dst)
+                       new_mask &= ~I40E_L3_DST_MASK;
+               else
+                       return -EOPNOTSUPP;
 
-       /* if filter exists with same id, delete the old one */
-       parent = NULL;
-       hlist_for_each_entry_safe(rule, node2,
-                                 &pf->cloud_filter_list, cloud_node) {
-               /* filter exists with the id */
-               if (rule->id == fsp->location)
-                       filter = rule;
+               /* L4 source port */
+               if (tcp_ip4_spec->psrc == htons(0xFFFF))
+                       new_mask |= I40E_L4_SRC_MASK;
+               else if (!tcp_ip4_spec->psrc)
+                       new_mask &= ~I40E_L4_SRC_MASK;
+               else
+                       return -EOPNOTSUPP;
 
-               /* bail out if we've passed the likely location in the list */
-               if (rule->id >= fsp->location)
-                       break;
+               /* L4 destination port */
+               if (tcp_ip4_spec->pdst == htons(0xFFFF))
+                       new_mask |= I40E_L4_DST_MASK;
+               else if (!tcp_ip4_spec->pdst)
+                       new_mask &= ~I40E_L4_DST_MASK;
+               else
+                       return -EOPNOTSUPP;
 
-               /* track where we left off */
-               parent = rule;
-       }
-       if (filter && (filter->id == fsp->location)) {
-               /* found it in the cloud list, so remove it */
-               ret = i40e_add_del_cloud_filter(pf, filter, false);
-               if (ret && (pf->hw.aq.asq_last_status != I40E_AQ_RC_ENOENT)) {
-                       dev_info(&pf->pdev->dev,
-                                "fail to delete old cloud filter, err %s, aq_err %s\n",
-                                i40e_stat_str(&pf->hw, ret),
-                                i40e_aq_str(&pf->hw,
-                                            pf->hw.aq.asq_last_status));
-                       return i40e_aq_rc_to_posix(ret,
-                                                  pf->hw.aq.asq_last_status);
-               }
-               hlist_del(&filter->cloud_node);
-               kfree(filter);
-               pf->num_cloud_filters--;
-       } else {
-               /* not in the cloud list, so check the PF's fdir list */
-               (void)i40e_del_fdir_entry(pf->vsi[pf->lan_vsi], cmd);
-       }
+               /* Filtering on Type of Service is not supported. */
+               if (tcp_ip4_spec->tos)
+                       return -EOPNOTSUPP;
 
-       /* Presence of cloud filter and flex filter is mutually exclusive */
-       if (pf->fd_flex_filter_cnt) {
-               dev_err(&pf->pdev->dev,
-                       "Filters(%d) using user-def (flexible payload) are present. Please delete them and try again\n",
-                       pf->fd_flex_filter_cnt);
-               return I40E_NOT_SUPPORTED;
-       }
+               break;
+       case IP_USER_FLOW:
+               usr_ip4_spec = &fsp->m_u.usr_ip4_spec;
 
-       filter = kzalloc(sizeof(*filter), GFP_KERNEL);
-       if (!filter)
-               return -ENOMEM;
+               /* IPv4 source address */
+               if (usr_ip4_spec->ip4src == htonl(0xFFFFFFFF))
+                       new_mask |= I40E_L3_SRC_MASK;
+               else if (!usr_ip4_spec->ip4src)
+                       new_mask &= ~I40E_L3_SRC_MASK;
+               else
+                       return -EOPNOTSUPP;
 
-       filter->id = fsp->location;
-       filter->seid = dst_vsi->seid;
+               /* IPv4 destination address */
+               if (usr_ip4_spec->ip4dst == htonl(0xFFFFFFFF))
+                       new_mask |= I40E_L3_DST_MASK;
+               else if (!usr_ip4_spec->ip4dst)
+                       new_mask &= ~I40E_L3_DST_MASK;
+               else
+                       return -EOPNOTSUPP;
+
+               /* First 4 bytes of L4 header */
+               if (usr_ip4_spec->l4_4_bytes == htonl(0xFFFFFFFF))
+                       new_mask |= I40E_L4_SRC_MASK | I40E_L4_DST_MASK;
+               else if (!usr_ip4_spec->l4_4_bytes)
+                       new_mask &= ~(I40E_L4_SRC_MASK | I40E_L4_DST_MASK);
+               else
+                       return -EOPNOTSUPP;
+
+               /* Filtering on Type of Service is not supported. */
+               if (usr_ip4_spec->tos)
+                       return -EOPNOTSUPP;
+
+               /* Filtering on IP version is not supported */
+               if (usr_ip4_spec->ip_ver)
+                       return -EINVAL;
+
+               /* Filtering on L4 protocol is not supported */
+               if (usr_ip4_spec->proto)
+                       return -EINVAL;
 
-       switch (fsp->flow_type & ~FLOW_EXT) {
-       case ETHER_FLOW:
-               ether_addr_copy(filter->outer_mac,
-                               fsp->h_u.ether_spec.h_dest);
-               ether_addr_copy(filter->inner_mac,
-                               fsp->h_u.ether_spec.h_source);
                break;
+       default:
+               return -EOPNOTSUPP;
+       }
+
+       /* First, clear all flexible filter entries */
+       new_mask &= ~I40E_FLEX_INPUT_MASK;
+
+       /* If we have a flexible filter, try to add this offset to the correct
+        * flexible filter PIT list. Once finished, we can update the mask.
+        * If the src_offset changed, we will get a new mask value which will
+        * trigger an input set change.
+        */
+       if (userdef->flex_filter) {
+               struct i40e_flex_pit *l3_flex_pit = NULL, *flex_pit = NULL;
+
+               /* Flexible offset must be even, since the flexible payload
+                * must be aligned on 2-byte boundary.
+                */
+               if (userdef->flex_offset & 0x1) {
+                       dev_warn(&pf->pdev->dev,
+                                "Flexible data offset must be 2-byte aligned\n");
+                       return -EINVAL;
+               }
+
+               src_offset = userdef->flex_offset >> 1;
+
+               /* FLX_PIT source offset value is only so large */
+               if (src_offset > I40E_MAX_FLEX_SRC_OFFSET) {
+                       dev_warn(&pf->pdev->dev,
+                                "Flexible data must reside within first 64 bytes of the packet payload\n");
+                       return -EINVAL;
+               }
+
+               /* See if this offset has already been programmed. If we get
+                * an ERR_PTR, then the filter is not safe to add. Otherwise,
+                * if we get a NULL pointer, this means we will need to add
+                * the offset.
+                */
+               flex_pit = i40e_find_flex_offset(&pf->l4_flex_pit_list,
+                                                src_offset);
+               if (IS_ERR(flex_pit))
+                       return PTR_ERR(flex_pit);
+
+               /* IP_USER_FLOW filters match both L4 (ICMP) and L3 (unknown)
+                * packet types, and thus we need to program both L3 and L4
+                * flexible values. These must have identical flexible index,
+                * as otherwise we can't correctly program the input set. So
+                * we'll find both an L3 and L4 index and make sure they are
+                * the same.
+                */
+               if (flex_l3) {
+                       l3_flex_pit =
+                               i40e_find_flex_offset(&pf->l3_flex_pit_list,
+                                                     src_offset);
+                       if (IS_ERR(l3_flex_pit))
+                               return PTR_ERR(l3_flex_pit);
+
+                       if (flex_pit) {
+                               /* If we already had a matching L4 entry, we
+                                * need to make sure that the L3 entry we
+                                * obtained uses the same index.
+                                */
+                               if (l3_flex_pit) {
+                                       if (l3_flex_pit->pit_index !=
+                                           flex_pit->pit_index) {
+                                               return -EINVAL;
+                                       }
+                               } else {
+                                       new_flex_offset = true;
+                               }
+                       } else {
+                               flex_pit = l3_flex_pit;
+                       }
+               }
 
-       case IP_USER_FLOW:
-               if (flags & I40E_CLOUD_FIELD_TEN_ID) {
-                       dev_info(&pf->pdev->dev, "Tenant id not allowed for ip filter\n");
-                       kfree(filter);
-                       return I40E_ERR_CONFIG;
+               /* If we didn't find an existing flex offset, we need to
+                * program a new one. However, we don't immediately program it
+                * here because we will wait to program until after we check
+                * that it is safe to change the input set.
+                */
+               if (!flex_pit) {
+                       new_flex_offset = true;
+                       pit_index = i40e_unused_pit_index(pf);
+               } else {
+                       pit_index = flex_pit->pit_index;
                }
-               filter->inner_ip[0] = fsp->h_u.usr_ip4_spec.ip4dst;
-               break;
 
-       default:
-               dev_info(&pf->pdev->dev, "unknown flow type 0x%x\n",
-                        (fsp->flow_type & ~FLOW_EXT));
-               kfree(filter);
-               return I40E_ERR_CONFIG;
+               /* Update the mask with the new offset */
+               new_mask |= i40e_pit_index_to_mask(pit_index);
        }
 
-       if (be32_to_cpu(fsp->h_ext.data[0]) != 0xffffffff) {
-               u32 id = be32_to_cpu(fsp->h_ext.data[0]);
+       /* If the mask and flexible filter offsets for this filter match the
+        * currently programmed values we don't need any input set change, so
+        * this filter is safe to install.
+        */
+       if (new_mask == current_mask && !new_flex_offset)
+               return 0;
 
-               filter->tenant_id = id & 0x00ffffff;
-               filter->tunnel_type = (id >> 24) & 0xff;
-       } else {
-               /* L3 VEB filter for non-tunneled packets or a tuple w/o vni  */
-               filter->tenant_id = 0;
-               filter->tunnel_type = I40E_CLOUD_TNL_TYPE_NONE;
+       netif_info(pf, drv, vsi->netdev, "Input set change requested for %s flows:\n",
+                  i40e_flow_str(fsp));
+       i40e_print_input_set(vsi, current_mask, new_mask);
+       if (new_flex_offset) {
+               netif_info(pf, drv, vsi->netdev, "FLEX index %d: Offset -> %d",
+                          pit_index, src_offset);
        }
-       filter->queue_id = fsp->ring_cookie;
-       filter->flags = flags;
-       filter->inner_vlan = fsp->h_ext.vlan_tci;
 
-       ret = i40e_add_del_cloud_filter(pf, filter, true);
-       if (ret) {
-               kfree(filter);
-               dev_info(&pf->pdev->dev,
-                        "fail to add cloud filter, err %s aq_err %s\n",
-                        i40e_stat_str(&pf->hw, ret),
-                        i40e_aq_str(&pf->hw,
-                                    pf->hw.aq.asq_last_status));
-               return i40e_aq_rc_to_posix(ret, pf->hw.aq.asq_last_status);
+       /* Hardware input sets are global across multiple ports, so even the
+        * main port cannot change them when in MFP mode as this would impact
+        * any filters on the other ports.
+        */
+       if (pf->flags & I40E_FLAG_MFP_ENABLED) {
+               netif_err(pf, drv, vsi->netdev, "Cannot change Flow Director input sets while MFP is enabled\n");
+               return -EOPNOTSUPP;
        }
 
-       /* add filter to the ordered list */
-       INIT_HLIST_NODE(&filter->cloud_node);
-       if (parent)
-               hlist_add_behind(&filter->cloud_node, &parent->cloud_node);
-       else
-               hlist_add_head(&filter->cloud_node, &pf->cloud_filter_list);
-       pf->num_cloud_filters++;
+       /* This filter requires us to update the input set. However, hardware
+        * only supports one input set per flow type, and does not support
+        * separate masks for each filter. This means that we can only support
+        * a single mask for all filters of a specific type.
+        *
+        * If we have preexisting filters, they obviously depend on the
+        * current programmed input set. Display a diagnostic message in this
+        * case explaining why the filter could not be accepted.
+        */
+       if (*fdir_filter_count) {
+               netif_err(pf, drv, vsi->netdev, "Cannot change input set for %s flows until %d preexisting filters are removed\n",
+                         i40e_flow_str(fsp),
+                         *fdir_filter_count);
+               return -EOPNOTSUPP;
+       }
+
+       i40e_write_fd_input_set(pf, index, new_mask);
+
+       /* Add the new offset and update table, if necessary */
+       if (new_flex_offset) {
+               err = i40e_add_flex_offset(&pf->l4_flex_pit_list, src_offset,
+                                          pit_index);
+               if (err)
+                       return err;
+
+               if (flex_l3) {
+                       err = i40e_add_flex_offset(&pf->l3_flex_pit_list,
+                                                  src_offset,
+                                                  pit_index);
+                       if (err)
+                               return err;
+               }
+
+               i40e_reprogram_flex_pit(pf);
+       }
 
        return 0;
 }
 
 /**
- * i40e_del_cloud_filter_ethtool - del vxlan filter
- * @pf: pointer to the physical function struct
- * @cmd: RX flow classification rules
+ * i40e_add_fdir_ethtool - Add/Remove Flow Director filters
+ * @vsi: pointer to the targeted VSI
+ * @cmd: command to get or set RX flow classification rules
  *
- * Delete vxlan filter for a specific flow spec.
- * Returns 0 if the filter was successfully deleted.
+ * Add Flow Director filters for a specific flow spec based on their
+ * protocol.  Returns 0 if the filters were successfully added.
  **/
-static int i40e_del_cloud_filter_ethtool(struct i40e_pf *pf,
-                                        struct ethtool_rxnfc *cmd)
+static int i40e_add_fdir_ethtool(struct i40e_vsi *vsi,
+                                struct ethtool_rxnfc *cmd)
 {
-       struct i40e_cloud_filter *rule, *filter = NULL;
+       struct i40e_rx_flow_userdef userdef;
        struct ethtool_rx_flow_spec *fsp;
-       struct hlist_node *node2;
+       struct i40e_fdir_filter *input;
+       u16 dest_vsi = 0, q_index = 0;
+       struct i40e_pf *pf;
+       int ret = -EINVAL;
+       u8 dest_ctl;
+
+       if (!vsi)
+               return -EINVAL;
+       pf = vsi->back;
+
+       if (!(pf->flags & I40E_FLAG_FD_SB_ENABLED))
+               return -EOPNOTSUPP;
+
+       if (pf->flags & I40E_FLAG_FD_SB_AUTO_DISABLED)
+               return -ENOSPC;
+
+       if (test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state) ||
+           test_bit(__I40E_RESET_INTR_RECEIVED, pf->state))
+               return -EBUSY;
+
+       if (test_bit(__I40E_FD_FLUSH_REQUESTED, pf->state))
+               return -EBUSY;
 
        fsp = (struct ethtool_rx_flow_spec *)&cmd->fs;
-       hlist_for_each_entry_safe(rule, node2,
-                                 &pf->cloud_filter_list, cloud_node) {
-               /* filter found */
-               if (rule->id == fsp->location)
-                       filter = rule;
 
-               /* bail out if we've passed the likely location in the list */
-               if (rule->id >= fsp->location)
-                       break;
+       /* Parse the user-defined field */
+       if (i40e_parse_rx_flow_user_data(fsp, &userdef))
+               return -EINVAL;
+
+       if (userdef.cloud_filter)
+               return i40e_add_cloud_filter_ethtool(vsi, cmd, &userdef);
+
+       /* Extended MAC field is not supported */
+       if (fsp->flow_type & FLOW_MAC_EXT)
+               return -EINVAL;
+
+       ret = i40e_check_fdir_input_set(vsi, fsp, &userdef);
+       if (ret)
+               return ret;
+
+       if (fsp->location >= (pf->hw.func_caps.fd_filters_best_effort +
+                             pf->hw.func_caps.fd_filters_guaranteed)) {
+               return -EINVAL;
        }
-       if (!filter)
-               return -ENOENT;
 
-       /* remove filter from the list even if failed to remove from device */
-       (void)i40e_add_del_cloud_filter(pf, filter, false);
-       hlist_del(&filter->cloud_node);
-       kfree(filter);
-       pf->num_cloud_filters--;
+       /* ring_cookie is either the drop index, or is a mask of the queue
+        * index and VF id we wish to target.
+        */
+       if (fsp->ring_cookie == RX_CLS_FLOW_DISC) {
+               dest_ctl = I40E_FILTER_PROGRAM_DESC_DEST_DROP_PACKET;
+       } else {
+               u32 ring = ethtool_get_flow_spec_ring(fsp->ring_cookie);
+               u8 vf = ethtool_get_flow_spec_ring_vf(fsp->ring_cookie);
+
+               if (!vf) {
+                       if (ring >= vsi->num_queue_pairs)
+                               return -EINVAL;
+                       dest_vsi = vsi->id;
+               } else {
+                       /* VFs are zero-indexed, so we subtract one here */
+                       vf--;
+
+                       if (vf >= pf->num_alloc_vfs)
+                               return -EINVAL;
+                       if (ring >= pf->vf[vf].num_queue_pairs)
+                               return -EINVAL;
+                       dest_vsi = pf->vf[vf].lan_vsi_id;
+               }
+               dest_ctl = I40E_FILTER_PROGRAM_DESC_DEST_DIRECT_PACKET_QINDEX;
+               q_index = ring;
+       }
+
+       input = kzalloc(sizeof(*input), GFP_KERNEL);
+       if (!input)
+               return -ENOMEM;
+
+       input->fd_id = fsp->location;
+       input->q_index = q_index;
+       input->dest_vsi = dest_vsi;
+       input->dest_ctl = dest_ctl;
+       input->fd_status = I40E_FILTER_PROGRAM_DESC_FD_STATUS_FD_ID;
+       input->cnt_index  = I40E_FD_SB_STAT_IDX(pf->hw.pf_id);
+       input->flow_type = fsp->flow_type & ~FLOW_EXT;
+       input->ip4_proto = fsp->h_u.usr_ip4_spec.proto;
+
+       /* Reverse the src and dest notion, since the HW expects them to be from
+        * Tx perspective where as the input from user is from Rx filter view.
+        */
+       input->dst_port = fsp->h_u.tcp_ip4_spec.psrc;
+       input->src_port = fsp->h_u.tcp_ip4_spec.pdst;
+       input->dst_ip = fsp->h_u.tcp_ip4_spec.ip4src;
+       input->src_ip = fsp->h_u.tcp_ip4_spec.ip4dst;
+
+       if (userdef.flex_filter) {
+               input->flex_filter = true;
+               input->flex_word = cpu_to_be16(userdef.flex_word);
+               input->flex_offset = userdef.flex_offset;
+       }
+
+       ret = i40e_add_del_fdir(vsi, input, true);
+       if (ret)
+               goto free_input;
+
+       /* Add the input filter to the fdir_filter_list, possibly replacing
+        * a previous filter. Do not free the input structure after adding it
+        * to the list as this would cause a use after free bug.
+        */
+       (void)i40e_del_cloud_filter_ethtool(pf, cmd);
+       i40e_update_ethtool_fdir_entry(vsi, input, fsp->location);
 
        return 0;
+
+free_input:
+       kfree(input);
+       return ret;
 }
 
 /**
@@ -4152,7 +5207,6 @@ static int i40e_del_cloud_filter_ethtool(struct i40e_pf *pf,
 static int i40e_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd)
 {
        struct i40e_netdev_priv *np = netdev_priv(netdev);
-       struct ethtool_rx_flow_spec *fsp;
        struct i40e_vsi *vsi = np->vsi;
        struct i40e_pf *pf = vsi->back;
        int ret = -EOPNOTSUPP;
@@ -4163,19 +5217,7 @@ static int i40e_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd)
                break;
 
        case ETHTOOL_SRXCLSRLINS:
-               /* if the user-def mask is non-zero, then something was set
-                * in the user-def value to ask us to set up a cloud filter
-                * specifying a target VF rather than flow director filter
-                */
-               fsp = (struct ethtool_rx_flow_spec *)&cmd->fs;
-               /* Following check qualifies it to be cloud filter */
-               if ((fsp->m_ext.data[0] == cpu_to_be32(~0)) &&
-                   (fsp->m_ext.data[1] == cpu_to_be32(~0))) {
-                       if (!(pf->flags & I40E_FLAG_MFP_ENABLED))
-                               ret = i40e_add_cloud_filter_ethtool(pf, cmd);
-               } else {
-                       ret = i40e_add_fdir_ethtool(vsi, cmd);
-               }
+               ret = i40e_add_fdir_ethtool(vsi, cmd);
                break;
 
        case ETHTOOL_SRXCLSRLDEL:
@@ -4450,7 +5492,7 @@ static int i40e_set_rxfh(struct net_device *netdev, const u32 *indir,
  * @dev: network interface device structure
  *
  * The get string set count and the string set should be matched for each
- * flag returned.  Add new strings for each flag to the i40e_priv_flags_strings
+ * flag returned.  Add new strings for each flag to the i40e_gstrings_priv_flags
  * array.
  *
  * Returns a u32 bitmap of flags.
@@ -4460,21 +5502,27 @@ static u32 i40e_get_priv_flags(struct net_device *dev)
        struct i40e_netdev_priv *np = netdev_priv(dev);
        struct i40e_vsi *vsi = np->vsi;
        struct i40e_pf *pf = vsi->back;
-       u32 ret_flags = 0;
-
-       ret_flags |= pf->flags & I40E_FLAG_MFP_ENABLED ?
-               I40E_PRIV_FLAGS_MFP_FLAG : 0;
-       ret_flags |= pf->flags & I40E_FLAG_LINK_POLLING_ENABLED ?
-               I40E_PRIV_FLAGS_LINKPOLL_FLAG : 0;
-       ret_flags |= pf->flags & I40E_FLAG_FD_ATR_ENABLED ?
-               I40E_PRIV_FLAGS_FD_ATR : 0;
-       ret_flags |= pf->flags & I40E_FLAG_VEB_STATS_ENABLED ?
-               I40E_PRIV_FLAGS_VEB_STATS : 0;
-       ret_flags |= pf->hw_disabled_flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE ?
-               0 : I40E_PRIV_FLAGS_HW_ATR_EVICT;
-       if (pf->hw.pf_id == 0) {
-               ret_flags |= pf->flags & I40E_FLAG_TRUE_PROMISC_SUPPORT ?
-                       I40E_PRIV_FLAGS_TRUE_PROMISC_SUPPORT : 0;
+       u32 i, j, ret_flags = 0;
+
+       for (i = 0; i < I40E_PRIV_FLAGS_STR_LEN; i++) {
+               const struct i40e_priv_flags *priv_flags;
+
+               priv_flags = &i40e_gstrings_priv_flags[i];
+
+               if (priv_flags->flag & pf->flags)
+                       ret_flags |= BIT(i);
+       }
+
+       if (pf->hw.pf_id != 0)
+               return ret_flags;
+
+       for (j = 0; j < I40E_GL_PRIV_FLAGS_STR_LEN; j++) {
+               const struct i40e_priv_flags *priv_flags;
+
+               priv_flags = &i40e_gl_gstrings_priv_flags[j];
+
+               if (priv_flags->flag & pf->flags)
+                       ret_flags |= BIT(i + j);
        }
 
        return ret_flags;
@@ -4490,54 +5538,87 @@ static int i40e_set_priv_flags(struct net_device *dev, u32 flags)
        struct i40e_netdev_priv *np = netdev_priv(dev);
        struct i40e_vsi *vsi = np->vsi;
        struct i40e_pf *pf = vsi->back;
-       u16 sw_flags = 0, valid_flags = 0;
-       bool reset_required = false;
-       bool promisc_change = false;
-       int ret;
+       u64 orig_flags, new_flags, changed_flags;
+       u32 i, j;
 
-       /* NOTE: MFP is not settable */
+       orig_flags = READ_ONCE(pf->flags);
+       new_flags = orig_flags;
 
-       if (flags & I40E_PRIV_FLAGS_LINKPOLL_FLAG)
-               pf->flags |= I40E_FLAG_LINK_POLLING_ENABLED;
-       else
-               pf->flags &= ~I40E_FLAG_LINK_POLLING_ENABLED;
+       for (i = 0; i < I40E_PRIV_FLAGS_STR_LEN; i++) {
+               const struct i40e_priv_flags *priv_flags;
+
+               priv_flags = &i40e_gstrings_priv_flags[i];
+
+               if (flags & BIT(i))
+                       new_flags |= priv_flags->flag;
+               else
+                       new_flags &= ~(priv_flags->flag);
+
+               /* If this is a read-only flag, it can't be changed */
+               if (priv_flags->read_only &&
+                   ((orig_flags ^ new_flags) & ~BIT(i)))
+                       return -EOPNOTSUPP;
+       }
+
+       if (pf->hw.pf_id != 0)
+               goto flags_complete;
+
+       for (j = 0; j < I40E_GL_PRIV_FLAGS_STR_LEN; j++) {
+               const struct i40e_priv_flags *priv_flags;
 
-       /* allow the user to control the state of the Flow
-        * Director ATR (Application Targeted Routing) feature
-        * of the driver
+               priv_flags = &i40e_gl_gstrings_priv_flags[j];
+
+               if (flags & BIT(i + j))
+                       new_flags |= priv_flags->flag;
+               else
+                       new_flags &= ~(priv_flags->flag);
+
+               /* If this is a read-only flag, it can't be changed */
+               if (priv_flags->read_only &&
+                   ((orig_flags ^ new_flags) & ~BIT(i)))
+                       return -EOPNOTSUPP;
+       }
+
+flags_complete:
+       /* Before we finalize any flag changes, we need to perform some
+        * checks to ensure that the changes are supported and safe.
         */
-       if (flags & I40E_PRIV_FLAGS_FD_ATR) {
-               pf->flags |= I40E_FLAG_FD_ATR_ENABLED;
-       } else {
-               pf->flags &= ~I40E_FLAG_FD_ATR_ENABLED;
-               pf->hw_disabled_flags |= I40E_FLAG_FD_ATR_ENABLED;
-
-               /* flush current ATR settings */
-               set_bit(__I40E_FD_FLUSH_REQUESTED, &pf->state);
-       }
-
-       if ((flags & I40E_PRIV_FLAGS_VEB_STATS) &&
-           !(pf->flags & I40E_FLAG_VEB_STATS_ENABLED)) {
-               pf->flags |= I40E_FLAG_VEB_STATS_ENABLED;
-               reset_required = true;
-       } else if (!(flags & I40E_PRIV_FLAGS_VEB_STATS) &&
-                  (pf->flags & I40E_FLAG_VEB_STATS_ENABLED)) {
-               pf->flags &= ~I40E_FLAG_VEB_STATS_ENABLED;
-               reset_required = true;
-       }
-
-       if (pf->hw.pf_id == 0) {
-               if ((flags & I40E_PRIV_FLAGS_TRUE_PROMISC_SUPPORT) &&
-                   !(pf->flags & I40E_FLAG_TRUE_PROMISC_SUPPORT)) {
-                       pf->flags |= I40E_FLAG_TRUE_PROMISC_SUPPORT;
-                       promisc_change = true;
-               } else if (!(flags & I40E_PRIV_FLAGS_TRUE_PROMISC_SUPPORT) &&
-                          (pf->flags & I40E_FLAG_TRUE_PROMISC_SUPPORT)) {
-                       pf->flags &= ~I40E_FLAG_TRUE_PROMISC_SUPPORT;
-                       promisc_change = true;
-               }
+
+       /* ATR eviction is not supported on all devices */
+       if ((new_flags & I40E_FLAG_HW_ATR_EVICT_ENABLED) &&
+           !(pf->hw_features & I40E_HW_ATR_EVICT_CAPABLE))
+               return -EOPNOTSUPP;
+
+       /* Compare and exchange the new flags into place. If we failed, that
+        * is if cmpxchg64 returns anything but the old value, this means that
+        * something else has modified the flags variable since we copied it
+        * originally. We'll just punt with an error and log something in the
+        * message buffer.
+        */
+       if (cmpxchg64(&pf->flags, orig_flags, new_flags) != orig_flags) {
+               dev_warn(&pf->pdev->dev,
+                        "Unable to update pf->flags as it was modified by another thread...\n");
+               return -EAGAIN;
+       }
+
+       changed_flags = orig_flags ^ new_flags;
+
+       /* Process any additional changes needed as a result of flag changes.
+        * The changed_flags value reflects the list of bits that were
+        * changed in the code above.
+        */
+
+       /* Flush current ATR settings if ATR was disabled */
+       if ((changed_flags & I40E_FLAG_FD_ATR_ENABLED) &&
+           !(pf->flags & I40E_FLAG_FD_ATR_ENABLED)) {
+               pf->flags |= I40E_FLAG_FD_ATR_AUTO_DISABLED;
+               set_bit(__I40E_FD_FLUSH_REQUESTED, pf->state);
        }
-       if (promisc_change) {
+
+       if (changed_flags & I40E_FLAG_TRUE_PROMISC_SUPPORT) {
+               u16 sw_flags = 0, valid_flags = 0;
+               int ret;
+
                if (!(pf->flags & I40E_FLAG_TRUE_PROMISC_SUPPORT))
                        sw_flags = I40E_AQ_SET_SWITCH_CFG_PROMISC;
                valid_flags = I40E_AQ_SET_SWITCH_CFG_PROMISC;
@@ -4553,20 +5634,173 @@ static int i40e_set_priv_flags(struct net_device *dev, u32 flags)
                }
        }
 
-       if ((flags & I40E_PRIV_FLAGS_HW_ATR_EVICT) &&
-           (pf->flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE))
-               pf->hw_disabled_flags &= ~I40E_FLAG_HW_ATR_EVICT_CAPABLE;
-       else
-               pf->hw_disabled_flags |= I40E_FLAG_HW_ATR_EVICT_CAPABLE;
-
-       /* if needed, issue reset to cause things to take effect */
-       if (reset_required)
-               i40e_do_reset(pf, BIT(__I40E_PF_RESET_REQUESTED));
+       /* Issue reset to cause things to take effect, as additional bits
+        * are added we will need to create a mask of bits requiring reset
+        */
+       if (changed_flags & (I40E_FLAG_VEB_STATS_ENABLED |
+                            I40E_FLAG_LEGACY_RX |
+                            I40E_FLAG_SOURCE_PRUNING_DISABLED))
+               i40e_do_reset(pf, BIT(__I40E_PF_RESET_REQUESTED), true);
 
        return 0;
 }
 #endif /* HAVE_ETHTOOL_GET_SSET_COUNT */
 
+#ifdef ETHTOOL_GMODULEINFO
+
+/**
+ * i40e_get_module_info - get (Q)SFP+ module type info
+ * @netdev: network interface device structure
+ * @modinfo: module EEPROM size and layout information structure
+ **/
+static int i40e_get_module_info(struct net_device *netdev,
+                               struct ethtool_modinfo *modinfo)
+{
+       i40e_status status;
+       struct i40e_netdev_priv *np = netdev_priv(netdev);
+       struct i40e_vsi *vsi = np->vsi;
+       struct i40e_pf *pf = vsi->back;
+       struct i40e_hw *hw = &pf->hw;
+       u32 sff8472_comp = 0;
+       u32 sff8472_swap = 0;
+       u32 sff8636_rev = 0;
+       u8 type;
+
+       /* Check if firmware supports reading module EEPROM. */
+       if (!(hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE)) {
+               netdev_err(vsi->netdev, "Module EEPROM memory read not supported. Please update the NVM image.\n");
+               return -EINVAL;
+       }
+
+       status = i40e_update_link_info(hw);
+       if (status)
+               return -EIO;
+
+       if (hw->phy.link_info.phy_type == I40E_PHY_TYPE_EMPTY) {
+               netdev_err(vsi->netdev, "Cannot read module EEPROM memory. No module connected.\n");
+               return -EINVAL;
+       }
+
+       type = hw->phy.link_info.module_type[0];
+
+       switch (type) {
+       case I40E_MODULE_TYPE_SFP:
+               status = i40e_aq_get_phy_register(hw,
+                               I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
+                               I40E_I2C_EEPROM_DEV_ADDR,
+                               I40E_MODULE_SFF_8472_COMP,
+                               &sff8472_comp, NULL);
+               if (status)
+                       return -EIO;
+
+               status = i40e_aq_get_phy_register(hw,
+                               I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
+                               I40E_I2C_EEPROM_DEV_ADDR,
+                               I40E_MODULE_SFF_8472_SWAP,
+                               &sff8472_swap, NULL);
+               if (status)
+                       return -EIO;
+
+               /* Check if the module requires address swap to access
+                * the other EEPROM memory page.
+                */
+               if (sff8472_swap & I40E_MODULE_SFF_ADDR_MODE) {
+                       netdev_warn(vsi->netdev, "Module address swap to access page 0xA2 is not supported.\n");
+                       modinfo->type = ETH_MODULE_SFF_8079;
+                       modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
+               } else if (sff8472_comp == 0x00) {
+                       /* Module is not SFF-8472 compliant */
+                       modinfo->type = ETH_MODULE_SFF_8079;
+                       modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
+               } else {
+                       modinfo->type = ETH_MODULE_SFF_8472;
+                       modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
+               }
+               break;
+       case I40E_MODULE_TYPE_QSFP_PLUS:
+               /* Read from memory page 0. */
+               status = i40e_aq_get_phy_register(hw,
+                               I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
+                               0,
+                               I40E_MODULE_REVISION_ADDR,
+                               &sff8636_rev, NULL);
+               if (status)
+                       return -EIO;
+               /* Determine revision compliance byte */
+               if (sff8636_rev > 0x02) {
+                       /* Module is SFF-8636 compliant */
+                       modinfo->type = ETH_MODULE_SFF_8636;
+                       modinfo->eeprom_len = I40E_MODULE_QSFP_MAX_LEN;
+               } else {
+                       modinfo->type = ETH_MODULE_SFF_8436;
+                       modinfo->eeprom_len = I40E_MODULE_QSFP_MAX_LEN;
+               }
+               break;
+       case I40E_MODULE_TYPE_QSFP28:
+               modinfo->type = ETH_MODULE_SFF_8636;
+               modinfo->eeprom_len = I40E_MODULE_QSFP_MAX_LEN;
+               break;
+       default:
+               netdev_err(vsi->netdev, "Module type unrecognized\n");
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/**
+ * i40e_get_module_eeprom - fills buffer with (Q)SFP+ module memory contents
+ * @netdev: network interface device structure
+ * @ee: EEPROM dump request structure
+ * @data: buffer to be filled with EEPROM contents
+ **/
+static int i40e_get_module_eeprom(struct net_device *netdev,
+                                 struct ethtool_eeprom *ee,
+                                 u8 *data)
+{
+       i40e_status status;
+       struct i40e_netdev_priv *np = netdev_priv(netdev);
+       struct i40e_vsi *vsi = np->vsi;
+       struct i40e_pf *pf = vsi->back;
+       struct i40e_hw *hw = &pf->hw;
+       bool is_sfp = false;
+       u32 value = 0;
+       int i;
+
+       if (!ee || !ee->len || !data)
+               return -EINVAL;
+
+       if (hw->phy.link_info.module_type[0] == I40E_MODULE_TYPE_SFP)
+               is_sfp = true;
+
+       for (i = 0; i < ee->len; i++) {
+               u32 offset = i + ee->offset;
+               u32 addr = is_sfp ? I40E_I2C_EEPROM_DEV_ADDR : 0;
+
+               /* Check if we need to access the other memory page */
+               if (is_sfp) {
+                       if (offset >= ETH_MODULE_SFF_8079_LEN) {
+                               offset -= ETH_MODULE_SFF_8079_LEN;
+                               addr = I40E_I2C_EEPROM_DEV_ADDR2;
+                       }
+               } else {
+                       while (offset >= ETH_MODULE_SFF_8436_LEN) {
+                               /* Compute memory page number and offset. */
+                               offset -= ETH_MODULE_SFF_8436_LEN / 2;
+                               addr++;
+                       }
+               }
+
+               status = i40e_aq_get_phy_register(hw,
+                               I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
+                               addr, offset, &value, NULL);
+               if (status)
+                       return -EIO;
+               data[i] = value;
+       }
+       return 0;
+}
+#endif /* ETHTOOL_GMODULEINFO */
+
 static const struct ethtool_ops i40e_ethtool_ops = {
        .get_settings           = i40e_get_settings,
        .set_settings           = i40e_set_settings,
@@ -4643,6 +5877,10 @@ static const struct ethtool_ops i40e_ethtool_ops = {
        .get_channels           = i40e_get_channels,
        .set_channels           = i40e_set_channels,
 #endif
+#ifdef ETHTOOL_GMODULEINFO
+       .get_module_info        = i40e_get_module_info,
+       .get_module_eeprom      = i40e_get_module_eeprom,
+#endif
 #ifdef HAVE_ETHTOOL_GET_TS_INFO
        .get_ts_info            = i40e_get_ts_info,
 #endif /* HAVE_ETHTOOL_GET_TS_INFO */
@@ -4651,6 +5889,10 @@ static const struct ethtool_ops i40e_ethtool_ops = {
        .set_per_queue_coalesce = i40e_set_per_queue_coalesce,
 #endif /* ETHTOOL_PERQUEUE */
 #endif /* HAVE_RHEL6_ETHTOOL_OPS_EXT_STRUCT */
+#ifdef ETHTOOL_GLINKSETTINGS
+       .get_link_ksettings = i40e_get_link_settings,
+       .set_link_ksettings = i40e_set_link_settings,
+#endif /* ETHTOOL_GLINKSETTINGS */
 };
 
 #ifdef HAVE_RHEL6_ETHTOOL_OPS_EXT_STRUCT
@@ -4666,6 +5908,10 @@ static const struct ethtool_ops_ext i40e_ethtool_ops_ext = {
        .get_rxfh               = i40e_get_rxfh,
        .set_rxfh               = i40e_set_rxfh,
 #endif /* ETHTOOL_GRSSH && ETHTOOL_SRSSH */
+#ifdef ETHTOOL_GMODULEINFO
+       .get_module_info        = i40e_get_module_info,
+       .get_module_eeprom      = i40e_get_module_eeprom,
+#endif
 };
 
 void i40e_set_ethtool_ops(struct net_device *netdev)
similarity index 85%
rename from i40e-dkms/i40e-1.6.42/src/i40e_main.c
rename to i40e-dkms/i40e-2.1.26/src/i40e_main.c
index 4dd9457eecae5b659b7f6dbd348f394ac3be5b96..4c70594534bcf579f4144af3a2b033ff803b3662 100644 (file)
 #ifdef HAVE_UDP_ENC_RX_OFFLOAD
 #include <net/udp_tunnel.h>
 #endif
+/* All i40e tracepoints are defined by the include below, which
+ * must be included exactly once across the whole kernel with
+ * CREATE_TRACE_POINTS defined
+ */
+#define CREATE_TRACE_POINTS
+#include "i40e_trace.h"
 
 char i40e_driver_name[] = "i40e";
 static const char i40e_driver_string[] =
@@ -52,9 +58,9 @@ static const char i40e_driver_string[] =
 
 #define DRV_VERSION_DESC ""
 
-#define DRV_VERSION_MAJOR 1
-#define DRV_VERSION_MINOR 6
-#define DRV_VERSION_BUILD 42
+#define DRV_VERSION_MAJOR 2
+#define DRV_VERSION_MINOR 1
+#define DRV_VERSION_BUILD 26
 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \
        __stringify(DRV_VERSION_MINOR) "." \
        __stringify(DRV_VERSION_BUILD) \
@@ -64,7 +70,7 @@ static const char i40e_copyright[] = "Copyright(c) 2013 - 2017 Intel Corporation
 
 /* a bit of forward declarations */
 static void i40e_vsi_reinit_locked(struct i40e_vsi *vsi);
-static void i40e_handle_reset_warning(struct i40e_pf *pf);
+static void i40e_handle_reset_warning(struct i40e_pf *pf, bool lock_acquired);
 static int i40e_add_vsi(struct i40e_vsi *vsi);
 static int i40e_add_veb(struct i40e_veb *veb, struct i40e_vsi *vsi);
 static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit);
@@ -72,6 +78,9 @@ static int i40e_setup_misc_vector(struct i40e_pf *pf);
 static void i40e_determine_queue_usage(struct i40e_pf *pf);
 static int i40e_setup_pf_filter_control(struct i40e_pf *pf);
 static void i40e_clear_rss_config_user(struct i40e_vsi *vsi);
+static void i40e_prep_for_reset(struct i40e_pf *pf, bool lock_acquired);
+static int i40e_reset(struct i40e_pf *pf);
+static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired);
 static void i40e_fdir_sb_setup(struct i40e_pf *pf);
 static int i40e_veb_get_bw_info(struct i40e_veb *veb);
 /* i40e_pci_tbl - PCI Device ID Table
@@ -93,14 +102,12 @@ static const struct pci_device_id i40e_pci_tbl[] = {
        {PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T4), 0},
        {PCI_VDEVICE(INTEL, I40E_DEV_ID_20G_KR2), 0},
        {PCI_VDEVICE(INTEL, I40E_DEV_ID_20G_KR2_A), 0},
-#ifdef X722_DEV_SUPPORT
        {PCI_VDEVICE(INTEL, I40E_DEV_ID_KX_X722), 0},
        {PCI_VDEVICE(INTEL, I40E_DEV_ID_QSFP_X722), 0},
        {PCI_VDEVICE(INTEL, I40E_DEV_ID_SFP_X722), 0},
        {PCI_VDEVICE(INTEL, I40E_DEV_ID_1G_BASE_T_X722), 0},
        {PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T_X722), 0},
        {PCI_VDEVICE(INTEL, I40E_DEV_ID_SFP_I_X722), 0},
-#endif /* X722_DEV_SUPPORT */
        {PCI_VDEVICE(INTEL, I40E_DEV_ID_25G_B), 0},
        {PCI_VDEVICE(INTEL, I40E_DEV_ID_25G_SFP28), 0},
        /* required last entry */
@@ -237,6 +244,22 @@ struct i40e_vsi *i40e_find_vsi_from_id(struct i40e_pf *pf, u16 id)
        return NULL;
 }
 
+/**
+ * i40e_find_vsi_from_seid - searches for the vsi with the given seid
+ * @pf - the pf structure to search for the vsi
+ * @seid - seid of the vsi it is searching for
+ **/
+struct i40e_vsi *i40e_find_vsi_from_seid(struct i40e_pf *pf, u16 seid)
+{
+       int i;
+
+       for (i = 0; i < pf->num_alloc_vsi; i++)
+               if (pf->vsi[i] && (pf->vsi[i]->seid == seid))
+                       return pf->vsi[i];
+
+       return NULL;
+}
+
 /**
  * i40e_service_event_schedule - Schedule the service task to wake up
  * @pf: board private structure
@@ -245,8 +268,8 @@ struct i40e_vsi *i40e_find_vsi_from_id(struct i40e_pf *pf, u16 id)
  **/
 void i40e_service_event_schedule(struct i40e_pf *pf)
 {
-       if (!test_bit(__I40E_DOWN, &pf->state) &&
-           !test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state))
+       if (!test_bit(__I40E_DOWN, pf->state) &&
+           !test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state))
                queue_work(i40e_wq, &pf->service_task);
 }
 
@@ -258,11 +281,7 @@ void i40e_service_event_schedule(struct i40e_pf *pf)
  * device is munged, not just the one netdev port, so go for the full
  * reset.
  **/
-#ifdef I40E_FCOE
-void i40e_tx_timeout(struct net_device *netdev)
-#else
 static void i40e_tx_timeout(struct net_device *netdev)
-#endif
 {
        struct i40e_netdev_priv *np = netdev_priv(netdev);
        struct i40e_vsi *vsi = np->vsi;
@@ -338,13 +357,13 @@ static void i40e_tx_timeout(struct net_device *netdev)
 
        switch (pf->tx_timeout_recovery_level) {
        case 1:
-               set_bit(__I40E_PF_RESET_REQUESTED, &pf->state);
+               set_bit(__I40E_PF_RESET_REQUESTED, pf->state);
                break;
        case 2:
-               set_bit(__I40E_CORE_RESET_REQUESTED, &pf->state);
+               set_bit(__I40E_CORE_RESET_REQUESTED, pf->state);
                break;
        case 3:
-               set_bit(__I40E_GLOBAL_RESET_REQUESTED, &pf->state);
+               set_bit(__I40E_GLOBAL_RESET_REQUESTED, pf->state);
                break;
        default:
                netdev_err(netdev, "tx_timeout recovery unsuccessful\n");
@@ -386,15 +405,14 @@ struct net_device_stats *i40e_get_vsi_stats_struct(struct i40e_vsi *vsi)
  * The statistics are actually updated from the service task.
  **/
 #ifdef HAVE_NDO_GET_STATS64
-#ifdef I40E_FCOE
-struct rtnl_link_stats64 *i40e_get_netdev_stats_struct(
-                                            struct net_device *netdev,
-                                            struct rtnl_link_stats64 *stats)
+#ifdef HAVE_VOID_NDO_GET_STATS64
+static void i40e_get_netdev_stats_struct(struct net_device *netdev,
+                                        struct rtnl_link_stats64 *stats)
 #else
 static struct rtnl_link_stats64 *i40e_get_netdev_stats_struct(
                                             struct net_device *netdev,
                                             struct rtnl_link_stats64 *stats)
-#endif
+#endif /* HAVE_VOID_NDO_GET_STATS64 */
 {
        struct i40e_netdev_priv *np = netdev_priv(netdev);
        struct i40e_ring *tx_ring, *rx_ring;
@@ -402,11 +420,19 @@ static struct rtnl_link_stats64 *i40e_get_netdev_stats_struct(
        struct rtnl_link_stats64 *vsi_stats = i40e_get_vsi_stats_struct(vsi);
        int i;
 
-       if (test_bit(__I40E_DOWN, &vsi->state))
+       if (test_bit(__I40E_VSI_DOWN, vsi->state))
+#ifdef HAVE_VOID_NDO_GET_STATS64
+               return;
+#else
                return stats;
+#endif /* HAVE_VOID_NDO_GET_STATS_64 */
 
        if (!vsi->tx_rings)
+#ifdef HAVE_VOID_NDO_GET_STATS64
+               return;
+#else
                return stats;
+#endif /* HAVE_VOID_NDO_GET_STATS_64 */
 
        rcu_read_lock();
        for (i = 0; i < vsi->num_queue_pairs; i++) {
@@ -446,23 +472,21 @@ static struct rtnl_link_stats64 *i40e_get_netdev_stats_struct(
        stats->rx_dropped       = vsi_stats->rx_dropped;
        stats->rx_crc_errors    = vsi_stats->rx_crc_errors;
        stats->rx_length_errors = vsi_stats->rx_length_errors;
+#ifndef HAVE_VOID_NDO_GET_STATS64
 
-       return stats;
+               return stats;
+#endif
 }
 #else
-#ifdef I40E_FCOE
-struct net_device_stats *i40e_get_netdev_stats_struct(struct net_device *netdev)
-#else
 static struct net_device_stats *i40e_get_netdev_stats_struct(
                                                      struct net_device *netdev)
-#endif
 {
        struct i40e_netdev_priv *np = netdev_priv(netdev);
        struct i40e_vsi *vsi = np->vsi;
 
        return i40e_get_vsi_stats_struct(vsi);
 }
-#endif
+#endif /* HAVE_NDO_GET_STATS64 */
 
 /**
  * i40e_vsi_reset_stats - Resets all stats of the given vsi
@@ -536,6 +560,9 @@ void i40e_pf_reset_stats(struct i40e_pf *pf)
        pf->rx_udp_cso_err = 0;
        pf->rx_sctp_cso_err = 0;
        pf->rx_ip4_cso_err = 0;
+       pf->hw_csum_rx_vxlan = 0;
+       pf->hw_csum_rx_geneve = 0;
+       pf->hw_csum_rx_outer = 0;
 #endif
 }
 
@@ -596,6 +623,20 @@ static void i40e_stat_update32(struct i40e_hw *hw, u32 reg,
                *stat = (u32)((new_data + BIT_ULL(32)) - *offset);
 }
 
+/**
+ * i40e_stat_update_and_clear32 - read and clear hw reg, update a 32 bit stat
+ * @hw: ptr to the hardware info
+ * @reg: the hw reg to read and clear
+ * @stat: ptr to the stat
+ **/
+static void i40e_stat_update_and_clear32(struct i40e_hw *hw, u32 reg, u64 *stat)
+{
+       u32 new_data = rd32(hw, reg);
+
+       wr32(hw, reg, 1); /* must write a nonzero value to clear register */
+       *stat += new_data;
+}
+
 /**
  * i40e_update_eth_stats - Update VSI-specific ethernet statistics counters.
  * @vsi: the VSI to be updated
@@ -739,55 +780,6 @@ static void i40e_update_veb_stats(struct i40e_veb *veb)
        veb->stat_offsets_loaded = true;
 }
 
-#ifdef I40E_FCOE
-/**
- * i40e_update_fcoe_stats - Update FCoE-specific ethernet statistics counters.
- * @vsi: the VSI that is capable of doing FCoE
- **/
-static void i40e_update_fcoe_stats(struct i40e_vsi *vsi)
-{
-       struct i40e_pf *pf = vsi->back;
-       struct i40e_hw *hw = &pf->hw;
-       struct i40e_fcoe_stats *ofs;
-       struct i40e_fcoe_stats *fs;     /* device's eth stats */
-       int idx;
-
-       if (vsi->type != I40E_VSI_FCOE)
-               return;
-
-       idx = hw->pf_id + I40E_FCOE_PF_STAT_OFFSET;
-       fs = &vsi->fcoe_stats;
-       ofs = &vsi->fcoe_stats_offsets;
-
-       i40e_stat_update32(hw, I40E_GL_FCOEPRC(idx),
-                          vsi->fcoe_stat_offsets_loaded,
-                          &ofs->rx_fcoe_packets, &fs->rx_fcoe_packets);
-       i40e_stat_update48(hw, I40E_GL_FCOEDWRCH(idx), I40E_GL_FCOEDWRCL(idx),
-                          vsi->fcoe_stat_offsets_loaded,
-                          &ofs->rx_fcoe_dwords, &fs->rx_fcoe_dwords);
-       i40e_stat_update32(hw, I40E_GL_FCOERPDC(idx),
-                          vsi->fcoe_stat_offsets_loaded,
-                          &ofs->rx_fcoe_dropped, &fs->rx_fcoe_dropped);
-       i40e_stat_update32(hw, I40E_GL_FCOEPTC(idx),
-                          vsi->fcoe_stat_offsets_loaded,
-                          &ofs->tx_fcoe_packets, &fs->tx_fcoe_packets);
-       i40e_stat_update48(hw, I40E_GL_FCOEDWTCH(idx), I40E_GL_FCOEDWTCL(idx),
-                          vsi->fcoe_stat_offsets_loaded,
-                          &ofs->tx_fcoe_dwords, &fs->tx_fcoe_dwords);
-       i40e_stat_update32(hw, I40E_GL_FCOECRC(idx),
-                          vsi->fcoe_stat_offsets_loaded,
-                          &ofs->fcoe_bad_fccrc, &fs->fcoe_bad_fccrc);
-       i40e_stat_update32(hw, I40E_GL_FCOELAST(idx),
-                          vsi->fcoe_stat_offsets_loaded,
-                          &ofs->fcoe_last_error, &fs->fcoe_last_error);
-       i40e_stat_update32(hw, I40E_GL_FCOEDDPC(idx),
-                          vsi->fcoe_stat_offsets_loaded,
-                          &ofs->fcoe_ddp_count, &fs->fcoe_ddp_count);
-
-       vsi->fcoe_stat_offsets_loaded = true;
-}
-
-#endif
 /**
  * i40e_update_vsi_stats - Update the vsi statistics counters.
  * @vsi: the VSI to be updated
@@ -811,7 +803,6 @@ static void i40e_update_vsi_stats(struct i40e_vsi *vsi)
        struct i40e_eth_stats *oes;
        struct i40e_eth_stats *es;     /* device's eth stats */
        u32 tx_restart, tx_busy;
-       u64 tx_lost_interrupt;
        struct i40e_ring *p;
        u32 rx_page, rx_buf;
        u64 bytes, packets;
@@ -824,8 +815,8 @@ static void i40e_update_vsi_stats(struct i40e_vsi *vsi)
        u64 tx_p, tx_b;
        u16 q;
 
-       if (test_bit(__I40E_DOWN, &vsi->state) ||
-           test_bit(__I40E_CONFIG_BUSY, &pf->state))
+       if (test_bit(__I40E_VSI_DOWN, vsi->state) ||
+           test_bit(__I40E_CONFIG_BUSY, pf->state))
                return;
 
        ns = i40e_get_vsi_stats_struct(vsi);
@@ -839,7 +830,6 @@ static void i40e_update_vsi_stats(struct i40e_vsi *vsi)
        rx_b = rx_p = 0;
        tx_b = tx_p = 0;
        tx_restart = tx_busy = tx_linearize = tx_force_wb = 0;
-       tx_lost_interrupt = 0;
        rx_page = 0;
        rx_buf = 0;
        rcu_read_lock();
@@ -862,8 +852,6 @@ static void i40e_update_vsi_stats(struct i40e_vsi *vsi)
                tx_busy += p->tx_stats.tx_busy;
                tx_linearize += p->tx_stats.tx_linearize;
                tx_force_wb += p->tx_stats.tx_force_wb;
-               tx_lost_interrupt += p->tx_stats.tx_lost_interrupt;
-
                /* Rx queue is part of the same block as Tx queue */
                p = &p[1];
 #ifdef HAVE_NDO_GET_STATS64
@@ -885,7 +873,6 @@ static void i40e_update_vsi_stats(struct i40e_vsi *vsi)
        vsi->tx_busy = tx_busy;
        vsi->tx_linearize = tx_linearize;
        vsi->tx_force_wb = tx_force_wb;
-       vsi->tx_lost_interrupt = tx_lost_interrupt;
        vsi->rx_page_failed = rx_page;
        vsi->rx_buf_failed = rx_buf;
 
@@ -893,7 +880,6 @@ static void i40e_update_vsi_stats(struct i40e_vsi *vsi)
        ns->rx_bytes = rx_b;
        ns->tx_packets = tx_p;
        ns->tx_bytes = tx_b;
-
        /* update netdev stats from eth stats */
        i40e_update_eth_stats(vsi);
        ons->tx_errors = oes->tx_errors;
@@ -1104,18 +1090,15 @@ static void i40e_update_pf_stats(struct i40e_pf *pf)
                           &osd->rx_jabber, &nsd->rx_jabber);
 
        /* FDIR stats */
-       i40e_stat_update32(hw,
-                          I40E_GLQF_PCNT(I40E_FD_ATR_STAT_IDX(pf->hw.pf_id)),
-                          pf->stat_offsets_loaded,
-                          &osd->fd_atr_match, &nsd->fd_atr_match);
-       i40e_stat_update32(hw,
-                          I40E_GLQF_PCNT(I40E_FD_SB_STAT_IDX(pf->hw.pf_id)),
-                          pf->stat_offsets_loaded,
-                          &osd->fd_sb_match, &nsd->fd_sb_match);
-       i40e_stat_update32(hw,
-                     I40E_GLQF_PCNT(I40E_FD_ATR_TUNNEL_STAT_IDX(pf->hw.pf_id)),
-                     pf->stat_offsets_loaded,
-                     &osd->fd_atr_tunnel_match, &nsd->fd_atr_tunnel_match);
+       i40e_stat_update_and_clear32(hw,
+                       I40E_GLQF_PCNT(I40E_FD_ATR_STAT_IDX(hw->pf_id)),
+                       &nsd->fd_atr_match);
+       i40e_stat_update_and_clear32(hw,
+                       I40E_GLQF_PCNT(I40E_FD_SB_STAT_IDX(hw->pf_id)),
+                       &nsd->fd_sb_match);
+       i40e_stat_update_and_clear32(hw,
+                       I40E_GLQF_PCNT(I40E_FD_ATR_TUNNEL_STAT_IDX(hw->pf_id)),
+                       &nsd->fd_atr_tunnel_match);
 
        val = rd32(hw, I40E_PRTPM_EEE_STAT);
        nsd->tx_lpi_status =
@@ -1131,16 +1114,14 @@ static void i40e_update_pf_stats(struct i40e_pf *pf)
                           pf->stat_offsets_loaded,
                           &osd->rx_lpi_count, &nsd->rx_lpi_count);
 
-       if (pf->hw_disabled_flags & I40E_FLAG_FD_SB_ENABLED)
-               nsd->fd_sb_status = false;
-       else if (pf->flags & I40E_FLAG_FD_SB_ENABLED)
+       if (pf->flags & I40E_FLAG_FD_SB_ENABLED &&
+           !(pf->flags & I40E_FLAG_FD_SB_AUTO_DISABLED))
                nsd->fd_sb_status = true;
        else
                nsd->fd_sb_status = false;
 
-       if (pf->hw_disabled_flags & I40E_FLAG_FD_ATR_ENABLED)
-               nsd->fd_atr_status = false;
-       else if (pf->flags & I40E_FLAG_FD_ATR_ENABLED)
+       if (pf->flags & I40E_FLAG_FD_ATR_ENABLED &&
+           !(pf->flags & I40E_FLAG_FD_ATR_AUTO_DISABLED))
                nsd->fd_atr_status = true;
        else
                nsd->fd_atr_status = false;
@@ -1162,9 +1143,6 @@ void i40e_update_stats(struct i40e_vsi *vsi)
                i40e_update_pf_stats(pf);
 
        i40e_update_vsi_stats(vsi);
-#ifdef I40E_FCOE
-       i40e_update_fcoe_stats(vsi);
-#endif
 }
 
 /**
@@ -1286,7 +1264,9 @@ static int i40e_correct_mac_vlan_filters(struct i40e_vsi *vsi,
                                         struct hlist_head *tmp_del_list,
                                         int vlan_filters)
 {
+       s16 pvid = le16_to_cpu(vsi->info.pvid);
        struct i40e_mac_filter *f, *add_head;
+       struct i40e_new_mac_filter *new;
        struct hlist_node *h;
        int bkt, new_vlan;
 
@@ -1305,13 +1285,13 @@ static int i40e_correct_mac_vlan_filters(struct i40e_vsi *vsi,
         */
 
        /* Update the filters about to be added in place */
-       hlist_for_each_entry(f, tmp_add_list, hlist) {
-               if (vsi->info.pvid && f->vlan != vsi->info.pvid)
-                       f->vlan = vsi->info.pvid;
-               else if (vlan_filters && f->vlan == I40E_VLAN_ANY)
-                       f->vlan = 0;
-               else if (!vlan_filters && f->vlan == 0)
-                       f->vlan = I40E_VLAN_ANY;
+       hlist_for_each_entry(new, tmp_add_list, hlist) {
+               if (pvid && new->f->vlan != pvid)
+                       new->f->vlan = pvid;
+               else if (vlan_filters && new->f->vlan == I40E_VLAN_ANY)
+                       new->f->vlan = 0;
+               else if (!vlan_filters && new->f->vlan == 0)
+                       new->f->vlan = I40E_VLAN_ANY;
        }
 
        /* Update the remaining active filters */
@@ -1321,12 +1301,12 @@ static int i40e_correct_mac_vlan_filters(struct i40e_vsi *vsi,
                 * order to avoid duplicating code for adding the new filter
                 * then deleting the old filter.
                 */
-               if ((vsi->info.pvid && f->vlan != vsi->info.pvid) ||
+               if ((pvid && f->vlan != pvid) ||
                    (vlan_filters && f->vlan == I40E_VLAN_ANY) ||
                    (!vlan_filters && f->vlan == 0)) {
                        /* Determine the new vlan we will be adding */
-                       if (vsi->info.pvid)
-                               new_vlan = vsi->info.pvid;
+                       if (pvid)
+                               new_vlan = pvid;
                        else if (vlan_filters)
                                new_vlan = 0;
                        else
@@ -1337,9 +1317,16 @@ static int i40e_correct_mac_vlan_filters(struct i40e_vsi *vsi,
                        if (!add_head)
                                return -ENOMEM;
 
-                       /* Put the replacement filter into the add list */
-                       hash_del(&add_head->hlist);
-                       hlist_add_head(&add_head->hlist, tmp_add_list);
+                       /* Create a temporary i40e_new_mac_filter */
+                       new = kzalloc(sizeof(*new), GFP_ATOMIC);
+                       if (!new)
+                               return -ENOMEM;
+
+                       new->f = add_head;
+                       new->state = add_head->state;
+
+                       /* Add the new filter to the tmp list */
+                       hlist_add_head(&new->hlist, tmp_add_list);
 
                        /* Put the original filter into the delete list */
                        f->state = I40E_FILTER_REMOVE;
@@ -1424,7 +1411,7 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
                 * to failed, so we don't bother to try sending the filter
                 * to the hardware.
                 */
-               if (test_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state))
+               if (test_bit(__I40E_VSI_OVERFLOW_PROMISC, vsi->state))
                        f->state = I40E_FILTER_FAILED;
                else
                        f->state = I40E_FILTER_NEW;
@@ -1472,18 +1459,20 @@ void __i40e_del_filter(struct i40e_vsi *vsi, struct i40e_mac_filter *f)
        if (!f)
                return;
 
+       /* If the filter was never added to firmware then we can just delete it
+        * directly and we don't want to set the status to remove or else an
+        * admin queue command will unnecessarily fire.
+        */
        if ((f->state == I40E_FILTER_FAILED) ||
            (f->state == I40E_FILTER_NEW)) {
-               /* this one never got added by the FW. Just remove it,
-                * no need to sync anything.
-                */
                hash_del(&f->hlist);
                kfree(f);
        } else {
                f->state = I40E_FILTER_REMOVE;
-               vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
-               vsi->back->flags |= I40E_FLAG_FILTER_SYNC;
        }
+
+       vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
+       vsi->back->flags |= I40E_FLAG_FILTER_SYNC;
 }
 
 /**
@@ -1583,11 +1572,7 @@ int i40e_del_mac_filter(struct i40e_vsi *vsi, const u8 *macaddr)
  *
  * Returns 0 on success, negative on failure
  **/
-#ifdef I40E_FCOE
-int i40e_set_mac(struct net_device *netdev, void *p)
-#else
 static int i40e_set_mac(struct net_device *netdev, void *p)
-#endif
 {
        struct i40e_netdev_priv *np = netdev_priv(netdev);
        struct i40e_vsi *vsi = np->vsi;
@@ -1604,8 +1589,8 @@ static int i40e_set_mac(struct net_device *netdev, void *p)
                return 0;
        }
 
-       if (test_bit(__I40E_DOWN, &vsi->back->state) ||
-           test_bit(__I40E_RESET_RECOVERY_PENDING, &vsi->back->state))
+       if (test_bit(__I40E_DOWN, vsi->back->state) ||
+           test_bit(__I40E_RESET_RECOVERY_PENDING, vsi->back->state))
                return -EADDRNOTAVAIL;
 
        if (ether_addr_equal(hw->mac.addr, addr->sa_data))
@@ -1647,17 +1632,10 @@ static int i40e_set_mac(struct net_device *netdev, void *p)
  *
  * Setup VSI queue mapping for enabled traffic classes.
  **/
-#ifdef I40E_FCOE
-void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi,
-                             struct i40e_vsi_context *ctxt,
-                             u8 enabled_tc,
-                             bool is_add)
-#else
 static void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi,
                                     struct i40e_vsi_context *ctxt,
                                     u8 enabled_tc,
                                     bool is_add)
-#endif
 {
        struct i40e_pf *pf = vsi->back;
        u16 sections = 0;
@@ -1706,11 +1684,6 @@ static void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi,
                                qcount = min_t(int, pf->alloc_rss_size,
                                               num_tc_qps);
                                break;
-#ifdef I40E_FCOE
-                       case I40E_VSI_FCOE:
-                               qcount = num_tc_qps;
-                               break;
-#endif
                        case I40E_VSI_FDIR:
                        case I40E_VSI_SRIOV:
                        case I40E_VSI_VMDQ2:
@@ -1824,11 +1797,7 @@ static int i40e_addr_unsync(struct net_device *netdev, const u8 *addr)
  * i40e_set_rx_mode - NDO callback to set the netdev filters
  * @netdev: network interface device structure
  **/
-#ifdef I40E_FCOE
-void i40e_set_rx_mode(struct net_device *netdev)
-#else
 static void i40e_set_rx_mode(struct net_device *netdev)
-#endif
 {
        struct i40e_netdev_priv *np = netdev_priv(netdev);
        struct i40e_vsi *vsi = np->vsi;
@@ -1853,16 +1822,15 @@ static void i40e_set_rx_mode(struct net_device *netdev)
 }
 
 /**
- * i40e_undo_filter_entries - Undo the changes made to MAC filter entries
+ * i40e_undo_del_filter_entries - Undo the changes made to MAC filter entries
  * @vsi: Pointer to vsi struct
  * @from: Pointer to list which contains MAC filter entries - changes to
  *        those entries needs to be undone.
  *
- * MAC filter entries from list were slated to be sent to firmware, either for
- * addition or deletion.
+ * MAC filter entries from this list were slated for deletion.
  **/
-static void i40e_undo_filter_entries(struct i40e_vsi *vsi,
-                                    struct hlist_head *from)
+static void i40e_undo_del_filter_entries(struct i40e_vsi *vsi,
+                                        struct hlist_head *from)
 {
        struct i40e_mac_filter *f;
        struct hlist_node *h;
@@ -1876,6 +1844,46 @@ static void i40e_undo_filter_entries(struct i40e_vsi *vsi,
        }
 }
 
+/**
+ * i40e_undo_add_filter_entries - Undo the changes made to MAC filter entries
+ * @vsi: Pointer to vsi struct
+ * @from: Pointer to list which contains MAC filter entries - changes to
+ *        those entries needs to be undone.
+ *
+ * MAC filter entries from this list were slated for addition.
+ **/
+static void i40e_undo_add_filter_entries(struct i40e_vsi *vsi,
+                                        struct hlist_head *from)
+{
+       struct i40e_new_mac_filter *new;
+       struct hlist_node *h;
+
+       hlist_for_each_entry_safe(new, h, from, hlist) {
+               /* We can simply free the wrapper structure */
+               hlist_del(&new->hlist);
+               kfree(new);
+       }
+}
+
+/**
+ * i40e_next_entry - Get the next non-broadcast filter from a list
+ * @next: pointer to filter in list
+ *
+ * Returns the next non-broadcast filter in the list. Required so that we
+ * ignore broadcast filters within the list, since these are not handled via
+ * the normal firmware update path.
+ */
+static
+struct i40e_new_mac_filter *i40e_next_filter(struct i40e_new_mac_filter *next)
+{
+       hlist_for_each_entry_continue(next, hlist) {
+               if (!is_broadcast_ether_addr(next->f->macaddr))
+                       return next;
+       }
+
+       return NULL;
+}
+
 /**
  * i40e_update_filter_state - Update filter state based on return data
  * from firmware
@@ -1889,7 +1897,7 @@ static void i40e_undo_filter_entries(struct i40e_vsi *vsi,
 static int
 i40e_update_filter_state(int count,
                         struct i40e_aqc_add_macvlan_element_data *add_list,
-                        struct i40e_mac_filter *add_head)
+                        struct i40e_new_mac_filter *add_head)
 {
        int retval = 0;
        int i;
@@ -1908,9 +1916,9 @@ i40e_update_filter_state(int count,
                        retval++;
                }
 
-               add_head = hlist_entry(add_head->hlist.next,
-                                      typeof(struct i40e_mac_filter),
-                                      hlist);
+               add_head = i40e_next_filter(add_head);
+               if (!add_head)
+                       break;
        }
 
        return retval;
@@ -1967,7 +1975,7 @@ void i40e_aqc_del_filters(struct i40e_vsi *vsi, const char *vsi_name,
 static
 void i40e_aqc_add_filters(struct i40e_vsi *vsi, const char *vsi_name,
                          struct i40e_aqc_add_macvlan_element_data *list,
-                         struct i40e_mac_filter *add_head,
+                         struct i40e_new_mac_filter *add_head,
                          int num_add, bool *promisc_changed)
 {
        struct i40e_hw *hw = &vsi->back->hw;
@@ -1979,7 +1987,7 @@ void i40e_aqc_add_filters(struct i40e_vsi *vsi, const char *vsi_name,
 
        if (fcnt != num_add) {
                *promisc_changed = true;
-               set_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state);
+               set_bit(__I40E_VSI_OVERFLOW_PROMISC, vsi->state);
                dev_warn(&vsi->back->pdev->dev,
                         "Error %s adding RX filters on %s, promiscuous mode forced on\n",
                         i40e_aq_str(hw, aq_err),
@@ -1995,10 +2003,12 @@ void i40e_aqc_add_filters(struct i40e_vsi *vsi, const char *vsi_name,
  * This function sets or clears the promiscuous broadcast flags for VLAN
  * filters in order to properly receive broadcast frames. Assumes that only
  * broadcast filters are passed.
+ *
+ * Returns status indicating success or failure;
  **/
-static
-void i40e_aqc_broadcast_filter(struct i40e_vsi *vsi, const char *vsi_name,
-                              struct i40e_mac_filter *f)
+static i40e_status
+i40e_aqc_broadcast_filter(struct i40e_vsi *vsi, const char *vsi_name,
+                         struct i40e_mac_filter *f)
 {
        bool enable = f->state == I40E_FILTER_NEW;
        struct i40e_hw *hw = &vsi->back->hw;
@@ -2017,15 +2027,13 @@ void i40e_aqc_broadcast_filter(struct i40e_vsi *vsi, const char *vsi_name,
                                                            NULL);
        }
 
-       if (aq_ret) {
+       if (aq_ret)
                dev_warn(&vsi->back->pdev->dev,
                         "Error %s setting broadcast promiscuous mode on %s\n",
                         i40e_aq_str(hw, hw->aq.asq_last_status),
                         vsi_name);
-               f->state = I40E_FILTER_FAILED;
-       } else if (enable) {
-               f->state = I40E_FILTER_ACTIVE;
-       }
+
+       return aq_ret;
 }
 
 /**
@@ -2039,7 +2047,8 @@ void i40e_aqc_broadcast_filter(struct i40e_vsi *vsi, const char *vsi_name,
 int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
 {
        struct hlist_head tmp_add_list, tmp_del_list;
-       struct i40e_mac_filter *f, *add_head = NULL;
+       struct i40e_mac_filter *f;
+       struct i40e_new_mac_filter *new, *add_head = NULL;
        struct i40e_hw *hw = &vsi->back->hw;
        unsigned int failed_filters = 0;
        unsigned int vlan_filters = 0;
@@ -2061,7 +2070,7 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
        struct i40e_aqc_add_macvlan_element_data *add_list;
        struct i40e_aqc_remove_macvlan_element_data *del_list;
 
-       while (test_and_set_bit(__I40E_CONFIG_BUSY, &vsi->state))
+       while (test_and_set_bit(__I40E_VSI_SYNCING_FILTERS, vsi->state))
                usleep_range(1000, 2000);
        pf = vsi->back;
 
@@ -2093,9 +2102,17 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
                                continue;
                        }
                        if (f->state == I40E_FILTER_NEW) {
-                               /* Move the element into temporary add_list */
-                               hash_del(&f->hlist);
-                               hlist_add_head(&f->hlist, &tmp_add_list);
+                               /* Create a temporary i40e_new_mac_filter */
+                               new = kzalloc(sizeof(*new), GFP_ATOMIC);
+                               if (!new)
+                                       goto err_no_memory_locked;
+
+                               /* Store pointer to the real filter */
+                               new->f = f;
+                               new->state = f->state;
+
+                               /* Add it to the hash list */
+                               hlist_add_head(&new->hlist, &tmp_add_list);
                        }
 
                        /* Count the number of active (current and new) VLAN
@@ -2130,7 +2147,7 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
                        cmd_flags = 0;
 
                        /* handle broadcast filters by updating the broadcast
-                        * promiscuous flag instead of deleting a MAC filter.
+                        * promiscuous flag and release filter list.
                         */
                        if (is_broadcast_ether_addr(f->macaddr)) {
                                i40e_aqc_broadcast_filter(vsi, vsi_name, f);
@@ -2188,41 +2205,41 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
                        goto err_no_memory;
 
                num_add = 0;
-               hlist_for_each_entry_safe(f, h, &tmp_add_list, hlist) {
-                       if (test_bit(__I40E_FILTER_OVERFLOW_PROMISC,
-                                    &vsi->state)) {
-                               f->state = I40E_FILTER_FAILED;
+               hlist_for_each_entry_safe(new, h, &tmp_add_list, hlist) {
+                       if (test_bit(__I40E_VSI_OVERFLOW_PROMISC,
+                                    vsi->state)) {
+                               new->state = I40E_FILTER_FAILED;
                                continue;
                        }
 
                        /* handle broadcast filters by updating the broadcast
                         * promiscuous flag instead of adding a MAC filter.
                         */
-                       if (is_broadcast_ether_addr(f->macaddr)) {
-                               u64 key = i40e_addr_to_hkey(f->macaddr);
-                               i40e_aqc_broadcast_filter(vsi, vsi_name, f);
-
-                               hlist_del(&f->hlist);
-                               hash_add(vsi->mac_filter_hash, &f->hlist, key);
+                       if (is_broadcast_ether_addr(new->f->macaddr)) {
+                               if (i40e_aqc_broadcast_filter(vsi, vsi_name,
+                                                             new->f))
+                                       new->state = I40E_FILTER_FAILED;
+                               else
+                                       new->state = I40E_FILTER_ACTIVE;
                                continue;
                        }
 
                        /* add to add array */
                        if (num_add == 0)
-                               add_head = f;
+                               add_head = new;
                        cmd_flags = 0;
-                       ether_addr_copy(add_list[num_add].mac_addr, f->macaddr);
-                       if (f->vlan == I40E_VLAN_ANY) {
+                       ether_addr_copy(add_list[num_add].mac_addr,
+                                       new->f->macaddr);
+                       if (new->f->vlan == I40E_VLAN_ANY) {
                                add_list[num_add].vlan_tag = 0;
                                cmd_flags |= I40E_AQC_MACVLAN_ADD_IGNORE_VLAN;
                        } else {
                                add_list[num_add].vlan_tag =
-                                       CPU_TO_LE16((u16)(f->vlan));
+                                       CPU_TO_LE16((u16)(new->f->vlan));
                        }
                        add_list[num_add].queue_number = 0;
                        /* set invalid match method for later detection */
-                       add_list[num_add].match_method =
-                               CPU_TO_LE16((u16)I40E_AQC_MM_ERR_NO_RES);
+                       add_list[num_add].match_method = I40E_AQC_MM_ERR_NO_RES;
                        cmd_flags |= I40E_AQC_MACVLAN_ADD_PERFECT_MATCH;
                        add_list[num_add].flags = CPU_TO_LE16(cmd_flags);
                        num_add++;
@@ -2244,11 +2261,12 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
                 * the VSI's list.
                 */
                spin_lock_bh(&vsi->mac_filter_hash_lock);
-               hlist_for_each_entry_safe(f, h, &tmp_add_list, hlist) {
-                       u64 key = i40e_addr_to_hkey(f->macaddr);
-
-                       hlist_del(&f->hlist);
-                       hash_add(vsi->mac_filter_hash, &f->hlist, key);
+               hlist_for_each_entry_safe(new, h, &tmp_add_list, hlist) {
+                       /* Only update the state if we're still NEW */
+                       if (new->f->state == I40E_FILTER_NEW)
+                               new->f->state = new->state;
+                       hlist_del(&new->hlist);
+                       kfree(new);
                }
                spin_unlock_bh(&vsi->mac_filter_hash_lock);
                kfree(add_list);
@@ -2276,19 +2294,19 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
         * safely exit if we didn't just enter, we no longer have any failed
         * filters, and we have reduced filters below the threshold value.
         */
-       if (test_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state) &&
+       if (test_bit(__I40E_VSI_OVERFLOW_PROMISC, vsi->state) &&
            !promisc_changed && !failed_filters &&
            (vsi->active_filters < vsi->promisc_threshold)) {
                dev_info(&pf->pdev->dev,
                         "filter logjam cleared on %s, leaving overflow promiscuous mode\n",
                         vsi_name);
-               clear_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state);
+               clear_bit(__I40E_VSI_OVERFLOW_PROMISC, vsi->state);
                promisc_changed = true;
                vsi->promisc_threshold = 0;
        }
        /* if the VF is not trusted do not do promisc */
        if ((vsi->type == I40E_VSI_SRIOV) && !pf->vf[vsi->vf_id].trusted) {
-               clear_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state);
+               clear_bit(__I40E_VSI_OVERFLOW_PROMISC, vsi->state);
                goto out;
        }
 
@@ -2311,12 +2329,13 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
                                 i40e_aq_str(hw, hw->aq.asq_last_status));
                }
        }
+
        if ((changed_flags & IFF_PROMISC) || promisc_changed) {
                bool cur_promisc;
 
                cur_promisc = (!!(vsi->current_netdev_flags & IFF_PROMISC) ||
-                              test_bit(__I40E_FILTER_OVERFLOW_PROMISC,
-                                       &vsi->state));
+                              test_bit(__I40E_VSI_OVERFLOW_PROMISC,
+                                       vsi->state));
                if ((vsi->type == I40E_VSI_MAIN) &&
                    (pf->lan_veb != I40E_NO_VEB) &&
                    !(pf->flags & I40E_FLAG_MFP_ENABLED)) {
@@ -2387,19 +2406,19 @@ out:
        if (retval)
                vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
 
-       clear_bit(__I40E_CONFIG_BUSY, &vsi->state);
+       clear_bit(__I40E_VSI_SYNCING_FILTERS, vsi->state);
        return retval;
 
 err_no_memory:
        /* Restore elements on the temporary add and delete lists */
        spin_lock_bh(&vsi->mac_filter_hash_lock);
 err_no_memory_locked:
-       i40e_undo_filter_entries(vsi, &tmp_del_list);
-       i40e_undo_filter_entries(vsi, &tmp_add_list);
+       i40e_undo_del_filter_entries(vsi, &tmp_del_list);
+       i40e_undo_add_filter_entries(vsi, &tmp_add_list);
        spin_unlock_bh(&vsi->mac_filter_hash_lock);
 
        vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
-       clear_bit(__I40E_CONFIG_BUSY, &vsi->state);
+       clear_bit(__I40E_VSI_SYNCING_FILTERS, vsi->state);
        return -ENOMEM;
 }
 
@@ -2439,8 +2458,9 @@ static void i40e_sync_filters_subtask(struct i40e_pf *pf)
 static int i40e_change_mtu(struct net_device *netdev, int new_mtu)
 {
        struct i40e_netdev_priv *np = netdev_priv(netdev);
-       int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
+       int max_frame = new_mtu + I40E_PACKET_HDR_PAD;
        struct i40e_vsi *vsi = np->vsi;
+       struct i40e_pf *pf = vsi->back;
 
        /* MTU < 68 is an error and causes problems on some kernels */
        if ((new_mtu < 68) || (max_frame > I40E_MAX_RXBUFFER))
@@ -2478,6 +2498,8 @@ static int i40e_change_mtu(struct net_device *netdev, int new_mtu)
        netdev->mtu = new_mtu;
        if (netif_running(netdev))
                i40e_vsi_reinit_locked(vsi);
+       pf->flags |= (I40E_FLAG_SERVICE_CLIENT_REQUESTED |
+                     I40E_FLAG_CLIENT_L2_CHANGE);
        return 0;
 }
 
@@ -2654,9 +2676,20 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, u16 vid)
 {
        int err;
 
-       if (!(vid > 0) || vsi->info.pvid)
+       if (vsi->info.pvid)
                return -EINVAL;
 
+       /* The network stack will attempt to add VID=0, with the intention to
+        * receive priority tagged packets with a VLAN of 0. Our HW receives
+        * these packets by default when configured to receive untagged
+        * packets, so we don't need to add a filter for this case.
+        * Additionally, HW interprets adding a VID=0 filter as meaning to
+        * receive *only* tagged traffic and stops receiving untagged traffic.
+        * Thus, we do not want to actually add a filter for VID=0
+        */
+       if (!vid)
+               return 0;
+
        /* Locked once because all functions invoked below iterates list*/
        spin_lock_bh(&vsi->mac_filter_hash_lock);
        err = i40e_add_vlan_all_mac(vsi, vid);
@@ -2703,7 +2736,7 @@ void i40e_rm_vlan_all_mac(struct i40e_vsi *vsi, s16 vid)
  **/
 void i40e_vsi_kill_vlan(struct i40e_vsi *vsi, u16 vid)
 {
-       if (!(vid > 0) || vsi->info.pvid)
+       if (!vid || vsi->info.pvid)
                return;
 
        spin_lock_bh(&vsi->mac_filter_hash_lock);
@@ -2725,27 +2758,14 @@ void i40e_vsi_kill_vlan(struct i40e_vsi *vsi, u16 vid)
  **/
 #ifdef HAVE_INT_NDO_VLAN_RX_ADD_VID
 #ifdef NETIF_F_HW_VLAN_CTAG_RX
-#ifdef I40E_FCOE
-int i40e_vlan_rx_add_vid(struct net_device *netdev,
-                        __always_unused __be16 proto, u16 vid)
-#else
 static int i40e_vlan_rx_add_vid(struct net_device *netdev,
                                __always_unused __be16 proto, u16 vid)
-#endif
-#else
-#ifdef I40E_FCOE
-int i40e_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
 #else
 static int i40e_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
 #endif
-#endif
-#else
-#ifdef I40E_FCOE
-void i40e_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
 #else
 static void i40e_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
 #endif
-#endif
 {
        struct i40e_netdev_priv *np = netdev_priv(netdev);
        struct i40e_vsi *vsi = np->vsi;
@@ -2758,15 +2778,7 @@ static void i40e_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
                return;
 #endif
 
-       /* If the network stack called us with vid = 0 then
-        * it is asking to receive priority tagged packets with
-        * vlan id 0.  Our HW receives them by default when configured
-        * to receive untagged packets so there is no need to add an
-        * extra filter for vlan 0 tagged packets.
-        */
-       if (vid)
-               ret = i40e_vsi_add_vlan(vsi, vid);
-
+       ret = i40e_vsi_add_vlan(vsi, vid);
 #ifndef HAVE_VLAN_RX_REGISTER
        if (!ret)
                set_bit(vid, vsi->active_vlans);
@@ -2805,27 +2817,14 @@ static void i40e_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
  **/
 #ifdef HAVE_INT_NDO_VLAN_RX_ADD_VID
 #ifdef NETIF_F_HW_VLAN_CTAG_RX
-#ifdef I40E_FCOE
-int i40e_vlan_rx_kill_vid(struct net_device *netdev,
-                         __always_unused __be16 proto, u16 vid)
-#else
 static int i40e_vlan_rx_kill_vid(struct net_device *netdev,
                                 __always_unused __be16 proto, u16 vid)
-#endif
-#else
-#ifdef I40E_FCOE
-int i40e_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
 #else
 static int i40e_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
 #endif
-#endif
-#else
-#ifdef I40E_FCOE
-void i40e_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
 #else
 static void i40e_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
 #endif
-#endif
 {
        struct i40e_netdev_priv *np = netdev_priv(netdev);
        struct i40e_vsi *vsi = np->vsi;
@@ -3065,9 +3064,6 @@ int i40e_vsi_setup_rx_resources(struct i40e_vsi *vsi)
 
        for (i = 0; i < vsi->num_queue_pairs && !err; i++)
                err = i40e_setup_rx_descriptors(vsi->rx_rings[i]);
-#ifdef I40E_FCOE
-       i40e_fcoe_setup_ddp_resources(vsi);
-#endif
        return err;
 }
 
@@ -3087,9 +3083,6 @@ static void i40e_vsi_free_rx_resources(struct i40e_vsi *vsi)
        for (i = 0; i < vsi->num_queue_pairs; i++)
                if (vsi->rx_rings[i] && vsi->rx_rings[i]->desc)
                        i40e_free_rx_resources(vsi->rx_rings[i]);
-#ifdef I40E_FCOE
-       i40e_fcoe_free_ddp_resources(vsi);
-#endif
 }
 
 /**
@@ -3102,22 +3095,33 @@ static void i40e_vsi_free_rx_resources(struct i40e_vsi *vsi)
 static void i40e_config_xps_tx_ring(struct i40e_ring *ring)
 {
        struct i40e_vsi *vsi = ring->vsi;
-       cpumask_var_t mask;
+       int cpu;
 
        if (!ring->q_vector || !ring->netdev)
                return;
 
-       /* Single TC mode enable XPS */
-       if (vsi->tc_config.numtc <= 1) {
-               if (!test_and_set_bit(__I40E_TX_XPS_INIT_DONE, &ring->state))
-                       netif_set_xps_queue(ring->netdev,
-                                           &ring->q_vector->affinity_mask,
-                                           ring->queue_index);
-       } else if (alloc_cpumask_var(&mask, GFP_KERNEL)) {
-               /* Disable XPS to allow selection based on TC */
-               bitmap_zero(cpumask_bits(mask), nr_cpumask_bits);
+#ifndef HAVE_NETDEV_TC_RESETS_XPS
+       /* Older kernels do not reset the XPS map when configuring traffic
+        * classes. To allow selection based on TC we need to clear the
+        * mapping here.
+        */
+       if ((vsi->tc_config.numtc > 1) &&
+           test_and_clear_bit(__I40E_TX_XPS_INIT_DONE, ring->state)) {
+               cpumask_var_t mask;
+
+               if (!zalloc_cpumask_var(&mask, GFP_KERNEL))
+                       return;
                netif_set_xps_queue(ring->netdev, mask, ring->queue_index);
                free_cpumask_var(mask);
+               return;
+       }
+
+#endif
+       if ((vsi->tc_config.numtc <= 1) &&
+           !test_and_set_bit(__I40E_TX_XPS_INIT_DONE, ring->state)) {
+               cpu = cpumask_local_spread(ring->q_vector->v_idx, -1);
+               netif_set_xps_queue(ring->netdev, get_cpu_mask(cpu),
+                                   ring->queue_index);
        }
 }
 
@@ -3154,9 +3158,6 @@ static int i40e_configure_tx_ring(struct i40e_ring *ring)
        tx_ctx.qlen = ring->count;
        tx_ctx.fd_ena = !!(vsi->back->flags & (I40E_FLAG_FD_SB_ENABLED |
                                               I40E_FLAG_FD_ATR_ENABLED));
-#ifdef I40E_FCOE
-       tx_ctx.fc_ena = (vsi->type == I40E_VSI_FCOE);
-#endif
 #ifdef HAVE_PTP_1588_CLOCK
        tx_ctx.timesync_ena = !!(vsi->back->flags & I40E_FLAG_PTP);
 #endif /* HAVE_PTP_1588_CLOCK */
@@ -3232,14 +3233,15 @@ static int i40e_configure_rx_ring(struct i40e_ring *ring)
        struct i40e_hmc_obj_rxq rx_ctx;
        i40e_status err = 0;
 
-       ring->state = 0;
+       bitmap_zero(ring->state, __I40E_RING_STATE_NBITS);
 
        /* clear the context structure first */
        memset(&rx_ctx, 0, sizeof(rx_ctx));
 
        ring->rx_buf_len = vsi->rx_buf_len;
 
-       rx_ctx.dbuff = ring->rx_buf_len >> I40E_RXQ_CTX_DBUFF_SHIFT;
+       rx_ctx.dbuff = DIV_ROUND_UP(ring->rx_buf_len,
+                                   BIT_ULL(I40E_RXQ_CTX_DBUFF_SHIFT));
 
        rx_ctx.base = (ring->dma / 128);
        rx_ctx.qlen = ring->count;
@@ -3258,9 +3260,6 @@ static int i40e_configure_rx_ring(struct i40e_ring *ring)
        rx_ctx.l2tsel = 1;
        /* this controls whether VLAN is stripped from inner headers */
        rx_ctx.showiv = 0;
-#ifdef I40E_FCOE
-       rx_ctx.fc_ena = (vsi->type == I40E_VSI_FCOE);
-#endif
        /* set the prefena field to 1 because the manual says to */
        rx_ctx.prefena = 1;
 
@@ -3282,6 +3281,12 @@ static int i40e_configure_rx_ring(struct i40e_ring *ring)
                return -ENOMEM;
        }
 
+       /* configure Rx buffer alignment */
+       if (!vsi->netdev || (vsi->back->flags & I40E_FLAG_LEGACY_RX))
+               clear_ring_build_skb_enabled(ring);
+       else
+               set_ring_build_skb_enabled(ring);
+
        /* cache tail for quicker writes, and clear the reg before use */
        ring->tail = hw->hw_addr + I40E_QRX_TAIL(pf_q);
        writel(0, ring->tail);
@@ -3318,27 +3323,33 @@ static int i40e_vsi_configure_rx(struct i40e_vsi *vsi)
 {
        int err = 0;
        u16 i;
+#ifdef CONFIG_I40E_DISABLE_PACKET_SPLIT
+       u16 max_frame = I40E_RXBUFFER_1536 - NET_IP_ALIGN;
 
-       if (vsi->netdev && (vsi->netdev->mtu > ETH_DATA_LEN))
-               vsi->max_frame = vsi->netdev->mtu + ETH_HLEN
-                              + ETH_FCS_LEN + VLAN_HLEN;
-       else
-               vsi->max_frame = I40E_RXBUFFER_2048;
-
-       vsi->rx_buf_len = I40E_RXBUFFER_2048;
-
-#ifdef I40E_FCOE
-       /* setup rx buffer for FCoE */
-       if ((vsi->type == I40E_VSI_FCOE) &&
-           (vsi->back->flags & I40E_FLAG_FCOE_ENABLED)) {
-               vsi->rx_buf_len = I40E_RXBUFFER_3072;
-               vsi->max_frame = I40E_RXBUFFER_3072;
+       if (!vsi->netdev)
+               max_frame = I40E_RXBUFFER_2048;
+       else if (vsi->netdev->mtu + I40E_PACKET_HDR_PAD > max_frame)
+               max_frame = vsi->netdev->mtu + I40E_PACKET_HDR_PAD;
+
+       vsi->max_frame = max_frame;
+       vsi->rx_buf_len = max_frame;
+#else /* CONFIG_I40E_DISABLE_PACKET_SPLIT */
+
+       if (!vsi->netdev || (vsi->back->flags & I40E_FLAG_LEGACY_RX)) {
+               vsi->max_frame = I40E_MAX_RXBUFFER;
+               vsi->rx_buf_len = I40E_RXBUFFER_2048;
+#if (PAGE_SIZE < 8192)
+       } else if (!I40E_2K_TOO_SMALL_WITH_PADDING &&
+                  (vsi->netdev->mtu <= ETH_DATA_LEN)) {
+               vsi->max_frame = I40E_RXBUFFER_1536 - NET_IP_ALIGN;
+               vsi->rx_buf_len = I40E_RXBUFFER_1536 - NET_IP_ALIGN;
+#endif
+       } else {
+               vsi->max_frame = I40E_MAX_RXBUFFER;
+               vsi->rx_buf_len = (PAGE_SIZE < 8192) ? I40E_RXBUFFER_3072 :
+                                                      I40E_RXBUFFER_2048;
        }
-
-#endif /* I40E_FCOE */
-       /* round up for the chip's needs */
-       vsi->rx_buf_len = ALIGN(vsi->rx_buf_len,
-                               BIT_ULL(I40E_RXQ_CTX_DBUFF_SHIFT));
+#endif /* CONFIG_I40E_DISABLE_PACKET_SPLIT */
 
        /* set up individual rings */
        for (i = 0; i < vsi->num_queue_pairs && !err; i++)
@@ -3390,6 +3401,7 @@ static void i40e_set_vsi_rx_mode(struct i40e_vsi *vsi)
 {
        if (vsi->netdev)
                i40e_set_rx_mode(vsi->netdev);
+
 }
 
 /**
@@ -3408,6 +3420,12 @@ static void i40e_fdir_filter_restore(struct i40e_vsi *vsi)
        if (!(pf->flags & I40E_FLAG_FD_SB_ENABLED))
                return;
 
+       /* reset FDIR counters as we're replaying all existing filters */
+       pf->fd_tcp4_filter_cnt = 0;
+       pf->fd_udp4_filter_cnt = 0;
+       pf->fd_sctp4_filter_cnt = 0;
+       pf->fd_ip4_filter_cnt = 0;
+
        hlist_for_each_entry_safe(filter, node,
                                  &pf->fdir_filter_list, fdir_node) {
                i40e_add_del_fdir(vsi, filter, true);
@@ -3537,6 +3555,8 @@ static void i40e_enable_misc_int_causes(struct i40e_pf *pf)
              I40E_PFINT_ICR0_ENA_HMC_ERR_MASK       |
              I40E_PFINT_ICR0_ENA_VFLR_MASK          |
              I40E_PFINT_ICR0_ENA_ADMINQ_MASK;
+       if (pf->flags & I40E_FLAG_IWARP_ENABLED)
+               val |= I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK;
 #ifdef HAVE_PTP_1588_CLOCK
 
        if (pf->flags & I40E_FLAG_PTP)
@@ -3636,7 +3656,7 @@ static irqreturn_t i40e_msix_clean_rings(int irq, void *data)
        if (!q_vector->tx.ring && !q_vector->rx.ring)
                return IRQ_HANDLED;
 
-       napi_schedule(&q_vector->napi);
+       napi_schedule_irqoff(&q_vector->napi);
 
        return IRQ_HANDLED;
 }
@@ -3656,7 +3676,7 @@ static void i40e_irq_affinity_notify(struct irq_affinity_notify *notify,
        struct i40e_q_vector *q_vector =
                container_of(notify, struct i40e_q_vector, affinity_notify);
 
-       q_vector->affinity_mask = *mask;
+       cpumask_copy(&q_vector->affinity_mask, mask);
 }
 
 /**
@@ -3686,6 +3706,9 @@ int i40e_vsi_request_irq_msix(struct i40e_vsi *vsi, char *basename)
        int tx_int_idx = 0;
        int vector, err;
        int irq_num;
+#ifdef HAVE_IRQ_AFFINITY_HINT
+       int cpu;
+#endif
 
        for (vector = 0; vector < q_vectors; vector++) {
                struct i40e_q_vector *q_vector = vsi->q_vectors[vector];
@@ -3724,9 +3747,15 @@ int i40e_vsi_request_irq_msix(struct i40e_vsi *vsi, char *basename)
                irq_set_affinity_notifier(irq_num, &q_vector->affinity_notify);
 #endif
 #ifdef HAVE_IRQ_AFFINITY_HINT
-               /* assign the mask for this irq */
-               irq_set_affinity_hint(irq_num, &q_vector->affinity_mask);
-#endif
+               /* Spread affinity hints out across online CPUs.
+                *
+                * get_cpu_mask returns a static constant mask with
+                * a permanent lifetime so it's ok to pass to
+                * irq_set_affinity_hint without making a copy.
+                */
+               cpu = cpumask_local_spread(q_vector->v_idx, -1);
+               irq_set_affinity_hint(irq_num, get_cpu_mask(cpu));
+#endif /* HAVE_IRQ_AFFINITY_HINT */
        }
 
        vsi->irqs_ready = true;
@@ -3810,14 +3839,20 @@ static int i40e_vsi_enable_irq(struct i40e_vsi *vsi)
 }
 
 /**
- * i40e_stop_misc_vector - Stop the vector that handles non-queue events
+ * i40e_free_misc_vector - Free the vector that handles non-queue events
  * @pf: board private structure
  **/
-static void i40e_stop_misc_vector(struct i40e_pf *pf)
+static void i40e_free_misc_vector(struct i40e_pf *pf)
 {
        /* Disable ICR 0 */
        wr32(&pf->hw, I40E_PFINT_ICR0_ENA, 0);
        i40e_flush(&pf->hw);
+
+       if (pf->flags & I40E_FLAG_MSIX_ENABLED && pf->msix_entries) {
+               synchronize_irq(pf->msix_entries[0].vector);
+               free_irq(pf->msix_entries[0].vector, pf);
+               clear_bit(__I40E_MISC_IRQ_REQUESTED, pf->state);
+       }
 }
 
 /**
@@ -3848,38 +3883,47 @@ static irqreturn_t i40e_intr(int irq, void *data)
        if (((icr0 & ~I40E_PFINT_ICR0_INTEVENT_MASK) == 0) ||
            (icr0 & I40E_PFINT_ICR0_SWINT_MASK))
                pf->sw_int_count++;
+       if ((pf->flags & I40E_FLAG_IWARP_ENABLED) &&
+           (icr0 & I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK)) {
+               ena_mask &= ~I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK;
+               dev_dbg(&pf->pdev->dev, "cleared PE_CRITERR\n");
+               set_bit(__I40E_CORE_RESET_REQUESTED, pf->state);
+       }
 
        /* only q0 is used in MSI/Legacy mode, and none are used in MSIX */
        if (icr0 & I40E_PFINT_ICR0_QUEUE_0_MASK) {
+               struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi];
+               struct i40e_q_vector *q_vector = vsi->q_vectors[0];
+
                /* We do not have a way to disarm Queue causes while leaving
                 * interrupt enabled for all other causes, ideally
                 * interrupt should be disabled while we are in NAPI but
                 * this is not a performance path and napi_schedule()
                 * can deal with rescheduling.
                 */
-               if (!test_bit(__I40E_DOWN, &pf->state))
-                       napi_schedule(&pf->vsi[pf->lan_vsi]->q_vectors[0]->napi);
+               if (!test_bit(__I40E_DOWN, pf->state))
+                       napi_schedule_irqoff(&q_vector->napi);
        }
 
        if (icr0 & I40E_PFINT_ICR0_ADMINQ_MASK) {
                ena_mask &= ~I40E_PFINT_ICR0_ENA_ADMINQ_MASK;
-               set_bit(__I40E_ADMINQ_EVENT_PENDING, &pf->state);
+               set_bit(__I40E_ADMINQ_EVENT_PENDING, pf->state);
                i40e_debug(&pf->hw, I40E_DEBUG_NVM, "AdminQ event\n");
        }
 
        if (icr0 & I40E_PFINT_ICR0_MAL_DETECT_MASK) {
                ena_mask &= ~I40E_PFINT_ICR0_ENA_MAL_DETECT_MASK;
-               set_bit(__I40E_MDD_EVENT_PENDING, &pf->state);
+               set_bit(__I40E_MDD_EVENT_PENDING, pf->state);
        }
 
        if (icr0 & I40E_PFINT_ICR0_VFLR_MASK) {
                ena_mask &= ~I40E_PFINT_ICR0_ENA_VFLR_MASK;
-               set_bit(__I40E_VFLR_EVENT_PENDING, &pf->state);
+               set_bit(__I40E_VFLR_EVENT_PENDING, pf->state);
        }
 
        if (icr0 & I40E_PFINT_ICR0_GRST_MASK) {
-               if (!test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state))
-                       set_bit(__I40E_RESET_INTR_RECEIVED, &pf->state);
+               if (!test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state))
+                       set_bit(__I40E_RESET_INTR_RECEIVED, pf->state);
                ena_mask &= ~I40E_PFINT_ICR0_ENA_GRST_MASK;
                val = rd32(hw, I40E_GLGEN_RSTAT);
                val = (val & I40E_GLGEN_RSTAT_RESET_TYPE_MASK)
@@ -3890,7 +3934,7 @@ static irqreturn_t i40e_intr(int irq, void *data)
                        pf->globr_count++;
                } else if (val == I40E_RESET_EMPR) {
                        pf->empr_count++;
-                       set_bit(__I40E_EMP_RESET_INTR_RECEIVED, &pf->state);
+                       set_bit(__I40E_EMP_RESET_INTR_RECEIVED, pf->state);
                }
        }
 
@@ -3925,7 +3969,7 @@ static irqreturn_t i40e_intr(int irq, void *data)
                    (icr0_remaining & I40E_PFINT_ICR0_PCI_EXCEPTION_MASK) ||
                    (icr0_remaining & I40E_PFINT_ICR0_ECC_ERR_MASK)) {
                        dev_info(&pf->pdev->dev, "device will be reset\n");
-                       set_bit(__I40E_PF_RESET_REQUESTED, &pf->state);
+                       set_bit(__I40E_PF_RESET_REQUESTED, pf->state);
                        i40e_service_event_schedule(pf);
                }
                ena_mask &= ~icr0_remaining;
@@ -3935,7 +3979,7 @@ static irqreturn_t i40e_intr(int irq, void *data)
 enable_intr:
        /* re-enable interrupt causes */
        wr32(hw, I40E_PFINT_ICR0_ENA, ena_mask);
-       if (!test_bit(__I40E_DOWN, &pf->state)) {
+       if (!test_bit(__I40E_DOWN, pf->state)) {
                i40e_service_event_schedule(pf);
                i40e_irq_dynamic_enable_icr0(pf, false);
        }
@@ -4147,11 +4191,7 @@ static int i40e_vsi_request_irq(struct i40e_vsi *vsi, char *basename)
  * This is used by netconsole to send skbs without having to re-enable
  * interrupts.  It's not called while the normal interrupt routine is executing.
  **/
-#ifdef I40E_FCOE
-void i40e_netpoll(struct net_device *netdev)
-#else
 static void i40e_netpoll(struct net_device *netdev)
-#endif
 {
        struct i40e_netdev_priv *np = netdev_priv(netdev);
        struct i40e_vsi *vsi = np->vsi;
@@ -4159,20 +4199,20 @@ static void i40e_netpoll(struct net_device *netdev)
        int i;
 
        /* if interface is down do nothing */
-       if (test_bit(__I40E_DOWN, &vsi->state))
+       if (test_bit(__I40E_VSI_DOWN, vsi->state))
                return;
 
-       pf->flags |= I40E_FLAG_IN_NETPOLL;
        if (pf->flags & I40E_FLAG_MSIX_ENABLED) {
                for (i = 0; i < vsi->num_q_vectors; i++)
                        i40e_msix_clean_rings(0, vsi->q_vectors[i]);
        } else {
                i40e_intr(pf->pdev->irq, netdev);
        }
-       pf->flags &= ~I40E_FLAG_IN_NETPOLL;
 }
 #endif
 
+#define I40E_QTX_ENA_WAIT_COUNT 50
+
 /**
  * i40e_pf_txq_wait - Wait for a PF's Tx queue to be enabled or disabled
  * @pf: the PF being configured
@@ -4202,6 +4242,50 @@ static int i40e_pf_txq_wait(struct i40e_pf *pf, int pf_q, bool enable)
        return 0;
 }
 
+/**
+ * i40e_control_tx_q - Start or stop a particular Tx queue
+ * @pf: the PF structure
+ * @pf_q: the PF queue to configure
+ * @enable: start or stop the queue
+ *
+ * This function enables or disables a single queue. Note that any delay
+ * required after the operation is expected to be handled by the caller of
+ * this function.
+ **/
+static void i40e_control_tx_q(struct i40e_pf *pf, int pf_q, bool enable)
+{
+       struct i40e_hw *hw = &pf->hw;
+       u32 tx_reg;
+       int i;
+
+       /* warn the TX unit of coming changes */
+       i40e_pre_tx_queue_cfg(&pf->hw, pf_q, enable);
+       if (!enable)
+               usleep_range(10, 20);
+
+       for (i = 0; i < I40E_QTX_ENA_WAIT_COUNT; i++) {
+               tx_reg = rd32(hw, I40E_QTX_ENA(pf_q));
+               if (((tx_reg >> I40E_QTX_ENA_QENA_REQ_SHIFT) & 1) ==
+                   ((tx_reg >> I40E_QTX_ENA_QENA_STAT_SHIFT) & 1))
+                       break;
+               usleep_range(1000, 2000);
+       }
+
+       /* Skip if the queue is already in the requested state */
+       if (enable == !!(tx_reg & I40E_QTX_ENA_QENA_STAT_MASK))
+               return;
+
+       /* turn on/off the queue */
+       if (enable) {
+               wr32(hw, I40E_QTX_HEAD(pf_q), 0);
+               tx_reg |= I40E_QTX_ENA_QENA_REQ_MASK;
+       } else {
+               tx_reg &= ~I40E_QTX_ENA_QENA_REQ_MASK;
+       }
+
+       wr32(hw, I40E_QTX_ENA(pf_q), tx_reg);
+}
+
 /**
  * i40e_vsi_control_tx - Start or stop a VSI's rings
  * @vsi: the VSI being configured
@@ -4210,41 +4294,11 @@ static int i40e_pf_txq_wait(struct i40e_pf *pf, int pf_q, bool enable)
 static int i40e_vsi_control_tx(struct i40e_vsi *vsi, bool enable)
 {
        struct i40e_pf *pf = vsi->back;
-       struct i40e_hw *hw = &pf->hw;
-       int i, j, pf_q, ret = 0;
-       u32 tx_reg;
+       int i, pf_q, ret = 0;
 
        pf_q = vsi->base_queue;
        for (i = 0; i < vsi->num_queue_pairs; i++, pf_q++) {
-
-               /* warn the TX unit of coming changes */
-               i40e_pre_tx_queue_cfg(&pf->hw, pf_q, enable);
-               if (!enable)
-                       usleep_range(10, 20);
-
-               for (j = 0; j < 50; j++) {
-                       tx_reg = rd32(hw, I40E_QTX_ENA(pf_q));
-                       if (((tx_reg >> I40E_QTX_ENA_QENA_REQ_SHIFT) & 1) ==
-                           ((tx_reg >> I40E_QTX_ENA_QENA_STAT_SHIFT) & 1))
-                               break;
-                       usleep_range(1000, 2000);
-               }
-               /* Skip if the queue is already in the requested state */
-               if (enable == !!(tx_reg & I40E_QTX_ENA_QENA_STAT_MASK))
-                       continue;
-
-               /* turn on/off the queue */
-               if (enable) {
-                       wr32(hw, I40E_QTX_HEAD(pf_q), 0);
-                       tx_reg |= I40E_QTX_ENA_QENA_REQ_MASK;
-               } else {
-                       tx_reg &= ~I40E_QTX_ENA_QENA_REQ_MASK;
-               }
-
-               wr32(hw, I40E_QTX_ENA(pf_q), tx_reg);
-               /* No waiting for the Tx queue to disable */
-               if (!enable && test_bit(__I40E_PORT_TX_SUSPENDED, &pf->state))
-                       continue;
+               i40e_control_tx_q(pf, pf_q, enable);
 
                /* wait for the change to finish */
                ret = i40e_pf_txq_wait(pf, pf_q, enable);
@@ -4288,6 +4342,43 @@ static int i40e_pf_rxq_wait(struct i40e_pf *pf, int pf_q, bool enable)
        return 0;
 }
 
+/**
+ * i40e_control_rx_q - Start or stop a particular Rx queue
+ * @pf: the PF structure
+ * @pf_q: the PF queue to configure
+ * @enable: start or stop the queue
+ *
+ * This function enables or disables a single queue. Note that any delay
+ * required after the operation is expected to be handled by the caller of
+ * this function.
+ **/
+static void i40e_control_rx_q(struct i40e_pf *pf, int pf_q, bool enable)
+{
+       struct i40e_hw *hw = &pf->hw;
+       u32 rx_reg;
+       int i;
+
+       for (i = 0; i < I40E_QTX_ENA_WAIT_COUNT; i++) {
+               rx_reg = rd32(hw, I40E_QRX_ENA(pf_q));
+               if (((rx_reg >> I40E_QRX_ENA_QENA_REQ_SHIFT) & 1) ==
+                   ((rx_reg >> I40E_QRX_ENA_QENA_STAT_SHIFT) & 1))
+                       break;
+               usleep_range(1000, 2000);
+       }
+
+       /* Skip if the queue is already in the requested state */
+       if (enable == !!(rx_reg & I40E_QRX_ENA_QENA_STAT_MASK))
+               return;
+
+       /* turn on/off the queue */
+       if (enable)
+               rx_reg |= I40E_QRX_ENA_QENA_REQ_MASK;
+       else
+               rx_reg &= ~I40E_QRX_ENA_QENA_REQ_MASK;
+
+       wr32(hw, I40E_QRX_ENA(pf_q), rx_reg);
+}
+
 /**
  * i40e_vsi_control_rx - Start or stop a VSI's rings
  * @vsi: the VSI being configured
@@ -4296,33 +4387,11 @@ static int i40e_pf_rxq_wait(struct i40e_pf *pf, int pf_q, bool enable)
 static int i40e_vsi_control_rx(struct i40e_vsi *vsi, bool enable)
 {
        struct i40e_pf *pf = vsi->back;
-       struct i40e_hw *hw = &pf->hw;
-       int i, j, pf_q, ret = 0;
-       u32 rx_reg;
+       int i, pf_q, ret = 0;
 
        pf_q = vsi->base_queue;
        for (i = 0; i < vsi->num_queue_pairs; i++, pf_q++) {
-               for (j = 0; j < 50; j++) {
-                       rx_reg = rd32(hw, I40E_QRX_ENA(pf_q));
-                       if (((rx_reg >> I40E_QRX_ENA_QENA_REQ_SHIFT) & 1) ==
-                           ((rx_reg >> I40E_QRX_ENA_QENA_STAT_SHIFT) & 1))
-                               break;
-                       usleep_range(1000, 2000);
-               }
-
-               /* Skip if the queue is already in the requested state */
-               if (enable == !!(rx_reg & I40E_QRX_ENA_QENA_STAT_MASK))
-                       continue;
-
-               /* turn on/off the queue */
-               if (enable)
-                       rx_reg |= I40E_QRX_ENA_QENA_REQ_MASK;
-               else
-                       rx_reg &= ~I40E_QRX_ENA_QENA_REQ_MASK;
-               wr32(hw, I40E_QRX_ENA(pf_q), rx_reg);
-               /* No waiting for the Tx queue to disable */
-               if (!enable && test_bit(__I40E_PORT_TX_SUSPENDED, &pf->state))
-                       continue;
+               i40e_control_rx_q(pf, pf_q, enable);
 
                /* wait for the change to finish */
                ret = i40e_pf_rxq_wait(pf, pf_q, enable);
@@ -4334,6 +4403,10 @@ static int i40e_vsi_control_rx(struct i40e_vsi *vsi, bool enable)
                }
        }
 
+       /* HW needs up to 50ms to finish RX queue disable*/
+       if (!enable)
+               mdelay(50);
+
        return ret;
 }
 
@@ -4360,6 +4433,10 @@ int i40e_vsi_start_rings(struct i40e_vsi *vsi)
  **/
 void i40e_vsi_stop_rings(struct i40e_vsi *vsi)
 {
+       /* When port TX is suspended, don't wait */
+       if (test_bit(__I40E_PORT_SUSPENDED, vsi->back->state))
+               return i40e_vsi_stop_rings_no_wait(vsi);
+
        /* do rx first for enable and last for disable
         * Ignore return value, we need to shutdown whatever we can
         */
@@ -4367,6 +4444,29 @@ void i40e_vsi_stop_rings(struct i40e_vsi *vsi)
        i40e_vsi_control_rx(vsi, false);
 }
 
+/**
+ * i40e_vsi_stop_rings_no_wait - Stop a VSI's rings and do not delay
+ * @vsi: the VSI being shutdown
+ *
+ * This function stops all the rings for a VSI but does not delay to verify
+ * that rings have been disabled. It is expected that the caller is shutting
+ * down multiple VSIs at once and will delay together for all the VSIs after
+ * initiating the shutdown. This is particularly useful for shutting down lots
+ * of VFs together. Otherwise, a large delay can be incurred while configuring
+ * each VSI in serial.
+ **/
+void i40e_vsi_stop_rings_no_wait(struct i40e_vsi *vsi)
+{
+       struct i40e_pf *pf = vsi->back;
+       int i, pf_q;
+
+       pf_q = vsi->base_queue;
+       for (i = 0; i < vsi->num_queue_pairs; i++, pf_q++) {
+               i40e_control_tx_q(pf, pf_q, false);
+               i40e_control_rx_q(pf, pf_q, false);
+       }
+}
+
 /**
  * i40e_vsi_free_irq - Free the irq association with the OS
  * @vsi: the VSI being configured
@@ -4404,7 +4504,7 @@ static void i40e_vsi_free_irq(struct i40e_vsi *vsi)
                        irq_set_affinity_notifier(irq_num, NULL);
 #endif
 #ifdef HAVE_IRQ_AFFINITY_HINT
-                       /* clear the affinity_mask in the IRQ descriptor */
+                       /* remove our suggested affinity mask for this IRQ */
                        irq_set_affinity_hint(irq_num, NULL);
 #endif
                        synchronize_irq(irq_num);
@@ -4569,11 +4669,10 @@ static void i40e_clear_interrupt_scheme(struct i40e_pf *pf)
 {
        int i;
 
-       i40e_stop_misc_vector(pf);
-       if (pf->flags & I40E_FLAG_MSIX_ENABLED && pf->msix_entries) {
-               synchronize_irq(pf->msix_entries[0].vector);
-               free_irq(pf->msix_entries[0].vector, pf);
-       }
+       i40e_free_misc_vector(pf);
+
+       i40e_put_lump(pf->irq_pile, pf->iwarp_base_vector,
+                     I40E_IWARP_IRQ_PILE_ID);
 
        i40e_put_lump(pf->irq_pile, 0, I40E_PILE_VALID_BIT-1);
        for (i = 0; i < pf->num_alloc_vsi; i++)
@@ -4593,8 +4692,12 @@ static void i40e_napi_enable_all(struct i40e_vsi *vsi)
        if (!vsi->netdev)
                return;
 
-       for (q_idx = 0; q_idx < vsi->num_q_vectors; q_idx++)
-               napi_enable(&vsi->q_vectors[q_idx]->napi);
+       for (q_idx = 0; q_idx < vsi->num_q_vectors; q_idx++) {
+               struct i40e_q_vector *q_vector = vsi->q_vectors[q_idx];
+
+               if (q_vector->tx.ring || q_vector->rx.ring)
+                       napi_enable(&q_vector->napi);
+       }
 }
 
 /**
@@ -4608,8 +4711,12 @@ static void i40e_napi_disable_all(struct i40e_vsi *vsi)
        if (!vsi->netdev)
                return;
 
-       for (q_idx = 0; q_idx < vsi->num_q_vectors; q_idx++)
-               napi_disable(&vsi->q_vectors[q_idx]->napi);
+       for (q_idx = 0; q_idx < vsi->num_q_vectors; q_idx++) {
+               struct i40e_q_vector *q_vector = vsi->q_vectors[q_idx];
+
+               if (q_vector->tx.ring || q_vector->rx.ring)
+                       napi_disable(&q_vector->napi);
+       }
 }
 
 /**
@@ -4618,12 +4725,16 @@ static void i40e_napi_disable_all(struct i40e_vsi *vsi)
  **/
 static void i40e_vsi_close(struct i40e_vsi *vsi)
 {
-       if (!test_and_set_bit(__I40E_DOWN, &vsi->state))
+       struct i40e_pf *pf = vsi->back;
+       if (!test_and_set_bit(__I40E_VSI_DOWN, vsi->state))
                i40e_down(vsi);
        i40e_vsi_free_irq(vsi);
        i40e_vsi_free_tx_resources(vsi);
        i40e_vsi_free_rx_resources(vsi);
        vsi->current_netdev_flags = 0;
+       pf->flags |= I40E_FLAG_SERVICE_CLIENT_REQUESTED;
+       if (test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state))
+               pf->flags |=  I40E_FLAG_CLIENT_RESET;
 }
 
 /**
@@ -4632,18 +4743,10 @@ static void i40e_vsi_close(struct i40e_vsi *vsi)
  **/
 void i40e_quiesce_vsi(struct i40e_vsi *vsi)
 {
-       if (test_bit(__I40E_DOWN, &vsi->state))
+       if (test_bit(__I40E_VSI_DOWN, vsi->state))
                return;
 
-       /* No need to disable FCoE VSI when Tx suspended */
-       if ((test_bit(__I40E_PORT_TX_SUSPENDED, &vsi->back->state)) &&
-            vsi->type == I40E_VSI_FCOE) {
-               dev_dbg(&vsi->back->pdev->dev,
-                        "VSI seid %d skipping FCoE VSI disable\n", vsi->seid);
-               return;
-       }
-
-       set_bit(__I40E_NEEDS_RESTART, &vsi->state);
+       set_bit(__I40E_VSI_NEEDS_RESTART, vsi->state);
        if (vsi->netdev && netif_running(vsi->netdev))
 #ifdef HAVE_NET_DEVICE_OPS
                vsi->netdev->netdev_ops->ndo_stop(vsi->netdev);
@@ -4660,10 +4763,9 @@ void i40e_quiesce_vsi(struct i40e_vsi *vsi)
  **/
 void i40e_unquiesce_vsi(struct i40e_vsi *vsi)
 {
-       if (!test_bit(__I40E_NEEDS_RESTART, &vsi->state))
+       if (!test_and_clear_bit(__I40E_VSI_NEEDS_RESTART, vsi->state))
                return;
 
-       clear_bit(__I40E_NEEDS_RESTART, &vsi->state);
        if (vsi->netdev && netif_running(vsi->netdev))
 #ifdef HAVE_NET_DEVICE_OPS
                vsi->netdev->netdev_ops->ndo_open(vsi->netdev);
@@ -4702,21 +4804,20 @@ void i40e_pf_unquiesce_all_vsi(struct i40e_pf *pf)
        }
 }
 
-#ifdef CONFIG_DCB
 /**
  * i40e_vsi_wait_queues_disabled - Wait for VSI's queues to be disabled
  * @vsi: the VSI being configured
  *
- * This function waits for the given VSI's queues to be disabled.
+ * Wait until all queues on a given VSI have been disabled.
 **/
-static int i40e_vsi_wait_queues_disabled(struct i40e_vsi *vsi)
+int i40e_vsi_wait_queues_disabled(struct i40e_vsi *vsi)
 {
        struct i40e_pf *pf = vsi->back;
        int i, pf_q, ret;
 
        pf_q = vsi->base_queue;
        for (i = 0; i < vsi->num_queue_pairs; i++, pf_q++) {
-               /* Check and wait for the disable status of the queue */
+               /* Check and wait for the Tx queue */
                ret = i40e_pf_txq_wait(pf, pf_q, false);
                if (ret) {
                        dev_info(&pf->pdev->dev,
@@ -4724,11 +4825,8 @@ static int i40e_vsi_wait_queues_disabled(struct i40e_vsi *vsi)
                                 vsi->seid, pf_q);
                        return ret;
                }
-       }
 
-       pf_q = vsi->base_queue;
-       for (i = 0; i < vsi->num_queue_pairs; i++, pf_q++) {
-               /* Check and wait for the disable status of the queue */
+               /* Check and wait for the Tx queue */
                ret = i40e_pf_rxq_wait(pf, pf_q, false);
                if (ret) {
                        dev_info(&pf->pdev->dev,
@@ -4741,6 +4839,7 @@ static int i40e_vsi_wait_queues_disabled(struct i40e_vsi *vsi)
        return 0;
 }
 
+#ifdef CONFIG_DCB
 /**
  * i40e_pf_wait_queues_disabled - Wait for all queues of PF VSIs to be disabled
  * @pf: the PF
@@ -4753,8 +4852,7 @@ static int i40e_pf_wait_queues_disabled(struct i40e_pf *pf)
        int v, ret = 0;
 
        for (v = 0; v < pf->hw.func_caps.num_vsis; v++) {
-               /* No need to wait for FCoE VSI queues */
-               if (pf->vsi[v] && pf->vsi[v]->type != I40E_VSI_FCOE) {
+               if (pf->vsi[v]) {
                        ret = i40e_vsi_wait_queues_disabled(pf->vsi[v]);
                        if (ret)
                                break;
@@ -5124,6 +5222,12 @@ int i40e_vsi_config_tc(struct i40e_vsi *vsi, u8 enabled_tc)
        ctxt.info = vsi->info;
        i40e_vsi_setup_queue_map(vsi, &ctxt, enabled_tc, false);
 
+       if (vsi->back->flags & I40E_FLAG_IWARP_ENABLED) {
+               ctxt.info.valid_sections |=
+                               cpu_to_le16(I40E_AQ_VSI_PROP_QUEUE_OPT_VALID);
+               ctxt.info.queueing_opt_flags |= I40E_AQ_VSI_QUE_OPT_TCP_ENA;
+       }
+
        /* Update the VSI after updating the VSI queue-mapping information */
        ret = i40e_aq_update_vsi_params(&vsi->back->hw, &ctxt, NULL);
        if (ret) {
@@ -5240,20 +5344,12 @@ static void i40e_dcb_reconfigure(struct i40e_pf *pf)
                        continue;
 
                /* - Enable all TCs for the LAN VSI
-#ifdef I40E_FCOE
-                * - For FCoE VSI only enable the TC configured
-                *   as per the APP TLV
-#endif
                 * - For all others keep them at TC0 for now
                 */
                if (v == pf->lan_vsi)
                        tc_map = i40e_pf_get_tc_map(pf);
                else
                        tc_map = I40E_DEFAULT_TRAFFIC_CLASS;
-#ifdef I40E_FCOE
-               if (pf->vsi[v]->type == I40E_VSI_FCOE)
-                       tc_map = i40e_get_fcoe_tc_map(pf);
-#endif /* #ifdef I40E_FCOE */
 
                ret = i40e_vsi_config_tc(pf->vsi[v], tc_map);
                if (ret) {
@@ -5291,7 +5387,7 @@ static int i40e_resume_port_tx(struct i40e_pf *pf)
                          i40e_stat_str(&pf->hw, ret),
                          i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status));
                /* Schedule PF reset to recover */
-               set_bit(__I40E_PF_RESET_REQUESTED, &pf->state);
+               set_bit(__I40E_PF_RESET_REQUESTED, pf->state);
                i40e_service_event_schedule(pf);
        }
 
@@ -5311,7 +5407,7 @@ static int i40e_init_pf_dcb(struct i40e_pf *pf)
        int err = 0;
 
        /* Do not enable DCB for SW1 and SW2 images even if the FW is capable */
-       if (pf->flags & I40E_FLAG_NO_DCB_SUPPORT)
+       if (pf->hw_features & I40E_HW_NO_DCB_SUPPORT)
                goto out;
 
        /* Get the initial DCB configuration */
@@ -5322,9 +5418,6 @@ static int i40e_init_pf_dcb(struct i40e_pf *pf)
                    (hw->dcbx_status == I40E_DCBX_STATUS_DISABLED)) {
                        dev_info(&pf->pdev->dev,
                                 "DCBX offload is not supported or is disabled for this PF.\n");
-
-                       if (pf->flags & I40E_FLAG_MFP_ENABLED)
-                               goto out;
                } else {
                        /* When status is not DISABLED then DCBX in FW */
                        pf->dcbx_cap = DCB_CAP_DCBX_LLD_MANAGED |
@@ -5362,12 +5455,14 @@ out:
 void i40e_print_link_message(struct i40e_vsi *vsi, bool isup)
 {
        enum i40e_aq_link_speed new_speed;
+       struct i40e_pf *pf = vsi->back;
        char *speed = "Unknown ";
        char *fc = "Unknown";
        char *fec = "";
+       char *req_fec = "";
        char *an = "";
 
-       new_speed = vsi->back->hw.phy.link_info.link_speed;
+       new_speed = pf->hw.phy.link_info.link_speed;
 
        if ((vsi->current_isup == isup) && (vsi->current_speed == new_speed))
                return;
@@ -5383,13 +5478,13 @@ void i40e_print_link_message(struct i40e_vsi *vsi, bool isup)
        /* Warn user if link speed on NPAR enabled partition is not at
         * least 10GB
         */
-       if (vsi->back->hw.func_caps.npar_enable &&
-           (vsi->back->hw.phy.link_info.link_speed == I40E_LINK_SPEED_1GB ||
-            vsi->back->hw.phy.link_info.link_speed == I40E_LINK_SPEED_100MB))
+       if (pf->hw.func_caps.npar_enable &&
+           (pf->hw.phy.link_info.link_speed == I40E_LINK_SPEED_1GB ||
+            pf->hw.phy.link_info.link_speed == I40E_LINK_SPEED_100MB))
                netdev_warn(vsi->netdev,
                            "The partition detected link speed that is less than 10Gbps\n");
 
-       switch (vsi->back->hw.phy.link_info.link_speed) {
+       switch (pf->hw.phy.link_info.link_speed) {
        case I40E_LINK_SPEED_40GB:
                speed = "40 G";
                break;
@@ -5412,7 +5507,7 @@ void i40e_print_link_message(struct i40e_vsi *vsi, bool isup)
                break;
        }
 
-       switch (vsi->back->hw.fc.current_mode) {
+       switch (pf->hw.fc.current_mode) {
        case I40E_FC_FULL:
                fc = "RX/TX";
                break;
@@ -5427,23 +5522,36 @@ void i40e_print_link_message(struct i40e_vsi *vsi, bool isup)
                break;
        }
 
-       if (vsi->back->hw.phy.link_info.link_speed == I40E_LINK_SPEED_25GB) {
+       if (pf->hw.phy.link_info.link_speed == I40E_LINK_SPEED_25GB) {
+               req_fec = ", Requested FEC: None";
                fec = ", FEC: None";
                an = ", Autoneg: False";
 
-               if (vsi->back->hw.phy.link_info.an_info & I40E_AQ_AN_COMPLETED)
+               if (pf->hw.phy.link_info.an_info & I40E_AQ_AN_COMPLETED)
                        an = ", Autoneg: True";
 
-               if (vsi->back->hw.phy.link_info.fec_info &
+               if (pf->hw.phy.link_info.fec_info &
                    I40E_AQ_CONFIG_FEC_KR_ENA)
                        fec = ", FEC: CL74 FC-FEC/BASE-R";
-               else if (vsi->back->hw.phy.link_info.fec_info &
+               else if (pf->hw.phy.link_info.fec_info &
                         I40E_AQ_CONFIG_FEC_RS_ENA)
                        fec = ", FEC: CL108 RS-FEC";
+
+               /* 'CL108 RS-FEC' should be displayed when RS is requested, or
+                * both RS and FC are requested
+                */
+               if (pf->hw.phy.link_info.req_fec_info &
+                   (I40E_AQ_REQUEST_FEC_KR | I40E_AQ_REQUEST_FEC_RS)) {
+                       if (pf->hw.phy.link_info.req_fec_info &
+                           I40E_AQ_REQUEST_FEC_RS)
+                               req_fec = ", Requested FEC: CL108 RS-FEC";
+                       else
+                               req_fec = ", Requested FEC: CL74 FC-FEC/BASE-R";
+               }
        }
 
-       netdev_info(vsi->netdev, "NIC Link is Up, %sbps Full Duplex%s%s, Flow Control: %s\n",
-                   speed, fec, an, fc);
+       netdev_info(vsi->netdev, "NIC Link is Up, %sbps Full Duplex%s%s%s, Flow Control: %s\n",
+                   speed, req_fec, fec, an, fc);
 }
 
 /**
@@ -5465,7 +5573,7 @@ static int i40e_up_complete(struct i40e_vsi *vsi)
        if (err)
                return err;
 
-       clear_bit(__I40E_DOWN, &vsi->state);
+       clear_bit(__I40E_VSI_DOWN, vsi->state);
        i40e_napi_enable_all(vsi);
        i40e_vsi_enable_irq(vsi);
 
@@ -5474,30 +5582,20 @@ static int i40e_up_complete(struct i40e_vsi *vsi)
                i40e_print_link_message(vsi, true);
                netif_tx_start_all_queues(vsi->netdev);
                netif_carrier_on(vsi->netdev);
-       } else if (vsi->netdev) {
-               i40e_print_link_message(vsi, false);
-               /* need to check for qualified module here*/
-               if ((pf->hw.phy.link_info.link_info &
-                       I40E_AQ_MEDIA_AVAILABLE) &&
-                   (!(pf->hw.phy.link_info.an_info &
-                       I40E_AQ_QUALIFIED_MODULE)))
-                       netdev_err(vsi->netdev,
-                                  "the driver failed to link because an unqualified module was detected.");
        }
 
        /* replay flow filters */
        if (vsi->type == I40E_VSI_FDIR) {
                /* reset fd counters */
                pf->fd_add_err = pf->fd_atr_cnt = 0;
-               if (pf->fd_tcp_rule > 0) {
-                       pf->hw_disabled_flags |= I40E_FLAG_FD_ATR_ENABLED;
-                       if (I40E_DEBUG_FD & pf->hw.debug_mask)
-                               dev_info(&pf->pdev->dev, "Forcing ATR off, sideband rules for TCP/IPv4 exist\n");
-                       pf->fd_tcp_rule = 0;
-               }
                i40e_fdir_filter_restore(vsi);
                i40e_cloud_filter_restore(pf);
        }
+
+       /* On the next run of the service_task, notify any clients of the new
+        * opened netdev
+        */
+       pf->flags |= I40E_FLAG_SERVICE_CLIENT_REQUESTED;
        i40e_service_event_schedule(pf);
 
        return 0;
@@ -5515,12 +5613,12 @@ static void i40e_vsi_reinit_locked(struct i40e_vsi *vsi)
        struct i40e_pf *pf = vsi->back;
 
        WARN_ON(in_interrupt());
-       while (test_and_set_bit(__I40E_CONFIG_BUSY, &pf->state))
+       while (test_and_set_bit(__I40E_CONFIG_BUSY, pf->state))
                usleep_range(1000, 2000);
        i40e_down(vsi);
 
        i40e_up(vsi);
-       clear_bit(__I40E_CONFIG_BUSY, &pf->state);
+       clear_bit(__I40E_CONFIG_BUSY, pf->state);
 }
 
 /**
@@ -5538,6 +5636,72 @@ int i40e_up(struct i40e_vsi *vsi)
        return err;
 }
 
+/**
+ * i40e_force_link_state - Force the link status
+ * @pf: board private structure
+ * @is_up: whether the link state should be forced up or down
+ **/
+static void i40e_force_link_state(struct i40e_pf *pf, bool is_up)
+{
+       struct i40e_aq_get_phy_abilities_resp abilities;
+       struct i40e_aq_set_phy_config config = {0};
+       struct i40e_hw *hw = &pf->hw;
+       enum i40e_aq_phy_type cnt;
+       u64 mask = 0;
+       i40e_status err;
+
+       /* Get the current phy config */
+       err = i40e_aq_get_phy_capabilities(hw, false, false, &abilities,
+                                          NULL);
+       if (err)
+               dev_dbg(&pf->pdev->dev,
+                       "failed to get phy cap., ret =  %s last_status =  %s\n",
+                       i40e_stat_str(hw, err),
+                       i40e_aq_str(hw, hw->aq.asq_last_status));
+
+       /* If link needs to go up, but was not forced to go down,
+        * no need for a flap
+        */
+       if (is_up && abilities.phy_type != 0)
+               return;
+
+       /* To force link we need to set bits for all supported PHY types,
+        * but there are now more than 32, so we need to split the bitmap
+        * across two fields.
+        */
+       for (cnt = I40E_PHY_TYPE_SGMII; cnt < I40E_PHY_TYPE_MAX; cnt++)
+               mask |= (1ULL << cnt);
+
+       config.phy_type = is_up ? cpu_to_le32((u32)(mask & 0xffffffff)) : 0;
+       config.phy_type_ext = is_up ? (u8)((mask >> 32) & 0xff) : 0;
+       /* Copy the old settings, except of phy_type */
+       config.abilities = abilities.abilities;
+       config.link_speed = abilities.link_speed;
+       config.eee_capability = abilities.eee_capability;
+       config.eeer = abilities.eeer_val;
+       config.low_power_ctrl = abilities.d3_lpan;
+       err = i40e_aq_set_phy_config(hw, &config, NULL);
+
+       if (err)
+               dev_dbg(&pf->pdev->dev,
+                       "set phy config ret =  %s last_status =  %s\n",
+                       i40e_stat_str(&pf->hw, err),
+                       i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status));
+
+       /* Update the link info */
+       err = i40e_update_link_info(hw);
+       if (err) {
+               /* Wait a little bit (on 40G cards it sometimes takes a really
+                * long time for link to come back from the atomic reset)
+                * and try once more
+                */
+               msleep(1000);
+               i40e_update_link_info(hw);
+       }
+
+       i40e_aq_set_link_restart_an(hw, true, NULL);
+}
+
 /**
  * i40e_down - Shutdown the connection processing
  * @vsi: the VSI being stopped
@@ -5547,7 +5711,7 @@ void i40e_down(struct i40e_vsi *vsi)
        int i;
 
        /* It is assumed that the caller of this function
-        * sets the vsi->state __I40E_DOWN bit.
+        * sets the vsi->state __I40E_VSI_DOWN bit.
         */
        if (vsi->netdev) {
                netif_carrier_off(vsi->netdev);
@@ -5555,6 +5719,9 @@ void i40e_down(struct i40e_vsi *vsi)
        }
        i40e_vsi_disable_irq(vsi);
        i40e_vsi_stop_rings(vsi);
+       if ((vsi->type == I40E_VSI_MAIN) &&
+           (vsi->back->flags & I40E_FLAG_LINK_DOWN_ON_CLOSE_ENABLED))
+               i40e_force_link_state(vsi->back, false);
        i40e_napi_disable_all(vsi);
 
        for (i = 0; i < vsi->num_queue_pairs; i++) {
@@ -5570,11 +5737,7 @@ void i40e_down(struct i40e_vsi *vsi)
  * @netdev: net device to configure
  * @tc: number of traffic classes to enable
  **/
-#ifdef I40E_FCOE
-int i40e_setup_tc(struct net_device *netdev, u8 tc)
-#else
 static int i40e_setup_tc(struct net_device *netdev, u8 tc)
-#endif
 {
        struct i40e_netdev_priv *np = netdev_priv(netdev);
        struct i40e_vsi *vsi = np->vsi;
@@ -5628,9 +5791,10 @@ exit:
 }
 
 #ifdef NETIF_F_HW_TC
-#ifdef I40E_FCOE
-int __i40e_setup_tc(struct net_device *netdev, u32 handle, __be16 proto,
-                   struct tc_to_netdev *tc)
+#ifdef HAVE_NDO_SETUP_TC_CHAIN_INDEX
+static int __i40e_setup_tc(struct net_device *netdev, u32 handle,
+                          u32 chain_index, __be16 proto,
+                          struct tc_to_netdev *tc)
 #else
 static int __i40e_setup_tc(struct net_device *netdev, u32 handle, __be16 proto,
                           struct tc_to_netdev *tc)
@@ -5638,7 +5802,14 @@ static int __i40e_setup_tc(struct net_device *netdev, u32 handle, __be16 proto,
 {
        if (tc->type != TC_SETUP_MQPRIO)
                return -EINVAL;
+
+#ifdef TC_MQPRIO_HW_OFFLOAD_MAX
+       tc->mqprio->hw = TC_MQPRIO_HW_OFFLOAD_TCS;
+
+       return i40e_setup_tc(netdev, tc->mqprio->num_tc);
+#else
        return i40e_setup_tc(netdev, tc->tc);
+#endif
 }
 #endif /* NETIF_F_HW_TC */
 #endif /* HAVE_SETUP_TC */
@@ -5663,12 +5834,14 @@ int i40e_open(struct net_device *netdev)
        int err;
 
        /* disallow open during test or if eeprom is broken */
-       if (test_bit(__I40E_TESTING, &pf->state) ||
-           test_bit(__I40E_BAD_EEPROM, &pf->state))
+       if (test_bit(__I40E_TESTING, pf->state) ||
+           test_bit(__I40E_BAD_EEPROM, pf->state))
                return -EBUSY;
 
        netif_carrier_off(netdev);
 
+       i40e_force_link_state(pf, true);
+
        err = i40e_vsi_open(vsi);
        if (err)
                return err;
@@ -5687,7 +5860,7 @@ int i40e_open(struct net_device *netdev)
 #endif /* HAVE_VXLAN_RX_OFFLOAD */
 #ifdef HAVE_GENEVE_RX_OFFLOAD
 #if IS_ENABLED(CONFIG_GENEVE)
-       if (pf->flags & I40E_FLAG_GENEVE_OFFLOAD_CAPABLE)
+       if (pf->hw_features & I40E_HW_GENEVE_OFFLOAD_CAPABLE)
                geneve_get_rx_port(netdev);
 #endif
 #endif /* HAVE_GENEVE_RX_OFFLOAD */
@@ -5705,6 +5878,8 @@ int i40e_open(struct net_device *netdev)
  * Finish initialization of the VSI.
  *
  * Returns 0 on success, negative value on failure
+ *
+ * Note: expects to be called while under rtnl_lock()
  **/
 int i40e_vsi_open(struct i40e_vsi *vsi)
 {
@@ -5733,6 +5908,7 @@ int i40e_vsi_open(struct i40e_vsi *vsi)
 
                /* Notify the stack of the actual queue counts. */
                netif_set_real_num_tx_queues(vsi->netdev, vsi->num_queue_pairs);
+               qdisc_reset_all_tx(vsi->netdev);
 
                err = netif_set_real_num_rx_queues(vsi->netdev,
                                                   vsi->num_queue_pairs);
@@ -5765,57 +5941,11 @@ err_setup_rx:
 err_setup_tx:
        i40e_vsi_free_tx_resources(vsi);
        if (vsi == pf->vsi[pf->lan_vsi])
-               i40e_do_reset(pf, BIT_ULL(__I40E_PF_RESET_REQUESTED));
+               i40e_do_reset(pf, BIT_ULL(__I40E_PF_RESET_REQUESTED), true);
 
        return err;
 }
 
-/**
- * i40e_cleanup_flex_filter - Cleans up the flex filter state and registers
- * @pf: Pointer to PF
- *
- * This function programs relevant register to good known initial state
- * which were programmed as part of adding flow director flex filter
- **/
-static void i40e_cleanup_flex_filter(struct i40e_pf *pf)
-{
-       int i;
-
-       if (unlikely(!pf))
-               return;
-
-       /* Reset flow specific flex registers to default state */
-       for (i = 0; i < I40E_MAX_FLEX_PIT_REG; i++)
-               i40e_write_rx_ctl(&pf->hw, I40E_PRTQF_FLX_PIT(i), 0);
-
-       /* Reset flow specific input set register to default state */
-       if (pf->fd_tcp4_input_set)
-               i40e_write_fd_input_set(pf,
-                                       I40E_FILTER_PCTYPE_NONF_IPV4_TCP,
-                                       pf->fd_tcp4_input_set);
-       if (pf->fd_udp4_input_set)
-               i40e_write_fd_input_set(pf,
-                                       I40E_FILTER_PCTYPE_NONF_IPV4_UDP,
-                                       pf->fd_udp4_input_set);
-       if (pf->fd_sctp4_input_set)
-               i40e_write_fd_input_set(pf,
-                                       I40E_FILTER_PCTYPE_NONF_IPV4_SCTP,
-                                       pf->fd_sctp4_input_set);
-       if (pf->fd_ip4_input_set)
-               i40e_write_fd_input_set(pf,
-                                       I40E_FILTER_PCTYPE_NONF_IPV4_OTHER,
-                                       pf->fd_ip4_input_set);
-       pf->fd_tcp4_input_set = 0;
-       pf->fd_udp4_input_set = 0;
-       pf->fd_sctp4_input_set = 0;
-       pf->fd_ip4_input_set = 0;
-       pf->fd_tcp4_filter_cnt = 0;
-       pf->fd_udp4_filter_cnt = 0;
-       pf->fd_sctp4_filter_cnt = 0;
-       pf->fd_ip4_filter_cnt = 0;
-       pf->fd_flex_filter_cnt = 0;
-}
-
 /**
  * i40e_fdir_filter_exit - Cleans up the Flow Director accounting
  * @pf: Pointer to PF
@@ -5826,6 +5956,7 @@ static void i40e_cleanup_flex_filter(struct i40e_pf *pf)
 static void i40e_fdir_filter_exit(struct i40e_pf *pf)
 {
        struct i40e_fdir_filter *filter;
+       struct i40e_flex_pit *pit_entry, *tmp;
        struct hlist_node *node2;
 
        hlist_for_each_entry_safe(filter, node2,
@@ -5834,8 +5965,42 @@ static void i40e_fdir_filter_exit(struct i40e_pf *pf)
                kfree(filter);
        }
 
-       /* Cleanup state related to flow director flex filter */
-       i40e_cleanup_flex_filter(pf);
+       list_for_each_entry_safe(pit_entry, tmp, &pf->l3_flex_pit_list, list) {
+               list_del(&pit_entry->list);
+               kfree(pit_entry);
+       }
+       INIT_LIST_HEAD(&pf->l3_flex_pit_list);
+
+       list_for_each_entry_safe(pit_entry, tmp, &pf->l4_flex_pit_list, list) {
+               list_del(&pit_entry->list);
+               kfree(pit_entry);
+       }
+       INIT_LIST_HEAD(&pf->l4_flex_pit_list);
+
+       pf->fdir_pf_active_filters = 0;
+       pf->fd_tcp4_filter_cnt = 0;
+       pf->fd_udp4_filter_cnt = 0;
+       pf->fd_sctp4_filter_cnt = 0;
+       pf->fd_ip4_filter_cnt = 0;
+
+       /* Reprogram the default input set for TCP/IPv4 */
+       i40e_write_fd_input_set(pf, I40E_FILTER_PCTYPE_NONF_IPV4_TCP,
+                               I40E_L3_SRC_MASK | I40E_L3_DST_MASK |
+                               I40E_L4_SRC_MASK | I40E_L4_DST_MASK);
+
+       /* Reprogram the default input set for UDP/IPv4 */
+       i40e_write_fd_input_set(pf, I40E_FILTER_PCTYPE_NONF_IPV4_UDP,
+                               I40E_L3_SRC_MASK | I40E_L3_DST_MASK |
+                               I40E_L4_SRC_MASK | I40E_L4_DST_MASK);
+
+       /* Reprogram the default input set for SCTP/IPv4 */
+       i40e_write_fd_input_set(pf, I40E_FILTER_PCTYPE_NONF_IPV4_SCTP,
+                               I40E_L3_SRC_MASK | I40E_L3_DST_MASK |
+                               I40E_L4_SRC_MASK | I40E_L4_DST_MASK);
+
+       /* Reprogram the default input set for Other/IPv4 */
+       i40e_write_fd_input_set(pf, I40E_FILTER_PCTYPE_NONF_IPV4_OTHER,
+                               I40E_L3_SRC_MASK | I40E_L3_DST_MASK);
 }
 
 /**
@@ -5881,12 +6046,14 @@ int i40e_close(struct net_device *netdev)
  * i40e_do_reset - Start a PF or Core Reset sequence
  * @pf: board private structure
  * @reset_flags: which reset is requested
+ * @lock_acquired: indicates whether or not the lock has been acquired
+ * before this function was called.
  *
  * The essential difference in resets is that the PF Reset
  * doesn't clear the packet buffers, doesn't reset the PE
  * firmware, and doesn't bother the other PFs on the chip.
  **/
-void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags)
+void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags, bool lock_acquired)
 {
        u32 val;
 
@@ -5932,7 +6099,7 @@ void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags)
                 * for the Core Reset.
                 */
                dev_dbg(&pf->pdev->dev, "PFR requested\n");
-               i40e_handle_reset_warning(pf);
+               i40e_handle_reset_warning(pf, lock_acquired);
 
        } else if (reset_flags & BIT_ULL(__I40E_REINIT_REQUESTED)) {
                int v;
@@ -5944,10 +6111,9 @@ void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags)
                        struct i40e_vsi *vsi = pf->vsi[v];
 
                        if (vsi != NULL &&
-                           test_bit(__I40E_REINIT_REQUESTED, &vsi->state)) {
+                           test_and_clear_bit(__I40E_VSI_REINIT_REQUESTED,
+                                              vsi->state))
                                i40e_vsi_reinit_locked(pf->vsi[v]);
-                               clear_bit(__I40E_REINIT_REQUESTED, &vsi->state);
-                       }
                }
        } else if (reset_flags & BIT_ULL(__I40E_DOWN_REQUESTED)) {
                int v;
@@ -5958,10 +6124,10 @@ void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags)
                        struct i40e_vsi *vsi = pf->vsi[v];
 
                        if (vsi != NULL &&
-                           test_bit(__I40E_DOWN_REQUESTED, &vsi->state)) {
-                               set_bit(__I40E_DOWN, &vsi->state);
+                           test_and_clear_bit(__I40E_VSI_DOWN_REQUESTED,
+                                              vsi->state)) {
+                               set_bit(__I40E_VSI_DOWN, vsi->state);
                                i40e_down(vsi);
-                               clear_bit(__I40E_DOWN_REQUESTED, &vsi->state);
                        }
                }
        } else {
@@ -5979,7 +6145,7 @@ void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags)
 void i40e_do_reset_safe(struct i40e_pf *pf, u32 reset_flags)
 {
        rtnl_lock();
-       i40e_do_reset(pf, reset_flags);
+       i40e_do_reset(pf, reset_flags, true);
        rtnl_unlock();
 }
 
@@ -6116,7 +6282,7 @@ static int i40e_handle_lldp_event(struct i40e_pf *pf,
        else
                pf->flags &= ~I40E_FLAG_DCB_ENABLED;
 
-       set_bit(__I40E_PORT_TX_SUSPENDED, &pf->state);
+       set_bit(__I40E_PORT_SUSPENDED, pf->state);
        /* Reconfiguration needed quiesce all VSIs */
        i40e_pf_quiesce_all_vsi(pf);
 
@@ -6125,7 +6291,7 @@ static int i40e_handle_lldp_event(struct i40e_pf *pf,
 
        ret = i40e_resume_port_tx(pf);
 
-       clear_bit(__I40E_PORT_TX_SUSPENDED, &pf->state);
+       clear_bit(__I40E_PORT_SUSPENDED, pf->state);
        /* In case of error no point in resuming VSIs */
        if (ret)
                goto exit;
@@ -6134,10 +6300,12 @@ static int i40e_handle_lldp_event(struct i40e_pf *pf,
        ret = i40e_pf_wait_queues_disabled(pf);
        if (ret) {
                /* Schedule PF reset to recover */
-               set_bit(__I40E_PF_RESET_REQUESTED, &pf->state);
+               set_bit(__I40E_PF_RESET_REQUESTED, pf->state);
                i40e_service_event_schedule(pf);
        } else {
                i40e_pf_unquiesce_all_vsi(pf);
+       pf->flags |= (I40E_FLAG_SERVICE_CLIENT_REQUESTED |
+                     I40E_FLAG_CLIENT_L2_CHANGE);
        }
 
 exit:
@@ -6234,34 +6402,33 @@ void i40e_fdir_check_and_reenable(struct i40e_pf *pf)
        u32 fcnt_prog, fcnt_avail;
        struct hlist_node *node;
 
-       if (test_bit(__I40E_FD_FLUSH_REQUESTED, &pf->state))
+       if (test_bit(__I40E_FD_FLUSH_REQUESTED, pf->state))
                return;
 
-       /* Check if, FD SB or ATR was auto disabled and if there is enough room
-        * to re-enable
-        */
+       /* Check if we have enough room to re-enable FDir SB capability. */
        fcnt_prog = i40e_get_global_fd_count(pf);
        fcnt_avail = pf->fdir_pf_filter_count;
        if ((fcnt_prog < (fcnt_avail - I40E_FDIR_BUFFER_HEAD_ROOM)) ||
            (pf->fd_add_err == 0) ||
            (i40e_get_current_atr_cnt(pf) < pf->fd_atr_cnt)) {
-               if ((pf->flags & I40E_FLAG_FD_SB_ENABLED) &&
-                   (pf->hw_disabled_flags & I40E_FLAG_FD_SB_ENABLED)) {
-                       pf->hw_disabled_flags &= ~I40E_FLAG_FD_SB_ENABLED;
-                       if (I40E_DEBUG_FD & pf->hw.debug_mask)
+               if (pf->flags & I40E_FLAG_FD_SB_AUTO_DISABLED) {
+                       pf->flags &= ~I40E_FLAG_FD_SB_AUTO_DISABLED;
+                       if ((pf->flags & I40E_FLAG_FD_SB_ENABLED) &&
+                           (I40E_DEBUG_FD & pf->hw.debug_mask))
                                dev_info(&pf->pdev->dev, "FD Sideband/ntuple is being enabled since we have space in the table now\n");
                }
        }
 
-       /* Wait for some more space to be available to turn on ATR. We also
-        * must check that no existing ntuple rules for TCP are in effect
+       /* We should wait for even more space before re-enabling ATR.
+        * Additionally, we cannot enable ATR as long as we still have TCP SB
+        * rules active.
         */
-       if (fcnt_prog < (fcnt_avail - I40E_FDIR_BUFFER_HEAD_ROOM * 2)) {
-               if ((pf->flags & I40E_FLAG_FD_ATR_ENABLED) &&
-                   (pf->hw_disabled_flags & I40E_FLAG_FD_ATR_ENABLED) &&
-                   (pf->fd_tcp_rule == 0)) {
-                       pf->hw_disabled_flags &= ~I40E_FLAG_FD_ATR_ENABLED;
-                       if (I40E_DEBUG_FD & pf->hw.debug_mask)
+       if ((fcnt_prog < (fcnt_avail - I40E_FDIR_BUFFER_HEAD_ROOM_FOR_ATR)) &&
+           (pf->fd_tcp4_filter_cnt == 0)) {
+               if (pf->flags & I40E_FLAG_FD_ATR_AUTO_DISABLED) {
+                       pf->flags &= ~I40E_FLAG_FD_ATR_AUTO_DISABLED;
+                       if ((pf->flags & I40E_FLAG_FD_ATR_ENABLED) &&
+                           (I40E_DEBUG_FD & pf->hw.debug_mask))
                                dev_info(&pf->pdev->dev, "ATR is being enabled since we have space in the table and there are no conflicting ntuple rules\n");
                }
        }
@@ -6274,10 +6441,9 @@ void i40e_fdir_check_and_reenable(struct i40e_pf *pf)
                                hlist_del(&filter->fdir_node);
                                kfree(filter);
                                pf->fdir_pf_active_filters--;
+                               pf->fd_inv = 0;
                        }
                }
-               /* Cleanup state related to flow director flex filter */
-               i40e_cleanup_flex_filter(pf);
        }
 }
 
@@ -6314,7 +6480,7 @@ static void i40e_fdir_flush_and_replay(struct i40e_pf *pf)
        }
 
        pf->fd_flush_timestamp = jiffies;
-       pf->hw_disabled_flags |= I40E_FLAG_FD_ATR_ENABLED;
+       pf->flags |= I40E_FLAG_FD_ATR_AUTO_DISABLED;
        /* flush all filters */
        wr32(&pf->hw, I40E_PFQF_CTL_1,
             I40E_PFQF_CTL_1_CLEARFDTABLE_MASK);
@@ -6334,9 +6500,9 @@ static void i40e_fdir_flush_and_replay(struct i40e_pf *pf)
        } else {
                /* replay sideband filters */
                i40e_fdir_filter_restore(pf->vsi[pf->lan_vsi]);
-               if (!disable_atr)
-                       pf->hw_disabled_flags &= ~I40E_FLAG_FD_ATR_ENABLED;
-               clear_bit(__I40E_FD_FLUSH_REQUESTED, &pf->state);
+               if (!disable_atr && !pf->fd_tcp4_filter_cnt)
+                       pf->flags &= ~I40E_FLAG_FD_ATR_AUTO_DISABLED;
+               clear_bit(__I40E_FD_FLUSH_REQUESTED, pf->state);
                if (I40E_DEBUG_FD & pf->hw.debug_mask)
                        dev_info(&pf->pdev->dev, "FD Filter table flushed and FD-SB replayed.\n");
        }
@@ -6365,10 +6531,10 @@ static void i40e_fdir_reinit_subtask(struct i40e_pf *pf)
 {
 
        /* if interface is down do nothing */
-       if (test_bit(__I40E_DOWN, &pf->state))
+       if (test_bit(__I40E_DOWN, pf->state))
                return;
 
-       if (test_bit(__I40E_FD_FLUSH_REQUESTED, &pf->state))
+       if (test_bit(__I40E_FD_FLUSH_REQUESTED, pf->state))
                i40e_fdir_flush_and_replay(pf);
 
        i40e_fdir_check_and_reenable(pf);
@@ -6382,14 +6548,11 @@ static void i40e_fdir_reinit_subtask(struct i40e_pf *pf)
  **/
 static void i40e_vsi_link_event(struct i40e_vsi *vsi, bool link_up)
 {
-       if (!vsi || (test_bit(__I40E_DOWN, &vsi->state)))
+       if (!vsi || (test_bit(__I40E_VSI_DOWN, vsi->state)))
                return;
 
        switch (vsi->type) {
        case I40E_VSI_MAIN:
-#ifdef I40E_FCOE
-       case I40E_VSI_FCOE:
-#endif
                if (!vsi->netdev || !vsi->netdev_registered)
                        break;
 
@@ -6405,6 +6568,7 @@ static void i40e_vsi_link_event(struct i40e_vsi *vsi, bool link_up)
        case I40E_VSI_SRIOV:
        case I40E_VSI_VMDQ2:
        case I40E_VSI_CTRL:
+       case I40E_VSI_IWARP:
        case I40E_VSI_MIRROR:
        default:
                /* there is no notification for other VSIs */
@@ -6459,10 +6623,10 @@ static void i40e_link_event(struct i40e_pf *pf)
        status = i40e_get_link_status(&pf->hw, &new_link);
 
        /* On success, disable temp link polling */
-       if (status == I40E_SUCCESS)
+       if (status == I40E_SUCCESS) {
                if (pf->flags & I40E_FLAG_TEMP_LINK_POLLING)
                        pf->flags &= ~I40E_FLAG_TEMP_LINK_POLLING;
-       if (status != I40E_SUCCESS) {
+       } else {
                /* Enable link polling temporarily until i40e_get_link_status
                 * returns I40E_SUCCESS
                 */
@@ -6477,12 +6641,11 @@ static void i40e_link_event(struct i40e_pf *pf)
 
        if (new_link == old_link &&
            new_link_speed == old_link_speed &&
-           (test_bit(__I40E_DOWN, &vsi->state) ||
+           (test_bit(__I40E_VSI_DOWN, vsi->state) ||
             new_link == netif_carrier_ok(vsi->netdev)))
                return;
 
-       if (!test_bit(__I40E_DOWN, &vsi->state))
-               i40e_print_link_message(vsi, new_link);
+       i40e_print_link_message(vsi, new_link);
 
        /* Notify the base of the switch tree connected to
         * the link.  Floating VEBs are not notified.
@@ -6510,8 +6673,8 @@ static void i40e_watchdog_subtask(struct i40e_pf *pf)
        int i;
 
        /* if interface is down do nothing */
-       if (test_bit(__I40E_DOWN, &pf->state) ||
-           test_bit(__I40E_CONFIG_BUSY, &pf->state))
+       if (test_bit(__I40E_DOWN, pf->state) ||
+           test_bit(__I40E_CONFIG_BUSY, pf->state))
                return;
 
        /* make sure we don't do these things too often */
@@ -6539,7 +6702,8 @@ static void i40e_watchdog_subtask(struct i40e_pf *pf)
        }
 #ifdef HAVE_PTP_1588_CLOCK
 
-       i40e_ptp_rx_hang(pf->vsi[pf->lan_vsi]);
+       i40e_ptp_rx_hang(pf);
+       i40e_ptp_tx_hang(pf);
 #endif /* HAVE_PTP_1588_CLOCK */
 }
 
@@ -6551,44 +6715,32 @@ static void i40e_reset_subtask(struct i40e_pf *pf)
 {
        u32 reset_flags = 0;
 
-       rtnl_lock();
-       if (test_bit(__I40E_REINIT_REQUESTED, &pf->state)) {
+       if (test_and_clear_bit(__I40E_REINIT_REQUESTED, pf->state))
                reset_flags |= BIT(__I40E_REINIT_REQUESTED);
-               clear_bit(__I40E_REINIT_REQUESTED, &pf->state);
-       }
-       if (test_bit(__I40E_PF_RESET_REQUESTED, &pf->state)) {
+       if (test_and_clear_bit(__I40E_PF_RESET_REQUESTED, pf->state))
                reset_flags |= BIT(__I40E_PF_RESET_REQUESTED);
-               clear_bit(__I40E_PF_RESET_REQUESTED, &pf->state);
-       }
-       if (test_bit(__I40E_CORE_RESET_REQUESTED, &pf->state)) {
+       if (test_and_clear_bit(__I40E_CORE_RESET_REQUESTED, pf->state))
                reset_flags |= BIT(__I40E_CORE_RESET_REQUESTED);
-               clear_bit(__I40E_CORE_RESET_REQUESTED, &pf->state);
-       }
-       if (test_bit(__I40E_GLOBAL_RESET_REQUESTED, &pf->state)) {
+       if (test_and_clear_bit(__I40E_GLOBAL_RESET_REQUESTED, pf->state))
                reset_flags |= BIT(__I40E_GLOBAL_RESET_REQUESTED);
-               clear_bit(__I40E_GLOBAL_RESET_REQUESTED, &pf->state);
-       }
-       if (test_bit(__I40E_DOWN_REQUESTED, &pf->state)) {
+       if (test_and_clear_bit(__I40E_DOWN_REQUESTED, pf->state))
                reset_flags |= BIT(__I40E_DOWN_REQUESTED);
-               clear_bit(__I40E_DOWN_REQUESTED, &pf->state);
-       }
 
        /* If there's a recovery already waiting, it takes
         * precedence before starting a new reset sequence.
         */
-       if (test_bit(__I40E_RESET_INTR_RECEIVED, &pf->state)) {
-               i40e_handle_reset_warning(pf);
-               goto unlock;
+       if (test_bit(__I40E_RESET_INTR_RECEIVED, pf->state)) {
+               i40e_prep_for_reset(pf, false);
+               i40e_reset(pf);
+               i40e_rebuild(pf, false, false);
        }
 
        /* If we're already down or resetting, just bail */
        if (reset_flags &&
-           !test_bit(__I40E_DOWN, &pf->state) &&
-           !test_bit(__I40E_CONFIG_BUSY, &pf->state))
-               i40e_do_reset(pf, reset_flags);
-
-unlock:
-       rtnl_unlock();
+           !test_bit(__I40E_DOWN, pf->state) &&
+           !test_bit(__I40E_CONFIG_BUSY, pf->state)) {
+               i40e_do_reset(pf, reset_flags, false);
+       }
 }
 
 /**
@@ -6610,12 +6762,26 @@ static void i40e_handle_link_event(struct i40e_pf *pf,
         */
        i40e_link_event(pf);
 
-       /* check for unqualified module, if link is down */
-       if ((status->link_info & I40E_AQ_MEDIA_AVAILABLE) &&
-           (!(status->an_info & I40E_AQ_QUALIFIED_MODULE)) &&
-           (!(status->link_info & I40E_AQ_LINK_UP)))
+       /* Check if module meets thermal requirements */
+       if (status->phy_type == I40E_PHY_TYPE_NOT_SUPPORTED_HIGH_TEMP) {
+               dev_err(&pf->pdev->dev,
+                       "Rx/Tx is disabled on this device because the module does not meet thermal requirements.\n");
                dev_err(&pf->pdev->dev,
-                       "The driver failed to link because an unqualified module was detected.\n");
+                       "Refer to the Intel(R) Ethernet Adapters and Devices User Guide for a list of supported modules.\n");
+       } else {
+               /* check for unqualified module, if link is down, suppress
+                * the message if link was forced to be down.
+                */
+               if ((status->link_info & I40E_AQ_MEDIA_AVAILABLE) &&
+                   (!(status->an_info & I40E_AQ_QUALIFIED_MODULE)) &&
+                   (!(status->link_info & I40E_AQ_LINK_UP)) &&
+                   (!(pf->flags & I40E_FLAG_LINK_DOWN_ON_CLOSE_ENABLED))) {
+                       dev_err(&pf->pdev->dev,
+                               "Rx/Tx is disabled on this device because an unsupported SFP+ module type was detected.\n");
+                       dev_err(&pf->pdev->dev,
+                               "Refer to the Intel(R) Ethernet Adapters and Devices User Guide for a list of supported modules.\n");
+               }
+       }
 }
 
 /**
@@ -6633,7 +6799,7 @@ static void i40e_clean_adminq_subtask(struct i40e_pf *pf)
        u32 val;
 
        /* Do not run clean AQ when PF reset fails */
-       if (test_bit(__I40E_RESET_FAILED, &pf->state))
+       if (test_bit(__I40E_RESET_FAILED, pf->state))
                return;
 
        /* check for error indications */
@@ -6734,9 +6900,11 @@ static void i40e_clean_adminq_subtask(struct i40e_pf *pf)
                                 opcode);
                        break;
                }
-       } while (pending && (i++ < pf->adminq_work_limit));
+       } while (i++ < pf->adminq_work_limit);
+
+       if (i < pf->adminq_work_limit)
+               clear_bit(__I40E_ADMINQ_EVENT_PENDING, pf->state);
 
-       clear_bit(__I40E_ADMINQ_EVENT_PENDING, &pf->state);
        /* re-enable Admin queue interrupt cause */
        val = rd32(hw, I40E_PFINT_ICR0_ENA);
        val |=  I40E_PFINT_ICR0_ENA_ADMINQ_MASK;
@@ -6761,13 +6929,13 @@ static void i40e_verify_eeprom(struct i40e_pf *pf)
                if (err) {
                        dev_info(&pf->pdev->dev, "eeprom check failed (%d), Tx/Rx traffic disabled\n",
                                 err);
-                       set_bit(__I40E_BAD_EEPROM, &pf->state);
+                       set_bit(__I40E_BAD_EEPROM, pf->state);
                }
        }
 
-       if (!err && test_bit(__I40E_BAD_EEPROM, &pf->state)) {
+       if (!err && test_bit(__I40E_BAD_EEPROM, pf->state)) {
                dev_info(&pf->pdev->dev, "eeprom check passed, Tx/Rx traffic enabled\n");
-               clear_bit(__I40E_BAD_EEPROM, &pf->state);
+               clear_bit(__I40E_BAD_EEPROM, pf->state);
        }
 }
 
@@ -7060,25 +7228,33 @@ static void i40e_fdir_teardown(struct i40e_pf *pf)
 /**
  * i40e_prep_for_reset - prep for the core to reset
  * @pf: board private structure
+ * @lock_acquired: indicates whether or not the lock has been acquired
+ * before this function was called.
  *
  * Close up the VFs and other things in prep for PF Reset.
   **/
-static void i40e_prep_for_reset(struct i40e_pf *pf)
+static void i40e_prep_for_reset(struct i40e_pf *pf, bool lock_acquired)
 {
        struct i40e_hw *hw = &pf->hw;
        i40e_status ret = 0;
        u32 v;
 
-       clear_bit(__I40E_RESET_INTR_RECEIVED, &pf->state);
-       if (test_and_set_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state))
+       clear_bit(__I40E_RESET_INTR_RECEIVED, pf->state);
+       if (test_and_set_bit(__I40E_RESET_RECOVERY_PENDING, pf->state))
                return;
        if (i40e_check_asq_alive(&pf->hw))
                i40e_vc_notify_reset(pf);
 
        dev_dbg(&pf->pdev->dev, "Tearing down internal switch for reset\n");
 
+       /* TODO: warn any registered clients */
        /* quiesce the VSIs and their queues that are not already DOWN */
+       /* pf_quiesce_all_vsi modifies netdev structures -rtnl_lock needed */
+       if (!lock_acquired)
+               rtnl_lock();
        i40e_pf_quiesce_all_vsi(pf);
+       if (!lock_acquired)
+               rtnl_unlock();
 
        for (v = 0; v < pf->num_alloc_vsi; v++) {
                if (pf->vsi[v])
@@ -7108,36 +7284,91 @@ static void i40e_send_version(struct i40e_pf *pf)
        dv.minor_version = DRV_VERSION_MINOR;
        dv.build_version = DRV_VERSION_BUILD;
        dv.subbuild_version = 0;
-       strncpy(dv.driver_string, DRV_VERSION, sizeof(dv.driver_string));
+       strlcpy(dv.driver_string, DRV_VERSION, sizeof(dv.driver_string));
        i40e_aq_send_driver_version(&pf->hw, &dv, NULL);
 }
 
 /**
- * i40e_reset_and_rebuild - reset and rebuild using a saved config
+ * i40e_get_oem_version - get OEM specific version information
+ * @hw: pointer to the hardware structure
+ **/
+static void i40e_get_oem_version(struct i40e_hw *hw)
+{
+       u16 block_offset = 0xffff;
+       u16 block_length = 0;
+       u16 capabilities = 0;
+       u16 gen_snap = 0;
+       u16 release = 0;
+
+#define I40E_SR_NVM_OEM_VERSION_PTR            0x1B
+#define I40E_NVM_OEM_LENGTH_OFFSET             0x00
+#define I40E_NVM_OEM_CAPABILITIES_OFFSET       0x01
+#define I40E_NVM_OEM_GEN_OFFSET                        0x02
+#define I40E_NVM_OEM_RELEASE_OFFSET            0x03
+#define I40E_NVM_OEM_CAPABILITIES_MASK         0x000F
+#define I40E_NVM_OEM_LENGTH                    3
+
+       /* Check if pointer to OEM version block is valid. */
+       i40e_read_nvm_word(hw, I40E_SR_NVM_OEM_VERSION_PTR, &block_offset);
+       if (block_offset == 0xffff)
+               return;
+
+       /* Check if OEM version block has correct length. */
+       i40e_read_nvm_word(hw, block_offset + I40E_NVM_OEM_LENGTH_OFFSET,
+                          &block_length);
+       if (block_length < I40E_NVM_OEM_LENGTH)
+               return;
+
+       /* Check if OEM version format is as expected. */
+       i40e_read_nvm_word(hw, block_offset + I40E_NVM_OEM_CAPABILITIES_OFFSET,
+                          &capabilities);
+       if ((capabilities & I40E_NVM_OEM_CAPABILITIES_MASK) != 0)
+               return;
+
+       i40e_read_nvm_word(hw, block_offset + I40E_NVM_OEM_GEN_OFFSET,
+                          &gen_snap);
+       i40e_read_nvm_word(hw, block_offset + I40E_NVM_OEM_RELEASE_OFFSET,
+                          &release);
+       hw->nvm.oem_ver = (gen_snap << I40E_OEM_SNAP_SHIFT) | release;
+       hw->nvm.eetrack = I40E_OEM_EETRACK_ID;
+}
+
+/**
+ * i40e_reset - wait for core reset to finish reset, reset pf if corer not seen
  * @pf: board private structure
- * @reinit: if the Main VSI needs to re-initialized.
  **/
-static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit)
+static int i40e_reset(struct i40e_pf *pf)
 {
        struct i40e_hw *hw = &pf->hw;
-       u8 set_fc_aq_fail = 0;
        i40e_status ret;
-       u32 val;
-       int v;
 
-       /* Now we wait for GRST to settle out.
-        * We don't have to delete the VEBs or VSIs from the hw switch
-        * because the reset will make them disappear.
-        */
        ret = i40e_pf_reset(hw);
        if (ret) {
                dev_info(&pf->pdev->dev, "PF reset failed, %d\n", ret);
-               set_bit(__I40E_RESET_FAILED, &pf->state);
-               goto clear_recovery;
+               set_bit(__I40E_RESET_FAILED, pf->state);
+               clear_bit(__I40E_RESET_RECOVERY_PENDING, pf->state);
+       } else {
+               pf->pfr_count++;
        }
-       pf->pfr_count++;
+       return ret;
+}
+
+/**
+ * i40e_rebuild - rebuild using a saved config
+ * @pf: board private structure
+ * @reinit: if the Main VSI needs to re-initialized.
+ * @lock_acquired: indicates whether or not the lock has been acquired
+ * before this function was called.
+ **/
+static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
+{
+       struct i40e_hw *hw = &pf->hw;
+       u8 set_fc_aq_fail = 0;
+       i40e_status ret;
+       u32 val;
+       int v;
 
-       if (test_bit(__I40E_DOWN, &pf->state))
+       if (test_bit(__I40E_DOWN, pf->state))
                goto clear_recovery;
        dev_dbg(&pf->pdev->dev, "Rebuilding internal switch\n");
 
@@ -7149,9 +7380,10 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit)
                         i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status));
                goto clear_recovery;
        }
+       i40e_get_oem_version(&pf->hw);
 
        /* re-verify the eeprom if we just had an EMP reset */
-       if (test_and_clear_bit(__I40E_EMP_RESET_INTR_RECEIVED, &pf->state))
+       if (test_and_clear_bit(__I40E_EMP_RESET_INTR_RECEIVED, pf->state))
                i40e_verify_eeprom(pf);
 
        i40e_clear_pxe_mode(hw);
@@ -7160,8 +7392,7 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit)
                goto end_core_reset;
 
        ret = i40e_init_lan_hmc(hw, hw->func_caps.num_tx_qp,
-                               hw->func_caps.num_rx_qp,
-                               pf->fcoe_hmc_cntx_num, pf->fcoe_hmc_filt_num);
+                               hw->func_caps.num_rx_qp, 0, 0);
        if (ret) {
                dev_info(&pf->pdev->dev, "init_lan_hmc failed: %d\n", ret);
                goto end_core_reset;
@@ -7181,14 +7412,12 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit)
        }
 
 #endif /* CONFIG_DCB */
-#ifdef I40E_FCOE
-       i40e_init_pf_fcoe(pf);
-
-#endif
        /* do basic switch setup */
+       if (!lock_acquired)
+               rtnl_lock();
        ret = i40e_setup_pf_switch(pf, reinit);
        if (ret)
-               goto end_core_reset;
+               goto end_unlock;
 
        /* The driver only wants link up/down and module qualification
         * reports from firmware.  Note the negative logic.
@@ -7259,7 +7488,7 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit)
                if (ret) {
                        dev_info(&pf->pdev->dev,
                                 "rebuild of Main VSI failed: %d\n", ret);
-                       goto end_core_reset;
+                       goto end_unlock;
                }
        }
 
@@ -7277,7 +7506,7 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit)
                wr32(hw, I40E_REG_MSS, val);
        }
 
-       if (pf->flags & I40E_FLAG_RESTART_AUTONEG) {
+       if (pf->hw_features & I40E_HW_RESTART_AUTONEG) {
                msleep(75);
                ret = i40e_aq_set_link_restart_an(&pf->hw, true, NULL);
                if (ret)
@@ -7302,18 +7531,46 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit)
        /* restart the VSIs that were rebuilt and running before the reset */
        i40e_pf_unquiesce_all_vsi(pf);
 
-       if (pf->num_alloc_vfs) {
-               for (v = 0; v < pf->num_alloc_vfs; v++)
-                       i40e_reset_vf(&pf->vf[v], true);
-       }
+       /* Release the RTNL lock before we start resetting VFs */
+       if (!lock_acquired)
+               rtnl_unlock();
 
+       i40e_reset_all_vfs(pf, true);
+
+       /* TODO: restart clients */
        /* tell the firmware that we're starting */
        i40e_send_version(pf);
 
+       /* We've already released the lock, so don't do it again */
+       goto end_core_reset;
+
+end_unlock:
+       if (!lock_acquired)
+               rtnl_unlock();
 end_core_reset:
-       clear_bit(__I40E_RESET_FAILED, &pf->state);
+       clear_bit(__I40E_RESET_FAILED, pf->state);
 clear_recovery:
-       clear_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state);
+       clear_bit(__I40E_RESET_RECOVERY_PENDING, pf->state);
+}
+
+/**
+ * i40e_reset_and_rebuild - reset and rebuild using a saved config
+ * @pf: board private structure
+ * @reinit: if the Main VSI needs to re-initialized.
+ * @lock_acquired: indicates whether or not the lock has been acquired
+ * before this function was called.
+ **/
+static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit,
+                                  bool lock_acquired)
+{
+       int ret;
+       /* Now we wait for GRST to settle out.
+        * We don't have to delete the VEBs or VSIs from the hw switch
+        * because the reset will make them disappear.
+        */
+       ret = i40e_reset(pf);
+       if (!ret)
+               i40e_rebuild(pf, reinit, lock_acquired);
 }
 
 /**
@@ -7322,11 +7579,13 @@ clear_recovery:
  *
  * Close up the VFs and other things in prep for a Core Reset,
  * then get ready to rebuild the world.
+ * @lock_acquired: indicates whether or not the lock has been acquired
+ * before this function was called.
  **/
-static void i40e_handle_reset_warning(struct i40e_pf *pf)
+static void i40e_handle_reset_warning(struct i40e_pf *pf, bool lock_acquired)
 {
-       i40e_prep_for_reset(pf);
-       i40e_reset_and_rebuild(pf, false);
+       i40e_prep_for_reset(pf, lock_acquired);
+       i40e_reset_and_rebuild(pf, false, lock_acquired);
 }
 
 /**
@@ -7344,7 +7603,7 @@ static void i40e_handle_mdd_event(struct i40e_pf *pf)
        u32 reg;
        int i;
 
-       if (!test_bit(__I40E_MDD_EVENT_PENDING, &pf->state))
+       if (!test_bit(__I40E_MDD_EVENT_PENDING, pf->state))
                return;
 
        /* find what triggered the MDD event */
@@ -7396,7 +7655,7 @@ static void i40e_handle_mdd_event(struct i40e_pf *pf)
                }
                /* Queue belongs to the PF initiate a reset */
                if (pf_mdd_detected) {
-                       set_bit(__I40E_PF_RESET_REQUESTED, &pf->state);
+                       set_bit(__I40E_PF_RESET_REQUESTED, pf->state);
                        i40e_service_event_schedule(pf);
                }
        }
@@ -7425,20 +7684,49 @@ static void i40e_handle_mdd_event(struct i40e_pf *pf)
                                 "Too many MDD events on VF %d, disabled\n", i);
                        dev_info(&pf->pdev->dev,
                                 "Use PF Control I/F to re-enable the VF\n");
-                       set_bit(I40E_VF_STAT_DISABLED, &vf->vf_states);
+                       set_bit(I40E_VF_STATE_DISABLED, &vf->vf_states);
                }
        }
 
        /* re-enable mdd interrupt cause */
-       clear_bit(__I40E_MDD_EVENT_PENDING, &pf->state);
+       clear_bit(__I40E_MDD_EVENT_PENDING, pf->state);
        reg = rd32(hw, I40E_PFINT_ICR0_ENA);
        reg |=  I40E_PFINT_ICR0_ENA_MAL_DETECT_MASK;
        wr32(hw, I40E_PFINT_ICR0_ENA, reg);
        i40e_flush(hw);
 }
 
-#if defined(HAVE_VXLAN_RX_OFFLOAD) || defined(HAVE_GENEVE_RX_OFFLOAD) || defined(HAVE_UDP_ENC_RX_OFFLOAD)
-#if IS_ENABLED(CONFIG_VXLAN) || IS_ENABLED(CONFIG_GENEVE) || defined(HAVE_UDP_ENC_RX_OFFLOAD)
+#if defined(HAVE_VXLAN_RX_OFFLOAD) || defined(HAVE_UDP_ENC_RX_OFFLOAD)
+#if defined(HAVE_UDP_ENC_TUNNEL) || defined(HAVE_UDP_ENC_RX_OFFLOAD)
+const char *i40e_tunnel_name(struct i40e_udp_port_config *port)
+{
+       switch (port->type) {
+       case UDP_TUNNEL_TYPE_VXLAN:
+               return "vxlan";
+       case UDP_TUNNEL_TYPE_GENEVE:
+               return "geneve";
+       default:
+               return "unknown";
+       }
+}
+
+/**
+ * i40e_sync_udp_filters - Trigger a sync event for existing UDP filters
+ * @pf: board private structure
+ **/
+static void i40e_sync_udp_filters(struct i40e_pf *pf)
+{
+       int i;
+
+       /* loop through and set pending bit for all active UDP filters */
+       for (i = 0; i < I40E_MAX_PF_UDP_OFFLOAD_PORTS; i++) {
+               if (pf->udp_ports[i].port)
+                       pf->pending_udp_bitmap |= BIT_ULL(i);
+       }
+
+       pf->flags |= I40E_FLAG_UDP_FILTER_SYNC;
+}
+
 /**
  * i40e_sync_udp_filters_subtask - Sync the VSI filter list with HW
  * @pf: board private structure
@@ -7468,29 +7756,21 @@ static void i40e_sync_udp_filters_subtask(struct i40e_pf *pf)
 
                        if (ret) {
                                dev_info(&pf->pdev->dev,
-                                        "%s vxlan port %d, index %d failed, err %s aq_err %s\n",
+                                        "%s %s port %d, index %d failed, err %s aq_err %s\n",
+                                        i40e_tunnel_name(&pf->udp_ports[i]),
                                         port ? "add" : "delete",
                                         port, i,
                                         i40e_stat_str(&pf->hw, ret),
                                         i40e_aq_str(&pf->hw,
                                                    pf->hw.aq.asq_last_status));
                                pf->udp_ports[i].port = 0;
-                       } else {
-                               if (port)
-                                       dev_dbg(&pf->pdev->dev,
-                                               "add vxlan port %d, index %d success\n",
-                                               port, i);
-                               else
-                                       dev_dbg(&pf->pdev->dev,
-                                               "delete vxlan port success\n");
-
                        }
                }
        }
 }
 
-#endif /* CONFIG_GENEVE || CONFIG_VXLAN || HAVE_UDP_ENC_RX_OFFLOAD */
-#endif /* HAVE_VXLAN_RX_OFFLOAD || HAVE_GENEVE_RX_OFFLOAD || HAVE_UDP_ENC_RX_OFFLOAD */
+#endif /* HAVE_UDP_ENC_TUNNEL || HAVE_UDP_ENC_RX_OFFLOAD */
+#endif /* HAVE_VXLAN_RX_OFFLOAD || HAVE_UDP_ENC_RX_OFFLOAD */
 
 /**
  * i40e_detect_recover_hung_queue - Function to detect and recover hung_queue
@@ -7498,16 +7778,15 @@ static void i40e_sync_udp_filters_subtask(struct i40e_pf *pf)
  * @vsi: Pointer to VSI struct
  *
  * This function checks specified queue for given VSI. Detects hung condition.
- * Sets hung bit since it is two step process. Before next run of service task
- * if napi_poll runs, it reset 'hung' bit for respective q_vector. If not,
- * hung condition remain unchanged and during subsequent run, this function
- * issues SW interrupt to recover from hung condition.
+ * We proactively detect hung TX queues by checking if interrupts are disabled
+ * but there are pending descriptors.  If it appears hung, attempt to recover
+ * by triggering a SW interrupt.
  **/
 static void i40e_detect_recover_hung_queue(int q_idx, struct i40e_vsi *vsi)
 {
        struct i40e_ring *tx_ring = NULL;
        struct i40e_pf  *pf;
-       u32 val, tx_pending_hw;
+       u32 val, tx_pending;
        int i;
 
        pf = vsi->back;
@@ -7533,26 +7812,15 @@ static void i40e_detect_recover_hung_queue(int q_idx, struct i40e_vsi *vsi)
        else
                val = rd32(&pf->hw, I40E_PFINT_DYN_CTL0);
 
-       tx_pending_hw = i40e_get_tx_pending(tx_ring, false);
+       tx_pending = i40e_get_tx_pending(tx_ring);
 
        /* Interrupts are disabled and TX pending is non-zero,
         * trigger the SW interrupt (don't wait). Worst case
         * there will be one extra interrupt which may result
         * into not cleaning any queues because queues are cleaned.
         */
-       if (tx_pending_hw && (!(val & I40E_PFINT_DYN_CTLN_INTENA_MASK)))
+       if (tx_pending && (!(val & I40E_PFINT_DYN_CTLN_INTENA_MASK)))
                i40e_force_wb(vsi, tx_ring->q_vector);
-
-       /* This is the case where we have interrupts missing,
-        * so the tx_pending in HW will most likely be 0, but we
-        * will have tx_pending in sw since the WB happened but the
-        * interrupt got lost.
-        */
-       if ((!tx_pending_hw) && i40e_get_tx_pending(tx_ring, true)
-          && (!(val & I40E_PFINT_DYN_CTLN_INTENA_MASK))) {
-               if (napi_reschedule(&tx_ring->q_vector->napi))
-                       tx_ring->tx_stats.tx_lost_interrupt++;
-       }
 }
 
 /**
@@ -7576,8 +7844,8 @@ static void i40e_detect_recover_hung(struct i40e_pf *pf)
                return;
 
        /* Make sure, VSI state is not DOWN/RECOVERY_PENDING */
-       if (test_bit(__I40E_DOWN, &vsi->back->state) ||
-           test_bit(__I40E_RESET_RECOVERY_PENDING, &vsi->back->state))
+       if (test_bit(__I40E_DOWN, vsi->back->state) ||
+           test_bit(__I40E_RESET_RECOVERY_PENDING, vsi->back->state))
                return;
 
        /* Make sure type is MAIN VSI */
@@ -7614,12 +7882,12 @@ static void i40e_service_task(struct work_struct *work)
        unsigned long start_time = jiffies;
 
        /* don't bother with service tasks if a reset is in progress */
-       if (test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state) ||
-           test_bit(__I40E_SUSPENDED, &pf->state)) {
+       if (test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state) ||
+           test_bit(__I40E_SUSPENDED, pf->state)) {
                return;
        }
 
-       if (test_and_set_bit(__I40E_SERVICE_SCHED, &pf->state))
+       if (test_and_set_bit(__I40E_SERVICE_SCHED, pf->state))
                return;
 
        i40e_detect_recover_hung(pf);
@@ -7629,27 +7897,39 @@ static void i40e_service_task(struct work_struct *work)
        i40e_vc_process_vflr_event(pf);
        i40e_watchdog_subtask(pf);
        i40e_fdir_reinit_subtask(pf);
-#if defined(HAVE_VXLAN_RX_OFFLOAD) || defined(HAVE_GENEVE_RX_OFFLOAD) || defined(HAVE_UDP_ENC_RX_OFFLOAD)
-#if IS_ENABLED(CONFIG_VXLAN) || IS_ENABLED(CONFIG_GENEVE) || defined(HAVE_UDP_ENC_RX_OFFLOAD)
+       if (pf->flags & I40E_FLAG_CLIENT_RESET) {
+               /* Client subtask will reopen next time through. */
+               i40e_notify_client_of_netdev_close(pf->vsi[pf->lan_vsi], true);
+               pf->flags &= ~I40E_FLAG_CLIENT_RESET;
+       } else {
+               i40e_client_subtask(pf);
+               if (pf->flags & I40E_FLAG_CLIENT_L2_CHANGE) {
+                       i40e_notify_client_of_l2_param_changes(
+                                                       pf->vsi[pf->lan_vsi]);
+                       pf->flags &= ~I40E_FLAG_CLIENT_L2_CHANGE;
+               }
+       }
+#if defined(HAVE_VXLAN_RX_OFFLOAD) || defined(HAVE_UDP_ENC_RX_OFFLOAD)
+#if defined(HAVE_UDP_ENC_TUNNEL) || defined(HAVE_UDP_ENC_RX_OFFLOAD)
        i40e_sync_udp_filters_subtask(pf);
 
 #endif
-#endif /* HAVE_VXLAN_RX_OFFLOAD || HAVE_GENEVE_RX_OFFLOAD || HAVE_UDP_ENC_RX_OFFLOAD */
+#endif /* HAVE_VXLAN_RX_OFFLOAD || HAVE_UDP_ENC_RX_OFFLOAD */
 
        i40e_clean_adminq_subtask(pf);
 
        /* flush memory to make sure state is correct before next watchdog */
        smp_mb__before_atomic();
-       clear_bit(__I40E_SERVICE_SCHED, &pf->state);
+       clear_bit(__I40E_SERVICE_SCHED, pf->state);
 
        /* If the tasks have taken longer than one timer cycle or there
         * is more work to be done, reschedule the service task now
         * rather than wait for the timer to tick again.
         */
        if (time_after(jiffies, (start_time + pf->service_timer_period)) ||
-           test_bit(__I40E_ADMINQ_EVENT_PENDING, &pf->state)            ||
-           test_bit(__I40E_MDD_EVENT_PENDING, &pf->state)               ||
-           test_bit(__I40E_VFLR_EVENT_PENDING, &pf->state))
+           test_bit(__I40E_ADMINQ_EVENT_PENDING, pf->state)             ||
+           test_bit(__I40E_MDD_EVENT_PENDING, pf->state)                ||
+           test_bit(__I40E_VFLR_EVENT_PENDING, pf->state))
                i40e_service_event_schedule(pf);
 }
 
@@ -7691,7 +7971,7 @@ static int i40e_set_num_rings_in_vsi(struct i40e_vsi *vsi)
                vsi->alloc_queue_pairs = 1;
                vsi->num_desc = ALIGN(I40E_FDIR_RING_COUNT,
                                      I40E_REQ_DESCRIPTOR_MULTIPLE);
-               vsi->num_q_vectors = 1;
+               vsi->num_q_vectors = pf->num_fdsb_msix;
                break;
 
        case I40E_VSI_VMDQ2:
@@ -7707,15 +7987,6 @@ static int i40e_set_num_rings_in_vsi(struct i40e_vsi *vsi)
                                      I40E_REQ_DESCRIPTOR_MULTIPLE);
                break;
 
-#ifdef I40E_FCOE
-       case I40E_VSI_FCOE:
-               vsi->alloc_queue_pairs = pf->num_fcoe_qps;
-               vsi->num_desc = ALIGN(I40E_DEFAULT_NUM_DESCRIPTORS,
-                                     I40E_REQ_DESCRIPTOR_MULTIPLE);
-               vsi->num_q_vectors = pf->num_fcoe_msix;
-               break;
-
-#endif /* I40E_FCOE */
        default:
                WARN_ON(1);
                return -ENODATA;
@@ -7808,7 +8079,7 @@ int i40e_vsi_mem_alloc(struct i40e_pf *pf, enum i40e_vsi_type type)
        }
        vsi->type = type;
        vsi->back = pf;
-       set_bit(__I40E_DOWN, &vsi->state);
+       set_bit(__I40E_VSI_DOWN, vsi->state);
        vsi->flags = 0;
        vsi->idx = vsi_idx;
        vsi->int_rate_limit = 0;
@@ -7836,6 +8107,7 @@ int i40e_vsi_mem_alloc(struct i40e_pf *pf, enum i40e_vsi_type type)
        spin_lock_init(&vsi->mac_filter_hash_lock);
        pf->vsi[vsi_idx] = vsi;
        ret = vsi_idx;
+
        goto unlock_pf;
 
 err_rings:
@@ -7961,7 +8233,7 @@ static int i40e_alloc_rings(struct i40e_vsi *vsi)
                tx_ring->size = 0;
                tx_ring->dcb_tc = 0;
 
-               if (vsi->back->flags & I40E_FLAG_WB_ON_ITR_CAPABLE)
+               if (vsi->back->hw_features & I40E_HW_WB_ON_ITR_CAPABLE)
                        tx_ring->flags = I40E_TXR_FLAGS_WB_ON_ITR;
                tx_ring->tx_itr_setting = pf->tx_itr_default;
                vsi->tx_rings[i] = tx_ring;
@@ -8025,6 +8297,7 @@ static int i40e_init_msix(struct i40e_pf *pf)
        int vectors_left;
        int v_budget, i;
        int v_actual;
+       int iwarp_requested = 0;
 
        if (!(pf->flags & I40E_FLAG_MSIX_ENABLED))
                return -ENODEV;
@@ -8039,9 +8312,7 @@ static int i40e_init_msix(struct i40e_pf *pf)
         *              is governed by number of cpus in the system.
         *      - assumes symmetric Tx/Rx pairing
         *   - The number of VMDq pairs
-#ifdef I40E_FCOE
-        *   - The number of FCOE qps.
-#endif
+        *   - The CPU count within the NUMA node if iWARP is enabled
         * Once we count this up, try the request.
         *
         * If we can't get what we want, we'll simplify to nearly nothing
@@ -8070,43 +8341,48 @@ static int i40e_init_msix(struct i40e_pf *pf)
        /* reserve one vector for sideband flow director */
        if (pf->flags & I40E_FLAG_FD_SB_ENABLED) {
                if (vectors_left) {
+                       pf->num_fdsb_msix = 1;
                        v_budget++;
                        vectors_left--;
                } else {
-                       pf->flags &= ~I40E_FLAG_FD_SB_ENABLED;
+                       pf->num_fdsb_msix = 0;
                }
        }
 
-#ifdef I40E_FCOE
-       /* can we reserve enough for FCoE? */
-       if (pf->flags & I40E_FLAG_FCOE_ENABLED) {
+       /* can we reserve enough for iWARP? */
+       if (pf->flags & I40E_FLAG_IWARP_ENABLED) {
+               iwarp_requested = pf->num_iwarp_msix;
+
                if (!vectors_left)
-                       pf->num_fcoe_msix = 0;
-               else if (vectors_left >= pf->num_fcoe_qps)
-                       pf->num_fcoe_msix = pf->num_fcoe_qps;
-               else
-                       pf->num_fcoe_msix = 1;
-               v_budget += pf->num_fcoe_msix;
-               vectors_left -= pf->num_fcoe_msix;
+                       pf->num_iwarp_msix = 0;
+               else if (vectors_left < pf->num_iwarp_msix)
+                       pf->num_iwarp_msix = 1;
+               v_budget += pf->num_iwarp_msix;
+               vectors_left -= pf->num_iwarp_msix;
        }
 
-#endif
        /* any vectors left over go for VMDq support */
        if (pf->flags & I40E_FLAG_VMDQ_ENABLED) {
                int vmdq_vecs_wanted = pf->num_vmdq_vsis * pf->num_vmdq_qps;
                int vmdq_vecs = min_t(int, vectors_left, vmdq_vecs_wanted);
 
-               /* if we're short on vectors for what's desired, we limit
-                * the queues per vmdq.  If this is still more than are
-                * available, the user will need to change the number of
-                * queues/vectors used by the PF later with the ethtool
-                * channels command */
-               if (vmdq_vecs < vmdq_vecs_wanted)
-                       pf->num_vmdq_qps = 1;
-               pf->num_vmdq_msix = pf->num_vmdq_qps;
+               if (!vectors_left) {
+                       pf->num_vmdq_msix = 0;
+                       pf->num_vmdq_qps = 0;
+               } else {
+                       /* if we're short on vectors for what's desired, we
+                        * limit the queues per vmdq.  If this is still more
+                        * than are available, the user will need to change
+                        * the number of queues/vectors used by the PF later
+                        * with the ethtool channels command
+                        */
+                       if (vmdq_vecs < vmdq_vecs_wanted)
+                               pf->num_vmdq_qps = 1;
+                       pf->num_vmdq_msix = pf->num_vmdq_qps;
 
-               v_budget += vmdq_vecs;
-               vectors_left -= vmdq_vecs;
+                       v_budget += vmdq_vecs;
+                       vectors_left -= vmdq_vecs;
+               }
        }
 
        /* On systems with a large number of SMP cores, we previously limited
@@ -8141,19 +8417,6 @@ static int i40e_init_msix(struct i40e_pf *pf)
                return -ENODEV;
        }
 
-       if (v_actual != v_budget) {
-               /* If we have limited resources, we will start with no vectors
-                * for the special features and then allocate vectors to some
-                * of these features based on the policy and at the end disable
-                * the features that did not get any vectors.
-                */
-#ifdef I40E_FCOE
-               pf->num_fcoe_qps = 0;
-               pf->num_fcoe_msix = 0;
-#endif
-               pf->num_vmdq_msix = 0;
-       }
-
        if (v_actual == I40E_MIN_MSIX) {
                /* Adjust for minimal MSIX use */
                pf->num_vmdq_vsis = 0;
@@ -8161,9 +8424,16 @@ static int i40e_init_msix(struct i40e_pf *pf)
                pf->num_lan_qps = 1;
                pf->num_lan_msix = 1;
 
-       } else if (v_actual != v_budget) {
+       } else if (!vectors_left) {
+               /* If we have limited resources, we will start with no vectors
+                * for the special features and then allocate vectors to some
+                * of these features based on the policy and at the end disable
+                * the features that did not get any vectors.
+                */
                int vec;
 
+               dev_info(&pf->pdev->dev,
+                        "MSI-X vector limit reached, attempting to redistribute vectors\n");
                /* reserve the misc vector */
                vec = v_actual - 1;
 
@@ -8171,7 +8441,6 @@ static int i40e_init_msix(struct i40e_pf *pf)
                pf->num_vmdq_msix = 1;    /* force VMDqs to only one vector */
                pf->num_vmdq_vsis = 1;
                pf->num_vmdq_qps = 1;
-               pf->flags &= ~I40E_FLAG_FD_SB_ENABLED;
 
                /* partition out the remaining vectors */
                switch (vec) {
@@ -8179,43 +8448,48 @@ static int i40e_init_msix(struct i40e_pf *pf)
                        pf->num_lan_msix = 1;
                        break;
                case 3:
-#ifdef I40E_FCOE
-                       /* give one vector to FCoE */
-                       if (pf->flags & I40E_FLAG_FCOE_ENABLED) {
+                       if (pf->flags & I40E_FLAG_IWARP_ENABLED) {
                                pf->num_lan_msix = 1;
-                               pf->num_fcoe_msix = 1;
+                               pf->num_iwarp_msix = 1;
                        }
-#else
-                       pf->num_lan_msix = 2;
-#endif
                        break;
                default:
-#ifdef I40E_FCOE
-                       /* give one vector to FCoE */
-                       if (pf->flags & I40E_FLAG_FCOE_ENABLED) {
-                               pf->num_fcoe_msix = 1;
+                       if (pf->flags & I40E_FLAG_IWARP_ENABLED) {
+                               pf->num_iwarp_msix = min_t(int, (vec / 3),
+                                                iwarp_requested);
+                               pf->num_vmdq_vsis = min_t(int, (vec / 3),
+                                                 I40E_DEFAULT_NUM_VMDQ_VSI);
+                       } else {
+                               pf->num_vmdq_vsis = min_t(int, (vec / 2),
+                                                 I40E_DEFAULT_NUM_VMDQ_VSI);
+                       }
+                       if (pf->flags & I40E_FLAG_FD_SB_ENABLED) {
+                               pf->num_fdsb_msix = 1;
                                vec--;
                        }
-#endif
-                       /* give the rest to the PF */
-                       pf->num_lan_msix = min_t(int, vec, pf->num_lan_qps);
+                       pf->num_lan_msix = min_t(int,
+                              (vec - (pf->num_iwarp_msix + pf->num_vmdq_vsis)),
+                                                             pf->num_lan_msix);
                        break;
                }
        }
 
+       if ((pf->flags & I40E_FLAG_FD_SB_ENABLED) &&
+           (pf->num_fdsb_msix == 0)) {
+               dev_info(&pf->pdev->dev, "Sideband Flowdir disabled, not enough MSI-X vectors\n");
+               pf->flags &= ~I40E_FLAG_FD_SB_ENABLED;
+       }
        if ((pf->flags & I40E_FLAG_VMDQ_ENABLED) &&
            (pf->num_vmdq_msix == 0)) {
                dev_info(&pf->pdev->dev, "VMDq disabled, not enough MSI-X vectors\n");
                pf->flags &= ~I40E_FLAG_VMDQ_ENABLED;
        }
-#ifdef I40E_FCOE
 
-       if ((pf->flags & I40E_FLAG_FCOE_ENABLED) &&
-                                       (pf->num_fcoe_msix == 0)) {
-               dev_info(&pf->pdev->dev, "FCOE disabled, not enough MSI-X vectors\n");
-               pf->flags &= ~I40E_FLAG_FCOE_ENABLED;
+       if ((pf->flags & I40E_FLAG_IWARP_ENABLED) &&
+           (pf->num_iwarp_msix == 0)) {
+               dev_info(&pf->pdev->dev, "IWARP disabled, not enough MSI-X vectors\n");
+               pf->flags &= ~I40E_FLAG_IWARP_ENABLED;
        }
-#endif
        return v_actual;
 }
 #endif
@@ -8230,8 +8504,6 @@ static int i40e_init_msix(struct i40e_pf *pf)
 static int i40e_vsi_alloc_q_vector(struct i40e_vsi *vsi, int v_idx)
 {
        struct i40e_q_vector *q_vector;
-#ifdef HAVE_IRQ_AFFINITY_HINT
-#endif
 
        /* allocate q_vector */
        q_vector = kzalloc(sizeof(struct i40e_q_vector), GFP_KERNEL);
@@ -8240,8 +8512,8 @@ static int i40e_vsi_alloc_q_vector(struct i40e_vsi *vsi, int v_idx)
 
        q_vector->vsi = vsi;
        q_vector->v_idx = v_idx;
-#ifdef HAVE_IRQ_AFFINITY_HINT
-       cpumask_set_cpu(v_idx, &q_vector->affinity_mask);
+#ifdef HAVE_IRQ_AFFINITY_NOTIFY
+       cpumask_copy(&q_vector->affinity_mask, cpu_possible_mask);
 #endif
        if (vsi->netdev)
                netif_napi_add(vsi->netdev, &q_vector->napi,
@@ -8309,9 +8581,7 @@ static int i40e_init_interrupt_scheme(struct i40e_pf *pf)
 #endif
                if (vectors < 0) {
                        pf->flags &= ~(I40E_FLAG_MSIX_ENABLED   |
-#ifdef I40E_FCOE
-                                      I40E_FLAG_FCOE_ENABLED   |
-#endif
+                                      I40E_FLAG_IWARP_ENABLED  |
                                       I40E_FLAG_RSS_ENABLED    |
                                       I40E_FLAG_DCB_CAPABLE    |
                                       I40E_FLAG_DCB_ENABLED    |
@@ -8373,13 +8643,12 @@ static int i40e_setup_misc_vector(struct i40e_pf *pf)
        struct i40e_hw *hw = &pf->hw;
        int err = 0;
 
-       /* Only request the irq if this is the first time through, and
-        * not when we're rebuilding after a Reset
-        */
-       if (!test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state)) {
+       /* Only request the IRQ once, the first time through. */
+       if (!test_and_set_bit(__I40E_MISC_IRQ_REQUESTED, pf->state)) {
                err = request_irq(pf->msix_entries[0].vector,
                                  i40e_intr, 0, pf->int_name, pf);
                if (err) {
+                       clear_bit(__I40E_MISC_IRQ_REQUESTED, pf->state);
                        dev_info(&pf->pdev->dev,
                                 "request_irq for %s failed: %d\n",
                                 pf->int_name, err);
@@ -8400,6 +8669,57 @@ static int i40e_setup_misc_vector(struct i40e_pf *pf)
        return err;
 }
 
+#ifdef CONFIG_PM
+/**
+ * i40e_restore_interrupt_scheme - Restore the interrupt scheme
+ * @pf: private board data structure
+ *
+ * Restore the interrupt scheme that was cleared when we suspended the
+ * device. This should be called during resume to re-allocate the q_vectors
+ * and reacquire IRQs.
+ */
+static int i40e_restore_interrupt_scheme(struct i40e_pf *pf)
+{
+       int err, i;
+
+       /* We cleared the MSI and MSI-X flags when disabling the old interrupt
+        * scheme. We need to re-enabled them here in order to attempt to
+        * re-acquire the MSI or MSI-X vectors
+        */
+       pf->flags |= (I40E_FLAG_MSIX_ENABLED | I40E_FLAG_MSI_ENABLED);
+
+       err = i40e_init_interrupt_scheme(pf);
+       if (err)
+               return err;
+
+       /* Now that we've re-acquired IRQs, we need to remap the vectors and
+        * rings together again.
+        */
+       for (i = 0; i < pf->num_alloc_vsi; i++) {
+               if (pf->vsi[i]) {
+                       err = i40e_vsi_alloc_q_vectors(pf->vsi[i]);
+                       if (err)
+                               goto err_unwind;
+                       i40e_vsi_map_rings_to_vectors(pf->vsi[i]);
+               }
+       }
+
+       err = i40e_setup_misc_vector(pf);
+       if (err)
+               goto err_unwind;
+
+       return 0;
+
+err_unwind:
+       while (i--) {
+               if (pf->vsi[i])
+                       i40e_vsi_free_q_vectors(pf->vsi[i]);
+       }
+
+       return err;
+}
+#endif /* CONFIG_PM */
+
 /**
  * i40e_config_rss_aq - Configure RSS keys and lut by using AQ commands
  * @vsi: Pointer to vsi structure
@@ -8500,7 +8820,7 @@ static int i40e_vsi_config_rss(struct i40e_vsi *vsi)
        u8 *lut;
        int ret;
 
-       if (!(pf->flags & I40E_FLAG_RSS_AQ_CAPABLE))
+       if (!(pf->hw_features & I40E_HW_RSS_AQ_CAPABLE))
                return 0;
 
        if (!vsi->rss_size)
@@ -8629,7 +8949,7 @@ int i40e_config_rss(struct i40e_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size)
 {
        struct i40e_pf *pf = vsi->back;
 
-       if (pf->flags & I40E_FLAG_RSS_AQ_CAPABLE)
+       if (pf->hw_features & I40E_HW_RSS_AQ_CAPABLE)
                return i40e_config_rss_aq(vsi, seed, lut, lut_size);
        else
                return i40e_config_rss_reg(vsi, seed, lut, lut_size);
@@ -8648,7 +8968,7 @@ int i40e_get_rss(struct i40e_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size)
 {
        struct i40e_pf *pf = vsi->back;
 
-       if (pf->flags & I40E_FLAG_RSS_AQ_CAPABLE)
+       if (pf->hw_features & I40E_HW_RSS_AQ_CAPABLE)
                return i40e_get_rss_aq(vsi, seed, lut, lut_size);
        else
                return i40e_get_rss_reg(vsi, seed, lut, lut_size);
@@ -8679,10 +8999,10 @@ static int i40e_pf_config_rss(struct i40e_pf *pf)
 {
        struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi];
        u8 seed[I40E_HKEY_ARRAY_SIZE];
-       u8 *lut;
        struct i40e_hw *hw = &pf->hw;
        u32 reg_val;
        u64 hena;
+       u8 *lut;
        int ret;
 
        /* By default we enable TCP/UDP with IPv4/IPv6 ptypes */
@@ -8701,9 +9021,12 @@ static int i40e_pf_config_rss(struct i40e_pf *pf)
        i40e_write_rx_ctl(hw, I40E_PFQF_CTL_0, reg_val);
 
        /* Determine the RSS size of the VSI */
-       if (!vsi->rss_size)
-               vsi->rss_size = min_t(int, pf->alloc_rss_size,
-                                     vsi->num_queue_pairs);
+       if (!vsi->rss_size) {
+               u16 qcount;
+
+               qcount = vsi->num_queue_pairs / vsi->tc_config.numtc;
+               vsi->rss_size = min_t(int, pf->alloc_rss_size, qcount);
+       }
        if (!vsi->rss_size)
                return -EINVAL;
 
@@ -8754,6 +9077,7 @@ static void i40e_clear_rss_config_user(struct i40e_vsi *vsi)
  *
  * returns 0 if rss is not enabled, if enabled returns the final rss queue
  * count which may be different from the requested queue count.
+ * Note: expects to be called while under rtnl_lock()
  **/
 int i40e_reconfig_rss_queues(struct i40e_pf *pf, int queue_count)
 {
@@ -8766,12 +9090,14 @@ int i40e_reconfig_rss_queues(struct i40e_pf *pf, int queue_count)
        new_rss_size = min_t(int, queue_count, pf->rss_size_max);
 
        if (queue_count != vsi->num_queue_pairs) {
+               u16 qcount;
+
                vsi->req_queue_pairs = queue_count;
-               i40e_prep_for_reset(pf);
+               i40e_prep_for_reset(pf, true);
 
                pf->alloc_rss_size = new_rss_size;
 
-               i40e_reset_and_rebuild(pf, true);
+               i40e_reset_and_rebuild(pf, true, true);
 
                /* Discard the user configured hash keys and lut, if less
                 * queues are enabled.
@@ -8782,9 +9108,9 @@ int i40e_reconfig_rss_queues(struct i40e_pf *pf, int queue_count)
                                "discard user configured hash keys and lut\n");
                }
 
-               /* Reset vsi->rss_size, as number of enabled queues changed */
-               vsi->rss_size = min_t(int, pf->alloc_rss_size,
-                                     vsi->num_queue_pairs);
+               /* Reset vsi->rss_size, as number of enabled queues changed */
+               qcount = vsi->num_queue_pairs / vsi->tc_config.numtc;
+               vsi->rss_size = min_t(int, pf->alloc_rss_size, qcount);
 
                i40e_pf_config_rss(pf);
        }
@@ -9002,54 +9328,62 @@ static int i40e_sw_init(struct i40e_pf *pf)
        }
 
        if (pf->hw.mac.type == I40E_MAC_X722) {
-               pf->flags |= I40E_FLAG_RSS_AQ_CAPABLE
-                            | I40E_FLAG_128_QP_RSS_CAPABLE
-                            | I40E_FLAG_HW_ATR_EVICT_CAPABLE
-                            | I40E_FLAG_WB_ON_ITR_CAPABLE
-                            | I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE
-                            | I40E_FLAG_NO_PCI_LINK_CHECK
-                            | I40E_FLAG_USE_SET_LLDP_MIB
-                            | I40E_FLAG_GENEVE_OFFLOAD_CAPABLE
-                            | I40E_FLAG_PTP_L4_CAPABLE;
+               pf->hw_features |= (I40E_HW_RSS_AQ_CAPABLE |
+                                   I40E_HW_128_QP_RSS_CAPABLE |
+                                   I40E_HW_ATR_EVICT_CAPABLE |
+                                   I40E_HW_WB_ON_ITR_CAPABLE |
+                                   I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE |
+                                   I40E_HW_NO_PCI_LINK_CHECK |
+                                   I40E_HW_USE_SET_LLDP_MIB |
+                                   I40E_HW_GENEVE_OFFLOAD_CAPABLE |
+                                   I40E_HW_PTP_L4_CAPABLE |
+                                   I40E_HW_WOL_MC_MAGIC_PKT_WAKE |
+                                   I40E_HW_OUTER_UDP_CSUM_CAPABLE);
 
 #define I40E_FDEVICT_PCTYPE_DEFAULT 0xc03
                if (rd32(&pf->hw, I40E_GLQF_FDEVICTENA(1)) !=
                                                I40E_FDEVICT_PCTYPE_DEFAULT) {
                        dev_warn(&pf->pdev->dev, "FD EVICT PCTYPES are not right, disable FD HW EVICT\n");
-                       pf->flags &= ~I40E_FLAG_HW_ATR_EVICT_CAPABLE;
+                       pf->hw_features &= ~I40E_HW_ATR_EVICT_CAPABLE;
                }
        } else if ((pf->hw.aq.api_maj_ver > 1) ||
                   ((pf->hw.aq.api_maj_ver == 1) &&
                    (pf->hw.aq.api_min_ver > 4))) {
                /* Supported in FW API version higher than 1.4 */
-               pf->flags |= I40E_FLAG_GENEVE_OFFLOAD_CAPABLE;
-               pf->hw_disabled_flags = I40E_FLAG_HW_ATR_EVICT_CAPABLE;
+               pf->hw_features |= I40E_HW_GENEVE_OFFLOAD_CAPABLE;
 
                /* supports mpls header skip and csum for following headers */
-               pf->flags |= I40E_FLAG_MPLS_HDR_OFFLOAD_CAPABLE;
-       } else {
-               pf->hw_disabled_flags = I40E_FLAG_HW_ATR_EVICT_CAPABLE;
+               pf->hw_features |= I40E_HW_MPLS_HDR_OFFLOAD_CAPABLE;
        }
 
+       /* Enable HW ATR eviction if possible */
+       if (pf->hw_features & I40E_HW_ATR_EVICT_CAPABLE)
+               pf->flags |= I40E_FLAG_HW_ATR_EVICT_ENABLED;
+
        if ((pf->hw.mac.type == I40E_MAC_XL710) &&
            (((pf->hw.aq.fw_maj_ver == 4) && (pf->hw.aq.fw_min_ver < 33)) ||
            (pf->hw.aq.fw_maj_ver < 4))) {
-               pf->flags |= I40E_FLAG_RESTART_AUTONEG;
+               pf->hw_features |= I40E_HW_RESTART_AUTONEG;
                /* No DCB support  for FW < v4.33 */
-               pf->flags |= I40E_FLAG_NO_DCB_SUPPORT;
+               pf->hw_features |= I40E_HW_NO_DCB_SUPPORT;
        }
 
        /* Disable FW LLDP if FW < v4.3 */
        if ((pf->hw.mac.type == I40E_MAC_XL710) &&
            (((pf->hw.aq.fw_maj_ver == 4) && (pf->hw.aq.fw_min_ver < 3)) ||
            (pf->hw.aq.fw_maj_ver < 4)))
-               pf->flags |= I40E_FLAG_STOP_FW_LLDP;
+               pf->hw_features |= I40E_HW_STOP_FW_LLDP;
 
        /* Use the FW Set LLDP MIB API if FW > v4.40 */
        if ((pf->hw.mac.type == I40E_MAC_XL710) &&
            (((pf->hw.aq.fw_maj_ver == 4) && (pf->hw.aq.fw_min_ver >= 40)) ||
            (pf->hw.aq.fw_maj_ver >= 5)))
-               pf->flags |= I40E_FLAG_USE_SET_LLDP_MIB;
+               pf->hw_features |= I40E_HW_USE_SET_LLDP_MIB;
+
+       /* Enable PTP L4 if FW > v6.0 */
+       if ((pf->hw.mac.type == I40E_MAC_XL710) &&
+           (pf->hw.aq.fw_maj_ver >= 6))
+               pf->hw_features |= I40E_HW_PTP_L4_CAPABLE;
 
        if (pf->hw.func_caps.vmdq) {
                pf->num_vmdq_vsis = I40E_DEFAULT_NUM_VMDQ_VSI;
@@ -9057,10 +9391,16 @@ static int i40e_sw_init(struct i40e_pf *pf)
                pf->num_vmdq_qps = i40e_default_queues_per_vmdq(pf);
        }
 
-#ifdef I40E_FCOE
-       i40e_init_pf_fcoe(pf);
+       if (pf->hw.func_caps.iwarp) {
+               pf->flags |= I40E_FLAG_IWARP_ENABLED;
+               /* IWARP needs one extra vector for CQP just like MISC.*/
+               pf->num_iwarp_msix = (int)num_online_cpus() + 1;
+       }
 
-#endif /* I40E_FCOE */
+#ifndef HAVE_SWIOTLB_SKIP_CPU_SYNC
+       /* force legacy Rx if SKIP_CPU_SYNC is not supported */
+       pf->flags |= I40E_FLAG_LEGACY_RX;
+#endif
 #ifdef CONFIG_PCI_IOV
        if (pf->hw.func_caps.num_vfs && pf->hw.partition_id == 1) {
 #if !defined(HAVE_SRIOV_CONFIGURE) && !defined(HAVE_RHEL6_SRIOV_CONFIGURE)
@@ -9136,7 +9476,9 @@ bool i40e_set_ntuple(struct i40e_pf *pf, netdev_features_t features)
                /* Enable filters and mark for reset */
                if (!(pf->flags & I40E_FLAG_FD_SB_ENABLED))
                        need_reset = true;
-               pf->flags |= I40E_FLAG_FD_SB_ENABLED;
+               /* enable FD_SB only if there is MSI-X vector */
+               if (pf->num_fdsb_msix > 0)
+                       pf->flags |= I40E_FLAG_FD_SB_ENABLED;
        } else {
                /* turn off filters, mark for reset and clear SW filter list */
                if (pf->flags & I40E_FLAG_FD_SB_ENABLED) {
@@ -9144,16 +9486,15 @@ bool i40e_set_ntuple(struct i40e_pf *pf, netdev_features_t features)
                        i40e_fdir_filter_exit(pf);
                        i40e_cloud_filter_exit(pf);
                }
-               pf->flags &= ~I40E_FLAG_FD_SB_ENABLED;
-               pf->hw_disabled_flags &= ~I40E_FLAG_FD_SB_ENABLED;
+               pf->flags &= ~(I40E_FLAG_FD_SB_ENABLED |
+                              I40E_FLAG_FD_SB_AUTO_DISABLED);
                /* reset fd counters */
-               pf->fd_add_err = pf->fd_atr_cnt = pf->fd_tcp_rule = 0;
-               pf->fdir_pf_active_filters = 0;
+               pf->fd_add_err = pf->fd_atr_cnt = 0;
                /* if ATR was auto disabled it can be re-enabled. */
-               if ((pf->flags & I40E_FLAG_FD_ATR_ENABLED) &&
-                   (pf->hw_disabled_flags & I40E_FLAG_FD_ATR_ENABLED)) {
-                       pf->hw_disabled_flags &= ~I40E_FLAG_FD_ATR_ENABLED;
-                       if (I40E_DEBUG_FD & pf->hw.debug_mask)
+               if (pf->flags & I40E_FLAG_FD_ATR_AUTO_DISABLED) {
+                       pf->flags &= ~I40E_FLAG_FD_ATR_AUTO_DISABLED;
+                       if ((pf->flags & I40E_FLAG_FD_ATR_ENABLED) &&
+                           (I40E_DEBUG_FD & pf->hw.debug_mask))
                                dev_info(&pf->pdev->dev, "ATR re-enabled.\n");
                }
        }
@@ -9187,6 +9528,7 @@ static void i40e_clear_rss_lut(struct i40e_vsi *vsi)
  * i40e_set_features - set the netdev feature flags
  * @netdev: ptr to the netdev being adjusted
  * @features: the feature set that the stack is suggesting
+ * Note: expects to be called while under rtnl_lock()
  **/
 #ifdef HAVE_RHEL6_NET_DEVICE_OPS_EXT
 static int i40e_set_features(struct net_device *netdev, u32 features)
@@ -9218,7 +9560,7 @@ static int i40e_set_features(struct net_device *netdev,
        need_reset = i40e_set_ntuple(pf, features);
 
        if (need_reset)
-               i40e_do_reset(pf, BIT_ULL(__I40E_PF_RESET_REQUESTED));
+               i40e_do_reset(pf, BIT_ULL(__I40E_PF_RESET_REQUESTED), true);
 
        return 0;
 }
@@ -9281,7 +9623,7 @@ static void i40e_udp_tunnel_add(struct net_device *netdev,
                pf->udp_ports[next_idx].type = I40E_AQC_TUNNEL_TYPE_VXLAN;
                break;
        case UDP_TUNNEL_TYPE_GENEVE:
-               if (!(pf->flags & I40E_FLAG_GENEVE_OFFLOAD_CAPABLE))
+               if (!(pf->hw_features & I40E_HW_GENEVE_OFFLOAD_CAPABLE))
                        return;
                pf->udp_ports[next_idx].type = I40E_AQC_TUNNEL_TYPE_NGE;
                break;
@@ -9322,7 +9664,7 @@ static void i40e_udp_tunnel_del(struct net_device *netdev,
                        goto not_found;
                break;
        case UDP_TUNNEL_TYPE_GENEVE:
-               if (!(pf->flags & I40E_FLAG_GENEVE_OFFLOAD_CAPABLE))
+               if (!(pf->hw_features & I40E_HW_GENEVE_OFFLOAD_CAPABLE))
                        return;
                if (pf->udp_ports[idx].type != I40E_AQC_TUNNEL_TYPE_NGE)
                        goto not_found;
@@ -9344,7 +9686,7 @@ not_found:
                    port);
 }
 
-#if defined(HAVE_VXLAN_RX_OFFLOAD)
+#if defined(HAVE_VXLAN_RX_OFFLOAD) && !defined(HAVE_UDP_ENC_RX_OFFLOAD)
 #if IS_ENABLED(CONFIG_VXLAN)
 /**
  * i40e_add_vxlan_port - Get notifications about vxlan ports that come up
@@ -9382,8 +9724,8 @@ static void i40e_del_vxlan_port(struct net_device *netdev,
        i40e_udp_tunnel_del(netdev, &ti);
 }
 #endif /* CONFIG_VXLAN */
-#endif /* HAVE_VXLAN_RX_OFFLOAD */
-#if defined(HAVE_GENEVE_RX_OFFLOAD)
+#endif /* HAVE_VXLAN_RX_OFFLOAD && !HAVE_UDP_ENC_RX_OFFLOAD */
+#if defined(HAVE_GENEVE_RX_OFFLOAD) && !defined(HAVE_UDP_ENC_RX_OFFLOAD)
 #if IS_ENABLED(CONFIG_GENEVE)
 /**
  * i40e_add_geneve_port - Get notifications about GENEVE ports that come up
@@ -9422,7 +9764,7 @@ static void i40e_del_geneve_port(struct net_device *netdev,
 }
 
 #endif /* CONFIG_GENEVE */
-#endif /* HAVE_GENEVE_RX_OFFLOAD */
+#endif /* HAVE_GENEVE_RX_OFFLOAD  && !HAVE_UDP_ENC_RX_OFFLOAD */
 #ifdef HAVE_NDO_GET_PHYS_PORT_ID
 static int i40e_get_phys_port_id(struct net_device *netdev,
                                 struct netdev_phys_item_id *ppid)
@@ -9431,7 +9773,7 @@ static int i40e_get_phys_port_id(struct net_device *netdev,
        struct i40e_pf *pf = np->vsi->back;
        struct i40e_hw *hw = &pf->hw;
 
-       if (!(pf->flags & I40E_FLAG_PORT_ID_VALID))
+       if (!(pf->hw_features & I40E_HW_PORT_ID_VALID))
                return -EOPNOTSUPP;
 
        ppid->id_len = min_t(int, sizeof(hw->mac.port_addr),
@@ -9444,6 +9786,14 @@ static int i40e_get_phys_port_id(struct net_device *netdev,
 #endif /* HAVE_NDO_GET_PHYS_PORT_ID */
 #ifdef HAVE_FDB_OPS
 #ifdef USE_CONST_DEV_UC_CHAR
+/**
+ * i40e_ndo_fdb_add - add an entry to the hardware database
+ * @ndm: the input from the stack
+ * @tb: pointer to array of nladdr (unused)
+ * @dev: the net device pointer
+ * @addr: the MAC address entry being added
+ * @flags: instructions from stack about fdb operation
+ */
 static int i40e_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
                            struct net_device *dev,
                            const unsigned char *addr,
@@ -9452,6 +9802,13 @@ static int i40e_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
 #endif
                            u16 flags)
 #else
+/**
+ * i40e_ndo_fdb_add - add an entry to the hardware database
+ * @ndm: the input from the stack
+ * @dev: the net device pointer
+ * @addr: the MAC address entry being added
+ * @flags: instructions from stack about fdb operation
+ */
 static int i40e_ndo_fdb_add(struct ndmsg *ndm,
                            struct net_device *dev,
                            unsigned char *addr,
@@ -9623,6 +9980,8 @@ static int i40e_ndo_fdb_dump(struct sk_buff *skb,
  * is to change the mode then that requires a PF reset to
  * allow rebuild of the components with required hardware
  * bridge mode enabled.
+ *
+ * Note: expects to be called while under rtnl_lock()
  **/
 #ifdef HAVE_NDO_BRIDGE_SET_DEL_LINK_FLAGS
 static int i40e_ndo_bridge_setlink(struct net_device *dev,
@@ -9682,7 +10041,8 @@ static int i40e_ndo_bridge_setlink(struct net_device *dev,
                                pf->flags |= I40E_FLAG_VEB_MODE_ENABLED;
                        else
                                pf->flags &= ~I40E_FLAG_VEB_MODE_ENABLED;
-                       i40e_do_reset(pf, BIT_ULL(__I40E_PF_RESET_REQUESTED));
+                       i40e_do_reset(pf, BIT_ULL(__I40E_PF_RESET_REQUESTED),
+                                     true);
                        break;
                }
        }
@@ -9757,7 +10117,7 @@ static const struct net_device_ops i40e_netdev_ops = {
        .ndo_open               = i40e_open,
        .ndo_stop               = i40e_close,
        .ndo_start_xmit         = i40e_lan_xmit_frame,
-#ifdef HAVE_NDO_GET_STATS64
+#if defined(HAVE_NDO_GET_STATS64) || defined(HAVE_VOID_NDO_GET_STATS64)
        .ndo_get_stats64        = i40e_get_netdev_stats_struct,
 #else
        .ndo_get_stats          = i40e_get_netdev_stats_struct,
@@ -9785,10 +10145,6 @@ static const struct net_device_ops i40e_netdev_ops = {
        .ndo_setup_tc           = i40e_setup_tc,
 #endif
 #endif /* HAVE_SETUP_TC */
-#ifdef I40E_FCOE
-       .ndo_fcoe_enable        = i40e_fcoe_enable,
-       .ndo_fcoe_disable       = i40e_fcoe_disable,
-#endif
 #ifdef HAVE_RHEL7_NET_DEVICE_OPS_EXT
 /* RHEL7 requires this to be defined to enable extended ops.  RHEL7 uses the
  * function get_ndo_ext to retrieve offsets for extended fields from with the
@@ -9799,7 +10155,11 @@ static const struct net_device_ops i40e_netdev_ops = {
 #endif
 #ifdef IFLA_VF_MAX
        .ndo_set_vf_mac         = i40e_ndo_set_vf_mac,
+#ifdef HAVE_RHEL7_NETDEV_OPS_EXT_NDO_SET_VF_VLAN
+       .extended.ndo_set_vf_vlan = i40e_ndo_set_vf_port_vlan,
+#else
        .ndo_set_vf_vlan        = i40e_ndo_set_vf_port_vlan,
+#endif
 #ifdef HAVE_NDO_SET_VF_MIN_MAX_TX_RATE
        .ndo_set_vf_rate        = i40e_ndo_set_vf_bw,
 #else
@@ -9817,6 +10177,15 @@ static const struct net_device_ops i40e_netdev_ops = {
 #endif /* HAVE_RHEL7_NET_DEVICE_OPS_EXT */
 #endif /* HAVE_NDO_SET_VF_TRUST */
 #endif /* IFLA_VF_MAX */
+#ifdef HAVE_UDP_ENC_RX_OFFLOAD
+#ifdef HAVE_RHEL7_NETDEV_OPS_EXT_NDO_UDP_TUNNEL
+       .extended.ndo_udp_tunnel_add = i40e_udp_tunnel_add,
+       .extended.ndo_udp_tunnel_del = i40e_udp_tunnel_del,
+#else
+       .ndo_udp_tunnel_add     = i40e_udp_tunnel_add,
+       .ndo_udp_tunnel_del     = i40e_udp_tunnel_del,
+#endif
+#else /* !HAVE_UDP_ENC_RX_OFFLOAD */
 #ifdef HAVE_VXLAN_RX_OFFLOAD
 #if IS_ENABLED(CONFIG_VXLAN)
        .ndo_add_vxlan_port     = i40e_add_vxlan_port,
@@ -9829,10 +10198,7 @@ static const struct net_device_ops i40e_netdev_ops = {
        .ndo_del_geneve_port    = i40e_del_geneve_port,
 #endif
 #endif /* HAVE_GENEVE_RX_OFFLOAD */
-#ifdef HAVE_UDP_ENC_RX_OFFLOAD
-       .ndo_udp_tunnel_add     = i40e_udp_tunnel_add,
-       .ndo_udp_tunnel_del     = i40e_udp_tunnel_del,
-#endif
+#endif /* HAVE_UDP_ENC_RX_OFFLOAD */
 #ifdef HAVE_NDO_GET_PHYS_PORT_ID
        .ndo_get_phys_port_id   = i40e_get_phys_port_id,
 #endif /* HAVE_NDO_GET_PHYS_PORT_ID */
@@ -9953,8 +10319,15 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
                          NETIF_F_TSO6                  |
 #ifdef HAVE_GRE_ENCAP_OFFLOAD
                          NETIF_F_GSO_GRE               |
+#ifdef NETIF_F_GSO_PARTIAL
+                         NETIF_F_GSO_GRE_CSUM          |
+                         NETIF_F_GSO_PARTIAL           |
+#endif
 #ifdef NETIF_F_GSO_IPXIP4
                          NETIF_F_GSO_IPXIP4            |
+#ifdef NETIF_F_GSO_IPXIP6
+                         NETIF_F_GSO_IPXIP6            |
+#endif
 #else
 #ifdef NETIF_F_GSO_IPIP
                          NETIF_F_GSO_IPIP              |
@@ -9976,8 +10349,14 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
 #endif
                          0;
 
-       if (!(pf->flags & I40E_FLAG_OUTER_UDP_CSUM_CAPABLE))
+       if (!(pf->hw_features & I40E_HW_OUTER_UDP_CSUM_CAPABLE))
+#ifndef NETIF_F_GSO_PARTIAL
                hw_enc_features ^= NETIF_F_GSO_UDP_TUNNEL_CSUM;
+#else
+               netdev->gso_partial_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
+
+       netdev->gso_partial_features |= NETIF_F_GSO_GRE_CSUM;
+#endif
 
 #ifdef HAVE_ENCAP_CSUM_OFFLOAD
        netdev->hw_enc_features |= hw_enc_features;
@@ -9985,7 +10364,11 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
 
 #ifdef HAVE_NETDEV_VLAN_FEATURES
        /* record features VLANs can make use of */
+#ifdef NETIF_F_GSO_PARTIAL
+       netdev->vlan_features |= hw_enc_features | NETIF_F_TSO_MANGLEID;
+#else
        netdev->vlan_features |= hw_enc_features;
+#endif
 #endif
 
        /* copy netdev features into list of user selectable features */
@@ -10017,6 +10400,9 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
 #else
        netdev->features |= hw_features | NETIF_F_HW_VLAN_FILTER;
 #endif
+#ifdef NETIF_F_GSO_PARTIAL
+       netdev->hw_enc_features |= NETIF_F_TSO_MANGLEID;
+#endif
 
 #ifndef HAVE_NDO_SET_FEATURES
 #ifdef NETIF_F_GRO
@@ -10027,18 +10413,28 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
        if (vsi->type == I40E_VSI_MAIN) {
                SET_NETDEV_DEV(netdev, &pf->pdev->dev);
                ether_addr_copy(mac_addr, hw->mac.perm_addr);
-               /* The following steps are necessary to prevent reception
-                * of tagged packets - some older NVM configurations load a
-                * default a MAC-VLAN filter that accepts any tagged packet
-                * which must be replaced by a normal filter.
+               /* The following steps are necessary for two reasons. First,
+                * some older NVM configurations load a default MAC-VLAN
+                * filter that will accept any tagged packet, and we want to
+                * replace this with a normal filter. Additionally, it is
+                * possible our MAC address was provided by the platform using
+                * Open Firmware or similar.
+                *
+                * Thus, we need to remove the default filter and install one
+                * specific to the MAC address.
                 */
                i40e_rm_default_mac_filter(vsi, mac_addr);
                spin_lock_bh(&vsi->mac_filter_hash_lock);
                i40e_add_mac_filter(vsi, mac_addr);
                spin_unlock_bh(&vsi->mac_filter_hash_lock);
        } else {
-               /* relate the VSI_VMDQ name to the VSI_MAIN name */
-               snprintf(netdev->name, IFNAMSIZ, "%sv%%d",
+               /* Relate the VSI_VMDQ name to the VSI_MAIN name. Note that we
+                * are still limited by IFNAMSIZ, but we're adding 'v%d\0' to
+                * the end, which is 4 bytes long, so force truncation of the
+                * original name by IFNAMSIZ - 4
+                */
+               snprintf(netdev->name, IFNAMSIZ, "%.*sv%%d",
+                        IFNAMSIZ - 4,
                         pf->vsi[pf->lan_vsi]->netdev->name);
                random_ether_addr(mac_addr);
 
@@ -10085,7 +10481,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
 #endif /* HAVE_NETDEV_VLAN_FEATURES */
 
 #ifdef HAVE_MPLS_FEATURES
-       if (pf->flags & I40E_FLAG_MPLS_HDR_OFFLOAD_CAPABLE)
+       if (pf->hw_features & I40E_HW_MPLS_HDR_OFFLOAD_CAPABLE)
                netdev->mpls_features =  NETIF_F_HW_CSUM;
 #endif
 
@@ -10104,8 +10500,10 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
 #ifdef SIOCETHTOOL
        i40e_set_ethtool_ops(netdev);
 #endif
-#ifdef I40E_FCOE
-       i40e_fcoe_config_netdev(netdev, vsi);
+#ifdef HAVE_NETDEVICE_MIN_MAX_MTU
+       /* MTU range: 68 - 9706 */
+       netdev->min_mtu = ETH_MIN_MTU;
+       netdev->max_mtu = I40E_MAX_RXBUFFER - I40E_PACKET_HDR_PAD;
 #endif
 
        return 0;
@@ -10215,6 +10613,31 @@ static int i40e_add_vsi(struct i40e_vsi *vsi)
 
                enabled_tc = i40e_pf_get_tc_map(pf);
 
+               /* Source pruning is enabled by default, so the flag is
+                * negative logic - if it's set, we need to fiddle with
+                * the VSI to disable source pruning.
+                */
+               if (pf->flags & I40E_FLAG_SOURCE_PRUNING_DISABLED) {
+                       memset(&ctxt, 0, sizeof(ctxt));
+                       ctxt.seid = pf->main_vsi_seid;
+                       ctxt.pf_num = pf->hw.pf_id;
+                       ctxt.vf_num = 0;
+                       ctxt.info.valid_sections |=
+                            cpu_to_le16(I40E_AQ_VSI_PROP_SWITCH_VALID);
+                       ctxt.info.switch_id =
+                                  cpu_to_le16(I40E_AQ_VSI_SW_ID_FLAG_LOCAL_LB);
+                       ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
+                       if (ret) {
+                               dev_info(&pf->pdev->dev,
+                                        "update vsi failed, err %s aq_err %s\n",
+                                        i40e_stat_str(&pf->hw, ret),
+                                        i40e_aq_str(&pf->hw,
+                                                   pf->hw.aq.asq_last_status));
+                               ret = -ENOENT;
+                               goto err;
+                       }
+               }
+
                /* MFP mode setup queue map and update VSI */
                if ((pf->flags & I40E_FLAG_MFP_ENABLED) &&
                    !(pf->hw.func_caps.iscsi)) { /* NIC type PF */
@@ -10245,13 +10668,15 @@ static int i40e_add_vsi(struct i40e_vsi *vsi)
                         */
                        ret = i40e_vsi_config_tc(vsi, enabled_tc);
                        if (ret) {
+                               /* Single TC condition is not fatal,
+                                * message and continue
+                                */
                                dev_info(&pf->pdev->dev,
                                         "failed to configure TCs for main VSI tc_map 0x%08x, err %s aq_err %s\n",
                                         enabled_tc,
                                         i40e_stat_str(&pf->hw, ret),
                                         i40e_aq_str(&pf->hw,
                                                    pf->hw.aq.asq_last_status));
-                               ret = -ENOENT;
                        }
                }
                break;
@@ -10310,6 +10735,14 @@ static int i40e_add_vsi(struct i40e_vsi *vsi)
                                cpu_to_le16(I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB);
                }
 
+               if (vsi->back->flags & I40E_FLAG_IWARP_ENABLED) {
+                       ctxt.info.valid_sections |=
+                               cpu_to_le16(I40E_AQ_VSI_PROP_QUEUE_OPT_VALID);
+                       ctxt.info.queueing_opt_flags |=
+                               (I40E_AQ_VSI_QUE_OPT_TCP_ENA |
+                                I40E_AQ_VSI_QUE_OPT_RSS_LUT_VSI);
+               }
+
                ctxt.info.valid_sections |= cpu_to_le16(I40E_AQ_VSI_PROP_VLAN_VALID);
                ctxt.info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_MODE_ALL;
                if (pf->vf[vsi->vf_id].spoofchk) {
@@ -10323,16 +10756,10 @@ static int i40e_add_vsi(struct i40e_vsi *vsi)
                i40e_vsi_setup_queue_map(vsi, &ctxt, enabled_tc, true);
                break;
 
-#ifdef I40E_FCOE
-       case I40E_VSI_FCOE:
-               ret = i40e_fcoe_vsi_init(vsi, &ctxt);
-               if (ret) {
-                       dev_info(&pf->pdev->dev, "failed to initialize FCoE VSI\n");
-                       return ret;
-               }
+       case I40E_VSI_IWARP:
+               /* send down message to iWARP */
                break;
 
-#endif /* I40E_FCOE */
        default:
                return -ENODEV;
        }
@@ -10359,7 +10786,7 @@ static int i40e_add_vsi(struct i40e_vsi *vsi)
        }
 
        vsi->active_filters = 0;
-       clear_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state);
+       clear_bit(__I40E_VSI_OVERFLOW_PROMISC, vsi->state);
        spin_lock_bh(&vsi->mac_filter_hash_lock);
        /* If macvlan filters already exist, force them to get loaded */
        hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) {
@@ -10412,7 +10839,7 @@ int i40e_vsi_release(struct i40e_vsi *vsi)
                return -ENODEV;
        }
        if (vsi == pf->vsi[pf->lan_vsi] &&
-           !test_bit(__I40E_DOWN, &pf->state)) {
+           !test_bit(__I40E_DOWN, pf->state)) {
                dev_info(&pf->pdev->dev, "Can't remove PF VSI\n");
                return -ENODEV;
        }
@@ -10742,9 +11169,6 @@ struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type,
        /* setup the netdev if needed */
        case I40E_VSI_MAIN:
        case I40E_VSI_VMDQ2:
-#ifdef I40E_FCOE
-       case I40E_VSI_FCOE:
-#endif
                ret = i40e_config_netdev(vsi);
                if (ret)
                        goto err_netdev;
@@ -10784,7 +11208,7 @@ struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type,
                break;
        }
 
-       if ((pf->flags & I40E_FLAG_RSS_AQ_CAPABLE) &&
+       if ((pf->hw_features & I40E_HW_RSS_AQ_CAPABLE) &&
            (vsi->type == I40E_VSI_VMDQ2)) {
                ret = i40e_vsi_config_rss(vsi);
        }
@@ -11388,7 +11812,6 @@ static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit)
                i40e_pf_config_rss(pf);
 
        /* fill in link information and enable LSE reporting */
-       i40e_update_link_info(&pf->hw);
        i40e_link_event(pf);
 
        /* Initialize user-specific link properties */
@@ -11399,6 +11822,13 @@ static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit)
        i40e_ptp_init(pf);
 
 #endif /* HAVE_PTP_1588_CLOCK */
+#if defined(HAVE_VXLAN_RX_OFFLOAD) || defined(HAVE_UDP_ENC_RX_OFFLOAD)
+#if defined(HAVE_UDP_ENC_TUNNEL) || defined(HAVE_UDP_ENC_RX_OFFLOAD)
+       /* repopulate tunnel port filters */
+       i40e_sync_udp_filters(pf);
+
+#endif /* HAVE_UDP_ENC_TUNNEL || HAVE_UDP_ENC_RX_OFFLOAD */
+#endif /* HAVE_VXLAN_RX_OFFLOAD || HAVE_UDP_ENC_RX_OFFLOAD */
        return ret;
 }
 
@@ -11411,9 +11841,6 @@ static void i40e_determine_queue_usage(struct i40e_pf *pf)
        int queues_left;
 
        pf->num_lan_qps = 0;
-#ifdef I40E_FCOE
-       pf->num_fcoe_qps = 0;
-#endif
 
        /* Find the max queues to be put into basic use.  We'll always be
         * using TC0, whether or not DCB is running, and TC0 will get the
@@ -11429,9 +11856,7 @@ static void i40e_determine_queue_usage(struct i40e_pf *pf)
 
                /* make sure all the fancies are disabled */
                pf->flags &= ~(I40E_FLAG_RSS_ENABLED    |
-#ifdef I40E_FCOE
-                              I40E_FLAG_FCOE_ENABLED   |
-#endif
+                              I40E_FLAG_IWARP_ENABLED  |
                               I40E_FLAG_FD_SB_ENABLED  |
                               I40E_FLAG_FD_ATR_ENABLED |
                               I40E_FLAG_DCB_CAPABLE    |
@@ -11447,9 +11872,7 @@ static void i40e_determine_queue_usage(struct i40e_pf *pf)
                queues_left -= pf->num_lan_qps;
 
                pf->flags &= ~(I40E_FLAG_RSS_ENABLED    |
-#ifdef I40E_FCOE
-                              I40E_FLAG_FCOE_ENABLED   |
-#endif
+                              I40E_FLAG_IWARP_ENABLED  |
                               I40E_FLAG_FD_SB_ENABLED  |
                               I40E_FLAG_FD_ATR_ENABLED |
                               I40E_FLAG_DCB_ENABLED    |
@@ -11470,22 +11893,6 @@ static void i40e_determine_queue_usage(struct i40e_pf *pf)
                queues_left -= pf->num_lan_qps;
        }
 
-#ifdef I40E_FCOE
-       if (pf->flags & I40E_FLAG_FCOE_ENABLED) {
-               if (I40E_DEFAULT_FCOE <= queues_left) {
-                       pf->num_fcoe_qps = I40E_DEFAULT_FCOE;
-               } else if (I40E_MINIMUM_FCOE <= queues_left) {
-                       pf->num_fcoe_qps = I40E_MINIMUM_FCOE;
-               } else {
-                       pf->num_fcoe_qps = 0;
-                       pf->flags &= ~I40E_FLAG_FCOE_ENABLED;
-                       dev_info(&pf->pdev->dev, "not enough queues for FCoE. FCoE feature will be disabled\n");
-               }
-
-               queues_left -= pf->num_fcoe_qps;
-       }
-
-#endif
        if (pf->flags & I40E_FLAG_FD_SB_ENABLED) {
                if (queues_left > 1) {
                        queues_left -= 1; /* save 1 queue for FD */
@@ -11517,9 +11924,6 @@ static void i40e_determine_queue_usage(struct i40e_pf *pf)
                pf->num_lan_qps, pf->alloc_rss_size, pf->num_req_vfs,
                pf->num_vf_qps, pf->num_vmdq_vsis, pf->num_vmdq_qps,
                queues_left);
-#ifdef I40E_FCOE
-       dev_dbg(&pf->pdev->dev, "fcoe queues = %d\n", pf->num_fcoe_qps);
-#endif
 }
 
 /**
@@ -11595,10 +11999,6 @@ static void i40e_print_features(struct i40e_pf *pf)
 #ifdef HAVE_PTP_1588_CLOCK
        if (pf->flags & I40E_FLAG_PTP)
                i += snprintf(&buf[i], REMAIN(i), " PTP");
-#endif
-#ifdef I40E_FCOE
-       if (pf->flags & I40E_FLAG_FCOE_ENABLED)
-               i += snprintf(&buf[i], REMAIN(i), " FCOE");
 #endif
        if (pf->flags & I40E_FLAG_VEB_MODE_ENABLED)
                i += snprintf(&buf[i], REMAIN(i), " VEB");
@@ -11610,6 +12010,22 @@ static void i40e_print_features(struct i40e_pf *pf)
        WARN_ON(i > INFO_STRING_LEN);
 }
 
+/**
+ * i40e_get_platform_mac_addr - get platform-specific MAC address
+ * @pdev: PCI device information struct
+ * @pf: board private structure
+ *
+ * Look up the MAC address for the device. First we'll try
+ * eth_platform_get_mac_address, which will check Open Firmware, or arch
+ * specific fallback. Otherwise, we'll default to the stored value in
+ * firmware.
+ **/
+static void i40e_get_platform_mac_addr(struct pci_dev *pdev, struct i40e_pf *pf)
+{
+       if (eth_platform_get_mac_address(&pdev->dev, pf->hw.mac.addr))
+               i40e_get_mac_addr(&pf->hw, pf->hw.mac.addr);
+}
+
 /**
  * i40e_probe - Device initialization routine
  * @pdev: PCI device information struct
@@ -11645,12 +12061,13 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        /* set up for high or low dma */
        err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
-       if (err)
-               err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
        if (err) {
-               dev_err(pci_dev_to_dev(pdev),
-                       "DMA configuration failed: 0x%x\n", err);
-               goto err_dma;
+               err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+               if (err) {
+                       dev_err(&pdev->dev,
+                               "DMA configuration failed: 0x%x\n", err);
+                       goto err_dma;
+               }
        }
 
        /* set up pci connections */
@@ -11678,7 +12095,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        pf->next_vsi = 0;
        pf->pdev = pdev;
        pci_set_drvdata(pdev, pf);
-       set_bit(__I40E_DOWN, &pf->state);
+       set_bit(__I40E_DOWN, pf->state);
 
        hw = &pf->hw;
        hw->back = pf;
@@ -11704,6 +12121,16 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        hw->bus.bus_id = pdev->bus->number;
        pf->instance = pfs_found;
 
+       /* Select something other than the 802.1ad ethertype for the
+        * switch to use internally and drop on ingress.
+        */
+       hw->switch_tag = 0xffff;
+       hw->first_tag = ETH_P_8021AD;
+       hw->second_tag = ETH_P_8021Q;
+
+       INIT_LIST_HEAD(&pf->l3_flex_pit_list);
+       INIT_LIST_HEAD(&pf->l4_flex_pit_list);
+
        /* set up the spinlocks for the AQ, do this only once in probe
         * and destroy them only once in remove
         */
@@ -11754,6 +12181,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
                goto err_pf_reset;
        }
+       i40e_get_oem_version(hw);
 
        /* provide nvm, fw, api versions */
        dev_info(&pdev->dev, "fw %d.%d.%05d api %d.%d nvm %s\n",
@@ -11762,11 +12190,10 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                 i40e_nvm_version_str(hw));
 
        if (hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR &&
-           hw->aq.api_min_ver > I40E_FW_API_VERSION_MINOR)
+           hw->aq.api_min_ver > I40E_FW_MINOR_VERSION(hw))
                dev_info(&pdev->dev,
                         "The driver for the device detected a newer version of the NVM image than expected. Please install the most recent version of the network driver.\n");
-       else if (hw->aq.api_maj_ver < I40E_FW_API_VERSION_MAJOR ||
-                hw->aq.api_min_ver < (I40E_FW_API_VERSION_MINOR - 1))
+       else if (hw->aq.api_maj_ver == 1 && hw->aq.api_min_ver < 4)
                dev_info(&pdev->dev,
                         "The driver for the device detected an older version of the NVM image than expected. Please update the NVM image.\n");
 
@@ -11788,8 +12215,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        }
 
        err = i40e_init_lan_hmc(hw, hw->func_caps.num_tx_qp,
-                               hw->func_caps.num_rx_qp,
-                               pf->fcoe_hmc_cntx_num, pf->fcoe_hmc_filt_num);
+                               hw->func_caps.num_rx_qp, 0, 0);
        if (err) {
                dev_info(&pdev->dev, "init_lan_hmc failed: %d\n", err);
                goto err_init_lan_hmc;
@@ -11806,12 +12232,14 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
         * Ignore error return codes because if it was already disabled via
         * hardware settings this will fail
         */
-       if (pf->flags & I40E_FLAG_STOP_FW_LLDP) {
+       if (pf->hw_features & I40E_HW_STOP_FW_LLDP) {
                dev_info(&pdev->dev, "Stopping firmware LLDP agent.\n");
                i40e_aq_stop_lldp(hw, true, NULL);
        }
 
-       i40e_get_mac_addr(hw, hw->mac.addr);
+       /* allow a platform config to override the HW addr */
+       i40e_get_platform_mac_addr(pdev, pf);
+
        if (!is_valid_ether_addr(hw->mac.addr)) {
                dev_info(&pdev->dev, "invalid MAC address %pM\n", hw->mac.addr);
                err = -EIO;
@@ -11821,19 +12249,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        ether_addr_copy(hw->mac.perm_addr, hw->mac.addr);
        i40e_get_port_mac_addr(hw, hw->mac.port_addr);
        if (is_valid_ether_addr(hw->mac.port_addr))
-               pf->flags |= I40E_FLAG_PORT_ID_VALID;
-#ifdef I40E_FCOE
-       err = i40e_get_san_mac_addr(hw, hw->mac.san_addr);
-       if (err)
-               dev_info(&pdev->dev,
-                        "(non-fatal) SAN MAC retrieval failed: %d\n", err);
-       if (!is_valid_ether_addr(hw->mac.san_addr)) {
-               dev_warn(&pdev->dev, "invalid SAN MAC address %pM, falling back to LAN MAC\n",
-                        hw->mac.san_addr);
-               ether_addr_copy(hw->mac.san_addr, hw->mac.addr);
-       }
-       dev_info(&pf->pdev->dev, "SAN MAC: %pM\n", hw->mac.san_addr);
-#endif /* I40E_FCOE */
+               pf->hw_features |= I40E_HW_PORT_ID_VALID;
 
 #ifdef HAVE_PCI_ERS
        pci_save_state(pdev);
@@ -11853,8 +12269,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        pf->service_timer_period = HZ;
 
        INIT_WORK(&pf->service_task, i40e_service_task);
-       clear_bit(__I40E_SERVICE_SCHED, &pf->state);
-       pf->flags |= I40E_FLAG_NEED_LINK_UPDATE;
+       clear_bit(__I40E_SERVICE_SCHED, pf->state);
 
        /* NVM bit on means WoL disabled for the port */
        i40e_read_nvm_word(hw, I40E_SR_NVM_WAKE_ON_LAN, &wol_nvm_bits);
@@ -11892,7 +12307,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        /* prep for VF support */
        if ((pf->flags & I40E_FLAG_SRIOV_ENABLED) &&
            (pf->flags & I40E_FLAG_MSIX_ENABLED) &&
-           !test_bit(__I40E_BAD_EEPROM, &pf->state)) {
+           !test_bit(__I40E_BAD_EEPROM, pf->state)) {
                if (pci_num_vf(pdev))
                        pf->flags |= I40E_FLAG_VEB_MODE_ENABLED;
 #if !defined(HAVE_SRIOV_CONFIGURE) && !defined(HAVE_RHEL6_SRIOV_CONFIGURE)
@@ -11956,7 +12371,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                wr32(hw, I40E_REG_MSS, val);
        }
 
-       if (pf->flags & I40E_FLAG_RESTART_AUTONEG) {
+       if (pf->hw_features & I40E_HW_RESTART_AUTONEG) {
                msleep(75);
                err = i40e_aq_set_link_restart_an(&pf->hw, true, NULL);
                if (err)
@@ -11969,7 +12384,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
         * before setting up the misc vector or we get a race and the vector
         * ends up disabled forever.
         */
-       clear_bit(__I40E_DOWN, &pf->state);
+       clear_bit(__I40E_DOWN, pf->state);
 
        /* In case of MSIX we are going to setup the misc vector right here
         * to handle admin queue events etc. In case of legacy and MSI
@@ -11989,7 +12404,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        /* prep for VF support */
        if ((pf->flags & I40E_FLAG_SRIOV_ENABLED) &&
            (pf->flags & I40E_FLAG_MSIX_ENABLED) &&
-           !test_bit(__I40E_BAD_EEPROM, &pf->state)) {
+           !test_bit(__I40E_BAD_EEPROM, pf->state)) {
                /* disable link interrupts for VFs */
                val = rd32(hw, I40E_PFGEN_PORTMDIO_NUM);
                val &= ~I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_MASK;
@@ -12017,6 +12432,18 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        }
 #endif /* CONFIG_PCI_IOV */
 
+       if (pf->flags & I40E_FLAG_IWARP_ENABLED) {
+               pf->iwarp_base_vector = i40e_get_lump(pf, pf->irq_pile,
+                                                     pf->num_iwarp_msix,
+                                                     I40E_IWARP_IRQ_PILE_ID);
+               if (pf->iwarp_base_vector < 0) {
+                       dev_info(&pdev->dev,
+                                "failed to get tracking for %d vectors for IWARP err=%d\n",
+                                pf->num_iwarp_msix, pf->iwarp_base_vector);
+                       pf->flags &= ~I40E_FLAG_IWARP_ENABLED;
+               }
+       }
+
        pfs_found++;
        i40e_dbg_pf_init(pf);
 
@@ -12027,18 +12454,20 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        mod_timer(&pf->service_timer,
                  round_jiffies(jiffies + pf->service_timer_period));
 
-#ifdef I40E_FCOE
-       /* create FCoE interface */
-       i40e_fcoe_vsi_setup(pf);
-
-#endif
+       /* add this PF to client device list and launch a client service task */
+       if (pf->flags & I40E_FLAG_IWARP_ENABLED) {
+               err = i40e_lan_add_device(pf);
+               if (err)
+                       dev_info(&pdev->dev, "Failed to add PF to client API service list: %d\n",
+                                err);
+       }
 #define PCI_SPEED_SIZE 8
 #define PCI_WIDTH_SIZE 8
        /* Devices on the IOSF bus do not have this information
         * and will report PCI Gen 1 x 1 by default so don't bother
         * checking them.
         */
-       if (!(pf->flags & I40E_FLAG_NO_PCI_LINK_CHECK)) {
+       if (!(pf->hw_features & I40E_HW_NO_PCI_LINK_CHECK)) {
                char speed[PCI_SPEED_SIZE] = "Unknown";
                char width[PCI_WIDTH_SIZE] = "Unknown";
 
@@ -12109,9 +12538,9 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        if ((pf->hw.device_id == I40E_DEV_ID_10G_BASE_T) ||
            (pf->hw.device_id == I40E_DEV_ID_10G_BASE_T4))
-               pf->flags |= I40E_FLAG_PHY_CONTROLS_LEDS;
+               pf->hw_features |= I40E_HW_PHY_CONTROLS_LEDS;
        if (pf->hw.device_id == I40E_DEV_ID_SFP_I_X722)
-               pf->flags |= I40E_FLAG_HAVE_CRT_RETIMER;
+               pf->hw_features |= I40E_HW_HAVE_CRT_RETIMER;
        /* print a string summarizing features */
        i40e_print_features(pf);
 
@@ -12119,7 +12548,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        /* Unwind what we've done if something failed in the setup */
 err_vsis:
-       set_bit(__I40E_DOWN, &pf->state);
+       set_bit(__I40E_DOWN, pf->state);
        i40e_clear_interrupt_scheme(pf);
        kfree(pf->vsi);
 err_switch_setup:
@@ -12135,7 +12564,7 @@ err_adminq_setup:
 err_pf_reset:
        dev_warn(&pdev->dev, "previous errors forcing module to load in debug mode\n");
        i40e_dbg_pf_init(pf);
-       set_bit(__I40E_DEBUG_MODE, &pf->state);
+       set_bit(__I40E_DEBUG_MODE, pf->state);
        return 0;
 err_ioremap:
        kfree(pf);
@@ -12179,14 +12608,19 @@ static void i40e_remove(struct pci_dev *pdev)
 
 #endif /* HAVE_PTP_1588_CLOCK */
        /* no more scheduling of any task */
-       set_bit(__I40E_SUSPENDED, &pf->state);
-       set_bit(__I40E_DOWN, &pf->state);
+       set_bit(__I40E_SUSPENDED, pf->state);
+       set_bit(__I40E_DOWN, pf->state);
        if (pf->service_timer.data)
                del_timer_sync(&pf->service_timer);
        if (pf->service_task.func)
                cancel_work_sync(&pf->service_task);
 
-       if (test_bit(__I40E_DEBUG_MODE, &pf->state))
+       /* Client close must be called explicitly here because the timer
+        * has been stopped.
+        */
+       i40e_notify_client_of_netdev_close(pf->vsi[pf->lan_vsi], false);
+
+       if (test_bit(__I40E_DEBUG_MODE, pf->state))
                goto unmap;
 
        if (pf->flags & I40E_FLAG_SRIOV_ENABLED) {
@@ -12214,6 +12648,14 @@ static void i40e_remove(struct pci_dev *pdev)
        if (pf->vsi[pf->lan_vsi])
                i40e_vsi_release(pf->vsi[pf->lan_vsi]);
 
+       /* remove attached clients */
+       if (pf->flags & I40E_FLAG_IWARP_ENABLED) {
+               ret_code = i40e_lan_del_device(pf);
+               if (ret_code)
+                       dev_warn(&pdev->dev, "Failed to delete client device: %d\n",
+                                ret_code);
+       }
+
        /* shutdown and destroy the HMC */
        if (hw->hmc.hmc_obj) {
                ret_code = i40e_shutdown_lan_hmc(hw);
@@ -12274,13 +12716,16 @@ static pci_ers_result_t i40e_pci_error_detected(struct pci_dev *pdev,
 
        dev_info(&pdev->dev, "%s: error %d\n", __func__, error);
 
-       /* shutdown all operations */
-       if (!test_bit(__I40E_SUSPENDED, &pf->state)) {
-               rtnl_lock();
-               i40e_prep_for_reset(pf);
-               rtnl_unlock();
+       if (!pf) {
+               dev_info(&pdev->dev,
+                        "Cannot recover -error happened during device probe\n");
+               return PCI_ERS_RESULT_DISCONNECT;
        }
 
+       /* shutdown all operations */
+       if (!test_bit(__I40E_SUSPENDED, pf->state))
+               i40e_prep_for_reset(pf, false);
+
        /* Request a slot reset */
        return PCI_ERS_RESULT_NEED_RESET;
 }
@@ -12330,6 +12775,49 @@ static pci_ers_result_t i40e_pci_error_slot_reset(struct pci_dev *pdev)
        return result;
 }
 
+#if defined(HAVE_PCI_ERROR_HANDLER_RESET_PREPARE) || defined(HAVE_PCI_ERROR_HANDLER_RESET_NOTIFY) || defined(HAVE_RHEL7_PCI_RESET_NOTIFY)
+/**
+ * i40e_pci_error_reset_prepare - prepare device driver for pci reset
+ * @pdev: PCI device information struct
+ */
+static void i40e_pci_error_reset_prepare(struct pci_dev *pdev)
+{
+       struct i40e_pf *pf = pci_get_drvdata(pdev);
+
+       i40e_prep_for_reset(pf, false);
+}
+
+/**
+ * i40e_pci_error_reset_done - pci reset done, device driver reset can begin
+ * @pdev: PCI device information struct
+ */
+static void i40e_pci_error_reset_done(struct pci_dev *pdev)
+{
+       struct i40e_pf *pf = pci_get_drvdata(pdev);
+
+       i40e_reset_and_rebuild(pf, false, false);
+}
+
+#endif
+#if defined(HAVE_PCI_ERROR_HANDLER_RESET_NOTIFY) || defined(HAVE_RHEL7_PCI_RESET_NOTIFY)
+/**
+ * i40e_pci_error_reset_notify - notify device driver of pci reset
+ * @pdev: PCI device information struct
+ * @prepare: true if device is about to be reset; false if reset attempt
+ * completed
+ *
+ * Called to perform pf reset when a pci function level reset is triggered
+ **/
+static void i40e_pci_error_reset_notify(struct pci_dev *pdev, bool prepare)
+{
+       dev_dbg(&pdev->dev, "%s\n", __func__);
+       if (prepare)
+               i40e_pci_error_reset_prepare(pdev);
+       else
+               i40e_pci_error_reset_done(pdev);
+}
+
+#endif
 /**
  * i40e_pci_error_resume - restart operations after PCI error recovery
  * @pdev: PCI device information struct
@@ -12342,12 +12830,57 @@ static void i40e_pci_error_resume(struct pci_dev *pdev)
        struct i40e_pf *pf = pci_get_drvdata(pdev);
 
        dev_dbg(&pdev->dev, "%s\n", __func__);
-       if (test_bit(__I40E_SUSPENDED, &pf->state))
+       if (test_bit(__I40E_SUSPENDED, pf->state))
                return;
 
-       rtnl_lock();
-       i40e_handle_reset_warning(pf);
-       rtnl_unlock();
+       i40e_handle_reset_warning(pf, false);
+}
+
+/**
+ * i40e_enable_mc_magic_wake - enable multicast magic packet wake up
+ * using the mac_address_write admin q function
+ * @pf: pointer to i40e_pf struct
+ **/
+static void i40e_enable_mc_magic_wake(struct i40e_pf *pf)
+{
+       struct i40e_hw *hw = &pf->hw;
+       i40e_status ret;
+       u8 mac_addr[6];
+       u16 flags = 0;
+
+       /* Get current MAC address in case it's an LAA */
+       if (pf->vsi[pf->lan_vsi] && pf->vsi[pf->lan_vsi]->netdev) {
+               ether_addr_copy(mac_addr,
+                               pf->vsi[pf->lan_vsi]->netdev->dev_addr);
+       } else {
+               dev_err(&pf->pdev->dev,
+                       "Failed to retrieve MAC address; using default\n");
+               ether_addr_copy(mac_addr, hw->mac.addr);
+       }
+
+       /* The FW expects the mac address write cmd to first be called with
+        * one of these flags before calling it again with the multicast
+        * enable flags.
+        */
+       flags = I40E_AQC_WRITE_TYPE_LAA_WOL;
+
+       if (hw->func_caps.flex10_enable && hw->partition_id != 1)
+               flags = I40E_AQC_WRITE_TYPE_LAA_ONLY;
+
+       ret = i40e_aq_mac_address_write(hw, flags, mac_addr, NULL);
+       if (ret) {
+               dev_err(&pf->pdev->dev,
+                       "Failed to update MAC address registers; cannot enable Multicast Magic packet wake up");
+               return;
+       }
+
+       flags = I40E_AQC_MC_MAG_EN
+                       | I40E_AQC_WOL_PRESERVE_ON_PFR
+                       | I40E_AQC_WRITE_TYPE_UPDATE_MC_MAG;
+       ret = i40e_aq_mac_address_write(hw, flags, mac_addr, NULL);
+       if (ret)
+               dev_err(&pf->pdev->dev,
+                       "Failed to enable Multicast Magic Packet wake up\n");
 }
 
 /**
@@ -12359,19 +12892,25 @@ static void i40e_shutdown(struct pci_dev *pdev)
        struct i40e_pf *pf = pci_get_drvdata(pdev);
        struct i40e_hw *hw = &pf->hw;
 
-       set_bit(__I40E_SUSPENDED, &pf->state);
-       set_bit(__I40E_DOWN, &pf->state);
+       set_bit(__I40E_SUSPENDED, pf->state);
+       set_bit(__I40E_DOWN, pf->state);
 
-       if (test_bit(__I40E_DEBUG_MODE, &pf->state))
+       if (test_bit(__I40E_DEBUG_MODE, pf->state))
                goto debug_mode;
 
        del_timer_sync(&pf->service_timer);
        cancel_work_sync(&pf->service_task);
        i40e_fdir_teardown(pf);
 
-       rtnl_lock();
-       i40e_prep_for_reset(pf);
-       rtnl_unlock();
+       /* Client close must be called explicitly here because the timer
+        * has been stopped.
+        */
+       i40e_notify_client_of_netdev_close(pf->vsi[pf->lan_vsi], false);
+
+       if (pf->wol_en && (pf->hw_features & I40E_HW_WOL_MC_MAGIC_PKT_WAKE))
+               i40e_enable_mc_magic_wake(pf);
+
+       i40e_prep_for_reset(pf, false);
 
        wr32(hw, I40E_PFPM_APM,
             (pf->wol_en ? I40E_PFPM_APM_APME_MASK : 0));
@@ -12389,40 +12928,103 @@ debug_mode:
 
 #ifdef CONFIG_PM
 /**
- * i40e_suspend - PCI callback for moving to D3
- * @pdev: PCI device information struct
+ * i40e_suspend - PM callback for moving to D3
+ * @dev: generic device information structure
  **/
-static int i40e_suspend(struct pci_dev *pdev, pm_message_t state)
+static int i40e_suspend(struct device *dev)
 {
+       struct pci_dev *pdev = to_pci_dev(dev);
        struct i40e_pf *pf = pci_get_drvdata(pdev);
        struct i40e_hw *hw = &pf->hw;
-       int retval = 0;
 
-       set_bit(__I40E_SUSPENDED, &pf->state);
-       set_bit(__I40E_DOWN, &pf->state);
+       /* If we're already suspended, then there is nothing to do */
+       if (test_and_set_bit(__I40E_SUSPENDED, pf->state))
+               return 0;
 
-       if (test_bit(__I40E_DEBUG_MODE, &pf->state))
-               goto debug_mode;
+       set_bit(__I40E_DOWN, pf->state);
 
-       rtnl_lock();
-       i40e_prep_for_reset(pf);
-       rtnl_unlock();
+       /* Ensure service task will not be running */
+       del_timer_sync(&pf->service_timer);
+       cancel_work_sync(&pf->service_task);
 
-       wr32(hw, I40E_PFPM_APM,
-            (pf->wol_en ? I40E_PFPM_APM_APME_MASK : 0));
-       wr32(hw, I40E_PFPM_WUFC,
-            (pf->wol_en ? I40E_PFPM_WUFC_MAG_MASK : 0));
+       if (test_bit(__I40E_DEBUG_MODE, pf->state))
+               return 0;
 
-       i40e_stop_misc_vector(pf);
-       if (pf->msix_entries) {
-               synchronize_irq(pf->msix_entries[0].vector);
-               free_irq(pf->msix_entries[0].vector, pf);
+       if (pf->wol_en && (pf->hw_features & I40E_HW_WOL_MC_MAGIC_PKT_WAKE))
+               i40e_enable_mc_magic_wake(pf);
+
+       i40e_prep_for_reset(pf, false);
+
+       wr32(hw, I40E_PFPM_APM, (pf->wol_en ? I40E_PFPM_APM_APME_MASK : 0));
+       wr32(hw, I40E_PFPM_WUFC, (pf->wol_en ? I40E_PFPM_WUFC_MAG_MASK : 0));
+
+       /* Clear the interrupt scheme and release our IRQs so that the system
+        * can safely hibernate even when there are a large number of CPUs.
+        * Otherwise hibernation might fail when mapping all the vectors back
+        * to CPU0.
+        */
+       i40e_clear_interrupt_scheme(pf);
+
+       return 0;
+}
+
+/**
+ * i40e_resume - PM callback for waking up from D3
+ * @dev: generic device information structure
+ **/
+static int i40e_resume(struct device *dev)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct i40e_pf *pf = pci_get_drvdata(pdev);
+       int err;
+
+       /* If we're not suspended, then there is nothing to do */
+       if (!test_bit(__I40E_SUSPENDED, pf->state))
+               return 0;
+
+       /* We cleared the interrupt scheme when we suspended, so we need to
+        * restore it now to resume device functionality.
+        */
+       err = i40e_restore_interrupt_scheme(pf);
+       if (err) {
+               dev_err(&pdev->dev, "Cannot restore interrupt scheme: %d\n",
+                       err);
        }
+
+       clear_bit(__I40E_DOWN, pf->state);
+       i40e_reset_and_rebuild(pf, false, false);
+
+       /* Clear suspended state last after everything is recovered */
+       clear_bit(__I40E_SUSPENDED, pf->state);
+
+       /* Restart the service task */
+       mod_timer(&pf->service_timer,
+                 round_jiffies(jiffies + pf->service_timer_period));
+
+       return 0;
+}
+
+#ifdef USE_LEGACY_PM_SUPPORT
+/**
+ * i40e_legacy_suspend - PCI callback for moving to D3
+ * @pdev: PCI device information struct
+ *
+ * Legacy suspend handler for older kernels which do not support the newer
+ * generic callbacks
+ **/
+static int i40e_legacy_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       struct i40e_pf *pf = pci_get_drvdata(pdev);
+       int retval = i40e_suspend(&pdev->dev);
+
+       /* Some older kernels may not handle state correctly for legacy power
+        * management, so we'll handle it here ourselves
+        */
        retval = pci_save_state(pdev);
        if (retval)
                return retval;
 
-debug_mode:
+       pci_disable_device(pdev);
        pci_wake_from_d3(pdev, pf->wol_en);
        pci_set_power_state(pdev, PCI_D3hot);
 
@@ -12432,10 +13034,13 @@ debug_mode:
 /**
  * i40e_resume - PCI callback for waking up from D3
  * @pdev: PCI device information struct
+ *
+ * Legacy resume handler for kernels which do not support the newer generic
+ * callbacks.
+ * __always_unused
  **/
-static int i40e_resume(struct pci_dev *pdev)
+static int i40e_legacy_resume(struct pci_dev *pdev)
 {
-       struct i40e_pf *pf = pci_get_drvdata(pdev);
        u32 err;
 
        pci_set_power_state(pdev, PCI_D0);
@@ -12455,27 +13060,11 @@ static int i40e_resume(struct pci_dev *pdev)
        /* no wakeup events while running */
        pci_wake_from_d3(pdev, false);
 
-       /* handling the reset will rebuild the device state */
-       if (test_and_clear_bit(__I40E_SUSPENDED, &pf->state)) {
-               clear_bit(__I40E_DOWN, &pf->state);
-               rtnl_lock();
-               if (pf->msix_entries) {
-                       err = request_irq(pf->msix_entries[0].vector,
-                                         i40e_intr, 0, pf->int_name, pf);
-                       if (err) {
-                               dev_err(&pf->pdev->dev,
-                                       "request_irq for %s failed: %d\n",
-                                       pf->int_name, err);
-                       }
-               }
-               i40e_reset_and_rebuild(pf, false);
-               rtnl_unlock();
-       }
-
-       return 0;
+       return i40e_resume(&pdev->dev);
 }
+#endif /* USE_LEGACY_PM_SUPPORT */
+#endif /* CONFIG_PM */
 
-#endif
 #ifdef HAVE_CONST_STRUCT_PCI_ERROR_HANDLERS
 static const struct pci_error_handlers i40e_err_handler = {
 #else
@@ -12483,16 +13072,31 @@ static struct pci_error_handlers i40e_err_handler = {
 #endif
        .error_detected = i40e_pci_error_detected,
        .slot_reset = i40e_pci_error_slot_reset,
+#ifdef HAVE_PCI_ERROR_HANDLER_RESET_NOTIFY
+       .reset_notify = i40e_pci_error_reset_notify,
+#endif
+#ifdef HAVE_PCI_ERROR_HANDLER_RESET_PREPARE
+       .reset_prepare = i40e_pci_error_reset_prepare,
+       .reset_done = i40e_pci_error_reset_done,
+#endif
        .resume = i40e_pci_error_resume,
 };
 
-#ifdef HAVE_RHEL6_SRIOV_CONFIGURE
+#if defined(HAVE_RHEL6_SRIOV_CONFIGURE) || defined(HAVE_RHEL7_PCI_DRIVER_RH)
 static struct pci_driver_rh i40e_driver_rh = {
+#ifdef HAVE_RHEL6_SRIOV_CONFIGURE
        .sriov_configure = i40e_pci_sriov_configure,
+#elif defined(HAVE_RHEL7_PCI_RESET_NOTIFY)
+       .reset_notify = i40e_pci_error_reset_notify,
+#endif
 };
 
 #endif
 #endif /* HAVE_PCI_ERS */
+#ifndef USE_LEGACY_PM_SUPPORT
+static SIMPLE_DEV_PM_OPS(i40e_pm_ops, i40e_suspend, i40e_resume);
+
+#endif
 static struct pci_driver i40e_driver = {
        .name     = i40e_driver_name,
        .id_table = i40e_pci_tbl,
@@ -12503,9 +13107,15 @@ static struct pci_driver i40e_driver = {
        .remove   = i40e_remove,
 #endif
 #ifdef CONFIG_PM
-       .suspend  = i40e_suspend,
-       .resume   = i40e_resume,
-#endif
+#ifdef USE_LEGACY_PM_SUPPORT
+       .suspend  = i40e_legacy_suspend,
+       .resume   = i40e_legacy_resume,
+#else /* USE_LEGACY_PM_SUPPORT */
+       .driver   = {
+               .pm = &i40e_pm_ops,
+       },
+#endif /* !USE_LEGACY_PM_SUPPORT */
+#endif /* CONFIG_PM */
        .shutdown = i40e_shutdown,
 #ifdef HAVE_PCI_ERS
        .err_handler = &i40e_err_handler,
@@ -12516,6 +13126,9 @@ static struct pci_driver i40e_driver = {
 #ifdef HAVE_RHEL6_SRIOV_CONFIGURE
        .rh_reserved = &i40e_driver_rh,
 #endif
+#ifdef HAVE_RHEL7_PCI_DRIVER_RH
+       .pci_driver_rh = &i40e_driver_rh,
+#endif
 };
 
 /**
@@ -12542,7 +13155,13 @@ static int __init i40e_init_module(void)
                pr_err("%s: Failed to create workqueue\n", i40e_driver_name);
                return -ENOMEM;
        }
+#ifdef HAVE_RHEL7_PCI_DRIVER_RH
+       /* The size member must be initialized in the driver via a call to
+        * set_pci_driver_rh_size before pci_register_driver is called
+        */
+       set_pci_driver_rh_size(i40e_driver_rh);
 
+#endif
        i40e_dbg_init();
        return pci_register_driver(&i40e_driver);
 }
similarity index 97%
rename from i40e-dkms/i40e-1.6.42/src/i40e_nvm.c
rename to i40e-dkms/i40e-2.1.26/src/i40e_nvm.c
index 8d721f55fc67656b5421f11dfb509848a9025dcf..fa8343c8347883f496fc624fcaf7773091de85c4 100644 (file)
@@ -201,14 +201,14 @@ i40e_status i40e_read_nvm_word(struct i40e_hw *hw, u16 offset,
 {
        i40e_status ret_code = I40E_SUCCESS;
 
-       if (hw->flags & I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE) {
-               ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
-               if (!ret_code) {
+       ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
+       if (!ret_code) {
+               if (hw->flags & I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE) {
                        ret_code = i40e_read_nvm_word_aq(hw, offset, data);
-                       i40e_release_nvm(hw);
+               } else {
+                       ret_code = i40e_read_nvm_word_srctl(hw, offset, data);
                }
-       } else {
-               ret_code = i40e_read_nvm_word_srctl(hw, offset, data);
+               i40e_release_nvm(hw);
        }
        return ret_code;
 }
@@ -658,12 +658,18 @@ i40e_status i40e_validate_nvm_checksum(struct i40e_hw *hw,
        u16 checksum_sr = 0;
        u16 checksum_local = 0;
 
-       if (hw->flags & I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE)
-               ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
+       /* acquire_nvm provides exclusive NVM lock to synchronize access across
+        * PFs. X710 uses i40e_read_nvm_word_srctl which polls for done bit
+        * twice (first time to be able to write address to I40E_GLNVM_SRCTL
+        * register, second to read data from I40E_GLNVM_SRDATA. One PF can see
+        * done bit and try to write address, while another one will interpret
+        * it as a good time to read data. It will cause invalid data to be
+        * read.
+        */
+       ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
        if (!ret_code) {
                ret_code = i40e_calc_nvm_checksum(hw, &checksum_local);
-               if (hw->flags & I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE)
-                       i40e_release_nvm(hw);
+       i40e_release_nvm(hw);
                if (ret_code != I40E_SUCCESS)
                        goto i40e_validate_nvm_checksum_exit;
        } else {
@@ -806,6 +812,15 @@ i40e_status i40e_nvmupd_command(struct i40e_hw *hw,
                hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
        }
 
+       /* Acquire lock to prevent race condition where adminq_task
+        * can execute after i40e_nvmupd_nvm_read/write but before state
+        * variables (nvm_wait_opcode, nvm_release_on_done) are updated.
+        *
+        * During NVMUpdate, it is observed that lock could be held for
+        * ~5ms for most commands. However lock is held for ~60ms for
+        * NVMUPD_CSUM_LCB command.
+        */
+       i40e_acquire_spinlock(&hw->aq.arq_spinlock);
        switch (hw->nvmupd_state) {
        case I40E_NVMUPD_STATE_INIT:
                status = i40e_nvmupd_state_init(hw, cmd, bytes, perrno);
@@ -826,7 +841,8 @@ i40e_status i40e_nvmupd_command(struct i40e_hw *hw,
                 */
                if (cmd->offset == 0xffff) {
                        i40e_nvmupd_check_wait_event(hw, hw->nvm_wait_opcode);
-                       return I40E_SUCCESS;
+                       status = I40E_SUCCESS;
+                       goto exit;
                }
 
                status = I40E_ERR_NOT_READY;
@@ -841,6 +857,8 @@ i40e_status i40e_nvmupd_command(struct i40e_hw *hw,
                *perrno = -ESRCH;
                break;
        }
+exit:
+       i40e_release_spinlock(&hw->aq.arq_spinlock);
        return status;
 }
 
similarity index 95%
rename from i40e-dkms/i40e-1.6.42/src/i40e_osdep.h
rename to i40e-dkms/i40e-2.1.26/src/i40e_osdep.h
index 6c2a73b46a9a981b19339ef7d139847063ec5743..c3fca50e71537ecbef7ddd2efd9d69fc81326d4b 100644 (file)
@@ -78,7 +78,7 @@ struct i40e_dma_mem {
        void *va;
        dma_addr_t pa;
        u32 size;
-} __packed;
+};
 
 #define i40e_allocate_dma_mem(h, m, unused, s, a) \
                        i40e_allocate_dma_mem_d(h, m, unused, s, a)
@@ -88,7 +88,7 @@ struct i40e_dma_mem {
 struct i40e_virt_mem {
        void *va;
        u32 size;
-} __packed;
+};
 
 #define i40e_allocate_virt_mem(h, m, s) i40e_allocate_virt_mem_d(h, m, s)
 #define i40e_free_virt_mem(h, m) i40e_free_virt_mem_d(h, m)
@@ -138,9 +138,4 @@ static inline void i40e_no_action(struct i40e_spinlock *sp)
 #define i40e_memcpy(a, b, c, d)  memcpy((a), (b), (c))
 
 typedef enum i40e_status_code i40e_status;
-#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
-#ifdef WITH_FCOE
-#define I40E_FCOE
-#endif
-#endif /* CONFIG_FCOE or CONFIG_FCOE_MODULE */
 #endif /* _I40E_OSDEP_H_ */
similarity index 91%
rename from i40e-dkms/i40e-1.6.42/src/i40e_prototype.h
rename to i40e-dkms/i40e-2.1.26/src/i40e_prototype.h
index ce478ab1c86b0844870eecb474d8c49e22dca0fa..783e5842ba13ee626a4707bb7cf197a0fd1863c4 100644 (file)
@@ -26,7 +26,7 @@
 
 #include "i40e_type.h"
 #include "i40e_alloc.h"
-#include "i40e_virtchnl.h"
+#include "virtchnl.h"
 
 /* Prototypes for shared code functions that are not in
  * the standard function pointer structures.  These are
@@ -307,11 +307,21 @@ i40e_status i40e_aq_add_cloud_filters(struct i40e_hw *hw,
                u16 vsi,
                struct i40e_aqc_add_remove_cloud_filters_element_data *filters,
                u8 filter_count);
-
+i40e_status i40e_aq_add_cloud_filters_big_buffer(struct i40e_hw *hw,
+       u16 seid,
+       struct i40e_aqc_add_rm_cloud_filt_elem_ext *filters,
+       u8 filter_count);
 i40e_status i40e_aq_remove_cloud_filters(struct i40e_hw *hw,
                u16 vsi,
                struct i40e_aqc_add_remove_cloud_filters_element_data *filters,
                u8 filter_count);
+i40e_status i40e_aq_remove_cloud_filters_big_buffer(
+       struct i40e_hw *hw, u16 seid,
+       struct i40e_aqc_add_rm_cloud_filt_elem_ext *filters,
+       u8 filter_count);
+i40e_status i40e_aq_replace_cloud_filters(struct i40e_hw *hw,
+               struct i40e_aqc_replace_cloud_filters_cmd *filters,
+               struct i40e_aqc_replace_cloud_filters_cmd_buf *cmd_buf);
 i40e_status i40e_aq_alternate_read(struct i40e_hw *hw,
                                u32 reg_addr0, u32 *reg_val0,
                                u32 reg_addr1, u32 *reg_val1);
@@ -332,9 +342,6 @@ i40e_status i40e_get_port_mac_addr(struct i40e_hw *hw, u8 *mac_addr);
 i40e_status i40e_read_pba_string(struct i40e_hw *hw, u8 *pba_num,
                                            u32 pba_num_size);
 void i40e_pre_tx_queue_cfg(struct i40e_hw *hw, u32 queue, bool enable);
-#ifdef I40E_FCOE
-i40e_status i40e_get_san_mac_addr(struct i40e_hw *hw, u8 *mac_addr);
-#endif
 /* prototype for functions used for NVM access */
 i40e_status i40e_init_nvm(struct i40e_hw *hw);
 i40e_status i40e_acquire_nvm(struct i40e_hw *hw,
@@ -371,10 +378,10 @@ void i40e_destroy_spinlock(struct i40e_spinlock *sp);
 
 /* i40e_common for VF drivers*/
 void i40e_vf_parse_hw_config(struct i40e_hw *hw,
-                            struct i40e_virtchnl_vf_resource *msg);
+                            struct virtchnl_vf_resource *msg);
 i40e_status i40e_vf_reset(struct i40e_hw *hw);
 i40e_status i40e_aq_send_msg_to_pf(struct i40e_hw *hw,
-                               enum i40e_virtchnl_ops v_opcode,
+                               enum virtchnl_ops v_opcode,
                                i40e_status v_retval,
                                u8 *msg, u16 msglen,
                                struct i40e_asq_cmd_details *cmd_details);
@@ -400,6 +407,15 @@ i40e_status i40e_aq_rx_ctl_write_register(struct i40e_hw *hw,
                                u32 reg_addr, u32 reg_val,
                                struct i40e_asq_cmd_details *cmd_details);
 void i40e_write_rx_ctl(struct i40e_hw *hw, u32 reg_addr, u32 reg_val);
+i40e_status i40e_aq_set_phy_register(struct i40e_hw *hw,
+                               u8 phy_select, u8 dev_addr,
+                               u32 reg_addr, u32 reg_val,
+                               struct i40e_asq_cmd_details *cmd_details);
+i40e_status i40e_aq_get_phy_register(struct i40e_hw *hw,
+                               u8 phy_select, u8 dev_addr,
+                               u32 reg_addr, u32 *reg_val,
+                               struct i40e_asq_cmd_details *cmd_details);
+
 i40e_status i40e_aq_set_arp_proxy_config(struct i40e_hw *hw,
                        struct i40e_aqc_arp_proxy_data *proxy_config,
                        struct i40e_asq_cmd_details *cmd_details);
@@ -432,4 +448,29 @@ i40e_status i40e_write_phy_register(struct i40e_hw *hw,
 u8 i40e_get_phy_address(struct i40e_hw *hw, u8 dev_num);
 i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw,
                                              u32 time, u32 interval);
+i40e_status i40e_aq_write_ddp(struct i40e_hw *hw, void *buff,
+                                       u16 buff_size, u32 track_id,
+                                       u32 *error_offset, u32 *error_info,
+                                       struct i40e_asq_cmd_details *
+                                       cmd_details);
+i40e_status i40e_aq_get_ddp_list(struct i40e_hw *hw, void *buff,
+                                          u16 buff_size, u8 flags,
+                                          struct i40e_asq_cmd_details *
+                                          cmd_details);
+struct i40e_generic_seg_header *
+i40e_find_segment_in_package(u32 segment_type,
+                            struct i40e_package_header *pkg_header);
+struct i40e_profile_section_header *
+i40e_find_section_in_profile(u32 section_type,
+                            struct i40e_profile_segment *profile);
+enum i40e_status_code
+i40e_write_profile(struct i40e_hw *hw, struct i40e_profile_segment *i40e_seg,
+                  u32 track_id);
+enum i40e_status_code
+i40e_rollback_profile(struct i40e_hw *hw, struct i40e_profile_segment *i40e_seg,
+                     u32 track_id);
+enum i40e_status_code
+i40e_add_pinfo_to_list(struct i40e_hw *hw,
+                      struct i40e_profile_segment *profile,
+                      u8 *profile_info_sec, u32 track_id);
 #endif /* _I40E_PROTOTYPE_H_ */
similarity index 87%
rename from i40e-dkms/i40e-1.6.42/src/i40e_ptp.c
rename to i40e-dkms/i40e-2.1.26/src/i40e_ptp.c
index cc41fe0051088ee5e8fc18878438b6caee00ad96..2ed5cb10007176f26f3e29bc1324fe4a70ed6d0f 100644 (file)
@@ -173,14 +173,14 @@ static int i40e_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
 }
 
 /**
- * i40e_ptp_gettime64 - Get the time of the PHC
+ * i40e_ptp_gettime - Get the time of the PHC
  * @ptp: The PTP clock structure
  * @ts: timespec64 structure to hold the current time value
  *
  * Read the device clock and return the correct value on ns, after converting it
  * into a timespec struct.
  **/
-static int i40e_ptp_gettime64(struct ptp_clock_info *ptp, struct timespec64 *ts)
+static int i40e_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
 {
        struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps);
 
@@ -191,14 +191,14 @@ static int i40e_ptp_gettime64(struct ptp_clock_info *ptp, struct timespec64 *ts)
 }
 
 /**
- * i40e_ptp_settime64 - Set the time of the PHC
+ * i40e_ptp_settime - Set the time of the PHC
  * @ptp: The PTP clock structure
  * @ts: timespec64 structure that holds the new time value
  *
  * Set the device clock to the user input value. The conversion from timespec
  * to ns happens in the write function.
  **/
-static int i40e_ptp_settime64(struct ptp_clock_info *ptp,
+static int i40e_ptp_settime(struct ptp_clock_info *ptp,
                            const struct timespec64 *ts)
 {
        struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps);
@@ -211,19 +211,19 @@ static int i40e_ptp_settime64(struct ptp_clock_info *ptp,
 
 #ifndef HAVE_PTP_CLOCK_INFO_GETTIME64
 /**
- * i40e_ptp_gettime - Get the time of the PHC
+ * i40e_ptp_gettime32 - Get the time of the PHC
  * @ptp: The PTP clock structure
  * @ts: timespec structure to hold the current time value
  *
  * Read the device clock and return the correct value on ns, after converting it
  * into a timespec struct.
  **/
-static int i40e_ptp_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
+static int i40e_ptp_gettime32(struct ptp_clock_info *ptp, struct timespec *ts)
 {
        struct timespec64 ts64;
        int err;
 
-       err = i40e_ptp_gettime64(ptp, &ts64);
+       err = i40e_ptp_gettime(ptp, &ts64);
        if (err)
                return err;
 
@@ -232,19 +232,19 @@ static int i40e_ptp_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
 }
 
 /**
- * i40e_ptp_settime - Set the time of the PHC
+ * i40e_ptp_settime32 - Set the time of the PHC
  * @ptp: The PTP clock structure
  * @ts: timespec structure that holds the new time value
  *
  * Set the device clock to the user input value. The conversion from timespec
  * to ns happens in the write function.
  **/
-static int i40e_ptp_settime(struct ptp_clock_info *ptp,
-                           const struct timespec *ts)
+static int i40e_ptp_settime32(struct ptp_clock_info *ptp,
+                             const struct timespec *ts)
 {
        struct timespec64 ts64 = timespec_to_timespec64(*ts);
 
-       return i40e_ptp_settime64(ptp, &ts64);
+       return i40e_ptp_settime(ptp, &ts64);
 }
 #endif
 
@@ -306,18 +306,17 @@ static u32 i40e_ptp_get_rx_events(struct i40e_pf *pf)
 
 /**
  * i40e_ptp_rx_hang - Detect error case when Rx timestamp registers are hung
- * @vsi: The VSI with the rings relevant to 1588
+ * @pf: The PF private data structure
  *
  * This watchdog task is scheduled to detect error case where hardware has
  * dropped an Rx packet that was timestamped when the ring is full. The
  * particular error is rare but leaves the device in a state unable to timestamp
  * any future packets.
  **/
-void i40e_ptp_rx_hang(struct i40e_vsi *vsi)
+void i40e_ptp_rx_hang(struct i40e_pf *pf)
 {
-       struct i40e_pf *pf = vsi->back;
        struct i40e_hw *hw = &pf->hw;
-       int i;
+       unsigned int i, cleared = 0;
 
        /* Since we cannot turn off the Rx timestamp logic if the device is
         * configured for Tx timestamping, we check if Rx timestamping is
@@ -343,14 +342,55 @@ void i40e_ptp_rx_hang(struct i40e_vsi *vsi)
                    time_is_before_jiffies(pf->latch_events[i] + HZ)) {
                        rd32(hw, I40E_PRTTSYN_RXTIME_H(i));
                        pf->latch_event_flags &= ~BIT(i);
-                       pf->rx_hwtstamp_cleared++;
-                       dev_warn(&pf->pdev->dev,
-                                "Clearing a missed Rx timestamp event for RXTIME[%d]\n",
-                                i);
+                       cleared++;
                }
        }
 
        spin_unlock_bh(&pf->ptp_rx_lock);
+
+       /* Log a warning if more than 2 timestamps got dropped in the same
+        * check. We don't want to warn about all drops because it can occur
+        * in normal scenarios such as PTP frames on multicast addresses we
+        * aren't listening to. However, administrator should know if this is
+        * the reason packets aren't receiving timestamps.
+        */
+       if (cleared > 2)
+               dev_dbg(&pf->pdev->dev,
+                       "Dropped %d missed RXTIME timestamp events\n",
+                       cleared);
+
+       /* Finally, update the rx_hwtstamp_cleared counter */
+       pf->rx_hwtstamp_cleared += cleared;
+}
+
+/**
+ * i40e_ptp_tx_hang - Detect error case when Tx timestamp register is hung
+ * @pf: The PF private data structure
+ *
+ * This watchdog task is run periodically to make sure that we clear the Tx
+ * timestamp logic if we don't obtain a timestamp in a reasonable amount of
+ * time. It is unexpected in the normal case but if it occurs it results in
+ * permanently prevent timestamps of future packets
+ **/
+void i40e_ptp_tx_hang(struct i40e_pf *pf)
+{
+       if (!(pf->flags & I40E_FLAG_PTP) || !pf->ptp_tx)
+               return;
+
+       /* Nothing to do if we're not already waiting for a timestamp */
+       if (!test_bit(__I40E_PTP_TX_IN_PROGRESS, pf->state))
+               return;
+
+       /* We already have a handler routine which is run when we are notified
+        * of a Tx timestamp in the hardware. If we don't get an interrupt
+        * within a second it is reasonable to assume that we never will.
+        */
+       if (time_is_before_jiffies(pf->ptp_tx_start + HZ)) {
+               dev_kfree_skb_any(pf->ptp_tx_skb);
+               pf->ptp_tx_skb = NULL;
+               clear_bit_unlock(__I40E_PTP_TX_IN_PROGRESS, pf->state);
+               pf->tx_hwtstamp_timeouts++;
+       }
 }
 
 /**
@@ -364,6 +404,7 @@ void i40e_ptp_rx_hang(struct i40e_vsi *vsi)
 void i40e_ptp_tx_hwtstamp(struct i40e_pf *pf)
 {
        struct skb_shared_hwtstamps shhwtstamps;
+       struct sk_buff *skb = pf->ptp_tx_skb;
        struct i40e_hw *hw = &pf->hw;
        u32 hi, lo;
        u64 ns;
@@ -379,12 +420,19 @@ void i40e_ptp_tx_hwtstamp(struct i40e_pf *pf)
        hi = rd32(hw, I40E_PRTTSYN_TXTIME_H);
 
        ns = (((u64)hi) << 32) | lo;
-
        i40e_ptp_convert_to_hwtstamp(&shhwtstamps, ns);
-       skb_tstamp_tx(pf->ptp_tx_skb, &shhwtstamps);
-       dev_kfree_skb_any(pf->ptp_tx_skb);
+
+       /* Clear the bit lock as soon as possible after reading the register,
+        * and prior to notifying the stack via skb_tstamp_tx(). Otherwise
+        * applications might wake up and attempt to request another transmit
+        * timestamp prior to the bit lock being cleared.
+        */
        pf->ptp_tx_skb = NULL;
-       clear_bit_unlock(__I40E_PTP_TX_IN_PROGRESS, &pf->state);
+       clear_bit_unlock(__I40E_PTP_TX_IN_PROGRESS, pf->state);
+
+       /* Notify the stack and free the skb after we've unlocked */
+       skb_tstamp_tx(skb, &shhwtstamps);
+       dev_kfree_skb_any(skb);
 }
 
 /**
@@ -463,10 +511,17 @@ void i40e_ptp_set_increment(struct i40e_pf *pf)
                incval = I40E_PTP_1GB_INCVAL;
                break;
        case I40E_LINK_SPEED_100MB:
-               dev_warn(&pf->pdev->dev,
-                        "1588 functionality is not supported at 100 Mbps. Stopping the PHC.\n");
+       {
+               static int warn_once;
+
+               if (!warn_once) {
+                       dev_warn(&pf->pdev->dev,
+                                "1588 functionality is not supported at 100 Mbps. Stopping the PHC.\n");
+                       warn_once++;
+               }
                incval = 0;
                break;
+       }
        case I40E_LINK_SPEED_40GB:
        default:
                incval = I40E_PTP_40GB_INCVAL;
@@ -551,7 +606,7 @@ static int i40e_ptp_set_timestamp_mode(struct i40e_pf *pf,
        case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
        case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
        case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
-               if (!(pf->flags & I40E_FLAG_PTP_L4_CAPABLE))
+               if (!(pf->hw_features & I40E_HW_PTP_L4_CAPABLE))
                        return -ERANGE;
                pf->ptp_rx = true;
                tsyntype = I40E_PRTTSYN_CTL1_V1MESSTYPE0_MASK |
@@ -565,7 +620,7 @@ static int i40e_ptp_set_timestamp_mode(struct i40e_pf *pf,
        case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
        case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
        case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
-               if (!(pf->flags & I40E_FLAG_PTP_L4_CAPABLE))
+               if (!(pf->hw_features & I40E_HW_PTP_L4_CAPABLE))
                        return -ERANGE;
                /* fall through */
        case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
@@ -574,13 +629,16 @@ static int i40e_ptp_set_timestamp_mode(struct i40e_pf *pf,
                pf->ptp_rx = true;
                tsyntype = I40E_PRTTSYN_CTL1_V2MESSTYPE0_MASK |
                           I40E_PRTTSYN_CTL1_TSYNTYPE_V2;
-               if (pf->flags & I40E_FLAG_PTP_L4_CAPABLE) {
+               if (pf->hw_features & I40E_HW_PTP_L4_CAPABLE) {
                        tsyntype |= I40E_PRTTSYN_CTL1_UDP_ENA_MASK;
                        config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
                } else {
                        config->rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
                }
                break;
+#ifdef HAVE_HWTSTAMP_FILTER_NTP_ALL
+       case HWTSTAMP_FILTER_NTP_ALL:
+#endif /* HAVE_HWTSTAMP_FILTER_NTP_ALL */
        case HWTSTAMP_FILTER_ALL:
        default:
                return -ERANGE;
@@ -688,11 +746,11 @@ static long i40e_ptp_create_clock(struct i40e_pf *pf)
        pf->ptp_caps.adjfreq = i40e_ptp_adjfreq;
        pf->ptp_caps.adjtime = i40e_ptp_adjtime;
 #ifdef HAVE_PTP_CLOCK_INFO_GETTIME64
-       pf->ptp_caps.gettime64 = i40e_ptp_gettime64;
-       pf->ptp_caps.settime64 = i40e_ptp_settime64;
+       pf->ptp_caps.gettime64 = i40e_ptp_gettime;
+       pf->ptp_caps.settime64 = i40e_ptp_settime;
 #else
-       pf->ptp_caps.gettime = i40e_ptp_gettime;
-       pf->ptp_caps.settime = i40e_ptp_settime;
+       pf->ptp_caps.gettime = i40e_ptp_gettime32;
+       pf->ptp_caps.settime = i40e_ptp_settime32;
 #endif
        pf->ptp_caps.enable = i40e_ptp_feature_enable;
 
@@ -769,7 +827,7 @@ void i40e_ptp_init(struct i40e_pf *pf)
 
                /* Set the clock value. */
                ts = ktime_to_timespec64(ktime_get_real());
-               i40e_ptp_settime64(&pf->ptp_caps, &ts);
+               i40e_ptp_settime(&pf->ptp_caps, &ts);
        }
 }
 
@@ -789,7 +847,7 @@ void i40e_ptp_stop(struct i40e_pf *pf)
        if (pf->ptp_tx_skb) {
                dev_kfree_skb_any(pf->ptp_tx_skb);
                pf->ptp_tx_skb = NULL;
-               clear_bit_unlock(__I40E_PTP_TX_IN_PROGRESS, &pf->state);
+               clear_bit_unlock(__I40E_PTP_TX_IN_PROGRESS, pf->state);
        }
 
        if (pf->ptp_clock) {
similarity index 99%
rename from i40e-dkms/i40e-1.6.42/src/i40e_register.h
rename to i40e-dkms/i40e-2.1.26/src/i40e_register.h
index 81e0f7be430508884b0e0bd8b81d467aba28be26..0997c3e45576e0563300a87d27c9847f961fc83c 100644 (file)
 #define I40E_GLV_RUPP_MAX_INDEX 383
 #define I40E_GLV_RUPP_RUPP_SHIFT 0
 #define I40E_GLV_RUPP_RUPP_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_RUPP_RUPP_SHIFT)
-#define I40E_GLV_TEPC(_VSI) (0x00344000 + ((_VSI) * 4)) /* _i=0...383 */ /* Reset: CORER */
+#define I40E_GLV_TEPC(_i) (0x00344000 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_TEPC_MAX_INDEX 383
 #define I40E_GLV_TEPC_TEPC_SHIFT 0
 #define I40E_GLV_TEPC_TEPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_TEPC_TEPC_SHIFT)
diff --git a/i40e-dkms/i40e-2.1.26/src/i40e_trace.h b/i40e-dkms/i40e-2.1.26/src/i40e_trace.h
new file mode 100644 (file)
index 0000000..5ea346e
--- /dev/null
@@ -0,0 +1,249 @@
+/*******************************************************************************
+ *
+ * Intel(R) 40-10 Gigabit Ethernet Connection Network Driver
+ * Copyright(c) 2013 - 2017 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ ******************************************************************************/
+
+#ifndef CONFIG_TRACEPOINTS
+#if !defined(_I40E_TRACE_H_)
+#define _I40E_TRACE_H_
+/* If the Linux kernel tracepoints are not available then the i40e_trace*
+ * macros become nops.
+ */
+
+#define i40e_trace(trace_name, args...)
+#define i40e_trace_enabled(trace_name) (0)
+#endif /* !defined(_I40E_TRACE_H_) */
+#else /* CONFIG_TRACEPOINTS */
+/*
+ * Modeled on trace-events-sample.h
+ */
+
+/*
+ * The trace subsystem name for i40e will be "i40e".
+ *
+ * This file is named i40e_trace.h.
+ *
+ * Since this include file's name is different from the trace
+ * subsystem name, we'll have to define TRACE_INCLUDE_FILE at the end
+ * of this file.
+ */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM i40e
+
+/*
+ * See trace-events-sample.h for a detailed description of why this
+ * guard clause is different from most normal include files.
+ */
+#if !defined(_I40E_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
+#define _I40E_TRACE_H_
+
+#include <linux/tracepoint.h>
+
+/**
+ * i40e_trace() macro enables shared code to refer to trace points
+ * like:
+ *
+ * trace_i40e{,vf}_example(args...)
+ *
+ * ... as:
+ *
+ * i40e_trace(example, args...)
+ *
+ * ... to resolve to the PF or VF version of the tracepoint without
+ * ifdefs, and to allow tracepoints to be disabled entirely at build
+ * time.
+ *
+ * Trace point should always be referred to in the driver via this
+ * macro.
+ *
+ * Similarly, i40e_trace_enabled(trace_name) wraps references to
+ * trace_i40e{,vf}_<trace_name>_enabled() functions.
+ */
+#define _I40E_TRACE_NAME(trace_name) (trace_ ## i40e ## _ ## trace_name)
+#define I40E_TRACE_NAME(trace_name) _I40E_TRACE_NAME(trace_name)
+
+#define i40e_trace(trace_name, args...) I40E_TRACE_NAME(trace_name)(args)
+
+#define i40e_trace_enabled(trace_name) I40E_TRACE_NAME(trace_name##_enabled)()
+
+/*
+ * Events common to PF and VF. Corresponding versions will be defined
+ * for both, named trace_i40e_* and trace_i40evf_*. The i40e_trace()
+ * macro above will select the right trace point name for the driver
+ * being built from shared code.
+ */
+
+/* Events related to a vsi & ring */
+DECLARE_EVENT_CLASS(
+       i40e_tx_template,
+
+       TP_PROTO(struct i40e_ring *ring,
+                struct i40e_tx_desc *desc,
+                struct i40e_tx_buffer *buf),
+
+       TP_ARGS(ring, desc, buf),
+
+       /*
+        * The convention here is to make the first fields in the
+        * TP_STRUCT match the TP_PROTO exactly. This enables the use
+        * of the args struct generated by the tplist tool (from the
+        * bcc-tools package) to be used for those fields. To access
+        * fields other than the tracepoint args will require the
+        * tplist output to be adjusted.
+        */
+       TP_STRUCT__entry(
+               __field(void*, ring)
+               __field(void*, desc)
+               __field(void*, buf)
+               __string(devname, ring->netdev->name)
+       ),
+
+       TP_fast_assign(
+               __entry->ring = ring;
+               __entry->desc = desc;
+               __entry->buf = buf;
+               __assign_str(devname, ring->netdev->name);
+       ),
+
+       TP_printk(
+               "netdev: %s ring: %p desc: %p buf %p",
+               __get_str(devname), __entry->ring,
+               __entry->desc, __entry->buf)
+);
+
+DEFINE_EVENT(
+       i40e_tx_template, i40e_clean_tx_irq,
+       TP_PROTO(struct i40e_ring *ring,
+                struct i40e_tx_desc *desc,
+                struct i40e_tx_buffer *buf),
+
+       TP_ARGS(ring, desc, buf));
+
+DEFINE_EVENT(
+       i40e_tx_template, i40e_clean_tx_irq_unmap,
+       TP_PROTO(struct i40e_ring *ring,
+                struct i40e_tx_desc *desc,
+                struct i40e_tx_buffer *buf),
+
+       TP_ARGS(ring, desc, buf));
+
+DECLARE_EVENT_CLASS(
+       i40e_rx_template,
+
+       TP_PROTO(struct i40e_ring *ring,
+                union i40e_32byte_rx_desc *desc,
+                struct sk_buff *skb),
+
+       TP_ARGS(ring, desc, skb),
+
+       TP_STRUCT__entry(
+               __field(void*, ring)
+               __field(void*, desc)
+               __field(void*, skb)
+               __string(devname, ring->netdev->name)
+       ),
+
+       TP_fast_assign(
+               __entry->ring = ring;
+               __entry->desc = desc;
+               __entry->skb = skb;
+               __assign_str(devname, ring->netdev->name);
+       ),
+
+       TP_printk(
+               "netdev: %s ring: %p desc: %p skb %p",
+               __get_str(devname), __entry->ring,
+               __entry->desc, __entry->skb)
+);
+
+DEFINE_EVENT(
+       i40e_rx_template, i40e_clean_rx_irq,
+       TP_PROTO(struct i40e_ring *ring,
+                union i40e_32byte_rx_desc *desc,
+                struct sk_buff *skb),
+
+       TP_ARGS(ring, desc, skb));
+
+DEFINE_EVENT(
+       i40e_rx_template, i40e_clean_rx_irq_rx,
+       TP_PROTO(struct i40e_ring *ring,
+                union i40e_32byte_rx_desc *desc,
+                struct sk_buff *skb),
+
+       TP_ARGS(ring, desc, skb));
+
+DECLARE_EVENT_CLASS(
+       i40e_xmit_template,
+
+       TP_PROTO(struct sk_buff *skb,
+                struct i40e_ring *ring),
+
+       TP_ARGS(skb, ring),
+
+       TP_STRUCT__entry(
+               __field(void*, skb)
+               __field(void*, ring)
+               __string(devname, ring->netdev->name)
+       ),
+
+       TP_fast_assign(
+               __entry->skb = skb;
+               __entry->ring = ring;
+               __assign_str(devname, ring->netdev->name);
+       ),
+
+       TP_printk(
+               "netdev: %s skb: %p ring: %p",
+               __get_str(devname), __entry->skb,
+               __entry->ring)
+);
+
+DEFINE_EVENT(
+       i40e_xmit_template, i40e_xmit_frame_ring,
+       TP_PROTO(struct sk_buff *skb,
+                struct i40e_ring *ring),
+
+       TP_ARGS(skb, ring));
+
+DEFINE_EVENT(
+       i40e_xmit_template, i40e_xmit_frame_ring_drop,
+       TP_PROTO(struct sk_buff *skb,
+                struct i40e_ring *ring),
+
+       TP_ARGS(skb, ring));
+
+/*
+ * Events unique to the PF.
+ */
+
+#endif /* _I40E_TRACE_H_ */
+/* This must be outside ifdef _I40E_TRACE_H */
+
+/* This trace include file is not located in the .../include/trace
+ * with the kernel tracepoint definitions, because we're a loadable
+ * module.
+ */
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE i40e_trace
+#include <trace/define_trace.h>
+#endif /* CONFIG_TRACEPOINTS */
similarity index 78%
rename from i40e-dkms/i40e-1.6.42/src/i40e_txrx.c
rename to i40e-dkms/i40e-2.1.26/src/i40e_txrx.c
index cd379990619370d746966c46b1824b786a9790a5..cbd49a9adcf3f0a2e0443aa367ee4d196d5f1d52 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <linux/prefetch.h>
 #include "i40e.h"
+#include "i40e_trace.h"
 #include "i40e_prototype.h"
 
 static inline __le64 build_ctob(u32 td_cmd, u32 td_offset, unsigned int size,
@@ -61,12 +62,12 @@ static void i40e_fdir(struct i40e_ring *tx_ring,
        flex_ptype = I40E_TXD_FLTR_QW0_QINDEX_MASK &
                     (fdata->q_index << I40E_TXD_FLTR_QW0_QINDEX_SHIFT);
 
-       flex_ptype |= I40E_TXD_FLTR_QW0_FLEXOFF_MASK &
-                     (fdata->flex_off << I40E_TXD_FLTR_QW0_FLEXOFF_SHIFT);
-
        flex_ptype |= I40E_TXD_FLTR_QW0_PCTYPE_MASK &
                      (fdata->pctype << I40E_TXD_FLTR_QW0_PCTYPE_SHIFT);
 
+       flex_ptype |= I40E_TXD_FLTR_QW0_PCTYPE_MASK &
+                     (fdata->flex_offset << I40E_TXD_FLTR_QW0_FLEXOFF_SHIFT);
+
        /* Use LAN VSI Id if not programmed by user */
        flex_ptype |= I40E_TXD_FLTR_QW0_DEST_VSI_MASK &
                      ((u32)(fdata->dest_vsi ? : pf->vsi[pf->lan_vsi]->id) <<
@@ -199,7 +200,6 @@ static int i40e_add_del_fdir_udpv4(struct i40e_vsi *vsi,
        struct i40e_pf *pf = vsi->back;
        struct udphdr *udp;
        struct iphdr *ip;
-       bool err = false;
        u8 *raw_packet;
        int ret;
        static char packet[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0,
@@ -215,18 +215,17 @@ static int i40e_add_del_fdir_udpv4(struct i40e_vsi *vsi,
        udp = (struct udphdr *)(raw_packet + IP_HEADER_OFFSET
              + sizeof(struct iphdr));
 
-       ip->daddr = fd_data->dst_ip[0];
+       ip->daddr = fd_data->dst_ip;
        udp->dest = fd_data->dst_port;
-       ip->saddr = fd_data->src_ip[0];
+       ip->saddr = fd_data->src_ip;
        udp->source = fd_data->src_port;
 
-       /* For now, supports only word as flex payload */
-       if (i40e_is_flex_filter(fd_data)) {
-               u16 off, pattern;
+       if (fd_data->flex_filter) {
+               u8 *payload = raw_packet + I40E_UDPIP_DUMMY_PACKET_LEN;
+               __be16 pattern = fd_data->flex_word;
+               u16 off = fd_data->flex_offset;
 
-               off = ~(be16_to_cpu(fd_data->flex_mask[3]));
-               pattern = be16_to_cpu(fd_data->flex_bytes[3]);
-               *((u16 *)(raw_packet + off)) = pattern;
+               *((__force __be16 *)(payload + off)) = pattern;
        }
 
        fd_data->pctype = I40E_FILTER_PCTYPE_NONF_IPV4_UDP;
@@ -235,7 +234,9 @@ static int i40e_add_del_fdir_udpv4(struct i40e_vsi *vsi,
                dev_info(&pf->pdev->dev,
                         "PCTYPE:%d, Filter command send failed for fd_id:%d (ret = %d)\n",
                         fd_data->pctype, fd_data->fd_id, ret);
-               err = true;
+               /* Free the packet buffer since it wasn't added to the ring */
+               kfree(raw_packet);
+               return -EOPNOTSUPP;
        } else if (I40E_DEBUG_FD & pf->hw.debug_mask) {
                if (add)
                        dev_info(&pf->pdev->dev,
@@ -246,21 +247,13 @@ static int i40e_add_del_fdir_udpv4(struct i40e_vsi *vsi,
                                 "Filter deleted for PCTYPE %d loc = %d\n",
                                 fd_data->pctype, fd_data->fd_id);
        }
-       if (err) {
-               kfree(raw_packet);
-       } else {
-               if (add) {
-                       pf->fd_udp4_filter_cnt++;
-                       if (i40e_is_flex_filter(fd_data))
-                               pf->fd_flex_filter_cnt++;
-               } else {
-                       pf->fd_udp4_filter_cnt--;
-                       if (i40e_is_flex_filter(fd_data))
-                               pf->fd_flex_filter_cnt--;
-               }
-       }
 
-       return err ? -EOPNOTSUPP : 0;
+       if (add)
+               pf->fd_udp4_filter_cnt++;
+       else
+               pf->fd_udp4_filter_cnt--;
+
+       return 0;
 }
 
 /**
@@ -278,7 +271,6 @@ static int i40e_add_del_fdir_tcpv4(struct i40e_vsi *vsi,
        struct i40e_pf *pf = vsi->back;
        struct tcphdr *tcp;
        struct iphdr *ip;
-       bool err = false;
        u8 *raw_packet;
        int ret;
        /* Dummy packet */
@@ -296,48 +288,109 @@ static int i40e_add_del_fdir_tcpv4(struct i40e_vsi *vsi,
        tcp = (struct tcphdr *)(raw_packet + IP_HEADER_OFFSET
              + sizeof(struct iphdr));
 
-       ip->daddr = fd_data->dst_ip[0];
+       ip->daddr = fd_data->dst_ip;
        tcp->dest = fd_data->dst_port;
-       ip->saddr = fd_data->src_ip[0];
+       ip->saddr = fd_data->src_ip;
        tcp->source = fd_data->src_port;
 
-       /* For now, supports only word as flex payload */
-       if (i40e_is_flex_filter(fd_data)) {
-               u16 off, pattern;
+       if (fd_data->flex_filter) {
+               u8 *payload = raw_packet + I40E_TCPIP_DUMMY_PACKET_LEN;
+               __be16 pattern = fd_data->flex_word;
+               u16 off = fd_data->flex_offset;
 
-               off = ~(be16_to_cpu(fd_data->flex_mask[3]));
-               pattern = be16_to_cpu(fd_data->flex_bytes[3]);
-               *((u16 *)(raw_packet + off)) = pattern;
+               *((__force __be16 *)(payload + off)) = pattern;
+       }
+
+       fd_data->pctype = I40E_FILTER_PCTYPE_NONF_IPV4_TCP;
+       ret = i40e_program_fdir_filter(fd_data, raw_packet, pf, add);
+       if (ret) {
+               dev_info(&pf->pdev->dev,
+                        "PCTYPE:%d, Filter command send failed for fd_id:%d (ret = %d)\n",
+                        fd_data->pctype, fd_data->fd_id, ret);
+               /* Free the packet buffer since it wasn't added to the ring */
+               kfree(raw_packet);
+               return -EOPNOTSUPP;
+       } else if (I40E_DEBUG_FD & pf->hw.debug_mask) {
+               if (add)
+                       dev_info(&pf->pdev->dev, "Filter OK for PCTYPE %d loc = %d)\n",
+                                fd_data->pctype, fd_data->fd_id);
+               else
+                       dev_info(&pf->pdev->dev,
+                                "Filter deleted for PCTYPE %d loc = %d\n",
+                                fd_data->pctype, fd_data->fd_id);
        }
 
        if (add) {
-               pf->fd_tcp_rule++;
+               pf->fd_tcp4_filter_cnt++;
                if ((pf->flags & I40E_FLAG_FD_ATR_ENABLED) &&
                    I40E_DEBUG_FD & pf->hw.debug_mask)
                        dev_info(&pf->pdev->dev, "Forcing ATR off, sideband rules for TCP/IPv4 flow being applied\n");
-               pf->hw_disabled_flags |= I40E_FLAG_FD_ATR_ENABLED;
+               pf->flags |= I40E_FLAG_FD_ATR_AUTO_DISABLED;
        } else {
-               pf->fd_tcp_rule = (pf->fd_tcp_rule > 0) ?
-                                 (pf->fd_tcp_rule - 1) : 0;
-               if (pf->fd_tcp_rule == 0) {
-                       if ((pf->flags & I40E_FLAG_FD_ATR_ENABLED) &&
-                           I40E_DEBUG_FD & pf->hw.debug_mask)
-                               dev_info(&pf->pdev->dev, "ATR re-enabled due to no sideband TCP/IPv4 rules\n");
-                       pf->hw_disabled_flags &= ~I40E_FLAG_FD_ATR_ENABLED;
-               }
+               pf->fd_tcp4_filter_cnt--;
        }
 
-       fd_data->pctype = I40E_FILTER_PCTYPE_NONF_IPV4_TCP;
-       ret = i40e_program_fdir_filter(fd_data, raw_packet, pf, add);
+       return 0;
+}
+
+/**
+ * i40e_add_del_fdir_sctpv4 - Add/Remove SCTPv4 Flow Director filters for
+ * a specific flow spec
+ * @vsi: pointer to the targeted VSI
+ * @fd_data: the flow director data required for the FDir descriptor
+ * @add: true adds a filter, false removes it
+ *
+ * Returns 0 if the filters were successfully added or removed
+ **/
+static int i40e_add_del_fdir_sctpv4(struct i40e_vsi *vsi,
+                                   struct i40e_fdir_filter *fd_data,
+                                   bool add)
+{
+       struct i40e_pf *pf = vsi->back;
+       struct sctphdr *sctp;
+       struct iphdr *ip;
+       u8 *raw_packet;
+       int ret;
+       /* Dummy packet */
+       static char packet[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0,
+               0x45, 0, 0, 0x20, 0, 0, 0x40, 0, 0x40, 0x84, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 
+       raw_packet = kzalloc(I40E_FDIR_MAX_RAW_PACKET_SIZE, GFP_KERNEL);
+       if (!raw_packet)
+               return -ENOMEM;
+       memcpy(raw_packet, packet, I40E_SCTPIP_DUMMY_PACKET_LEN);
+
+       ip = (struct iphdr *)(raw_packet + IP_HEADER_OFFSET);
+       sctp = (struct sctphdr *)(raw_packet + IP_HEADER_OFFSET
+             + sizeof(struct iphdr));
+
+       ip->daddr = fd_data->dst_ip;
+       sctp->dest = fd_data->dst_port;
+       ip->saddr = fd_data->src_ip;
+       sctp->source = fd_data->src_port;
+
+       if (fd_data->flex_filter) {
+               u8 *payload = raw_packet + I40E_SCTPIP_DUMMY_PACKET_LEN;
+               __be16 pattern = fd_data->flex_word;
+               u16 off = fd_data->flex_offset;
+
+               *((__force __be16 *)(payload + off)) = pattern;
+       }
+
+       fd_data->pctype = I40E_FILTER_PCTYPE_NONF_IPV4_SCTP;
+       ret = i40e_program_fdir_filter(fd_data, raw_packet, pf, add);
        if (ret) {
                dev_info(&pf->pdev->dev,
                         "PCTYPE:%d, Filter command send failed for fd_id:%d (ret = %d)\n",
                         fd_data->pctype, fd_data->fd_id, ret);
-               err = true;
+               /* Free the packet buffer since it wasn't added to the ring */
+               kfree(raw_packet);
+               return -EOPNOTSUPP;
        } else if (I40E_DEBUG_FD & pf->hw.debug_mask) {
                if (add)
-                       dev_info(&pf->pdev->dev, "Filter OK for PCTYPE %d loc = %d)\n",
+                       dev_info(&pf->pdev->dev,
+                                "Filter OK for PCTYPE %d loc = %d\n",
                                 fd_data->pctype, fd_data->fd_id);
                else
                        dev_info(&pf->pdev->dev,
@@ -345,21 +398,12 @@ static int i40e_add_del_fdir_tcpv4(struct i40e_vsi *vsi,
                                 fd_data->pctype, fd_data->fd_id);
        }
 
-       if (err) {
-               kfree(raw_packet);
-       } else {
-               if (add) {
-                       pf->fd_tcp4_filter_cnt++;
-                       if (i40e_is_flex_filter(fd_data))
-                               pf->fd_flex_filter_cnt++;
-               } else {
-                       pf->fd_tcp4_filter_cnt--;
-                       if (i40e_is_flex_filter(fd_data))
-                               pf->fd_flex_filter_cnt--;
-               }
-       }
+       if (add)
+               pf->fd_sctp4_filter_cnt++;
+       else
+               pf->fd_sctp4_filter_cnt--;
 
-       return err ? -EOPNOTSUPP : 0;
+       return 0;
 }
 
 /**
@@ -377,7 +421,6 @@ static int i40e_add_del_fdir_ipv4(struct i40e_vsi *vsi,
 {
        struct i40e_pf *pf = vsi->back;
        struct iphdr *ip;
-       bool err = false;
        u8 *raw_packet;
        int ret;
        int i;
@@ -393,27 +436,26 @@ static int i40e_add_del_fdir_ipv4(struct i40e_vsi *vsi,
                memcpy(raw_packet, packet, I40E_IP_DUMMY_PACKET_LEN);
                ip = (struct iphdr *)(raw_packet + IP_HEADER_OFFSET);
 
-               ip->saddr = fd_data->src_ip[0];
-               ip->daddr = fd_data->dst_ip[0];
+               ip->saddr = fd_data->src_ip;
+               ip->daddr = fd_data->dst_ip;
                ip->protocol = 0;
 
-               /* For now, supports only word as flex payload */
-               if (i40e_is_flex_filter(fd_data)) {
-                       u16 off, pattern;
+               if (fd_data->flex_filter) {
+                       u8 *payload = raw_packet + I40E_IP_DUMMY_PACKET_LEN;
+                       __be16 pattern = fd_data->flex_word;
+                       u16 off = fd_data->flex_offset;
 
-                       off = ~(be16_to_cpu(fd_data->flex_mask[3]));
-                       pattern = be16_to_cpu(fd_data->flex_bytes[3]);
-                       *((u16 *)(raw_packet + off)) = pattern;
+                       *((__force __be16 *)(payload + off)) = pattern;
                }
 
                fd_data->pctype = i;
                ret = i40e_program_fdir_filter(fd_data, raw_packet, pf, add);
-
                if (ret) {
                        dev_info(&pf->pdev->dev,
                                 "PCTYPE:%d, Filter command send failed for fd_id:%d (ret = %d)\n",
                                 fd_data->pctype, fd_data->fd_id, ret);
-                       err = true;
+                       kfree(raw_packet);
+                       return -EOPNOTSUPP;
                } else if (I40E_DEBUG_FD & pf->hw.debug_mask) {
                        if (add)
                                dev_info(&pf->pdev->dev,
@@ -426,21 +468,12 @@ static int i40e_add_del_fdir_ipv4(struct i40e_vsi *vsi,
                }
        }
 
-       if (err) {
-               kfree(raw_packet);
-       } else {
-               if (add) {
-                       pf->fd_ip4_filter_cnt++;
-                       if (fd_data->flex_bytes[3] && fd_data->flex_mask[3])
-                               pf->fd_flex_filter_cnt++;
-               } else {
-                       pf->fd_ip4_filter_cnt--;
-                       if (fd_data->flex_bytes[3] && fd_data->flex_mask[3])
-                               pf->fd_flex_filter_cnt--;
-               }
-       }
+       if (add)
+               pf->fd_ip4_filter_cnt++;
+       else
+               pf->fd_ip4_filter_cnt--;
 
-       return err ? -EOPNOTSUPP : 0;
+       return 0;
 }
 
 /**
@@ -463,6 +496,9 @@ int i40e_add_del_fdir(struct i40e_vsi *vsi,
        case UDP_V4_FLOW:
                ret = i40e_add_del_fdir_udpv4(vsi, input, add);
                break;
+       case SCTP_V4_FLOW:
+               ret = i40e_add_del_fdir_sctpv4(vsi, input, add);
+               break;
        case IP_USER_FLOW:
                switch (input->ip4_proto) {
                case IPPROTO_TCP:
@@ -471,22 +507,31 @@ int i40e_add_del_fdir(struct i40e_vsi *vsi,
                case IPPROTO_UDP:
                        ret = i40e_add_del_fdir_udpv4(vsi, input, add);
                        break;
+               case IPPROTO_SCTP:
+                       ret = i40e_add_del_fdir_sctpv4(vsi, input, add);
+                       break;
                case IPPROTO_IP:
                        ret = i40e_add_del_fdir_ipv4(vsi, input, add);
                        break;
                default:
                        /* We cannot support masking based on protocol */
-                       goto unsupported_flow;
+                       dev_info(&pf->pdev->dev, "Unsupported IPv4 protocol 0x%02x\n",
+                                input->ip4_proto);
+                       return -EINVAL;
                }
                break;
        default:
-unsupported_flow:
-               dev_info(&pf->pdev->dev, "Could not specify spec type %d\n",
+               dev_info(&pf->pdev->dev, "Unsupported flow type 0x%02x\n",
                         input->flow_type);
-               ret = -EINVAL;
+               return -EINVAL;
        }
 
-       /* The buffer allocated here is freed by the i40e_clean_tx_ring() */
+       /* The buffer allocated here will be normally be freed by
+        * i40e_clean_fdir_tx_irq() as it reclaims resources after transmit
+        * completion. In the event of an error adding the buffer to the FDIR
+        * ring, it will immediately be freed. It may also be freed by
+        * i40e_clean_tx_ring() when closing the VSI.
+        */
        return ret;
 }
 
@@ -525,7 +570,7 @@ static void i40e_fd_handle_status(struct i40e_ring *rx_ring,
                 * progress do nothing, once flush is complete the state will
                 * be cleared.
                 */
-               if (test_bit(__I40E_FD_FLUSH_REQUESTED, &pf->state))
+               if (test_bit(__I40E_FD_FLUSH_REQUESTED, pf->state))
                        return;
 
                pf->fd_add_err++;
@@ -533,9 +578,9 @@ static void i40e_fd_handle_status(struct i40e_ring *rx_ring,
                pf->fd_atr_cnt = i40e_get_current_atr_cnt(pf);
 
                if ((rx_desc->wb.qword0.hi_dword.fd_id == 0) &&
-                   (pf->hw_disabled_flags & I40E_FLAG_FD_SB_ENABLED)) {
-                       pf->hw_disabled_flags |= I40E_FLAG_FD_ATR_ENABLED;
-                       set_bit(__I40E_FD_FLUSH_REQUESTED, &pf->state);
+                   pf->flags & I40E_FLAG_FD_SB_AUTO_DISABLED) {
+                       pf->flags |= I40E_FLAG_FD_ATR_AUTO_DISABLED;
+                       set_bit(__I40E_FD_FLUSH_REQUESTED, pf->state);
                }
 
                /* filter programming failed most likely due to table full */
@@ -547,12 +592,10 @@ static void i40e_fd_handle_status(struct i40e_ring *rx_ring,
                 */
                if (fcnt_prog >= (fcnt_avail - I40E_FDIR_BUFFER_FULL_MARGIN)) {
                        if ((pf->flags & I40E_FLAG_FD_SB_ENABLED) &&
-                           !(pf->hw_disabled_flags &
-                                    I40E_FLAG_FD_SB_ENABLED)) {
+                           !(pf->flags & I40E_FLAG_FD_SB_AUTO_DISABLED)) {
+                               pf->flags |= I40E_FLAG_FD_SB_AUTO_DISABLED;
                                if (I40E_DEBUG_FD & pf->hw.debug_mask)
                                        dev_warn(&pdev->dev, "FD filter space full, new ntuple rules will not be added\n");
-                               pf->hw_disabled_flags |=
-                                                       I40E_FLAG_FD_SB_ENABLED;
                        }
                }
        } else if (error == BIT(I40E_RX_PROG_STATUS_DESC_NO_FD_ENTRY_SHIFT)) {
@@ -648,19 +691,15 @@ void i40e_free_tx_resources(struct i40e_ring *tx_ring)
 /**
  * i40e_get_tx_pending - how many tx descriptors not processed
  * @tx_ring: the ring of descriptors
- * @in_sw: is tx_pending being checked in SW or HW
  *
  * Since there is no access to the ring head register
  * in XL710, we need to use our local copies
  **/
-u32 i40e_get_tx_pending(struct i40e_ring *ring, bool in_sw)
+u32 i40e_get_tx_pending(struct i40e_ring *ring)
 {
        u32 head, tail;
 
-       if (!in_sw)
-               head = i40e_get_head(ring);
-       else
-               head = ring->next_to_clean;
+       head = i40e_get_head(ring);
        tail = readl(ring->tail);
 
        if (head != tail)
@@ -706,6 +745,7 @@ static bool i40e_clean_tx_irq(struct i40e_vsi *vsi,
                /* prevent any other reads prior to eop_desc */
                read_barrier_depends();
 
+               i40e_trace(clean_tx_irq, tx_ring, tx_desc, tx_buf);
                /* we have caught up to head, no work left to do */
                if (tx_head == tx_desc)
                        break;
@@ -732,6 +772,8 @@ static bool i40e_clean_tx_irq(struct i40e_vsi *vsi,
 
                /* unmap remaining buffers */
                while (tx_desc != eop_desc) {
+                       i40e_trace(clean_tx_irq_unmap,
+                                  tx_ring, tx_desc, tx_buf);
 
                        tx_buf++;
                        tx_desc++;
@@ -783,11 +825,11 @@ static bool i40e_clean_tx_irq(struct i40e_vsi *vsi,
                 * them to be written back in case we stay in NAPI.
                 * In this mode on X722 we do not enable Interrupt.
                 */
-               unsigned int j = i40e_get_tx_pending(tx_ring, false);
+               unsigned int j = i40e_get_tx_pending(tx_ring);
 
                if (budget &&
                    ((j / WB_STRIDE) == 0) && (j > 0) &&
-                   !test_bit(__I40E_DOWN, &vsi->state) &&
+                   !test_bit(__I40E_VSI_DOWN, vsi->state) &&
                    (I40E_DESC_UNUSED(tx_ring) != tx_ring->count))
                        tx_ring->arm_wb = true;
        }
@@ -805,7 +847,7 @@ static bool i40e_clean_tx_irq(struct i40e_vsi *vsi,
                smp_mb();
                if (__netif_subqueue_stopped(tx_ring->netdev,
                                             tx_ring->queue_index) &&
-                  !test_bit(__I40E_DOWN, &vsi->state)) {
+                  !test_bit(__I40E_VSI_DOWN, vsi->state)) {
                        netif_wake_subqueue(tx_ring->netdev,
                                            tx_ring->queue_index);
                        ++tx_ring->tx_stats.restart_queue;
@@ -895,19 +937,31 @@ void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector)
 static bool i40e_set_new_dynamic_itr(struct i40e_ring_container *rc)
 {
        enum i40e_latency_range new_latency_range = rc->latency_range;
-       struct i40e_q_vector *qv = rc->ring->q_vector;
        u32 new_itr = rc->itr;
-       int bytes_per_int;
-       int usecs;
+       int bytes_per_usec;
+       unsigned int usecs, estimated_usecs;
 
        if (rc->total_packets == 0 || !rc->itr)
                return false;
 
+       usecs = (rc->itr << 1) * ITR_COUNTDOWN_START;
+       bytes_per_usec = rc->total_bytes / usecs;
+
+       /* The calculations in this algorithm depend on interrupts actually
+        * firing at the ITR rate. This may not happen if the packet rate is
+        * really low, or if we've been napi polling. Check to make sure
+        * that's not the case before we continue.
+        */
+       estimated_usecs = jiffies_to_usecs(jiffies - rc->last_itr_update);
+       if (estimated_usecs > usecs) {
+               new_latency_range = I40E_LOW_LATENCY;
+               goto reset_latency;
+       }
+
        /* simple throttlerate management
         *   0-10MB/s   lowest (50000 ints/s)
         *  10-20MB/s   low    (20000 ints/s)
         *  20-1249MB/s bulk   (18000 ints/s)
-        *  > 40000 Rx packets per second (8000 ints/s)
         *
         * The math works out because the divisor is in 10^(-6) which
         * turns the bytes/us input value into MB/s values, but
@@ -915,39 +969,25 @@ static bool i40e_set_new_dynamic_itr(struct i40e_ring_container *rc)
         * are in 2 usec increments in the ITR registers, and make sure
         * to use the smoothed values that the countdown timer gives us.
         */
-       usecs = (rc->itr << 1) * ITR_COUNTDOWN_START;
-       bytes_per_int = rc->total_bytes / usecs;
-
        switch (new_latency_range) {
        case I40E_LOWEST_LATENCY:
-               if (bytes_per_int > 10)
+               if (bytes_per_usec > 10)
                        new_latency_range = I40E_LOW_LATENCY;
                break;
        case I40E_LOW_LATENCY:
-               if (bytes_per_int > 20)
+               if (bytes_per_usec > 20)
                        new_latency_range = I40E_BULK_LATENCY;
-               else if (bytes_per_int <= 10)
+               else if (bytes_per_usec <= 10)
                        new_latency_range = I40E_LOWEST_LATENCY;
                break;
        case I40E_BULK_LATENCY:
-       case I40E_ULTRA_LATENCY:
        default:
-               if (bytes_per_int <= 20)
+               if (bytes_per_usec <= 20)
                        new_latency_range = I40E_LOW_LATENCY;
                break;
        }
 
-       /* this is to adjust RX more aggressively when streaming small
-        * packets.  The value of 40000 was picked as it is just beyond
-        * what the hardware can receive per second if in low latency
-        * mode.
-        */
-#define RX_ULTRA_PACKET_RATE 40000
-
-       if ((((rc->total_packets * 1000000) / usecs) > RX_ULTRA_PACKET_RATE) &&
-           (&qv->rx == rc))
-               new_latency_range = I40E_ULTRA_LATENCY;
-
+reset_latency:
        rc->latency_range = new_latency_range;
 
        switch (new_latency_range) {
@@ -960,28 +1000,45 @@ static bool i40e_set_new_dynamic_itr(struct i40e_ring_container *rc)
        case I40E_BULK_LATENCY:
                new_itr = I40E_ITR_18K;
                break;
-       case I40E_ULTRA_LATENCY:
-               new_itr = I40E_ITR_8K;
-               break;
        default:
                break;
        }
 
        rc->total_bytes = 0;
        rc->total_packets = 0;
+       rc->last_itr_update = jiffies;
 
        if (new_itr != rc->itr) {
                rc->itr = new_itr;
                return true;
        }
-
        return false;
 }
 
+/**
+ * i40e_rx_is_programming_status - check for programming status descriptor
+ * @qw: qword representing status_error_len in CPU ordering
+ *
+ * The value of in the descriptor length field indicate if this
+ * is a programming status descriptor for flow director or FCoE
+ * by the value of I40E_RX_PROG_STATUS_DESC_LENGTH, otherwise
+ * it is a packet descriptor.
+ **/
+static inline bool i40e_rx_is_programming_status(u64 qw)
+{
+       /* The Rx filter programming status and SPH bit occupy the same
+        * spot in the descriptor. Since we don't support packet split we
+        * can just reuse the bit as an indication that this is a
+        * programming status descriptor.
+        */
+       return qw & I40E_RXD_QW1_LENGTH_SPH_MASK;
+}
+
 /**
  * i40e_clean_programming_status - clean the programming status descriptor
  * @rx_ring: the rx ring that has this descriptor
  * @rx_desc: the rx descriptor written back by HW
+ * @qw: qword representing status_error_len in CPU ordering
  *
  * Flow director should handle FD_FILTER_STATUS to check its filter programming
  * status being successful or not and take actions accordingly. FCoE should
@@ -989,22 +1046,23 @@ static bool i40e_set_new_dynamic_itr(struct i40e_ring_container *rc)
  *
  **/
 static void i40e_clean_programming_status(struct i40e_ring *rx_ring,
-                                         union i40e_rx_desc *rx_desc)
+                                         union i40e_rx_desc *rx_desc,
+                                         u64 qw)
 {
-       u64 qw;
+       u32 ntc = rx_ring->next_to_clean + 1;
        u8 id;
 
-       qw = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
+       /* fetch, update, and store next to clean */
+       ntc = (ntc < rx_ring->count) ? ntc : 0;
+       rx_ring->next_to_clean = ntc;
+
+       prefetch(I40E_RX_DESC(rx_ring, ntc));
+
        id = (qw & I40E_RX_PROG_STATUS_DESC_QW1_PROGID_MASK) >>
                  I40E_RX_PROG_STATUS_DESC_QW1_PROGID_SHIFT;
 
        if (id == I40E_RX_PROG_STATUS_DESC_FD_FILTER_STATUS)
                i40e_fd_handle_status(rx_ring, rx_desc, id);
-#ifdef I40E_FCOE
-       else if ((id == I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_PROG_STATUS) ||
-                (id == I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_INVL_STATUS))
-               i40e_fcoe_handle_status(rx_ring, rx_desc, id);
-#endif
 }
 
 /**
@@ -1059,7 +1117,6 @@ err:
  **/
 void i40e_clean_rx_ring(struct i40e_ring *rx_ring)
 {
-       struct device *dev = rx_ring->dev;
        unsigned long bi_size;
        u16 i;
 
@@ -1067,22 +1124,47 @@ void i40e_clean_rx_ring(struct i40e_ring *rx_ring)
        if (!rx_ring->rx_bi)
                return;
 
+       if (rx_ring->skb) {
+               dev_kfree_skb(rx_ring->skb);
+               rx_ring->skb = NULL;
+       }
+
        /* Free all the Rx ring sk_buffs */
        for (i = 0; i < rx_ring->count; i++) {
                struct i40e_rx_buffer *rx_bi = &rx_ring->rx_bi[i];
 
-               if (rx_bi->skb) {
-                       dev_kfree_skb(rx_bi->skb);
-                       rx_bi->skb = NULL;
-               }
+#ifdef CONFIG_I40E_DISABLE_PACKET_SPLIT
+               if (!rx_bi->skb)
+                       continue;
+
+               dma_unmap_single(rx_ring->dev, rx_bi->dma,
+                                rx_ring->rx_buf_len, DMA_FROM_DEVICE);
+               dev_kfree_skb(rx_bi->skb);
+               rx_bi->skb = NULL;
+#else /* CONFIG_I40E_DISABLE_PACKET_SPLIT */
                if (!rx_bi->page)
                        continue;
 
-               dma_unmap_page(dev, rx_bi->dma, PAGE_SIZE, DMA_FROM_DEVICE);
-               __free_pages(rx_bi->page, 0);
+               /* Invalidate cache lines that may have been written to by
+                * device so that we avoid corrupting memory.
+                */
+               dma_sync_single_range_for_cpu(rx_ring->dev,
+                                             rx_bi->dma,
+                                             rx_bi->page_offset,
+                                             rx_ring->rx_buf_len,
+                                             DMA_FROM_DEVICE);
+
+               /* free resources associated with mapping */
+               dma_unmap_page_attrs(rx_ring->dev, rx_bi->dma,
+                                    i40e_rx_pg_size(rx_ring),
+                                    DMA_FROM_DEVICE,
+                                    I40E_RX_DMA_ATTR);
+
+               __page_frag_cache_drain(rx_bi->page, rx_bi->pagecnt_bias);
 
                rx_bi->page = NULL;
                rx_bi->page_offset = 0;
+#endif /* CONFIG_I40E_DISABLE_PACKET_SPLIT */
        }
 
        bi_size = sizeof(struct i40e_rx_buffer) * rx_ring->count;
@@ -1181,6 +1263,57 @@ static inline void i40e_release_rx_desc(struct i40e_ring *rx_ring, u32 val)
        writel(val, rx_ring->tail);
 }
 
+#ifdef CONFIG_I40E_DISABLE_PACKET_SPLIT
+static bool i40e_alloc_mapped_skb(struct i40e_ring *rx_ring,
+                                 struct i40e_rx_buffer *bi)
+{
+       struct sk_buff *skb = bi->skb;
+       dma_addr_t dma;
+
+       if (unlikely(skb))
+               return true;
+
+       if (likely(!skb)) {
+               skb = __napi_alloc_skb(&rx_ring->q_vector->napi,
+                                      rx_ring->rx_buf_len,
+                                      GFP_ATOMIC | __GFP_NOWARN);
+               if (unlikely(!skb)) {
+                       rx_ring->rx_stats.alloc_buff_failed++;
+                       return false;
+               }
+       }
+
+       dma = dma_map_single(rx_ring->dev, skb->data,
+                            rx_ring->rx_buf_len, DMA_FROM_DEVICE);
+
+       /*
+        * if mapping failed free memory back to system since
+        * there isn't much point in holding memory we can't use
+        */
+       if (dma_mapping_error(rx_ring->dev, dma)) {
+               dev_kfree_skb_any(skb);
+               rx_ring->rx_stats.alloc_buff_failed++;
+               return false;
+       }
+
+       bi->skb = skb;
+       bi->dma = dma;
+
+       return true;
+}
+
+#else
+/**
+ * i40e_rx_offset - Return expected offset into page to access data
+ * @rx_ring: Ring we are requesting offset of
+ *
+ * Returns the offset value for ring into the data buffer.
+ */
+static inline unsigned int i40e_rx_offset(struct i40e_ring *rx_ring)
+{
+       return ring_uses_build_skb(rx_ring) ? I40E_SKB_PAD : 0;
+}
+
 /**
  * i40e_alloc_mapped_page - recycle or make a new page
  * @rx_ring: ring to use
@@ -1202,31 +1335,38 @@ static bool i40e_alloc_mapped_page(struct i40e_ring *rx_ring,
        }
 
        /* alloc new page for storage */
-       page = dev_alloc_page();
+       page = dev_alloc_pages(i40e_rx_pg_order(rx_ring));
        if (unlikely(!page)) {
                rx_ring->rx_stats.alloc_page_failed++;
                return false;
        }
 
        /* map page for use */
-       dma = dma_map_page(rx_ring->dev, page, 0, PAGE_SIZE, DMA_FROM_DEVICE);
+       dma = dma_map_page_attrs(rx_ring->dev, page, 0,
+                                i40e_rx_pg_size(rx_ring),
+                                DMA_FROM_DEVICE,
+                                I40E_RX_DMA_ATTR);
 
        /* if mapping failed free memory back to system since
         * there isn't much point in holding memory we can't use
         */
        if (dma_mapping_error(rx_ring->dev, dma)) {
-               __free_pages(page, 0);
+               __free_pages(page, i40e_rx_pg_order(rx_ring));
                rx_ring->rx_stats.alloc_page_failed++;
                return false;
        }
 
        bi->dma = dma;
        bi->page = page;
-       bi->page_offset = 0;
+       bi->page_offset = i40e_rx_offset(rx_ring);
+
+       /* initialize pagecnt_bias to 1 representing we fully own page */
+       bi->pagecnt_bias = 1;
 
        return true;
 }
 
+#endif /* CONFIG_I40E_DISABLE_PACKET_SPLIT */
 /**
  * i40e_receive_skb - Send a completed packet up the stack
  * @rx_ring:  rx ring in play
@@ -1240,22 +1380,16 @@ static void i40e_receive_skb(struct i40e_ring *rx_ring,
 #ifdef HAVE_VLAN_RX_REGISTER
        struct i40e_vsi *vsi = rx_ring->vsi;
 #endif
-       u64 flags = rx_ring->vsi->back->flags;
 
 #ifdef HAVE_VLAN_RX_REGISTER
        if (vlan_tag & VLAN_VID_MASK) {
                if (!vsi->vlgrp)
                        dev_kfree_skb_any(skb);
-               else if (flags & I40E_FLAG_IN_NETPOLL)
-                       vlan_hwaccel_rx(skb, vsi->vlgrp, vlan_tag);
                else
                        vlan_gro_receive(&q_vector->napi, vsi->vlgrp,
                                         vlan_tag, skb);
        } else {
-               if (flags & I40E_FLAG_IN_NETPOLL)
-                       netif_rx(skb);
-               else
-                       napi_gro_receive(&q_vector->napi, skb);
+               napi_gro_receive(&q_vector->napi, skb);
        }
 #else /* HAVE_VLAN_RX_REGISTER */
 #ifdef NETIF_F_HW_VLAN_CTAG_RX
@@ -1267,10 +1401,7 @@ static void i40e_receive_skb(struct i40e_ring *rx_ring,
 #endif /* NETIF_F_HW_VLAN_CTAG_RX */
                __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tag);
 
-       if (flags & I40E_FLAG_IN_NETPOLL)
-               netif_rx(skb);
-       else
-               napi_gro_receive(&q_vector->napi, skb);
+       napi_gro_receive(&q_vector->napi, skb);
 #endif /* HAVE_VLAN_RX_REGISTER */
 }
 
@@ -1295,13 +1426,26 @@ bool i40e_alloc_rx_buffers(struct i40e_ring *rx_ring, u16 cleaned_count)
        bi = &rx_ring->rx_bi[ntu];
 
        do {
+#ifdef CONFIG_I40E_DISABLE_PACKET_SPLIT
+               if (!i40e_alloc_mapped_skb(rx_ring, bi))
+                       goto no_buffers;
+
+               rx_desc->read.pkt_addr = cpu_to_le64(bi->dma);
+#else
                if (!i40e_alloc_mapped_page(rx_ring, bi))
                        goto no_buffers;
 
+               /* sync the buffer for use by the device */
+               dma_sync_single_range_for_device(rx_ring->dev, bi->dma,
+                                                bi->page_offset,
+                                                rx_ring->rx_buf_len,
+                                                DMA_FROM_DEVICE);
+
                /* Refresh the desc even if buffer_addrs didn't change
                 * because each write-back erases this info.
                 */
                rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset);
+#endif /* CONFIG_I40E_DISABLE_PACKET_SPLIT */
 
                rx_desc++;
                bi++;
@@ -1368,18 +1512,14 @@ static void i40e_rx_extra_counters(struct i40e_vsi *vsi, u32 rx_error,
 }
 
 #endif /* I40E_ADD_PROBES */
-#if defined(HAVE_VXLAN_RX_OFFLOAD) || defined(HAVE_GENEVE_RX_OFFLOAD) || defined(HAVE_UDP_ENC_RX_OFFLOAD)
-#if defined(HAVE_SKBUFF_CSUM_LEVEL) || defined(ESX55)
+#if defined(HAVE_VXLAN_RX_OFFLOAD) || defined(HAVE_GENEVE_RX_OFFLOAD) || defined(HAVE_UDP_ENC_RX_OFFLOAD) || defined(ESX55)
 #define I40E_TUNNEL_SUPPORT
 #endif
-#endif
 /**
  * i40e_rx_checksum - Indicate in skb if hw indicated a good cksum
  * @vsi: the VSI we care about
  * @skb: skb currently being received and modified
  * @rx_desc: the receive descriptor
- *
- * skb->protocol must be set before this function is called
  **/
 static inline void i40e_rx_checksum(struct i40e_vsi *vsi,
                                    struct sk_buff *skb,
@@ -1419,6 +1559,9 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi,
        /* both known and outer_ip must be set for the below code to work */
        if (!(decoded.known && decoded.outer_ip))
                return;
+#ifdef I40E_ADD_PROBES
+       vsi->back->hw_csum_rx_outer++;
+#endif
 
        ipv4 = (decoded.outer_ip == I40E_RX_PTYPE_OUTER_IP) &&
               (decoded.outer_ip_ver == I40E_RX_PTYPE_OUTER_IPV4);
@@ -1456,10 +1599,20 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi,
         * we need to bump the checksum level by 1 to reflect the fact that
         * we are indicating we validated the inner checksum.
         */
-#ifdef HAVE_SKBUFF_CSUM_LEVEL
        if (decoded.tunnel_type >= I40E_RX_PTYPE_TUNNEL_IP_GRENAT)
+#ifdef HAVE_SKBUFF_CSUM_LEVEL
                skb->csum_level = 1;
+#else
+               skb->encapsulation = 1;
 #endif
+#ifdef I40E_ADD_PROBES
+       if (strcmp(i40e_tunnel_name(&vsi->back->udp_ports[vsi->idx]),
+                  "vxlan") == 0)
+               vsi->back->hw_csum_rx_vxlan++;
+       else if (strcmp(i40e_tunnel_name(&vsi->back->udp_ports[vsi->idx]),
+                       "geneve") == 0)
+               vsi->back->hw_csum_rx_geneve++;
+#endif /* I40E_ADD_PROBES */
 #endif /* I40E_TUNNEL_SUPPORT */
 
        /* Only report checksum unnecessary for TCP, UDP, or SCTP */
@@ -1484,7 +1637,7 @@ checksum_fail:
  *
  * Returns a hash type to be used by skb_set_hash
  **/
-static inline int i40e_ptype_to_htype(u8 ptype)
+static inline enum pkt_hash_types i40e_ptype_to_htype(u8 ptype)
 {
        struct i40e_rx_ptype_decoded decoded = decode_rx_desc_ptype(ptype);
 
@@ -1557,49 +1710,12 @@ void i40e_process_skb_fields(struct i40e_ring *rx_ring,
 
        i40e_rx_hash(rx_ring, rx_desc, skb, rx_ptype);
 
-       /* modifies the skb - consumes the enet header */
-       skb->protocol = eth_type_trans(skb, rx_ring->netdev);
-
        i40e_rx_checksum(rx_ring->vsi, skb, rx_desc);
-}
-
-/**
- * i40e_pull_tail - i40e specific version of skb_pull_tail
- * @rx_ring: rx descriptor ring packet is being transacted on
- * @skb: pointer to current skb being adjusted
- *
- * This function is an i40e specific version of __pskb_pull_tail.  The
- * main difference between this version and the original function is that
- * this function can make several assumptions about the state of things
- * that allow for significant optimizations versus the standard function.
- * As a result we can do things like drop a frag and maintain an accurate
- * truesize for the skb.
- */
-static void i40e_pull_tail(struct i40e_ring *rx_ring, struct sk_buff *skb)
-{
-       struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[0];
-       unsigned char *va;
-       unsigned int pull_len;
-
-       /* it is valid to use page_address instead of kmap since we are
-        * working with pages allocated out of the lomem pool per
-        * alloc_page(GFP_ATOMIC)
-        */
-       va = skb_frag_address(frag);
-
-       /* we need the header to contain the greater of either ETH_HLEN or
-        * 60 bytes if the skb->len is less than 60 for skb_pad.
-        */
-       pull_len = eth_get_headlen(va, I40E_RX_HDR_SIZE);
 
-       /* align pull length to size of long to optimize memcpy performance */
-       skb_copy_to_linear_data(skb, va, ALIGN(pull_len, sizeof(long)));
+       skb_record_rx_queue(skb, rx_ring->queue_index);
 
-       /* update all of the pointers */
-       skb_frag_size_sub(frag, pull_len);
-       frag->page_offset += pull_len;
-       skb->data_len -= pull_len;
-       skb->tail += pull_len;
+       /* modifies the skb - consumes the enet header */
+       skb->protocol = eth_type_trans(skb, rx_ring->netdev);
 }
 
 /**
@@ -1617,10 +1733,6 @@ static void i40e_pull_tail(struct i40e_ring *rx_ring, struct sk_buff *skb)
  **/
 static bool i40e_cleanup_headers(struct i40e_ring *rx_ring, struct sk_buff *skb)
 {
-       /* place header in linear portion of buffer */
-       if (skb_is_nonlinear(skb))
-               i40e_pull_tail(rx_ring, skb);
-
        /* if eth_skb_pad returns an error the skb was freed */
        if (eth_skb_pad(skb))
                return true;
@@ -1628,6 +1740,51 @@ static bool i40e_cleanup_headers(struct i40e_ring *rx_ring, struct sk_buff *skb)
        return false;
 }
 
+#ifdef CONFIG_I40E_DISABLE_PACKET_SPLIT
+/**
+ * i40e_get_rx_buffer - Fetch Rx buffer and synchronize data for use
+ * @rx_ring: rx descriptor ring to transact packets on
+ * @size: size of buffer to add to skb
+ *
+ * This function will pull an Rx buffer from the ring and synchronize it
+ * for use by the CPU.
+ *
+ * ONE-BUFF version
+ */
+static struct i40e_rx_buffer *i40e_get_rx_buffer(struct i40e_ring *rx_ring,
+                                                const unsigned int size)
+{
+       struct i40e_rx_buffer *rx_buffer;
+
+       rx_buffer = &rx_ring->rx_bi[rx_ring->next_to_clean];
+
+       /* we are reusing so sync this buffer for CPU use */
+       dma_unmap_single(rx_ring->dev, rx_buffer->dma,
+                        rx_ring->rx_buf_len, DMA_FROM_DEVICE);
+
+       prefetch(rx_buffer->skb->data);
+
+       return rx_buffer;
+}
+
+/**
+ * i40e_put_rx_buffer - Clean up used buffer and either recycle or free
+ * @rx_ring: rx descriptor ring to transact packets on
+ * @rx_buffer: rx buffer to pull data from
+ *
+ * This function will clean up the contents of the rx_buffer.  It will
+ * either recycle the bufer or unmap it and free the associated resources.
+ *
+ * ONE-BUFF version
+ */
+static void i40e_put_rx_buffer(struct i40e_ring *rx_ring,
+                              struct i40e_rx_buffer *rx_buffer)
+{
+       /* clear contents of buffer_info */
+       rx_buffer->skb = NULL;
+}
+
+#else /* CONFIG_I40E_DISABLE_PACKET_SPLIT */
 /**
  * i40e_reuse_rx_page - page flip buffer and store it back on the ring
  * @rx_ring: rx descriptor ring to store buffers on
@@ -1648,173 +1805,297 @@ static void i40e_reuse_rx_page(struct i40e_ring *rx_ring,
        rx_ring->next_to_alloc = (nta < rx_ring->count) ? nta : 0;
 
        /* transfer page from old buffer to new buffer */
-       *new_buff = *old_buff;
+       new_buff->dma           = old_buff->dma;
+       new_buff->page          = old_buff->page;
+       new_buff->page_offset   = old_buff->page_offset;
+       new_buff->pagecnt_bias  = old_buff->pagecnt_bias;
 }
 
 /**
- * i40e_page_is_reserved - check if reuse is possible
+ * i40e_page_is_reusable - check if any reuse is possible
  * @page: page struct to check
+ *
+ * A page is not reusable if it was allocated under low memory
+ * conditions, or it's not in the same NUMA node as this CPU.
  */
-static inline bool i40e_page_is_reserved(struct page *page)
+static inline bool i40e_page_is_reusable(struct page *page)
+{
+       return (page_to_nid(page) == numa_mem_id()) &&
+               !page_is_pfmemalloc(page);
+}
+
+/**
+ * i40e_can_reuse_rx_page - Determine if this page can be reused by
+ * the adapter for another receive
+ *
+ * @rx_buffer: buffer containing the page
+ *
+ * If page is reusable, rx_buffer->page_offset is adjusted to point to
+ * an unused region in the page.
+ *
+ * For small pages, @truesize will be a constant value, half the size
+ * of the memory at page.  We'll attempt to alternate between high and
+ * low halves of the page, with one half ready for use by the hardware
+ * and the other half being consumed by the stack.  We use the page
+ * ref count to determine whether the stack has finished consuming the
+ * portion of this page that was passed up with a previous packet.  If
+ * the page ref count is >1, we'll assume the "other" half page is
+ * still busy, and this page cannot be reused.
+ *
+ * For larger pages, @truesize will be the actual space used by the
+ * received packet (adjusted upward to an even multiple of the cache
+ * line size).  This will advance through the page by the amount
+ * actually consumed by the received packets while there is still
+ * space for a buffer.  Each region of larger pages will be used at
+ * most once, after which the page will not be reused.
+ *
+ * In either case, if the page is reusable its refcount is increased.
+ **/
+static bool i40e_can_reuse_rx_page(struct i40e_rx_buffer *rx_buffer)
 {
-       return (page_to_nid(page) != numa_mem_id()) || page_is_pfmemalloc(page);
+       unsigned int pagecnt_bias = rx_buffer->pagecnt_bias;
+       struct page *page = rx_buffer->page;
+
+       /* Is any reuse possible? */
+       if (unlikely(!i40e_page_is_reusable(page)))
+               return false;
+
+#if (PAGE_SIZE < 8192)
+       /* if we are only owner of page we can reuse it */
+       if (unlikely((page_count(page) - pagecnt_bias) > 1))
+               return false;
+#else
+#define I40E_LAST_OFFSET \
+       (SKB_WITH_OVERHEAD(PAGE_SIZE) - I40E_RXBUFFER_2048)
+       if (rx_buffer->page_offset > I40E_LAST_OFFSET)
+               return false;
+#endif
+
+       /* If we have drained the page fragment pool we need to update
+        * the pagecnt_bias and page count so that we fully restock the
+        * number of references the driver holds.
+        */
+#ifdef HAVE_PAGE_COUNT_BULK_UPDATE
+       if (unlikely(!pagecnt_bias)) {
+               page_ref_add(page, USHRT_MAX);
+               rx_buffer->pagecnt_bias = USHRT_MAX;
+       }
+#else
+       if (likely(!pagecnt_bias)) {
+               get_page(page);
+               rx_buffer->pagecnt_bias = 1;
+       }
+#endif
+
+       return true;
 }
 
 /**
  * i40e_add_rx_frag - Add contents of Rx buffer to sk_buff
  * @rx_ring: rx descriptor ring to transact packets on
  * @rx_buffer: buffer containing page to add
- * @rx_desc: descriptor containing length of buffer written by hardware
  * @skb: sk_buff to place the data into
+ * @size: packet length from rx_desc
  *
  * This function will add the data contained in rx_buffer->page to the skb.
- * This is done either through a direct copy if the data in the buffer is
- * less than the skb header size, otherwise it will just attach the page as
- * a frag to the skb.
+ * It will just attach the page as a frag to the skb.
  *
- * The function will then update the page offset if necessary and return
- * true if the buffer can be reused by the adapter.
+ * The function will then update the page offset.
  **/
-static bool i40e_add_rx_frag(struct i40e_ring *rx_ring,
+static void i40e_add_rx_frag(struct i40e_ring *rx_ring,
                             struct i40e_rx_buffer *rx_buffer,
-                            union i40e_rx_desc *rx_desc,
-                            struct sk_buff *skb)
+                            struct sk_buff *skb,
+                            unsigned int size)
 {
-       struct page *page = rx_buffer->page;
-       u64 qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
-       unsigned int size = (qword & I40E_RXD_QW1_LENGTH_PBUF_MASK) >>
-                           I40E_RXD_QW1_LENGTH_PBUF_SHIFT;
 #if (PAGE_SIZE < 8192)
-       unsigned int truesize = I40E_RXBUFFER_2048;
+       unsigned int truesize = i40e_rx_pg_size(rx_ring) / 2;
 #else
-       unsigned int truesize = ALIGN(size, L1_CACHE_BYTES);
-       unsigned int last_offset = PAGE_SIZE - I40E_RXBUFFER_2048;
+       unsigned int truesize = SKB_DATA_ALIGN(size + i40e_rx_offset(rx_ring));
 #endif
 
-       /* will the data fit in the skb we allocated? if so, just
-        * copy it as it is pretty small anyway
-        */
-       if ((size <= I40E_RX_HDR_SIZE) && !skb_is_nonlinear(skb)) {
-               unsigned char *va = page_address(page) + rx_buffer->page_offset;
-
-               memcpy(__skb_put(skb, size), va, ALIGN(size, sizeof(long)));
-
-               /* page is not reserved, we can reuse buffer as-is */
-               if (likely(!i40e_page_is_reserved(page)))
-                       return true;
-
-               /* this page cannot be reused so discard it */
-               __free_pages(page, 0);
-               return false;
-       }
-
-       skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page,
+       skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, rx_buffer->page,
                        rx_buffer->page_offset, size, truesize);
 
-       /* avoid re-using remote pages */
-       if (unlikely(i40e_page_is_reserved(page)))
-               return false;
-
+       /* page is being used so we must update the page offset */
 #if (PAGE_SIZE < 8192)
-       /* if we are only owner of page we can reuse it */
-       if (unlikely(page_count(page) != 1))
-               return false;
-
-       /* flip page offset to other buffer */
        rx_buffer->page_offset ^= truesize;
 #else
-       /* move offset up to the next cache line */
        rx_buffer->page_offset += truesize;
-
-       if (rx_buffer->page_offset > last_offset)
-               return false;
 #endif
-
-       /* Even if we own the page, we are not allowed to use atomic_set()
-        * This would break get_page_unless_zero() users.
-        */
-       get_page(rx_buffer->page);
-
-       return true;
 }
 
 /**
- * i40e_fetch_rx_buffer - Allocate skb and populate it
+ * i40e_get_rx_buffer - Fetch Rx buffer and synchronize data for use
  * @rx_ring: rx descriptor ring to transact packets on
- * @rx_desc: descriptor containing info written by hardware
+ * @size: size of buffer to add to skb
  *
- * This function allocates an skb on the fly, and populates it with the page
- * data from the current receive descriptor, taking care to set up the skb
- * correctly, as well as handling calling the page recycle function if
- * necessary.
+ * This function will pull an Rx buffer from the ring and synchronize it
+ * for use by the CPU.
  */
-static inline
-struct sk_buff *i40e_fetch_rx_buffer(struct i40e_ring *rx_ring,
-                                    union i40e_rx_desc *rx_desc)
+static struct i40e_rx_buffer *i40e_get_rx_buffer(struct i40e_ring *rx_ring,
+                                                const unsigned int size)
 {
        struct i40e_rx_buffer *rx_buffer;
-       struct sk_buff *skb;
-       struct page *page;
 
        rx_buffer = &rx_ring->rx_bi[rx_ring->next_to_clean];
-       page = rx_buffer->page;
-       prefetchw(page);
+       prefetchw(rx_buffer->page);
 
-       skb = rx_buffer->skb;
+       /* we are reusing so sync this buffer for CPU use */
+       dma_sync_single_range_for_cpu(rx_ring->dev,
+                                     rx_buffer->dma,
+                                     rx_buffer->page_offset,
+                                     size,
+                                     DMA_FROM_DEVICE);
 
-       if (likely(!skb)) {
-               void *page_addr = page_address(page) + rx_buffer->page_offset;
+       /* We have pulled a buffer for use, so decrement pagecnt_bias */
+       rx_buffer->pagecnt_bias--;
+
+       return rx_buffer;
+}
+
+/**
+ * i40e_construct_skb - Allocate skb and populate it
+ * @rx_ring: rx descriptor ring to transact packets on
+ * @rx_buffer: rx buffer to pull data from
+ * @size: size of buffer to add to skb
+ *
+ * This function allocates an skb.  It then populates it with the page
+ * data from the current receive descriptor, taking care to set up the
+ * skb correctly.
+ */
+static struct sk_buff *i40e_construct_skb(struct i40e_ring *rx_ring,
+                                         struct i40e_rx_buffer *rx_buffer,
+                                         unsigned int size)
+{
+       u8 *va = page_address(rx_buffer->page) + rx_buffer->page_offset;
+#if (PAGE_SIZE < 8192)
+       unsigned int truesize = i40e_rx_pg_size(rx_ring) / 2;
+#else
+       unsigned int truesize = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) +
+                               SKB_DATA_ALIGN(I40E_SKB_PAD + size);
+#endif
+       unsigned int headlen;
+       struct sk_buff *skb;
 
-               /* prefetch first cache line of first page */
-               prefetch(page_addr);
+       /* prefetch first cache line of first page */
+       prefetch(va);
 #if L1_CACHE_BYTES < 128
-               prefetch(page_addr + L1_CACHE_BYTES);
+       prefetch((void *)(va + L1_CACHE_BYTES));
 #endif
 
-               /* allocate a skb to store the frags */
-               skb = __napi_alloc_skb(&rx_ring->q_vector->napi,
-                                      I40E_RX_HDR_SIZE,
-                                      GFP_ATOMIC | __GFP_NOWARN);
-               if (unlikely(!skb)) {
-                       rx_ring->rx_stats.alloc_buff_failed++;
-                       return NULL;
-               }
+       /* allocate a skb to store the frags */
+       skb = __napi_alloc_skb(&rx_ring->q_vector->napi,
+                              I40E_RX_HDR_SIZE,
+                              GFP_ATOMIC | __GFP_NOWARN);
+       if (unlikely(!skb))
+               return NULL;
 
-               /* we will be copying header into skb->data in
-                * pskb_may_pull so it is in our interest to prefetch
-                * it now to avoid a possible cache miss
-                */
-               prefetchw(skb->data);
+       /* Determine available headroom for copy */
+       headlen = size;
+       if (headlen > I40E_RX_HDR_SIZE)
+               headlen = eth_get_headlen(va, I40E_RX_HDR_SIZE);
+
+       /* align pull length to size of long to optimize memcpy performance */
+       memcpy(__skb_put(skb, headlen), va, ALIGN(headlen, sizeof(long)));
 
-               skb_record_rx_queue(skb, rx_ring->queue_index);
+       /* update all of the pointers */
+       size -= headlen;
+       if (size) {
+               skb_add_rx_frag(skb, 0, rx_buffer->page,
+                               rx_buffer->page_offset + headlen,
+                               size, truesize);
+
+               /* buffer is used by skb, update page_offset */
+#if (PAGE_SIZE < 8192)
+               rx_buffer->page_offset ^= truesize;
+#else
+               rx_buffer->page_offset += truesize;
+#endif
        } else {
-               rx_buffer->skb = NULL;
+               /* buffer is unused, reset bias back to rx_buffer */
+               rx_buffer->pagecnt_bias++;
        }
 
-       /* we are reusing so sync this buffer for CPU use */
-       dma_sync_single_range_for_cpu(rx_ring->dev,
-                                     rx_buffer->dma,
-                                     rx_buffer->page_offset,
-                                     I40E_RXBUFFER_2048,
-                                     DMA_FROM_DEVICE);
+       return skb;
+}
+
+#ifdef HAVE_SWIOTLB_SKIP_CPU_SYNC
+/**
+ * i40e_build_skb - Build skb around an existing buffer
+ * @rx_ring: rx descriptor ring to transact packets on
+ * @rx_buffer: rx buffer to pull data from
+ * @size: size of buffer to add to skb
+ *
+ * This function builds an skb around an existing Rx buffer, taking care
+ * to set up the skb correctly and avoid any memcpy overhead.
+ */
+static struct sk_buff *i40e_build_skb(struct i40e_ring *rx_ring,
+                                     struct i40e_rx_buffer *rx_buffer,
+                                     unsigned int size)
+{
+       void *va = page_address(rx_buffer->page) + rx_buffer->page_offset;
+#if (PAGE_SIZE < 8192)
+       unsigned int truesize = i40e_rx_pg_size(rx_ring) / 2;
+#else
+       unsigned int truesize = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) +
+                               SKB_DATA_ALIGN(I40E_SKB_PAD + size);
+#endif
+       struct sk_buff *skb;
+
+       /* prefetch first cache line of first page */
+       prefetch(va);
+#if L1_CACHE_BYTES < 128
+       prefetch(va + L1_CACHE_BYTES);
+#endif
+       /* build an skb around the page buffer */
+       skb = build_skb(va - I40E_SKB_PAD, truesize);
+       if (unlikely(!skb))
+               return NULL;
+
+       /* update pointers within the skb to store the data */
+       skb_reserve(skb, I40E_SKB_PAD);
+       __skb_put(skb, size);
+
+       /* buffer is used by skb, update page_offset */
+#if (PAGE_SIZE < 8192)
+       rx_buffer->page_offset ^= truesize;
+#else
+       rx_buffer->page_offset += truesize;
+#endif
+
+       return skb;
+}
 
-       /* pull page into skb */
-       if (i40e_add_rx_frag(rx_ring, rx_buffer, rx_desc, skb)) {
+#endif /* HAVE_SWIOTLB_SKIP_CPU_SYNC */
+/**
+ * i40e_put_rx_buffer - Clean up used buffer and either recycle or free
+ * @rx_ring: rx descriptor ring to transact packets on
+ * @rx_buffer: rx buffer to pull data from
+ *
+ * This function will clean up the contents of the rx_buffer.  It will
+ * either recycle the bufer or unmap it and free the associated resources.
+ */
+static void i40e_put_rx_buffer(struct i40e_ring *rx_ring,
+                              struct i40e_rx_buffer *rx_buffer)
+{
+       if (i40e_can_reuse_rx_page(rx_buffer)) {
                /* hand second half of page back to the ring */
                i40e_reuse_rx_page(rx_ring, rx_buffer);
                rx_ring->rx_stats.page_reuse_count++;
        } else {
                /* we are not reusing the buffer so unmap it */
-               dma_unmap_page(rx_ring->dev, rx_buffer->dma, PAGE_SIZE,
-                              DMA_FROM_DEVICE);
+               dma_unmap_page_attrs(rx_ring->dev, rx_buffer->dma,
+                                    i40e_rx_pg_size(rx_ring),
+                                    DMA_FROM_DEVICE, I40E_RX_DMA_ATTR);
+               __page_frag_cache_drain(rx_buffer->page,
+                                       rx_buffer->pagecnt_bias);
        }
 
        /* clear contents of buffer_info */
        rx_buffer->page = NULL;
-
-       return skb;
 }
 
+#endif /* CONFIG_I40E_DISABLE_PACKET_SPLIT */
 /**
  * i40e_is_non_eop - process handling of non-EOP buffers
  * @rx_ring: Rx ring being processed
@@ -1838,19 +2119,11 @@ static bool i40e_is_non_eop(struct i40e_ring *rx_ring,
 
        prefetch(I40E_RX_DESC(rx_ring, ntc));
 
-#define staterrlen rx_desc->wb.qword1.status_error_len
-       if (unlikely(i40e_rx_is_programming_status(le64_to_cpu(staterrlen)))) {
-               i40e_clean_programming_status(rx_ring, rx_desc);
-               rx_ring->rx_bi[ntc].skb = skb;
-               return true;
-       }
        /* if we are the last buffer then there is nothing else to do */
 #define I40E_RXD_EOF BIT(I40E_RX_DESC_STATUS_EOF_SHIFT)
        if (likely(i40e_test_staterr(rx_desc, I40E_RXD_EOF)))
                return false;
 
-       /* place skb in next buffer to be received */
-       rx_ring->rx_bi[ntc].skb = skb;
        rx_ring->rx_stats.non_eop_descs++;
 
        return true;
@@ -1871,12 +2144,14 @@ static bool i40e_is_non_eop(struct i40e_ring *rx_ring,
 static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
 {
        unsigned int total_rx_bytes = 0, total_rx_packets = 0;
+       struct sk_buff *skb = rx_ring->skb;
        u16 cleaned_count = I40E_DESC_UNUSED(rx_ring);
        bool failure = false;
 
        while (likely(total_rx_packets < (unsigned int)budget)) {
+               struct i40e_rx_buffer *rx_buffer;
                union i40e_rx_desc *rx_desc;
-               struct sk_buff *skb;
+               unsigned int size;
                u16 vlan_tag;
                u8 rx_ptype;
                u64 qword;
@@ -1893,22 +2168,53 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
                /* status_error_len will always be zero for unused descriptors
                 * because it's cleared in cleanup, and overlaps with hdr_addr
                 * which is always zero because packet split isn't used, if the
-                * hardware wrote DD then it will be non-zero
+                * hardware wrote DD then the length will be non-zero
                 */
-               if (!i40e_test_staterr(rx_desc,
-                                      BIT(I40E_RX_DESC_STATUS_DD_SHIFT)))
-                       break;
+               qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
 
                /* This memory barrier is needed to keep us from reading
-                * any other fields out of the rx_desc until we know the
-                * DD bit is set.
+                * any other fields out of the rx_desc until we have
+                * verified the descriptor has been written back.
                 */
                dma_rmb();
 
-               skb = i40e_fetch_rx_buffer(rx_ring, rx_desc);
-               if (!skb)
+               if (unlikely(i40e_rx_is_programming_status(qword))) {
+                       i40e_clean_programming_status(rx_ring, rx_desc, qword);
+                       continue;
+               }
+               size = (qword & I40E_RXD_QW1_LENGTH_PBUF_MASK) >>
+                      I40E_RXD_QW1_LENGTH_PBUF_SHIFT;
+               if (!size)
                        break;
 
+               i40e_trace(clean_rx_irq, rx_ring, rx_desc, skb);
+               rx_buffer = i40e_get_rx_buffer(rx_ring, size);
+
+               /* retrieve a buffer from the ring */
+#ifdef CONFIG_I40E_DISABLE_PACKET_SPLIT
+               /* we are leaking memory if an skb is already present */
+               WARN_ON(skb);
+               skb = rx_buffer->skb;
+               __skb_put(skb, size);
+#else
+               if (skb)
+                       i40e_add_rx_frag(rx_ring, rx_buffer, skb, size);
+#ifdef HAVE_SWIOTLB_SKIP_CPU_SYNC
+               else if (ring_uses_build_skb(rx_ring))
+                       skb = i40e_build_skb(rx_ring, rx_buffer, size);
+#endif
+               else
+                       skb = i40e_construct_skb(rx_ring, rx_buffer, size);
+
+               /* exit if we failed to retrieve a buffer */
+               if (!skb) {
+                       rx_ring->rx_stats.alloc_buff_failed++;
+                       rx_buffer->pagecnt_bias++;
+                       break;
+               }
+#endif /* CONFIG_I40E_DISABLE_PACKET_SPLIT */
+
+               i40e_put_rx_buffer(rx_ring, rx_buffer);
                cleaned_count++;
 
                if (i40e_is_non_eop(rx_ring, rx_desc, skb))
@@ -1921,11 +2227,14 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
                 */
                if (unlikely(i40e_test_staterr(rx_desc, BIT(I40E_RXD_QW1_ERROR_SHIFT)))) {
                        dev_kfree_skb_any(skb);
+                       skb = NULL;
                        continue;
                }
 
-               if (i40e_cleanup_headers(rx_ring, skb))
+               if (i40e_cleanup_headers(rx_ring, skb)) {
+                       skb = NULL;
                        continue;
+               }
 
                /* probably a little skewed due to removing CRC */
                total_rx_bytes += skb->len;
@@ -1937,23 +2246,19 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
                /* populate checksum, VLAN, and protocol */
                i40e_process_skb_fields(rx_ring, rx_desc, skb, rx_ptype);
 
-#ifdef I40E_FCOE
-               if (unlikely(
-                   i40e_rx_is_fcoe(rx_ptype) &&
-                   !i40e_fcoe_handle_offload(rx_ring, rx_desc, skb))) {
-                       dev_kfree_skb_any(skb);
-                       continue;
-               }
-#endif
                vlan_tag = (qword & BIT(I40E_RX_DESC_STATUS_L2TAG1P_SHIFT)) ?
                           le16_to_cpu(rx_desc->wb.qword0.lo_dword.l2tag1) : 0;
 
+               i40e_trace(clean_rx_irq_rx, rx_ring, rx_desc, skb);
                i40e_receive_skb(rx_ring, skb, vlan_tag);
+               skb = NULL;
 
                /* update budget accounting */
                total_rx_packets++;
        }
 
+       rx_ring->skb = skb;
+
        u64_stats_update_begin(&rx_ring->syncp);
        rx_ring->stats.packets += total_rx_packets;
        rx_ring->stats.bytes += total_rx_bytes;
@@ -2007,6 +2312,12 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi,
        int idx = q_vector->v_idx;
        int rx_itr_setting, tx_itr_setting;
 
+       /* If we don't have MSIX, then we only need to re-enable icr0 */
+       if (!(vsi->back->flags & I40E_FLAG_MSIX_ENABLED)) {
+               i40e_irq_dynamic_enable_icr0(vsi->back, false);
+               return;
+       }
+
        vector = (q_vector->v_idx + vsi->base_vector);
 
        /* avoid dynamic calculation if in countdown mode OR if
@@ -2061,7 +2372,7 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi,
        }
 
 enable_int:
-       if (!test_bit(__I40E_DOWN, &vsi->state))
+       if (!test_bit(__I40E_VSI_DOWN, vsi->state))
                wr32(hw, INTREG(vector - 1), txval);
 
        if (q_vector->itr_countdown)
@@ -2091,7 +2402,7 @@ int i40e_napi_poll(struct napi_struct *napi, int budget)
        int budget_per_ring;
        int work_done = 0;
 
-       if (test_bit(__I40E_DOWN, &vsi->state)) {
+       if (test_bit(__I40E_VSI_DOWN, vsi->state)) {
                napi_complete(napi);
                return 0;
        }
@@ -2108,10 +2419,6 @@ int i40e_napi_poll(struct napi_struct *napi, int budget)
                ring->arm_wb = false;
        }
 
-       /* if the netpoll flag is set then we skip rx */
-       if (flags & I40E_FLAG_IN_NETPOLL)
-               goto tx_only;
-
        /* Handle case where we are called by netpoll with a budget of 0 */
        if (budget <= 0)
                goto tx_only;
@@ -2139,7 +2446,6 @@ int i40e_napi_poll(struct napi_struct *napi, int budget)
        /* If work not completed, return budget and polling will return */
        if (!clean_complete) {
 #ifdef HAVE_IRQ_AFFINITY_NOTIFY
-               const cpumask_t *aff_mask = &q_vector->affinity_mask;
                int cpu_id = smp_processor_id();
 
                /* It is possible that the interrupt affinity has changed but,
@@ -2149,23 +2455,23 @@ int i40e_napi_poll(struct napi_struct *napi, int budget)
                 * continue to poll, otherwise we must stop polling so the
                 * interrupt can move to the correct cpu.
                 */
-               if (likely(cpumask_test_cpu(cpu_id, aff_mask) ||
-                          !(vsi->back->flags & I40E_FLAG_MSIX_ENABLED))) {
-tx_only:
-                       if (arm_wb) {
-                               q_vector->tx.ring[0].tx_stats.tx_force_wb++;
-                               i40e_enable_wb_on_itr(vsi, q_vector);
-                       }
-                       return budget;
+               if (!cpumask_test_cpu(cpu_id, &q_vector->affinity_mask)) {
+                       /* Tell napi that we are done polling */
+                       napi_complete_done(napi, work_done);
+
+                       /* Force an interrupt */
+                       i40e_force_wb(vsi, q_vector);
+
+                       /* Return budget-1 so that polling stops */
+                       return budget - 1;
                }
-#else /* HAVE_IRQ_AFFINITY_NOTIFY */
+#endif /* HAVE_IRQ_AFFINITY_NOTIFY */
 tx_only:
                if (arm_wb) {
                        q_vector->tx.ring[0].tx_stats.tx_force_wb++;
                        i40e_enable_wb_on_itr(vsi, q_vector);
                }
                return budget;
-#endif /* HAVE_IRQ_AFFINITY_NOTIFY */
        }
 
        if (flags & I40E_TXR_FLAGS_WB_ON_ITR)
@@ -2174,16 +2480,7 @@ tx_only:
        /* Work is done so exit the polling mode and re-enable the interrupt */
        napi_complete_done(napi, work_done);
 
-       /* If we're prematurely stopping polling to fix the interrupt
-        * affinity we want to make sure polling starts back up so we
-        * issue a call to i40e_force_wb which triggers a SW interrupt.
-        */
-       if (!clean_complete)
-               i40e_force_wb(vsi, q_vector);
-       else if (!(vsi->back->flags & I40E_FLAG_MSIX_ENABLED))
-               i40e_irq_dynamic_enable_icr0(vsi->back, false);
-       else
-               i40e_update_enable_itr(vsi, q_vector);
+       i40e_update_enable_itr(vsi, q_vector);
 
        return min(work_done, budget - 1);
 }
@@ -2214,7 +2511,7 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct sk_buff *skb,
        if (!(pf->flags & I40E_FLAG_FD_ATR_ENABLED))
                return;
 
-       if ((pf->hw_disabled_flags & I40E_FLAG_FD_ATR_ENABLED))
+       if (pf->flags & I40E_FLAG_FD_ATR_AUTO_DISABLED)
                return;
 
        /* if sampling is disabled do nothing */
@@ -2257,11 +2554,10 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct sk_buff *skb,
        th = (struct tcphdr *)(hdr.network + hlen);
 
        /* Due to lack of space, no more new filters can be programmed */
-       if (th->syn && (pf->hw_disabled_flags & I40E_FLAG_FD_ATR_ENABLED))
+       if (th->syn && (pf->flags & I40E_FLAG_FD_ATR_AUTO_DISABLED))
                return;
 
-       if ((pf->flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE) &&
-           (!(pf->hw_disabled_flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE))) {
+       if (pf->flags & I40E_FLAG_HW_ATR_EVICT_ENABLED) {
                /* HW ATR eviction will take care of removing filters on FIN
                 * and RST packets.
                 */
@@ -2323,8 +2619,7 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct sk_buff *skb,
                        I40E_TXD_FLTR_QW1_CNTINDEX_SHIFT) &
                        I40E_TXD_FLTR_QW1_CNTINDEX_MASK;
 
-       if ((pf->flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE) &&
-           (!(pf->hw_disabled_flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE)))
+       if (pf->flags & I40E_FLAG_HW_ATR_EVICT_ENABLED)
                dtype_cmd |= I40E_TXD_FLTR_QW1_ATR_MASK;
 
        fdir_desc->qindex_flex_ptype_vsi = cpu_to_le32(flex_ptype);
@@ -2345,15 +2640,9 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct sk_buff *skb,
  * Returns error code indicate the frame should be dropped upon error and the
  * otherwise  returns 0 to indicate the flags has been set properly.
  **/
-#ifdef I40E_FCOE
-inline int i40e_tx_prepare_vlan_flags(struct sk_buff *skb,
-                                     struct i40e_ring *tx_ring,
-                                     u32 *flags)
-#else
 static inline int i40e_tx_prepare_vlan_flags(struct sk_buff *skb,
                                             struct i40e_ring *tx_ring,
                                             u32 *flags)
-#endif
 {
        __be16 protocol = skb->protocol;
        u32  tx_flags = 0;
@@ -2480,8 +2769,14 @@ static int i40e_tso(struct i40e_tx_buffer *first, u8 *hdr_len,
 
 #ifdef HAVE_ENCAP_TSO_OFFLOAD
        if (skb_shinfo(skb)->gso_type & (SKB_GSO_GRE |
+#ifdef NETIF_F_GSO_PARTIAL
+                                        SKB_GSO_GRE_CSUM |
+#endif
 #ifdef NETIF_F_GSO_IPXIP4
                                         SKB_GSO_IPXIP4 |
+#ifdef NETIF_F_GSO_IPXIP6
+                                        SKB_GSO_IPXIP6 |
+#endif
 #else
 #ifdef NETIF_F_GSO_IPIP
                                         SKB_GSO_IPIP |
@@ -2492,13 +2787,21 @@ static int i40e_tso(struct i40e_tx_buffer *first, u8 *hdr_len,
 #endif
                                         SKB_GSO_UDP_TUNNEL |
                                         SKB_GSO_UDP_TUNNEL_CSUM)) {
+#ifndef NETIF_F_GSO_PARTIAL
                if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM) {
+#else
+               if (!(skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL) &&
+                   (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM)) {
+#endif
+                       l4.udp->len = 0;
+
                        /* determine offset of outer transport header */
                        l4_offset = l4.hdr - skb->data;
 
                        /* remove payload length from outer checksum */
                        paylen = skb->len - l4_offset;
-                       csum_replace_by_diff(&l4.udp->check, htonl(paylen));
+                       csum_replace_by_diff(&l4.udp->check,
+                                            (__force __wsum)htonl(paylen));
                }
 
                /* reset pointers to inner headers */
@@ -2520,7 +2823,7 @@ static int i40e_tso(struct i40e_tx_buffer *first, u8 *hdr_len,
 
        /* remove payload length from inner checksum */
        paylen = skb->len - l4_offset;
-       csum_replace_by_diff(&l4.tcp->check, htonl(paylen));
+       csum_replace_by_diff(&l4.tcp->check, (__force __wsum)htonl(paylen));
 
        /* compute length of segmentation header */
        *hdr_len = (l4.tcp->doff * 4) + l4_offset;
@@ -2584,7 +2887,7 @@ static int i40e_tsyn(struct i40e_ring *tx_ring, struct sk_buff *skb,
                return 0;
 
        if (pf->ptp_tx &&
-           !test_and_set_bit_lock(__I40E_PTP_TX_IN_PROGRESS, &pf->state)) {
+           !test_and_set_bit_lock(__I40E_PTP_TX_IN_PROGRESS, pf->state)) {
 #ifdef SKB_SHARED_TX_IS_UNION
                skb_tx(skb)->in_progress = 1;
 #else
@@ -2592,6 +2895,7 @@ static int i40e_tsyn(struct i40e_ring *tx_ring, struct sk_buff *skb,
 #endif
                pf->ptp_tx_skb = skb_get(skb);
        } else {
+               pf->tx_hwtstamp_skipped++;
                return 0;
        }
 
@@ -2643,17 +2947,6 @@ static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
 #ifdef HAVE_ENCAP_CSUM_OFFLOAD
        if (skb->encapsulation) {
                u32 tunnel = 0;
-               /* There seems to be an issue in some versions of kernel stack
-                * (e.g. v3.14) where the transport_header is getting set to
-                * the same value as the inner_transport_header which messes up
-                * the calculations used by the skbuff macros.  Here we find our
-                * own network_header_len and transport_header values.
-                */
-               int net_head_len = ip_hdr(skb)->ihl * 4;
-               int trans_head = skb->network_header + net_head_len;
-
-               if (skb->transport_header == skb->inner_transport_header)
-                       l4.hdr = skb->data + trans_head;
                /* define outer network header type */
                if (*tx_flags & I40E_TX_FLAGS_IPV4) {
                        tunnel |= (*tx_flags & I40E_TX_FLAGS_TSO) ?
@@ -2681,6 +2974,16 @@ static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
                case IPPROTO_GRE:
                        tunnel |= I40E_TXD_CTX_GRE_TUNNELING;
                        *tx_flags |= I40E_TX_FLAGS_TUNNEL;
+                       /* There was a long-standing issue in GRE where GSO
+                        * was not setting the outer transport header unless
+                        * a GRE checksum was requested. This was fixed in
+                        * the 4.6 version of the kernel.  In the 4.7 kernel
+                        * support for GRE over IPv6 was added to GSO.  So we
+                        * can assume this workaround for all IPv4 headers
+                        * without impacting later versions of the GRE.
+                        */
+                       if (ip.v4->version == 4)
+                               l4.hdr = ip.hdr + (ip.v4->ihl * 4);
                        break;
                case IPPROTO_IPIP:
                case IPPROTO_IPV6:
@@ -2714,6 +3017,9 @@ static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
 
                /* indicate if we need to offload outer UDP header */
                if ((*tx_flags & I40E_TX_FLAGS_TSO) &&
+#ifdef NETIF_F_GSO_PARTIAL
+                   !(skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL) &&
+#endif
                    (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM))
                        tunnel |= I40E_TXD_CTX_QW0_L4T_CS_MASK;
 
@@ -2930,16 +3236,12 @@ bool __i40e_chk_linearize(struct sk_buff *skb)
  * @hdr_len:  size of the packet header
  * @td_cmd:   the command field in the descriptor
  * @td_offset: offset for checksum or crc
+ *
+ * Returns 0 on success, negative error code on DMA failure.
  **/
-#ifdef I40E_FCOE
-inline void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
-                       struct i40e_tx_buffer *first, u32 tx_flags,
-                       const u8 hdr_len, u32 td_cmd, u32 td_offset)
-#else
-static inline void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
-                              struct i40e_tx_buffer *first, u32 tx_flags,
-                              const u8 hdr_len, u32 td_cmd, u32 td_offset)
-#endif
+static inline int i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
+                             struct i40e_tx_buffer *first, u32 tx_flags,
+                             const u8 hdr_len, u32 td_cmd, u32 td_offset)
 {
        unsigned int data_len = skb->data_len;
        unsigned int size = skb_headlen(skb);
@@ -3113,7 +3415,7 @@ do_rs:
        mmiowb();
 #endif /* HAVE_XMIT_MORE */
 
-       return;
+       return 0;
 
 dma_error:
        dev_info(tx_ring->dev, "TX DMA map failed\n");
@@ -3130,6 +3432,8 @@ dma_error:
        }
 
        tx_ring->next_to_use = i;
+
+       return -EIO;
 }
 
 #if !defined(HAVE_NET_DEVICE_OPS) && defined(HAVE_NETDEV_SELECT_QUEUE)
@@ -3172,6 +3476,8 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
        /* prefetch the data, we'll need it later */
        prefetch(skb->data);
 
+       i40e_trace(xmit_frame_ring, skb, tx_ring);
+
        count = i40e_xmit_descriptor_count(skb);
        if (i40e_chk_linearize(skb, count)) {
                if (__skb_linearize(skb)) {
@@ -3246,8 +3552,14 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
         */
        i40e_atr(tx_ring, skb, tx_flags);
 
+#ifdef HAVE_PTP_1588_CLOCK
+       if (i40e_tx_map(tx_ring, skb, first, tx_flags, hdr_len,
+                       td_cmd, td_offset))
+               goto cleanup_tx_tstamp;
+#else
        i40e_tx_map(tx_ring, skb, first, tx_flags, hdr_len,
                    td_cmd, td_offset);
+#endif
 
 #ifndef HAVE_TRANS_START_IN_QUEUE
        tx_ring->netdev->trans_start = jiffies;
@@ -3255,8 +3567,19 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
        return NETDEV_TX_OK;
 
 out_drop:
+       i40e_trace(xmit_frame_ring_drop, first->skb, tx_ring);
        dev_kfree_skb_any(first->skb);
        first->skb = NULL;
+#ifdef HAVE_PTP_1588_CLOCK
+cleanup_tx_tstamp:
+       if (unlikely(tx_flags & I40E_TX_FLAGS_TSYN)) {
+               struct i40e_pf *pf = i40e_netdev_to_pf(tx_ring->netdev);
+
+               dev_kfree_skb_any(pf->ptp_tx_skb);
+               pf->ptp_tx_skb = NULL;
+               clear_bit_unlock(__I40E_PTP_TX_IN_PROGRESS, pf->state);
+       }
+#endif
        return NETDEV_TX_OK;
 }
 
similarity index 82%
rename from i40e-dkms/i40e-1.6.42/src/i40e_txrx.h
rename to i40e-dkms/i40e-2.1.26/src/i40e_txrx.h
index f44a3e6406f2570d3851155495bb667ab5f6d00c..451043de13bba3d28c4728538d3c409c0efd1ffc 100644 (file)
@@ -109,15 +109,14 @@ enum i40e_dyn_idx_t {
        BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP))
 
 #define i40e_pf_get_default_rss_hena(pf) \
-       (((pf)->flags & I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE) ? \
+       (((pf)->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE) ? \
          I40E_DEFAULT_RSS_HENA_EXPANDED : I40E_DEFAULT_RSS_HENA)
 
 /* Supported Rx Buffer Sizes (a multiple of 128) */
 #define I40E_RXBUFFER_256   256
+#define I40E_RXBUFFER_1536  1536  /* 128B aligned standard Ethernet frame */
 #define I40E_RXBUFFER_2048  2048
-#define I40E_RXBUFFER_3072  3072   /* For FCoE MTU of 2158 */
-#define I40E_RXBUFFER_4096  4096
-#define I40E_RXBUFFER_8192  8192
+#define I40E_RXBUFFER_3072  3072  /* Used for large frames w/ padding */
 #define I40E_MAX_RXBUFFER   9728  /* largest size for single descriptor */
 
 /* NOTE: netdev_alloc_skb reserves up to 64 bytes, NET_IP_ALIGN means we
@@ -128,8 +127,68 @@ enum i40e_dyn_idx_t {
  * i.e. RXBUFFER_512 --> 1216 byte skb (size-2048 slab)
  */
 #define I40E_RX_HDR_SIZE I40E_RXBUFFER_256
+#define I40E_PACKET_HDR_PAD (ETH_HLEN + ETH_FCS_LEN + (VLAN_HLEN * 2))
 #define i40e_rx_desc i40e_32byte_rx_desc
 
+#ifdef HAVE_STRUCT_DMA_ATTRS
+#define I40E_RX_DMA_ATTR NULL
+#else
+#define I40E_RX_DMA_ATTR \
+       (DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_WEAK_ORDERING)
+#endif
+
+/* Attempt to maximize the headroom available for incoming frames.  We
+ * use a 2K buffer for receives and need 1536/1534 to store the data for
+ * the frame.  This leaves us with 512 bytes of room.  From that we need
+ * to deduct the space needed for the shared info and the padding needed
+ * to IP align the frame.
+ *
+ * Note: For cache line sizes 256 or larger this value is going to end
+ *      up negative.  In these cases we should fall back to the legacy
+ *      receive path.
+ */
+#if (PAGE_SIZE < 8192)
+#define I40E_2K_TOO_SMALL_WITH_PADDING \
+((NET_SKB_PAD + I40E_RXBUFFER_1536) > SKB_WITH_OVERHEAD(I40E_RXBUFFER_2048))
+
+static inline int i40e_compute_pad(int rx_buf_len)
+{
+       int page_size, pad_size;
+
+       page_size = ALIGN(rx_buf_len, PAGE_SIZE / 2);
+       pad_size = SKB_WITH_OVERHEAD(page_size) - rx_buf_len;
+
+       return pad_size;
+}
+
+static inline int i40e_skb_pad(void)
+{
+       int rx_buf_len;
+
+       /* If a 2K buffer cannot handle a standard Ethernet frame then
+        * optimize padding for a 3K buffer instead of a 1.5K buffer.
+        *
+        * For a 3K buffer we need to add enough padding to allow for
+        * tailroom due to NET_IP_ALIGN possibly shifting us out of
+        * cache-line alignment.
+        */
+       if (I40E_2K_TOO_SMALL_WITH_PADDING)
+               rx_buf_len = I40E_RXBUFFER_3072 + SKB_DATA_ALIGN(NET_IP_ALIGN);
+       else
+               rx_buf_len = I40E_RXBUFFER_1536;
+
+       /* if needed make room for NET_IP_ALIGN */
+       rx_buf_len -= NET_IP_ALIGN;
+
+       return i40e_compute_pad(rx_buf_len);
+}
+
+#define I40E_SKB_PAD i40e_skb_pad()
+#else
+#define I40E_2K_TOO_SMALL_WITH_PADDING false
+#define I40E_SKB_PAD (NET_SKB_PAD + NET_IP_ALIGN)
+#endif
+
 /**
  * i40e_test_staterr - tests bits in Rx descriptor status and error fields
  * @rx_desc: pointer to receive descriptor (in le64 format)
@@ -252,10 +311,18 @@ struct i40e_tx_buffer {
 };
 
 struct i40e_rx_buffer {
-       struct sk_buff *skb;
        dma_addr_t dma;
+#ifdef CONFIG_I40E_DISABLE_PACKET_SPLIT
+       struct sk_buff *skb;
+#else
        struct page *page;
-       unsigned int page_offset;
+#if (BITS_PER_LONG > 32) || (PAGE_SIZE >= 65536)
+       __u32 page_offset;
+#else
+       __u16 page_offset;
+#endif
+       __u16 pagecnt_bias;
+#endif /* CONFIG_I40E_DISABLE_PACKET_SPLIT */
 };
 
 struct i40e_queue_stats {
@@ -269,7 +336,6 @@ struct i40e_tx_queue_stats {
        u64 tx_done_old;
        u64 tx_linearize;
        u64 tx_force_wb;
-       u64 tx_lost_interrupt;
 };
 
 struct i40e_rx_queue_stats {
@@ -283,6 +349,7 @@ struct i40e_rx_queue_stats {
 enum i40e_ring_state_t {
        __I40E_TX_FDIR_INIT_DONE,
        __I40E_TX_XPS_INIT_DONE,
+       __I40E_RING_STATE_NBITS /* must be last */
 };
 
 /* some useful defines for virtchannel interface, which
@@ -306,7 +373,7 @@ struct i40e_ring {
                struct i40e_tx_buffer *tx_bi;
                struct i40e_rx_buffer *rx_bi;
        };
-       unsigned long state;
+       DECLARE_BITMAP(state, __I40E_RING_STATE_NBITS);
        u16 queue_index;                /* Queue number of ring */
        u8 dcb_tc;                      /* Traffic class of ring */
        u8 __iomem *tail;
@@ -335,7 +402,8 @@ struct i40e_ring {
        u8 packet_stride;
 
        u16 flags;
-#define I40E_TXR_FLAGS_WB_ON_ITR       BIT(0)
+#define I40E_TXR_FLAGS_WB_ON_ITR               BIT(0)
+#define I40E_RXR_FLAGS_BUILD_SKB_ENABLED       BIT(1)
 
        /* stats structs */
        struct i40e_queue_stats stats;
@@ -355,13 +423,35 @@ struct i40e_ring {
 
        struct rcu_head rcu;            /* to avoid race on free */
        u16 next_to_alloc;
+       struct sk_buff *skb;            /* When i40e_clean_rx_ring_irq() must
+                                        * return before it sees the EOP for
+                                        * the current packet, we save that skb
+                                        * here and resume receiving this
+                                        * packet the next time
+                                        * i40e_clean_rx_ring_irq() is called
+                                        * for this ring.
+                                        */
 } ____cacheline_internodealigned_in_smp;
 
+static inline bool ring_uses_build_skb(struct i40e_ring *ring)
+{
+       return !!(ring->flags & I40E_RXR_FLAGS_BUILD_SKB_ENABLED);
+}
+
+static inline void set_ring_build_skb_enabled(struct i40e_ring *ring)
+{
+       ring->flags |= I40E_RXR_FLAGS_BUILD_SKB_ENABLED;
+}
+
+static inline void clear_ring_build_skb_enabled(struct i40e_ring *ring)
+{
+       ring->flags &= ~I40E_RXR_FLAGS_BUILD_SKB_ENABLED;
+}
+
 enum i40e_latency_range {
        I40E_LOWEST_LATENCY = 0,
        I40E_LOW_LATENCY = 1,
        I40E_BULK_LATENCY = 2,
-       I40E_ULTRA_LATENCY = 3,
 };
 
 struct i40e_ring_container {
@@ -369,6 +459,7 @@ struct i40e_ring_container {
        struct i40e_ring *ring;
        unsigned int total_bytes;       /* total bytes processed this int */
        unsigned int total_packets;     /* total packets processed this int */
+       unsigned long last_itr_update;  /* jiffies of last ITR update */
        u16 count;
        enum i40e_latency_range latency_range;
        u16 itr;
@@ -378,6 +469,17 @@ struct i40e_ring_container {
 #define i40e_for_each_ring(pos, head) \
        for (pos = (head).ring; pos != NULL; pos = pos->next)
 
+static inline unsigned int i40e_rx_pg_order(struct i40e_ring *ring)
+{
+#if (PAGE_SIZE < 8192)
+       if (ring->rx_buf_len > (PAGE_SIZE / 2))
+               return 1;
+#endif
+       return 0;
+}
+
+#define i40e_rx_pg_size(_ring) (PAGE_SIZE << i40e_rx_pg_order(_ring))
+
 bool i40e_alloc_rx_buffers(struct i40e_ring *rxr, u16 cleaned_count);
 netdev_tx_t i40e_lan_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
 #if !defined(HAVE_NET_DEVICE_OPS) && defined(HAVE_NETDEV_SELECT_QUEUE)
@@ -391,15 +493,8 @@ int i40e_setup_rx_descriptors(struct i40e_ring *rx_ring);
 void i40e_free_tx_resources(struct i40e_ring *tx_ring);
 void i40e_free_rx_resources(struct i40e_ring *rx_ring);
 int i40e_napi_poll(struct napi_struct *napi, int budget);
-#ifdef I40E_FCOE
-void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
-                struct i40e_tx_buffer *first, u32 tx_flags,
-                const u8 hdr_len, u32 td_cmd, u32 td_offset);
-int i40e_tx_prepare_vlan_flags(struct sk_buff *skb,
-                              struct i40e_ring *tx_ring, u32 *flags);
-#endif
 void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector);
-u32 i40e_get_tx_pending(struct i40e_ring *ring, bool in_sw);
+u32 i40e_get_tx_pending(struct i40e_ring *ring);
 int __i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size);
 bool __i40e_chk_linearize(struct sk_buff *skb);
 
@@ -417,16 +512,6 @@ static inline u32 i40e_get_head(struct i40e_ring *tx_ring)
        return le32_to_cpu(*(volatile __le32 *)head);
 }
 
-/**
- * i40e_rx_is_fcoe - returns true if the rx packet type is FCoE
- * @ptype: the packet type field from rx descriptor write-back
- **/
-static inline bool i40e_rx_is_fcoe(u16 ptype)
-{
-       return (ptype >= I40E_RX_PTYPE_L2_FCOE_PAY3) &&
-              (ptype <= I40E_RX_PTYPE_L2_FCOE_VFT_FCOTHER);
-}
-
 /**
  * i40e_xmit_descriptor_count - calculate number of Tx descriptors needed
  * @skb:     send buffer
similarity index 86%
rename from i40e-dkms/i40e-1.6.42/src/i40e_type.h
rename to i40e-dkms/i40e-2.1.26/src/i40e_type.h
index f20467677b05cd780939530be02e41aa4c18159f..3d37e3aad4952eb04c2adb6a060461430cbc5a76 100644 (file)
@@ -50,6 +50,9 @@
 struct i40e_hw;
 typedef void (*I40E_ADMINQ_CALLBACK)(struct i40e_hw *, struct i40e_aq_desc *);
 
+#ifndef ETH_ALEN
+#define ETH_ALEN       6
+#endif
 /* Data type manipulation macros. */
 
 #define I40E_DESC_UNUSED(R)    \
@@ -75,6 +78,9 @@ enum i40e_debug_mask {
        I40E_DEBUG_DCB                  = 0x00000400,
        I40E_DEBUG_DIAG                 = 0x00000800,
        I40E_DEBUG_FD                   = 0x00001000,
+       I40E_DEBUG_PACKAGE              = 0x00002000,
+
+       I40E_DEBUG_IWARP                = 0x00F00000,
 
        I40E_DEBUG_AQ_MESSAGE           = 0x01000000,
        I40E_DEBUG_AQ_DESCRIPTOR        = 0x02000000,
@@ -112,9 +118,6 @@ enum i40e_debug_mask {
 #define I40E_PHY_LED_MODE_MASK                 0xFFFF
 #define I40E_PHY_LED_MODE_ORIG                 0x80000000
 
-#define I40E_FW_API_VERSION_MINOR_X722 0x0005
-#define I40E_FW_API_VERSION_MINOR_X710 0x0005
-
 /* These are structs for managing the hardware information and the operations.
  * The structures of function pointers are filled out at init time when we
  * know for sure exactly which hardware we're working with.  This gives us the
@@ -168,6 +171,7 @@ enum i40e_vsi_type {
        I40E_VSI_MIRROR = 5,
        I40E_VSI_SRIOV  = 6,
        I40E_VSI_FDIR   = 7,
+       I40E_VSI_IWARP  = 8,
        I40E_VSI_TYPE_UNKNOWN
 };
 
@@ -183,6 +187,7 @@ struct i40e_link_status {
        enum i40e_aq_link_speed link_speed;
        u8 link_info;
        u8 an_info;
+       u8 req_fec_info;
        u8 fec_info;
        u8 ext_info;
        u8 loopback;
@@ -266,15 +271,19 @@ struct i40e_phy_info {
                                             I40E_PHY_TYPE_OFFSET)
 #define I40E_CAP_PHY_TYPE_25GBASE_LR BIT_ULL(I40E_PHY_TYPE_25GBASE_LR + \
                                             I40E_PHY_TYPE_OFFSET)
+#define I40E_CAP_PHY_TYPE_25GBASE_AOC BIT_ULL(I40E_PHY_TYPE_25GBASE_AOC + \
+                                            I40E_PHY_TYPE_OFFSET)
+#define I40E_CAP_PHY_TYPE_25GBASE_ACC BIT_ULL(I40E_PHY_TYPE_25GBASE_ACC + \
+                                            I40E_PHY_TYPE_OFFSET)
 #define I40E_HW_CAP_MAX_GPIO                   30
 enum i40e_acpi_programming_method {
        I40E_ACPI_PROGRAMMING_METHOD_HW_FVL = 0,
        I40E_ACPI_PROGRAMMING_METHOD_AQC_FPK = 1
 };
 
-#define I40E_WOL_SUPPORT_MASK                  1
-#define I40E_ACPI_PROGRAMMING_METHOD_MASK      (1 << 1)
-#define I40E_PROXY_SUPPORT_MASK                        (1 << 2)
+#define I40E_WOL_SUPPORT_MASK                  0x1
+#define I40E_ACPI_PROGRAMMING_METHOD_MASK      0x2
+#define I40E_PROXY_SUPPORT_MASK                        0x4
 
 /* Capabilities of a PF or a VF or the whole device */
 struct i40e_hw_capabilities {
@@ -438,6 +447,18 @@ struct i40e_nvm_access {
        u8 data[1];
 };
 
+/* (Q)SFP module access definitions */
+#define I40E_I2C_EEPROM_DEV_ADDR       0xA0
+#define I40E_I2C_EEPROM_DEV_ADDR2      0xA2
+#define I40E_MODULE_TYPE_ADDR          0x00
+#define I40E_MODULE_REVISION_ADDR      0x01
+#define I40E_MODULE_SFF_8472_COMP      0x5E
+#define I40E_MODULE_SFF_8472_SWAP      0x5C
+#define I40E_MODULE_SFF_ADDR_MODE      0x04
+#define I40E_MODULE_TYPE_QSFP_PLUS     0x0D
+#define I40E_MODULE_TYPE_QSFP28                0x11
+#define I40E_MODULE_QSFP_MAX_LEN       640
+
 /* PCI bus types */
 enum i40e_bus_type {
        i40e_bus_type_unknown = 0,
@@ -612,8 +633,15 @@ struct i40e_hw {
        u16 wol_proxy_vsi_seid;
 
 #define I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE BIT_ULL(0)
+#define I40E_HW_FLAG_802_1AD_CAPABLE        BIT_ULL(1)
+#define I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE  BIT_ULL(2)
        u64 flags;
 
+       /* Used in set switch config AQ command */
+       u16 switch_tag;
+       u16 first_tag;
+       u16 second_tag;
+
        /* debug mask */
        u32 debug_mask;
        char err_str[16];
@@ -1220,25 +1248,6 @@ struct i40e_veb_tc_stats {
        u64 tc_tx_bytes[I40E_MAX_TRAFFIC_CLASS];
 };
 
-#ifdef I40E_FCOE
-/* Statistics collected per function for FCoE */
-struct i40e_fcoe_stats {
-       u64 rx_fcoe_packets;            /* fcoeprc */
-       u64 rx_fcoe_dwords;             /* focedwrc */
-       u64 rx_fcoe_dropped;            /* fcoerpdc */
-       u64 tx_fcoe_packets;            /* fcoeptc */
-       u64 tx_fcoe_dwords;             /* focedwtc */
-       u64 fcoe_bad_fccrc;             /* fcoecrc */
-       u64 fcoe_last_error;            /* fcoelast */
-       u64 fcoe_ddp_count;             /* fcoeddpc */
-};
-
-/* offset to per function FCoE statistics block */
-#define I40E_FCOE_VF_STAT_OFFSET       0
-#define I40E_FCOE_PF_STAT_OFFSET       128
-#define I40E_FCOE_STAT_MAX             (I40E_FCOE_PF_STAT_OFFSET + I40E_MAX_PF)
-
-#endif
 /* Statistics collected by the MAC */
 struct i40e_hw_port_stats {
        /* eth stats collected by the port */
@@ -1330,182 +1339,6 @@ struct i40e_hw_port_stats {
 
 #define I40E_SRRD_SRCTL_ATTEMPTS       100000
 
-#ifdef I40E_FCOE
-/* FCoE Tx context descriptor - Use the i40e_tx_context_desc struct */
-
-enum i40E_fcoe_tx_ctx_desc_cmd_bits {
-       I40E_FCOE_TX_CTX_DESC_OPCODE_SINGLE_SEND        = 0x00, /* 4 BITS */
-       I40E_FCOE_TX_CTX_DESC_OPCODE_TSO_FC_CLASS2      = 0x01, /* 4 BITS */
-       I40E_FCOE_TX_CTX_DESC_OPCODE_TSO_FC_CLASS3      = 0x05, /* 4 BITS */
-       I40E_FCOE_TX_CTX_DESC_OPCODE_ETSO_FC_CLASS2     = 0x02, /* 4 BITS */
-       I40E_FCOE_TX_CTX_DESC_OPCODE_ETSO_FC_CLASS3     = 0x06, /* 4 BITS */
-       I40E_FCOE_TX_CTX_DESC_OPCODE_DWO_FC_CLASS2      = 0x03, /* 4 BITS */
-       I40E_FCOE_TX_CTX_DESC_OPCODE_DWO_FC_CLASS3      = 0x07, /* 4 BITS */
-       I40E_FCOE_TX_CTX_DESC_OPCODE_DDP_CTX_INVL       = 0x08, /* 4 BITS */
-       I40E_FCOE_TX_CTX_DESC_OPCODE_DWO_CTX_INVL       = 0x09, /* 4 BITS */
-       I40E_FCOE_TX_CTX_DESC_RELOFF                    = 0x10,
-       I40E_FCOE_TX_CTX_DESC_CLRSEQ                    = 0x20,
-       I40E_FCOE_TX_CTX_DESC_DIFENA                    = 0x40,
-       I40E_FCOE_TX_CTX_DESC_IL2TAG2                   = 0x80
-};
-
-/* FCoE DIF/DIX Context descriptor */
-struct i40e_fcoe_difdix_context_desc {
-       __le64 flags_buff0_buff1_ref;
-       __le64 difapp_msk_bias;
-};
-
-enum i40e_fcoe_difdix_ctx_desc_flags_bits {
-       /* 2 BITS */
-       I40E_FCOE_DIFDIX_CTX_DESC_RSVD                          = 0x0000,
-       /* 1 BIT  */
-       I40E_FCOE_DIFDIX_CTX_DESC_APPTYPE_TAGCHK                = 0x0000,
-       /* 1 BIT  */
-       I40E_FCOE_DIFDIX_CTX_DESC_APPTYPE_TAGNOTCHK             = 0x0004,
-       /* 2 BITS */
-       I40E_FCOE_DIFDIX_CTX_DESC_GTYPE_OPAQUE                  = 0x0000,
-       /* 2 BITS */
-       I40E_FCOE_DIFDIX_CTX_DESC_GTYPE_CHKINTEGRITY            = 0x0008,
-       /* 2 BITS */
-       I40E_FCOE_DIFDIX_CTX_DESC_GTYPE_CHKINTEGRITY_APPTAG     = 0x0010,
-       /* 2 BITS */
-       I40E_FCOE_DIFDIX_CTX_DESC_GTYPE_CHKINTEGRITY_APPREFTAG  = 0x0018,
-       /* 2 BITS */
-       I40E_FCOE_DIFDIX_CTX_DESC_REFTYPE_CNST                  = 0x0000,
-       /* 2 BITS */
-       I40E_FCOE_DIFDIX_CTX_DESC_REFTYPE_INC1BLK               = 0x0020,
-       /* 2 BITS */
-       I40E_FCOE_DIFDIX_CTX_DESC_REFTYPE_APPTAG                = 0x0040,
-       /* 2 BITS */
-       I40E_FCOE_DIFDIX_CTX_DESC_REFTYPE_RSVD                  = 0x0060,
-       /* 1 BIT  */
-       I40E_FCOE_DIFDIX_CTX_DESC_DIXMODE_XSUM                  = 0x0000,
-       /* 1 BIT  */
-       I40E_FCOE_DIFDIX_CTX_DESC_DIXMODE_CRC                   = 0x0080,
-       /* 2 BITS */
-       I40E_FCOE_DIFDIX_CTX_DESC_DIFHOST_UNTAG                 = 0x0000,
-       /* 2 BITS */
-       I40E_FCOE_DIFDIX_CTX_DESC_DIFHOST_BUF                   = 0x0100,
-       /* 2 BITS */
-       I40E_FCOE_DIFDIX_CTX_DESC_DIFHOST_RSVD                  = 0x0200,
-       /* 2 BITS */
-       I40E_FCOE_DIFDIX_CTX_DESC_DIFHOST_EMBDTAGS              = 0x0300,
-       /* 1 BIT  */
-       I40E_FCOE_DIFDIX_CTX_DESC_DIFLAN_UNTAG                  = 0x0000,
-       /* 1 BIT  */
-       I40E_FCOE_DIFDIX_CTX_DESC_DIFLAN_TAG                    = 0x0400,
-       /* 1 BIT */
-       I40E_FCOE_DIFDIX_CTX_DESC_DIFBLK_512B                   = 0x0000,
-       /* 1 BIT */
-       I40E_FCOE_DIFDIX_CTX_DESC_DIFBLK_4K                     = 0x0800
-};
-
-/* FCoE DIF/DIX Buffers descriptor */
-struct i40e_fcoe_difdix_buffers_desc {
-       __le64 buff_addr0;
-       __le64 buff_addr1;
-};
-
-/* FCoE DDP Context descriptor */
-struct i40e_fcoe_ddp_context_desc {
-       __le64 rsvd;
-       __le64 type_cmd_foff_lsize;
-};
-
-#define I40E_FCOE_DDP_CTX_QW1_DTYPE_SHIFT      0
-#define I40E_FCOE_DDP_CTX_QW1_DTYPE_MASK       (0xFULL << \
-                                       I40E_FCOE_DDP_CTX_QW1_DTYPE_SHIFT)
-
-#define I40E_FCOE_DDP_CTX_QW1_CMD_SHIFT        4
-#define I40E_FCOE_DDP_CTX_QW1_CMD_MASK (0xFULL << \
-                                        I40E_FCOE_DDP_CTX_QW1_CMD_SHIFT)
-
-enum i40e_fcoe_ddp_ctx_desc_cmd_bits {
-       I40E_FCOE_DDP_CTX_DESC_BSIZE_512B       = 0x00, /* 2 BITS */
-       I40E_FCOE_DDP_CTX_DESC_BSIZE_4K         = 0x01, /* 2 BITS */
-       I40E_FCOE_DDP_CTX_DESC_BSIZE_8K         = 0x02, /* 2 BITS */
-       I40E_FCOE_DDP_CTX_DESC_BSIZE_16K        = 0x03, /* 2 BITS */
-       I40E_FCOE_DDP_CTX_DESC_DIFENA           = 0x04, /* 1 BIT  */
-       I40E_FCOE_DDP_CTX_DESC_LASTSEQH         = 0x08, /* 1 BIT  */
-};
-
-#define I40E_FCOE_DDP_CTX_QW1_FOFF_SHIFT       16
-#define I40E_FCOE_DDP_CTX_QW1_FOFF_MASK        (0x3FFFULL << \
-                                        I40E_FCOE_DDP_CTX_QW1_FOFF_SHIFT)
-
-#define I40E_FCOE_DDP_CTX_QW1_LSIZE_SHIFT      32
-#define I40E_FCOE_DDP_CTX_QW1_LSIZE_MASK       (0x3FFFULL << \
-                                       I40E_FCOE_DDP_CTX_QW1_LSIZE_SHIFT)
-
-/* FCoE DDP/DWO Queue Context descriptor */
-struct i40e_fcoe_queue_context_desc {
-       __le64 dmaindx_fbase;           /* 0:11 DMAINDX, 12:63 FBASE */
-       __le64 flen_tph;                /* 0:12 FLEN, 13:15 TPH */
-};
-
-#define I40E_FCOE_QUEUE_CTX_QW0_DMAINDX_SHIFT  0
-#define I40E_FCOE_QUEUE_CTX_QW0_DMAINDX_MASK   (0xFFFULL << \
-                                       I40E_FCOE_QUEUE_CTX_QW0_DMAINDX_SHIFT)
-
-#define I40E_FCOE_QUEUE_CTX_QW0_FBASE_SHIFT    12
-#define I40E_FCOE_QUEUE_CTX_QW0_FBASE_MASK     (0xFFFFFFFFFFFFFULL << \
-                                       I40E_FCOE_QUEUE_CTX_QW0_FBASE_SHIFT)
-
-#define I40E_FCOE_QUEUE_CTX_QW1_FLEN_SHIFT     0
-#define I40E_FCOE_QUEUE_CTX_QW1_FLEN_MASK      (0x1FFFULL << \
-                                       I40E_FCOE_QUEUE_CTX_QW1_FLEN_SHIFT)
-
-#define I40E_FCOE_QUEUE_CTX_QW1_TPH_SHIFT      13
-#define I40E_FCOE_QUEUE_CTX_QW1_TPH_MASK       (0x7ULL << \
-                                       I40E_FCOE_QUEUE_CTX_QW1_FLEN_SHIFT)
-
-enum i40e_fcoe_queue_ctx_desc_tph_bits {
-       I40E_FCOE_QUEUE_CTX_DESC_TPHRDESC       = 0x1,
-       I40E_FCOE_QUEUE_CTX_DESC_TPHDATA        = 0x2
-};
-
-#define I40E_FCOE_QUEUE_CTX_QW1_RECIPE_SHIFT   30
-#define I40E_FCOE_QUEUE_CTX_QW1_RECIPE_MASK    (0x3ULL << \
-                                       I40E_FCOE_QUEUE_CTX_QW1_RECIPE_SHIFT)
-
-/* FCoE DDP/DWO Filter Context descriptor */
-struct i40e_fcoe_filter_context_desc {
-       __le32 param;
-       __le16 seqn;
-
-       /* 48:51(0:3) RSVD, 52:63(4:15) DMAINDX */
-       __le16 rsvd_dmaindx;
-
-       /* 0:7 FLAGS, 8:52 RSVD, 53:63 LANQ */
-       __le64 flags_rsvd_lanq;
-};
-
-#define I40E_FCOE_FILTER_CTX_QW0_DMAINDX_SHIFT 4
-#define I40E_FCOE_FILTER_CTX_QW0_DMAINDX_MASK  (0xFFF << \
-                                       I40E_FCOE_FILTER_CTX_QW0_DMAINDX_SHIFT)
-
-enum i40e_fcoe_filter_ctx_desc_flags_bits {
-       I40E_FCOE_FILTER_CTX_DESC_CTYP_DDP      = 0x00,
-       I40E_FCOE_FILTER_CTX_DESC_CTYP_DWO      = 0x01,
-       I40E_FCOE_FILTER_CTX_DESC_ENODE_INIT    = 0x00,
-       I40E_FCOE_FILTER_CTX_DESC_ENODE_RSP     = 0x02,
-       I40E_FCOE_FILTER_CTX_DESC_FC_CLASS2     = 0x00,
-       I40E_FCOE_FILTER_CTX_DESC_FC_CLASS3     = 0x04
-};
-
-#define I40E_FCOE_FILTER_CTX_QW1_FLAGS_SHIFT   0
-#define I40E_FCOE_FILTER_CTX_QW1_FLAGS_MASK    (0xFFULL << \
-                                       I40E_FCOE_FILTER_CTX_QW1_FLAGS_SHIFT)
-
-#define I40E_FCOE_FILTER_CTX_QW1_PCTYPE_SHIFT     8
-#define I40E_FCOE_FILTER_CTX_QW1_PCTYPE_MASK      (0x3FULL << \
-                       I40E_FCOE_FILTER_CTX_QW1_PCTYPE_SHIFT)
-
-#define I40E_FCOE_FILTER_CTX_QW1_LANQINDX_SHIFT     53
-#define I40E_FCOE_FILTER_CTX_QW1_LANQINDX_MASK      (0x7FFULL << \
-                       I40E_FCOE_FILTER_CTX_QW1_LANQINDX_SHIFT)
-
-#endif /* I40E_FCOE */
 enum i40e_switch_element_types {
        I40E_SWITCH_ELEMENT_TYPE_MAC    = 1,
        I40E_SWITCH_ELEMENT_TYPE_PF     = 2,
@@ -1668,4 +1501,106 @@ struct i40e_lldp_variables {
 #define I40E_FLEX_56_MASK              (0x1ULL << I40E_FLEX_56_SHIFT)
 #define I40E_FLEX_57_SHIFT             6
 #define I40E_FLEX_57_MASK              (0x1ULL << I40E_FLEX_57_SHIFT)
+
+/* Version format for Dynamic Device Personalization(DDP) */
+struct i40e_ddp_version {
+       u8 major;
+       u8 minor;
+       u8 update;
+       u8 draft;
+};
+
+#define I40E_DDP_NAME_SIZE     32
+
+/* Package header */
+struct i40e_package_header {
+       struct i40e_ddp_version version;
+       u32 segment_count;
+       u32 segment_offset[1];
+};
+
+/* Generic segment header */
+struct i40e_generic_seg_header {
+#define SEGMENT_TYPE_METADATA  0x00000001
+#define SEGMENT_TYPE_NOTES     0x00000002
+#define SEGMENT_TYPE_I40E      0x00000011
+#define SEGMENT_TYPE_X722      0x00000012
+       u32 type;
+       struct i40e_ddp_version version;
+       u32 size;
+       char name[I40E_DDP_NAME_SIZE];
+};
+
+struct i40e_metadata_segment {
+       struct i40e_generic_seg_header header;
+       struct i40e_ddp_version version;
+#define I40E_DDP_TRACKID_RDONLY                0
+#define I40E_DDP_TRACKID_INVALID       0xFFFFFFFF
+       u32 track_id;
+       char name[I40E_DDP_NAME_SIZE];
+};
+
+struct i40e_device_id_entry {
+       u32 vendor_dev_id;
+       u32 sub_vendor_dev_id;
+};
+
+struct i40e_profile_segment {
+       struct i40e_generic_seg_header header;
+       struct i40e_ddp_version version;
+       char name[I40E_DDP_NAME_SIZE];
+       u32 device_table_count;
+       struct i40e_device_id_entry device_table[1];
+};
+
+struct i40e_section_table {
+       u32 section_count;
+       u32 section_offset[1];
+};
+
+struct i40e_profile_section_header {
+       u16 tbl_size;
+       u16 data_end;
+       struct {
+#define SECTION_TYPE_INFO      0x00000010
+#define SECTION_TYPE_MMIO      0x00000800
+#define SECTION_TYPE_RB_MMIO   0x00001800
+#define SECTION_TYPE_AQ                0x00000801
+#define SECTION_TYPE_RB_AQ     0x00001801
+#define SECTION_TYPE_NOTE      0x80000000
+#define SECTION_TYPE_NAME      0x80000001
+#define SECTION_TYPE_PROTO     0x80000002
+#define SECTION_TYPE_PCTYPE    0x80000003
+#define SECTION_TYPE_PTYPE     0x80000004
+               u32 type;
+               u32 offset;
+               u32 size;
+       } section;
+};
+
+struct i40e_profile_tlv_section_record {
+       u8 rtype;
+       u8 type;
+       u16 len;
+       u8 data[12];
+};
+
+/* Generic AQ section in proflie */
+struct i40e_profile_aq_section {
+       u16 opcode;
+       u16 flags;
+       u8  param[16];
+       u16 datalen;
+       u8  data[1];
+};
+
+struct i40e_profile_info {
+       u32 track_id;
+       struct i40e_ddp_version version;
+       u8 op;
+#define I40E_DDP_ADD_TRACKID           0x01
+#define I40E_DDP_REMOVE_TRACKID        0x02
+       u8 reserved[7];
+       u8 name[I40E_DDP_NAME_SIZE];
+};
 #endif /* _I40E_TYPE_H_ */
similarity index 70%
rename from i40e-dkms/i40e-1.6.42/src/i40e_virtchnl_pf.c
rename to i40e-dkms/i40e-2.1.26/src/i40e_virtchnl_pf.c
index f3251475cc9b0933ce5dabebf07cf6ab20ac7e4e..8270b67e759e36d541426ed25d72446b6cd8482d 100644 (file)
@@ -36,7 +36,7 @@
  * send a message to all VFs on a given PF
  **/
 static void i40e_vc_vf_broadcast(struct i40e_pf *pf,
-                                enum i40e_virtchnl_ops v_opcode,
+                                enum virtchnl_ops v_opcode,
                                 i40e_status v_retval, u8 *msg,
                                 u16 msglen)
 {
@@ -47,8 +47,8 @@ static void i40e_vc_vf_broadcast(struct i40e_pf *pf,
        for (i = 0; i < pf->num_alloc_vfs; i++, vf++) {
                int abs_vf_id = vf->vf_id + (int)hw->func_caps.vf_base_id;
                /* Not all vfs are enabled so skip the ones that are not */
-               if (!test_bit(I40E_VF_STAT_INIT, &vf->vf_states) &&
-                   !test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states))
+               if (!test_bit(I40E_VF_STATE_INIT, &vf->vf_states) &&
+                   !test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states))
                        continue;
 
                /* Ignore return value on purpose - a given VF may fail, but
@@ -67,14 +67,14 @@ static void i40e_vc_vf_broadcast(struct i40e_pf *pf,
  **/
 static void i40e_vc_notify_vf_link_state(struct i40e_vf *vf)
 {
-       struct i40e_virtchnl_pf_event pfe;
+       struct virtchnl_pf_event pfe;
        struct i40e_pf *pf = vf->pf;
        struct i40e_hw *hw = &pf->hw;
        struct i40e_link_status *ls = &pf->hw.phy.link_info;
        int abs_vf_id = vf->vf_id + (int)hw->func_caps.vf_base_id;
 
-       pfe.event = I40E_VIRTCHNL_EVENT_LINK_CHANGE;
-       pfe.severity = I40E_PF_EVENT_SEVERITY_INFO;
+       pfe.event = VIRTCHNL_EVENT_LINK_CHANGE;
+       pfe.severity = PF_EVENT_SEVERITY_INFO;
 #ifdef HAVE_NDO_SET_VF_LINK_STATE
        if (vf->link_forced) {
                pfe.event_data.link_event.link_status = vf->link_up;
@@ -84,11 +84,12 @@ static void i40e_vc_notify_vf_link_state(struct i40e_vf *vf)
 #endif
                pfe.event_data.link_event.link_status =
                        ls->link_info & I40E_AQ_LINK_UP;
-               pfe.event_data.link_event.link_speed = ls->link_speed;
+               pfe.event_data.link_event.link_speed =
+                       (enum virtchnl_link_speed)ls->link_speed;
 #ifdef HAVE_NDO_SET_VF_LINK_STATE
        }
 #endif
-       i40e_aq_send_msg_to_vf(hw, abs_vf_id, I40E_VIRTCHNL_OP_EVENT,
+       i40e_aq_send_msg_to_vf(hw, abs_vf_id, VIRTCHNL_OP_EVENT,
                               I40E_SUCCESS, (u8 *)&pfe, sizeof(pfe), NULL);
 }
 
@@ -114,12 +115,12 @@ void i40e_vc_notify_link_state(struct i40e_pf *pf)
  **/
 void i40e_vc_notify_reset(struct i40e_pf *pf)
 {
-       struct i40e_virtchnl_pf_event pfe;
+       struct virtchnl_pf_event pfe;
 
-       pfe.event = I40E_VIRTCHNL_EVENT_RESET_IMPENDING;
-       pfe.severity = I40E_PF_EVENT_SEVERITY_CERTAIN_DOOM;
-       i40e_vc_vf_broadcast(pf, I40E_VIRTCHNL_OP_EVENT, I40E_SUCCESS,
-                            (u8 *)&pfe, sizeof(struct i40e_virtchnl_pf_event));
+       pfe.event = VIRTCHNL_EVENT_RESET_IMPENDING;
+       pfe.severity = PF_EVENT_SEVERITY_CERTAIN_DOOM;
+       i40e_vc_vf_broadcast(pf, VIRTCHNL_OP_EVENT, I40E_SUCCESS,
+                            (u8 *)&pfe, sizeof(struct virtchnl_pf_event));
 }
 
 /**
@@ -130,7 +131,7 @@ void i40e_vc_notify_reset(struct i40e_pf *pf)
  **/
 void i40e_vc_notify_vf_reset(struct i40e_vf *vf)
 {
-       struct i40e_virtchnl_pf_event pfe;
+       struct virtchnl_pf_event pfe;
        int abs_vf_id;
 
        /* validate the request */
@@ -138,31 +139,46 @@ void i40e_vc_notify_vf_reset(struct i40e_vf *vf)
                return;
 
        /* verify if the VF is in either init or active before proceeding */
-       if (!test_bit(I40E_VF_STAT_INIT, &vf->vf_states) &&
-           !test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states))
+       if (!test_bit(I40E_VF_STATE_INIT, &vf->vf_states) &&
+           !test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states))
                return;
 
        abs_vf_id = vf->vf_id + (int)vf->pf->hw.func_caps.vf_base_id;
 
-       pfe.event = I40E_VIRTCHNL_EVENT_RESET_IMPENDING;
-       pfe.severity = I40E_PF_EVENT_SEVERITY_CERTAIN_DOOM;
-       i40e_aq_send_msg_to_vf(&vf->pf->hw, abs_vf_id, I40E_VIRTCHNL_OP_EVENT,
+       pfe.event = VIRTCHNL_EVENT_RESET_IMPENDING;
+       pfe.severity = PF_EVENT_SEVERITY_CERTAIN_DOOM;
+       i40e_aq_send_msg_to_vf(&vf->pf->hw, abs_vf_id, VIRTCHNL_OP_EVENT,
                               I40E_SUCCESS, (u8 *)&pfe,
-                              sizeof(struct i40e_virtchnl_pf_event), NULL);
+                              sizeof(struct virtchnl_pf_event), NULL);
 }
 /***********************misc routines*****************************/
 
 /**
  * i40e_vc_disable_vf
- * @pf: pointer to the PF info
  * @vf: pointer to the VF info
  *
- * Disable the VF through a SW reset
+ * Disable the VF through a SW reset.
  **/
-static inline void i40e_vc_disable_vf(struct i40e_pf *pf, struct i40e_vf *vf)
+static inline void i40e_vc_disable_vf(struct i40e_vf *vf)
 {
+       int i;
+
        i40e_vc_notify_vf_reset(vf);
-       i40e_reset_vf(vf, false);
+
+       /* We want to ensure that an actual reset occurs initiated after this
+        * function was called. However, we do not want to wait forever, so
+        * we'll give a reasonable time and print a message if we failed to
+        * ensure a reset.
+        */
+       for (i = 0; i < 20; i++) {
+               if (i40e_reset_vf(vf, false))
+                       return;
+               usleep_range(10000, 20000);
+       }
+
+       dev_warn(&vf->pf->pdev->dev,
+                "Failed to initiate reset for VF %d after 200 milliseconds\n",
+                vf->vf_id);
 }
 
 /**
@@ -229,7 +245,7 @@ static u16 i40e_vc_get_pf_queue_id(struct i40e_vf *vf, u16 vsi_id,
        u16 pf_queue_id = I40E_QUEUE_END_OF_LIST;
 
        if (!vsi)
-               return I40E_QUEUE_END_OF_LIST;
+               return pf_queue_id;
 
        if (le16_to_cpu(vsi->info.mapping_flags) &
            I40E_AQ_VSI_QUE_MAP_NONCONTIG)
@@ -251,7 +267,7 @@ static u16 i40e_vc_get_pf_queue_id(struct i40e_vf *vf, u16 vsi_id,
  * configure irq link list from the map
  **/
 static void i40e_config_irq_link_list(struct i40e_vf *vf, u16 vsi_id,
-                                     struct i40e_virtchnl_vector_map *vecmap)
+                                     struct virtchnl_vector_map *vecmap)
 {
        unsigned long linklistmap = 0, tempmap;
        struct i40e_pf *pf = vf->pf;
@@ -278,16 +294,14 @@ static void i40e_config_irq_link_list(struct i40e_vf *vf, u16 vsi_id,
        }
        tempmap = vecmap->rxq_map;
        for_each_set_bit(vsi_queue_id, &tempmap, I40E_MAX_VSI_QP) {
-               linklistmap |= (1 <<
-                               (I40E_VIRTCHNL_SUPPORTED_QTYPES *
-                                vsi_queue_id));
+               linklistmap |= (BIT(I40E_VIRTCHNL_SUPPORTED_QTYPES *
+                                   vsi_queue_id));
        }
 
        tempmap = vecmap->txq_map;
        for_each_set_bit(vsi_queue_id, &tempmap, I40E_MAX_VSI_QP) {
-               linklistmap |= (1 <<
-                               (I40E_VIRTCHNL_SUPPORTED_QTYPES * vsi_queue_id
-                                + 1));
+               linklistmap |= (BIT(I40E_VIRTCHNL_SUPPORTED_QTYPES *
+                                    vsi_queue_id + 1));
        }
 
        next_q = find_first_bit(&linklistmap,
@@ -341,7 +355,7 @@ static void i40e_config_irq_link_list(struct i40e_vf *vf, u16 vsi_id,
        /* if the vf is running in polling mode and using interrupt zero,
         * need to disable auto-mask on enabling zero interrupt for VFs.
         */
-       if ((vf->driver_caps & I40E_VIRTCHNL_VF_OFFLOAD_RX_POLLING) &&
+       if ((vf->driver_caps & VIRTCHNL_VF_OFFLOAD_RX_POLLING) &&
            (vector_id == 0)) {
                reg = rd32(hw, I40E_GLINT_CTL);
                if (!(reg & I40E_GLINT_CTL_DIS_AUTOMASK_VF0_MASK)) {
@@ -354,6 +368,136 @@ irq_list_done:
        i40e_flush(hw);
 }
 
+/**
+ * i40e_release_iwarp_qvlist
+ * @vf: pointer to the VF.
+ *
+ **/
+static void i40e_release_iwarp_qvlist(struct i40e_vf *vf)
+{
+       struct i40e_pf *pf = vf->pf;
+       struct virtchnl_iwarp_qvlist_info *qvlist_info = vf->qvlist_info;
+       u32 msix_vf;
+       u32 i;
+
+       if (!vf->qvlist_info)
+               return;
+
+       msix_vf = pf->hw.func_caps.num_msix_vectors_vf;
+       for (i = 0; i < qvlist_info->num_vectors; i++) {
+               struct virtchnl_iwarp_qv_info *qv_info;
+               u32 next_q_index, next_q_type;
+               struct i40e_hw *hw = &pf->hw;
+               u32 v_idx, reg_idx, reg;
+
+               qv_info = &qvlist_info->qv_info[i];
+               if (!qv_info)
+                       continue;
+               v_idx = qv_info->v_idx;
+               if (qv_info->ceq_idx != I40E_QUEUE_INVALID_IDX) {
+                       /* Figure out the queue after CEQ and make that the
+                        * first queue.
+                        */
+                       reg_idx = (msix_vf - 1) * vf->vf_id + qv_info->ceq_idx;
+                       reg = rd32(hw, I40E_VPINT_CEQCTL(reg_idx));
+                       next_q_index = (reg & I40E_VPINT_CEQCTL_NEXTQ_INDX_MASK)
+                                       >> I40E_VPINT_CEQCTL_NEXTQ_INDX_SHIFT;
+                       next_q_type = (reg & I40E_VPINT_CEQCTL_NEXTQ_TYPE_MASK)
+                                       >> I40E_VPINT_CEQCTL_NEXTQ_TYPE_SHIFT;
+
+                       reg_idx = ((msix_vf - 1) * vf->vf_id) + (v_idx - 1);
+                       reg = (next_q_index &
+                              I40E_VPINT_LNKLSTN_FIRSTQ_INDX_MASK) |
+                              (next_q_type <<
+                              I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT);
+
+                       wr32(hw, I40E_VPINT_LNKLSTN(reg_idx), reg);
+               }
+       }
+       kfree(vf->qvlist_info);
+       vf->qvlist_info = NULL;
+}
+
+/**
+ * i40e_config_iwarp_qvlist
+ * @vf: pointer to the VF info
+ * @qvlist_info: queue and vector list
+ *
+ * Return 0 on success or < 0 on error
+ **/
+static int i40e_config_iwarp_qvlist(struct i40e_vf *vf,
+                           struct virtchnl_iwarp_qvlist_info *qvlist_info)
+{
+       struct i40e_pf *pf = vf->pf;
+       struct i40e_hw *hw = &pf->hw;
+       struct virtchnl_iwarp_qv_info *qv_info;
+       u32 v_idx, i, reg_idx, reg;
+       u32 next_q_idx, next_q_type;
+       u32 msix_vf, size;
+
+       size = sizeof(struct virtchnl_iwarp_qvlist_info) +
+              (sizeof(struct virtchnl_iwarp_qv_info) *
+                                               (qvlist_info->num_vectors - 1));
+       vf->qvlist_info = kzalloc(size, GFP_KERNEL);
+       vf->qvlist_info->num_vectors = qvlist_info->num_vectors;
+
+       msix_vf = pf->hw.func_caps.num_msix_vectors_vf;
+       for (i = 0; i < qvlist_info->num_vectors; i++) {
+               qv_info = &qvlist_info->qv_info[i];
+               if (!qv_info)
+                       continue;
+               v_idx = qv_info->v_idx;
+
+               /* Validate vector id belongs to this vf */
+               if (!i40e_vc_isvalid_vector_id(vf, v_idx))
+                       goto err;
+
+               vf->qvlist_info->qv_info[i] = *qv_info;
+
+               reg_idx = ((msix_vf - 1) * vf->vf_id) + (v_idx - 1);
+               /* We might be sharing the interrupt, so get the first queue
+                * index and type, push it down the list by adding the new
+                * queue on top. Also link it with the new queue in CEQCTL.
+                */
+               reg = rd32(hw, I40E_VPINT_LNKLSTN(reg_idx));
+               next_q_idx = ((reg & I40E_VPINT_LNKLSTN_FIRSTQ_INDX_MASK) >>
+                               I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT);
+               next_q_type = ((reg & I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_MASK) >>
+                               I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT);
+
+               if (qv_info->ceq_idx != I40E_QUEUE_INVALID_IDX) {
+                       reg_idx = (msix_vf - 1) * vf->vf_id + qv_info->ceq_idx;
+                       reg = (I40E_VPINT_CEQCTL_CAUSE_ENA_MASK |
+                       (v_idx << I40E_VPINT_CEQCTL_MSIX_INDX_SHIFT) |
+                       (qv_info->itr_idx << I40E_VPINT_CEQCTL_ITR_INDX_SHIFT) |
+                       (next_q_type << I40E_VPINT_CEQCTL_NEXTQ_TYPE_SHIFT) |
+                       (next_q_idx << I40E_VPINT_CEQCTL_NEXTQ_INDX_SHIFT));
+                       wr32(hw, I40E_VPINT_CEQCTL(reg_idx), reg);
+
+                       reg_idx = ((msix_vf - 1) * vf->vf_id) + (v_idx - 1);
+                       reg = (qv_info->ceq_idx &
+                              I40E_VPINT_LNKLSTN_FIRSTQ_INDX_MASK) |
+                              (I40E_QUEUE_TYPE_PE_CEQ <<
+                              I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT);
+                       wr32(hw, I40E_VPINT_LNKLSTN(reg_idx), reg);
+               }
+
+               if (qv_info->aeq_idx != I40E_QUEUE_INVALID_IDX) {
+                       reg = (I40E_VPINT_AEQCTL_CAUSE_ENA_MASK |
+                       (v_idx << I40E_VPINT_AEQCTL_MSIX_INDX_SHIFT) |
+                       (qv_info->itr_idx << I40E_VPINT_AEQCTL_ITR_INDX_SHIFT));
+
+                       wr32(hw, I40E_VPINT_AEQCTL(vf->vf_id), reg);
+               }
+       }
+
+       return 0;
+err:
+       kfree(vf->qvlist_info);
+       vf->qvlist_info = NULL;
+       return -EINVAL;
+}
+
 /**
  * i40e_config_vsi_tx_queue
  * @vf: pointer to the VF info
@@ -365,7 +509,7 @@ irq_list_done:
  **/
 static int i40e_config_vsi_tx_queue(struct i40e_vf *vf, u16 vsi_id,
                                    u16 vsi_queue_id,
-                                   struct i40e_virtchnl_txq_info *info)
+                                   struct virtchnl_txq_info *info)
 {
        struct i40e_pf *pf = vf->pf;
        struct i40e_hw *hw = &pf->hw;
@@ -442,7 +586,7 @@ error_context:
  **/
 static int i40e_config_vsi_rx_queue(struct i40e_vf *vf, u16 vsi_id,
                                    u16 vsi_queue_id,
-                                   struct i40e_virtchnl_rxq_info *info)
+                                   struct virtchnl_rxq_info *info)
 {
        struct i40e_pf *pf = vf->pf;
        struct i40e_hw *hw = &pf->hw;
@@ -682,6 +826,19 @@ static void i40e_free_vf_res(struct i40e_vf *vf)
        u32 reg_idx, reg;
        int i, msix_vf;
 
+       /* Start by disabling VF's configuration API to prevent the OS from
+        * accessing the VF's VSI after it's freed / invalidated.
+        */
+       clear_bit(I40E_VF_STATE_INIT, &vf->vf_states);
+
+       /* It's possible the VF had requeuested more queues than the default so
+        * do the accounting here when we're about to free them.
+        */
+       if (vf->num_queue_pairs > I40E_DEFAULT_QUEUES_PER_VF) {
+               pf->queues_left +=
+                       vf->num_queue_pairs - I40E_DEFAULT_QUEUES_PER_VF;
+       }
+
        /* free vsi & disconnect it from the parent uplink */
        if (vf->lan_vsi_idx) {
                i40e_vsi_release(pf->vsi[vf->lan_vsi_idx]);
@@ -718,12 +875,10 @@ static void i40e_free_vf_res(struct i40e_vf *vf)
                wr32(hw, reg_idx, reg);
                i40e_flush(hw);
        }
-       /* reset some of the state varibles keeping
-        * track of the resources
-        */
+       /* reset some of the state variables keeping track of the resources */
        vf->num_queue_pairs = 0;
-       vf->vf_states = 0;
-       clear_bit(I40E_VF_STAT_INIT, &vf->vf_states);
+       clear_bit(I40E_VF_STATE_MC_PROMISC, &vf->vf_states);
+       clear_bit(I40E_VF_STATE_UC_PROMISC, &vf->vf_states);
 }
 
 /**
@@ -738,16 +893,38 @@ static int i40e_alloc_vf_res(struct i40e_vf *vf)
        int total_queue_pairs = 0;
        int ret;
 
+       if (vf->num_req_queues &&
+           vf->num_req_queues <= pf->queues_left + I40E_DEFAULT_QUEUES_PER_VF)
+               pf->num_vf_qps = vf->num_req_queues;
+       else
+               pf->num_vf_qps = I40E_DEFAULT_QUEUES_PER_VF;
+
        /* allocate hw vsi context & associated resources */
        ret = i40e_alloc_vsi_res(vf, I40E_VSI_SRIOV);
        if (ret)
                goto error_alloc;
        total_queue_pairs += pf->vsi[vf->lan_vsi_idx]->alloc_queue_pairs;
 
+       /* We account for each VF to get a default number of queue pairs.  If
+        * the VF has now requested more, we need to account for that to make
+        * certain we never request more queues than we actually have left in
+        * HW.
+        */
+       if (total_queue_pairs > I40E_DEFAULT_QUEUES_PER_VF)
+               pf->queues_left -=
+                       total_queue_pairs - I40E_DEFAULT_QUEUES_PER_VF;
+
        if (vf->trusted)
                set_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps);
        else
                clear_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps);
+       /* if iwarp, then use an iwarp PF callback to allocate
+        * iwarp resources
+        */
+#if 0
+       if (test_bit(VIRTCHNL_VF_CAP_IWARP, &vf->vf_caps))
+               /* TODO: */
+#endif
 
        /* store the total qps number for the runtime
         * VF req validation
@@ -755,7 +932,7 @@ static int i40e_alloc_vf_res(struct i40e_vf *vf)
        vf->num_queue_pairs = total_queue_pairs;
 
        /* VF is now completely initialized */
-       set_bit(I40E_VF_STAT_INIT, &vf->vf_states);
+       set_bit(I40E_VF_STATE_INIT, &vf->vf_states);
 
 error_alloc:
        if (ret)
@@ -794,25 +971,30 @@ static int i40e_quiesce_vf_pci(struct i40e_vf *vf)
 }
 
 /**
- * i40e_reset_vf
+ * i40e_trigger_vf_reset
  * @vf: pointer to the VF structure
  * @flr: VFLR was issued or not
  *
- * reset the VF
+ * Trigger hardware to start a reset for a particular VF. Expects the caller
+ * to wait the proper amount of time to allow hardware to reset the VF before
+ * it cleans up and restores VF functionality.
  **/
-void i40e_reset_vf(struct i40e_vf *vf, bool flr)
+static void i40e_trigger_vf_reset(struct i40e_vf *vf, bool flr)
 {
        struct i40e_pf *pf = vf->pf;
        struct i40e_hw *hw = &pf->hw;
        u32 reg, reg_idx, bit_idx;
-       bool rsd = false;
-       int i;
-
-       if (test_and_set_bit(__I40E_VF_DISABLE, &pf->state))
-               return;
 
        /* warn the VF */
-       clear_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states);
+       clear_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states);
+
+       /* Disable VF's configuration API during reset. The flag is re-enabled
+        * in i40e_alloc_vf_res(), when it's safe again to access VF's VSI.
+        * It's normally disabled in i40e_free_vf_res(), but it's safer
+        * to do it earlier to give some time to finish to any VF config
+        * functions that may still be running at this point.
+        */
+       clear_bit(I40E_VF_STATE_INIT, &vf->vf_states);
 
        /* In the case of a VFLR, the HW has already reset the VF and we
         * just need to clean up, so don't hit the VFRTRIG register.
@@ -832,6 +1014,81 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr)
        if (i40e_quiesce_vf_pci(vf))
                dev_err(&pf->pdev->dev, "VF %d PCI transactions stuck\n",
                        vf->vf_id);
+}
+
+/**
+ * i40e_cleanup_reset_vf
+ * @vf: pointer to the VF structure
+ *
+ * Cleanup a VF after the hardware reset is finished. Expects the caller to
+ * have verified whether the reset is finished properly, and ensure the
+ * minimum amount of wait time has passed.
+ **/
+static void i40e_cleanup_reset_vf(struct i40e_vf *vf)
+{
+       struct i40e_pf *pf = vf->pf;
+       struct i40e_hw *hw = &pf->hw;
+       u32 reg;
+
+       /* free VF resources to begin resetting the VSI state */
+       i40e_free_vf_res(vf);
+
+       /* Enable hardware by clearing the reset bit in the VPGEN_VFRTRIG reg.
+        * By doing this we allow HW to access VF memory at any point. If we
+        * did it any sooner, HW could access memory while it was being freed
+        * in i40e_free_vf_res(), causing an IOMMU fault.
+        *
+        * On the other hand, this needs to be done ASAP, because the VF driver
+        * is waiting for this to happen and may report a timeout. It's
+        * harmless, but it gets logged into Guest OS kernel log, so best avoid
+        * it.
+        */
+       reg = rd32(hw, I40E_VPGEN_VFRTRIG(vf->vf_id));
+       reg &= ~I40E_VPGEN_VFRTRIG_VFSWR_MASK;
+       wr32(hw, I40E_VPGEN_VFRTRIG(vf->vf_id), reg);
+
+       /* reallocate VF resources to finish resetting the VSI state */
+       if (!i40e_alloc_vf_res(vf)) {
+               int abs_vf_id = vf->vf_id + (int)hw->func_caps.vf_base_id;
+               i40e_enable_vf_mappings(vf);
+               set_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states);
+               clear_bit(I40E_VF_STATE_DISABLED, &vf->vf_states);
+               /* Do not notify the client during VF init */
+               if (!test_and_clear_bit(I40E_VF_STATE_PRE_ENABLE,
+                                       &vf->vf_states))
+                       i40e_notify_client_of_vf_reset(pf, abs_vf_id);
+               vf->num_vlan = 0;
+       }
+
+       /* Tell the VF driver the reset is done. This needs to be done only
+        * after VF has been fully initialized, because the VF driver may
+        * request resources immediately after setting this flag.
+        */
+       wr32(hw, I40E_VFGEN_RSTAT1(vf->vf_id), VIRTCHNL_VFR_VFACTIVE);
+}
+
+/**
+ * i40e_reset_vf
+ * @vf: pointer to the VF structure
+ * @flr: VFLR was issued or not
+ *
+ * Returns true if the VF is reset, false otherwise.
+ **/
+bool i40e_reset_vf(struct i40e_vf *vf, bool flr)
+{
+       struct i40e_pf *pf = vf->pf;
+       struct i40e_hw *hw = &pf->hw;
+       bool rsd = false;
+       u32 reg;
+       int i;
+
+       /* If the VFs have been disabled, this means something else is
+        * resetting the VF, so we shouldn't continue.
+        */
+       if (test_and_set_bit(__I40E_VF_DISABLE, pf->state))
+               return false;
+
+       i40e_trigger_vf_reset(vf, flr);
 
        /* poll VPGEN_VFRSTAT reg to make sure
         * that reset is complete
@@ -857,31 +1114,121 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr)
                dev_err(&pf->pdev->dev, "VF reset check timeout on VF %d\n",
                        vf->vf_id);
        usleep_range(10000, 20000);
-       wr32(hw, I40E_VFGEN_RSTAT1(vf->vf_id), I40E_VFR_COMPLETED);
-       /* clear the reset bit in the VPGEN_VFRTRIG reg */
-       reg = rd32(hw, I40E_VPGEN_VFRTRIG(vf->vf_id));
-       reg &= ~I40E_VPGEN_VFRTRIG_VFSWR_MASK;
-       wr32(hw, I40E_VPGEN_VFRTRIG(vf->vf_id), reg);
 
-       /* On initial reset, we won't have any queues */
-       if (vf->lan_vsi_idx == 0)
-               goto complete_reset;
+       /* On initial reset, we don't have any queues to disable */
+       if (vf->lan_vsi_idx != 0)
+               i40e_vsi_stop_rings(pf->vsi[vf->lan_vsi_idx]);
 
-       i40e_vsi_stop_rings(pf->vsi[vf->lan_vsi_idx]);
-complete_reset:
-       /* reallocate VF resources to reset the VSI state */
-       i40e_free_vf_res(vf);
-       if (!i40e_alloc_vf_res(vf)) {
-               i40e_enable_vf_mappings(vf);
-               set_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states);
-               clear_bit(I40E_VF_STAT_DISABLED, &vf->vf_states);
-               vf->num_vlan = 0;
+       i40e_cleanup_reset_vf(vf);
+
+       i40e_flush(hw);
+       clear_bit(__I40E_VF_DISABLE, pf->state);
+
+       return true;
+}
+
+/**
+ * i40e_reset_all_vfs
+ * @pf: pointer to the PF structure
+ * @flr: VFLR was issued or not
+ *
+ * Reset all allocated VFs in one go. First, tell the hardware to reset each
+ * VF, then do all the waiting in one chunk, and finally finish restoring each
+ * VF after the wait. This is useful during PF routines which need to reset
+ * all VFs, as otherwise it must perform these resets in a serialized fashion.
+ *
+ * Returns true if any VFs were reset, and false otherwise.
+ **/
+bool i40e_reset_all_vfs(struct i40e_pf *pf, bool flr)
+{
+       struct i40e_hw *hw = &pf->hw;
+       struct i40e_vf *vf;
+       int i, v;
+       u32 reg;
+
+       /* If we don't have any VFs, then there is nothing to reset */
+       if (!pf->num_alloc_vfs)
+               return false;
+
+       /* If VFs have been disabled, there is no need to reset */
+       if (test_and_set_bit(__I40E_VF_DISABLE, pf->state))
+               return false;
+
+       /* Begin reset on all VFs at once */
+       for (v = 0; v < pf->num_alloc_vfs; v++)
+               i40e_trigger_vf_reset(&pf->vf[v], flr);
+
+       /* HW requires some time to make sure it can flush the FIFO for a VF
+        * when it resets it. Poll the VPGEN_VFRSTAT register for each VF in
+        * sequence to make sure that it has completed. We'll keep track of
+        * the VFs using a simple iterator that increments once that VF has
+        * finished resetting.
+        */
+       for (i = 0, v = 0; i < 10 && v < pf->num_alloc_vfs; i++) {
+               usleep_range(10000, 20000);
+
+               /* Check each VF in sequence, beginning with the VF to fail
+                * the previous check.
+                */
+               while (v < pf->num_alloc_vfs) {
+                       vf = &pf->vf[v];
+                       reg = rd32(hw, I40E_VPGEN_VFRSTAT(vf->vf_id));
+                       if (!(reg & I40E_VPGEN_VFRSTAT_VFRD_MASK))
+                               break;
+
+                       /* If the current VF has finished resetting, move on
+                        * to the next VF in sequence.
+                        */
+                       v++;
+               }
        }
-       /* tell the VF the reset is done */
-       wr32(hw, I40E_VFGEN_RSTAT1(vf->vf_id), I40E_VFR_VFACTIVE);
+
+       if (flr)
+               usleep_range(10000, 20000);
+
+       /* Display a warning if at least one VF didn't manage to reset in
+        * time, but continue on with the operation.
+        */
+       if (v < pf->num_alloc_vfs)
+               dev_err(&pf->pdev->dev, "VF reset check timeout on VF %d\n",
+                       pf->vf[v].vf_id);
+       usleep_range(10000, 20000);
+
+       /* Begin disabling all the rings associated with VFs, but do not wait
+        * between each VF.
+        */
+       for (v = 0; v < pf->num_alloc_vfs; v++) {
+               /* On initial reset, we don't have any queues to disable */
+               if (pf->vf[v].lan_vsi_idx == 0)
+                       continue;
+
+               i40e_vsi_stop_rings_no_wait(pf->vsi[pf->vf[v].lan_vsi_idx]);
+       }
+
+       /* Now that we've notified HW to disable all of the VF rings, wait
+        * until they finish.
+        */
+       for (v = 0; v < pf->num_alloc_vfs; v++) {
+               /* On initial reset, we don't have any queues to disable */
+               if (pf->vf[v].lan_vsi_idx == 0)
+                       continue;
+
+               i40e_vsi_wait_queues_disabled(pf->vsi[pf->vf[v].lan_vsi_idx]);
+       }
+
+       /* Hw may need up to 50ms to finish disabling the RX queues. We
+        * minimize the wait by delaying only once for all VFs.
+        */
+       mdelay(50);
+
+       /* Finish the reset on each VF */
+       for (v = 0; v < pf->num_alloc_vfs; v++)
+               i40e_cleanup_reset_vf(&pf->vf[v]);
 
        i40e_flush(hw);
-       clear_bit(__I40E_VF_DISABLE, &pf->state);
+       clear_bit(__I40E_VF_DISABLE, pf->state);
+
+       return true;
 }
 
 /**
@@ -898,12 +1245,25 @@ void i40e_free_vfs(struct i40e_pf *pf)
 
        if (!pf->vf)
                return;
-       while (test_and_set_bit(__I40E_VF_DISABLE, &pf->state))
+       while (test_and_set_bit(__I40E_VF_DISABLE, pf->state))
                usleep_range(1000, 2000);
 
-       for (i = 0; i < pf->num_alloc_vfs; i++)
-               if (test_bit(I40E_VF_STAT_INIT, &pf->vf[i].vf_states))
-                       i40e_vsi_stop_rings(pf->vsi[pf->vf[i].lan_vsi_idx]);
+       i40e_notify_client_of_vf_enable(pf, 0);
+
+       /* Amortize wait time by stopping all VFs at the same time */
+       for (i = 0; i < pf->num_alloc_vfs; i++) {
+               if (test_bit(I40E_VF_STATE_INIT, &pf->vf[i].vf_states))
+                       continue;
+
+               i40e_vsi_stop_rings_no_wait(pf->vsi[pf->vf[i].lan_vsi_idx]);
+       }
+
+       for (i = 0; i < pf->num_alloc_vfs; i++) {
+               if (test_bit(I40E_VF_STATE_INIT, &pf->vf[i].vf_states))
+                       continue;
+
+               i40e_vsi_wait_queues_disabled(pf->vsi[pf->vf[i].lan_vsi_idx]);
+       }
 
        /* Disable IOV before freeing resources. This lets any VF drivers
         * running in the host get themselves cleaned up before we yank
@@ -914,13 +1274,11 @@ void i40e_free_vfs(struct i40e_pf *pf)
        else
                dev_warn(&pf->pdev->dev, "VFs are assigned - not disabling SR-IOV\n");
 
-       msleep(20); /* let any messages in transit get finished up */
-
        /* free up VF resources */
        tmp = pf->num_alloc_vfs;
        pf->num_alloc_vfs = 0;
        for (i = 0; i < tmp; i++) {
-               if (test_bit(I40E_VF_STAT_INIT, &pf->vf[i].vf_states))
+               if (test_bit(I40E_VF_STATE_INIT, &pf->vf[i].vf_states))
                        i40e_free_vf_res(&pf->vf[i]);
                /* disable qp mappings */
                i40e_disable_vf_mappings(&pf->vf[i]);
@@ -943,7 +1301,7 @@ void i40e_free_vfs(struct i40e_pf *pf)
                        wr32(hw, I40E_GLGEN_VFLRSTAT(reg_idx), BIT(bit_idx));
                }
        }
-       clear_bit(__I40E_VF_DISABLE, &pf->state);
+       clear_bit(__I40E_VF_DISABLE, pf->state);
 }
 
 #ifdef CONFIG_PCI_IOV
@@ -988,12 +1346,19 @@ int i40e_alloc_vfs(struct i40e_pf *pf, u16 num_alloc_vfs)
                /* assign default capabilities */
                set_bit(I40E_VIRTCHNL_VF_CAP_L2, &vfs[i].vf_caps);
                vfs[i].spoofchk = true;
-               /* VF resources get allocated during reset */
-               i40e_reset_vf(&vfs[i], false);
-
+#if 0
+               /* TODO */
+               set_bit(VIRTCHNL_VF_CAP_IWARP, &vfs[i].vf_caps);
+#endif
+               set_bit(I40E_VF_STATE_PRE_ENABLE, &vfs[i].vf_states);
        }
        pf->num_alloc_vfs = num_alloc_vfs;
 
+       /* VF resources get allocated during reset */
+       i40e_reset_all_vfs(pf, false);
+
+       i40e_notify_client_of_vf_enable(pf, num_alloc_vfs);
+
 err_alloc:
        if (ret)
                i40e_free_vfs(pf);
@@ -1019,7 +1384,7 @@ static int i40e_pci_sriov_enable(struct pci_dev *pdev, int num_vfs)
        int pre_existing_vfs = pci_num_vf(pdev);
        int err = 0;
 
-       if (test_bit(__I40E_TESTING, &pf->state)) {
+       if (test_bit(__I40E_TESTING, pf->state)) {
                dev_warn(&pdev->dev,
                         "Cannot enable SR-IOV virtual functions while the device is undergoing diagnostic testing\n");
                err = -EPERM;
@@ -1126,7 +1491,7 @@ static int i40e_vc_send_msg_to_vf(struct i40e_vf *vf, u32 v_opcode,
                                "Number of invalid messages exceeded for VF %d\n",
                                vf->vf_id);
                        dev_err(&pf->pdev->dev, "Use PF Control I/F to enable the VF\n");
-                       set_bit(I40E_VF_STAT_DISABLED, &vf->vf_states);
+                       set_bit(I40E_VF_STATE_DISABLED, &vf->vf_states);
                }
        } else {
                vf->num_valid_msgs++;
@@ -1155,7 +1520,7 @@ static int i40e_vc_send_msg_to_vf(struct i40e_vf *vf, u32 v_opcode,
  * send resp msg to VF
  **/
 static int i40e_vc_send_resp_to_vf(struct i40e_vf *vf,
-                                  enum i40e_virtchnl_ops opcode,
+                                  enum virtchnl_ops opcode,
                                   i40e_status retval)
 {
        return i40e_vc_send_msg_to_vf(vf, opcode, retval, NULL, 0);
@@ -1169,18 +1534,17 @@ static int i40e_vc_send_resp_to_vf(struct i40e_vf *vf,
  **/
 static int i40e_vc_get_version_msg(struct i40e_vf *vf, u8 *msg)
 {
-       struct i40e_virtchnl_version_info info = {
-               I40E_VIRTCHNL_VERSION_MAJOR, I40E_VIRTCHNL_VERSION_MINOR
+       struct virtchnl_version_info info = {
+               VIRTCHNL_VERSION_MAJOR, VIRTCHNL_VERSION_MINOR
        };
 
-       vf->vf_ver = *(struct i40e_virtchnl_version_info *)msg;
+       vf->vf_ver = *(struct virtchnl_version_info *)msg;
        /* VFs running the 1.0 API expect to get 1.0 back or they will cry. */
-       if (VF_IS_V10(vf))
-               info.minor = I40E_VIRTCHNL_VERSION_MINOR_NO_VF_CAPS;
-       return i40e_vc_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_VERSION,
+       if (VF_IS_V10(&vf->vf_ver))
+               info.minor = VIRTCHNL_VERSION_MINOR_NO_VF_CAPS;
+       return i40e_vc_send_msg_to_vf(vf, VIRTCHNL_OP_VERSION,
                                      I40E_SUCCESS, (u8 *)&info,
-                                     sizeof(struct
-                                            i40e_virtchnl_version_info));
+                                     sizeof(struct virtchnl_version_info));
 }
 
 /**
@@ -1193,7 +1557,7 @@ static int i40e_vc_get_version_msg(struct i40e_vf *vf, u8 *msg)
  **/
 static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg)
 {
-       struct i40e_virtchnl_vf_resource *vfres = NULL;
+       struct virtchnl_vf_resource *vfres = NULL;
        struct i40e_pf *pf = vf->pf;
        i40e_status aq_ret = 0;
        struct i40e_vsi *vsi;
@@ -1201,13 +1565,16 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg)
        int len = 0;
        int ret;
 
-       if (!test_bit(I40E_VF_STAT_INIT, &vf->vf_states)) {
+       if (!test_bit(I40E_VF_STATE_INIT, &vf->vf_states)) {
                aq_ret = I40E_ERR_PARAM;
                goto err;
        }
 
-       len = (sizeof(struct i40e_virtchnl_vf_resource) +
-              sizeof(struct i40e_virtchnl_vsi_resource) * num_vsis);
+       if (test_bit(I40E_VF_STATE_IWARPENA, &vf->vf_states))
+               num_vsis++;
+
+       len = (sizeof(struct virtchnl_vf_resource) +
+              sizeof(struct virtchnl_vsi_resource) * num_vsis);
 
        vfres = kzalloc(len, GFP_KERNEL);
        if (!vfres) {
@@ -1215,55 +1582,67 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg)
                len = 0;
                goto err;
        }
-       if (VF_IS_V11(vf))
+       if (VF_IS_V11(&vf->vf_ver))
                vf->driver_caps = *(u32 *)msg;
        else
-               vf->driver_caps = I40E_VIRTCHNL_VF_OFFLOAD_L2 |
-                                 I40E_VIRTCHNL_VF_OFFLOAD_RSS_REG |
-                                 I40E_VIRTCHNL_VF_OFFLOAD_VLAN;
+               vf->driver_caps = VIRTCHNL_VF_OFFLOAD_L2 |
+                                 VIRTCHNL_VF_OFFLOAD_RSS_REG |
+                                 VIRTCHNL_VF_OFFLOAD_VLAN;
 
-       vfres->vf_offload_flags = I40E_VIRTCHNL_VF_OFFLOAD_L2;
+       vfres->vf_offload_flags = VIRTCHNL_VF_OFFLOAD_L2;
        vsi = pf->vsi[vf->lan_vsi_idx];
        if (!vsi->info.pvid)
-               vfres->vf_offload_flags |= I40E_VIRTCHNL_VF_OFFLOAD_VLAN;
+               vfres->vf_offload_flags |= VIRTCHNL_VF_OFFLOAD_VLAN;
+       if (i40e_vf_client_capable(pf, vf->vf_id) &&
+           (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_IWARP)) {
+               vfres->vf_offload_flags |= VIRTCHNL_VF_OFFLOAD_IWARP;
+               set_bit(I40E_VF_STATE_IWARPENA, &vf->vf_states);
+       } else {
+               clear_bit(I40E_VF_STATE_IWARPENA, &vf->vf_states);
+       }
 
-       if (vf->driver_caps & I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF) {
-               vfres->vf_offload_flags |= I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF;
+       if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_RSS_PF) {
+               vfres->vf_offload_flags |= VIRTCHNL_VF_OFFLOAD_RSS_PF;
        } else {
-               if ((pf->flags & I40E_FLAG_RSS_AQ_CAPABLE) &&
-                   (vf->driver_caps & I40E_VIRTCHNL_VF_OFFLOAD_RSS_AQ))
-                       vfres->vf_offload_flags |=
-                                       I40E_VIRTCHNL_VF_OFFLOAD_RSS_AQ;
+               if ((pf->hw_features & I40E_HW_RSS_AQ_CAPABLE) &&
+                   (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_RSS_AQ))
+                       vfres->vf_offload_flags |= VIRTCHNL_VF_OFFLOAD_RSS_AQ;
                else
-                       vfres->vf_offload_flags |=
-                                       I40E_VIRTCHNL_VF_OFFLOAD_RSS_REG;
+                       vfres->vf_offload_flags |= VIRTCHNL_VF_OFFLOAD_RSS_REG;
        }
-       if (pf->flags & I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE) {
-               if (vf->driver_caps & I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2)
+       if (pf->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE) {
+               if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2)
                        vfres->vf_offload_flags |=
-                               I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2;
+                               VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2;
        }
 
-       if (vf->driver_caps & I40E_VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM)
-               vfres->vf_offload_flags |= I40E_VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM;
+       if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_ENCAP)
+               vfres->vf_offload_flags |= VIRTCHNL_VF_OFFLOAD_ENCAP;
 
-       if (vf->driver_caps & I40E_VIRTCHNL_VF_OFFLOAD_RX_POLLING) {
+       if ((pf->hw_features & I40E_HW_OUTER_UDP_CSUM_CAPABLE) &&
+           (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM))
+               vfres->vf_offload_flags |= VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM;
+
+       if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_RX_POLLING) {
                if (pf->flags & I40E_FLAG_MFP_ENABLED) {
                        dev_err(&pf->pdev->dev,
                                "VF %d requested polling mode: this feature is supported only when the device is running in single function per port (SFP) mode\n",
                                 vf->vf_id);
-                       ret = I40E_ERR_PARAM;
+                       aq_ret = I40E_ERR_PARAM;
                        goto err;
                }
-               vfres->vf_offload_flags |= I40E_VIRTCHNL_VF_OFFLOAD_RX_POLLING;
+               vfres->vf_offload_flags |= VIRTCHNL_VF_OFFLOAD_RX_POLLING;
        }
 
-       if (pf->flags & I40E_FLAG_WB_ON_ITR_CAPABLE) {
-               if (vf->driver_caps & I40E_VIRTCHNL_VF_OFFLOAD_WB_ON_ITR)
+       if (pf->hw_features & I40E_HW_WB_ON_ITR_CAPABLE) {
+               if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_WB_ON_ITR)
                        vfres->vf_offload_flags |=
-                                       I40E_VIRTCHNL_VF_OFFLOAD_WB_ON_ITR;
+                                       VIRTCHNL_VF_OFFLOAD_WB_ON_ITR;
        }
 
+       if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_REQ_QUEUES)
+               vfres->vf_offload_flags |= VIRTCHNL_VF_OFFLOAD_REQ_QUEUES;
+
        vfres->num_vsis = num_vsis;
        vfres->num_queue_pairs = vf->num_queue_pairs;
        vfres->max_vectors = pf->hw.func_caps.num_msix_vectors_vf;
@@ -1272,7 +1651,7 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg)
 
        if (vf->lan_vsi_idx) {
                vfres->vsi_res[0].vsi_id = vf->lan_vsi_id;
-               vfres->vsi_res[0].vsi_type = I40E_VSI_SRIOV;
+               vfres->vsi_res[0].vsi_type = VIRTCHNL_VSI_SRIOV;
                vfres->vsi_res[0].num_queue_pairs = vsi->alloc_queue_pairs;
                /* VFs only use TC 0 */
                vfres->vsi_res[0].qset_handle
@@ -1280,16 +1659,16 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg)
                ether_addr_copy(vfres->vsi_res[0].default_mac_addr,
                                vf->default_lan_addr.addr);
        }
-       set_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states);
+       set_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states);
 
        /* if vf is in base mode, keep only the base capabilities that are
         * negotiated
         */
        if (pf->vf_base_mode_only)
-               vfres->vf_offload_flags &= I40E_VF_BASE_MODE_OFFLOADS;
+               vfres->vf_offload_flags &= VF_BASE_MODE_OFFLOADS;
 err:
        /* send the response back to the VF */
-       ret = i40e_vc_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_GET_VF_RESOURCES,
+       ret = i40e_vc_send_msg_to_vf(vf, VIRTCHNL_OP_GET_VF_RESOURCES,
                                     aq_ret, (u8 *)vfres, len);
 
        kfree(vfres);
@@ -1308,7 +1687,7 @@ err:
  **/
 static void i40e_vc_reset_vf_msg(struct i40e_vf *vf)
 {
-       if (test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states))
+       if (test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states))
                i40e_reset_vf(vf, false);
 }
 
@@ -1343,20 +1722,20 @@ static inline int i40e_getnum_vf_vsi_vlan_filters(struct i40e_vsi *vsi)
 static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf,
                                               u8 *msg, u16 msglen)
 {
-       struct i40e_virtchnl_promisc_info *info =
-           (struct i40e_virtchnl_promisc_info *)msg;
+       struct virtchnl_promisc_info *info =
+           (struct virtchnl_promisc_info *)msg;
        i40e_status aq_ret = I40E_SUCCESS;
        struct i40e_pf *pf = vf->pf;
        struct i40e_hw *hw = &pf->hw;
        struct i40e_mac_filter *f;
        bool allmulti = false;
+       struct i40e_vsi *vsi;
        bool alluni = false;
        int aq_err = 0;
        int bkt;
-       struct i40e_vsi *vsi;
 
        vsi = i40e_find_vsi_from_id(pf, info->vsi_id);
-       if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states) ||
+       if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) ||
            !i40e_vc_isvalid_vsi_id(vf, info->vsi_id) ||
            !vsi) {
                aq_ret = I40E_ERR_PARAM;
@@ -1374,7 +1753,7 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf,
                goto error_param;
        }
        /* Multicast promiscuous handling*/
-       if (info->flags & I40E_FLAG_VF_MULTICAST_PROMISC)
+       if (info->flags & FLAG_VF_MULTICAST_PROMISC)
                allmulti = true;
        if (vf->port_vlan_id) {
                aq_ret = i40e_aq_set_vsi_mc_promisc_on_vlan(hw, vsi->seid,
@@ -1419,12 +1798,12 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf,
                         "VF %d successfully set multicast promiscuous mode\n",
                         vf->vf_id);
                if (allmulti)
-                       set_bit(I40E_VF_STAT_MC_PROMISC, &vf->vf_states);
+                       set_bit(I40E_VF_STATE_MC_PROMISC, &vf->vf_states);
                else
-                       clear_bit(I40E_VF_STAT_MC_PROMISC, &vf->vf_states);
+                       clear_bit(I40E_VF_STATE_MC_PROMISC, &vf->vf_states);
        }
 
-       if (info->flags & I40E_FLAG_VF_UNICAST_PROMISC)
+       if (info->flags & FLAG_VF_UNICAST_PROMISC)
                alluni = true;
        if (vf->port_vlan_id) {
                aq_ret = i40e_aq_set_vsi_uc_promisc_on_vlan(hw, vsi->seid,
@@ -1450,7 +1829,7 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf,
                }
        } else {
                aq_ret = i40e_aq_set_vsi_unicast_promiscuous(hw, vsi->seid,
-                                                            allmulti, NULL,
+                                                            alluni, NULL,
                                                             true);
                aq_err = pf->hw.aq.asq_last_status;
                if (aq_ret) {
@@ -1468,15 +1847,15 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf,
                         "VF %d successfully set unicast promiscuous mode\n",
                         vf->vf_id);
                if (alluni)
-                       set_bit(I40E_VF_STAT_UC_PROMISC, &vf->vf_states);
+                       set_bit(I40E_VF_STATE_UC_PROMISC, &vf->vf_states);
                else
-                       clear_bit(I40E_VF_STAT_UC_PROMISC, &vf->vf_states);
+                       clear_bit(I40E_VF_STATE_UC_PROMISC, &vf->vf_states);
        }
 
 error_param:
        /* send the response to the VF */
        return i40e_vc_send_resp_to_vf(vf,
-                                      I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE,
+                                      VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE,
                                       aq_ret);
 }
 
@@ -1491,15 +1870,15 @@ error_param:
  **/
 static int i40e_vc_config_queues_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
 {
-       struct i40e_virtchnl_vsi_queue_config_info *qci =
-           (struct i40e_virtchnl_vsi_queue_config_info *)msg;
-       struct i40e_virtchnl_queue_pair_info *qpi;
+       struct virtchnl_vsi_queue_config_info *qci =
+           (struct virtchnl_vsi_queue_config_info *)msg;
+       struct virtchnl_queue_pair_info *qpi;
        struct i40e_pf *pf = vf->pf;
        u16 vsi_id, vsi_queue_id;
        i40e_status aq_ret = 0;
        int i;
 
-       if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states)) {
+       if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) {
                aq_ret = I40E_ERR_PARAM;
                goto error_param;
        }
@@ -1534,7 +1913,7 @@ static int i40e_vc_config_queues_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
 
 error_param:
        /* send the response to the VF */
-       return i40e_vc_send_resp_to_vf(vf, I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES,
+       return i40e_vc_send_resp_to_vf(vf, VIRTCHNL_OP_CONFIG_VSI_QUEUES,
                                       aq_ret);
 }
 
@@ -1549,15 +1928,15 @@ error_param:
  **/
 static int i40e_vc_config_irq_map_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
 {
-       struct i40e_virtchnl_irq_map_info *irqmap_info =
-           (struct i40e_virtchnl_irq_map_info *)msg;
-       struct i40e_virtchnl_vector_map *map;
+       struct virtchnl_irq_map_info *irqmap_info =
+           (struct virtchnl_irq_map_info *)msg;
+       struct virtchnl_vector_map *map;
        u16 vsi_id, vsi_queue_id, vector_id;
        i40e_status aq_ret = 0;
        unsigned long tempmap;
        int i;
 
-       if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states)) {
+       if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) {
                aq_ret = I40E_ERR_PARAM;
                goto error_param;
        }
@@ -1597,7 +1976,7 @@ static int i40e_vc_config_irq_map_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
        }
 error_param:
        /* send the response to the VF */
-       return i40e_vc_send_resp_to_vf(vf, I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP,
+       return i40e_vc_send_resp_to_vf(vf, VIRTCHNL_OP_CONFIG_IRQ_MAP,
                                       aq_ret);
 }
 
@@ -1611,13 +1990,13 @@ error_param:
  **/
 static int i40e_vc_enable_queues_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
 {
-       struct i40e_virtchnl_queue_select *vqs =
-           (struct i40e_virtchnl_queue_select *)msg;
+       struct virtchnl_queue_select *vqs =
+           (struct virtchnl_queue_select *)msg;
        struct i40e_pf *pf = vf->pf;
        u16 vsi_id = vqs->vsi_id;
        i40e_status aq_ret = 0;
 
-       if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states)) {
+       if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) {
                aq_ret = I40E_ERR_PARAM;
                goto error_param;
        }
@@ -1636,7 +2015,7 @@ static int i40e_vc_enable_queues_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
                aq_ret = I40E_ERR_TIMEOUT;
 error_param:
        /* send the response to the VF */
-       return i40e_vc_send_resp_to_vf(vf, I40E_VIRTCHNL_OP_ENABLE_QUEUES,
+       return i40e_vc_send_resp_to_vf(vf, VIRTCHNL_OP_ENABLE_QUEUES,
                                       aq_ret);
 }
 
@@ -1651,12 +2030,12 @@ error_param:
  **/
 static int i40e_vc_disable_queues_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
 {
-       struct i40e_virtchnl_queue_select *vqs =
-           (struct i40e_virtchnl_queue_select *)msg;
+       struct virtchnl_queue_select *vqs =
+           (struct virtchnl_queue_select *)msg;
        struct i40e_pf *pf = vf->pf;
        i40e_status aq_ret = 0;
 
-       if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states)) {
+       if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) {
                aq_ret = I40E_ERR_PARAM;
                goto error_param;
        }
@@ -1675,10 +2054,56 @@ static int i40e_vc_disable_queues_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
 
 error_param:
        /* send the response to the VF */
-       return i40e_vc_send_resp_to_vf(vf, I40E_VIRTCHNL_OP_DISABLE_QUEUES,
+       return i40e_vc_send_resp_to_vf(vf, VIRTCHNL_OP_DISABLE_QUEUES,
                                       aq_ret);
 }
 
+/**
+ * i40e_vc_request_queues_msg
+ * @vf: pointer to the VF info
+ * @msg: pointer to the msg buffer
+ * @msglen: msg length
+ *
+ * VFs get a default number of queues but can use this message to request a
+ * different number.  Will respond with either the number requested or the
+ * maximum we can support.
+ **/
+static int i40e_vc_request_queues_msg(struct i40e_vf *vf, u8 *msg, int msglen)
+{
+       struct virtchnl_vf_res_request *vfres =
+               (struct virtchnl_vf_res_request *)msg;
+       int req_pairs = vfres->num_queue_pairs;
+       int cur_pairs = vf->num_queue_pairs;
+       struct i40e_pf *pf = vf->pf;
+
+       if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states))
+               return -EINVAL;
+
+       if (req_pairs <= 0) {
+               dev_err(&pf->pdev->dev,
+                       "VF %d tried to request %d queues.  Ignoring.\n",
+                       vf->vf_id, req_pairs);
+       } else if (req_pairs > I40E_MAX_VF_QUEUES) {
+               dev_err(&pf->pdev->dev,
+                       "VF %d tried to request more than %d queues.\n",
+                       vf->vf_id,
+                       I40E_MAX_VF_QUEUES);
+               vfres->num_queue_pairs = I40E_MAX_VF_QUEUES;
+       } else if (req_pairs - cur_pairs > pf->queues_left) {
+               dev_warn(&pf->pdev->dev,
+                        "VF %d requested %d more queues, but only %d left.\n",
+                        vf->vf_id,
+                        req_pairs - cur_pairs,
+                        pf->queues_left);
+               vfres->num_queue_pairs = pf->queues_left + cur_pairs;
+       } else {
+               vf->num_req_queues = req_pairs;
+       }
+
+       return i40e_vc_send_msg_to_vf(vf, VIRTCHNL_OP_REQUEST_QUEUES, 0,
+                                     (u8 *)vfres, sizeof(vfres));
+}
+
 /**
  * i40e_vc_get_stats_msg
  * @vf: pointer to the VF info
@@ -1689,8 +2114,8 @@ error_param:
  **/
 static int i40e_vc_get_stats_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
 {
-       struct i40e_virtchnl_queue_select *vqs =
-           (struct i40e_virtchnl_queue_select *)msg;
+       struct virtchnl_queue_select *vqs =
+           (struct virtchnl_queue_select *)msg;
        struct i40e_pf *pf = vf->pf;
        struct i40e_eth_stats stats;
        i40e_status aq_ret = 0;
@@ -1698,7 +2123,7 @@ static int i40e_vc_get_stats_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
 
        memset(&stats, 0, sizeof(struct i40e_eth_stats));
 
-       if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states)) {
+       if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) {
                aq_ret = I40E_ERR_PARAM;
                goto error_param;
        }
@@ -1718,7 +2143,7 @@ static int i40e_vc_get_stats_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
 
 error_param:
        /* send the response back to the VF */
-       return i40e_vc_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_GET_STATS, aq_ret,
+       return i40e_vc_send_msg_to_vf(vf, VIRTCHNL_OP_GET_STATS, aq_ret,
                                      (u8 *)&stats, sizeof(stats));
 }
 
@@ -1780,15 +2205,15 @@ static inline int i40e_check_vf_permission(struct i40e_vf *vf, u8 *macaddr)
  **/
 static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
 {
-       struct i40e_virtchnl_ether_addr_list *al =
-           (struct i40e_virtchnl_ether_addr_list *)msg;
+       struct virtchnl_ether_addr_list *al =
+           (struct virtchnl_ether_addr_list *)msg;
        struct i40e_pf *pf = vf->pf;
        struct i40e_vsi *vsi = NULL;
        u16 vsi_id = al->vsi_id;
        i40e_status ret = 0;
        int i;
 
-       if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states) ||
+       if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) ||
            !i40e_vc_isvalid_vsi_id(vf, vsi_id)) {
                ret = I40E_ERR_PARAM;
                goto error_param;
@@ -1835,7 +2260,7 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
 
 error_param:
        /* send the response to the VF */
-       return i40e_vc_send_resp_to_vf(vf, I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS,
+       return i40e_vc_send_resp_to_vf(vf, VIRTCHNL_OP_ADD_ETH_ADDR,
                                       ret);
 }
 
@@ -1849,15 +2274,15 @@ error_param:
  **/
 static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
 {
-       struct i40e_virtchnl_ether_addr_list *al =
-           (struct i40e_virtchnl_ether_addr_list *)msg;
+       struct virtchnl_ether_addr_list *al =
+           (struct virtchnl_ether_addr_list *)msg;
        struct i40e_pf *pf = vf->pf;
        struct i40e_vsi *vsi = NULL;
        u16 vsi_id = al->vsi_id;
        i40e_status ret = 0;
        int i;
 
-       if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states) ||
+       if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) ||
            !i40e_vc_isvalid_vsi_id(vf, vsi_id)) {
                ret = I40E_ERR_PARAM;
                goto error_param;
@@ -1895,7 +2320,7 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
 
 error_param:
        /* send the response to the VF */
-       return i40e_vc_send_resp_to_vf(vf, I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS,
+       return i40e_vc_send_resp_to_vf(vf, VIRTCHNL_OP_DEL_ETH_ADDR,
                                       ret);
 }
 
@@ -1909,8 +2334,8 @@ error_param:
  **/
 static int i40e_vc_add_vlan_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
 {
-       struct i40e_virtchnl_vlan_filter_list *vfl =
-           (struct i40e_virtchnl_vlan_filter_list *)msg;
+       struct virtchnl_vlan_filter_list *vfl =
+           (struct virtchnl_vlan_filter_list *)msg;
        struct i40e_pf *pf = vf->pf;
        struct i40e_vsi *vsi = NULL;
        u16 vsi_id = vfl->vsi_id;
@@ -1926,7 +2351,7 @@ static int i40e_vc_add_vlan_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
                                vf->vf_id, I40E_VC_MAX_VLAN_PER_VF);
                goto error_param;
        }
-       if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states) ||
+       if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) ||
            !i40e_vc_isvalid_vsi_id(vf, vsi_id)) {
                aq_ret = I40E_ERR_PARAM;
                goto error_param;
@@ -1953,12 +2378,12 @@ static int i40e_vc_add_vlan_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
                if (!ret)
                        vf->num_vlan++;
 
-               if (test_bit(I40E_VF_STAT_UC_PROMISC, &vf->vf_states))
+               if (test_bit(I40E_VF_STATE_UC_PROMISC, &vf->vf_states))
                        i40e_aq_set_vsi_uc_promisc_on_vlan(&pf->hw, vsi->seid,
                                                           true,
                                                           vfl->vlan_id[i],
                                                           NULL);
-               if (test_bit(I40E_VF_STAT_MC_PROMISC, &vf->vf_states))
+               if (test_bit(I40E_VF_STATE_MC_PROMISC, &vf->vf_states))
                        i40e_aq_set_vsi_mc_promisc_on_vlan(&pf->hw, vsi->seid,
                                                           true,
                                                           vfl->vlan_id[i],
@@ -1972,7 +2397,7 @@ static int i40e_vc_add_vlan_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
 
 error_param:
        /* send the response to the VF */
-       return i40e_vc_send_resp_to_vf(vf, I40E_VIRTCHNL_OP_ADD_VLAN, aq_ret);
+       return i40e_vc_send_resp_to_vf(vf, VIRTCHNL_OP_ADD_VLAN, aq_ret);
 }
 
 /**
@@ -1985,15 +2410,15 @@ error_param:
  **/
 static int i40e_vc_remove_vlan_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
 {
-       struct i40e_virtchnl_vlan_filter_list *vfl =
-           (struct i40e_virtchnl_vlan_filter_list *)msg;
+       struct virtchnl_vlan_filter_list *vfl =
+           (struct virtchnl_vlan_filter_list *)msg;
        struct i40e_pf *pf = vf->pf;
        struct i40e_vsi *vsi = NULL;
        u16 vsi_id = vfl->vsi_id;
        i40e_status aq_ret = 0;
        int i;
 
-       if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states) ||
+       if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) ||
            !i40e_vc_isvalid_vsi_id(vf, vsi_id)) {
                aq_ret = I40E_ERR_PARAM;
                goto error_param;
@@ -2016,12 +2441,12 @@ static int i40e_vc_remove_vlan_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
                i40e_vsi_kill_vlan(vsi, vfl->vlan_id[i]);
                vf->num_vlan--;
 
-               if (test_bit(I40E_VF_STAT_UC_PROMISC, &vf->vf_states))
+               if (test_bit(I40E_VF_STATE_UC_PROMISC, &vf->vf_states))
                        i40e_aq_set_vsi_uc_promisc_on_vlan(&pf->hw, vsi->seid,
                                                           false,
                                                           vfl->vlan_id[i],
                                                           NULL);
-               if (test_bit(I40E_VF_STAT_MC_PROMISC, &vf->vf_states))
+               if (test_bit(I40E_VF_STATE_MC_PROMISC, &vf->vf_states))
                        i40e_aq_set_vsi_mc_promisc_on_vlan(&pf->hw, vsi->seid,
                                                           false,
                                                           vfl->vlan_id[i],
@@ -2030,7 +2455,73 @@ static int i40e_vc_remove_vlan_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
 
 error_param:
        /* send the response to the VF */
-       return i40e_vc_send_resp_to_vf(vf, I40E_VIRTCHNL_OP_DEL_VLAN, aq_ret);
+       return i40e_vc_send_resp_to_vf(vf, VIRTCHNL_OP_DEL_VLAN, aq_ret);
+}
+
+/**
+ * i40e_vc_iwarp_msg
+ * @vf: pointer to the VF info
+ * @msg: pointer to the msg buffer
+ * @msglen: msg length
+ *
+ * called from the VF for the iwarp msgs
+ **/
+static int i40e_vc_iwarp_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
+{
+       struct i40e_pf *pf = vf->pf;
+       int abs_vf_id = vf->vf_id + (int)pf->hw.func_caps.vf_base_id;
+       i40e_status aq_ret = I40E_SUCCESS;
+
+       if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) ||
+           !test_bit(I40E_VF_STATE_IWARPENA, &vf->vf_states)) {
+               aq_ret = I40E_ERR_PARAM;
+               goto error_param;
+       }
+
+       i40e_notify_client_of_vf_msg(pf->vsi[pf->lan_vsi], abs_vf_id,
+                                    msg, msglen);
+
+error_param:
+       /* send the response to the VF */
+       return i40e_vc_send_resp_to_vf(vf, VIRTCHNL_OP_IWARP,
+                                      aq_ret);
+}
+
+/**
+ * i40e_vc_iwarp_qvmap_msg
+ * @vf: pointer to the VF info
+ * @msg: pointer to the msg buffer
+ * @msglen: msg length
+ * @config: config qvmap or release it
+ *
+ * called from the VF for the iwarp msgs
+ **/
+static int i40e_vc_iwarp_qvmap_msg(struct i40e_vf *vf, u8 *msg, u16 msglen,
+                                  bool config)
+{
+       struct virtchnl_iwarp_qvlist_info *qvlist_info =
+                               (struct virtchnl_iwarp_qvlist_info *)msg;
+       i40e_status aq_ret = 0;
+
+       if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) ||
+           !test_bit(I40E_VF_STATE_IWARPENA, &vf->vf_states)) {
+               aq_ret = I40E_ERR_PARAM;
+               goto error_param;
+       }
+
+       if (config) {
+               if (i40e_config_iwarp_qvlist(vf, qvlist_info))
+                       aq_ret = I40E_ERR_PARAM;
+       } else {
+               i40e_release_iwarp_qvlist(vf);
+       }
+
+error_param:
+       /* send the response to the VF */
+       return i40e_vc_send_resp_to_vf(vf,
+                              config ? VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP :
+                              VIRTCHNL_OP_RELEASE_IWARP_IRQ_MAP,
+                              aq_ret);
 }
 
 /**
@@ -2043,14 +2534,14 @@ error_param:
  **/
 static int i40e_vc_config_rss_key(struct i40e_vf *vf, u8 *msg, u16 msglen)
 {
-       struct i40e_virtchnl_rss_key *vrk =
-               (struct i40e_virtchnl_rss_key *)msg;
+       struct virtchnl_rss_key *vrk =
+               (struct virtchnl_rss_key *)msg;
        struct i40e_pf *pf = vf->pf;
        struct i40e_vsi *vsi = NULL;
        u16 vsi_id = vrk->vsi_id;
        i40e_status aq_ret = 0;
 
-       if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states) ||
+       if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) ||
            !i40e_vc_isvalid_vsi_id(vf, vsi_id) ||
            (vrk->key_len != I40E_HKEY_ARRAY_SIZE)) {
                aq_ret = I40E_ERR_PARAM;
@@ -2061,7 +2552,7 @@ static int i40e_vc_config_rss_key(struct i40e_vf *vf, u8 *msg, u16 msglen)
        aq_ret = i40e_config_rss(vsi, vrk->key, NULL, 0);
 err:
        /* send the response to the VF */
-       return i40e_vc_send_resp_to_vf(vf, I40E_VIRTCHNL_OP_CONFIG_RSS_KEY,
+       return i40e_vc_send_resp_to_vf(vf, VIRTCHNL_OP_CONFIG_RSS_KEY,
                                       aq_ret);
 }
 
@@ -2075,14 +2566,14 @@ err:
  **/
 static int i40e_vc_config_rss_lut(struct i40e_vf *vf, u8 *msg, u16 msglen)
 {
-       struct i40e_virtchnl_rss_lut *vrl =
-               (struct i40e_virtchnl_rss_lut *)msg;
+       struct virtchnl_rss_lut *vrl =
+               (struct virtchnl_rss_lut *)msg;
        struct i40e_pf *pf = vf->pf;
        struct i40e_vsi *vsi = NULL;
        u16 vsi_id = vrl->vsi_id;
        i40e_status aq_ret = 0;
 
-       if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states) ||
+       if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) ||
            !i40e_vc_isvalid_vsi_id(vf, vsi_id) ||
            (vrl->lut_entries != I40E_VF_HLUT_ARRAY_SIZE)) {
                aq_ret = I40E_ERR_PARAM;
@@ -2093,7 +2584,7 @@ static int i40e_vc_config_rss_lut(struct i40e_vf *vf, u8 *msg, u16 msglen)
        aq_ret = i40e_config_rss(vsi, NULL, vrl->lut, I40E_VF_HLUT_ARRAY_SIZE);
        /* send the response to the VF */
 err:
-       return i40e_vc_send_resp_to_vf(vf, I40E_VIRTCHNL_OP_CONFIG_RSS_LUT,
+       return i40e_vc_send_resp_to_vf(vf, VIRTCHNL_OP_CONFIG_RSS_LUT,
                                       aq_ret);
 }
 
@@ -2107,16 +2598,16 @@ err:
  **/
 static int i40e_vc_get_rss_hena(struct i40e_vf *vf, u8 *msg, u16 msglen)
 {
-       struct i40e_virtchnl_rss_hena *vrh = NULL;
+       struct virtchnl_rss_hena *vrh = NULL;
        struct i40e_pf *pf = vf->pf;
        i40e_status aq_ret = 0;
        int len = 0;
 
-       if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states)) {
+       if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) {
                aq_ret = I40E_ERR_PARAM;
                goto err;
        }
-       len = sizeof(struct i40e_virtchnl_rss_hena);
+       len = sizeof(struct virtchnl_rss_hena);
 
        vrh = kzalloc(len, GFP_KERNEL);
        if (!vrh) {
@@ -2127,7 +2618,7 @@ static int i40e_vc_get_rss_hena(struct i40e_vf *vf, u8 *msg, u16 msglen)
        vrh->hena = i40e_pf_get_default_rss_hena(pf);
 err:
        /* send the response back to the VF */
-       aq_ret = i40e_vc_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_GET_RSS_HENA_CAPS,
+       aq_ret = i40e_vc_send_msg_to_vf(vf, VIRTCHNL_OP_GET_RSS_HENA_CAPS,
                                        aq_ret, (u8 *)vrh, len);
        kfree(vrh);
        return aq_ret;
@@ -2143,13 +2634,13 @@ err:
  **/
 static int i40e_vc_set_rss_hena(struct i40e_vf *vf, u8 *msg, u16 msglen)
 {
-       struct i40e_virtchnl_rss_hena *vrh =
-               (struct i40e_virtchnl_rss_hena *)msg;
+       struct virtchnl_rss_hena *vrh =
+               (struct virtchnl_rss_hena *)msg;
        struct i40e_pf *pf = vf->pf;
        struct i40e_hw *hw = &pf->hw;
        i40e_status aq_ret = 0;
 
-       if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states)) {
+       if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) {
                aq_ret = I40E_ERR_PARAM;
                goto err;
        }
@@ -2159,144 +2650,61 @@ static int i40e_vc_set_rss_hena(struct i40e_vf *vf, u8 *msg, u16 msglen)
 
        /* send the response to the VF */
 err:
-       return i40e_vc_send_resp_to_vf(vf, I40E_VIRTCHNL_OP_SET_RSS_HENA,
-                                      aq_ret);
+       return i40e_vc_send_resp_to_vf(vf, VIRTCHNL_OP_SET_RSS_HENA, aq_ret);
 }
 
 /**
- * i40e_vc_validate_vf_msg
+ * i40e_vc_enable_vlan_stripping
  * @vf: pointer to the VF info
  * @msg: pointer to the msg buffer
  * @msglen: msg length
- * @msghndl: msg handle
  *
- * validate msg
+ * Enable vlan header stripping for the VF
  **/
-static int i40e_vc_validate_vf_msg(struct i40e_vf *vf, u32 v_opcode,
-                                  u32 v_retval, u8 *msg, u16 msglen)
+static int i40e_vc_enable_vlan_stripping(struct i40e_vf *vf, u8 *msg,
+                                        u16 msglen)
 {
-       bool err_msg_format = false;
-       int valid_len = 0;
-
-       /* Check if VF is disabled. */
-       if (test_bit(I40E_VF_STAT_DISABLED, &vf->vf_states))
-               return I40E_ERR_PARAM;
+       struct i40e_vsi *vsi = vf->pf->vsi[vf->lan_vsi_idx];
+       i40e_status aq_ret = 0;
 
-       /* Validate message length. */
-       switch (v_opcode) {
-       case I40E_VIRTCHNL_OP_VERSION:
-               valid_len = sizeof(struct i40e_virtchnl_version_info);
-               break;
-       case I40E_VIRTCHNL_OP_RESET_VF:
-               break;
-       case I40E_VIRTCHNL_OP_GET_VF_RESOURCES:
-               if (VF_IS_V11(vf))
-                       valid_len = sizeof(u32);
-               break;
-       case I40E_VIRTCHNL_OP_CONFIG_TX_QUEUE:
-               valid_len = sizeof(struct i40e_virtchnl_txq_info);
-               break;
-       case I40E_VIRTCHNL_OP_CONFIG_RX_QUEUE:
-               valid_len = sizeof(struct i40e_virtchnl_rxq_info);
-               break;
-       case I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES:
-               valid_len = sizeof(struct i40e_virtchnl_vsi_queue_config_info);
-               if (msglen >= valid_len) {
-                       struct i40e_virtchnl_vsi_queue_config_info *vqc =
-                           (struct i40e_virtchnl_vsi_queue_config_info *)msg;
-                       valid_len += (vqc->num_queue_pairs *
-                                     sizeof(struct
-                                            i40e_virtchnl_queue_pair_info));
-                       if (vqc->num_queue_pairs == 0)
-                               err_msg_format = true;
-               }
-               break;
-       case I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP:
-               valid_len = sizeof(struct i40e_virtchnl_irq_map_info);
-               if (msglen >= valid_len) {
-                       struct i40e_virtchnl_irq_map_info *vimi =
-                           (struct i40e_virtchnl_irq_map_info *)msg;
-                       valid_len += (vimi->num_vectors *
-                                     sizeof(struct i40e_virtchnl_vector_map));
-                       if (vimi->num_vectors == 0)
-                               err_msg_format = true;
-               }
-               break;
-       case I40E_VIRTCHNL_OP_ENABLE_QUEUES:
-       case I40E_VIRTCHNL_OP_DISABLE_QUEUES:
-               valid_len = sizeof(struct i40e_virtchnl_queue_select);
-               break;
-       case I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS:
-       case I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS:
-               valid_len = sizeof(struct i40e_virtchnl_ether_addr_list);
-               if (msglen >= valid_len) {
-                       struct i40e_virtchnl_ether_addr_list *veal =
-                           (struct i40e_virtchnl_ether_addr_list *)msg;
-                       valid_len += veal->num_elements *
-                           sizeof(struct i40e_virtchnl_ether_addr);
-                       if (veal->num_elements == 0)
-                               err_msg_format = true;
-               }
-               break;
-       case I40E_VIRTCHNL_OP_ADD_VLAN:
-       case I40E_VIRTCHNL_OP_DEL_VLAN:
-               valid_len = sizeof(struct i40e_virtchnl_vlan_filter_list);
-               if (msglen >= valid_len) {
-                       struct i40e_virtchnl_vlan_filter_list *vfl =
-                           (struct i40e_virtchnl_vlan_filter_list *)msg;
-                       valid_len += vfl->num_elements * sizeof(u16);
-                       if (vfl->num_elements == 0)
-                               err_msg_format = true;
-               }
-               break;
-       case I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE:
-               valid_len = sizeof(struct i40e_virtchnl_promisc_info);
-               break;
-       case I40E_VIRTCHNL_OP_GET_STATS:
-               valid_len = sizeof(struct i40e_virtchnl_queue_select);
-               break;
-       case I40E_VIRTCHNL_OP_CONFIG_RSS_KEY:
-               valid_len = sizeof(struct i40e_virtchnl_rss_key);
-               if (msglen >= valid_len) {
-                       struct i40e_virtchnl_rss_key *vrk =
-                               (struct i40e_virtchnl_rss_key *)msg;
-                       if (vrk->key_len != I40E_HKEY_ARRAY_SIZE) {
-                               err_msg_format = true;
-                               break;
-                       }
-                       valid_len += vrk->key_len - 1;
-               }
-               break;
-       case I40E_VIRTCHNL_OP_CONFIG_RSS_LUT:
-               valid_len = sizeof(struct i40e_virtchnl_rss_lut);
-               if (msglen >= valid_len) {
-                       struct i40e_virtchnl_rss_lut *vrl =
-                               (struct i40e_virtchnl_rss_lut *)msg;
-                       if (vrl->lut_entries != I40E_VF_HLUT_ARRAY_SIZE) {
-                               err_msg_format = true;
-                               break;
-                       }
-                       valid_len += vrl->lut_entries - 1;
-               }
-               break;
-       case I40E_VIRTCHNL_OP_GET_RSS_HENA_CAPS:
-               break;
-       case I40E_VIRTCHNL_OP_SET_RSS_HENA:
-               valid_len = sizeof(struct i40e_virtchnl_rss_hena);
-               break;
-       /* These are always errors coming from the VF. */
-       case I40E_VIRTCHNL_OP_EVENT:
-       case I40E_VIRTCHNL_OP_UNKNOWN:
-       default:
-               return -EPERM;
+       if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) {
+               aq_ret = I40E_ERR_PARAM;
+               goto err;
        }
-       /* few more checks */
-       if ((valid_len != msglen) || (err_msg_format)) {
-               i40e_vc_send_resp_to_vf(vf, v_opcode, I40E_ERR_PARAM);
-               return -EINVAL;
-       } else {
-               return 0;
+
+       i40e_vlan_stripping_enable(vsi);
+
+       /* send the response to the VF */
+err:
+       return i40e_vc_send_resp_to_vf(vf, VIRTCHNL_OP_ENABLE_VLAN_STRIPPING,
+                                      aq_ret);
+}
+
+/**
+ * i40e_vc_disable_vlan_stripping
+ * @vf: pointer to the VF info
+ * @msg: pointer to the msg buffer
+ * @msglen: msg length
+ *
+ * Disable vlan header stripping for the VF
+ **/
+static int i40e_vc_disable_vlan_stripping(struct i40e_vf *vf, u8 *msg,
+                                         u16 msglen)
+{
+       struct i40e_vsi *vsi = vf->pf->vsi[vf->lan_vsi_idx];
+       i40e_status aq_ret = 0;
+
+       if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) {
+               aq_ret = I40E_ERR_PARAM;
+               goto err;
        }
+
+       i40e_vlan_stripping_disable(vsi);
+
+       /* send the response to the VF */
+err:
+       return i40e_vc_send_resp_to_vf(vf, VIRTCHNL_OP_DISABLE_VLAN_STRIPPING,
+                                      aq_ret);
 }
 
 /**
@@ -2322,71 +2730,113 @@ int i40e_vc_process_vf_msg(struct i40e_pf *pf, s16 vf_id, u32 v_opcode,
        if (local_vf_id >= pf->num_alloc_vfs)
                return -EINVAL;
        vf = &(pf->vf[local_vf_id]);
+
+       /* Check if VF is disabled. */
+       if (test_bit(I40E_VF_STATE_DISABLED, &vf->vf_states))
+               return I40E_ERR_PARAM;
+
        /* perform basic checks on the msg */
-       ret = i40e_vc_validate_vf_msg(vf, v_opcode, v_retval, msg, msglen);
+       ret = virtchnl_vc_validate_vf_msg(&vf->vf_ver, v_opcode, msg, msglen);
+
+       /* perform additional checks specific to this driver */
+       if (v_opcode == VIRTCHNL_OP_CONFIG_RSS_KEY) {
+               struct virtchnl_rss_key *vrk = (struct virtchnl_rss_key *)msg;
+
+               if (vrk->key_len != I40E_HKEY_ARRAY_SIZE)
+                       ret = -EINVAL;
+       } else if (v_opcode == VIRTCHNL_OP_CONFIG_RSS_LUT) {
+               struct virtchnl_rss_lut *vrl = (struct virtchnl_rss_lut *)msg;
+
+               if (vrl->lut_entries != I40E_VF_HLUT_ARRAY_SIZE)
+                       ret = -EINVAL;
+       }
 
        if (ret) {
+               i40e_vc_send_resp_to_vf(vf, v_opcode, I40E_ERR_PARAM);
                dev_err(&pf->pdev->dev, "Invalid message from VF %d, opcode %d, len %d\n",
                        local_vf_id, v_opcode, msglen);
-               return ret;
+               switch (ret) {
+               case VIRTCHNL_ERR_PARAM:
+                       return -EPERM;
+               default:
+                       return -EINVAL;
+               }
        }
 
        switch (v_opcode) {
-       case I40E_VIRTCHNL_OP_VERSION:
+       case VIRTCHNL_OP_VERSION:
                ret = i40e_vc_get_version_msg(vf, msg);
                break;
-       case I40E_VIRTCHNL_OP_GET_VF_RESOURCES:
+       case VIRTCHNL_OP_GET_VF_RESOURCES:
                ret = i40e_vc_get_vf_resources_msg(vf, msg);
                break;
-       case I40E_VIRTCHNL_OP_RESET_VF:
+       case VIRTCHNL_OP_RESET_VF:
                i40e_vc_reset_vf_msg(vf);
                ret = 0;
                break;
-       case I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE:
+       case VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE:
                ret = i40e_vc_config_promiscuous_mode_msg(vf, msg, msglen);
                break;
-       case I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES:
+       case VIRTCHNL_OP_CONFIG_VSI_QUEUES:
                ret = i40e_vc_config_queues_msg(vf, msg, msglen);
                break;
-       case I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP:
+       case VIRTCHNL_OP_CONFIG_IRQ_MAP:
                ret = i40e_vc_config_irq_map_msg(vf, msg, msglen);
                break;
-       case I40E_VIRTCHNL_OP_ENABLE_QUEUES:
+       case VIRTCHNL_OP_ENABLE_QUEUES:
                ret = i40e_vc_enable_queues_msg(vf, msg, msglen);
                i40e_vc_notify_vf_link_state(vf);
                break;
-       case I40E_VIRTCHNL_OP_DISABLE_QUEUES:
+       case VIRTCHNL_OP_DISABLE_QUEUES:
                ret = i40e_vc_disable_queues_msg(vf, msg, msglen);
                break;
-       case I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS:
+       case VIRTCHNL_OP_ADD_ETH_ADDR:
                ret = i40e_vc_add_mac_addr_msg(vf, msg, msglen);
                break;
-       case I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS:
+       case VIRTCHNL_OP_DEL_ETH_ADDR:
                ret = i40e_vc_del_mac_addr_msg(vf, msg, msglen);
                break;
-       case I40E_VIRTCHNL_OP_ADD_VLAN:
+       case VIRTCHNL_OP_ADD_VLAN:
                ret = i40e_vc_add_vlan_msg(vf, msg, msglen);
                break;
-       case I40E_VIRTCHNL_OP_DEL_VLAN:
+       case VIRTCHNL_OP_DEL_VLAN:
                ret = i40e_vc_remove_vlan_msg(vf, msg, msglen);
                break;
-       case I40E_VIRTCHNL_OP_GET_STATS:
+       case VIRTCHNL_OP_GET_STATS:
                ret = i40e_vc_get_stats_msg(vf, msg, msglen);
                break;
-       case I40E_VIRTCHNL_OP_CONFIG_RSS_KEY:
+       case VIRTCHNL_OP_IWARP:
+               ret = i40e_vc_iwarp_msg(vf, msg, msglen);
+               break;
+       case VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP:
+               ret = i40e_vc_iwarp_qvmap_msg(vf, msg, msglen, true);
+               break;
+       case VIRTCHNL_OP_RELEASE_IWARP_IRQ_MAP:
+               ret = i40e_vc_iwarp_qvmap_msg(vf, msg, msglen, false);
+               break;
+       case VIRTCHNL_OP_CONFIG_RSS_KEY:
                ret = i40e_vc_config_rss_key(vf, msg, msglen);
                break;
-       case I40E_VIRTCHNL_OP_CONFIG_RSS_LUT:
+       case VIRTCHNL_OP_CONFIG_RSS_LUT:
                ret = i40e_vc_config_rss_lut(vf, msg, msglen);
                break;
-       case I40E_VIRTCHNL_OP_GET_RSS_HENA_CAPS:
+       case VIRTCHNL_OP_GET_RSS_HENA_CAPS:
                ret = i40e_vc_get_rss_hena(vf, msg, msglen);
                break;
-       case I40E_VIRTCHNL_OP_SET_RSS_HENA:
+       case VIRTCHNL_OP_SET_RSS_HENA:
                ret = i40e_vc_set_rss_hena(vf, msg, msglen);
                break;
+       case VIRTCHNL_OP_ENABLE_VLAN_STRIPPING:
+               ret = i40e_vc_enable_vlan_stripping(vf, msg, msglen);
+               break;
+       case VIRTCHNL_OP_DISABLE_VLAN_STRIPPING:
+               ret = i40e_vc_disable_vlan_stripping(vf, msg, msglen);
+               break;
+       case VIRTCHNL_OP_REQUEST_QUEUES:
+               ret = i40e_vc_request_queues_msg(vf, msg, msglen);
+               break;
 
-       case I40E_VIRTCHNL_OP_UNKNOWN:
+       case VIRTCHNL_OP_UNKNOWN:
        default:
                dev_err(&pf->pdev->dev, "Unsupported opcode %d from VF %d\n",
                        v_opcode, local_vf_id);
@@ -2412,7 +2862,7 @@ int i40e_vc_process_vflr_event(struct i40e_pf *pf)
        struct i40e_vf *vf;
        int vf_id;
 
-       if (!test_bit(__I40E_VFLR_EVENT_PENDING, &pf->state))
+       if (!test_bit(__I40E_VFLR_EVENT_PENDING, pf->state))
                return 0;
 
        /* Re-enable the VFLR interrupt cause here, before looking for which
@@ -2425,7 +2875,7 @@ int i40e_vc_process_vflr_event(struct i40e_pf *pf)
        wr32(hw, I40E_PFINT_ICR0_ENA, reg);
        i40e_flush(hw);
 
-       clear_bit(__I40E_VFLR_EVENT_PENDING, &pf->state);
+       clear_bit(__I40E_VFLR_EVENT_PENDING, pf->state);
        for (vf_id = 0; vf_id < pf->num_alloc_vfs; vf_id++) {
                reg_idx = (hw->func_caps.vf_base_id + vf_id) / 32;
                bit_idx = (hw->func_caps.vf_base_id + vf_id) % 32;
@@ -2470,7 +2920,7 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
 
        vf = &(pf->vf[vf_id]);
        vsi = pf->vsi[vf->lan_vsi_idx];
-       if (!test_bit(I40E_VF_STAT_INIT, &vf->vf_states)) {
+       if (!test_bit(I40E_VF_STATE_INIT, &vf->vf_states)) {
                dev_err(&pf->pdev->dev, "VF %d still in reset. Try again.\n",
                        vf_id);
                ret = -EAGAIN;
@@ -2511,13 +2961,41 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
        ether_addr_copy(vf->default_lan_addr.addr, mac);
        vf->pf_set_mac = true;
        /* Force the VF driver stop so it has to reload with new MAC address */
-       i40e_vc_disable_vf(pf, vf);
+       i40e_vc_disable_vf(vf);
        dev_info(&pf->pdev->dev, "Reload the VF driver to make this change effective.\n");
 
 error_param:
        return ret;
 }
 
+/**
+ * i40e_vsi_has_vlans - True if VSI has configured VLANs
+ * @vsi: pointer to the vsi
+ *
+ * Check if a VSI has configured any VLANs. False if we have a port VLAN or if
+ * we have no configured VLANs. Do not call while holding the
+ * mac_filter_hash_lock.
+ */
+static bool i40e_vsi_has_vlans(struct i40e_vsi *vsi)
+{
+       bool have_vlans;
+
+       /* If we have a port VLAN, then the VSI cannot have any VLANs
+        * configured, as all MAC/VLAN filters will be assigned to the PVID.
+        */
+       if (vsi->info.pvid)
+               return false;
+
+       /* Since we don't have a PVID, we know that if the device is in VLAN
+        * mode it must be because of a VLAN filter configured on this VSI.
+        */
+       spin_lock_bh(&vsi->mac_filter_hash_lock);
+       have_vlans = i40e_is_vsi_in_vlan(vsi);
+       spin_unlock_bh(&vsi->mac_filter_hash_lock);
+
+       return have_vlans;
+}
+
 #ifdef IFLA_VF_VLAN_INFO_MAX
 /**
  * i40e_ndo_set_vf_port_vlan
@@ -2565,15 +3043,17 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev,
                goto error_pvid;
        }
 #ifdef IFLA_VF_VLAN_INFO_MAX
+
        if (vlan_proto != htons(ETH_P_8021Q)) {
                dev_err(&pf->pdev->dev, "VF VLAN protocol is not supported\n");
                ret = -EPROTONOSUPPORT;
                goto error_pvid;
        }
 #endif
+
        vf = &(pf->vf[vf_id]);
        vsi = pf->vsi[vf->lan_vsi_idx];
-       if (!test_bit(I40E_VF_STAT_INIT, &vf->vf_states)) {
+       if (!test_bit(I40E_VF_STATE_INIT, &vf->vf_states)) {
                dev_err(&pf->pdev->dev, "VF %d still in reset. Try again.\n",
                        vf_id);
                ret = -EAGAIN;
@@ -2584,10 +3064,7 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev,
                /* duplicate request, so just return success */
                goto error_pvid;
 
-       /* Locked once because multiple functions below iterate list */
-       spin_lock_bh(&vsi->mac_filter_hash_lock);
-
-       if (le16_to_cpu(vsi->info.pvid) == 0 && i40e_is_vsi_in_vlan(vsi)) {
+       if (i40e_vsi_has_vlans(vsi)) {
                dev_err(&pf->pdev->dev,
                        "VF %d has already configured VLAN filters and the administrator is requesting a port VLAN override.\nPlease unload and reload the VF driver for this change to take effect.\n",
                        vf_id);
@@ -2595,11 +3072,14 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev,
                 * the right thing by reconfiguring his network correctly
                 * and then reloading the VF driver.
                 */
-               i40e_vc_disable_vf(pf, vf);
+               i40e_vc_disable_vf(vf);
                /* During reset the VF got a new VSI, so refresh the pointer. */
                vsi = pf->vsi[vf->lan_vsi_idx];
        }
 
+       /* Locked once because multiple functions below iterate list */
+       spin_lock_bh(&vsi->mac_filter_hash_lock);
+
        /* Check for condition where there was already a port VLAN ID
         * filter set and now it is being deleted by setting it to zero.
         * Additionally check for the condition where there was a port
@@ -2627,10 +3107,12 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev,
                                           VLAN_VID_MASK));
        }
 
+       spin_unlock_bh(&vsi->mac_filter_hash_lock);
        if (vlan_id || qos)
                ret = i40e_vsi_add_pvid(vsi, vlanprio);
        else
                i40e_vsi_remove_pvid(vsi);
+       spin_lock_bh(&vsi->mac_filter_hash_lock);
 
        if (vlan_id) {
                dev_info(&pf->pdev->dev, "Setting VLAN %d, QOS 0x%x on VF %d\n",
@@ -2703,7 +3185,7 @@ int i40e_ndo_set_vf_bw(struct net_device *netdev, int vf_id, int max_tx_rate)
 
        vf = &(pf->vf[vf_id]);
        vsi = pf->vsi[vf->lan_vsi_idx];
-       if (!test_bit(I40E_VF_STAT_INIT, &vf->vf_states)) {
+       if (!test_bit(I40E_VF_STATE_INIT, &vf->vf_states)) {
                dev_err(&pf->pdev->dev, "VF %d still in reset. Try again.\n",
                        vf_id);
                ret = -EAGAIN;
@@ -2796,7 +3278,7 @@ int i40e_ndo_get_vf_config(struct net_device *netdev,
        vf = &(pf->vf[vf_id]);
        /* first vsi is always the LAN vsi */
        vsi = pf->vsi[vf->lan_vsi_idx];
-       if (!test_bit(I40E_VF_STAT_INIT, &vf->vf_states)) {
+       if (!test_bit(I40E_VF_STATE_INIT, &vf->vf_states)) {
                dev_err(&pf->pdev->dev, "VF %d still in reset. Try again.\n",
                        vf_id);
                ret = -EAGAIN;
@@ -2827,6 +3309,9 @@ int i40e_ndo_get_vf_config(struct net_device *netdev,
 #ifdef HAVE_VF_SPOOFCHK_CONFIGURE
        ivi->spoofchk = vf->spoofchk;
 #endif
+#ifdef HAVE_NDO_SET_VF_TRUST
+       ivi->trusted = vf->trusted;
+#endif /* HAVE_NDO_SET_VF_TRUST */
        ret = 0;
 
 error_param:
@@ -2846,7 +3331,8 @@ int i40e_ndo_set_vf_link_state(struct net_device *netdev, int vf_id, int link)
 {
        struct i40e_netdev_priv *np = netdev_priv(netdev);
        struct i40e_pf *pf = np->vsi->back;
-       struct i40e_virtchnl_pf_event pfe;
+       struct i40e_link_status *ls = &pf->hw.phy.link_info;
+       struct virtchnl_pf_event pfe;
        struct i40e_hw *hw = &pf->hw;
        struct i40e_vf *vf;
        int abs_vf_id;
@@ -2862,16 +3348,16 @@ int i40e_ndo_set_vf_link_state(struct net_device *netdev, int vf_id, int link)
        vf = &pf->vf[vf_id];
        abs_vf_id = vf->vf_id + hw->func_caps.vf_base_id;
 
-       pfe.event = I40E_VIRTCHNL_EVENT_LINK_CHANGE;
-       pfe.severity = I40E_PF_EVENT_SEVERITY_INFO;
+       pfe.event = VIRTCHNL_EVENT_LINK_CHANGE;
+       pfe.severity = PF_EVENT_SEVERITY_INFO;
 
        switch (link) {
        case IFLA_VF_LINK_STATE_AUTO:
                vf->link_forced = false;
                pfe.event_data.link_event.link_status =
-                       pf->hw.phy.link_info.link_info & I40E_AQ_LINK_UP;
+                       ls->link_info & I40E_AQ_LINK_UP;
                pfe.event_data.link_event.link_speed =
-                       pf->hw.phy.link_info.link_speed;
+                       (enum virtchnl_link_speed)ls->link_speed;
                break;
        case IFLA_VF_LINK_STATE_ENABLE:
                vf->link_forced = true;
@@ -2890,7 +3376,7 @@ int i40e_ndo_set_vf_link_state(struct net_device *netdev, int vf_id, int link)
                goto error_out;
        }
        /* Notify the VF of its new link state */
-       i40e_aq_send_msg_to_vf(hw, abs_vf_id, I40E_VIRTCHNL_OP_EVENT,
+       i40e_aq_send_msg_to_vf(hw, abs_vf_id, VIRTCHNL_OP_EVENT,
                               I40E_SUCCESS, (u8 *)&pfe, sizeof(pfe), NULL);
 
 error_out:
@@ -2925,7 +3411,7 @@ int i40e_ndo_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool enable)
        }
 
        vf = &(pf->vf[vf_id]);
-       if (!test_bit(I40E_VF_STAT_INIT, &vf->vf_states)) {
+       if (!test_bit(I40E_VF_STATE_INIT, &vf->vf_states)) {
                dev_err(&pf->pdev->dev, "VF %d still in reset. Try again.\n",
                        vf_id);
                ret = -EAGAIN;
@@ -2990,8 +3476,7 @@ int i40e_ndo_set_vf_trust(struct net_device *netdev, int vf_id, bool setting)
                goto out;
 
        vf->trusted = setting;
-       i40e_vc_notify_vf_reset(vf);
-       i40e_reset_vf(vf, false);
+       i40e_vc_disable_vf(vf);
        dev_info(&pf->pdev->dev, "VF %u is now %strusted\n",
                 vf_id, setting ? "" : "un");
 out:
similarity index 87%
rename from i40e-dkms/i40e-1.6.42/src/i40e_virtchnl_pf.h
rename to i40e-dkms/i40e-2.1.26/src/i40e_virtchnl_pf.h
index 3025654f7990b678a6794a6560ade18d79ebbd36..8f20b4745fb7f96486bbc43289fe0ae2b8d7d87f 100644 (file)
@@ -37,9 +37,6 @@
 #define I40E_VLAN_MASK                 0xFFF
 #define I40E_PRIORITY_MASK             0x7000
 
-#define VF_IS_V10(_v) (((_v)->vf_ver.major == 1) && ((_v)->vf_ver.minor == 0))
-#define VF_IS_V11(_v) (((_v)->vf_ver.major == 1) && ((_v)->vf_ver.minor == 1))
-
 /* Various queue ctrls */
 enum i40e_queue_ctrl {
        I40E_QUEUE_CTRL_UNKNOWN = 0,
@@ -53,21 +50,20 @@ enum i40e_queue_ctrl {
 
 /* VF states */
 enum i40e_vf_states {
-       I40E_VF_STAT_INIT = 0,
-       I40E_VF_STAT_ACTIVE,
-       I40E_VF_STAT_FCOEENA,
-       I40E_VF_STAT_DISABLED,
-       I40E_VF_STAT_MC_PROMISC,
-       I40E_VF_STAT_UC_PROMISC,
+       I40E_VF_STATE_INIT = 0,
+       I40E_VF_STATE_ACTIVE,
+       I40E_VF_STATE_IWARPENA,
+       I40E_VF_STATE_DISABLED,
+       I40E_VF_STATE_MC_PROMISC,
+       I40E_VF_STATE_UC_PROMISC,
+       I40E_VF_STATE_PRE_ENABLE,
 };
 
 /* VF capabilities */
 enum i40e_vf_capabilities {
        I40E_VIRTCHNL_VF_CAP_PRIVILEGE = 0,
        I40E_VIRTCHNL_VF_CAP_L2,
-#ifdef I40E_FCOE
-       I40E_VIRTCHNL_VF_CAP_FCOE,
-#endif
+       I40E_VIRTCHNL_VF_CAP_IWARP,
 };
 
 /* VF information structure */
@@ -78,14 +74,13 @@ struct i40e_vf {
        s16 vf_id;
        /* all VF vsis connect to the same parent */
        enum i40e_switch_element_types parent_type;
-       struct i40e_virtchnl_version_info vf_ver;
+       struct virtchnl_version_info vf_ver;
        u32 driver_caps; /* reported by VF driver */
 
        /* VF Port Extender (PE) stag if used */
        u16 stag;
 
-       struct i40e_virtchnl_ether_addr default_lan_addr;
-       struct i40e_virtchnl_ether_addr default_fcoe_addr;
+       struct virtchnl_ether_addr default_lan_addr;
        u16 port_vlan_id;
        bool pf_set_mac;        /* The VMM admin set the VF MAC address */
        bool trusted;
@@ -96,12 +91,9 @@ struct i40e_vf {
         */
        u16 lan_vsi_idx;        /* index into PF struct */
        u16 lan_vsi_id;         /* ID as used by firmware */
-#ifdef I40E_FCOE
-       u8 fcoe_vsi_index;
-       u8 fcoe_vsi_id;
-#endif
 
        u8 num_queue_pairs;     /* num of qps assigned to VF vsis */
+       u8 num_req_queues;      /* num of requested qps */
        u64 num_mdd_events;     /* num of mdd events detected */
        /* num of continuous malformed or invalid msgs detected */
        u64 num_invalid_msgs;
@@ -119,7 +111,7 @@ struct i40e_vf {
        u16 num_vlan;
 
        /* RDMA Client */
-       struct i40e_virtchnl_iwarp_qvlist_info *qvlist_info;
+       struct virtchnl_iwarp_qvlist_info *qvlist_info;
 };
 
 void i40e_free_vfs(struct i40e_pf *pf);
@@ -130,7 +122,8 @@ int i40e_alloc_vfs(struct i40e_pf *pf, u16 num_alloc_vfs);
 int i40e_vc_process_vf_msg(struct i40e_pf *pf, s16 vf_id, u32 v_opcode,
                           u32 v_retval, u8 *msg, u16 msglen);
 int i40e_vc_process_vflr_event(struct i40e_pf *pf);
-void i40e_reset_vf(struct i40e_vf *vf, bool flr);
+bool i40e_reset_vf(struct i40e_vf *vf, bool flr);
+bool i40e_reset_all_vfs(struct i40e_pf *pf, bool flr);
 void i40e_vc_notify_vf_reset(struct i40e_vf *vf);
 
 /* VF configuration related iplink handlers */
similarity index 95%
rename from i40e-dkms/i40e-1.6.42/src/kcompat.c
rename to i40e-dkms/i40e-2.1.26/src/kcompat.c
index 9ae8bb20f3610ed019c9e795b3ce943a679e82ca..3b12bca6d0490e15f5d5464a6be0243acc1b51d3 100644 (file)
@@ -25,7 +25,7 @@
 #include "kcompat.h"
 
 /*****************************************************************************/
-#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,8) )
+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,8) ) || defined __VMKLNX__
 /* From lib/vsprintf.c */
 #include <asm/div64.h>
 
@@ -270,16 +270,20 @@ int _kc_vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
                                continue;
 
                        case 'p':
-                               if (field_width == -1) {
-                                       field_width = 2*sizeof(void *);
-                                       flags |= _kc_ZEROPAD;
+                               if ('M' == *(fmt+1)) {
+                                       str = get_mac(str, end, va_arg(args, unsigned char *));
+                                       fmt++;
+                               } else  {
+                                       if (field_width == -1) {
+                                               field_width = 2*sizeof(void *);
+                                               flags |= _kc_ZEROPAD;
+                                       }
+                                       str = number(str, end,
+                                                       (unsigned long) va_arg(args, void *),
+                                                       16, field_width, precision, flags);
                                }
-                               str = number(str, end,
-                                               (unsigned long) va_arg(args, void *),
-                                               16, field_width, precision, flags);
                                continue;
 
-
                        case 'n':
                                /* FIXME:
                                * What does C99 say about the overflow case here? */
@@ -1578,7 +1582,7 @@ struct _kc_netdev_queue_attribute {
 #define to_kc_netdev_queue_attr(_attr) container_of(_attr,             \
     struct _kc_netdev_queue_attribute, attr)
 
-int __kc_netif_set_xps_queue(struct net_device *dev, struct cpumask *mask,
+int __kc_netif_set_xps_queue(struct net_device *dev, const struct cpumask *mask,
                             u16 index)
 {
        struct netdev_queue *txq = netdev_get_tx_queue(dev, index);
@@ -1923,6 +1927,23 @@ int __kc_pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries,
 }
 #endif /* 3.14.0 */
 
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,15,0))
+char *_kc_devm_kstrdup(struct device *dev, const char *s, gfp_t gfp)
+{
+       size_t size;
+       char *buf;
+
+       if (!s)
+               return NULL;
+
+       size = strlen(s) + 1;
+       buf = devm_kzalloc(dev, size, gfp);
+       if (buf)
+               memcpy(buf, s, size);
+       return buf;
+}
+#endif /* 3.15.0 */
+
 #if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0) )
 #ifdef HAVE_SET_RX_MODE
 #ifdef NETDEV_HW_ADDR_T_UNICAST
@@ -2067,6 +2088,17 @@ void __kc_dev_addr_unsync_dev(struct dev_addr_list **list, int *count,
 }
 #endif /* NETDEV_HW_ADDR_T_MULTICAST  */
 #endif /* HAVE_SET_RX_MODE */
+void *__kc_devm_kmemdup(struct device *dev, const void *src, size_t len,
+                       unsigned int gfp)
+{
+       void *p;
+
+       p = devm_kzalloc(dev, len, gfp);
+       if (p)
+               memcpy(p, src, len);
+
+       return p;
+}
 #endif /* 3.16.0 */
 
 /******************************************************************************/
@@ -2254,6 +2286,53 @@ void __kc_netdev_rss_key_fill(void *buffer, size_t len)
 #endif
 #endif
 
+/******************************************************************************/
+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(4,1,0) )
+#if !((RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(6,8) && RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,0)) && \
+      (RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(7,2)) && \
+      (SLE_VERSION_CODE > SLE_VERSION(12,1,0)))
+unsigned int _kc_cpumask_local_spread(unsigned int i, int node)
+{
+       int cpu;
+
+       /* Wrap: we always want a cpu. */
+       i %= num_online_cpus();
+
+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) )
+       /* Kernels prior to 2.6.28 do not have for_each_cpu or
+        * cpumask_of_node, so just use for_each_online_cpu()
+        */
+       for_each_online_cpu(cpu)
+               if (i-- == 0)
+                       return cpu;
+
+       return 0;
+#else
+       if (node == -1) {
+               for_each_cpu(cpu, cpu_online_mask)
+                       if (i-- == 0)
+                               return cpu;
+       } else {
+               /* NUMA first. */
+               for_each_cpu_and(cpu, cpumask_of_node(node), cpu_online_mask)
+                       if (i-- == 0)
+                               return cpu;
+
+               for_each_cpu(cpu, cpu_online_mask) {
+                       /* Skip NUMA nodes, done above. */
+                       if (cpumask_test_cpu(cpu, cpumask_of_node(node)))
+                               continue;
+
+                       if (i-- == 0)
+                               return cpu;
+               }
+       }
+#endif /* KERNEL_VERSION >= 2.6.28 */
+       BUG();
+}
+#endif
+#endif
+
 /******************************************************************************/
 #if ( LINUX_VERSION_CODE < KERNEL_VERSION(4,5,0) )
 #if (!(RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7,3)))
@@ -2261,8 +2340,14 @@ void __kc_netdev_rss_key_fill(void *buffer, size_t len)
 #include <asm/idprom.h>
 #include <asm/prom.h>
 #endif
-int _kc_eth_platform_get_mac_address(struct device *dev, u8 *mac_addr)
+int _kc_eth_platform_get_mac_address(struct device *dev __maybe_unused,
+                                    u8 *mac_addr __maybe_unused)
 {
+#if (((LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0)) && defined(CONFIG_OF) && \
+      !defined(HAVE_STRUCT_DEVICE_OF_NODE) || !defined(CONFIG_OF)) && \
+     !defined(CONFIG_SPARC))
+       return -ENODEV;
+#else
        const unsigned char *addr;
        struct device_node *dp;
 
@@ -2292,6 +2377,7 @@ int _kc_eth_platform_get_mac_address(struct device *dev, u8 *mac_addr)
 
        ether_addr_copy(mac_addr, addr);
        return 0;
+#endif
 }
 #endif /* !(RHEL_RELEASE >= 7.3) */
 #endif
similarity index 95%
rename from i40e-dkms/i40e-1.6.42/src/kcompat.h
rename to i40e-dkms/i40e-2.1.26/src/kcompat.h
index 8eac8ab86e0922c760415720284e358b90325c71..477e6be52998651f28267b26887c74c602840032 100644 (file)
@@ -863,9 +863,12 @@ struct _kc_ethtool_pauseparam {
 /* SLES12 SP1 GA is 3.12.49-11
  * updates 3.12.xx-60.yy where xx={51..} */
 #define SLE_VERSION_CODE SLE_VERSION(12,1,0)
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,21))
+#elif (LINUX_VERSION_CODE == KERNEL_VERSION(4,4,21))
 /* SLES12 SP2 GA is 4.4.21-69 */
 #define SLE_VERSION_CODE SLE_VERSION(12,2,0)
+/* SLES12 SP3 Beta3 is 4.4.68-2 */
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,68))
+#define SLE_VERSION_CODE SLE_VERSION(12,3,0)
 /* new SLES kernels must be added here with >= based on kernel
  * the idea is to order from newest to oldest and just catch all
  * of them using the >=
@@ -880,10 +883,66 @@ struct _kc_ethtool_pauseparam {
 #endif /* SLE_LOCALVERSION_CODE */
 
 #ifdef __KLOCWORK__
+/* The following are not compiled into the binary driver; they are here
+ * only to tune Klocwork scans to workaround false-positive issues.
+ */
 #ifdef ARRAY_SIZE
 #undef ARRAY_SIZE
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
 #endif
+
+#define memcpy(dest, src, len) memcpy_s(dest, len, src, len)
+
+static inline int _kc_test_and_clear_bit(int nr, volatile unsigned long *addr)
+{
+       unsigned long mask = BIT_MASK(nr);
+       unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
+       unsigned long old;
+       unsigned long flags = 0;
+
+       _atomic_spin_lock_irqsave(p, flags);
+       old = *p;
+       *p = old & ~mask;
+       _atomic_spin_unlock_irqrestore(p, flags);
+
+       return (old & mask) != 0;
+}
+#define test_and_clear_bit(nr, addr) _kc_test_and_clear_bit(nr, addr)
+
+static inline int _kc_test_and_set_bit(int nr, volatile unsigned long *addr)
+{
+       unsigned long mask = BIT_MASK(nr);
+       unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
+       unsigned long old;
+       unsigned long flags = 0;
+
+       _atomic_spin_lock_irqsave(p, flags);
+       old = *p;
+       *p = old | mask;
+       _atomic_spin_unlock_irqrestore(p, flags);
+
+       return (old & mask) != 0;
+}
+#define test_and_set_bit(nr, addr) _kc_test_and_set_bit(nr, addr)
+
+#ifdef CONFIG_DYNAMIC_DEBUG
+#undef dev_dbg
+#define dev_dbg(dev, format, arg...) dev_printk(KERN_DEBUG, dev, format, ##arg)
+#endif /* CONFIG_DYNAMIC_DEBUG */
+
+#undef list_for_each_entry_safe
+#define list_for_each_entry_safe(pos, n, head, member)                    \
+       for (n = NULL, pos = list_first_entry(head, typeof(*pos), member); \
+            &pos->member != (head);                                       \
+            pos = list_next_entry(pos, member))
+
+#undef hlist_for_each_entry_safe
+#define hlist_for_each_entry_safe(pos, n, head, member)                             \
+       for (n = NULL, pos = hlist_entry_safe((head)->first, typeof(*(pos)), \
+                                             member);                       \
+            pos;                                                            \
+            pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
+
 #endif /* __KLOCWORK__ */
 
 /*****************************************************************************/
@@ -1315,7 +1374,6 @@ static inline struct device *pci_dev_to_dev(struct pci_dev *pdev)
 {
        return (struct device *) pdev;
 }
-
 #define pdev_printk(lvl, pdev, fmt, args...)   \
        printk("%s %s: " fmt, lvl, pci_name(pdev), ## args)
 #define dev_err(dev, fmt, args...)            \
@@ -1460,6 +1518,9 @@ struct __kc_callback_head {
 #ifndef CONFIG_IGB_DISABLE_PACKET_SPLIT
 #define CONFIG_IGB_DISABLE_PACKET_SPLIT 1
 #endif
+#ifndef CONFIG_IGC_DISABLE_PACKET_SPLIT
+#define CONFIG_IGC_DISABLE_PACKET_SPLIT 1
+#endif
 
 #define dma_set_coherent_mask(dev,mask) 1
 
@@ -2162,6 +2223,8 @@ extern void *_kc_kmemdup(const void *src, size_t len, unsigned gfp);
 #else /* 2.6.19 */
 #include <linux/aer.h>
 #include <linux/pci_hotplug.h>
+
+#define NEW_SKB_CSUM_HELP
 #endif /* < 2.6.19 */
 
 /*****************************************************************************/
@@ -2248,7 +2311,9 @@ static inline __wsum csum_unfold(__sum16 n)
 extern struct pci_dev *_kc_netdev_to_pdev(struct net_device *netdev);
 #define netdev_to_dev(netdev)  \
        pci_dev_to_dev(_kc_netdev_to_pdev(netdev))
-#else
+#define devm_kzalloc(dev, size, flags) kzalloc(size, flags)
+#define devm_kfree(dev, p) kfree(p)
+#else /* 2.6.21 */
 static inline struct device *netdev_to_dev(struct net_device *netdev)
 {
        return &netdev->dev;
@@ -2337,6 +2402,11 @@ static inline int compound_order(struct page *page)
 {
        return 0;
 }
+
+#ifndef SKB_WITH_OVERHEAD
+#define SKB_WITH_OVERHEAD(X) \
+       ((X) - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
+#endif
 #else /* 2.6.22 */
 #define ETH_TYPE_TRANS_SETS_DEV
 #define HAVE_NETDEV_STATS_IN_NETDEV
@@ -2737,7 +2807,9 @@ extern void __kc_warn_slowpath(const char *file, const int line,
 #endif /* WARN */
 #undef HAVE_IXGBE_DEBUG_FS
 #undef HAVE_IGB_DEBUG_FS
+#define qdisc_reset_all_tx(a)
 #else /* < 2.6.27 */
+#include <net/sch_generic.h>
 #define ethtool_cmd_speed_set _kc_ethtool_cmd_speed_set
 static inline void _kc_ethtool_cmd_speed_set(struct ethtool_cmd *ep,
                                             __u32 speed)
@@ -2774,6 +2846,9 @@ static inline void __kc_skb_queue_head_init(struct sk_buff_head *list)
 #define PCI_EXP_DEVCAP2                36      /* Device Capabilities 2 */
 #define PCI_EXP_DEVCTL2                40      /* Device Control 2 */
 
+#define PCI_EXP_DEVCAP_FLR     0x10000000 /* Function Level Reset */
+#define PCI_EXP_DEVCTL_BCR_FLR 0x8000 /* Bridge Configuration Retry / FLR */
+
 #endif /* < 2.6.28 */
 
 /*****************************************************************************/
@@ -3422,8 +3497,10 @@ do {                                                             \
                netdev_##level(dev, fmt, ##args);               \
 } while (0)
 
+#if (!(RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6,3)))
 #undef usleep_range
 #define usleep_range(min, max) msleep(DIV_ROUND_UP(min, 1000))
+#endif
 
 #define u64_stats_update_begin(a) do { } while(0)
 #define u64_stats_update_end(a) do { } while(0)
@@ -4359,6 +4436,8 @@ static inline void hash_del(struct hlist_node *node)
 
 /*****************************************************************************/
 #if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) )
+#if (!(RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6,5)) && \
+     !(SLE_VERSION_CODE && SLE_VERSION_CODE >= SLE_VERSION(11,4,0)))
 #ifndef pci_sriov_set_totalvfs
 static inline int __kc_pci_sriov_set_totalvfs(struct pci_dev __always_unused *dev, u16 __always_unused numvfs)
 {
@@ -4366,6 +4445,7 @@ static inline int __kc_pci_sriov_set_totalvfs(struct pci_dev __always_unused *de
 }
 #define pci_sriov_set_totalvfs(a, b) __kc_pci_sriov_set_totalvfs((a), (b))
 #endif
+#endif /* !(RHEL_RELEASE_CODE >= 6.5 && SLE_VERSION_CODE >= 11.4) */
 #ifndef PCI_EXP_LNKCTL_ASPM_L0S
 #define  PCI_EXP_LNKCTL_ASPM_L0S  0x01 /* L0s Enable */
 #endif
@@ -4511,6 +4591,17 @@ int __kc_ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
             pos && ({ n = pos->member.next; 1; });                         \
             pos = hlist_entry_safe(n, typeof(*pos), member))
 
+#undef hlist_for_each_entry_continue
+#define hlist_for_each_entry_continue(pos, member)                     \
+       for (pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member);\
+            pos;                                                       \
+            pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
+
+#undef hlist_for_each_entry_from
+#define hlist_for_each_entry_from(pos, member)                         \
+       for (; pos;                                                     \
+            pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
+
 #undef hash_for_each
 #define hash_for_each(name, bkt, obj, member)                          \
        for ((bkt) = 0, obj = NULL; obj == NULL && (bkt) < HASH_SIZE(name);\
@@ -4533,7 +4624,7 @@ int __kc_ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
                &name[hash_min(key, HASH_BITS(name))], member)
 
 #ifdef CONFIG_XPS
-extern int __kc_netif_set_xps_queue(struct net_device *, struct cpumask *, u16);
+extern int __kc_netif_set_xps_queue(struct net_device *, const struct cpumask *, u16);
 #define netif_set_xps_queue(_dev, _mask, _idx) __kc_netif_set_xps_queue((_dev), (_mask), (_idx))
 #else /* CONFIG_XPS */
 #define netif_set_xps_queue(_dev, _mask, _idx) do {} while (0)
@@ -4636,14 +4727,31 @@ of_get_mac_address(struct device_node __always_unused *np)
 #define USE_DEFAULT_FDB_DEL_DUMP
 #define HAVE_SKB_INNER_NETWORK_HEADER
 #if (RHEL_RELEASE_CODE && \
-     (RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7,3)) && \
+     (RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7,0)) && \
      (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(8,0)))
+#define HAVE_RHEL7_PCI_DRIVER_RH
+#if (RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7,2))
+#define HAVE_RHEL7_PCI_RESET_NOTIFY
+#endif /* RHEL >= 7.2 */
+#if (RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7,3))
 #define HAVE_RHEL7_NET_DEVICE_OPS_EXT
 #define HAVE_GENEVE_RX_OFFLOAD
+#if !defined(HAVE_UDP_ENC_TUNNEL) && IS_ENABLED(CONFIG_GENEVE)
+#define HAVE_UDP_ENC_TUNNEL
+#endif
 #ifdef ETHTOOL_GLINKSETTINGS
 #define HAVE_ETHTOOL_25G_BITS
 #endif /* ETHTOOL_GLINKSETTINGS */
-#endif
+#endif /* RHEL >= 7.3 */
+
+/* new hooks added to net_device_ops_extended in RHEL7.4 */
+#if (RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7,4))
+#define HAVE_RHEL7_NETDEV_OPS_EXT_NDO_SET_VF_VLAN
+#define HAVE_RHEL7_NETDEV_OPS_EXT_NDO_UDP_TUNNEL
+#define HAVE_UDP_ENC_RX_OFFLOAD
+#endif /* RHEL >= 7.4 */
+
+#endif /* RHEL >= 7.0 && RHEL < 8.0 */
 #endif /* >= 3.10.0 */
 
 /*****************************************************************************/
@@ -4676,6 +4784,9 @@ extern int __kc_pcie_get_minimum_link(struct pci_dev *dev,
 #endif
 #if ( LINUX_VERSION_CODE < KERNEL_VERSION(4,8,0) )
 #define HAVE_VXLAN_RX_OFFLOAD
+#if !defined(HAVE_UDP_ENC_TUNNEL) && IS_ENABLED(CONFIG_VXLAN)
+#define HAVE_UDP_ENC_TUNNEL
+#endif
 #endif /* < 4.8.0 */
 #define HAVE_NDO_GET_PHYS_PORT_ID
 #endif /* >= 3.12.0 */
@@ -4772,6 +4883,10 @@ static inline void __kc_skb_set_hash(struct sk_buff __maybe_unused *skb,
 #define HAVE_VXLAN_RX_OFFLOAD
 #endif /* HAVE_VXLAN_RX_OFFLOAD */
 
+#if !defined(HAVE_UDP_ENC_TUNNEL) && IS_ENABLED(CONFIG_VXLAN)
+#define HAVE_UDP_ENC_TUNNEL
+#endif
+
 #ifndef HAVE_VXLAN_CHECKS
 #define HAVE_VXLAN_CHECKS
 #endif /* HAVE_VXLAN_CHECKS */
@@ -4820,6 +4935,9 @@ static inline void __kc_ether_addr_copy(u8 *dst, const u8 *src)
 #define u64_stats_fetch_retry_irq u64_stats_fetch_retry_bh
 #endif
 
+char *_kc_devm_kstrdup(struct device *dev, const char *s, gfp_t gfp);
+#define devm_kstrdup(dev, s, gfp) _kc_devm_kstrdup(dev, s, gfp)
+
 #else
 #define HAVE_PTP_1588_CLOCK_PINS
 #define HAVE_NETDEV_PORT
@@ -4923,9 +5041,14 @@ static inline void __kc_dev_mc_unsync(struct net_device __maybe_unused *dev,
 #define NETIF_F_GSO_UDP_TUNNEL_CSUM 0
 #define SKB_GSO_UDP_TUNNEL_CSUM 0
 #endif
+extern void *__kc_devm_kmemdup(struct device *dev, const void *src, size_t len,
+                              unsigned int gfp);
+#define devm_kmemdup __kc_devm_kmemdup
 
 #else
+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(4,13,0) )
 #define HAVE_PCI_ERROR_HANDLER_RESET_NOTIFY
+#endif /* >= 3.16.0 && < 4.13.0 */
 #define HAVE_NDO_SET_VF_MIN_MAX_TX_RATE
 #endif /* 3.16.0 */
 
@@ -4959,7 +5082,9 @@ static inline struct timespec timespec64_to_timespec(const struct timespec64 ts6
 #endif /* timespec64 */
 #endif /* !(RHEL6.8<RHEL7.0) && !RHEL7.2+ */
 
+#if !(RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7,4))
 #define hlist_add_behind(_a, _b) hlist_add_after(_b, _a)
+#endif
 
 #else
 #define HAVE_DCBNL_OPS_SETAPP_RETURN_INT
@@ -5095,6 +5220,18 @@ static inline struct sk_buff *__kc_napi_alloc_skb(struct napi_struct *napi, unsi
 #if RHEL_RELEASE_CODE && (RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(7,2))
 #define HAVE_NDO_FDB_ADD_VID
 #endif
+#ifndef ETH_MODULE_SFF_8636
+#define ETH_MODULE_SFF_8636            0x3
+#endif
+#ifndef ETH_MODULE_SFF_8636_LEN
+#define ETH_MODULE_SFF_8636_LEN                256
+#endif
+#ifndef ETH_MODULE_SFF_8436
+#define ETH_MODULE_SFF_8436            0x4
+#endif
+#ifndef ETH_MODULE_SFF_8436_LEN
+#define ETH_MODULE_SFF_8436_LEN                256
+#endif
 #else /* 3.19.0 */
 #define HAVE_NDO_FDB_ADD_VID
 #define HAVE_RXFH_HASHFUNC
@@ -5152,10 +5289,20 @@ of_find_net_device_by_node(struct device_node __always_unused *np)
 
 #define timecounter_adjtime __kc_timecounter_adjtime
 #endif
+#if ((RHEL_RELEASE_CODE && (RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7,2))) || \
+     (SLE_VERSION_CODE && (SLE_VERSION_CODE >= SLE_VERSION(12,2,0))))
+#define HAVE_NDO_SET_VF_RSS_QUERY_EN
+#endif
 #if RHEL_RELEASE_CODE && (RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(7,2))
 #define HAVE_NDO_BRIDGE_GETLINK_NLFLAGS
 #endif
-#else
+#if !((RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(6,8) && RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,0)) && \
+      (RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(7,2)) && \
+      (SLE_VERSION_CODE > SLE_VERSION(12,1,0)))
+extern unsigned int _kc_cpumask_local_spread(unsigned int i, int node);
+#define cpumask_local_spread _kc_cpumask_local_spread
+#endif
+#else /* >= 4,1,0 */
 #define HAVE_PTP_CLOCK_INFO_GETTIME64
 #define HAVE_NDO_BRIDGE_GETLINK_NLFLAGS
 #define HAVE_PASSTHRU_FEATURES_CHECK
@@ -5201,6 +5348,9 @@ static inline __u64 ethtool_get_flow_spec_ring_vf(__u64 ring_cookie)
                                ETHTOOL_RX_FLOW_SPEC_RING_VF_OFF;
 };
 #endif /* ! RHEL >= 7.2 && ! SLES >= 12.1 */
+#if (RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7,4))
+#define HAVE_NDO_DFLT_BRIDGE_GETLINK_VLAN_SUPPORT
+#endif
 #else
 #define HAVE_NDO_DFLT_BRIDGE_GETLINK_VLAN_SUPPORT
 #endif /* 4.2.0 */
@@ -5260,11 +5410,15 @@ static inline void writeq(__u64 val, volatile void __iomem *addr)
 #endif /* NETIF_F_SCTP_CRC */
 #if (!(RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7,3)))
 #define eth_platform_get_mac_address _kc_eth_platform_get_mac_address
-extern int _kc_eth_platform_get_mac_address(struct device *dev, u8 *mac_addr);
+extern int _kc_eth_platform_get_mac_address(struct device *dev __maybe_unused,
+                                           u8 *mac_addr __maybe_unused);
 #endif /* !(RHEL_RELEASE >= 7.3) */
 #else /* 4.5.0 */
 #if ( LINUX_VERSION_CODE < KERNEL_VERSION(4,8,0) )
 #define HAVE_GENEVE_RX_OFFLOAD
+#if !defined(HAVE_UDP_ENC_TUNNEL) && IS_ENABLED(CONFIG_GENEVE)
+#define HAVE_UDP_ENC_TUNNEL
+#endif
 #endif /* < 4.8.0 */
 #define HAVE_NETIF_NAPI_ADD_CALLS_NAPI_HASH_ADD
 #endif /* 4.5.0 */
@@ -5273,18 +5427,23 @@ extern int _kc_eth_platform_get_mac_address(struct device *dev, u8 *mac_addr);
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0))
 #if !(UBUNTU_VERSION_CODE && \
                UBUNTU_VERSION_CODE >= UBUNTU_VERSION(4,4,0,21)) && \
-       !(RHEL_RELEASE_CODE && (RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(7,2)))
+       !(RHEL_RELEASE_CODE && \
+               (RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(7,2))) && \
+       !(SLE_VERSION_CODE && (SLE_VERSION_CODE >= SLE_VERSION(12,3,0)))
 static inline void napi_consume_skb(struct sk_buff *skb,
                                    int __always_unused budget)
 {
        dev_consume_skb_any(skb);
 }
 
-#endif /* UBUNTU_VERSION(4,4,0,21) */
+#endif /* UBUNTU 4,4,0,21, RHEL 7.2, SLES12 SP3 */
+#if !(SLE_VERSION_CODE && (SLE_VERSION_CODE >= SLE_VERSION(12,3,0))) && \
+       !(RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7,4))
 static inline void csum_replace_by_diff(__sum16 *sum, __wsum diff)
 {
        * sum = csum_fold(csum_add(diff, ~csum_unfold(*sum)));
 }
+#endif
 
 #if !(RHEL_RELEASE_CODE && (RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(7,2)))
 static inline void page_ref_inc(struct page *page)
@@ -5301,8 +5460,13 @@ static inline void page_ref_inc(struct page *page)
 
 /*****************************************************************************/
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0))
-#else
+#if (SLE_VERSION_CODE && (SLE_VERSION_CODE >= SLE_VERSION(12,3,0))) ||\
+       (RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7,4))
+#define HAVE_NETIF_TRANS_UPDATE
+#endif
+#else /* 4.7.0 */
 #define HAVE_NETIF_TRANS_UPDATE
+#define HAVE_ETHTOOL_CONVERT_U32_AND_LINK_MODE
 #ifdef ETHTOOL_GLINKSETTINGS
 #define HAVE_ETHTOOL_25G_BITS
 #endif /* ETHTOOL_GLINKSETTINGS */
@@ -5310,6 +5474,7 @@ static inline void page_ref_inc(struct page *page)
 
 /*****************************************************************************/
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4,8,0))
+#if !(RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7,4))
 enum udp_parsable_tunnel_type {
        UDP_TUNNEL_TYPE_VXLAN,
        UDP_TUNNEL_TYPE_GENEVE,
@@ -5319,7 +5484,10 @@ struct udp_tunnel_info {
        sa_family_t sa_family;
        __be16 port;
 };
+#endif
 
+#if !(SLE_VERSION_CODE && (SLE_VERSION_CODE >= SLE_VERSION(12,3,0))) &&\
+       !(RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7,4))
 static inline int
 #ifdef HAVE_NON_CONST_PCI_DRIVER_NAME
 pci_request_io_regions(struct pci_dev *pdev, char *name)
@@ -5355,17 +5523,28 @@ pci_release_mem_regions(struct pci_dev *pdev)
        return pci_release_selected_regions(pdev,
                            pci_select_bars(pdev, IORESOURCE_MEM));
 }
+#endif /* !SLE_VERSION(12,3,0) */
 #else
 #define HAVE_UDP_ENC_RX_OFFLOAD
+#define HAVE_XPS_QOS_SUPPORT
 #endif /* 4.8.0 */
 
 /*****************************************************************************/
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0))
+#if (RHEL_RELEASE_CODE && (RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7,4)))
+#define HAVE_ETHTOOL_NEW_10G_BITS
+#endif /* RHEL */
 #else
+#define HAVE_ETHTOOL_NEW_10G_BITS
 #endif /* 4.9.0 */
 
 /*****************************************************************************/
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0))
+#if (SLE_VERSION_CODE && (SLE_VERSION_CODE >= SLE_VERSION(12,3,0)))
+#define HAVE_STRUCT_DMA_ATTRS
+#endif
+
+#if !(SLE_VERSION_CODE && (SLE_VERSION_CODE >= SLE_VERSION(12,3,0)))
 #ifndef dma_map_page_attrs
 #define dma_map_page_attrs __kc_dma_map_page_attrs
 static inline dma_addr_t __kc_dma_map_page_attrs(struct device *dev,
@@ -5404,15 +5583,34 @@ static inline void __page_frag_cache_drain(struct page *page,
 #endif
        __free_pages(page, compound_order(page));
 }
+#endif /* !SLE_VERSION(12,3,0) */
+#ifndef ETH_MIN_MTU
+#define ETH_MIN_MTU 68
+#endif /* ETH_MIN_MTU */
 #else
 #define HAVE_NETDEVICE_MIN_MAX_MTU
 #define HAVE_SWIOTLB_SKIP_CPU_SYNC
+#define HAVE_NETDEV_TC_RESETS_XPS
 #endif /* 4.10.0 */
 
 /*****************************************************************************/
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4,11,0))
-#else
+#ifdef CONFIG_NET_RX_BUSY_POLL
+#define HAVE_NDO_BUSY_POLL
+#if (SLE_VERSION_CODE && (SLE_VERSION_CODE >= SLE_VERSION(12,3,0)))
+#define HAVE_VOID_NDO_GET_STATS64
+#endif
+#endif
+#else /* > 4.11 */
 #define HAVE_VOID_NDO_GET_STATS64
 #endif /* 4.11.0 */
 
+/*****************************************************************************/
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,13,0))
+#else /* > 4.13 */
+#define HAVE_HWTSTAMP_FILTER_NTP_ALL
+#define HAVE_NDO_SETUP_TC_CHAIN_INDEX
+#define HAVE_PCI_ERROR_HANDLER_RESET_PREPARE
+#endif /* 4.13.0 */
+
 #endif /* _KCOMPAT_H_ */
diff --git a/i40e-dkms/i40e-2.1.26/src/virtchnl.h b/i40e-dkms/i40e-2.1.26/src/virtchnl.h
new file mode 100644 (file)
index 0000000..8cf91d4
--- /dev/null
@@ -0,0 +1,731 @@
+/*******************************************************************************
+ *
+ * Intel(R) 40-10 Gigabit Ethernet Connection Network Driver
+ * Copyright(c) 2013 - 2017 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ ******************************************************************************/
+
+#ifndef _VIRTCHNL_H_
+#define _VIRTCHNL_H_
+
+/* Description:
+ * This header file describes the VF-PF communication protocol used
+ * by the drivers for all devices starting from our 40G product line
+ *
+ * Admin queue buffer usage:
+ * desc->opcode is always aqc_opc_send_msg_to_pf
+ * flags, retval, datalen, and data addr are all used normally.
+ * The Firmware copies the cookie fields when sending messages between the
+ * PF and VF, but uses all other fields internally. Due to this limitation,
+ * we must send all messages as "indirect", i.e. using an external buffer.
+ *
+ * All the VSI indexes are relative to the VF. Each VF can have maximum of
+ * three VSIs. All the queue indexes are relative to the VSI.  Each VF can
+ * have a maximum of sixteen queues for all of its VSIs.
+ *
+ * The PF is required to return a status code in v_retval for all messages
+ * except RESET_VF, which does not require any response. The return value
+ * is of status_code type, defined in the shared type.h.
+ *
+ * In general, VF driver initialization should roughly follow the order of
+ * these opcodes. The VF driver must first validate the API version of the
+ * PF driver, then request a reset, then get resources, then configure
+ * queues and interrupts. After these operations are complete, the VF
+ * driver may start its queues, optionally add MAC and VLAN filters, and
+ * process traffic.
+ */
+
+/* START GENERIC DEFINES
+ * Need to ensure the following enums and defines hold the same meaning and
+ * value in current and future projects
+ */
+
+/* Error Codes */
+enum virtchnl_status_code {
+       VIRTCHNL_STATUS_SUCCESS                         = 0,
+       VIRTCHNL_ERR_PARAM                              = -5,
+       VIRTCHNL_STATUS_ERR_OPCODE_MISMATCH             = -38,
+       VIRTCHNL_STATUS_ERR_CQP_COMPL_ERROR             = -39,
+       VIRTCHNL_STATUS_ERR_INVALID_VF_ID               = -40,
+       VIRTCHNL_STATUS_NOT_SUPPORTED                   = -64,
+};
+
+#define VIRTCHNL_LINK_SPEED_100MB_SHIFT                0x1
+#define VIRTCHNL_LINK_SPEED_1000MB_SHIFT       0x2
+#define VIRTCHNL_LINK_SPEED_10GB_SHIFT         0x3
+#define VIRTCHNL_LINK_SPEED_40GB_SHIFT         0x4
+#define VIRTCHNL_LINK_SPEED_20GB_SHIFT         0x5
+#define VIRTCHNL_LINK_SPEED_25GB_SHIFT         0x6
+
+enum virtchnl_link_speed {
+       VIRTCHNL_LINK_SPEED_UNKNOWN     = 0,
+       VIRTCHNL_LINK_SPEED_100MB       = BIT(VIRTCHNL_LINK_SPEED_100MB_SHIFT),
+       VIRTCHNL_LINK_SPEED_1GB         = BIT(VIRTCHNL_LINK_SPEED_1000MB_SHIFT),
+       VIRTCHNL_LINK_SPEED_10GB        = BIT(VIRTCHNL_LINK_SPEED_10GB_SHIFT),
+       VIRTCHNL_LINK_SPEED_40GB        = BIT(VIRTCHNL_LINK_SPEED_40GB_SHIFT),
+       VIRTCHNL_LINK_SPEED_20GB        = BIT(VIRTCHNL_LINK_SPEED_20GB_SHIFT),
+       VIRTCHNL_LINK_SPEED_25GB        = BIT(VIRTCHNL_LINK_SPEED_25GB_SHIFT),
+};
+
+/* for hsplit_0 field of Rx HMC context */
+/* deprecated with AVF 1.0 */
+enum virtchnl_rx_hsplit {
+       VIRTCHNL_RX_HSPLIT_NO_SPLIT      = 0,
+       VIRTCHNL_RX_HSPLIT_SPLIT_L2      = 1,
+       VIRTCHNL_RX_HSPLIT_SPLIT_IP      = 2,
+       VIRTCHNL_RX_HSPLIT_SPLIT_TCP_UDP = 4,
+       VIRTCHNL_RX_HSPLIT_SPLIT_SCTP    = 8,
+};
+
+/* END GENERIC DEFINES */
+
+/* Opcodes for VF-PF communication. These are placed in the v_opcode field
+ * of the virtchnl_msg structure.
+ */
+enum virtchnl_ops {
+/* The PF sends status change events to VFs using
+ * the VIRTCHNL_OP_EVENT opcode.
+ * VFs send requests to the PF using the other ops.
+ * Use of "advanced opcode" features must be negotiated as part of capabilities
+ * exchange and are not considered part of base mode feature set.
+ */
+       VIRTCHNL_OP_UNKNOWN = 0,
+       VIRTCHNL_OP_VERSION = 1, /* must ALWAYS be 1 */
+       VIRTCHNL_OP_RESET_VF = 2,
+       VIRTCHNL_OP_GET_VF_RESOURCES = 3,
+       VIRTCHNL_OP_CONFIG_TX_QUEUE = 4,
+       VIRTCHNL_OP_CONFIG_RX_QUEUE = 5,
+       VIRTCHNL_OP_CONFIG_VSI_QUEUES = 6,
+       VIRTCHNL_OP_CONFIG_IRQ_MAP = 7,
+       VIRTCHNL_OP_ENABLE_QUEUES = 8,
+       VIRTCHNL_OP_DISABLE_QUEUES = 9,
+       VIRTCHNL_OP_ADD_ETH_ADDR = 10,
+       VIRTCHNL_OP_DEL_ETH_ADDR = 11,
+       VIRTCHNL_OP_ADD_VLAN = 12,
+       VIRTCHNL_OP_DEL_VLAN = 13,
+       VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE = 14,
+       VIRTCHNL_OP_GET_STATS = 15,
+       VIRTCHNL_OP_RSVD = 16,
+       VIRTCHNL_OP_EVENT = 17, /* must ALWAYS be 17 */
+       VIRTCHNL_OP_IWARP = 20, /* advanced opcode */
+       VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP = 21, /* advanced opcode */
+       VIRTCHNL_OP_RELEASE_IWARP_IRQ_MAP = 22, /* advanced opcode */
+       VIRTCHNL_OP_CONFIG_RSS_KEY = 23,
+       VIRTCHNL_OP_CONFIG_RSS_LUT = 24,
+       VIRTCHNL_OP_GET_RSS_HENA_CAPS = 25,
+       VIRTCHNL_OP_SET_RSS_HENA = 26,
+       VIRTCHNL_OP_ENABLE_VLAN_STRIPPING = 27,
+       VIRTCHNL_OP_DISABLE_VLAN_STRIPPING = 28,
+       VIRTCHNL_OP_REQUEST_QUEUES = 29,
+
+};
+
+/* This macro is used to generate a compilation error if a structure
+ * is not exactly the correct length. It gives a divide by zero error if the
+ * structure is not of the correct size, otherwise it creates an enum that is
+ * never used.
+ */
+#define VIRTCHNL_CHECK_STRUCT_LEN(n, X) enum virtchnl_static_assert_enum_##X \
+       {virtchnl_static_assert_##X = (n) / ((sizeof(struct X) == (n)) ? 1 : 0)}
+
+/* Virtual channel message descriptor. This overlays the admin queue
+ * descriptor. All other data is passed in external buffers.
+ */
+
+struct virtchnl_msg {
+       u8 pad[8];                       /* AQ flags/opcode/len/retval fields */
+       enum virtchnl_ops v_opcode; /* avoid confusion with desc->opcode */
+       enum virtchnl_status_code v_retval;  /* ditto for desc->retval */
+       u32 vfid;                        /* used by PF when sending to VF */
+};
+
+VIRTCHNL_CHECK_STRUCT_LEN(20, virtchnl_msg);
+
+/* Message descriptions and data structures.*/
+
+/* VIRTCHNL_OP_VERSION
+ * VF posts its version number to the PF. PF responds with its version number
+ * in the same format, along with a return code.
+ * Reply from PF has its major/minor versions also in param0 and param1.
+ * If there is a major version mismatch, then the VF cannot operate.
+ * If there is a minor version mismatch, then the VF can operate but should
+ * add a warning to the system log.
+ *
+ * This enum element MUST always be specified as == 1, regardless of other
+ * changes in the API. The PF must always respond to this message without
+ * error regardless of version mismatch.
+ */
+#define VIRTCHNL_VERSION_MAJOR         1
+#define VIRTCHNL_VERSION_MINOR         1
+#define VIRTCHNL_VERSION_MINOR_NO_VF_CAPS      0
+
+struct virtchnl_version_info {
+       u32 major;
+       u32 minor;
+};
+
+VIRTCHNL_CHECK_STRUCT_LEN(8, virtchnl_version_info);
+
+#define VF_IS_V10(_v) (((_v)->major == 1) && ((_v)->minor == 0))
+#define VF_IS_V11(_ver) (((_ver)->major == 1) && ((_ver)->minor == 1))
+
+/* VIRTCHNL_OP_RESET_VF
+ * VF sends this request to PF with no parameters
+ * PF does NOT respond! VF driver must delay then poll VFGEN_RSTAT register
+ * until reset completion is indicated. The admin queue must be reinitialized
+ * after this operation.
+ *
+ * When reset is complete, PF must ensure that all queues in all VSIs associated
+ * with the VF are stopped, all queue configurations in the HMC are set to 0,
+ * and all MAC and VLAN filters (except the default MAC address) on all VSIs
+ * are cleared.
+ */
+
+/* VSI types that use VIRTCHNL interface for VF-PF communication. VSI_SRIOV
+ * vsi_type should always be 6 for backward compatibility. Add other fields
+ * as needed.
+ */
+enum virtchnl_vsi_type {
+       VIRTCHNL_VSI_TYPE_INVALID = 0,
+       VIRTCHNL_VSI_SRIOV = 6,
+};
+
+/* VIRTCHNL_OP_GET_VF_RESOURCES
+ * Version 1.0 VF sends this request to PF with no parameters
+ * Version 1.1 VF sends this request to PF with u32 bitmap of its capabilities
+ * PF responds with an indirect message containing
+ * virtchnl_vf_resource and one or more
+ * virtchnl_vsi_resource structures.
+ */
+
+struct virtchnl_vsi_resource {
+       u16 vsi_id;
+       u16 num_queue_pairs;
+       enum virtchnl_vsi_type vsi_type;
+       u16 qset_handle;
+       u8 default_mac_addr[ETH_ALEN];
+};
+
+VIRTCHNL_CHECK_STRUCT_LEN(16, virtchnl_vsi_resource);
+
+/* VF offload flags
+ * VIRTCHNL_VF_OFFLOAD_L2 flag is inclusive of base mode L2 offloads including
+ * TX/RX Checksum offloading and TSO for non-tunnelled packets.
+ */
+#define VIRTCHNL_VF_OFFLOAD_L2                 0x00000001
+#define VIRTCHNL_VF_OFFLOAD_IWARP              0x00000002
+#define VIRTCHNL_VF_OFFLOAD_RSVD               0x00000004
+#define VIRTCHNL_VF_OFFLOAD_RSS_AQ             0x00000008
+#define VIRTCHNL_VF_OFFLOAD_RSS_REG            0x00000010
+#define VIRTCHNL_VF_OFFLOAD_WB_ON_ITR          0x00000020
+#define VIRTCHNL_VF_OFFLOAD_REQ_QUEUES         0x00000040
+#define VIRTCHNL_VF_OFFLOAD_VLAN               0x00010000
+#define VIRTCHNL_VF_OFFLOAD_RX_POLLING         0x00020000
+#define VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2      0x00040000
+#define VIRTCHNL_VF_OFFLOAD_RSS_PF             0X00080000
+#define VIRTCHNL_VF_OFFLOAD_ENCAP              0X00100000
+#define VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM         0X00200000
+#define VIRTCHNL_VF_OFFLOAD_RX_ENCAP_CSUM      0X00400000
+
+#define VF_BASE_MODE_OFFLOADS (VIRTCHNL_VF_OFFLOAD_L2 | \
+                              VIRTCHNL_VF_OFFLOAD_VLAN | \
+                              VIRTCHNL_VF_OFFLOAD_RSS_PF)
+
+struct virtchnl_vf_resource {
+       u16 num_vsis;
+       u16 num_queue_pairs;
+       u16 max_vectors;
+       u16 max_mtu;
+
+       u32 vf_offload_flags;
+       u32 rss_key_size;
+       u32 rss_lut_size;
+
+       struct virtchnl_vsi_resource vsi_res[1];
+};
+
+VIRTCHNL_CHECK_STRUCT_LEN(36, virtchnl_vf_resource);
+
+/* VIRTCHNL_OP_CONFIG_TX_QUEUE
+ * VF sends this message to set up parameters for one TX queue.
+ * External data buffer contains one instance of virtchnl_txq_info.
+ * PF configures requested queue and returns a status code.
+ */
+
+/* Tx queue config info */
+struct virtchnl_txq_info {
+       u16 vsi_id;
+       u16 queue_id;
+       u16 ring_len;           /* number of descriptors, multiple of 8 */
+       u16 headwb_enabled; /* deprecated with AVF 1.0 */
+       u64 dma_ring_addr;
+       u64 dma_headwb_addr; /* deprecated with AVF 1.0 */
+};
+
+VIRTCHNL_CHECK_STRUCT_LEN(24, virtchnl_txq_info);
+
+/* VIRTCHNL_OP_CONFIG_RX_QUEUE
+ * VF sends this message to set up parameters for one RX queue.
+ * External data buffer contains one instance of virtchnl_rxq_info.
+ * PF configures requested queue and returns a status code.
+ */
+
+/* Rx queue config info */
+struct virtchnl_rxq_info {
+       u16 vsi_id;
+       u16 queue_id;
+       u32 ring_len;           /* number of descriptors, multiple of 32 */
+       u16 hdr_size;
+       u16 splithdr_enabled; /* deprecated with AVF 1.0 */
+       u32 databuffer_size;
+       u32 max_pkt_size;
+       u32 pad1;
+       u64 dma_ring_addr;
+       enum virtchnl_rx_hsplit rx_split_pos; /* deprecated with AVF 1.0 */
+       u32 pad2;
+};
+
+VIRTCHNL_CHECK_STRUCT_LEN(40, virtchnl_rxq_info);
+
+/* VIRTCHNL_OP_CONFIG_VSI_QUEUES
+ * VF sends this message to set parameters for all active TX and RX queues
+ * associated with the specified VSI.
+ * PF configures queues and returns status.
+ * If the number of queues specified is greater than the number of queues
+ * associated with the VSI, an error is returned and no queues are configured.
+ */
+struct virtchnl_queue_pair_info {
+       /* NOTE: vsi_id and queue_id should be identical for both queues. */
+       struct virtchnl_txq_info txq;
+       struct virtchnl_rxq_info rxq;
+};
+
+VIRTCHNL_CHECK_STRUCT_LEN(64, virtchnl_queue_pair_info);
+
+struct virtchnl_vsi_queue_config_info {
+       u16 vsi_id;
+       u16 num_queue_pairs;
+       u32 pad;
+       struct virtchnl_queue_pair_info qpair[1];
+};
+
+VIRTCHNL_CHECK_STRUCT_LEN(72, virtchnl_vsi_queue_config_info);
+
+/* VIRTCHNL_OP_REQUEST_QUEUES
+ * VF sends this message to request the PF to allocate additional queues to
+ * this VF.  Each VF gets a guaranteed number of queues on init but asking for
+ * additional queues must be negotiated.  This is a best effort request as it
+ * is possible the PF does not have enough queues left to support the request.
+ * If the PF cannot support the number requested it will respond with the
+ * maximum number it is able to support; otherwise it will respond with the
+ * number requested.
+ */
+
+/* VF resource request */
+struct virtchnl_vf_res_request {
+       u16 num_queue_pairs;
+};
+
+/* VIRTCHNL_OP_CONFIG_IRQ_MAP
+ * VF uses this message to map vectors to queues.
+ * The rxq_map and txq_map fields are bitmaps used to indicate which queues
+ * are to be associated with the specified vector.
+ * The "other" causes are always mapped to vector 0.
+ * PF configures interrupt mapping and returns status.
+ */
+struct virtchnl_vector_map {
+       u16 vsi_id;
+       u16 vector_id;
+       u16 rxq_map;
+       u16 txq_map;
+       u16 rxitr_idx;
+       u16 txitr_idx;
+};
+
+VIRTCHNL_CHECK_STRUCT_LEN(12, virtchnl_vector_map);
+
+struct virtchnl_irq_map_info {
+       u16 num_vectors;
+       struct virtchnl_vector_map vecmap[1];
+};
+
+VIRTCHNL_CHECK_STRUCT_LEN(14, virtchnl_irq_map_info);
+
+/* VIRTCHNL_OP_ENABLE_QUEUES
+ * VIRTCHNL_OP_DISABLE_QUEUES
+ * VF sends these message to enable or disable TX/RX queue pairs.
+ * The queues fields are bitmaps indicating which queues to act upon.
+ * (Currently, we only support 16 queues per VF, but we make the field
+ * u32 to allow for expansion.)
+ * PF performs requested action and returns status.
+ */
+struct virtchnl_queue_select {
+       u16 vsi_id;
+       u16 pad;
+       u32 rx_queues;
+       u32 tx_queues;
+};
+
+VIRTCHNL_CHECK_STRUCT_LEN(12, virtchnl_queue_select);
+
+/* VIRTCHNL_OP_ADD_ETH_ADDR
+ * VF sends this message in order to add one or more unicast or multicast
+ * address filters for the specified VSI.
+ * PF adds the filters and returns status.
+ */
+
+/* VIRTCHNL_OP_DEL_ETH_ADDR
+ * VF sends this message in order to remove one or more unicast or multicast
+ * filters for the specified VSI.
+ * PF removes the filters and returns status.
+ */
+
+struct virtchnl_ether_addr {
+       u8 addr[ETH_ALEN];
+       u8 pad[2];
+};
+
+VIRTCHNL_CHECK_STRUCT_LEN(8, virtchnl_ether_addr);
+
+struct virtchnl_ether_addr_list {
+       u16 vsi_id;
+       u16 num_elements;
+       struct virtchnl_ether_addr list[1];
+};
+
+VIRTCHNL_CHECK_STRUCT_LEN(12, virtchnl_ether_addr_list);
+
+/* VIRTCHNL_OP_ADD_VLAN
+ * VF sends this message to add one or more VLAN tag filters for receives.
+ * PF adds the filters and returns status.
+ * If a port VLAN is configured by the PF, this operation will return an
+ * error to the VF.
+ */
+
+/* VIRTCHNL_OP_DEL_VLAN
+ * VF sends this message to remove one or more VLAN tag filters for receives.
+ * PF removes the filters and returns status.
+ * If a port VLAN is configured by the PF, this operation will return an
+ * error to the VF.
+ */
+
+struct virtchnl_vlan_filter_list {
+       u16 vsi_id;
+       u16 num_elements;
+       u16 vlan_id[1];
+};
+
+VIRTCHNL_CHECK_STRUCT_LEN(6, virtchnl_vlan_filter_list);
+
+/* VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE
+ * VF sends VSI id and flags.
+ * PF returns status code in retval.
+ * Note: we assume that broadcast accept mode is always enabled.
+ */
+struct virtchnl_promisc_info {
+       u16 vsi_id;
+       u16 flags;
+};
+
+VIRTCHNL_CHECK_STRUCT_LEN(4, virtchnl_promisc_info);
+
+#define FLAG_VF_UNICAST_PROMISC        0x00000001
+#define FLAG_VF_MULTICAST_PROMISC      0x00000002
+
+/* VIRTCHNL_OP_GET_STATS
+ * VF sends this message to request stats for the selected VSI. VF uses
+ * the virtchnl_queue_select struct to specify the VSI. The queue_id
+ * field is ignored by the PF.
+ *
+ * PF replies with struct eth_stats in an external buffer.
+ */
+
+/* VIRTCHNL_OP_CONFIG_RSS_KEY
+ * VIRTCHNL_OP_CONFIG_RSS_LUT
+ * VF sends these messages to configure RSS. Only supported if both PF
+ * and VF drivers set the VIRTCHNL_VF_OFFLOAD_RSS_PF bit during
+ * configuration negotiation. If this is the case, then the RSS fields in
+ * the VF resource struct are valid.
+ * Both the key and LUT are initialized to 0 by the PF, meaning that
+ * RSS is effectively disabled until set up by the VF.
+ */
+struct virtchnl_rss_key {
+       u16 vsi_id;
+       u16 key_len;
+       u8 key[1];         /* RSS hash key, packed bytes */
+};
+
+VIRTCHNL_CHECK_STRUCT_LEN(6, virtchnl_rss_key);
+
+struct virtchnl_rss_lut {
+       u16 vsi_id;
+       u16 lut_entries;
+       u8 lut[1];        /* RSS lookup table*/
+};
+
+VIRTCHNL_CHECK_STRUCT_LEN(6, virtchnl_rss_lut);
+
+/* VIRTCHNL_OP_GET_RSS_HENA_CAPS
+ * VIRTCHNL_OP_SET_RSS_HENA
+ * VF sends these messages to get and set the hash filter enable bits for RSS.
+ * By default, the PF sets these to all possible traffic types that the
+ * hardware supports. The VF can query this value if it wants to change the
+ * traffic types that are hashed by the hardware.
+ */
+struct virtchnl_rss_hena {
+       u64 hena;
+};
+
+VIRTCHNL_CHECK_STRUCT_LEN(8, virtchnl_rss_hena);
+
+/* VIRTCHNL_OP_EVENT
+ * PF sends this message to inform the VF driver of events that may affect it.
+ * No direct response is expected from the VF, though it may generate other
+ * messages in response to this one.
+ */
+enum virtchnl_event_codes {
+       VIRTCHNL_EVENT_UNKNOWN = 0,
+       VIRTCHNL_EVENT_LINK_CHANGE,
+       VIRTCHNL_EVENT_RESET_IMPENDING,
+       VIRTCHNL_EVENT_PF_DRIVER_CLOSE,
+};
+
+#define PF_EVENT_SEVERITY_INFO         0
+#define PF_EVENT_SEVERITY_CERTAIN_DOOM 255
+
+struct virtchnl_pf_event {
+       enum virtchnl_event_codes event;
+       union {
+               struct {
+                       enum virtchnl_link_speed link_speed;
+                       bool link_status;
+               } link_event;
+       } event_data;
+
+       int severity;
+};
+
+VIRTCHNL_CHECK_STRUCT_LEN(16, virtchnl_pf_event);
+
+/* VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP
+ * VF uses this message to request PF to map IWARP vectors to IWARP queues.
+ * The request for this originates from the VF IWARP driver through
+ * a client interface between VF LAN and VF IWARP driver.
+ * A vector could have an AEQ and CEQ attached to it although
+ * there is a single AEQ per VF IWARP instance in which case
+ * most vectors will have an INVALID_IDX for aeq and valid idx for ceq.
+ * There will never be a case where there will be multiple CEQs attached
+ * to a single vector.
+ * PF configures interrupt mapping and returns status.
+ */
+
+/* HW does not define a type value for AEQ; only for RX/TX and CEQ.
+ * In order for us to keep the interface simple, SW will define a
+ * unique type value for AEQ.
+ */
+#define QUEUE_TYPE_PE_AEQ  0x80
+#define QUEUE_INVALID_IDX  0xFFFF
+
+struct virtchnl_iwarp_qv_info {
+       u32 v_idx; /* msix_vector */
+       u16 ceq_idx;
+       u16 aeq_idx;
+       u8 itr_idx;
+};
+
+VIRTCHNL_CHECK_STRUCT_LEN(12, virtchnl_iwarp_qv_info);
+
+struct virtchnl_iwarp_qvlist_info {
+       u32 num_vectors;
+       struct virtchnl_iwarp_qv_info qv_info[1];
+};
+
+VIRTCHNL_CHECK_STRUCT_LEN(16, virtchnl_iwarp_qvlist_info);
+
+/* VF reset states - these are written into the RSTAT register:
+ * VFGEN_RSTAT on the VF
+ * When the PF initiates a reset, it writes 0
+ * When the reset is complete, it writes 1
+ * When the PF detects that the VF has recovered, it writes 2
+ * VF checks this register periodically to determine if a reset has occurred,
+ * then polls it to know when the reset is complete.
+ * If either the PF or VF reads the register while the hardware
+ * is in a reset state, it will return DEADBEEF, which, when masked
+ * will result in 3.
+ */
+enum virtchnl_vfr_states {
+       VIRTCHNL_VFR_INPROGRESS = 0,
+       VIRTCHNL_VFR_COMPLETED,
+       VIRTCHNL_VFR_VFACTIVE,
+};
+
+/**
+ * virtchnl_vc_validate_vf_msg
+ * @ver: Virtchnl version info
+ * @v_opcode: Opcode for the message
+ * @msg: pointer to the msg buffer
+ * @msglen: msg length
+ *
+ * validate msg format against struct for each opcode
+ */
+static inline int
+virtchnl_vc_validate_vf_msg(struct virtchnl_version_info *ver, u32 v_opcode,
+                           u8 *msg, u16 msglen)
+{
+       bool err_msg_format = false;
+       int valid_len = 0;
+
+       /* Validate message length. */
+       switch (v_opcode) {
+       case VIRTCHNL_OP_VERSION:
+               valid_len = sizeof(struct virtchnl_version_info);
+               break;
+       case VIRTCHNL_OP_RESET_VF:
+               break;
+       case VIRTCHNL_OP_GET_VF_RESOURCES:
+               if (VF_IS_V11(ver))
+                       valid_len = sizeof(u32);
+               break;
+       case VIRTCHNL_OP_CONFIG_TX_QUEUE:
+               valid_len = sizeof(struct virtchnl_txq_info);
+               break;
+       case VIRTCHNL_OP_CONFIG_RX_QUEUE:
+               valid_len = sizeof(struct virtchnl_rxq_info);
+               break;
+       case VIRTCHNL_OP_CONFIG_VSI_QUEUES:
+               valid_len = sizeof(struct virtchnl_vsi_queue_config_info);
+               if (msglen >= valid_len) {
+                       struct virtchnl_vsi_queue_config_info *vqc =
+                           (struct virtchnl_vsi_queue_config_info *)msg;
+                       valid_len += (vqc->num_queue_pairs *
+                                     sizeof(struct
+                                            virtchnl_queue_pair_info));
+                       if (vqc->num_queue_pairs == 0)
+                               err_msg_format = true;
+               }
+               break;
+       case VIRTCHNL_OP_CONFIG_IRQ_MAP:
+               valid_len = sizeof(struct virtchnl_irq_map_info);
+               if (msglen >= valid_len) {
+                       struct virtchnl_irq_map_info *vimi =
+                           (struct virtchnl_irq_map_info *)msg;
+                       valid_len += (vimi->num_vectors *
+                                     sizeof(struct virtchnl_vector_map));
+                       if (vimi->num_vectors == 0)
+                               err_msg_format = true;
+               }
+               break;
+       case VIRTCHNL_OP_ENABLE_QUEUES:
+       case VIRTCHNL_OP_DISABLE_QUEUES:
+               valid_len = sizeof(struct virtchnl_queue_select);
+               break;
+       case VIRTCHNL_OP_ADD_ETH_ADDR:
+       case VIRTCHNL_OP_DEL_ETH_ADDR:
+               valid_len = sizeof(struct virtchnl_ether_addr_list);
+               if (msglen >= valid_len) {
+                       struct virtchnl_ether_addr_list *veal =
+                           (struct virtchnl_ether_addr_list *)msg;
+                       valid_len += veal->num_elements *
+                           sizeof(struct virtchnl_ether_addr);
+                       if (veal->num_elements == 0)
+                               err_msg_format = true;
+               }
+               break;
+       case VIRTCHNL_OP_ADD_VLAN:
+       case VIRTCHNL_OP_DEL_VLAN:
+               valid_len = sizeof(struct virtchnl_vlan_filter_list);
+               if (msglen >= valid_len) {
+                       struct virtchnl_vlan_filter_list *vfl =
+                           (struct virtchnl_vlan_filter_list *)msg;
+                       valid_len += vfl->num_elements * sizeof(u16);
+                       if (vfl->num_elements == 0)
+                               err_msg_format = true;
+               }
+               break;
+       case VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE:
+               valid_len = sizeof(struct virtchnl_promisc_info);
+               break;
+       case VIRTCHNL_OP_GET_STATS:
+               valid_len = sizeof(struct virtchnl_queue_select);
+               break;
+       case VIRTCHNL_OP_IWARP:
+               /* These messages are opaque to us and will be validated in
+                * the RDMA client code. We just need to check for nonzero
+                * length. The firmware will enforce max length restrictions.
+                */
+               if (msglen)
+                       valid_len = msglen;
+               else
+                       err_msg_format = true;
+               break;
+       case VIRTCHNL_OP_RELEASE_IWARP_IRQ_MAP:
+               break;
+       case VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP:
+               valid_len = sizeof(struct virtchnl_iwarp_qvlist_info);
+               if (msglen >= valid_len) {
+                       struct virtchnl_iwarp_qvlist_info *qv =
+                               (struct virtchnl_iwarp_qvlist_info *)msg;
+                       if (qv->num_vectors == 0) {
+                               err_msg_format = true;
+                               break;
+                       }
+                       valid_len += ((qv->num_vectors - 1) *
+                               sizeof(struct virtchnl_iwarp_qv_info));
+               }
+               break;
+       case VIRTCHNL_OP_CONFIG_RSS_KEY:
+               valid_len = sizeof(struct virtchnl_rss_key);
+               if (msglen >= valid_len) {
+                       struct virtchnl_rss_key *vrk =
+                               (struct virtchnl_rss_key *)msg;
+                       valid_len += vrk->key_len - 1;
+               }
+               break;
+       case VIRTCHNL_OP_CONFIG_RSS_LUT:
+               valid_len = sizeof(struct virtchnl_rss_lut);
+               if (msglen >= valid_len) {
+                       struct virtchnl_rss_lut *vrl =
+                               (struct virtchnl_rss_lut *)msg;
+                       valid_len += vrl->lut_entries - 1;
+               }
+               break;
+       case VIRTCHNL_OP_GET_RSS_HENA_CAPS:
+               break;
+       case VIRTCHNL_OP_SET_RSS_HENA:
+               valid_len = sizeof(struct virtchnl_rss_hena);
+               break;
+       case VIRTCHNL_OP_ENABLE_VLAN_STRIPPING:
+       case VIRTCHNL_OP_DISABLE_VLAN_STRIPPING:
+               break;
+       case VIRTCHNL_OP_REQUEST_QUEUES:
+               valid_len = sizeof(struct virtchnl_vf_res_request);
+               break;
+       /* These are always errors coming from the VF. */
+       case VIRTCHNL_OP_EVENT:
+       case VIRTCHNL_OP_UNKNOWN:
+       default:
+               return VIRTCHNL_ERR_PARAM;
+       }
+       /* few more checks */
+       if ((valid_len != msglen) || (err_msg_format))
+               return VIRTCHNL_STATUS_ERR_OPCODE_MISMATCH;
+
+       return 0;
+}
+#endif /* _VIRTCHNL_H_ */