├── .github └── workflows │ └── build.yml ├── .gitignore ├── LICENSE.md ├── Makefile ├── Module.symvers ├── README.md ├── backport.h ├── backport_overflow.h ├── igc.h ├── igc ├── releases │ ├── apollolake_42218.json │ ├── broadwell_42218.json │ ├── broadwellnk_42218.json │ ├── denverton_42218.json │ ├── epyc7002_42962.json │ ├── geminilake_42218.json │ ├── igc-apollolake.tgz │ ├── igc-broadwell.tgz │ ├── igc-broadwellnk.tgz │ ├── igc-denverton.tgz │ ├── igc-epyc7002.tgz │ ├── igc-geminilake.tgz │ ├── igc-r1000.tgz │ ├── igc-v1000.tgz │ ├── r1000_42218.json │ └── v1000_42218.json ├── rpext-index.json └── src │ └── check-igc.sh ├── igc_base.c ├── igc_base.h ├── igc_defines.h ├── igc_diag.c ├── igc_diag.h ├── igc_dump.c ├── igc_ethtool.c ├── igc_hw.h ├── igc_i225.c ├── igc_i225.h ├── igc_mac.c ├── igc_mac.h ├── igc_main.c ├── igc_nvm.c ├── igc_nvm.h ├── igc_phy.c ├── igc_phy.h ├── igc_ptp.c ├── igc_regs.h ├── igc_tsn.c └── igc_tsn.h /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2022 Ing 3 | # 4 | # This is free software, licensed under the MIT License. 5 | # See /LICENSE for more information. 6 | # 7 | 8 | 9 | name: Build 10 | on: 11 | push: 12 | tags: 13 | - '*' 14 | 15 | workflow_dispatch: 16 | inputs: 17 | version: 18 | description: 'tag' 19 | required: false 20 | type: string 21 | 22 | jobs: 23 | build: 24 | runs-on: ubuntu-latest 25 | strategy: 26 | matrix: 27 | platform: [apollolake, broadwell, broadwellnk, denverton, geminilake, v1000, r1000] 28 | 29 | steps: 30 | - name: Checkout 31 | uses: actions/checkout@main 32 | 33 | - name: Init Env 34 | run: | 35 | git config --global user.email "github-actions[bot]@users.noreply.github.com" 36 | git config --global user.name "github-actions[bot]" 37 | sudo timedatectl set-timezone "Asia/Shanghai" 38 | 39 | - name: Calculate tag 40 | run: | 41 | function increment_version() { 42 | declare -a part=( ${1//\./ } ) 43 | declare new 44 | declare -i carry=1 45 | 46 | for (( CNTR=${#part[@]}-1; CNTR>=0; CNTR-=1 )); do 47 | len=${#part[CNTR]} 48 | new=$((part[CNTR]+carry)) 49 | [ ${#new} -gt $len ] && carry=1 || carry=0 50 | [ $CNTR -gt 0 ] && part[CNTR]=${new: -len} || part[CNTR]=${new} 51 | done 52 | new="${part[*]}" 53 | echo -e "${new// /.}" 54 | } 55 | 56 | git clone ${{ github.server_url }}/${{ github.repository }} 57 | cd ${{ github.event.repository.name }} 58 | CUR_TAG=$(git tag -l | tail -1) 59 | NEW_TAG=$(increment_version ${CUR_TAG}) 60 | echo CUR_TAG: ${CUR_TAG} NEW_TAG:${NEW_TAG} 61 | 62 | if [ ${{ github.event_name }} == 'push' -a ${{ github.ref_type }} == 'tag' ]; then 63 | echo "new_tag=${{ github.ref_name }}" >> $GITHUB_ENV 64 | else 65 | if [ -n "${{ inputs.version }}" ]; then 66 | echo "new_tag=${{ inputs.version }}" >> $GITHUB_ENV 67 | else 68 | echo "new_tag=${NEW_TAG}" >> $GITHUB_ENV 69 | fi 70 | fi 71 | 72 | echo 'git_log<> $GITHUB_ENV 73 | git log ${CUR_TAG}..HEAD --oneline >> $GITHUB_ENV 74 | echo 'EOF' >> $GITHUB_ENV 75 | 76 | cd .. 77 | rm -rf ${{ github.event.repository.name }} 78 | 79 | # 修改源文件版本号 80 | sed -i "s/^#define DRV_VERSION.*/#define DRV_VERSION \"$NEW_TAG\"/" igc_main.c 81 | 82 | - name: Build igc for ${{matrix.platform}} 83 | run: | 84 | echo new_tag: ${{ env.new_tag }} 85 | 86 | mkdir ./${{matrix.platform}} && chmod 777 ./${{matrix.platform}} 87 | sudo docker run -u 1000 --rm -t -v "${PWD}":/input -v "${PWD}/${{matrix.platform}}":/output fbelavenuto/syno-compiler compile-module ${{matrix.platform}} 88 | 89 | ls -al ${PWD}/${{matrix.platform}} 90 | tar zcvf igc-${{matrix.platform}}.tgz -C./${{matrix.platform}}/ . 91 | rm -rf ${PWD}/${{matrix.platform}} 92 | 93 | - name: Upload firmware to artifacts 94 | uses: actions/upload-artifact@v3 95 | if: (!cancelled()) 96 | with: 97 | name: igc 98 | path: ./igc-*.tgz 99 | 100 | - name: Upload firmware to releases 101 | uses: softprops/action-gh-release@v1 102 | if: (!cancelled()) 103 | env: 104 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 105 | with: 106 | tag_name: ${{ env.new_tag }} 107 | body: | 108 | Changes: 109 | ${{ env.git_log }} 110 | files: ./igc-*.tgz 111 | 112 | ext: 113 | runs-on: ubuntu-latest 114 | needs: build 115 | steps: 116 | - name: Checkout 117 | uses: actions/checkout@main 118 | 119 | - name: git switch 120 | if: github.event_name == 'push' && github.ref_type == 'tag' 121 | run: | 122 | git fetch 123 | git branch -a 124 | git checkout --progress --force main 125 | 126 | - name: Init Env 127 | run: | 128 | git config --global user.email "github-actions[bot]@users.noreply.github.com" 129 | git config --global user.name "github-actions[bot]" 130 | sudo timedatectl set-timezone "Asia/Shanghai" 131 | 132 | - name: download to artifacts 133 | uses: actions/download-artifact@v3 134 | with: 135 | name: igc 136 | path: ./ 137 | 138 | - name: update exts 139 | run: | 140 | ls -al 141 | 142 | git clone ${{ github.server_url }}/${{ github.repository }} 143 | cd ${{ github.event.repository.name }} 144 | NEW_TAG=$(git tag -l | tail -1) 145 | cd .. 146 | rm -rf ${{ github.event.repository.name }} 147 | echo NEW_TAG ${NEW_TAG} 148 | echo "new_tag=${NEW_TAG}" >> $GITHUB_ENV 149 | 150 | for i in igc-*.tgz 151 | do 152 | echo ${i} 153 | rm -f ./igc/releases/${i} 154 | cp -f ${i} ./igc/releases/${i} 155 | platform=$(echo ${i} | awk -F'[-.]' '{ print $2 }') 156 | configfile=./igc/releases/${platform}_42218.json 157 | sed -i "s/$(jq -r .files[0].sha256 ${configfile})/$(sha256sum ./igc/releases/igc-${platform}.tgz | awk '{print $1}')/g" ${configfile} 158 | sed -i "s/\"$(jq -r .mod_version ${configfile})\"/\"${NEW_TAG}\"/g" ${configfile} 159 | done 160 | 161 | baseurl=$(jq -r .url ./igc/rpext-index.json) 162 | repotmp=${baseurl%/master/*} 163 | oldrepo=${repotmp#*.com/} 164 | echo ${oldrepo} 165 | for i in $(find ./igc -name "*.json") 166 | do 167 | echo ${i} 168 | sed -i "s|${oldrepo}|${{ github.repository }}|g" ${i} 169 | done 170 | 171 | # 修改源文件版本号 172 | sed -i "s/^#define DRV_VERSION.*/#define DRV_VERSION \"$NEW_TAG\"/" igc_main.c 173 | 174 | - name: Commit and Push 175 | run: | 176 | ischange=false 177 | if [ -n "$(git status -s | grep igc/)" ];then 178 | git add ./igc/* 179 | ischange=true 180 | fi 181 | if [ -n "$(git status -s | grep igc_main.c)" ];then 182 | git add ./igc_main.c 183 | ischange=true 184 | fi 185 | if [ ${ischange} == true ];then 186 | git commit -m "update ${{ env.new_tag }}" 187 | git push -f 188 | fi 189 | 190 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | *.o 3 | *.o.cmd 4 | *.ko 5 | *.ko.cmd 6 | .tmp_versions 7 | igc.mod.c 8 | modules.order -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0 2 | # Copyright (c) 2018 Intel Corporation 3 | 4 | # 5 | # Intel(R) I225-LM/I225-V 2.5G Ethernet Controller 6 | # 7 | 8 | obj-m = igc.o 9 | 10 | igc-objs := igc_main.o igc_mac.o igc_i225.o igc_base.o igc_nvm.o igc_phy.o \ 11 | igc_diag.o igc_ethtool.o igc_ptp.o igc_dump.o igc_tsn.o 12 | -------------------------------------------------------------------------------- /Module.symvers: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jim3ma/synology-igc/d8cd0f0c155f35eed7b4a10ef57b28d9630ea78c/Module.symvers -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Intel igc driver for Synology Kernel 4.4.180 2 | 3 | > Backport from Linux Kernel v5.12, commit: https://github.com/torvalds/linux/commit/9f4ad9e425a1d3b6a34617b8ea226d56a119a717 4 | 5 | ## Known issues 6 | 7 | * None 8 | 9 | ## Compatible devices&NICs manifest 10 | 11 | I have updated the most pciids of I225/I226 NICs. All I225/I226 NICs should work normal. 12 | 13 | If this igc driver is compatible with your devices, you can reply in [this issue](https://github.com/jim3ma/synology-igc/issues/3). 14 | 15 | | Motherboard | NIC Version | Device ID | Ports | Firmware Version | 16 | | --- | --- | --- | --- | --- | 17 | | UGREEN DX4600 | I225-V B3 | 8086:15F3| 2 | 1057:8754 | 18 | | ROG MAXIMUS XIII HERO | I225-V B3 | 8086:15F3 | 2 | 1057:8754 | 19 | | CW N5105-N6005-6SATA | I226-V | 8086:125C | 4 | 2014:8877 | 20 | 21 | ## Prebuild module 22 | 23 | Download from https://github.com/jim3ma/synology-igc/tree/main/igc/releases 24 | 25 | Eg: https://github.com/jim3ma/synology-igc/raw/main/igc/releases/igc-geminilake.tgz 26 | 27 | Follow load module action: https://github.com/jim3ma/synology-igc#3-load-module 28 | 29 | ## Build in docker 30 | 31 | ``` 32 | mkdir -p output 33 | 34 | # avaliable platform: 35 | # apollolake 36 | # broadwell 37 | # broadwellnk 38 | # denverton 39 | # geminilake 40 | # v1000 41 | # I think the platform is not important for building `igc`, change it as your own 42 | PLATFORM=geminilake 43 | 44 | docker run -u 1000 --rm -t -v "${PWD}":/input -v "${PWD}/output":/output fbelavenuto/syno-compiler compile-module ${PLATFORM} 45 | ``` 46 | 47 | The `output/igc.ko` is the module. 48 | 49 | And then Follow load module actions: https://github.com/jim3ma/synology-igc#3-load-module 50 | 51 | ## Build in Synology develop environment 52 | 53 | ### 1. Setup develop environment 54 | 55 | #### Prepare Environment 56 | 57 | Refer: https://help.synology.com/developer-guide/getting_started/prepare_environment.html 58 | 59 | Assume `platform=geminilake`, `version=7.1`, working directory is `/synology-toolkit` 60 | 61 | Now the build env is `/synology-toolkit/build_env/ds.geminilake-7.1` 62 | 63 | #### Enter chrooot 64 | 65 | ``` 66 | sudo chroot /synology-toolkit/build_env/ds.geminilake-7.1 67 | ``` 68 | 69 | #### Clone source code 70 | 71 | ``` 72 | cd /usr/src/ 73 | git clone https://github.com/jim3ma/synology-igc.git 74 | ``` 75 | 76 | ### 2. Build module 77 | 78 | ```shell 79 | cd /usr/src/synology-igc/ 80 | make -C /usr/local/x86_64-pc-linux-gnu/x86_64-pc-linux-gnu/sys-root/usr/lib/modules/DSM-7.1/build M=$PWD modules 81 | ``` 82 | 83 | ### 3. Load module 84 | 85 | Copy `igc.ko` to target machine 86 | 87 | #### Find i225/i226 pci device 88 | 89 | ``` 90 | 03:00.0 Ethernet controller: Intel Corporation Ethernet Controller I225-V (rev 03) 91 | ``` 92 | 93 | ``` 94 | insmod igc.ko debug=16 # enable debug log 95 | echo igc > /sys/bus/pci/devices/0000:03:00.0/driver_override 96 | echo 0000:03:00.0 > /sys/bus/pci/drivers_probe 97 | ip link set up eth1 # in my machine, the nic name is eth1 98 | ``` 99 | 100 | ## TODO 101 | 102 | 1. tc support 103 | 2. igc: Enable internal i225 PPS - https://github.com/torvalds/linux/commit/64433e5bf40abf893c7edbc60899bdcdd7c70b76 104 | 105 | ## History 106 | 107 | ### 1.3.1 108 | 109 | _Date 2022.11.26_ 110 | * update ethtool version 111 | 112 | ### 1.3.0 113 | 114 | _Date 2022.11.23_ 115 | 116 | * fix page refcount not decrease when free page 117 | 118 | ### 1.2.8 119 | 120 | _Date 2022.11.17_ 121 | 122 | * fix pages leak for IGC_RING_FLAG_RX_3K_BUFFER devices 123 | 124 | ### 1.2.4 - 1.2.7 125 | 126 | Only test for automating build, no code changes 127 | 128 | ### 1.2.3 129 | 130 | _Date 2022.11.16_ 131 | 132 | This version support i226 with device id 8086:125C, firmware version: 2014:8877 133 | 134 | * igc: Remove phy->type checking 135 | * igc: Remove _I_PHY_ID checking 136 | 137 | ### 1.2.2 138 | 139 | _Date 2022.11.15_ 140 | 141 | * Update defines for compile error 142 | 143 | ### 1.2.1 144 | 145 | _Date 2022.11.03_ 146 | 147 | * igc: Fix BUG: scheduling while atomic 148 | * igc: Add new device ID I226_LMVP 149 | * igc: Fix suspending when PTM is active 150 | 151 | ### 1.2.0 152 | 153 | _Date 2022.10.27_ 154 | 155 | Backport fixes from upstream 156 | 157 | * igc: Fix TX timestamp support for non-MSI-X platforms 158 | * igc: Fix typo in i225 LTR functions 159 | * igc: Update I226_K device ID 160 | * igc: Reinstate IGC_REMOVED logic and implement it properly 161 | * igc: Fix infinite loop in release_swfw_sync 162 | * igc: Increase timeout value for Speed 100/1000/2500 163 | * igc: Fix use-after-free error during reset 164 | * igc: change default return of igc_read_phy_reg() 165 | * igc: Fix an error handling path in 'igc_probe()' 166 | 167 | ### 1.1.0 168 | 169 | _Date 2022.10.27_ 170 | 171 | * Support ethtool operations 172 | 173 | ### 1.0.0 174 | 175 | _Date 2022.10.26_ 176 | 177 | * Backport from Linux Kernel v5.12, commit: 9f4ad9e425a1d3b6a34617b8ea226d56a119a717. -------------------------------------------------------------------------------- /backport.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | /* Copyright (c) Jim Ma */ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | static inline unsigned char *skb_checksum_start(const struct sk_buff *skb) 18 | { 19 | return skb->head + skb->csum_start; 20 | } 21 | 22 | static inline void csum_replace_by_diff(__sum16 *sum, __wsum diff) 23 | { 24 | *sum = csum_fold(csum_add(diff, ~csum_unfold(*sum))); 25 | } 26 | 27 | static inline void net_prefetch(void *p) 28 | { 29 | prefetch(p); 30 | #if L1_CACHE_BYTES < 128 31 | prefetch((u8 *)p + L1_CACHE_BYTES); 32 | #endif 33 | } 34 | 35 | static inline bool dev_page_is_reusable(struct page *page) 36 | { 37 | return likely(page_to_nid(page) == numa_mem_id() && 38 | !page_is_pfmemalloc(page)); 39 | } 40 | 41 | /** 42 | * refcount_read - get a refcount's value 43 | * @r: the refcount 44 | * 45 | * Return: the refcount's value 46 | */ 47 | static inline unsigned int refcount_read(atomic_t *r) 48 | { 49 | return atomic_read(r); 50 | } 51 | 52 | // static inline __must_check bool __refcount_sub_and_test(int i, atomic_t *r, int *oldp) 53 | // { 54 | // // int old = atomic_fetch_sub_release(i, r); 55 | 56 | // // if (oldp) 57 | // // *oldp = old; 58 | 59 | // // if (old == i) { 60 | // // smp_acquire__after_ctrl_dep(); 61 | // // return true; 62 | // // } 63 | 64 | // // if (unlikely(old < 0 || old - i < 0)) 65 | // // refcount_warn_saturate(r, REFCOUNT_SUB_UAF); 66 | 67 | // return false; 68 | // } 69 | 70 | /** 71 | * refcount_sub_and_test - subtract from a refcount and test if it is 0 72 | * @i: amount to subtract from the refcount 73 | * @r: the refcount 74 | * 75 | * Similar to atomic_dec_and_test(), but it will WARN, return false and 76 | * ultimately leak on underflow and will fail to decrement when saturated 77 | * at REFCOUNT_SATURATED. 78 | * 79 | * Provides release memory ordering, such that prior loads and stores are done 80 | * before, and provides an acquire ordering on success such that free() 81 | * must come after. 82 | * 83 | * Use of this function is not recommended for the normal reference counting 84 | * use case in which references are taken and released one at a time. In these 85 | * cases, refcount_dec(), or one of its variants, should instead be used to 86 | * decrement a reference count. 87 | * 88 | * Return: true if the resulting refcount is 0, false otherwise 89 | */ 90 | // static inline __must_check bool refcount_sub_and_test(int i, atomic_t *r) 91 | // { 92 | // return __refcount_sub_and_test(i, r, NULL); 93 | // } 94 | 95 | // static inline __must_check bool __refcount_dec_and_test(atomic_t *r, int *oldp) 96 | // { 97 | // return __refcount_sub_and_test(1, r, oldp); 98 | // } 99 | 100 | /** 101 | * refcount_dec_and_test - decrement a refcount and test if it is 0 102 | * @r: the refcount 103 | * 104 | * Similar to atomic_dec_and_test(), it will WARN on underflow and fail to 105 | * decrement when saturated at REFCOUNT_SATURATED. 106 | * 107 | * Provides release memory ordering, such that prior loads and stores are done 108 | * before, and provides an acquire ordering on success such that free() 109 | * must come after. 110 | * 111 | * Return: true if the resulting refcount is 0, false otherwise 112 | */ 113 | // static inline __must_check bool refcount_dec_and_test(atomic_t *r) 114 | // { 115 | // return __refcount_dec_and_test(r, NULL); 116 | // } 117 | 118 | /** 119 | * skb_unref - decrement the skb's reference count 120 | * @skb: buffer 121 | * 122 | * Returns true if we can free the skb. 123 | */ 124 | // static inline bool skb_unref(struct sk_buff *skb) 125 | // { 126 | // if (unlikely(!skb)) 127 | // return false; 128 | // if (likely(atomic_read(&skb->users) == 1)) 129 | // smp_rmb(); 130 | // else if (likely(!refcount_dec_and_test(&skb->users))) 131 | // return false; 132 | 133 | // return true; 134 | // } 135 | 136 | // static void skb_release_all(struct sk_buff *skb) 137 | // { 138 | // skb_release_head_state(skb); 139 | // if (likely(skb->head)) 140 | // skb_release_data(skb); 141 | // } 142 | 143 | // static void napi_consume_skb(struct sk_buff *skb, int budget) 144 | // { 145 | // /* Zero budget indicate non-NAPI context called us, like netpoll */ 146 | // if (unlikely(!budget)) { 147 | // dev_consume_skb_any(skb); 148 | // return; 149 | // } 150 | 151 | // // lockdep_assert_in_softirq(); 152 | 153 | // if (!skb_unref(skb)) 154 | // return; 155 | 156 | // /* if reaching here SKB is ready to free */ 157 | // trace_consume_skb(skb); 158 | 159 | // /* if SKB is a clone, don't handle this case */ 160 | // if (skb->fclone != SKB_FCLONE_UNAVAILABLE) { 161 | // __kfree_skb(skb); 162 | // return; 163 | // } 164 | 165 | // skb_release_all(skb); 166 | // napi_skb_cache_put(skb); 167 | // } 168 | 169 | static inline int 170 | pci_request_mem_regions(struct pci_dev *pdev, const char *name) 171 | { 172 | return pci_request_selected_regions(pdev, 173 | pci_select_bars(pdev, IORESOURCE_MEM), name); 174 | } 175 | 176 | static inline void 177 | pci_release_mem_regions(struct pci_dev *pdev) 178 | { 179 | return pci_release_selected_regions(pdev, 180 | pci_select_bars(pdev, IORESOURCE_MEM)); 181 | } 182 | 183 | static inline bool ethtool_convert_link_mode_to_legacy_u32(u32 *legacy_u32, 184 | const unsigned long *src) 185 | { 186 | bool retval = true; 187 | 188 | /* TODO: following test will soon always be true */ 189 | if (__ETHTOOL_LINK_MODE_MASK_NBITS > 32) { 190 | __ETHTOOL_DECLARE_LINK_MODE_MASK(ext); 191 | 192 | bitmap_zero(ext, __ETHTOOL_LINK_MODE_MASK_NBITS); 193 | bitmap_fill(ext, 32); 194 | bitmap_complement(ext, ext, __ETHTOOL_LINK_MODE_MASK_NBITS); 195 | if (bitmap_intersects(ext, src, 196 | __ETHTOOL_LINK_MODE_MASK_NBITS)) { 197 | /* src mask goes beyond bit 31 */ 198 | retval = false; 199 | } 200 | } 201 | *legacy_u32 = src[0]; 202 | return retval; 203 | } 204 | 205 | static inline int page_ref_sub_and_test(struct page *page, int nr) 206 | { 207 | int ret = atomic_sub_and_test(nr, &page->_count); 208 | return ret; 209 | } 210 | 211 | static inline void __page_frag_cache_drain(struct page *page, unsigned int count) 212 | { 213 | if (page_ref_sub_and_test(page, count)) { 214 | unsigned int order = compound_order(page); 215 | 216 | // TODO optimize with free_unref_page 217 | // if (order == 0) 218 | // free_unref_page(page); 219 | // else 220 | __free_pages(page, order); 221 | } 222 | } -------------------------------------------------------------------------------- /backport_overflow.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 OR MIT */ 2 | #ifndef __LINUX_OVERFLOW_H 3 | #define __LINUX_OVERFLOW_H 4 | 5 | #include 6 | 7 | /* 8 | * In the fallback code below, we need to compute the minimum and 9 | * maximum values representable in a given type. These macros may also 10 | * be useful elsewhere, so we provide them outside the 11 | * COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW block. 12 | * 13 | * It would seem more obvious to do something like 14 | * 15 | * #define type_min(T) (T)(is_signed_type(T) ? (T)1 << (8*sizeof(T)-1) : 0) 16 | * #define type_max(T) (T)(is_signed_type(T) ? ((T)1 << (8*sizeof(T)-1)) - 1 : ~(T)0) 17 | * 18 | * Unfortunately, the middle expressions, strictly speaking, have 19 | * undefined behaviour, and at least some versions of gcc warn about 20 | * the type_max expression (but not if -fsanitize=undefined is in 21 | * effect; in that case, the warning is deferred to runtime...). 22 | * 23 | * The slightly excessive casting in type_min is to make sure the 24 | * macros also produce sensible values for the exotic type _Bool. [The 25 | * overflow checkers only almost work for _Bool, but that's 26 | * a-feature-not-a-bug, since people shouldn't be doing arithmetic on 27 | * _Bools. Besides, the gcc builtins don't allow _Bool* as third 28 | * argument.] 29 | * 30 | * Idea stolen from 31 | * https://mail-index.netbsd.org/tech-misc/2007/02/05/0000.html - 32 | * credit to Christian Biere. 33 | */ 34 | #define is_signed_type(type) (((type)(-1)) < (type)1) 35 | #define __type_half_max(type) ((type)1 << (8*sizeof(type) - 1 - is_signed_type(type))) 36 | #define type_max(T) ((T)((__type_half_max(T) - 1) + __type_half_max(T))) 37 | #define type_min(T) ((T)((T)-type_max(T)-(T)1)) 38 | 39 | 40 | #ifdef COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 41 | /* 42 | * For simplicity and code hygiene, the fallback code below insists on 43 | * a, b and *d having the same type (similar to the min() and max() 44 | * macros), whereas gcc's type-generic overflow checkers accept 45 | * different types. Hence we don't just make check_add_overflow an 46 | * alias for __builtin_add_overflow, but add type checks similar to 47 | * below. 48 | */ 49 | #define check_add_overflow(a, b, d) ({ \ 50 | typeof(a) __a = (a); \ 51 | typeof(b) __b = (b); \ 52 | typeof(d) __d = (d); \ 53 | (void) (&__a == &__b); \ 54 | (void) (&__a == __d); \ 55 | __builtin_add_overflow(__a, __b, __d); \ 56 | }) 57 | 58 | #define check_sub_overflow(a, b, d) ({ \ 59 | typeof(a) __a = (a); \ 60 | typeof(b) __b = (b); \ 61 | typeof(d) __d = (d); \ 62 | (void) (&__a == &__b); \ 63 | (void) (&__a == __d); \ 64 | __builtin_sub_overflow(__a, __b, __d); \ 65 | }) 66 | 67 | #define check_mul_overflow(a, b, d) ({ \ 68 | typeof(a) __a = (a); \ 69 | typeof(b) __b = (b); \ 70 | typeof(d) __d = (d); \ 71 | (void) (&__a == &__b); \ 72 | (void) (&__a == __d); \ 73 | __builtin_mul_overflow(__a, __b, __d); \ 74 | }) 75 | 76 | #else 77 | 78 | 79 | /* Checking for unsigned overflow is relatively easy without causing UB. */ 80 | #define __unsigned_add_overflow(a, b, d) ({ \ 81 | typeof(a) __a = (a); \ 82 | typeof(b) __b = (b); \ 83 | typeof(d) __d = (d); \ 84 | (void) (&__a == &__b); \ 85 | (void) (&__a == __d); \ 86 | *__d = __a + __b; \ 87 | *__d < __a; \ 88 | }) 89 | #define __unsigned_sub_overflow(a, b, d) ({ \ 90 | typeof(a) __a = (a); \ 91 | typeof(b) __b = (b); \ 92 | typeof(d) __d = (d); \ 93 | (void) (&__a == &__b); \ 94 | (void) (&__a == __d); \ 95 | *__d = __a - __b; \ 96 | __a < __b; \ 97 | }) 98 | /* 99 | * If one of a or b is a compile-time constant, this avoids a division. 100 | */ 101 | #define __unsigned_mul_overflow(a, b, d) ({ \ 102 | typeof(a) __a = (a); \ 103 | typeof(b) __b = (b); \ 104 | typeof(d) __d = (d); \ 105 | (void) (&__a == &__b); \ 106 | (void) (&__a == __d); \ 107 | *__d = __a * __b; \ 108 | __builtin_constant_p(__b) ? \ 109 | __b > 0 && __a > type_max(typeof(__a)) / __b : \ 110 | __a > 0 && __b > type_max(typeof(__b)) / __a; \ 111 | }) 112 | 113 | /* 114 | * For signed types, detecting overflow is much harder, especially if 115 | * we want to avoid UB. But the interface of these macros is such that 116 | * we must provide a result in *d, and in fact we must produce the 117 | * result promised by gcc's builtins, which is simply the possibly 118 | * wrapped-around value. Fortunately, we can just formally do the 119 | * operations in the widest relevant unsigned type (u64) and then 120 | * truncate the result - gcc is smart enough to generate the same code 121 | * with and without the (u64) casts. 122 | */ 123 | 124 | /* 125 | * Adding two signed integers can overflow only if they have the same 126 | * sign, and overflow has happened iff the result has the opposite 127 | * sign. 128 | */ 129 | #define __signed_add_overflow(a, b, d) ({ \ 130 | typeof(a) __a = (a); \ 131 | typeof(b) __b = (b); \ 132 | typeof(d) __d = (d); \ 133 | (void) (&__a == &__b); \ 134 | (void) (&__a == __d); \ 135 | *__d = (u64)__a + (u64)__b; \ 136 | (((~(__a ^ __b)) & (*__d ^ __a)) \ 137 | & type_min(typeof(__a))) != 0; \ 138 | }) 139 | 140 | /* 141 | * Subtraction is similar, except that overflow can now happen only 142 | * when the signs are opposite. In this case, overflow has happened if 143 | * the result has the opposite sign of a. 144 | */ 145 | #define __signed_sub_overflow(a, b, d) ({ \ 146 | typeof(a) __a = (a); \ 147 | typeof(b) __b = (b); \ 148 | typeof(d) __d = (d); \ 149 | (void) (&__a == &__b); \ 150 | (void) (&__a == __d); \ 151 | *__d = (u64)__a - (u64)__b; \ 152 | ((((__a ^ __b)) & (*__d ^ __a)) \ 153 | & type_min(typeof(__a))) != 0; \ 154 | }) 155 | 156 | /* 157 | * Signed multiplication is rather hard. gcc always follows C99, so 158 | * division is truncated towards 0. This means that we can write the 159 | * overflow check like this: 160 | * 161 | * (a > 0 && (b > MAX/a || b < MIN/a)) || 162 | * (a < -1 && (b > MIN/a || b < MAX/a) || 163 | * (a == -1 && b == MIN) 164 | * 165 | * The redundant casts of -1 are to silence an annoying -Wtype-limits 166 | * (included in -Wextra) warning: When the type is u8 or u16, the 167 | * __b_c_e in check_mul_overflow obviously selects 168 | * __unsigned_mul_overflow, but unfortunately gcc still parses this 169 | * code and warns about the limited range of __b. 170 | */ 171 | 172 | #define __signed_mul_overflow(a, b, d) ({ \ 173 | typeof(a) __a = (a); \ 174 | typeof(b) __b = (b); \ 175 | typeof(d) __d = (d); \ 176 | typeof(a) __tmax = type_max(typeof(a)); \ 177 | typeof(a) __tmin = type_min(typeof(a)); \ 178 | (void) (&__a == &__b); \ 179 | (void) (&__a == __d); \ 180 | *__d = (u64)__a * (u64)__b; \ 181 | (__b > 0 && (__a > __tmax/__b || __a < __tmin/__b)) || \ 182 | (__b < (typeof(__b))-1 && (__a > __tmin/__b || __a < __tmax/__b)) || \ 183 | (__b == (typeof(__b))-1 && __a == __tmin); \ 184 | }) 185 | 186 | 187 | #define check_add_overflow(a, b, d) \ 188 | __builtin_choose_expr(is_signed_type(typeof(a)), \ 189 | __signed_add_overflow(a, b, d), \ 190 | __unsigned_add_overflow(a, b, d)) 191 | 192 | #define check_sub_overflow(a, b, d) \ 193 | __builtin_choose_expr(is_signed_type(typeof(a)), \ 194 | __signed_sub_overflow(a, b, d), \ 195 | __unsigned_sub_overflow(a, b, d)) 196 | 197 | #define check_mul_overflow(a, b, d) \ 198 | __builtin_choose_expr(is_signed_type(typeof(a)), \ 199 | __signed_mul_overflow(a, b, d), \ 200 | __unsigned_mul_overflow(a, b, d)) 201 | 202 | 203 | #endif /* COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW */ 204 | 205 | /** 206 | * array_size() - Calculate size of 2-dimensional array. 207 | * 208 | * @a: dimension one 209 | * @b: dimension two 210 | * 211 | * Calculates size of 2-dimensional array: @a * @b. 212 | * 213 | * Returns: number of bytes needed to represent the array or SIZE_MAX on 214 | * overflow. 215 | */ 216 | static inline __must_check size_t array_size(size_t a, size_t b) 217 | { 218 | size_t bytes; 219 | 220 | if (check_mul_overflow(a, b, &bytes)) 221 | return SIZE_MAX; 222 | 223 | return bytes; 224 | } 225 | 226 | /** 227 | * array3_size() - Calculate size of 3-dimensional array. 228 | * 229 | * @a: dimension one 230 | * @b: dimension two 231 | * @c: dimension three 232 | * 233 | * Calculates size of 3-dimensional array: @a * @b * @c. 234 | * 235 | * Returns: number of bytes needed to represent the array or SIZE_MAX on 236 | * overflow. 237 | */ 238 | static inline __must_check size_t array3_size(size_t a, size_t b, size_t c) 239 | { 240 | size_t bytes; 241 | 242 | if (check_mul_overflow(a, b, &bytes)) 243 | return SIZE_MAX; 244 | if (check_mul_overflow(bytes, c, &bytes)) 245 | return SIZE_MAX; 246 | 247 | return bytes; 248 | } 249 | 250 | static inline __must_check size_t __ab_c_size(size_t n, size_t size, size_t c) 251 | { 252 | size_t bytes; 253 | 254 | if (check_mul_overflow(n, size, &bytes)) 255 | return SIZE_MAX; 256 | if (check_add_overflow(bytes, c, &bytes)) 257 | return SIZE_MAX; 258 | 259 | return bytes; 260 | } 261 | 262 | /** 263 | * struct_size() - Calculate size of structure with trailing array. 264 | * @p: Pointer to the structure. 265 | * @member: Name of the array member. 266 | * @n: Number of elements in the array. 267 | * 268 | * Calculates size of memory needed for structure @p followed by an 269 | * array of @n @member elements. 270 | * 271 | * Return: number of bytes needed or SIZE_MAX on overflow. 272 | */ 273 | #define struct_size(p, member, n) \ 274 | __ab_c_size(n, \ 275 | sizeof(*(p)->member) + __must_be_array((p)->member),\ 276 | sizeof(*(p))) 277 | 278 | #endif /* __LINUX_OVERFLOW_H */ 279 | -------------------------------------------------------------------------------- /igc.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | /* Copyright (c) 2018 Intel Corporation */ 3 | 4 | #ifndef _IGC_H_ 5 | #define _IGC_H_ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "igc_hw.h" 18 | 19 | void igc_ethtool_set_ops(struct net_device *); 20 | 21 | /* Transmit and receive queues */ 22 | #define IGC_MAX_RX_QUEUES 4 23 | #define IGC_MAX_TX_QUEUES 4 24 | 25 | #define MAX_Q_VECTORS 8 26 | #define MAX_STD_JUMBO_FRAME_SIZE 9216 27 | 28 | #define MAX_ETYPE_FILTER 8 29 | #define IGC_RETA_SIZE 128 30 | 31 | enum igc_mac_filter_type { 32 | IGC_MAC_FILTER_TYPE_DST = 0, 33 | IGC_MAC_FILTER_TYPE_SRC 34 | }; 35 | 36 | struct igc_tx_queue_stats { 37 | u64 packets; 38 | u64 bytes; 39 | u64 restart_queue; 40 | u64 restart_queue2; 41 | }; 42 | 43 | struct igc_rx_queue_stats { 44 | u64 packets; 45 | u64 bytes; 46 | u64 drops; 47 | u64 csum_err; 48 | u64 alloc_failed; 49 | }; 50 | 51 | struct igc_rx_packet_stats { 52 | u64 ipv4_packets; /* IPv4 headers processed */ 53 | u64 ipv4e_packets; /* IPv4E headers with extensions processed */ 54 | u64 ipv6_packets; /* IPv6 headers processed */ 55 | u64 ipv6e_packets; /* IPv6E headers with extensions processed */ 56 | u64 tcp_packets; /* TCP headers processed */ 57 | u64 udp_packets; /* UDP headers processed */ 58 | u64 sctp_packets; /* SCTP headers processed */ 59 | u64 nfs_packets; /* NFS headers processe */ 60 | u64 other_packets; 61 | }; 62 | 63 | struct igc_ring_container { 64 | struct igc_ring *ring; /* pointer to linked list of rings */ 65 | unsigned int total_bytes; /* total bytes processed this int */ 66 | unsigned int total_packets; /* total packets processed this int */ 67 | u16 work_limit; /* total work allowed per interrupt */ 68 | u8 count; /* total number of rings in vector */ 69 | u8 itr; /* current ITR setting for ring */ 70 | }; 71 | 72 | struct igc_ring { 73 | struct igc_q_vector *q_vector; /* backlink to q_vector */ 74 | struct net_device *netdev; /* back pointer to net_device */ 75 | struct device *dev; /* device for dma mapping */ 76 | union { /* array of buffer info structs */ 77 | struct igc_tx_buffer *tx_buffer_info; 78 | struct igc_rx_buffer *rx_buffer_info; 79 | }; 80 | void *desc; /* descriptor ring memory */ 81 | unsigned long flags; /* ring specific flags */ 82 | void __iomem *tail; /* pointer to ring tail register */ 83 | dma_addr_t dma; /* phys address of the ring */ 84 | unsigned int size; /* length of desc. ring in bytes */ 85 | 86 | u16 count; /* number of desc. in the ring */ 87 | u8 queue_index; /* logical index of the ring*/ 88 | u8 reg_idx; /* physical index of the ring */ 89 | bool launchtime_enable; /* true if LaunchTime is enabled */ 90 | 91 | u32 start_time; 92 | u32 end_time; 93 | 94 | /* everything past this point are written often */ 95 | u16 next_to_clean; 96 | u16 next_to_use; 97 | u16 next_to_alloc; 98 | 99 | union { 100 | /* TX */ 101 | struct { 102 | struct igc_tx_queue_stats tx_stats; 103 | struct u64_stats_sync tx_syncp; 104 | struct u64_stats_sync tx_syncp2; 105 | }; 106 | /* RX */ 107 | struct { 108 | struct igc_rx_queue_stats rx_stats; 109 | struct igc_rx_packet_stats pkt_stats; 110 | struct u64_stats_sync rx_syncp; 111 | struct sk_buff *skb; 112 | }; 113 | }; 114 | } ____cacheline_internodealigned_in_smp; 115 | 116 | /* Board specific private data structure */ 117 | struct igc_adapter { 118 | struct net_device *netdev; 119 | 120 | struct ethtool_eee eee; 121 | u16 eee_advert; 122 | 123 | unsigned long state; 124 | unsigned int flags; 125 | unsigned int num_q_vectors; 126 | 127 | struct msix_entry *msix_entries; 128 | 129 | /* TX */ 130 | u16 tx_work_limit; 131 | u32 tx_timeout_count; 132 | int num_tx_queues; 133 | struct igc_ring *tx_ring[IGC_MAX_TX_QUEUES]; 134 | 135 | /* RX */ 136 | int num_rx_queues; 137 | struct igc_ring *rx_ring[IGC_MAX_RX_QUEUES]; 138 | 139 | struct timer_list watchdog_timer; 140 | struct timer_list dma_err_timer; 141 | struct timer_list phy_info_timer; 142 | 143 | u32 wol; 144 | u32 en_mng_pt; 145 | u16 link_speed; 146 | u16 link_duplex; 147 | 148 | u8 port_num; 149 | 150 | u8 __iomem *io_addr; 151 | /* Interrupt Throttle Rate */ 152 | u32 rx_itr_setting; 153 | u32 tx_itr_setting; 154 | 155 | struct work_struct reset_task; 156 | struct work_struct watchdog_task; 157 | struct work_struct dma_err_task; 158 | bool fc_autoneg; 159 | 160 | u8 tx_timeout_factor; 161 | 162 | int msg_enable; 163 | u32 max_frame_size; 164 | u32 min_frame_size; 165 | 166 | ktime_t base_time; 167 | ktime_t cycle_time; 168 | 169 | /* OS defined structs */ 170 | struct pci_dev *pdev; 171 | /* lock for statistics */ 172 | spinlock_t stats64_lock; 173 | struct rtnl_link_stats64 stats64; 174 | 175 | /* structs defined in igc_hw.h */ 176 | struct igc_hw hw; 177 | struct igc_hw_stats stats; 178 | 179 | struct igc_q_vector *q_vector[MAX_Q_VECTORS]; 180 | u32 eims_enable_mask; 181 | u32 eims_other; 182 | 183 | u16 tx_ring_count; 184 | u16 rx_ring_count; 185 | 186 | u32 tx_hwtstamp_timeouts; 187 | u32 tx_hwtstamp_skipped; 188 | u32 rx_hwtstamp_cleared; 189 | 190 | u32 rss_queues; 191 | u32 rss_indir_tbl_init; 192 | 193 | /* Any access to elements in nfc_rule_list is protected by the 194 | * nfc_rule_lock. 195 | */ 196 | struct mutex nfc_rule_lock; 197 | struct list_head nfc_rule_list; 198 | unsigned int nfc_rule_count; 199 | 200 | u8 rss_indir_tbl[IGC_RETA_SIZE]; 201 | 202 | unsigned long link_check_timeout; 203 | struct igc_info ei; 204 | 205 | u32 test_icr; 206 | 207 | struct ptp_clock *ptp_clock; 208 | struct ptp_clock_info ptp_caps; 209 | struct work_struct ptp_tx_work; 210 | struct sk_buff *ptp_tx_skb; 211 | struct hwtstamp_config tstamp_config; 212 | unsigned long ptp_tx_start; 213 | unsigned int ptp_flags; 214 | /* System time value lock */ 215 | spinlock_t tmreg_lock; 216 | struct cyclecounter cc; 217 | struct timecounter tc; 218 | struct timespec64 prev_ptp_time; /* Pre-reset PTP clock */ 219 | ktime_t ptp_reset_start; /* Reset time in clock mono */ 220 | 221 | char fw_version[32]; 222 | }; 223 | 224 | void igc_up(struct igc_adapter *adapter); 225 | void igc_down(struct igc_adapter *adapter); 226 | int igc_open(struct net_device *netdev); 227 | int igc_close(struct net_device *netdev); 228 | int igc_setup_tx_resources(struct igc_ring *ring); 229 | int igc_setup_rx_resources(struct igc_ring *ring); 230 | void igc_free_tx_resources(struct igc_ring *ring); 231 | void igc_free_rx_resources(struct igc_ring *ring); 232 | unsigned int igc_get_max_rss_queues(struct igc_adapter *adapter); 233 | void igc_set_flag_queue_pairs(struct igc_adapter *adapter, 234 | const u32 max_rss_queues); 235 | int igc_reinit_queues(struct igc_adapter *adapter); 236 | void igc_write_rss_indir_tbl(struct igc_adapter *adapter); 237 | bool igc_has_link(struct igc_adapter *adapter); 238 | void igc_reset(struct igc_adapter *adapter); 239 | int igc_set_spd_dplx(struct igc_adapter *adapter, u32 spd, u8 dplx); 240 | void igc_update_stats(struct igc_adapter *adapter); 241 | 242 | /* igc_dump declarations */ 243 | void igc_rings_dump(struct igc_adapter *adapter); 244 | void igc_regs_dump(struct igc_adapter *adapter); 245 | 246 | extern char igc_driver_name[]; 247 | extern char igc_driver_version[]; 248 | 249 | #define IGC_REGS_LEN 740 250 | 251 | /* flags controlling PTP/1588 function */ 252 | #define IGC_PTP_ENABLED BIT(0) 253 | 254 | /* Flags definitions */ 255 | #define IGC_FLAG_HAS_MSI BIT(0) 256 | #define IGC_FLAG_QUEUE_PAIRS BIT(3) 257 | #define IGC_FLAG_DMAC BIT(4) 258 | #define IGC_FLAG_PTP BIT(8) 259 | #define IGC_FLAG_WOL_SUPPORTED BIT(8) 260 | #define IGC_FLAG_NEED_LINK_UPDATE BIT(9) 261 | #define IGC_FLAG_MEDIA_RESET BIT(10) 262 | #define IGC_FLAG_MAS_ENABLE BIT(12) 263 | #define IGC_FLAG_HAS_MSIX BIT(13) 264 | #define IGC_FLAG_EEE BIT(14) 265 | #define IGC_FLAG_VLAN_PROMISC BIT(15) 266 | #define IGC_FLAG_RX_LEGACY BIT(16) 267 | #define IGC_FLAG_TSN_QBV_ENABLED BIT(17) 268 | 269 | #define IGC_FLAG_RSS_FIELD_IPV4_UDP BIT(6) 270 | #define IGC_FLAG_RSS_FIELD_IPV6_UDP BIT(7) 271 | 272 | #define IGC_MRQC_ENABLE_RSS_MQ 0x00000002 273 | #define IGC_MRQC_RSS_FIELD_IPV4_UDP 0x00400000 274 | #define IGC_MRQC_RSS_FIELD_IPV6_UDP 0x00800000 275 | 276 | /* Interrupt defines */ 277 | #define IGC_START_ITR 648 /* ~6000 ints/sec */ 278 | #define IGC_4K_ITR 980 279 | #define IGC_20K_ITR 196 280 | #define IGC_70K_ITR 56 281 | 282 | #define IGC_DEFAULT_ITR 3 /* dynamic */ 283 | #define IGC_MAX_ITR_USECS 10000 284 | #define IGC_MIN_ITR_USECS 10 285 | #define NON_Q_VECTORS 1 286 | #define MAX_MSIX_ENTRIES 10 287 | 288 | /* TX/RX descriptor defines */ 289 | #define IGC_DEFAULT_TXD 256 290 | #define IGC_DEFAULT_TX_WORK 128 291 | #define IGC_MIN_TXD 80 292 | #define IGC_MAX_TXD 4096 293 | 294 | #define IGC_DEFAULT_RXD 256 295 | #define IGC_MIN_RXD 80 296 | #define IGC_MAX_RXD 4096 297 | 298 | /* Supported Rx Buffer Sizes */ 299 | #define IGC_RXBUFFER_256 256 300 | #define IGC_RXBUFFER_2048 2048 301 | #define IGC_RXBUFFER_3072 3072 302 | 303 | #define AUTO_ALL_MODES 0 304 | #define IGC_RX_HDR_LEN IGC_RXBUFFER_256 305 | 306 | /* Transmit and receive latency (for PTP timestamps) */ 307 | #define IGC_I225_TX_LATENCY_10 240 308 | #define IGC_I225_TX_LATENCY_100 58 309 | #define IGC_I225_TX_LATENCY_1000 80 310 | #define IGC_I225_TX_LATENCY_2500 1325 311 | #define IGC_I225_RX_LATENCY_10 6450 312 | #define IGC_I225_RX_LATENCY_100 185 313 | #define IGC_I225_RX_LATENCY_1000 300 314 | #define IGC_I225_RX_LATENCY_2500 1485 315 | 316 | /* RX and TX descriptor control thresholds. 317 | * PTHRESH - MAC will consider prefetch if it has fewer than this number of 318 | * descriptors available in its onboard memory. 319 | * Setting this to 0 disables RX descriptor prefetch. 320 | * HTHRESH - MAC will only prefetch if there are at least this many descriptors 321 | * available in host memory. 322 | * If PTHRESH is 0, this should also be 0. 323 | * WTHRESH - RX descriptor writeback threshold - MAC will delay writing back 324 | * descriptors until either it has this many to write back, or the 325 | * ITR timer expires. 326 | */ 327 | #define IGC_RX_PTHRESH 8 328 | #define IGC_RX_HTHRESH 8 329 | #define IGC_TX_PTHRESH 8 330 | #define IGC_TX_HTHRESH 1 331 | #define IGC_RX_WTHRESH 4 332 | #define IGC_TX_WTHRESH 16 333 | 334 | #define IGC_RX_DMA_ATTR \ 335 | (DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_WEAK_ORDERING) 336 | 337 | #define IGC_TS_HDR_LEN 16 338 | 339 | #define IGC_SKB_PAD (NET_SKB_PAD + NET_IP_ALIGN) 340 | 341 | #if (PAGE_SIZE < 8192) 342 | #define IGC_MAX_FRAME_BUILD_SKB \ 343 | (SKB_WITH_OVERHEAD(IGC_RXBUFFER_2048) - IGC_SKB_PAD - IGC_TS_HDR_LEN) 344 | #else 345 | #define IGC_MAX_FRAME_BUILD_SKB (IGC_RXBUFFER_2048 - IGC_TS_HDR_LEN) 346 | #endif 347 | 348 | /* How many Rx Buffers do we bundle into one write to the hardware ? */ 349 | #define IGC_RX_BUFFER_WRITE 16 /* Must be power of 2 */ 350 | 351 | /* VLAN info */ 352 | #define IGC_TX_FLAGS_VLAN_MASK 0xffff0000 353 | 354 | /* igc_test_staterr - tests bits within Rx descriptor status and error fields */ 355 | static inline __le32 igc_test_staterr(union igc_adv_rx_desc *rx_desc, 356 | const u32 stat_err_bits) 357 | { 358 | return rx_desc->wb.upper.status_error & cpu_to_le32(stat_err_bits); 359 | } 360 | 361 | enum igc_state_t { 362 | __IGC_TESTING, 363 | __IGC_RESETTING, 364 | __IGC_DOWN, 365 | __IGC_PTP_TX_IN_PROGRESS, 366 | }; 367 | 368 | enum igc_tx_flags { 369 | /* cmd_type flags */ 370 | IGC_TX_FLAGS_VLAN = 0x01, 371 | IGC_TX_FLAGS_TSO = 0x02, 372 | IGC_TX_FLAGS_TSTAMP = 0x04, 373 | 374 | /* olinfo flags */ 375 | IGC_TX_FLAGS_IPV4 = 0x10, 376 | IGC_TX_FLAGS_CSUM = 0x20, 377 | }; 378 | 379 | enum igc_boards { 380 | board_base, 381 | }; 382 | 383 | /* The largest size we can write to the descriptor is 65535. In order to 384 | * maintain a power of two alignment we have to limit ourselves to 32K. 385 | */ 386 | #define IGC_MAX_TXD_PWR 15 387 | #define IGC_MAX_DATA_PER_TXD BIT(IGC_MAX_TXD_PWR) 388 | 389 | /* Tx Descriptors needed, worst case */ 390 | #define TXD_USE_COUNT(S) DIV_ROUND_UP((S), IGC_MAX_DATA_PER_TXD) 391 | #define DESC_NEEDED (MAX_SKB_FRAGS + 4) 392 | 393 | /* wrapper around a pointer to a socket buffer, 394 | * so a DMA handle can be stored along with the buffer 395 | */ 396 | struct igc_tx_buffer { 397 | union igc_adv_tx_desc *next_to_watch; 398 | unsigned long time_stamp; 399 | struct sk_buff *skb; 400 | unsigned int bytecount; 401 | u16 gso_segs; 402 | __be16 protocol; 403 | 404 | DEFINE_DMA_UNMAP_ADDR(dma); 405 | DEFINE_DMA_UNMAP_LEN(len); 406 | u32 tx_flags; 407 | }; 408 | 409 | struct igc_rx_buffer { 410 | dma_addr_t dma; 411 | struct page *page; 412 | #if (BITS_PER_LONG > 32) || (PAGE_SIZE >= 65536) 413 | __u32 page_offset; 414 | #else 415 | __u16 page_offset; 416 | #endif 417 | __u16 pagecnt_bias; 418 | }; 419 | 420 | struct igc_q_vector { 421 | struct igc_adapter *adapter; /* backlink */ 422 | void __iomem *itr_register; 423 | u32 eims_value; /* EIMS mask value */ 424 | 425 | u16 itr_val; 426 | u8 set_itr; 427 | 428 | struct igc_ring_container rx, tx; 429 | 430 | struct napi_struct napi; 431 | 432 | struct rcu_head rcu; /* to avoid race with update stats on free */ 433 | char name[IFNAMSIZ + 9]; 434 | struct net_device poll_dev; 435 | 436 | /* for dynamic allocation of rings associated with this q_vector */ 437 | struct igc_ring ring[] ____cacheline_internodealigned_in_smp; 438 | }; 439 | 440 | enum igc_filter_match_flags { 441 | IGC_FILTER_FLAG_ETHER_TYPE = 0x1, 442 | IGC_FILTER_FLAG_VLAN_TCI = 0x2, 443 | IGC_FILTER_FLAG_SRC_MAC_ADDR = 0x4, 444 | IGC_FILTER_FLAG_DST_MAC_ADDR = 0x8, 445 | }; 446 | 447 | struct igc_nfc_filter { 448 | u8 match_flags; 449 | u16 etype; 450 | u16 vlan_tci; 451 | u8 src_addr[ETH_ALEN]; 452 | u8 dst_addr[ETH_ALEN]; 453 | }; 454 | 455 | struct igc_nfc_rule { 456 | struct list_head list; 457 | struct igc_nfc_filter filter; 458 | u32 location; 459 | u16 action; 460 | }; 461 | 462 | /* IGC supports a total of 32 NFC rules: 16 MAC address based,, 8 VLAN priority 463 | * based, and 8 ethertype based. 464 | */ 465 | #define IGC_MAX_RXNFC_RULES 32 466 | 467 | /* igc_desc_unused - calculate if we have unused descriptors */ 468 | static inline u16 igc_desc_unused(const struct igc_ring *ring) 469 | { 470 | u16 ntc = ring->next_to_clean; 471 | u16 ntu = ring->next_to_use; 472 | 473 | return ((ntc > ntu) ? 0 : ring->count) + ntc - ntu - 1; 474 | } 475 | 476 | static inline s32 igc_get_phy_info(struct igc_hw *hw) 477 | { 478 | if (hw->phy.ops.get_phy_info) 479 | return hw->phy.ops.get_phy_info(hw); 480 | 481 | return 0; 482 | } 483 | 484 | static inline s32 igc_reset_phy(struct igc_hw *hw) 485 | { 486 | if (hw->phy.ops.reset) 487 | return hw->phy.ops.reset(hw); 488 | 489 | return 0; 490 | } 491 | 492 | static inline struct netdev_queue *txring_txq(const struct igc_ring *tx_ring) 493 | { 494 | return netdev_get_tx_queue(tx_ring->netdev, tx_ring->queue_index); 495 | } 496 | 497 | enum igc_ring_flags_t { 498 | IGC_RING_FLAG_RX_3K_BUFFER, 499 | IGC_RING_FLAG_RX_BUILD_SKB_ENABLED, 500 | IGC_RING_FLAG_RX_SCTP_CSUM, 501 | IGC_RING_FLAG_RX_LB_VLAN_BSWAP, 502 | IGC_RING_FLAG_TX_CTX_IDX, 503 | IGC_RING_FLAG_TX_DETECT_HANG 504 | }; 505 | 506 | #define ring_uses_large_buffer(ring) \ 507 | test_bit(IGC_RING_FLAG_RX_3K_BUFFER, &(ring)->flags) 508 | 509 | #define ring_uses_build_skb(ring) \ 510 | test_bit(IGC_RING_FLAG_RX_BUILD_SKB_ENABLED, &(ring)->flags) 511 | 512 | static inline unsigned int igc_rx_bufsz(struct igc_ring *ring) 513 | { 514 | #if (PAGE_SIZE < 8192) 515 | if (ring_uses_large_buffer(ring)) 516 | return IGC_RXBUFFER_3072; 517 | 518 | if (ring_uses_build_skb(ring)) 519 | return IGC_MAX_FRAME_BUILD_SKB + IGC_TS_HDR_LEN; 520 | #endif 521 | return IGC_RXBUFFER_2048; 522 | } 523 | 524 | static inline unsigned int igc_rx_pg_order(struct igc_ring *ring) 525 | { 526 | #if (PAGE_SIZE < 8192) 527 | if (ring_uses_large_buffer(ring)) 528 | return 1; 529 | #endif 530 | return 0; 531 | } 532 | 533 | static inline s32 igc_read_phy_reg(struct igc_hw *hw, u32 offset, u16 *data) 534 | { 535 | if (hw->phy.ops.read_reg) 536 | return hw->phy.ops.read_reg(hw, offset, data); 537 | 538 | return -EOPNOTSUPP; 539 | } 540 | 541 | void igc_reinit_locked(struct igc_adapter *); 542 | struct igc_nfc_rule *igc_get_nfc_rule(struct igc_adapter *adapter, 543 | u32 location); 544 | int igc_add_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule); 545 | void igc_del_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule); 546 | 547 | void igc_ptp_init(struct igc_adapter *adapter); 548 | void igc_ptp_reset(struct igc_adapter *adapter); 549 | void igc_ptp_suspend(struct igc_adapter *adapter); 550 | void igc_ptp_stop(struct igc_adapter *adapter); 551 | void igc_ptp_rx_pktstamp(struct igc_q_vector *q_vector, __le32 *va, 552 | struct sk_buff *skb); 553 | int igc_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr); 554 | int igc_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr); 555 | void igc_ptp_tx_hang(struct igc_adapter *adapter); 556 | void igc_ptp_read(struct igc_adapter *adapter, struct timespec64 *ts); 557 | 558 | #define igc_rx_pg_size(_ring) (PAGE_SIZE << igc_rx_pg_order(_ring)) 559 | 560 | #define IGC_TXD_DCMD (IGC_ADVTXD_DCMD_EOP | IGC_ADVTXD_DCMD_RS) 561 | 562 | #define IGC_RX_DESC(R, i) \ 563 | (&(((union igc_adv_rx_desc *)((R)->desc))[i])) 564 | #define IGC_TX_DESC(R, i) \ 565 | (&(((union igc_adv_tx_desc *)((R)->desc))[i])) 566 | #define IGC_TX_CTXTDESC(R, i) \ 567 | (&(((struct igc_adv_tx_context_desc *)((R)->desc))[i])) 568 | 569 | #endif /* _IGC_H_ */ 570 | -------------------------------------------------------------------------------- /igc/releases/apollolake_42218.json: -------------------------------------------------------------------------------- 1 | { 2 | "mod_version": "1.3.1", 3 | 4 | "files": [ 5 | { 6 | "name": "igc-apollolake.tgz", 7 | "url": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/igc-apollolake.tgz", 8 | "sha256": "eee0addbdda861622f3126c7f6e2b21ccd3a2dcf0d4637ab84e0a510e71e924f", 9 | "packed": true 10 | }, 11 | { 12 | "name": "check-igc.sh", 13 | "url": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/src/check-igc.sh", 14 | "sha256": "4892e37cc4f974700b88332e005d61676257876938f8e57677c655a2eca5a8ef", 15 | "packed": false 16 | } 17 | ], 18 | 19 | "kmods": { 20 | "igc.ko": "" 21 | }, 22 | 23 | "scripts": { 24 | "on_boot": "check-igc.sh" 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /igc/releases/broadwell_42218.json: -------------------------------------------------------------------------------- 1 | { 2 | "mod_version": "1.3.1", 3 | 4 | "files": [ 5 | { 6 | "name": "igc-broadwell.tgz", 7 | "url": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/igc-broadwell.tgz", 8 | "sha256": "f9fde02c3197ac3adb1769f453ef8ade8f879e705b5ed7aa505c5300c6ef5a50", 9 | "packed": true 10 | }, 11 | { 12 | "name": "check-igc.sh", 13 | "url": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/src/check-igc.sh", 14 | "sha256": "4892e37cc4f974700b88332e005d61676257876938f8e57677c655a2eca5a8ef", 15 | "packed": false 16 | } 17 | ], 18 | 19 | "kmods": { 20 | "igc.ko": "" 21 | }, 22 | 23 | "scripts": { 24 | "on_boot": "check-igc.sh" 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /igc/releases/broadwellnk_42218.json: -------------------------------------------------------------------------------- 1 | { 2 | "mod_version": "1.3.1", 3 | 4 | "files": [ 5 | { 6 | "name": "igc-broadwellnk.tgz", 7 | "url": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/igc-broadwellnk.tgz", 8 | "sha256": "04afa9da36bcea1efdab14267788098eed741ab167b6910f7283cf9e621b7233", 9 | "packed": true 10 | }, 11 | { 12 | "name": "check-igc.sh", 13 | "url": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/src/check-igc.sh", 14 | "sha256": "4892e37cc4f974700b88332e005d61676257876938f8e57677c655a2eca5a8ef", 15 | "packed": false 16 | } 17 | ], 18 | 19 | "kmods": { 20 | "igc.ko": "" 21 | }, 22 | 23 | "scripts": { 24 | "on_boot": "check-igc.sh" 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /igc/releases/denverton_42218.json: -------------------------------------------------------------------------------- 1 | { 2 | "mod_version": "1.3.1", 3 | 4 | "files": [ 5 | { 6 | "name": "igc-denverton.tgz", 7 | "url": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/igc-denverton.tgz", 8 | "sha256": "7775539f8fb42da716e6ac8b48c4001005f569716b3a908d6523e4710bde3ad4", 9 | "packed": true 10 | }, 11 | { 12 | "name": "check-igc.sh", 13 | "url": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/src/check-igc.sh", 14 | "sha256": "4892e37cc4f974700b88332e005d61676257876938f8e57677c655a2eca5a8ef", 15 | "packed": false 16 | } 17 | ], 18 | 19 | "kmods": { 20 | "igc.ko": "" 21 | }, 22 | 23 | "scripts": { 24 | "on_boot": "check-igc.sh" 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /igc/releases/epyc7002_42962.json: -------------------------------------------------------------------------------- 1 | { 2 | "mod_version": "1.3.1", 3 | 4 | "files": [ 5 | { 6 | "name": "igc-epyc7002.tgz", 7 | "url": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/igc-epyc7002.tgz", 8 | "sha256": "12bd8493bd7285fa4d9790ebacd1efe43caafd5134ec5d350edab12a829cdbff", 9 | "packed": true 10 | }, 11 | { 12 | "name": "check-igc.sh", 13 | "url": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/src/check-igc.sh", 14 | "sha256": "4892e37cc4f974700b88332e005d61676257876938f8e57677c655a2eca5a8ef", 15 | "packed": false 16 | } 17 | ], 18 | 19 | "kmods": { 20 | "igc.ko": "" 21 | }, 22 | 23 | "scripts": { 24 | "on_boot": "check-igc.sh" 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /igc/releases/geminilake_42218.json: -------------------------------------------------------------------------------- 1 | { 2 | "mod_version": "1.3.1", 3 | 4 | "files": [ 5 | { 6 | "name": "igc-geminilake.tgz", 7 | "url": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/igc-geminilake.tgz", 8 | "sha256": "b66aa18f4104c1649987e0fafff2380686d0f683b7d4d55a5f9c4f150393988b", 9 | "packed": true 10 | }, 11 | { 12 | "name": "check-igc.sh", 13 | "url": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/src/check-igc.sh", 14 | "sha256": "4892e37cc4f974700b88332e005d61676257876938f8e57677c655a2eca5a8ef", 15 | "packed": false 16 | } 17 | ], 18 | 19 | "kmods": { 20 | "igc.ko": "" 21 | }, 22 | 23 | "scripts": { 24 | "on_boot": "check-igc.sh" 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /igc/releases/igc-apollolake.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jim3ma/synology-igc/d8cd0f0c155f35eed7b4a10ef57b28d9630ea78c/igc/releases/igc-apollolake.tgz -------------------------------------------------------------------------------- /igc/releases/igc-broadwell.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jim3ma/synology-igc/d8cd0f0c155f35eed7b4a10ef57b28d9630ea78c/igc/releases/igc-broadwell.tgz -------------------------------------------------------------------------------- /igc/releases/igc-broadwellnk.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jim3ma/synology-igc/d8cd0f0c155f35eed7b4a10ef57b28d9630ea78c/igc/releases/igc-broadwellnk.tgz -------------------------------------------------------------------------------- /igc/releases/igc-denverton.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jim3ma/synology-igc/d8cd0f0c155f35eed7b4a10ef57b28d9630ea78c/igc/releases/igc-denverton.tgz -------------------------------------------------------------------------------- /igc/releases/igc-epyc7002.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jim3ma/synology-igc/d8cd0f0c155f35eed7b4a10ef57b28d9630ea78c/igc/releases/igc-epyc7002.tgz -------------------------------------------------------------------------------- /igc/releases/igc-geminilake.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jim3ma/synology-igc/d8cd0f0c155f35eed7b4a10ef57b28d9630ea78c/igc/releases/igc-geminilake.tgz -------------------------------------------------------------------------------- /igc/releases/igc-r1000.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jim3ma/synology-igc/d8cd0f0c155f35eed7b4a10ef57b28d9630ea78c/igc/releases/igc-r1000.tgz -------------------------------------------------------------------------------- /igc/releases/igc-v1000.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jim3ma/synology-igc/d8cd0f0c155f35eed7b4a10ef57b28d9630ea78c/igc/releases/igc-v1000.tgz -------------------------------------------------------------------------------- /igc/releases/r1000_42218.json: -------------------------------------------------------------------------------- 1 | { 2 | "mod_version": "1.3.1", 3 | 4 | "files": [ 5 | { 6 | "name": "igc-r1000.tgz", 7 | "url": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/igc-r1000.tgz", 8 | "sha256": "e5d52d9aaf0f7c9a55d5c6e046c8cce023b2aa05bad626f69660736ea333e60b", 9 | "packed": true 10 | }, 11 | { 12 | "name": "check-igc.sh", 13 | "url": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/src/check-igc.sh", 14 | "sha256": "4892e37cc4f974700b88332e005d61676257876938f8e57677c655a2eca5a8ef", 15 | "packed": false 16 | } 17 | ], 18 | 19 | "kmods": { 20 | "igc.ko": "" 21 | }, 22 | 23 | "scripts": { 24 | "on_boot": "check-igc.sh" 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /igc/releases/v1000_42218.json: -------------------------------------------------------------------------------- 1 | { 2 | "mod_version": "1.3.1", 3 | 4 | "files": [ 5 | { 6 | "name": "igc-v1000.tgz", 7 | "url": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/igc-v1000.tgz", 8 | "sha256": "de4d55d9360b27fc678a1bd2dfa38005e04ae79979f2531aefd2f57c5a3ab9f8", 9 | "packed": true 10 | }, 11 | { 12 | "name": "check-igc.sh", 13 | "url": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/src/check-igc.sh", 14 | "sha256": "4892e37cc4f974700b88332e005d61676257876938f8e57677c655a2eca5a8ef", 15 | "packed": false 16 | } 17 | ], 18 | 19 | "kmods": { 20 | "igc.ko": "" 21 | }, 22 | 23 | "scripts": { 24 | "on_boot": "check-igc.sh" 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /igc/rpext-index.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "jim3ma.igc", 3 | "url": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/rpext-index.json", 4 | "info": { 5 | "name": "igc", 6 | "description": "Adds Intel(R) 2.5G Ethernet Linux Driver Support", 7 | "author_url": "https://github.com/jim3ma/synology-igc", 8 | "packer_url": "https://github.com/jim3ma/synology-igc", 9 | "help_url": "" 10 | }, 11 | "releases": { 12 | "ds3617xs_42218": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/broadwell_42218.json", 13 | "ds3617xs_42621": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/broadwell_42218.json", 14 | "ds3617xs_42661": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/broadwell_42218.json", 15 | "ds3617xs_42951": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/broadwell_42218.json", 16 | "ds3617xs_42962": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/broadwell_42218.json", 17 | "ds3622xsp_42218": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/broadwellnk_42218.json", 18 | "ds3622xsp_42621": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/broadwellnk_42218.json", 19 | "ds3622xsp_42661": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/broadwellnk_42218.json", 20 | "ds3622xsp_42951": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/broadwellnk_42218.json", 21 | "ds3622xsp_42962": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/broadwellnk_42218.json", 22 | "rs4021xsp_42218": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/broadwellnk_42218.json", 23 | "rs4021xsp_42621": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/broadwellnk_42218.json", 24 | "rs4021xsp_42661": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/broadwellnk_42218.json", 25 | "rs4021xsp_42951": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/broadwellnk_42218.json", 26 | "rs4021xsp_42962": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/broadwellnk_42218.json", 27 | "fs3600_42218": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/broadwellnk_42218.json", 28 | "fs3600_42621": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/broadwellnk_42218.json", 29 | "fs3600_42661": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/broadwellnk_42218.json", 30 | "fs3600_42951": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/broadwellnk_42218.json", 31 | "fs3600_42962": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/broadwellnk_42218.json", 32 | "ds1621p_42218": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/v1000_42218.json", 33 | "ds1621p_42621": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/v1000_42218.json", 34 | "ds1621p_42661": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/v1000_42218.json", 35 | "ds1621p_42951": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/v1000_42218.json", 36 | "ds1621p_42962": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/v1000_42218.json", 37 | "ds1821p_42218": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/v1000_42218.json", 38 | "ds1821p_42621": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/v1000_42218.json", 39 | "ds1821p_42661": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/v1000_42218.json", 40 | "ds1821p_42951": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/v1000_42218.json", 41 | "ds1821p_42962": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/v1000_42218.json", 42 | "ds2422p_42218": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/v1000_42218.json", 43 | "ds2422p_42621": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/v1000_42218.json", 44 | "ds2422p_42661": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/v1000_42218.json", 45 | "ds2422p_42951": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/v1000_42218.json", 46 | "ds2422p_42962": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/v1000_42218.json", 47 | "fs2500_42218": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/v1000_42218.json", 48 | "fs2500_42621": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/v1000_42218.json", 49 | "fs2500_42661": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/v1000_42218.json", 50 | "fs2500_42951": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/v1000_42218.json", 51 | "fs2500_42962": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/v1000_42218.json", 52 | "dva3221_42218": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/denverton_42218.json", 53 | "dva3221_42621": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/denverton_42218.json", 54 | "dva3221_42661": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/denverton_42218.json", 55 | "dva3221_42951": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/denverton_42218.json", 56 | "dva3221_42962": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/denverton_42218.json", 57 | "ds918p_42218": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/apollolake_42218.json", 58 | "ds918p_42621": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/apollolake_42218.json", 59 | "ds918p_42661": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/apollolake_42218.json", 60 | "ds918p_42951": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/apollolake_42218.json", 61 | "ds918p_42962": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/apollolake_42218.json", 62 | "ds920p_42218": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/geminilake_42218.json", 63 | "ds920p_42621": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/geminilake_42218.json", 64 | "ds920p_42661": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/geminilake_42218.json", 65 | "ds920p_42951": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/geminilake_42218.json", 66 | "ds920p_42962": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/geminilake_42218.json", 67 | "ds1520p_42218": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/geminilake_42218.json", 68 | "ds1520p_42621": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/geminilake_42218.json", 69 | "ds1520p_42661": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/geminilake_42218.json", 70 | "ds1520p_42951": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/geminilake_42218.json", 71 | "ds1520p_42962": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/geminilake_42218.json", 72 | "dva1622_42218": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/geminilake_42218.json", 73 | "dva1622_42621": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/geminilake_42218.json", 74 | "dva1622_42661": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/geminilake_42218.json", 75 | "dva1622_42951": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/geminilake_42218.json", 76 | "dva1622_42962": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/geminilake_42218.json", 77 | "ds923p_42962": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/r1000_42218.json", 78 | "sa6400_42962": "https://raw.githubusercontent.com/jim3ma/synology-igc/master/igc/releases/epyc7002_42962.json", 79 | "endofmodel": "endofurls" 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /igc/src/check-igc.sh: -------------------------------------------------------------------------------- 1 | # 2 | # Checking modules is loaded 3 | # 4 | 5 | echo -n "Loading module igc -> " 6 | 7 | if [ `/sbin/lsmod |grep -i igc|wc -l` -gt 0 ] ; then 8 | echo "Module igc loaded succesfully" 9 | else echo "Module igc is not loaded " 10 | fi 11 | -------------------------------------------------------------------------------- /igc_base.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | /* Copyright (c) 2018 Intel Corporation */ 3 | 4 | #include 5 | 6 | #include "igc_hw.h" 7 | #include "igc_i225.h" 8 | #include "igc_mac.h" 9 | #include "igc_base.h" 10 | #include "igc.h" 11 | 12 | /** 13 | * igc_reset_hw_base - Reset hardware 14 | * @hw: pointer to the HW structure 15 | * 16 | * This resets the hardware into a known state. This is a 17 | * function pointer entry point called by the api module. 18 | */ 19 | static s32 igc_reset_hw_base(struct igc_hw *hw) 20 | { 21 | s32 ret_val; 22 | u32 ctrl; 23 | 24 | /* Prevent the PCI-E bus from sticking if there is no TLP connection 25 | * on the last TLP read/write transaction when MAC is reset. 26 | */ 27 | ret_val = igc_disable_pcie_master(hw); 28 | if (ret_val) 29 | hw_dbg("PCI-E Master disable polling has failed\n"); 30 | 31 | hw_dbg("Masking off all interrupts\n"); 32 | wr32(IGC_IMC, 0xffffffff); 33 | 34 | wr32(IGC_RCTL, 0); 35 | wr32(IGC_TCTL, IGC_TCTL_PSP); 36 | wrfl(); 37 | 38 | usleep_range(10000, 20000); 39 | 40 | ctrl = rd32(IGC_CTRL); 41 | 42 | hw_dbg("Issuing a global reset to MAC\n"); 43 | wr32(IGC_CTRL, ctrl | IGC_CTRL_DEV_RST); 44 | 45 | ret_val = igc_get_auto_rd_done(hw); 46 | if (ret_val) { 47 | /* When auto config read does not complete, do not 48 | * return with an error. This can happen in situations 49 | * where there is no eeprom and prevents getting link. 50 | */ 51 | hw_dbg("Auto Read Done did not complete\n"); 52 | } 53 | 54 | /* Clear any pending interrupt events. */ 55 | wr32(IGC_IMC, 0xffffffff); 56 | rd32(IGC_ICR); 57 | 58 | return ret_val; 59 | } 60 | 61 | /** 62 | * igc_init_nvm_params_base - Init NVM func ptrs. 63 | * @hw: pointer to the HW structure 64 | */ 65 | static s32 igc_init_nvm_params_base(struct igc_hw *hw) 66 | { 67 | struct igc_nvm_info *nvm = &hw->nvm; 68 | u32 eecd = rd32(IGC_EECD); 69 | u16 size; 70 | 71 | size = (u16)((eecd & IGC_EECD_SIZE_EX_MASK) >> 72 | IGC_EECD_SIZE_EX_SHIFT); 73 | 74 | /* Added to a constant, "size" becomes the left-shift value 75 | * for setting word_size. 76 | */ 77 | size += NVM_WORD_SIZE_BASE_SHIFT; 78 | 79 | /* Just in case size is out of range, cap it to the largest 80 | * EEPROM size supported 81 | */ 82 | if (size > 15) 83 | size = 15; 84 | 85 | nvm->type = igc_nvm_eeprom_spi; 86 | nvm->word_size = BIT(size); 87 | nvm->opcode_bits = 8; 88 | nvm->delay_usec = 1; 89 | 90 | nvm->page_size = eecd & IGC_EECD_ADDR_BITS ? 32 : 8; 91 | nvm->address_bits = eecd & IGC_EECD_ADDR_BITS ? 92 | 16 : 8; 93 | 94 | if (nvm->word_size == BIT(15)) 95 | nvm->page_size = 128; 96 | 97 | return 0; 98 | } 99 | 100 | /** 101 | * igc_setup_copper_link_base - Configure copper link settings 102 | * @hw: pointer to the HW structure 103 | * 104 | * Configures the link for auto-neg or forced speed and duplex. Then we check 105 | * for link, once link is established calls to configure collision distance 106 | * and flow control are called. 107 | */ 108 | static s32 igc_setup_copper_link_base(struct igc_hw *hw) 109 | { 110 | s32 ret_val = 0; 111 | u32 ctrl; 112 | 113 | ctrl = rd32(IGC_CTRL); 114 | ctrl |= IGC_CTRL_SLU; 115 | ctrl &= ~(IGC_CTRL_FRCSPD | IGC_CTRL_FRCDPX); 116 | wr32(IGC_CTRL, ctrl); 117 | 118 | ret_val = igc_setup_copper_link(hw); 119 | 120 | return ret_val; 121 | } 122 | 123 | /** 124 | * igc_init_mac_params_base - Init MAC func ptrs. 125 | * @hw: pointer to the HW structure 126 | */ 127 | static s32 igc_init_mac_params_base(struct igc_hw *hw) 128 | { 129 | struct igc_dev_spec_base *dev_spec = &hw->dev_spec._base; 130 | struct igc_mac_info *mac = &hw->mac; 131 | 132 | /* Set mta register count */ 133 | mac->mta_reg_count = 128; 134 | mac->rar_entry_count = IGC_RAR_ENTRIES; 135 | 136 | /* reset */ 137 | mac->ops.reset_hw = igc_reset_hw_base; 138 | 139 | mac->ops.acquire_swfw_sync = igc_acquire_swfw_sync_i225; 140 | mac->ops.release_swfw_sync = igc_release_swfw_sync_i225; 141 | 142 | /* Allow a single clear of the SW semaphore on I225 */ 143 | if (mac->type == igc_i225) 144 | dev_spec->clear_semaphore_once = true; 145 | 146 | /* physical interface link setup */ 147 | mac->ops.setup_physical_interface = igc_setup_copper_link_base; 148 | 149 | return 0; 150 | } 151 | 152 | /** 153 | * igc_init_phy_params_base - Init PHY func ptrs. 154 | * @hw: pointer to the HW structure 155 | */ 156 | static s32 igc_init_phy_params_base(struct igc_hw *hw) 157 | { 158 | struct igc_phy_info *phy = &hw->phy; 159 | s32 ret_val = 0; 160 | 161 | if (hw->phy.media_type != igc_media_type_copper) { 162 | phy->type = igc_phy_none; 163 | goto out; 164 | } 165 | 166 | phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT_2500; 167 | phy->reset_delay_us = 100; 168 | 169 | /* set lan id */ 170 | hw->bus.func = (rd32(IGC_STATUS) & IGC_STATUS_FUNC_MASK) >> 171 | IGC_STATUS_FUNC_SHIFT; 172 | 173 | /* Make sure the PHY is in a good state. Several people have reported 174 | * firmware leaving the PHY's page select register set to something 175 | * other than the default of zero, which causes the PHY ID read to 176 | * access something other than the intended register. 177 | */ 178 | ret_val = hw->phy.ops.reset(hw); 179 | if (ret_val) { 180 | hw_dbg("Error resetting the PHY\n"); 181 | goto out; 182 | } 183 | 184 | ret_val = igc_get_phy_id(hw); 185 | if (ret_val) 186 | return ret_val; 187 | 188 | igc_check_for_copper_link(hw); 189 | 190 | phy->type = igc_phy_i225; 191 | 192 | out: 193 | return ret_val; 194 | } 195 | 196 | static s32 igc_get_invariants_base(struct igc_hw *hw) 197 | { 198 | struct igc_mac_info *mac = &hw->mac; 199 | s32 ret_val = 0; 200 | 201 | switch (hw->device_id) { 202 | case IGC_DEV_ID_I225_LM: 203 | case IGC_DEV_ID_I225_V: 204 | case IGC_DEV_ID_I225_I: 205 | case IGC_DEV_ID_I220_V: 206 | case IGC_DEV_ID_I225_K: 207 | case IGC_DEV_ID_I225_K2: 208 | case IGC_DEV_ID_I226_K: 209 | case IGC_DEV_ID_I225_LMVP: 210 | case IGC_DEV_ID_I226_LMVP: 211 | case IGC_DEV_ID_I225_IT: 212 | case IGC_DEV_ID_I226_LM: 213 | case IGC_DEV_ID_I226_V: 214 | case IGC_DEV_ID_I226_IT: 215 | case IGC_DEV_ID_I221_V: 216 | case IGC_DEV_ID_I226_BLANK_NVM: 217 | case IGC_DEV_ID_I225_BLANK_NVM: 218 | mac->type = igc_i225; 219 | break; 220 | default: 221 | return -IGC_ERR_MAC_INIT; 222 | } 223 | 224 | hw->phy.media_type = igc_media_type_copper; 225 | 226 | /* mac initialization and operations */ 227 | ret_val = igc_init_mac_params_base(hw); 228 | if (ret_val) 229 | goto out; 230 | 231 | /* NVM initialization */ 232 | ret_val = igc_init_nvm_params_base(hw); 233 | switch (hw->mac.type) { 234 | case igc_i225: 235 | ret_val = igc_init_nvm_params_i225(hw); 236 | break; 237 | default: 238 | break; 239 | } 240 | 241 | /* setup PHY parameters */ 242 | ret_val = igc_init_phy_params_base(hw); 243 | if (ret_val) 244 | goto out; 245 | 246 | out: 247 | return ret_val; 248 | } 249 | 250 | /** 251 | * igc_acquire_phy_base - Acquire rights to access PHY 252 | * @hw: pointer to the HW structure 253 | * 254 | * Acquire access rights to the correct PHY. This is a 255 | * function pointer entry point called by the api module. 256 | */ 257 | static s32 igc_acquire_phy_base(struct igc_hw *hw) 258 | { 259 | u16 mask = IGC_SWFW_PHY0_SM; 260 | 261 | return hw->mac.ops.acquire_swfw_sync(hw, mask); 262 | } 263 | 264 | /** 265 | * igc_release_phy_base - Release rights to access PHY 266 | * @hw: pointer to the HW structure 267 | * 268 | * A wrapper to release access rights to the correct PHY. This is a 269 | * function pointer entry point called by the api module. 270 | */ 271 | static void igc_release_phy_base(struct igc_hw *hw) 272 | { 273 | u16 mask = IGC_SWFW_PHY0_SM; 274 | 275 | hw->mac.ops.release_swfw_sync(hw, mask); 276 | } 277 | 278 | /** 279 | * igc_init_hw_base - Initialize hardware 280 | * @hw: pointer to the HW structure 281 | * 282 | * This inits the hardware readying it for operation. 283 | */ 284 | static s32 igc_init_hw_base(struct igc_hw *hw) 285 | { 286 | struct igc_mac_info *mac = &hw->mac; 287 | u16 i, rar_count = mac->rar_entry_count; 288 | s32 ret_val = 0; 289 | 290 | /* Setup the receive address */ 291 | igc_init_rx_addrs(hw, rar_count); 292 | 293 | /* Zero out the Multicast HASH table */ 294 | hw_dbg("Zeroing the MTA\n"); 295 | for (i = 0; i < mac->mta_reg_count; i++) 296 | array_wr32(IGC_MTA, i, 0); 297 | 298 | /* Zero out the Unicast HASH table */ 299 | hw_dbg("Zeroing the UTA\n"); 300 | for (i = 0; i < mac->uta_reg_count; i++) 301 | array_wr32(IGC_UTA, i, 0); 302 | 303 | /* Setup link and flow control */ 304 | ret_val = igc_setup_link(hw); 305 | 306 | /* Clear all of the statistics registers (clear on read). It is 307 | * important that we do this after we have tried to establish link 308 | * because the symbol error count will increment wildly if there 309 | * is no link. 310 | */ 311 | igc_clear_hw_cntrs_base(hw); 312 | 313 | return ret_val; 314 | } 315 | 316 | /** 317 | * igc_power_down_phy_copper_base - Remove link during PHY power down 318 | * @hw: pointer to the HW structure 319 | * 320 | * In the case of a PHY power down to save power, or to turn off link during a 321 | * driver unload, or wake on lan is not enabled, remove the link. 322 | */ 323 | void igc_power_down_phy_copper_base(struct igc_hw *hw) 324 | { 325 | /* If the management interface is not enabled, then power down */ 326 | if (!(igc_enable_mng_pass_thru(hw) || igc_check_reset_block(hw))) 327 | igc_power_down_phy_copper(hw); 328 | } 329 | 330 | /** 331 | * igc_rx_fifo_flush_base - Clean rx fifo after Rx enable 332 | * @hw: pointer to the HW structure 333 | * 334 | * After Rx enable, if manageability is enabled then there is likely some 335 | * bad data at the start of the fifo and possibly in the DMA fifo. This 336 | * function clears the fifos and flushes any packets that came in as rx was 337 | * being enabled. 338 | */ 339 | void igc_rx_fifo_flush_base(struct igc_hw *hw) 340 | { 341 | u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled; 342 | int i, ms_wait; 343 | 344 | /* disable IPv6 options as per hardware errata */ 345 | rfctl = rd32(IGC_RFCTL); 346 | rfctl |= IGC_RFCTL_IPV6_EX_DIS; 347 | wr32(IGC_RFCTL, rfctl); 348 | 349 | if (!(rd32(IGC_MANC) & IGC_MANC_RCV_TCO_EN)) 350 | return; 351 | 352 | /* Disable all Rx queues */ 353 | for (i = 0; i < 4; i++) { 354 | rxdctl[i] = rd32(IGC_RXDCTL(i)); 355 | wr32(IGC_RXDCTL(i), 356 | rxdctl[i] & ~IGC_RXDCTL_QUEUE_ENABLE); 357 | } 358 | /* Poll all queues to verify they have shut down */ 359 | for (ms_wait = 0; ms_wait < 10; ms_wait++) { 360 | usleep_range(1000, 2000); 361 | rx_enabled = 0; 362 | for (i = 0; i < 4; i++) 363 | rx_enabled |= rd32(IGC_RXDCTL(i)); 364 | if (!(rx_enabled & IGC_RXDCTL_QUEUE_ENABLE)) 365 | break; 366 | } 367 | 368 | if (ms_wait == 10) 369 | hw_dbg("Queue disable timed out after 10ms\n"); 370 | 371 | /* Clear RLPML, RCTL.SBP, RFCTL.LEF, and set RCTL.LPE so that all 372 | * incoming packets are rejected. Set enable and wait 2ms so that 373 | * any packet that was coming in as RCTL.EN was set is flushed 374 | */ 375 | wr32(IGC_RFCTL, rfctl & ~IGC_RFCTL_LEF); 376 | 377 | rlpml = rd32(IGC_RLPML); 378 | wr32(IGC_RLPML, 0); 379 | 380 | rctl = rd32(IGC_RCTL); 381 | temp_rctl = rctl & ~(IGC_RCTL_EN | IGC_RCTL_SBP); 382 | temp_rctl |= IGC_RCTL_LPE; 383 | 384 | wr32(IGC_RCTL, temp_rctl); 385 | wr32(IGC_RCTL, temp_rctl | IGC_RCTL_EN); 386 | wrfl(); 387 | usleep_range(2000, 3000); 388 | 389 | /* Enable Rx queues that were previously enabled and restore our 390 | * previous state 391 | */ 392 | for (i = 0; i < 4; i++) 393 | wr32(IGC_RXDCTL(i), rxdctl[i]); 394 | wr32(IGC_RCTL, rctl); 395 | wrfl(); 396 | 397 | wr32(IGC_RLPML, rlpml); 398 | wr32(IGC_RFCTL, rfctl); 399 | 400 | /* Flush receive errors generated by workaround */ 401 | rd32(IGC_ROC); 402 | rd32(IGC_RNBC); 403 | rd32(IGC_MPC); 404 | } 405 | 406 | static struct igc_mac_operations igc_mac_ops_base = { 407 | .init_hw = igc_init_hw_base, 408 | .check_for_link = igc_check_for_copper_link, 409 | .rar_set = igc_rar_set, 410 | .read_mac_addr = igc_read_mac_addr, 411 | .get_speed_and_duplex = igc_get_speed_and_duplex_copper, 412 | }; 413 | 414 | static const struct igc_phy_operations igc_phy_ops_base = { 415 | .acquire = igc_acquire_phy_base, 416 | .release = igc_release_phy_base, 417 | .reset = igc_phy_hw_reset, 418 | .read_reg = igc_read_phy_reg_gpy, 419 | .write_reg = igc_write_phy_reg_gpy, 420 | }; 421 | 422 | const struct igc_info igc_base_info = { 423 | .get_invariants = igc_get_invariants_base, 424 | .mac_ops = &igc_mac_ops_base, 425 | .phy_ops = &igc_phy_ops_base, 426 | }; 427 | -------------------------------------------------------------------------------- /igc_base.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | /* Copyright (c) 2018 Intel Corporation */ 3 | 4 | #ifndef _IGC_BASE_H_ 5 | #define _IGC_BASE_H_ 6 | 7 | /* forward declaration */ 8 | void igc_rx_fifo_flush_base(struct igc_hw *hw); 9 | void igc_power_down_phy_copper_base(struct igc_hw *hw); 10 | 11 | /* Transmit Descriptor - Advanced */ 12 | union igc_adv_tx_desc { 13 | struct { 14 | __le64 buffer_addr; /* Address of descriptor's data buf */ 15 | __le32 cmd_type_len; 16 | __le32 olinfo_status; 17 | } read; 18 | struct { 19 | __le64 rsvd; /* Reserved */ 20 | __le32 nxtseq_seed; 21 | __le32 status; 22 | } wb; 23 | }; 24 | 25 | /* Context descriptors */ 26 | struct igc_adv_tx_context_desc { 27 | __le32 vlan_macip_lens; 28 | __le32 launch_time; 29 | __le32 type_tucmd_mlhl; 30 | __le32 mss_l4len_idx; 31 | }; 32 | 33 | /* Adv Transmit Descriptor Config Masks */ 34 | #define IGC_ADVTXD_MAC_TSTAMP 0x00080000 /* IEEE1588 Timestamp packet */ 35 | #define IGC_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */ 36 | #define IGC_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */ 37 | #define IGC_ADVTXD_DCMD_EOP 0x01000000 /* End of Packet */ 38 | #define IGC_ADVTXD_DCMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */ 39 | #define IGC_ADVTXD_DCMD_RS 0x08000000 /* Report Status */ 40 | #define IGC_ADVTXD_DCMD_DEXT 0x20000000 /* Descriptor extension (1=Adv) */ 41 | #define IGC_ADVTXD_DCMD_VLE 0x40000000 /* VLAN pkt enable */ 42 | #define IGC_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */ 43 | #define IGC_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */ 44 | 45 | #define IGC_RAR_ENTRIES 16 46 | 47 | /* Receive Descriptor - Advanced */ 48 | union igc_adv_rx_desc { 49 | struct { 50 | __le64 pkt_addr; /* Packet buffer address */ 51 | __le64 hdr_addr; /* Header buffer address */ 52 | } read; 53 | struct { 54 | struct { 55 | union { 56 | __le32 data; 57 | struct { 58 | __le16 pkt_info; /*RSS type, Pkt type*/ 59 | /* Split Header, header buffer len */ 60 | __le16 hdr_info; 61 | } hs_rss; 62 | } lo_dword; 63 | union { 64 | __le32 rss; /* RSS Hash */ 65 | struct { 66 | __le16 ip_id; /* IP id */ 67 | __le16 csum; /* Packet Checksum */ 68 | } csum_ip; 69 | } hi_dword; 70 | } lower; 71 | struct { 72 | __le32 status_error; /* ext status/error */ 73 | __le16 length; /* Packet length */ 74 | __le16 vlan; /* VLAN tag */ 75 | } upper; 76 | } wb; /* writeback */ 77 | }; 78 | 79 | /* Additional Transmit Descriptor Control definitions */ 80 | #define IGC_TXDCTL_QUEUE_ENABLE 0x02000000 /* Ena specific Tx Queue */ 81 | 82 | /* Additional Receive Descriptor Control definitions */ 83 | #define IGC_RXDCTL_QUEUE_ENABLE 0x02000000 /* Ena specific Rx Queue */ 84 | 85 | /* SRRCTL bit definitions */ 86 | #define IGC_SRRCTL_BSIZEPKT_SHIFT 10 /* Shift _right_ */ 87 | #define IGC_SRRCTL_BSIZEHDRSIZE_SHIFT 2 /* Shift _left_ */ 88 | #define IGC_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000 89 | 90 | #endif /* _IGC_BASE_H */ 91 | -------------------------------------------------------------------------------- /igc_defines.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | /* Copyright (c) 2018 Intel Corporation */ 3 | 4 | #ifndef _IGC_DEFINES_H_ 5 | #define _IGC_DEFINES_H_ 6 | 7 | /* Number of Transmit and Receive Descriptors must be a multiple of 8 */ 8 | #define REQ_TX_DESCRIPTOR_MULTIPLE 8 9 | #define REQ_RX_DESCRIPTOR_MULTIPLE 8 10 | 11 | #define IGC_CTRL_EXT_DRV_LOAD 0x10000000 /* Drv loaded bit for FW */ 12 | 13 | /* Definitions for power management and wakeup registers */ 14 | /* Wake Up Control */ 15 | #define IGC_WUC_PME_EN 0x00000002 /* PME Enable */ 16 | 17 | /* Wake Up Filter Control */ 18 | #define IGC_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */ 19 | #define IGC_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */ 20 | #define IGC_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */ 21 | #define IGC_WUFC_MC 0x00000008 /* Directed Multicast Wakeup Enable */ 22 | #define IGC_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */ 23 | 24 | #define IGC_CTRL_ADVD3WUC 0x00100000 /* D3 WUC */ 25 | 26 | /* Wake Up Status */ 27 | #define IGC_WUS_EX 0x00000004 /* Directed Exact */ 28 | #define IGC_WUS_ARPD 0x00000020 /* Directed ARP Request */ 29 | #define IGC_WUS_IPV4 0x00000040 /* Directed IPv4 */ 30 | #define IGC_WUS_IPV6 0x00000080 /* Directed IPv6 */ 31 | #define IGC_WUS_NSD 0x00000400 /* Directed IPv6 Neighbor Solicitation */ 32 | 33 | /* Packet types that are enabled for wake packet delivery */ 34 | #define WAKE_PKT_WUS ( \ 35 | IGC_WUS_EX | \ 36 | IGC_WUS_ARPD | \ 37 | IGC_WUS_IPV4 | \ 38 | IGC_WUS_IPV6 | \ 39 | IGC_WUS_NSD) 40 | 41 | /* Wake Up Packet Length */ 42 | #define IGC_WUPL_MASK 0x00000FFF 43 | 44 | /* Wake Up Packet Memory stores the first 128 bytes of the wake up packet */ 45 | #define IGC_WUPM_BYTES 128 46 | 47 | /* Loop limit on how long we wait for auto-negotiation to complete */ 48 | #define COPPER_LINK_UP_LIMIT 10 49 | #define PHY_AUTO_NEG_LIMIT 45 50 | 51 | /* Number of 100 microseconds we wait for PCI Express master disable */ 52 | #define MASTER_DISABLE_TIMEOUT 800 53 | /*Blocks new Master requests */ 54 | #define IGC_CTRL_GIO_MASTER_DISABLE 0x00000004 55 | /* Status of Master requests. */ 56 | #define IGC_STATUS_GIO_MASTER_ENABLE 0x00080000 57 | 58 | /* Receive Address 59 | * Number of high/low register pairs in the RAR. The RAR (Receive Address 60 | * Registers) holds the directed and multicast addresses that we monitor. 61 | * Technically, we have 16 spots. However, we reserve one of these spots 62 | * (RAR[15]) for our directed address used by controllers with 63 | * manageability enabled, allowing us room for 15 multicast addresses. 64 | */ 65 | #define IGC_RAH_RAH_MASK 0x0000FFFF 66 | #define IGC_RAH_ASEL_MASK 0x00030000 67 | #define IGC_RAH_ASEL_SRC_ADDR BIT(16) 68 | #define IGC_RAH_QSEL_MASK 0x000C0000 69 | #define IGC_RAH_QSEL_SHIFT 18 70 | #define IGC_RAH_QSEL_ENABLE BIT(28) 71 | #define IGC_RAH_AV 0x80000000 /* Receive descriptor valid */ 72 | 73 | #define IGC_RAL_MAC_ADDR_LEN 4 74 | #define IGC_RAH_MAC_ADDR_LEN 2 75 | 76 | /* Error Codes */ 77 | #define IGC_SUCCESS 0 78 | #define IGC_ERR_NVM 1 79 | #define IGC_ERR_PHY 2 80 | #define IGC_ERR_CONFIG 3 81 | #define IGC_ERR_PARAM 4 82 | #define IGC_ERR_MAC_INIT 5 83 | #define IGC_ERR_RESET 9 84 | #define IGC_ERR_MASTER_REQUESTS_PENDING 10 85 | #define IGC_ERR_BLK_PHY_RESET 12 86 | #define IGC_ERR_SWFW_SYNC 13 87 | 88 | /* Device Control */ 89 | #define IGC_CTRL_DEV_RST 0x20000000 /* Device reset */ 90 | 91 | #define IGC_CTRL_PHY_RST 0x80000000 /* PHY Reset */ 92 | #define IGC_CTRL_SLU 0x00000040 /* Set link up (Force Link) */ 93 | #define IGC_CTRL_FRCSPD 0x00000800 /* Force Speed */ 94 | #define IGC_CTRL_FRCDPX 0x00001000 /* Force Duplex */ 95 | 96 | #define IGC_CTRL_RFCE 0x08000000 /* Receive Flow Control enable */ 97 | #define IGC_CTRL_TFCE 0x10000000 /* Transmit flow control enable */ 98 | 99 | /* As per the EAS the maximum supported size is 9.5KB (9728 bytes) */ 100 | #define MAX_JUMBO_FRAME_SIZE 0x2600 101 | 102 | /* PBA constants */ 103 | #define IGC_PBA_34K 0x0022 104 | 105 | /* SW Semaphore Register */ 106 | #define IGC_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */ 107 | #define IGC_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */ 108 | 109 | /* SWFW_SYNC Definitions */ 110 | #define IGC_SWFW_EEP_SM 0x1 111 | #define IGC_SWFW_PHY0_SM 0x2 112 | 113 | /* Autoneg Advertisement Register */ 114 | #define NWAY_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */ 115 | #define NWAY_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */ 116 | #define NWAY_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */ 117 | #define NWAY_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */ 118 | #define NWAY_AR_PAUSE 0x0400 /* Pause operation desired */ 119 | #define NWAY_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */ 120 | 121 | /* Link Partner Ability Register (Base Page) */ 122 | #define NWAY_LPAR_PAUSE 0x0400 /* LP Pause operation desired */ 123 | #define NWAY_LPAR_ASM_DIR 0x0800 /* LP Asymmetric Pause Direction bit */ 124 | 125 | /* 1000BASE-T Control Register */ 126 | #define CR_1000T_ASYM_PAUSE 0x0080 /* Advertise asymmetric pause bit */ 127 | #define CR_1000T_HD_CAPS 0x0100 /* Advertise 1000T HD capability */ 128 | #define CR_1000T_FD_CAPS 0x0200 /* Advertise 1000T FD capability */ 129 | 130 | /* 1000BASE-T Status Register */ 131 | #define SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */ 132 | 133 | /* PHY GPY 211 registers */ 134 | #define STANDARD_AN_REG_MASK 0x0007 /* MMD */ 135 | #define ANEG_MULTIGBT_AN_CTRL 0x0020 /* MULTI GBT AN Control Register */ 136 | #define MMD_DEVADDR_SHIFT 16 /* Shift MMD to higher bits */ 137 | #define CR_2500T_FD_CAPS 0x0080 /* Advertise 2500T FD capability */ 138 | 139 | /* NVM Control */ 140 | /* Number of milliseconds for NVM auto read done after MAC reset. */ 141 | #define AUTO_READ_DONE_TIMEOUT 10 142 | #define IGC_EECD_AUTO_RD 0x00000200 /* NVM Auto Read done */ 143 | #define IGC_EECD_REQ 0x00000040 /* NVM Access Request */ 144 | #define IGC_EECD_GNT 0x00000080 /* NVM Access Grant */ 145 | /* NVM Addressing bits based on type 0=small, 1=large */ 146 | #define IGC_EECD_ADDR_BITS 0x00000400 147 | #define IGC_NVM_GRANT_ATTEMPTS 1000 /* NVM # attempts to gain grant */ 148 | #define IGC_EECD_SIZE_EX_MASK 0x00007800 /* NVM Size */ 149 | #define IGC_EECD_SIZE_EX_SHIFT 11 150 | #define IGC_EECD_FLUPD_I225 0x00800000 /* Update FLASH */ 151 | #define IGC_EECD_FLUDONE_I225 0x04000000 /* Update FLASH done*/ 152 | #define IGC_EECD_FLASH_DETECTED_I225 0x00080000 /* FLASH detected */ 153 | #define IGC_FLUDONE_ATTEMPTS 20000 154 | #define IGC_EERD_EEWR_MAX_COUNT 512 /* buffered EEPROM words rw */ 155 | 156 | /* Offset to data in NVM read/write registers */ 157 | #define IGC_NVM_RW_REG_DATA 16 158 | #define IGC_NVM_RW_REG_DONE 2 /* Offset to READ/WRITE done bit */ 159 | #define IGC_NVM_RW_REG_START 1 /* Start operation */ 160 | #define IGC_NVM_RW_ADDR_SHIFT 2 /* Shift to the address bits */ 161 | #define IGC_NVM_POLL_READ 0 /* Flag for polling for read complete */ 162 | #define IGC_NVM_DEV_STARTER 5 /* Dev_starter Version */ 163 | 164 | /* NVM Word Offsets */ 165 | #define NVM_CHECKSUM_REG 0x003F 166 | 167 | /* For checksumming, the sum of all words in the NVM should equal 0xBABA. */ 168 | #define NVM_SUM 0xBABA 169 | #define NVM_WORD_SIZE_BASE_SHIFT 6 170 | 171 | /* Collision related configuration parameters */ 172 | #define IGC_COLLISION_THRESHOLD 15 173 | #define IGC_CT_SHIFT 4 174 | #define IGC_COLLISION_DISTANCE 63 175 | #define IGC_COLD_SHIFT 12 176 | 177 | /* Device Status */ 178 | #define IGC_STATUS_FD 0x00000001 /* Full duplex.0=half,1=full */ 179 | #define IGC_STATUS_LU 0x00000002 /* Link up.0=no,1=link */ 180 | #define IGC_STATUS_FUNC_MASK 0x0000000C /* PCI Function Mask */ 181 | #define IGC_STATUS_FUNC_SHIFT 2 182 | #define IGC_STATUS_TXOFF 0x00000010 /* transmission paused */ 183 | #define IGC_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */ 184 | #define IGC_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */ 185 | #define IGC_STATUS_SPEED_2500 0x00400000 /* Speed 2.5Gb/s */ 186 | 187 | #define SPEED_10 10 188 | #define SPEED_100 100 189 | #define SPEED_1000 1000 190 | #define SPEED_2500 2500 191 | #define HALF_DUPLEX 1 192 | #define FULL_DUPLEX 2 193 | 194 | /* 1Gbps and 2.5Gbps half duplex is not supported, nor spec-compliant. */ 195 | #define ADVERTISE_10_HALF 0x0001 196 | #define ADVERTISE_10_FULL 0x0002 197 | #define ADVERTISE_100_HALF 0x0004 198 | #define ADVERTISE_100_FULL 0x0008 199 | #define ADVERTISE_1000_HALF 0x0010 /* Not used, just FYI */ 200 | #define ADVERTISE_1000_FULL 0x0020 201 | #define ADVERTISE_2500_HALF 0x0040 /* Not used, just FYI */ 202 | #define ADVERTISE_2500_FULL 0x0080 203 | 204 | #define IGC_ALL_SPEED_DUPLEX_2500 ( \ 205 | ADVERTISE_10_HALF | ADVERTISE_10_FULL | ADVERTISE_100_HALF | \ 206 | ADVERTISE_100_FULL | ADVERTISE_1000_FULL | ADVERTISE_2500_FULL) 207 | 208 | #define AUTONEG_ADVERTISE_SPEED_DEFAULT_2500 IGC_ALL_SPEED_DUPLEX_2500 209 | 210 | /* Interrupt Cause Read */ 211 | #define IGC_ICR_TXDW BIT(0) /* Transmit desc written back */ 212 | #define IGC_ICR_TXQE BIT(1) /* Transmit Queue empty */ 213 | #define IGC_ICR_LSC BIT(2) /* Link Status Change */ 214 | #define IGC_ICR_RXSEQ BIT(3) /* Rx sequence error */ 215 | #define IGC_ICR_RXDMT0 BIT(4) /* Rx desc min. threshold (0) */ 216 | #define IGC_ICR_RXO BIT(6) /* Rx overrun */ 217 | #define IGC_ICR_RXT0 BIT(7) /* Rx timer intr (ring 0) */ 218 | #define IGC_ICR_TS BIT(19) /* Time Sync Interrupt */ 219 | #define IGC_ICR_DRSTA BIT(30) /* Device Reset Asserted */ 220 | 221 | /* If this bit asserted, the driver should claim the interrupt */ 222 | #define IGC_ICR_INT_ASSERTED BIT(31) 223 | 224 | #define IGC_ICS_RXT0 IGC_ICR_RXT0 /* Rx timer intr */ 225 | 226 | #define IMS_ENABLE_MASK ( \ 227 | IGC_IMS_RXT0 | \ 228 | IGC_IMS_TXDW | \ 229 | IGC_IMS_RXDMT0 | \ 230 | IGC_IMS_RXSEQ | \ 231 | IGC_IMS_LSC) 232 | 233 | /* Interrupt Mask Set */ 234 | #define IGC_IMS_TXDW IGC_ICR_TXDW /* Tx desc written back */ 235 | #define IGC_IMS_RXSEQ IGC_ICR_RXSEQ /* Rx sequence error */ 236 | #define IGC_IMS_LSC IGC_ICR_LSC /* Link Status Change */ 237 | #define IGC_IMS_DOUTSYNC IGC_ICR_DOUTSYNC /* NIC DMA out of sync */ 238 | #define IGC_IMS_DRSTA IGC_ICR_DRSTA /* Device Reset Asserted */ 239 | #define IGC_IMS_RXT0 IGC_ICR_RXT0 /* Rx timer intr */ 240 | #define IGC_IMS_RXDMT0 IGC_ICR_RXDMT0 /* Rx desc min. threshold */ 241 | #define IGC_IMS_TS IGC_ICR_TS /* Time Sync Interrupt */ 242 | 243 | #define IGC_QVECTOR_MASK 0x7FFC /* Q-vector mask */ 244 | #define IGC_ITR_VAL_MASK 0x04 /* ITR value mask */ 245 | 246 | /* Interrupt Cause Set */ 247 | #define IGC_ICS_LSC IGC_ICR_LSC /* Link Status Change */ 248 | #define IGC_ICS_RXDMT0 IGC_ICR_RXDMT0 /* rx desc min. threshold */ 249 | 250 | #define IGC_ICR_DOUTSYNC 0x10000000 /* NIC DMA out of sync */ 251 | #define IGC_EITR_CNT_IGNR 0x80000000 /* Don't reset counters on write */ 252 | #define IGC_IVAR_VALID 0x80 253 | #define IGC_GPIE_NSICR 0x00000001 254 | #define IGC_GPIE_MSIX_MODE 0x00000010 255 | #define IGC_GPIE_EIAME 0x40000000 256 | #define IGC_GPIE_PBA 0x80000000 257 | 258 | /* Receive Descriptor bit definitions */ 259 | #define IGC_RXD_STAT_DD 0x01 /* Descriptor Done */ 260 | 261 | /* Transmit Descriptor bit definitions */ 262 | #define IGC_TXD_DTYP_D 0x00100000 /* Data Descriptor */ 263 | #define IGC_TXD_DTYP_C 0x00000000 /* Context Descriptor */ 264 | #define IGC_TXD_POPTS_IXSM 0x01 /* Insert IP checksum */ 265 | #define IGC_TXD_POPTS_TXSM 0x02 /* Insert TCP/UDP checksum */ 266 | #define IGC_TXD_CMD_EOP 0x01000000 /* End of Packet */ 267 | #define IGC_TXD_CMD_IC 0x04000000 /* Insert Checksum */ 268 | #define IGC_TXD_CMD_DEXT 0x20000000 /* Desc extension (0 = legacy) */ 269 | #define IGC_TXD_CMD_VLE 0x40000000 /* Add VLAN tag */ 270 | #define IGC_TXD_STAT_DD 0x00000001 /* Descriptor Done */ 271 | #define IGC_TXD_CMD_TCP 0x01000000 /* TCP packet */ 272 | #define IGC_TXD_CMD_IP 0x02000000 /* IP packet */ 273 | #define IGC_TXD_CMD_TSE 0x04000000 /* TCP Seg enable */ 274 | #define IGC_TXD_EXTCMD_TSTAMP 0x00000010 /* IEEE1588 Timestamp packet */ 275 | 276 | /* IPSec Encrypt Enable */ 277 | #define IGC_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */ 278 | #define IGC_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */ 279 | 280 | /* Transmit Control */ 281 | #define IGC_TCTL_EN 0x00000002 /* enable Tx */ 282 | #define IGC_TCTL_PSP 0x00000008 /* pad short packets */ 283 | #define IGC_TCTL_CT 0x00000ff0 /* collision threshold */ 284 | #define IGC_TCTL_COLD 0x003ff000 /* collision distance */ 285 | #define IGC_TCTL_RTLC 0x01000000 /* Re-transmit on late collision */ 286 | 287 | /* Flow Control Constants */ 288 | #define FLOW_CONTROL_ADDRESS_LOW 0x00C28001 289 | #define FLOW_CONTROL_ADDRESS_HIGH 0x00000100 290 | #define FLOW_CONTROL_TYPE 0x8808 291 | /* Enable XON frame transmission */ 292 | #define IGC_FCRTL_XONE 0x80000000 293 | 294 | /* Management Control */ 295 | #define IGC_MANC_RCV_TCO_EN 0x00020000 /* Receive TCO Packets Enabled */ 296 | #define IGC_MANC_BLK_PHY_RST_ON_IDE 0x00040000 /* Block phy resets */ 297 | 298 | /* Receive Control */ 299 | #define IGC_RCTL_RST 0x00000001 /* Software reset */ 300 | #define IGC_RCTL_EN 0x00000002 /* enable */ 301 | #define IGC_RCTL_SBP 0x00000004 /* store bad packet */ 302 | #define IGC_RCTL_UPE 0x00000008 /* unicast promisc enable */ 303 | #define IGC_RCTL_MPE 0x00000010 /* multicast promisc enable */ 304 | #define IGC_RCTL_LPE 0x00000020 /* long packet enable */ 305 | #define IGC_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */ 306 | #define IGC_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */ 307 | 308 | #define IGC_RCTL_RDMTS_HALF 0x00000000 /* Rx desc min thresh size */ 309 | #define IGC_RCTL_BAM 0x00008000 /* broadcast enable */ 310 | 311 | /* Split Replication Receive Control */ 312 | #define IGC_SRRCTL_TIMESTAMP 0x40000000 313 | #define IGC_SRRCTL_TIMER1SEL(timer) (((timer) & 0x3) << 14) 314 | #define IGC_SRRCTL_TIMER0SEL(timer) (((timer) & 0x3) << 17) 315 | 316 | /* Receive Descriptor bit definitions */ 317 | #define IGC_RXD_STAT_EOP 0x02 /* End of Packet */ 318 | #define IGC_RXD_STAT_IXSM 0x04 /* Ignore checksum */ 319 | #define IGC_RXD_STAT_UDPCS 0x10 /* UDP xsum calculated */ 320 | #define IGC_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */ 321 | 322 | /* Advanced Receive Descriptor bit definitions */ 323 | #define IGC_RXDADV_STAT_TSIP 0x08000 /* timestamp in packet */ 324 | 325 | #define IGC_RXDEXT_STATERR_L4E 0x20000000 326 | #define IGC_RXDEXT_STATERR_IPE 0x40000000 327 | #define IGC_RXDEXT_STATERR_RXE 0x80000000 328 | 329 | #define IGC_MRQC_RSS_FIELD_IPV4_TCP 0x00010000 330 | #define IGC_MRQC_RSS_FIELD_IPV4 0x00020000 331 | #define IGC_MRQC_RSS_FIELD_IPV6_TCP_EX 0x00040000 332 | #define IGC_MRQC_RSS_FIELD_IPV6 0x00100000 333 | #define IGC_MRQC_RSS_FIELD_IPV6_TCP 0x00200000 334 | 335 | /* Header split receive */ 336 | #define IGC_RFCTL_IPV6_EX_DIS 0x00010000 337 | #define IGC_RFCTL_LEF 0x00040000 338 | 339 | #define IGC_RCTL_SZ_256 0x00030000 /* Rx buffer size 256 */ 340 | 341 | #define IGC_RCTL_MO_SHIFT 12 /* multicast offset shift */ 342 | #define IGC_RCTL_CFIEN 0x00080000 /* canonical form enable */ 343 | #define IGC_RCTL_DPF 0x00400000 /* discard pause frames */ 344 | #define IGC_RCTL_PMCF 0x00800000 /* pass MAC control frames */ 345 | #define IGC_RCTL_SECRC 0x04000000 /* Strip Ethernet CRC */ 346 | 347 | #define I225_RXPBSIZE_DEFAULT 0x000000A2 /* RXPBSIZE default */ 348 | #define I225_TXPBSIZE_DEFAULT 0x04000014 /* TXPBSIZE default */ 349 | #define IGC_RXPBS_CFG_TS_EN 0x80000000 /* Timestamp in Rx buffer */ 350 | 351 | #define IGC_TXPBSIZE_TSN 0x04145145 /* 5k bytes buffer for each queue */ 352 | 353 | #define IGC_DTXMXPKTSZ_TSN 0x19 /* 1600 bytes of max TX DMA packet size */ 354 | #define IGC_DTXMXPKTSZ_DEFAULT 0x98 /* 9728-byte Jumbo frames */ 355 | 356 | /* Time Sync Interrupt Causes */ 357 | #define IGC_TSICR_SYS_WRAP BIT(0) /* SYSTIM Wrap around. */ 358 | #define IGC_TSICR_TXTS BIT(1) /* Transmit Timestamp. */ 359 | #define IGC_TSICR_TT0 BIT(3) /* Target Time 0 Trigger. */ 360 | #define IGC_TSICR_TT1 BIT(4) /* Target Time 1 Trigger. */ 361 | #define IGC_TSICR_AUTT0 BIT(5) /* Auxiliary Timestamp 0 Taken. */ 362 | #define IGC_TSICR_AUTT1 BIT(6) /* Auxiliary Timestamp 1 Taken. */ 363 | 364 | #define IGC_TSICR_INTERRUPTS IGC_TSICR_TXTS 365 | 366 | #define IGC_FTQF_VF_BP 0x00008000 367 | #define IGC_FTQF_1588_TIME_STAMP 0x08000000 368 | #define IGC_FTQF_MASK 0xF0000000 369 | #define IGC_FTQF_MASK_PROTO_BP 0x10000000 370 | 371 | /* Time Sync Receive Control bit definitions */ 372 | #define IGC_TSYNCRXCTL_TYPE_MASK 0x0000000E /* Rx type mask */ 373 | #define IGC_TSYNCRXCTL_TYPE_L2_V2 0x00 374 | #define IGC_TSYNCRXCTL_TYPE_L4_V1 0x02 375 | #define IGC_TSYNCRXCTL_TYPE_L2_L4_V2 0x04 376 | #define IGC_TSYNCRXCTL_TYPE_ALL 0x08 377 | #define IGC_TSYNCRXCTL_TYPE_EVENT_V2 0x0A 378 | #define IGC_TSYNCRXCTL_ENABLED 0x00000010 /* enable Rx timestamping */ 379 | #define IGC_TSYNCRXCTL_SYSCFI 0x00000020 /* Sys clock frequency */ 380 | #define IGC_TSYNCRXCTL_RXSYNSIG 0x00000400 /* Sample RX tstamp in PHY sop */ 381 | 382 | /* Time Sync Receive Configuration */ 383 | #define IGC_TSYNCRXCFG_PTP_V1_CTRLT_MASK 0x000000FF 384 | #define IGC_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE 0x00 385 | #define IGC_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE 0x01 386 | 387 | /* Immediate Interrupt Receive */ 388 | #define IGC_IMIR_CLEAR_MASK 0xF001FFFF /* IMIR Reg Clear Mask */ 389 | #define IGC_IMIR_PORT_BYPASS 0x20000 /* IMIR Port Bypass Bit */ 390 | #define IGC_IMIR_PRIORITY_SHIFT 29 /* IMIR Priority Shift */ 391 | #define IGC_IMIREXT_CLEAR_MASK 0x7FFFF /* IMIREXT Reg Clear Mask */ 392 | 393 | /* Immediate Interrupt Receive Extended */ 394 | #define IGC_IMIREXT_CTRL_BP 0x00080000 /* Bypass check of ctrl bits */ 395 | #define IGC_IMIREXT_SIZE_BP 0x00001000 /* Packet size bypass */ 396 | 397 | /* Time Sync Transmit Control bit definitions */ 398 | #define IGC_TSYNCTXCTL_TXTT_0 0x00000001 /* Tx timestamp reg 0 valid */ 399 | #define IGC_TSYNCTXCTL_ENABLED 0x00000010 /* enable Tx timestamping */ 400 | #define IGC_TSYNCTXCTL_MAX_ALLOWED_DLY_MASK 0x0000F000 /* max delay */ 401 | #define IGC_TSYNCTXCTL_SYNC_COMP_ERR 0x20000000 /* sync err */ 402 | #define IGC_TSYNCTXCTL_SYNC_COMP 0x40000000 /* sync complete */ 403 | #define IGC_TSYNCTXCTL_START_SYNC 0x80000000 /* initiate sync */ 404 | #define IGC_TSYNCTXCTL_TXSYNSIG 0x00000020 /* Sample TX tstamp in PHY sop */ 405 | 406 | /* Transmit Scheduling */ 407 | #define IGC_TQAVCTRL_TRANSMIT_MODE_TSN 0x00000001 408 | #define IGC_TQAVCTRL_ENHANCED_QAV 0x00000008 409 | 410 | #define IGC_TXQCTL_QUEUE_MODE_LAUNCHT 0x00000001 411 | #define IGC_TXQCTL_STRICT_CYCLE 0x00000002 412 | #define IGC_TXQCTL_STRICT_END 0x00000004 413 | 414 | /* Receive Checksum Control */ 415 | #define IGC_RXCSUM_CRCOFL 0x00000800 /* CRC32 offload enable */ 416 | #define IGC_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */ 417 | 418 | /* PCIe PTM Control */ 419 | #define IGC_PTM_CTRL_START_NOW BIT(29) /* Start PTM Now */ 420 | #define IGC_PTM_CTRL_EN BIT(30) /* Enable PTM */ 421 | #define IGC_PTM_CTRL_TRIG BIT(31) /* PTM Cycle trigger */ 422 | #define IGC_PTM_CTRL_SHRT_CYC(usec) (((usec) & 0x2f) << 2) 423 | #define IGC_PTM_CTRL_PTM_TO(usec) (((usec) & 0xff) << 8) 424 | 425 | #define IGC_PTM_SHORT_CYC_DEFAULT 10 /* Default Short/interrupted cycle interval */ 426 | #define IGC_PTM_CYC_TIME_DEFAULT 5 /* Default PTM cycle time */ 427 | #define IGC_PTM_TIMEOUT_DEFAULT 255 /* Default timeout for PTM errors */ 428 | 429 | /* PCIe Digital Delay */ 430 | #define IGC_PCIE_DIG_DELAY_DEFAULT 0x01440000 431 | 432 | /* PCIe PHY Delay */ 433 | #define IGC_PCIE_PHY_DELAY_DEFAULT 0x40900000 434 | 435 | #define IGC_TIMADJ_ADJUST_METH 0x40000000 436 | 437 | /* PCIe PTM Status */ 438 | #define IGC_PTM_STAT_VALID BIT(0) /* PTM Status */ 439 | #define IGC_PTM_STAT_RET_ERR BIT(1) /* Root port timeout */ 440 | #define IGC_PTM_STAT_BAD_PTM_RES BIT(2) /* PTM Response msg instead of PTM Response Data */ 441 | #define IGC_PTM_STAT_T4M1_OVFL BIT(3) /* T4 minus T1 overflow */ 442 | #define IGC_PTM_STAT_ADJUST_1ST BIT(4) /* 1588 timer adjusted during 1st PTM cycle */ 443 | #define IGC_PTM_STAT_ADJUST_CYC BIT(5) /* 1588 timer adjusted during non-1st PTM cycle */ 444 | 445 | /* PCIe PTM Cycle Control */ 446 | #define IGC_PTM_CYCLE_CTRL_CYC_TIME(msec) ((msec) & 0x3ff) /* PTM Cycle Time (msec) */ 447 | #define IGC_PTM_CYCLE_CTRL_AUTO_CYC_EN BIT(31) /* PTM Cycle Control */ 448 | 449 | /* GPY211 - I225 defines */ 450 | #define GPY_MMD_MASK 0xFFFF0000 451 | #define GPY_MMD_SHIFT 16 452 | #define GPY_REG_MASK 0x0000FFFF 453 | 454 | #define IGC_MMDAC_FUNC_DATA 0x4000 /* Data, no post increment */ 455 | 456 | /* MAC definitions */ 457 | #define IGC_FACTPS_MNGCG 0x20000000 458 | #define IGC_FWSM_MODE_MASK 0xE 459 | #define IGC_FWSM_MODE_SHIFT 1 460 | 461 | /* Management Control */ 462 | #define IGC_MANC_SMBUS_EN 0x00000001 /* SMBus Enabled - RO */ 463 | #define IGC_MANC_ASF_EN 0x00000002 /* ASF Enabled - RO */ 464 | 465 | /* PHY */ 466 | #define PHY_REVISION_MASK 0xFFFFFFF0 467 | #define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */ 468 | #define IGC_GEN_POLL_TIMEOUT 1920 469 | 470 | /* PHY Control Register */ 471 | #define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */ 472 | #define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */ 473 | #define MII_CR_POWER_DOWN 0x0800 /* Power down */ 474 | #define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */ 475 | #define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */ 476 | #define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */ 477 | #define MII_CR_SPEED_1000 0x0040 478 | #define MII_CR_SPEED_100 0x2000 479 | #define MII_CR_SPEED_10 0x0000 480 | 481 | /* PHY Status Register */ 482 | #define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */ 483 | #define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */ 484 | #define IGC_PHY_RST_COMP 0x0100 /* Internal PHY reset completion */ 485 | 486 | /* PHY 1000 MII Register/Bit Definitions */ 487 | /* PHY Registers defined by IEEE */ 488 | #define PHY_CONTROL 0x00 /* Control Register */ 489 | #define PHY_STATUS 0x01 /* Status Register */ 490 | #define PHY_ID1 0x02 /* Phy Id Reg (word 1) */ 491 | #define PHY_ID2 0x03 /* Phy Id Reg (word 2) */ 492 | #define PHY_AUTONEG_ADV 0x04 /* Autoneg Advertisement */ 493 | #define PHY_LP_ABILITY 0x05 /* Link Partner Ability (Base Page) */ 494 | #define PHY_1000T_CTRL 0x09 /* 1000Base-T Control Reg */ 495 | #define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */ 496 | 497 | /* Bit definitions for valid PHY IDs. I = Integrated E = External */ 498 | #define I225_I_PHY_ID 0x67C9DC00 499 | 500 | /* MDI Control */ 501 | #define IGC_MDIC_DATA_MASK 0x0000FFFF 502 | #define IGC_MDIC_REG_MASK 0x001F0000 503 | #define IGC_MDIC_REG_SHIFT 16 504 | #define IGC_MDIC_PHY_MASK 0x03E00000 505 | #define IGC_MDIC_PHY_SHIFT 21 506 | #define IGC_MDIC_OP_WRITE 0x04000000 507 | #define IGC_MDIC_OP_READ 0x08000000 508 | #define IGC_MDIC_READY 0x10000000 509 | #define IGC_MDIC_INT_EN 0x20000000 510 | #define IGC_MDIC_ERROR 0x40000000 511 | 512 | #define IGC_N0_QUEUE -1 513 | 514 | #define IGC_MAX_MAC_HDR_LEN 127 515 | #define IGC_MAX_NETWORK_HDR_LEN 511 516 | 517 | #define IGC_VLANPQF_QSEL(_n, q_idx) ((q_idx) << ((_n) * 4)) 518 | #define IGC_VLANPQF_VALID(_n) (0x1 << (3 + (_n) * 4)) 519 | #define IGC_VLANPQF_QUEUE_MASK 0x03 520 | 521 | #define IGC_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */ 522 | #define IGC_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type:1=IPv4 */ 523 | #define IGC_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet Type of TCP */ 524 | #define IGC_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 packet TYPE of SCTP */ 525 | 526 | /* Maximum size of the MTA register table in all supported adapters */ 527 | #define MAX_MTA_REG 128 528 | 529 | /* EEE defines */ 530 | #define IGC_IPCNFG_EEE_2_5G_AN 0x00000010 /* IPCNFG EEE Ena 2.5G AN */ 531 | #define IGC_IPCNFG_EEE_1G_AN 0x00000008 /* IPCNFG EEE Ena 1G AN */ 532 | #define IGC_IPCNFG_EEE_100M_AN 0x00000004 /* IPCNFG EEE Ena 100M AN */ 533 | #define IGC_EEER_EEE_NEG 0x20000000 /* EEE capability nego */ 534 | #define IGC_EEER_TX_LPI_EN 0x00010000 /* EEER Tx LPI Enable */ 535 | #define IGC_EEER_RX_LPI_EN 0x00020000 /* EEER Rx LPI Enable */ 536 | #define IGC_EEER_LPI_FC 0x00040000 /* EEER Ena on Flow Cntrl */ 537 | #define IGC_EEE_SU_LPI_CLK_STP 0x00800000 /* EEE LPI Clock Stop */ 538 | 539 | /* LTR defines */ 540 | #define IGC_LTRC_EEEMS_EN 0x00000020 /* Enable EEE LTR max send */ 541 | #define IGC_RXPBS_SIZE_I225_MASK 0x0000003F /* Rx packet buffer size */ 542 | #define IGC_TW_SYSTEM_1000_MASK 0x000000FF 543 | /* Minimum time for 100BASE-T where no data will be transmit following move out 544 | * of EEE LPI Tx state 545 | */ 546 | #define IGC_TW_SYSTEM_100_MASK 0x0000FF00 547 | #define IGC_TW_SYSTEM_100_SHIFT 8 548 | #define IGC_DMACR_DMAC_EN 0x80000000 /* Enable DMA Coalescing */ 549 | #define IGC_DMACR_DMACTHR_MASK 0x00FF0000 550 | #define IGC_DMACR_DMACTHR_SHIFT 16 551 | /* Reg val to set scale to 1024 nsec */ 552 | #define IGC_LTRMINV_SCALE_1024 2 553 | /* Reg val to set scale to 32768 nsec */ 554 | #define IGC_LTRMINV_SCALE_32768 3 555 | /* Reg val to set scale to 1024 nsec */ 556 | #define IGC_LTRMAXV_SCALE_1024 2 557 | /* Reg val to set scale to 32768 nsec */ 558 | #define IGC_LTRMAXV_SCALE_32768 3 559 | #define IGC_LTRMINV_LTRV_MASK 0x000003FF /* LTR minimum value */ 560 | #define IGC_LTRMAXV_LTRV_MASK 0x000003FF /* LTR maximum value */ 561 | #define IGC_LTRMINV_LSNP_REQ 0x00008000 /* LTR Snoop Requirement */ 562 | #define IGC_LTRMINV_SCALE_SHIFT 10 563 | #define IGC_LTRMAXV_LSNP_REQ 0x00008000 /* LTR Snoop Requirement */ 564 | #define IGC_LTRMAXV_SCALE_SHIFT 10 565 | 566 | #endif /* _IGC_DEFINES_H_ */ 567 | -------------------------------------------------------------------------------- /igc_diag.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | /* Copyright (c) 2020 Intel Corporation */ 3 | 4 | #include "igc.h" 5 | #include "igc_diag.h" 6 | 7 | static struct igc_reg_test reg_test[] = { 8 | { IGC_FCAL, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, 9 | { IGC_FCAH, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF }, 10 | { IGC_FCT, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF }, 11 | { IGC_RDBAH(0), 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, 12 | { IGC_RDBAL(0), 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFF80 }, 13 | { IGC_RDLEN(0), 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF }, 14 | { IGC_RDT(0), 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, 15 | { IGC_FCRTH, 1, PATTERN_TEST, 0x0003FFF0, 0x0003FFF0 }, 16 | { IGC_FCTTV, 1, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, 17 | { IGC_TIPG, 1, PATTERN_TEST, 0x3FFFFFFF, 0x3FFFFFFF }, 18 | { IGC_TDBAH(0), 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, 19 | { IGC_TDBAL(0), 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFF80 }, 20 | { IGC_TDLEN(0), 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF }, 21 | { IGC_TDT(0), 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, 22 | { IGC_RCTL, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 }, 23 | { IGC_RCTL, 1, SET_READ_TEST, 0x04CFB2FE, 0x003FFFFB }, 24 | { IGC_RCTL, 1, SET_READ_TEST, 0x04CFB2FE, 0xFFFFFFFF }, 25 | { IGC_TCTL, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 }, 26 | { IGC_RA, 16, TABLE64_TEST_LO, 27 | 0xFFFFFFFF, 0xFFFFFFFF }, 28 | { IGC_RA, 16, TABLE64_TEST_HI, 29 | 0x900FFFFF, 0xFFFFFFFF }, 30 | { IGC_MTA, 128, TABLE32_TEST, 31 | 0xFFFFFFFF, 0xFFFFFFFF }, 32 | { 0, 0, 0, 0} 33 | }; 34 | 35 | static bool reg_pattern_test(struct igc_adapter *adapter, u64 *data, int reg, 36 | u32 mask, u32 write) 37 | { 38 | struct igc_hw *hw = &adapter->hw; 39 | u32 pat, val, before; 40 | static const u32 test_pattern[] = { 41 | 0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF 42 | }; 43 | 44 | for (pat = 0; pat < ARRAY_SIZE(test_pattern); pat++) { 45 | before = rd32(reg); 46 | wr32(reg, test_pattern[pat] & write); 47 | val = rd32(reg); 48 | if (val != (test_pattern[pat] & write & mask)) { 49 | netdev_err(adapter->netdev, 50 | "pattern test reg %04X failed: got 0x%08X expected 0x%08X", 51 | reg, val, test_pattern[pat] & write & mask); 52 | *data = reg; 53 | wr32(reg, before); 54 | return false; 55 | } 56 | wr32(reg, before); 57 | } 58 | return true; 59 | } 60 | 61 | static bool reg_set_and_check(struct igc_adapter *adapter, u64 *data, int reg, 62 | u32 mask, u32 write) 63 | { 64 | struct igc_hw *hw = &adapter->hw; 65 | u32 val, before; 66 | 67 | before = rd32(reg); 68 | wr32(reg, write & mask); 69 | val = rd32(reg); 70 | if ((write & mask) != (val & mask)) { 71 | netdev_err(adapter->netdev, 72 | "set/check reg %04X test failed: got 0x%08X expected 0x%08X", 73 | reg, (val & mask), (write & mask)); 74 | *data = reg; 75 | wr32(reg, before); 76 | return false; 77 | } 78 | wr32(reg, before); 79 | return true; 80 | } 81 | 82 | bool igc_reg_test(struct igc_adapter *adapter, u64 *data) 83 | { 84 | struct igc_reg_test *test = reg_test; 85 | struct igc_hw *hw = &adapter->hw; 86 | u32 value, before, after; 87 | u32 i, toggle, b = false; 88 | 89 | /* Because the status register is such a special case, 90 | * we handle it separately from the rest of the register 91 | * tests. Some bits are read-only, some toggle, and some 92 | * are writeable. 93 | */ 94 | toggle = 0x6800D3; 95 | before = rd32(IGC_STATUS); 96 | value = before & toggle; 97 | wr32(IGC_STATUS, toggle); 98 | after = rd32(IGC_STATUS) & toggle; 99 | if (value != after) { 100 | netdev_err(adapter->netdev, 101 | "failed STATUS register test got: 0x%08X expected: 0x%08X", 102 | after, value); 103 | *data = 1; 104 | return false; 105 | } 106 | /* restore previous status */ 107 | wr32(IGC_STATUS, before); 108 | 109 | /* Perform the remainder of the register test, looping through 110 | * the test table until we either fail or reach the null entry. 111 | */ 112 | while (test->reg) { 113 | for (i = 0; i < test->array_len; i++) { 114 | switch (test->test_type) { 115 | case PATTERN_TEST: 116 | b = reg_pattern_test(adapter, data, 117 | test->reg + (i * 0x40), 118 | test->mask, 119 | test->write); 120 | break; 121 | case SET_READ_TEST: 122 | b = reg_set_and_check(adapter, data, 123 | test->reg + (i * 0x40), 124 | test->mask, 125 | test->write); 126 | break; 127 | case TABLE64_TEST_LO: 128 | b = reg_pattern_test(adapter, data, 129 | test->reg + (i * 8), 130 | test->mask, 131 | test->write); 132 | break; 133 | case TABLE64_TEST_HI: 134 | b = reg_pattern_test(adapter, data, 135 | test->reg + 4 + (i * 8), 136 | test->mask, 137 | test->write); 138 | break; 139 | case TABLE32_TEST: 140 | b = reg_pattern_test(adapter, data, 141 | test->reg + (i * 4), 142 | test->mask, 143 | test->write); 144 | break; 145 | } 146 | if (!b) 147 | return false; 148 | } 149 | test++; 150 | } 151 | *data = 0; 152 | return true; 153 | } 154 | 155 | bool igc_eeprom_test(struct igc_adapter *adapter, u64 *data) 156 | { 157 | struct igc_hw *hw = &adapter->hw; 158 | 159 | *data = 0; 160 | 161 | if (hw->nvm.ops.validate(hw) != IGC_SUCCESS) { 162 | *data = 1; 163 | return false; 164 | } 165 | 166 | return true; 167 | } 168 | 169 | bool igc_link_test(struct igc_adapter *adapter, u64 *data) 170 | { 171 | bool link_up; 172 | 173 | *data = 0; 174 | 175 | /* add delay to give enough time for autonegotioation to finish */ 176 | if (adapter->hw.mac.autoneg) 177 | ssleep(5); 178 | 179 | link_up = igc_has_link(adapter); 180 | if (!link_up) { 181 | *data = 1; 182 | return false; 183 | } 184 | 185 | return true; 186 | } 187 | -------------------------------------------------------------------------------- /igc_diag.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | /* Copyright (c) 2020 Intel Corporation */ 3 | 4 | bool igc_reg_test(struct igc_adapter *adapter, u64 *data); 5 | bool igc_eeprom_test(struct igc_adapter *adapter, u64 *data); 6 | bool igc_link_test(struct igc_adapter *adapter, u64 *data); 7 | 8 | struct igc_reg_test { 9 | u16 reg; 10 | u8 array_len; 11 | u8 test_type; 12 | u32 mask; 13 | u32 write; 14 | }; 15 | 16 | /* In the hardware, registers are laid out either singly, in arrays 17 | * spaced 0x40 bytes apart, or in contiguous tables. We assume 18 | * most tests take place on arrays or single registers (handled 19 | * as a single-element array) and special-case the tables. 20 | * Table tests are always pattern tests. 21 | * 22 | * We also make provision for some required setup steps by specifying 23 | * registers to be written without any read-back testing. 24 | */ 25 | 26 | #define PATTERN_TEST 1 27 | #define SET_READ_TEST 2 28 | #define TABLE32_TEST 3 29 | #define TABLE64_TEST_LO 4 30 | #define TABLE64_TEST_HI 5 31 | -------------------------------------------------------------------------------- /igc_dump.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | /* Copyright (c) 2018 Intel Corporation */ 3 | 4 | #include "igc.h" 5 | 6 | struct igc_reg_info { 7 | u32 ofs; 8 | char *name; 9 | }; 10 | 11 | static const struct igc_reg_info igc_reg_info_tbl[] = { 12 | /* General Registers */ 13 | {IGC_CTRL, "CTRL"}, 14 | {IGC_STATUS, "STATUS"}, 15 | {IGC_CTRL_EXT, "CTRL_EXT"}, 16 | {IGC_MDIC, "MDIC"}, 17 | 18 | /* Interrupt Registers */ 19 | {IGC_ICR, "ICR"}, 20 | 21 | /* RX Registers */ 22 | {IGC_RCTL, "RCTL"}, 23 | {IGC_RDLEN(0), "RDLEN"}, 24 | {IGC_RDH(0), "RDH"}, 25 | {IGC_RDT(0), "RDT"}, 26 | {IGC_RXDCTL(0), "RXDCTL"}, 27 | {IGC_RDBAL(0), "RDBAL"}, 28 | {IGC_RDBAH(0), "RDBAH"}, 29 | 30 | /* TX Registers */ 31 | {IGC_TCTL, "TCTL"}, 32 | {IGC_TDBAL(0), "TDBAL"}, 33 | {IGC_TDBAH(0), "TDBAH"}, 34 | {IGC_TDLEN(0), "TDLEN"}, 35 | {IGC_TDH(0), "TDH"}, 36 | {IGC_TDT(0), "TDT"}, 37 | {IGC_TXDCTL(0), "TXDCTL"}, 38 | 39 | /* List Terminator */ 40 | {} 41 | }; 42 | 43 | /* igc_regdump - register printout routine */ 44 | static void igc_regdump(struct igc_hw *hw, struct igc_reg_info *reginfo) 45 | { 46 | struct net_device *dev = igc_get_hw_dev(hw); 47 | int n = 0; 48 | char rname[16]; 49 | u32 regs[8]; 50 | 51 | switch (reginfo->ofs) { 52 | case IGC_RDLEN(0): 53 | for (n = 0; n < 4; n++) 54 | regs[n] = rd32(IGC_RDLEN(n)); 55 | break; 56 | case IGC_RDH(0): 57 | for (n = 0; n < 4; n++) 58 | regs[n] = rd32(IGC_RDH(n)); 59 | break; 60 | case IGC_RDT(0): 61 | for (n = 0; n < 4; n++) 62 | regs[n] = rd32(IGC_RDT(n)); 63 | break; 64 | case IGC_RXDCTL(0): 65 | for (n = 0; n < 4; n++) 66 | regs[n] = rd32(IGC_RXDCTL(n)); 67 | break; 68 | case IGC_RDBAL(0): 69 | for (n = 0; n < 4; n++) 70 | regs[n] = rd32(IGC_RDBAL(n)); 71 | break; 72 | case IGC_RDBAH(0): 73 | for (n = 0; n < 4; n++) 74 | regs[n] = rd32(IGC_RDBAH(n)); 75 | break; 76 | case IGC_TDBAL(0): 77 | for (n = 0; n < 4; n++) 78 | regs[n] = rd32(IGC_TDBAL(n)); 79 | break; 80 | case IGC_TDBAH(0): 81 | for (n = 0; n < 4; n++) 82 | regs[n] = rd32(IGC_TDBAH(n)); 83 | break; 84 | case IGC_TDLEN(0): 85 | for (n = 0; n < 4; n++) 86 | regs[n] = rd32(IGC_TDLEN(n)); 87 | break; 88 | case IGC_TDH(0): 89 | for (n = 0; n < 4; n++) 90 | regs[n] = rd32(IGC_TDH(n)); 91 | break; 92 | case IGC_TDT(0): 93 | for (n = 0; n < 4; n++) 94 | regs[n] = rd32(IGC_TDT(n)); 95 | break; 96 | case IGC_TXDCTL(0): 97 | for (n = 0; n < 4; n++) 98 | regs[n] = rd32(IGC_TXDCTL(n)); 99 | break; 100 | default: 101 | netdev_info(dev, "%-15s %08x\n", reginfo->name, 102 | rd32(reginfo->ofs)); 103 | return; 104 | } 105 | 106 | snprintf(rname, 16, "%s%s", reginfo->name, "[0-3]"); 107 | netdev_info(dev, "%-15s %08x %08x %08x %08x\n", rname, regs[0], regs[1], 108 | regs[2], regs[3]); 109 | } 110 | 111 | /* igc_rings_dump - Tx-rings and Rx-rings */ 112 | void igc_rings_dump(struct igc_adapter *adapter) 113 | { 114 | struct net_device *netdev = adapter->netdev; 115 | struct my_u0 { u64 a; u64 b; } *u0; 116 | union igc_adv_tx_desc *tx_desc; 117 | union igc_adv_rx_desc *rx_desc; 118 | struct igc_ring *tx_ring; 119 | struct igc_ring *rx_ring; 120 | u32 staterr; 121 | u16 i, n; 122 | 123 | if (!netif_msg_hw(adapter)) 124 | return; 125 | 126 | netdev_info(netdev, "Device info: state %016lX trans_start %016lX\n", 127 | netdev->state, dev_trans_start(netdev)); 128 | 129 | /* Print TX Ring Summary */ 130 | if (!netif_running(netdev)) 131 | goto exit; 132 | 133 | netdev_info(netdev, "TX Rings Summary\n"); 134 | netdev_info(netdev, "Queue [NTU] [NTC] [bi(ntc)->dma ] leng ntw timestamp\n"); 135 | for (n = 0; n < adapter->num_tx_queues; n++) { 136 | struct igc_tx_buffer *buffer_info; 137 | 138 | tx_ring = adapter->tx_ring[n]; 139 | buffer_info = &tx_ring->tx_buffer_info[tx_ring->next_to_clean]; 140 | 141 | netdev_info(netdev, "%5d %5X %5X %016llX %04X %p %016llX\n", 142 | n, tx_ring->next_to_use, tx_ring->next_to_clean, 143 | (u64)dma_unmap_addr(buffer_info, dma), 144 | dma_unmap_len(buffer_info, len), 145 | buffer_info->next_to_watch, 146 | (u64)buffer_info->time_stamp); 147 | } 148 | 149 | /* Print TX Rings */ 150 | if (!netif_msg_tx_done(adapter)) 151 | goto rx_ring_summary; 152 | 153 | netdev_info(netdev, "TX Rings Dump\n"); 154 | 155 | /* Transmit Descriptor Formats 156 | * 157 | * Advanced Transmit Descriptor 158 | * +--------------------------------------------------------------+ 159 | * 0 | Buffer Address [63:0] | 160 | * +--------------------------------------------------------------+ 161 | * 8 | PAYLEN | PORTS |CC|IDX | STA | DCMD |DTYP|MAC|RSV| DTALEN | 162 | * +--------------------------------------------------------------+ 163 | * 63 46 45 40 39 38 36 35 32 31 24 15 0 164 | */ 165 | 166 | for (n = 0; n < adapter->num_tx_queues; n++) { 167 | tx_ring = adapter->tx_ring[n]; 168 | netdev_info(netdev, "------------------------------------\n"); 169 | netdev_info(netdev, "TX QUEUE INDEX = %d\n", 170 | tx_ring->queue_index); 171 | netdev_info(netdev, "------------------------------------\n"); 172 | netdev_info(netdev, "T [desc] [address 63:0 ] [PlPOCIStDDM Ln] [bi->dma ] leng ntw timestamp bi->skb\n"); 173 | 174 | for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) { 175 | const char *next_desc; 176 | struct igc_tx_buffer *buffer_info; 177 | 178 | tx_desc = IGC_TX_DESC(tx_ring, i); 179 | buffer_info = &tx_ring->tx_buffer_info[i]; 180 | u0 = (struct my_u0 *)tx_desc; 181 | if (i == tx_ring->next_to_use && 182 | i == tx_ring->next_to_clean) 183 | next_desc = " NTC/U"; 184 | else if (i == tx_ring->next_to_use) 185 | next_desc = " NTU"; 186 | else if (i == tx_ring->next_to_clean) 187 | next_desc = " NTC"; 188 | else 189 | next_desc = ""; 190 | 191 | netdev_info(netdev, "T [0x%03X] %016llX %016llX %016llX %04X %p %016llX %p%s\n", 192 | i, le64_to_cpu(u0->a), 193 | le64_to_cpu(u0->b), 194 | (u64)dma_unmap_addr(buffer_info, dma), 195 | dma_unmap_len(buffer_info, len), 196 | buffer_info->next_to_watch, 197 | (u64)buffer_info->time_stamp, 198 | buffer_info->skb, next_desc); 199 | 200 | if (netif_msg_pktdata(adapter) && buffer_info->skb) 201 | print_hex_dump(KERN_INFO, "", 202 | DUMP_PREFIX_ADDRESS, 203 | 16, 1, buffer_info->skb->data, 204 | dma_unmap_len(buffer_info, len), 205 | true); 206 | } 207 | } 208 | 209 | /* Print RX Rings Summary */ 210 | rx_ring_summary: 211 | netdev_info(netdev, "RX Rings Summary\n"); 212 | netdev_info(netdev, "Queue [NTU] [NTC]\n"); 213 | for (n = 0; n < adapter->num_rx_queues; n++) { 214 | rx_ring = adapter->rx_ring[n]; 215 | netdev_info(netdev, "%5d %5X %5X\n", n, rx_ring->next_to_use, 216 | rx_ring->next_to_clean); 217 | } 218 | 219 | /* Print RX Rings */ 220 | if (!netif_msg_rx_status(adapter)) 221 | goto exit; 222 | 223 | netdev_info(netdev, "RX Rings Dump\n"); 224 | 225 | /* Advanced Receive Descriptor (Read) Format 226 | * 63 1 0 227 | * +-----------------------------------------------------+ 228 | * 0 | Packet Buffer Address [63:1] |A0/NSE| 229 | * +----------------------------------------------+------+ 230 | * 8 | Header Buffer Address [63:1] | DD | 231 | * +-----------------------------------------------------+ 232 | * 233 | * 234 | * Advanced Receive Descriptor (Write-Back) Format 235 | * 236 | * 63 48 47 32 31 30 21 20 17 16 4 3 0 237 | * +------------------------------------------------------+ 238 | * 0 | Packet IP |SPH| HDR_LEN | RSV|Packet| RSS | 239 | * | Checksum Ident | | | | Type | Type | 240 | * +------------------------------------------------------+ 241 | * 8 | VLAN Tag | Length | Extended Error | Extended Status | 242 | * +------------------------------------------------------+ 243 | * 63 48 47 32 31 20 19 0 244 | */ 245 | 246 | for (n = 0; n < adapter->num_rx_queues; n++) { 247 | rx_ring = adapter->rx_ring[n]; 248 | netdev_info(netdev, "------------------------------------\n"); 249 | netdev_info(netdev, "RX QUEUE INDEX = %d\n", 250 | rx_ring->queue_index); 251 | netdev_info(netdev, "------------------------------------\n"); 252 | netdev_info(netdev, "R [desc] [ PktBuf A0] [ HeadBuf DD] [bi->dma ] [bi->skb] <-- Adv Rx Read format\n"); 253 | netdev_info(netdev, "RWB[desc] [PcsmIpSHl PtRs] [vl er S cks ln] ---------------- [bi->skb] <-- Adv Rx Write-Back format\n"); 254 | 255 | for (i = 0; i < rx_ring->count; i++) { 256 | const char *next_desc; 257 | struct igc_rx_buffer *buffer_info; 258 | 259 | buffer_info = &rx_ring->rx_buffer_info[i]; 260 | rx_desc = IGC_RX_DESC(rx_ring, i); 261 | u0 = (struct my_u0 *)rx_desc; 262 | staterr = le32_to_cpu(rx_desc->wb.upper.status_error); 263 | 264 | if (i == rx_ring->next_to_use) 265 | next_desc = " NTU"; 266 | else if (i == rx_ring->next_to_clean) 267 | next_desc = " NTC"; 268 | else 269 | next_desc = ""; 270 | 271 | if (staterr & IGC_RXD_STAT_DD) { 272 | /* Descriptor Done */ 273 | netdev_info(netdev, "%s[0x%03X] %016llX %016llX ---------------- %s\n", 274 | "RWB", i, 275 | le64_to_cpu(u0->a), 276 | le64_to_cpu(u0->b), 277 | next_desc); 278 | } else { 279 | netdev_info(netdev, "%s[0x%03X] %016llX %016llX %016llX %s\n", 280 | "R ", i, 281 | le64_to_cpu(u0->a), 282 | le64_to_cpu(u0->b), 283 | (u64)buffer_info->dma, 284 | next_desc); 285 | 286 | if (netif_msg_pktdata(adapter) && 287 | buffer_info->dma && buffer_info->page) { 288 | print_hex_dump(KERN_INFO, "", 289 | DUMP_PREFIX_ADDRESS, 290 | 16, 1, 291 | page_address 292 | (buffer_info->page) + 293 | buffer_info->page_offset, 294 | igc_rx_bufsz(rx_ring), 295 | true); 296 | } 297 | } 298 | } 299 | } 300 | 301 | exit: 302 | return; 303 | } 304 | 305 | /* igc_regs_dump - registers dump */ 306 | void igc_regs_dump(struct igc_adapter *adapter) 307 | { 308 | struct igc_hw *hw = &adapter->hw; 309 | struct igc_reg_info *reginfo; 310 | 311 | /* Print Registers */ 312 | netdev_info(adapter->netdev, "Register Dump\n"); 313 | netdev_info(adapter->netdev, "Register Name Value\n"); 314 | for (reginfo = (struct igc_reg_info *)igc_reg_info_tbl; 315 | reginfo->name; reginfo++) { 316 | igc_regdump(hw, reginfo); 317 | } 318 | } 319 | -------------------------------------------------------------------------------- /igc_hw.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | /* Copyright (c) 2018 Intel Corporation */ 3 | 4 | #ifndef _IGC_HW_H_ 5 | #define _IGC_HW_H_ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "igc_regs.h" 12 | #include "igc_defines.h" 13 | #include "igc_mac.h" 14 | #include "igc_phy.h" 15 | #include "igc_nvm.h" 16 | #include "igc_i225.h" 17 | #include "igc_base.h" 18 | 19 | #define IGC_DEV_ID_I225_LM 0x15F2 20 | #define IGC_DEV_ID_I225_V 0x15F3 21 | #define IGC_DEV_ID_I225_I 0x15F8 22 | #define IGC_DEV_ID_I220_V 0x15F7 23 | #define IGC_DEV_ID_I225_K 0x3100 24 | #define IGC_DEV_ID_I225_K2 0x3101 25 | #define IGC_DEV_ID_I226_K 0x3102 26 | #define IGC_DEV_ID_I225_LMVP 0x5502 27 | #define IGC_DEV_ID_I226_LMVP 0x5503 28 | #define IGC_DEV_ID_I225_IT 0x0D9F 29 | #define IGC_DEV_ID_I226_LM 0x125B 30 | #define IGC_DEV_ID_I226_V 0x125C 31 | #define IGC_DEV_ID_I226_IT 0x125D 32 | #define IGC_DEV_ID_I221_V 0x125E 33 | #define IGC_DEV_ID_I226_BLANK_NVM 0x125F 34 | #define IGC_DEV_ID_I225_BLANK_NVM 0x15FD 35 | 36 | /* Function pointers for the MAC. */ 37 | struct igc_mac_operations { 38 | s32 (*check_for_link)(struct igc_hw *hw); 39 | s32 (*reset_hw)(struct igc_hw *hw); 40 | s32 (*init_hw)(struct igc_hw *hw); 41 | s32 (*setup_physical_interface)(struct igc_hw *hw); 42 | void (*rar_set)(struct igc_hw *hw, u8 *address, u32 index); 43 | s32 (*read_mac_addr)(struct igc_hw *hw); 44 | s32 (*get_speed_and_duplex)(struct igc_hw *hw, u16 *speed, 45 | u16 *duplex); 46 | s32 (*acquire_swfw_sync)(struct igc_hw *hw, u16 mask); 47 | void (*release_swfw_sync)(struct igc_hw *hw, u16 mask); 48 | }; 49 | 50 | enum igc_mac_type { 51 | igc_undefined = 0, 52 | igc_i225, 53 | igc_num_macs /* List is 1-based, so subtract 1 for true count. */ 54 | }; 55 | 56 | enum igc_phy_type { 57 | igc_phy_unknown = 0, 58 | igc_phy_none, 59 | igc_phy_i225, 60 | }; 61 | 62 | enum igc_media_type { 63 | igc_media_type_unknown = 0, 64 | igc_media_type_copper = 1, 65 | igc_num_media_types 66 | }; 67 | 68 | enum igc_nvm_type { 69 | igc_nvm_unknown = 0, 70 | igc_nvm_eeprom_spi, 71 | igc_nvm_flash_hw, 72 | igc_nvm_invm, 73 | }; 74 | 75 | struct igc_info { 76 | s32 (*get_invariants)(struct igc_hw *hw); 77 | struct igc_mac_operations *mac_ops; 78 | const struct igc_phy_operations *phy_ops; 79 | struct igc_nvm_operations *nvm_ops; 80 | }; 81 | 82 | extern const struct igc_info igc_base_info; 83 | 84 | struct igc_mac_info { 85 | struct igc_mac_operations ops; 86 | 87 | u8 addr[ETH_ALEN]; 88 | u8 perm_addr[ETH_ALEN]; 89 | 90 | enum igc_mac_type type; 91 | 92 | u32 mc_filter_type; 93 | 94 | u16 mta_reg_count; 95 | u16 uta_reg_count; 96 | 97 | u32 mta_shadow[MAX_MTA_REG]; 98 | u16 rar_entry_count; 99 | 100 | u8 forced_speed_duplex; 101 | 102 | bool asf_firmware_present; 103 | bool arc_subsystem_valid; 104 | 105 | bool autoneg; 106 | bool autoneg_failed; 107 | bool get_link_status; 108 | }; 109 | 110 | struct igc_nvm_operations { 111 | s32 (*acquire)(struct igc_hw *hw); 112 | s32 (*read)(struct igc_hw *hw, u16 offset, u16 i, u16 *data); 113 | void (*release)(struct igc_hw *hw); 114 | s32 (*write)(struct igc_hw *hw, u16 offset, u16 i, u16 *data); 115 | s32 (*update)(struct igc_hw *hw); 116 | s32 (*validate)(struct igc_hw *hw); 117 | }; 118 | 119 | struct igc_phy_operations { 120 | s32 (*acquire)(struct igc_hw *hw); 121 | s32 (*check_reset_block)(struct igc_hw *hw); 122 | s32 (*force_speed_duplex)(struct igc_hw *hw); 123 | s32 (*get_phy_info)(struct igc_hw *hw); 124 | s32 (*read_reg)(struct igc_hw *hw, u32 address, u16 *data); 125 | void (*release)(struct igc_hw *hw); 126 | s32 (*reset)(struct igc_hw *hw); 127 | s32 (*write_reg)(struct igc_hw *hw, u32 address, u16 data); 128 | }; 129 | 130 | struct igc_nvm_info { 131 | struct igc_nvm_operations ops; 132 | enum igc_nvm_type type; 133 | 134 | u16 word_size; 135 | u16 delay_usec; 136 | u16 address_bits; 137 | u16 opcode_bits; 138 | u16 page_size; 139 | }; 140 | 141 | struct igc_phy_info { 142 | struct igc_phy_operations ops; 143 | 144 | enum igc_phy_type type; 145 | 146 | u32 addr; 147 | u32 id; 148 | u32 reset_delay_us; /* in usec */ 149 | u32 revision; 150 | 151 | enum igc_media_type media_type; 152 | 153 | u16 autoneg_advertised; 154 | u16 autoneg_mask; 155 | 156 | u8 mdix; 157 | 158 | bool is_mdix; 159 | bool speed_downgraded; 160 | bool autoneg_wait_to_complete; 161 | }; 162 | 163 | struct igc_bus_info { 164 | u16 func; 165 | u16 pci_cmd_word; 166 | }; 167 | 168 | enum igc_fc_mode { 169 | igc_fc_none = 0, 170 | igc_fc_rx_pause, 171 | igc_fc_tx_pause, 172 | igc_fc_full, 173 | igc_fc_default = 0xFF 174 | }; 175 | 176 | struct igc_fc_info { 177 | u32 high_water; /* Flow control high-water mark */ 178 | u32 low_water; /* Flow control low-water mark */ 179 | u16 pause_time; /* Flow control pause timer */ 180 | bool send_xon; /* Flow control send XON */ 181 | bool strict_ieee; /* Strict IEEE mode */ 182 | enum igc_fc_mode current_mode; /* Type of flow control */ 183 | enum igc_fc_mode requested_mode; 184 | }; 185 | 186 | struct igc_dev_spec_base { 187 | bool clear_semaphore_once; 188 | bool eee_enable; 189 | }; 190 | 191 | struct igc_hw { 192 | void *back; 193 | 194 | u8 __iomem *hw_addr; 195 | unsigned long io_base; 196 | 197 | struct igc_mac_info mac; 198 | struct igc_fc_info fc; 199 | struct igc_nvm_info nvm; 200 | struct igc_phy_info phy; 201 | 202 | struct igc_bus_info bus; 203 | 204 | union { 205 | struct igc_dev_spec_base _base; 206 | } dev_spec; 207 | 208 | u16 device_id; 209 | u16 subsystem_vendor_id; 210 | u16 subsystem_device_id; 211 | u16 vendor_id; 212 | 213 | u8 revision_id; 214 | }; 215 | 216 | /* Statistics counters collected by the MAC */ 217 | struct igc_hw_stats { 218 | u64 crcerrs; 219 | u64 algnerrc; 220 | u64 symerrs; 221 | u64 rxerrc; 222 | u64 mpc; 223 | u64 scc; 224 | u64 ecol; 225 | u64 mcc; 226 | u64 latecol; 227 | u64 colc; 228 | u64 dc; 229 | u64 tncrs; 230 | u64 sec; 231 | u64 cexterr; 232 | u64 rlec; 233 | u64 xonrxc; 234 | u64 xontxc; 235 | u64 xoffrxc; 236 | u64 xofftxc; 237 | u64 fcruc; 238 | u64 prc64; 239 | u64 prc127; 240 | u64 prc255; 241 | u64 prc511; 242 | u64 prc1023; 243 | u64 prc1522; 244 | u64 tlpic; 245 | u64 rlpic; 246 | u64 gprc; 247 | u64 bprc; 248 | u64 mprc; 249 | u64 gptc; 250 | u64 gorc; 251 | u64 gotc; 252 | u64 rnbc; 253 | u64 ruc; 254 | u64 rfc; 255 | u64 roc; 256 | u64 rjc; 257 | u64 mgprc; 258 | u64 mgpdc; 259 | u64 mgptc; 260 | u64 tor; 261 | u64 tot; 262 | u64 tpr; 263 | u64 tpt; 264 | u64 ptc64; 265 | u64 ptc127; 266 | u64 ptc255; 267 | u64 ptc511; 268 | u64 ptc1023; 269 | u64 ptc1522; 270 | u64 mptc; 271 | u64 bptc; 272 | u64 tsctc; 273 | u64 tsctfc; 274 | u64 iac; 275 | u64 htdpmc; 276 | u64 rpthc; 277 | u64 hgptc; 278 | u64 hgorc; 279 | u64 hgotc; 280 | u64 lenerrs; 281 | u64 scvpc; 282 | u64 hrmpc; 283 | u64 doosync; 284 | u64 o2bgptc; 285 | u64 o2bspc; 286 | u64 b2ospc; 287 | u64 b2ogprc; 288 | }; 289 | 290 | struct net_device *igc_get_hw_dev(struct igc_hw *hw); 291 | #define hw_dbg(format, arg...) \ 292 | netdev_dbg(igc_get_hw_dev(hw), format, ##arg) 293 | 294 | s32 igc_read_pcie_cap_reg(struct igc_hw *hw, u32 reg, u16 *value); 295 | s32 igc_write_pcie_cap_reg(struct igc_hw *hw, u32 reg, u16 *value); 296 | void igc_read_pci_cfg(struct igc_hw *hw, u32 reg, u16 *value); 297 | void igc_write_pci_cfg(struct igc_hw *hw, u32 reg, u16 *value); 298 | 299 | #endif /* _IGC_HW_H_ */ 300 | -------------------------------------------------------------------------------- /igc_i225.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | /* Copyright (c) 2018 Intel Corporation */ 3 | 4 | #include 5 | 6 | #include "igc_hw.h" 7 | 8 | /** 9 | * igc_get_hw_semaphore_i225 - Acquire hardware semaphore 10 | * @hw: pointer to the HW structure 11 | * 12 | * Acquire the necessary semaphores for exclusive access to the EEPROM. 13 | * Set the EEPROM access request bit and wait for EEPROM access grant bit. 14 | * Return successful if access grant bit set, else clear the request for 15 | * EEPROM access and return -IGC_ERR_NVM (-1). 16 | */ 17 | static s32 igc_acquire_nvm_i225(struct igc_hw *hw) 18 | { 19 | return igc_acquire_swfw_sync_i225(hw, IGC_SWFW_EEP_SM); 20 | } 21 | 22 | /** 23 | * igc_release_nvm_i225 - Release exclusive access to EEPROM 24 | * @hw: pointer to the HW structure 25 | * 26 | * Stop any current commands to the EEPROM and clear the EEPROM request bit, 27 | * then release the semaphores acquired. 28 | */ 29 | static void igc_release_nvm_i225(struct igc_hw *hw) 30 | { 31 | igc_release_swfw_sync_i225(hw, IGC_SWFW_EEP_SM); 32 | } 33 | 34 | /** 35 | * igc_get_hw_semaphore_i225 - Acquire hardware semaphore 36 | * @hw: pointer to the HW structure 37 | * 38 | * Acquire the HW semaphore to access the PHY or NVM 39 | */ 40 | static s32 igc_get_hw_semaphore_i225(struct igc_hw *hw) 41 | { 42 | s32 timeout = hw->nvm.word_size + 1; 43 | s32 i = 0; 44 | u32 swsm; 45 | 46 | /* Get the SW semaphore */ 47 | while (i < timeout) { 48 | swsm = rd32(IGC_SWSM); 49 | if (!(swsm & IGC_SWSM_SMBI)) 50 | break; 51 | 52 | usleep_range(500, 600); 53 | i++; 54 | } 55 | 56 | if (i == timeout) { 57 | /* In rare circumstances, the SW semaphore may already be held 58 | * unintentionally. Clear the semaphore once before giving up. 59 | */ 60 | if (hw->dev_spec._base.clear_semaphore_once) { 61 | hw->dev_spec._base.clear_semaphore_once = false; 62 | igc_put_hw_semaphore(hw); 63 | for (i = 0; i < timeout; i++) { 64 | swsm = rd32(IGC_SWSM); 65 | if (!(swsm & IGC_SWSM_SMBI)) 66 | break; 67 | 68 | usleep_range(500, 600); 69 | } 70 | } 71 | 72 | /* If we do not have the semaphore here, we have to give up. */ 73 | if (i == timeout) { 74 | hw_dbg("Driver can't access device - SMBI bit is set.\n"); 75 | return -IGC_ERR_NVM; 76 | } 77 | } 78 | 79 | /* Get the FW semaphore. */ 80 | for (i = 0; i < timeout; i++) { 81 | swsm = rd32(IGC_SWSM); 82 | wr32(IGC_SWSM, swsm | IGC_SWSM_SWESMBI); 83 | 84 | /* Semaphore acquired if bit latched */ 85 | if (rd32(IGC_SWSM) & IGC_SWSM_SWESMBI) 86 | break; 87 | 88 | usleep_range(500, 600); 89 | } 90 | 91 | if (i == timeout) { 92 | /* Release semaphores */ 93 | igc_put_hw_semaphore(hw); 94 | hw_dbg("Driver can't access the NVM\n"); 95 | return -IGC_ERR_NVM; 96 | } 97 | 98 | return 0; 99 | } 100 | 101 | /** 102 | * igc_acquire_swfw_sync_i225 - Acquire SW/FW semaphore 103 | * @hw: pointer to the HW structure 104 | * @mask: specifies which semaphore to acquire 105 | * 106 | * Acquire the SW/FW semaphore to access the PHY or NVM. The mask 107 | * will also specify which port we're acquiring the lock for. 108 | */ 109 | s32 igc_acquire_swfw_sync_i225(struct igc_hw *hw, u16 mask) 110 | { 111 | s32 i = 0, timeout = 200; 112 | u32 fwmask = mask << 16; 113 | u32 swmask = mask; 114 | s32 ret_val = 0; 115 | u32 swfw_sync; 116 | 117 | while (i < timeout) { 118 | if (igc_get_hw_semaphore_i225(hw)) { 119 | ret_val = -IGC_ERR_SWFW_SYNC; 120 | goto out; 121 | } 122 | 123 | swfw_sync = rd32(IGC_SW_FW_SYNC); 124 | if (!(swfw_sync & (fwmask | swmask))) 125 | break; 126 | 127 | /* Firmware currently using resource (fwmask) */ 128 | igc_put_hw_semaphore(hw); 129 | mdelay(5); 130 | i++; 131 | } 132 | 133 | if (i == timeout) { 134 | hw_dbg("Driver can't access resource, SW_FW_SYNC timeout.\n"); 135 | ret_val = -IGC_ERR_SWFW_SYNC; 136 | goto out; 137 | } 138 | 139 | swfw_sync |= swmask; 140 | wr32(IGC_SW_FW_SYNC, swfw_sync); 141 | 142 | igc_put_hw_semaphore(hw); 143 | out: 144 | return ret_val; 145 | } 146 | 147 | /** 148 | * igc_release_swfw_sync_i225 - Release SW/FW semaphore 149 | * @hw: pointer to the HW structure 150 | * @mask: specifies which semaphore to acquire 151 | * 152 | * Release the SW/FW semaphore used to access the PHY or NVM. The mask 153 | * will also specify which port we're releasing the lock for. 154 | */ 155 | void igc_release_swfw_sync_i225(struct igc_hw *hw, u16 mask) 156 | { 157 | u32 swfw_sync; 158 | 159 | /* Releasing the resource requires first getting the HW semaphore. 160 | * If we fail to get the semaphore, there is nothing we can do, 161 | * except log an error and quit. We are not allowed to hang here 162 | * indefinitely, as it may cause denial of service or system crash. 163 | */ 164 | if (igc_get_hw_semaphore_i225(hw)) { 165 | hw_dbg("Failed to release SW_FW_SYNC.\n"); 166 | return; 167 | } 168 | 169 | swfw_sync = rd32(IGC_SW_FW_SYNC); 170 | swfw_sync &= ~mask; 171 | wr32(IGC_SW_FW_SYNC, swfw_sync); 172 | 173 | igc_put_hw_semaphore(hw); 174 | } 175 | 176 | /** 177 | * igc_read_nvm_srrd_i225 - Reads Shadow Ram using EERD register 178 | * @hw: pointer to the HW structure 179 | * @offset: offset of word in the Shadow Ram to read 180 | * @words: number of words to read 181 | * @data: word read from the Shadow Ram 182 | * 183 | * Reads a 16 bit word from the Shadow Ram using the EERD register. 184 | * Uses necessary synchronization semaphores. 185 | */ 186 | static s32 igc_read_nvm_srrd_i225(struct igc_hw *hw, u16 offset, u16 words, 187 | u16 *data) 188 | { 189 | s32 status = 0; 190 | u16 i, count; 191 | 192 | /* We cannot hold synchronization semaphores for too long, 193 | * because of forceful takeover procedure. However it is more efficient 194 | * to read in bursts than synchronizing access for each word. 195 | */ 196 | for (i = 0; i < words; i += IGC_EERD_EEWR_MAX_COUNT) { 197 | count = (words - i) / IGC_EERD_EEWR_MAX_COUNT > 0 ? 198 | IGC_EERD_EEWR_MAX_COUNT : (words - i); 199 | 200 | status = hw->nvm.ops.acquire(hw); 201 | if (status) 202 | break; 203 | 204 | status = igc_read_nvm_eerd(hw, offset, count, data + i); 205 | hw->nvm.ops.release(hw); 206 | if (status) 207 | break; 208 | } 209 | 210 | return status; 211 | } 212 | 213 | /** 214 | * igc_write_nvm_srwr - Write to Shadow Ram using EEWR 215 | * @hw: pointer to the HW structure 216 | * @offset: offset within the Shadow Ram to be written to 217 | * @words: number of words to write 218 | * @data: 16 bit word(s) to be written to the Shadow Ram 219 | * 220 | * Writes data to Shadow Ram at offset using EEWR register. 221 | * 222 | * If igc_update_nvm_checksum is not called after this function , the 223 | * Shadow Ram will most likely contain an invalid checksum. 224 | */ 225 | static s32 igc_write_nvm_srwr(struct igc_hw *hw, u16 offset, u16 words, 226 | u16 *data) 227 | { 228 | struct igc_nvm_info *nvm = &hw->nvm; 229 | s32 ret_val = -IGC_ERR_NVM; 230 | u32 attempts = 100000; 231 | u32 i, k, eewr = 0; 232 | 233 | /* A check for invalid values: offset too large, too many words, 234 | * too many words for the offset, and not enough words. 235 | */ 236 | if (offset >= nvm->word_size || (words > (nvm->word_size - offset)) || 237 | words == 0) { 238 | hw_dbg("nvm parameter(s) out of bounds\n"); 239 | goto out; 240 | } 241 | 242 | for (i = 0; i < words; i++) { 243 | eewr = ((offset + i) << IGC_NVM_RW_ADDR_SHIFT) | 244 | (data[i] << IGC_NVM_RW_REG_DATA) | 245 | IGC_NVM_RW_REG_START; 246 | 247 | wr32(IGC_SRWR, eewr); 248 | 249 | for (k = 0; k < attempts; k++) { 250 | if (IGC_NVM_RW_REG_DONE & 251 | rd32(IGC_SRWR)) { 252 | ret_val = 0; 253 | break; 254 | } 255 | udelay(5); 256 | } 257 | 258 | if (ret_val) { 259 | hw_dbg("Shadow RAM write EEWR timed out\n"); 260 | break; 261 | } 262 | } 263 | 264 | out: 265 | return ret_val; 266 | } 267 | 268 | /** 269 | * igc_write_nvm_srwr_i225 - Write to Shadow RAM using EEWR 270 | * @hw: pointer to the HW structure 271 | * @offset: offset within the Shadow RAM to be written to 272 | * @words: number of words to write 273 | * @data: 16 bit word(s) to be written to the Shadow RAM 274 | * 275 | * Writes data to Shadow RAM at offset using EEWR register. 276 | * 277 | * If igc_update_nvm_checksum is not called after this function , the 278 | * data will not be committed to FLASH and also Shadow RAM will most likely 279 | * contain an invalid checksum. 280 | * 281 | * If error code is returned, data and Shadow RAM may be inconsistent - buffer 282 | * partially written. 283 | */ 284 | static s32 igc_write_nvm_srwr_i225(struct igc_hw *hw, u16 offset, u16 words, 285 | u16 *data) 286 | { 287 | s32 status = 0; 288 | u16 i, count; 289 | 290 | /* We cannot hold synchronization semaphores for too long, 291 | * because of forceful takeover procedure. However it is more efficient 292 | * to write in bursts than synchronizing access for each word. 293 | */ 294 | for (i = 0; i < words; i += IGC_EERD_EEWR_MAX_COUNT) { 295 | count = (words - i) / IGC_EERD_EEWR_MAX_COUNT > 0 ? 296 | IGC_EERD_EEWR_MAX_COUNT : (words - i); 297 | 298 | status = hw->nvm.ops.acquire(hw); 299 | if (status) 300 | break; 301 | 302 | status = igc_write_nvm_srwr(hw, offset, count, data + i); 303 | hw->nvm.ops.release(hw); 304 | if (status) 305 | break; 306 | } 307 | 308 | return status; 309 | } 310 | 311 | /** 312 | * igc_validate_nvm_checksum_i225 - Validate EEPROM checksum 313 | * @hw: pointer to the HW structure 314 | * 315 | * Calculates the EEPROM checksum by reading/adding each word of the EEPROM 316 | * and then verifies that the sum of the EEPROM is equal to 0xBABA. 317 | */ 318 | static s32 igc_validate_nvm_checksum_i225(struct igc_hw *hw) 319 | { 320 | s32 (*read_op_ptr)(struct igc_hw *hw, u16 offset, u16 count, 321 | u16 *data); 322 | s32 status = 0; 323 | 324 | status = hw->nvm.ops.acquire(hw); 325 | if (status) 326 | goto out; 327 | 328 | /* Replace the read function with semaphore grabbing with 329 | * the one that skips this for a while. 330 | * We have semaphore taken already here. 331 | */ 332 | read_op_ptr = hw->nvm.ops.read; 333 | hw->nvm.ops.read = igc_read_nvm_eerd; 334 | 335 | status = igc_validate_nvm_checksum(hw); 336 | 337 | /* Revert original read operation. */ 338 | hw->nvm.ops.read = read_op_ptr; 339 | 340 | hw->nvm.ops.release(hw); 341 | 342 | out: 343 | return status; 344 | } 345 | 346 | /** 347 | * igc_pool_flash_update_done_i225 - Pool FLUDONE status 348 | * @hw: pointer to the HW structure 349 | */ 350 | static s32 igc_pool_flash_update_done_i225(struct igc_hw *hw) 351 | { 352 | s32 ret_val = -IGC_ERR_NVM; 353 | u32 i, reg; 354 | 355 | for (i = 0; i < IGC_FLUDONE_ATTEMPTS; i++) { 356 | reg = rd32(IGC_EECD); 357 | if (reg & IGC_EECD_FLUDONE_I225) { 358 | ret_val = 0; 359 | break; 360 | } 361 | udelay(5); 362 | } 363 | 364 | return ret_val; 365 | } 366 | 367 | /** 368 | * igc_update_flash_i225 - Commit EEPROM to the flash 369 | * @hw: pointer to the HW structure 370 | */ 371 | static s32 igc_update_flash_i225(struct igc_hw *hw) 372 | { 373 | s32 ret_val = 0; 374 | u32 flup; 375 | 376 | ret_val = igc_pool_flash_update_done_i225(hw); 377 | if (ret_val == -IGC_ERR_NVM) { 378 | hw_dbg("Flash update time out\n"); 379 | goto out; 380 | } 381 | 382 | flup = rd32(IGC_EECD) | IGC_EECD_FLUPD_I225; 383 | wr32(IGC_EECD, flup); 384 | 385 | ret_val = igc_pool_flash_update_done_i225(hw); 386 | if (ret_val) 387 | hw_dbg("Flash update time out\n"); 388 | else 389 | hw_dbg("Flash update complete\n"); 390 | 391 | out: 392 | return ret_val; 393 | } 394 | 395 | /** 396 | * igc_update_nvm_checksum_i225 - Update EEPROM checksum 397 | * @hw: pointer to the HW structure 398 | * 399 | * Updates the EEPROM checksum by reading/adding each word of the EEPROM 400 | * up to the checksum. Then calculates the EEPROM checksum and writes the 401 | * value to the EEPROM. Next commit EEPROM data onto the Flash. 402 | */ 403 | static s32 igc_update_nvm_checksum_i225(struct igc_hw *hw) 404 | { 405 | u16 checksum = 0; 406 | s32 ret_val = 0; 407 | u16 i, nvm_data; 408 | 409 | /* Read the first word from the EEPROM. If this times out or fails, do 410 | * not continue or we could be in for a very long wait while every 411 | * EEPROM read fails 412 | */ 413 | ret_val = igc_read_nvm_eerd(hw, 0, 1, &nvm_data); 414 | if (ret_val) { 415 | hw_dbg("EEPROM read failed\n"); 416 | goto out; 417 | } 418 | 419 | ret_val = hw->nvm.ops.acquire(hw); 420 | if (ret_val) 421 | goto out; 422 | 423 | /* Do not use hw->nvm.ops.write, hw->nvm.ops.read 424 | * because we do not want to take the synchronization 425 | * semaphores twice here. 426 | */ 427 | 428 | for (i = 0; i < NVM_CHECKSUM_REG; i++) { 429 | ret_val = igc_read_nvm_eerd(hw, i, 1, &nvm_data); 430 | if (ret_val) { 431 | hw->nvm.ops.release(hw); 432 | hw_dbg("NVM Read Error while updating checksum.\n"); 433 | goto out; 434 | } 435 | checksum += nvm_data; 436 | } 437 | checksum = (u16)NVM_SUM - checksum; 438 | ret_val = igc_write_nvm_srwr(hw, NVM_CHECKSUM_REG, 1, 439 | &checksum); 440 | if (ret_val) { 441 | hw->nvm.ops.release(hw); 442 | hw_dbg("NVM Write Error while updating checksum.\n"); 443 | goto out; 444 | } 445 | 446 | hw->nvm.ops.release(hw); 447 | 448 | ret_val = igc_update_flash_i225(hw); 449 | 450 | out: 451 | return ret_val; 452 | } 453 | 454 | /** 455 | * igc_get_flash_presence_i225 - Check if flash device is detected 456 | * @hw: pointer to the HW structure 457 | */ 458 | bool igc_get_flash_presence_i225(struct igc_hw *hw) 459 | { 460 | bool ret_val = false; 461 | u32 eec = 0; 462 | 463 | eec = rd32(IGC_EECD); 464 | if (eec & IGC_EECD_FLASH_DETECTED_I225) 465 | ret_val = true; 466 | 467 | return ret_val; 468 | } 469 | 470 | /** 471 | * igc_init_nvm_params_i225 - Init NVM func ptrs. 472 | * @hw: pointer to the HW structure 473 | */ 474 | s32 igc_init_nvm_params_i225(struct igc_hw *hw) 475 | { 476 | struct igc_nvm_info *nvm = &hw->nvm; 477 | 478 | nvm->ops.acquire = igc_acquire_nvm_i225; 479 | nvm->ops.release = igc_release_nvm_i225; 480 | 481 | /* NVM Function Pointers */ 482 | if (igc_get_flash_presence_i225(hw)) { 483 | hw->nvm.type = igc_nvm_flash_hw; 484 | nvm->ops.read = igc_read_nvm_srrd_i225; 485 | nvm->ops.write = igc_write_nvm_srwr_i225; 486 | nvm->ops.validate = igc_validate_nvm_checksum_i225; 487 | nvm->ops.update = igc_update_nvm_checksum_i225; 488 | } else { 489 | hw->nvm.type = igc_nvm_invm; 490 | nvm->ops.read = igc_read_nvm_eerd; 491 | nvm->ops.write = NULL; 492 | nvm->ops.validate = NULL; 493 | nvm->ops.update = NULL; 494 | } 495 | return 0; 496 | } 497 | 498 | /** 499 | * igc_set_eee_i225 - Enable/disable EEE support 500 | * @hw: pointer to the HW structure 501 | * @adv2p5G: boolean flag enabling 2.5G EEE advertisement 502 | * @adv1G: boolean flag enabling 1G EEE advertisement 503 | * @adv100M: boolean flag enabling 100M EEE advertisement 504 | * 505 | * Enable/disable EEE based on setting in dev_spec structure. 506 | **/ 507 | s32 igc_set_eee_i225(struct igc_hw *hw, bool adv2p5G, bool adv1G, 508 | bool adv100M) 509 | { 510 | u32 ipcnfg, eeer; 511 | 512 | ipcnfg = rd32(IGC_IPCNFG); 513 | eeer = rd32(IGC_EEER); 514 | 515 | /* enable or disable per user setting */ 516 | if (hw->dev_spec._base.eee_enable) { 517 | u32 eee_su = rd32(IGC_EEE_SU); 518 | 519 | if (adv100M) 520 | ipcnfg |= IGC_IPCNFG_EEE_100M_AN; 521 | else 522 | ipcnfg &= ~IGC_IPCNFG_EEE_100M_AN; 523 | 524 | if (adv1G) 525 | ipcnfg |= IGC_IPCNFG_EEE_1G_AN; 526 | else 527 | ipcnfg &= ~IGC_IPCNFG_EEE_1G_AN; 528 | 529 | if (adv2p5G) 530 | ipcnfg |= IGC_IPCNFG_EEE_2_5G_AN; 531 | else 532 | ipcnfg &= ~IGC_IPCNFG_EEE_2_5G_AN; 533 | 534 | eeer |= (IGC_EEER_TX_LPI_EN | IGC_EEER_RX_LPI_EN | 535 | IGC_EEER_LPI_FC); 536 | 537 | /* This bit should not be set in normal operation. */ 538 | if (eee_su & IGC_EEE_SU_LPI_CLK_STP) 539 | hw_dbg("LPI Clock Stop Bit should not be set!\n"); 540 | } else { 541 | ipcnfg &= ~(IGC_IPCNFG_EEE_2_5G_AN | IGC_IPCNFG_EEE_1G_AN | 542 | IGC_IPCNFG_EEE_100M_AN); 543 | eeer &= ~(IGC_EEER_TX_LPI_EN | IGC_EEER_RX_LPI_EN | 544 | IGC_EEER_LPI_FC); 545 | } 546 | wr32(IGC_IPCNFG, ipcnfg); 547 | wr32(IGC_EEER, eeer); 548 | rd32(IGC_IPCNFG); 549 | rd32(IGC_EEER); 550 | 551 | return IGC_SUCCESS; 552 | } 553 | 554 | /* igc_set_ltr_i225 - Set Latency Tolerance Reporting thresholds 555 | * @hw: pointer to the HW structure 556 | * @link: bool indicating link status 557 | * 558 | * Set the LTR thresholds based on the link speed (Mbps), EEE, and DMAC 559 | * settings, otherwise specify that there is no LTR requirement. 560 | */ 561 | s32 igc_set_ltr_i225(struct igc_hw *hw, bool link) 562 | { 563 | u32 tw_system, ltrc, ltrv, ltr_min, ltr_max, scale_min, scale_max; 564 | u16 speed, duplex; 565 | s32 size; 566 | 567 | /* If we do not have link, LTR thresholds are zero. */ 568 | if (link) { 569 | hw->mac.ops.get_speed_and_duplex(hw, &speed, &duplex); 570 | 571 | /* Check if using copper interface with EEE enabled or if the 572 | * link speed is 10 Mbps. 573 | */ 574 | if (hw->dev_spec._base.eee_enable && 575 | speed != SPEED_10) { 576 | /* EEE enabled, so send LTRMAX threshold. */ 577 | ltrc = rd32(IGC_LTRC) | 578 | IGC_LTRC_EEEMS_EN; 579 | wr32(IGC_LTRC, ltrc); 580 | 581 | /* Calculate tw_system (nsec). */ 582 | if (speed == SPEED_100) { 583 | tw_system = ((rd32(IGC_EEE_SU) & 584 | IGC_TW_SYSTEM_100_MASK) >> 585 | IGC_TW_SYSTEM_100_SHIFT) * 500; 586 | } else { 587 | tw_system = (rd32(IGC_EEE_SU) & 588 | IGC_TW_SYSTEM_1000_MASK) * 500; 589 | } 590 | } else { 591 | tw_system = 0; 592 | } 593 | 594 | /* Get the Rx packet buffer size. */ 595 | size = rd32(IGC_RXPBS) & 596 | IGC_RXPBS_SIZE_I225_MASK; 597 | 598 | /* Calculations vary based on DMAC settings. */ 599 | if (rd32(IGC_DMACR) & IGC_DMACR_DMAC_EN) { 600 | size -= (rd32(IGC_DMACR) & 601 | IGC_DMACR_DMACTHR_MASK) >> 602 | IGC_DMACR_DMACTHR_SHIFT; 603 | /* Convert size to bits. */ 604 | size *= 1024 * 8; 605 | } else { 606 | /* Convert size to bytes, subtract the MTU, and then 607 | * convert the size to bits. 608 | */ 609 | size *= 1024; 610 | size *= 8; 611 | } 612 | 613 | if (size < 0) { 614 | hw_dbg("Invalid effective Rx buffer size %d\n", 615 | size); 616 | return -IGC_ERR_CONFIG; 617 | } 618 | 619 | /* Calculate the thresholds. Since speed is in Mbps, simplify 620 | * the calculation by multiplying size/speed by 1000 for result 621 | * to be in nsec before dividing by the scale in nsec. Set the 622 | * scale such that the LTR threshold fits in the register. 623 | */ 624 | ltr_min = (1000 * size) / speed; 625 | ltr_max = ltr_min + tw_system; 626 | scale_min = (ltr_min / 1024) < 1024 ? IGC_LTRMINV_SCALE_1024 : 627 | IGC_LTRMINV_SCALE_32768; 628 | scale_max = (ltr_max / 1024) < 1024 ? IGC_LTRMAXV_SCALE_1024 : 629 | IGC_LTRMAXV_SCALE_32768; 630 | ltr_min /= scale_min == IGC_LTRMINV_SCALE_1024 ? 1024 : 32768; 631 | ltr_min -= 1; 632 | ltr_max /= scale_max == IGC_LTRMAXV_SCALE_1024 ? 1024 : 32768; 633 | ltr_max -= 1; 634 | 635 | /* Only write the LTR thresholds if they differ from before. */ 636 | ltrv = rd32(IGC_LTRMINV); 637 | if (ltr_min != (ltrv & IGC_LTRMINV_LTRV_MASK)) { 638 | ltrv = IGC_LTRMINV_LSNP_REQ | ltr_min | 639 | (scale_min << IGC_LTRMINV_SCALE_SHIFT); 640 | wr32(IGC_LTRMINV, ltrv); 641 | } 642 | 643 | ltrv = rd32(IGC_LTRMAXV); 644 | if (ltr_max != (ltrv & IGC_LTRMAXV_LTRV_MASK)) { 645 | ltrv = IGC_LTRMAXV_LSNP_REQ | ltr_max | 646 | (scale_max << IGC_LTRMAXV_SCALE_SHIFT); 647 | wr32(IGC_LTRMAXV, ltrv); 648 | } 649 | } 650 | 651 | return IGC_SUCCESS; 652 | } 653 | -------------------------------------------------------------------------------- /igc_i225.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | /* Copyright (c) 2018 Intel Corporation */ 3 | 4 | #ifndef _IGC_I225_H_ 5 | #define _IGC_I225_H_ 6 | 7 | s32 igc_acquire_swfw_sync_i225(struct igc_hw *hw, u16 mask); 8 | void igc_release_swfw_sync_i225(struct igc_hw *hw, u16 mask); 9 | 10 | s32 igc_init_nvm_params_i225(struct igc_hw *hw); 11 | bool igc_get_flash_presence_i225(struct igc_hw *hw); 12 | s32 igc_set_eee_i225(struct igc_hw *hw, bool adv2p5G, bool adv1G, 13 | bool adv100M); 14 | s32 igc_set_ltr_i225(struct igc_hw *hw, bool link); 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /igc_mac.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | /* Copyright (c) 2018 Intel Corporation */ 3 | 4 | #ifndef _IGC_MAC_H_ 5 | #define _IGC_MAC_H_ 6 | 7 | #include "igc_hw.h" 8 | #include "igc_phy.h" 9 | #include "igc_defines.h" 10 | 11 | /* forward declaration */ 12 | s32 igc_disable_pcie_master(struct igc_hw *hw); 13 | s32 igc_check_for_copper_link(struct igc_hw *hw); 14 | s32 igc_config_fc_after_link_up(struct igc_hw *hw); 15 | s32 igc_force_mac_fc(struct igc_hw *hw); 16 | void igc_init_rx_addrs(struct igc_hw *hw, u16 rar_count); 17 | s32 igc_setup_link(struct igc_hw *hw); 18 | void igc_clear_hw_cntrs_base(struct igc_hw *hw); 19 | s32 igc_get_auto_rd_done(struct igc_hw *hw); 20 | void igc_put_hw_semaphore(struct igc_hw *hw); 21 | void igc_rar_set(struct igc_hw *hw, u8 *addr, u32 index); 22 | void igc_config_collision_dist(struct igc_hw *hw); 23 | 24 | s32 igc_get_speed_and_duplex_copper(struct igc_hw *hw, u16 *speed, 25 | u16 *duplex); 26 | 27 | bool igc_enable_mng_pass_thru(struct igc_hw *hw); 28 | void igc_update_mc_addr_list(struct igc_hw *hw, 29 | u8 *mc_addr_list, u32 mc_addr_count); 30 | 31 | enum igc_mng_mode { 32 | igc_mng_mode_none = 0, 33 | igc_mng_mode_asf, 34 | igc_mng_mode_pt, 35 | igc_mng_mode_ipmi, 36 | igc_mng_mode_host_if_only 37 | }; 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /igc_nvm.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | /* Copyright (c) 2018 Intel Corporation */ 3 | 4 | #include "igc_mac.h" 5 | #include "igc_nvm.h" 6 | 7 | /** 8 | * igc_poll_eerd_eewr_done - Poll for EEPROM read/write completion 9 | * @hw: pointer to the HW structure 10 | * @ee_reg: EEPROM flag for polling 11 | * 12 | * Polls the EEPROM status bit for either read or write completion based 13 | * upon the value of 'ee_reg'. 14 | */ 15 | static s32 igc_poll_eerd_eewr_done(struct igc_hw *hw, int ee_reg) 16 | { 17 | s32 ret_val = -IGC_ERR_NVM; 18 | u32 attempts = 100000; 19 | u32 i, reg = 0; 20 | 21 | for (i = 0; i < attempts; i++) { 22 | if (ee_reg == IGC_NVM_POLL_READ) 23 | reg = rd32(IGC_EERD); 24 | else 25 | reg = rd32(IGC_EEWR); 26 | 27 | if (reg & IGC_NVM_RW_REG_DONE) { 28 | ret_val = 0; 29 | break; 30 | } 31 | 32 | udelay(5); 33 | } 34 | 35 | return ret_val; 36 | } 37 | 38 | /** 39 | * igc_acquire_nvm - Generic request for access to EEPROM 40 | * @hw: pointer to the HW structure 41 | * 42 | * Set the EEPROM access request bit and wait for EEPROM access grant bit. 43 | * Return successful if access grant bit set, else clear the request for 44 | * EEPROM access and return -IGC_ERR_NVM (-1). 45 | */ 46 | s32 igc_acquire_nvm(struct igc_hw *hw) 47 | { 48 | s32 timeout = IGC_NVM_GRANT_ATTEMPTS; 49 | u32 eecd = rd32(IGC_EECD); 50 | s32 ret_val = 0; 51 | 52 | wr32(IGC_EECD, eecd | IGC_EECD_REQ); 53 | eecd = rd32(IGC_EECD); 54 | 55 | while (timeout) { 56 | if (eecd & IGC_EECD_GNT) 57 | break; 58 | udelay(5); 59 | eecd = rd32(IGC_EECD); 60 | timeout--; 61 | } 62 | 63 | if (!timeout) { 64 | eecd &= ~IGC_EECD_REQ; 65 | wr32(IGC_EECD, eecd); 66 | hw_dbg("Could not acquire NVM grant\n"); 67 | ret_val = -IGC_ERR_NVM; 68 | } 69 | 70 | return ret_val; 71 | } 72 | 73 | /** 74 | * igc_release_nvm - Release exclusive access to EEPROM 75 | * @hw: pointer to the HW structure 76 | * 77 | * Stop any current commands to the EEPROM and clear the EEPROM request bit. 78 | */ 79 | void igc_release_nvm(struct igc_hw *hw) 80 | { 81 | u32 eecd; 82 | 83 | eecd = rd32(IGC_EECD); 84 | eecd &= ~IGC_EECD_REQ; 85 | wr32(IGC_EECD, eecd); 86 | } 87 | 88 | /** 89 | * igc_read_nvm_eerd - Reads EEPROM using EERD register 90 | * @hw: pointer to the HW structure 91 | * @offset: offset of word in the EEPROM to read 92 | * @words: number of words to read 93 | * @data: word read from the EEPROM 94 | * 95 | * Reads a 16 bit word from the EEPROM using the EERD register. 96 | */ 97 | s32 igc_read_nvm_eerd(struct igc_hw *hw, u16 offset, u16 words, u16 *data) 98 | { 99 | struct igc_nvm_info *nvm = &hw->nvm; 100 | u32 i, eerd = 0; 101 | s32 ret_val = 0; 102 | 103 | /* A check for invalid values: offset too large, too many words, 104 | * and not enough words. 105 | */ 106 | if (offset >= nvm->word_size || (words > (nvm->word_size - offset)) || 107 | words == 0) { 108 | hw_dbg("nvm parameter(s) out of bounds\n"); 109 | ret_val = -IGC_ERR_NVM; 110 | goto out; 111 | } 112 | 113 | for (i = 0; i < words; i++) { 114 | eerd = ((offset + i) << IGC_NVM_RW_ADDR_SHIFT) + 115 | IGC_NVM_RW_REG_START; 116 | 117 | wr32(IGC_EERD, eerd); 118 | ret_val = igc_poll_eerd_eewr_done(hw, IGC_NVM_POLL_READ); 119 | if (ret_val) 120 | break; 121 | 122 | data[i] = (rd32(IGC_EERD) >> IGC_NVM_RW_REG_DATA); 123 | } 124 | 125 | out: 126 | return ret_val; 127 | } 128 | 129 | /** 130 | * igc_read_mac_addr - Read device MAC address 131 | * @hw: pointer to the HW structure 132 | */ 133 | s32 igc_read_mac_addr(struct igc_hw *hw) 134 | { 135 | u32 rar_high; 136 | u32 rar_low; 137 | u16 i; 138 | 139 | rar_high = rd32(IGC_RAH(0)); 140 | rar_low = rd32(IGC_RAL(0)); 141 | 142 | for (i = 0; i < IGC_RAL_MAC_ADDR_LEN; i++) 143 | hw->mac.perm_addr[i] = (u8)(rar_low >> (i * 8)); 144 | 145 | for (i = 0; i < IGC_RAH_MAC_ADDR_LEN; i++) 146 | hw->mac.perm_addr[i + 4] = (u8)(rar_high >> (i * 8)); 147 | 148 | for (i = 0; i < ETH_ALEN; i++) 149 | hw->mac.addr[i] = hw->mac.perm_addr[i]; 150 | 151 | return 0; 152 | } 153 | 154 | /** 155 | * igc_validate_nvm_checksum - Validate EEPROM checksum 156 | * @hw: pointer to the HW structure 157 | * 158 | * Calculates the EEPROM checksum by reading/adding each word of the EEPROM 159 | * and then verifies that the sum of the EEPROM is equal to 0xBABA. 160 | */ 161 | s32 igc_validate_nvm_checksum(struct igc_hw *hw) 162 | { 163 | u16 checksum = 0; 164 | u16 i, nvm_data; 165 | s32 ret_val = 0; 166 | 167 | for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { 168 | ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); 169 | if (ret_val) { 170 | hw_dbg("NVM Read Error\n"); 171 | goto out; 172 | } 173 | checksum += nvm_data; 174 | } 175 | 176 | if (checksum != (u16)NVM_SUM) { 177 | hw_dbg("NVM Checksum Invalid\n"); 178 | ret_val = -IGC_ERR_NVM; 179 | goto out; 180 | } 181 | 182 | out: 183 | return ret_val; 184 | } 185 | 186 | /** 187 | * igc_update_nvm_checksum - Update EEPROM checksum 188 | * @hw: pointer to the HW structure 189 | * 190 | * Updates the EEPROM checksum by reading/adding each word of the EEPROM 191 | * up to the checksum. Then calculates the EEPROM checksum and writes the 192 | * value to the EEPROM. 193 | */ 194 | s32 igc_update_nvm_checksum(struct igc_hw *hw) 195 | { 196 | u16 checksum = 0; 197 | u16 i, nvm_data; 198 | s32 ret_val; 199 | 200 | for (i = 0; i < NVM_CHECKSUM_REG; i++) { 201 | ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); 202 | if (ret_val) { 203 | hw_dbg("NVM Read Error while updating checksum.\n"); 204 | goto out; 205 | } 206 | checksum += nvm_data; 207 | } 208 | checksum = (u16)NVM_SUM - checksum; 209 | ret_val = hw->nvm.ops.write(hw, NVM_CHECKSUM_REG, 1, &checksum); 210 | if (ret_val) 211 | hw_dbg("NVM Write Error while updating checksum.\n"); 212 | 213 | out: 214 | return ret_val; 215 | } 216 | -------------------------------------------------------------------------------- /igc_nvm.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | /* Copyright (c) 2018 Intel Corporation */ 3 | 4 | #ifndef _IGC_NVM_H_ 5 | #define _IGC_NVM_H_ 6 | 7 | s32 igc_acquire_nvm(struct igc_hw *hw); 8 | void igc_release_nvm(struct igc_hw *hw); 9 | s32 igc_read_mac_addr(struct igc_hw *hw); 10 | s32 igc_read_nvm_eerd(struct igc_hw *hw, u16 offset, u16 words, u16 *data); 11 | s32 igc_validate_nvm_checksum(struct igc_hw *hw); 12 | s32 igc_update_nvm_checksum(struct igc_hw *hw); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /igc_phy.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | /* Copyright (c) 2018 Intel Corporation */ 3 | 4 | #ifndef _IGC_PHY_H_ 5 | #define _IGC_PHY_H_ 6 | 7 | #include "igc_mac.h" 8 | 9 | s32 igc_check_reset_block(struct igc_hw *hw); 10 | s32 igc_phy_hw_reset(struct igc_hw *hw); 11 | s32 igc_get_phy_id(struct igc_hw *hw); 12 | s32 igc_phy_has_link(struct igc_hw *hw, u32 iterations, 13 | u32 usec_interval, bool *success); 14 | s32 igc_check_downshift(struct igc_hw *hw); 15 | s32 igc_setup_copper_link(struct igc_hw *hw); 16 | void igc_power_up_phy_copper(struct igc_hw *hw); 17 | void igc_power_down_phy_copper(struct igc_hw *hw); 18 | s32 igc_write_phy_reg_gpy(struct igc_hw *hw, u32 offset, u16 data); 19 | s32 igc_read_phy_reg_gpy(struct igc_hw *hw, u32 offset, u16 *data); 20 | u16 igc_read_phy_fw_version(struct igc_hw *hw); 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /igc_ptp.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | /* Copyright (c) 2019 Intel Corporation */ 3 | 4 | #include "igc.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #define INCVALUE_MASK 0x7fffffff 14 | #define ISGN 0x80000000 15 | 16 | #define IGC_SYSTIM_OVERFLOW_PERIOD (HZ * 60 * 9) 17 | #define IGC_PTP_TX_TIMEOUT (HZ * 15) 18 | 19 | #define netdev_level_once(level, dev, fmt, ...) \ 20 | do { \ 21 | static bool __print_once __read_mostly; \ 22 | \ 23 | if (!__print_once) { \ 24 | __print_once = true; \ 25 | netdev_printk(level, dev, fmt, ##__VA_ARGS__); \ 26 | } \ 27 | } while (0) 28 | 29 | #define netdev_emerg_once(dev, fmt, ...) \ 30 | netdev_level_once(KERN_EMERG, dev, fmt, ##__VA_ARGS__) 31 | #define netdev_alert_once(dev, fmt, ...) \ 32 | netdev_level_once(KERN_ALERT, dev, fmt, ##__VA_ARGS__) 33 | #define netdev_crit_once(dev, fmt, ...) \ 34 | netdev_level_once(KERN_CRIT, dev, fmt, ##__VA_ARGS__) 35 | #define netdev_err_once(dev, fmt, ...) \ 36 | netdev_level_once(KERN_ERR, dev, fmt, ##__VA_ARGS__) 37 | #define netdev_warn_once(dev, fmt, ...) \ 38 | netdev_level_once(KERN_WARNING, dev, fmt, ##__VA_ARGS__) 39 | #define netdev_notice_once(dev, fmt, ...) \ 40 | netdev_level_once(KERN_NOTICE, dev, fmt, ##__VA_ARGS__) 41 | #define netdev_info_once(dev, fmt, ...) \ 42 | netdev_level_once(KERN_INFO, dev, fmt, ##__VA_ARGS__) 43 | 44 | /* SYSTIM read access for I225 */ 45 | void igc_ptp_read(struct igc_adapter *adapter, struct timespec64 *ts) 46 | { 47 | struct igc_hw *hw = &adapter->hw; 48 | u32 sec, nsec; 49 | 50 | /* The timestamp is latched when SYSTIML is read. */ 51 | nsec = rd32(IGC_SYSTIML); 52 | sec = rd32(IGC_SYSTIMH); 53 | 54 | ts->tv_sec = sec; 55 | ts->tv_nsec = nsec; 56 | } 57 | 58 | static void igc_ptp_write_i225(struct igc_adapter *adapter, 59 | const struct timespec64 *ts) 60 | { 61 | struct igc_hw *hw = &adapter->hw; 62 | 63 | wr32(IGC_SYSTIML, ts->tv_nsec); 64 | wr32(IGC_SYSTIMH, ts->tv_sec); 65 | } 66 | 67 | static int igc_ptp_adjfine_i225(struct ptp_clock_info *ptp, long scaled_ppm) 68 | { 69 | struct igc_adapter *igc = container_of(ptp, struct igc_adapter, 70 | ptp_caps); 71 | struct igc_hw *hw = &igc->hw; 72 | int neg_adj = 0; 73 | u64 rate; 74 | u32 inca; 75 | 76 | if (scaled_ppm < 0) { 77 | neg_adj = 1; 78 | scaled_ppm = -scaled_ppm; 79 | } 80 | rate = scaled_ppm; 81 | rate <<= 14; 82 | rate = div_u64(rate, 78125); 83 | 84 | inca = rate & INCVALUE_MASK; 85 | if (neg_adj) 86 | inca |= ISGN; 87 | 88 | wr32(IGC_TIMINCA, inca); 89 | 90 | return 0; 91 | } 92 | 93 | static int igc_ptp_adjtime_i225(struct ptp_clock_info *ptp, s64 delta) 94 | { 95 | struct igc_adapter *igc = container_of(ptp, struct igc_adapter, 96 | ptp_caps); 97 | struct timespec64 now, then = ns_to_timespec64(delta); 98 | unsigned long flags; 99 | 100 | spin_lock_irqsave(&igc->tmreg_lock, flags); 101 | 102 | igc_ptp_read(igc, &now); 103 | now = timespec64_add(now, then); 104 | igc_ptp_write_i225(igc, (const struct timespec64 *)&now); 105 | 106 | spin_unlock_irqrestore(&igc->tmreg_lock, flags); 107 | 108 | return 0; 109 | } 110 | 111 | static int igc_ptp_gettimex64_i225(struct ptp_clock_info *ptp, 112 | struct timespec64 *ts) 113 | { 114 | struct igc_adapter *igc = container_of(ptp, struct igc_adapter, 115 | ptp_caps); 116 | struct igc_hw *hw = &igc->hw; 117 | unsigned long flags; 118 | 119 | spin_lock_irqsave(&igc->tmreg_lock, flags); 120 | 121 | ts->tv_nsec = rd32(IGC_SYSTIML); 122 | ts->tv_sec = rd32(IGC_SYSTIMH); 123 | 124 | spin_unlock_irqrestore(&igc->tmreg_lock, flags); 125 | 126 | return 0; 127 | } 128 | 129 | static int igc_ptp_settime_i225(struct ptp_clock_info *ptp, 130 | const struct timespec64 *ts) 131 | { 132 | struct igc_adapter *igc = container_of(ptp, struct igc_adapter, 133 | ptp_caps); 134 | unsigned long flags; 135 | 136 | spin_lock_irqsave(&igc->tmreg_lock, flags); 137 | 138 | igc_ptp_write_i225(igc, ts); 139 | 140 | spin_unlock_irqrestore(&igc->tmreg_lock, flags); 141 | 142 | return 0; 143 | } 144 | 145 | static int igc_ptp_feature_enable_i225(struct ptp_clock_info *ptp, 146 | struct ptp_clock_request *rq, int on) 147 | { 148 | return -EOPNOTSUPP; 149 | } 150 | 151 | /** 152 | * igc_ptp_systim_to_hwtstamp - convert system time value to HW timestamp 153 | * @adapter: board private structure 154 | * @hwtstamps: timestamp structure to update 155 | * @systim: unsigned 64bit system time value 156 | * 157 | * We need to convert the system time value stored in the RX/TXSTMP registers 158 | * into a hwtstamp which can be used by the upper level timestamping functions. 159 | **/ 160 | static void igc_ptp_systim_to_hwtstamp(struct igc_adapter *adapter, 161 | struct skb_shared_hwtstamps *hwtstamps, 162 | u64 systim) 163 | { 164 | switch (adapter->hw.mac.type) { 165 | case igc_i225: 166 | memset(hwtstamps, 0, sizeof(*hwtstamps)); 167 | /* Upper 32 bits contain s, lower 32 bits contain ns. */ 168 | hwtstamps->hwtstamp = ktime_set(systim >> 32, 169 | systim & 0xFFFFFFFF); 170 | break; 171 | default: 172 | break; 173 | } 174 | } 175 | 176 | /** 177 | * igc_ptp_rx_pktstamp - Retrieve timestamp from Rx packet buffer 178 | * @q_vector: Pointer to interrupt specific structure 179 | * @va: Pointer to address containing Rx buffer 180 | * @skb: Buffer containing timestamp and packet 181 | * 182 | * This function retrieves the timestamp saved in the beginning of packet 183 | * buffer. While two timestamps are available, one in timer0 reference and the 184 | * other in timer1 reference, this function considers only the timestamp in 185 | * timer0 reference. 186 | */ 187 | void igc_ptp_rx_pktstamp(struct igc_q_vector *q_vector, __le32 *va, 188 | struct sk_buff *skb) 189 | { 190 | struct igc_adapter *adapter = q_vector->adapter; 191 | u64 regval; 192 | int adjust; 193 | 194 | /* Timestamps are saved in little endian at the beginning of the packet 195 | * buffer following the layout: 196 | * 197 | * DWORD: | 0 | 1 | 2 | 3 | 198 | * Field: | Timer1 SYSTIML | Timer1 SYSTIMH | Timer0 SYSTIML | Timer0 SYSTIMH | 199 | * 200 | * SYSTIML holds the nanoseconds part while SYSTIMH holds the seconds 201 | * part of the timestamp. 202 | */ 203 | regval = le32_to_cpu(va[2]); 204 | regval |= (u64)le32_to_cpu(va[3]) << 32; 205 | igc_ptp_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), regval); 206 | 207 | /* Adjust timestamp for the RX latency based on link speed */ 208 | switch (adapter->link_speed) { 209 | case SPEED_10: 210 | adjust = IGC_I225_RX_LATENCY_10; 211 | break; 212 | case SPEED_100: 213 | adjust = IGC_I225_RX_LATENCY_100; 214 | break; 215 | case SPEED_1000: 216 | adjust = IGC_I225_RX_LATENCY_1000; 217 | break; 218 | case SPEED_2500: 219 | adjust = IGC_I225_RX_LATENCY_2500; 220 | break; 221 | default: 222 | adjust = 0; 223 | netdev_warn_once(adapter->netdev, "Imprecise timestamp\n"); 224 | break; 225 | } 226 | skb_hwtstamps(skb)->hwtstamp = 227 | ktime_sub_ns(skb_hwtstamps(skb)->hwtstamp, adjust); 228 | } 229 | 230 | static void igc_ptp_disable_rx_timestamp(struct igc_adapter *adapter) 231 | { 232 | struct igc_hw *hw = &adapter->hw; 233 | u32 val; 234 | int i; 235 | 236 | wr32(IGC_TSYNCRXCTL, 0); 237 | 238 | for (i = 0; i < adapter->num_rx_queues; i++) { 239 | val = rd32(IGC_SRRCTL(i)); 240 | val &= ~IGC_SRRCTL_TIMESTAMP; 241 | wr32(IGC_SRRCTL(i), val); 242 | } 243 | 244 | val = rd32(IGC_RXPBS); 245 | val &= ~IGC_RXPBS_CFG_TS_EN; 246 | wr32(IGC_RXPBS, val); 247 | } 248 | 249 | static void igc_ptp_enable_rx_timestamp(struct igc_adapter *adapter) 250 | { 251 | struct igc_hw *hw = &adapter->hw; 252 | u32 val; 253 | int i; 254 | 255 | val = rd32(IGC_RXPBS); 256 | val |= IGC_RXPBS_CFG_TS_EN; 257 | wr32(IGC_RXPBS, val); 258 | 259 | for (i = 0; i < adapter->num_rx_queues; i++) { 260 | val = rd32(IGC_SRRCTL(i)); 261 | /* FIXME: For now, only support retrieving RX timestamps from 262 | * timer 0. 263 | */ 264 | val |= IGC_SRRCTL_TIMER1SEL(0) | IGC_SRRCTL_TIMER0SEL(0) | 265 | IGC_SRRCTL_TIMESTAMP; 266 | wr32(IGC_SRRCTL(i), val); 267 | } 268 | 269 | val = IGC_TSYNCRXCTL_ENABLED | IGC_TSYNCRXCTL_TYPE_ALL | 270 | IGC_TSYNCRXCTL_RXSYNSIG; 271 | wr32(IGC_TSYNCRXCTL, val); 272 | } 273 | 274 | static void igc_ptp_disable_tx_timestamp(struct igc_adapter *adapter) 275 | { 276 | struct igc_hw *hw = &adapter->hw; 277 | 278 | wr32(IGC_TSYNCTXCTL, 0); 279 | } 280 | 281 | static void igc_ptp_enable_tx_timestamp(struct igc_adapter *adapter) 282 | { 283 | struct igc_hw *hw = &adapter->hw; 284 | 285 | wr32(IGC_TSYNCTXCTL, IGC_TSYNCTXCTL_ENABLED | IGC_TSYNCTXCTL_TXSYNSIG); 286 | 287 | /* Read TXSTMP registers to discard any timestamp previously stored. */ 288 | rd32(IGC_TXSTMPL); 289 | rd32(IGC_TXSTMPH); 290 | } 291 | 292 | /** 293 | * igc_ptp_set_timestamp_mode - setup hardware for timestamping 294 | * @adapter: networking device structure 295 | * @config: hwtstamp configuration 296 | * 297 | * Return: 0 in case of success, negative errno code otherwise. 298 | */ 299 | static int igc_ptp_set_timestamp_mode(struct igc_adapter *adapter, 300 | struct hwtstamp_config *config) 301 | { 302 | /* reserved for future extensions */ 303 | if (config->flags) 304 | return -EINVAL; 305 | 306 | switch (config->tx_type) { 307 | case HWTSTAMP_TX_OFF: 308 | igc_ptp_disable_tx_timestamp(adapter); 309 | break; 310 | case HWTSTAMP_TX_ON: 311 | igc_ptp_enable_tx_timestamp(adapter); 312 | break; 313 | default: 314 | return -ERANGE; 315 | } 316 | 317 | switch (config->rx_filter) { 318 | case HWTSTAMP_FILTER_NONE: 319 | igc_ptp_disable_rx_timestamp(adapter); 320 | break; 321 | case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: 322 | case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: 323 | case HWTSTAMP_FILTER_PTP_V2_EVENT: 324 | case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: 325 | case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: 326 | case HWTSTAMP_FILTER_PTP_V2_SYNC: 327 | case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: 328 | case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: 329 | case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: 330 | case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: 331 | case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: 332 | case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: 333 | // case HWTSTAMP_FILTER_NTP_ALL: 334 | case HWTSTAMP_FILTER_ALL: 335 | igc_ptp_enable_rx_timestamp(adapter); 336 | config->rx_filter = HWTSTAMP_FILTER_ALL; 337 | break; 338 | default: 339 | return -ERANGE; 340 | } 341 | 342 | return 0; 343 | } 344 | 345 | static void igc_ptp_tx_timeout(struct igc_adapter *adapter) 346 | { 347 | struct igc_hw *hw = &adapter->hw; 348 | 349 | dev_kfree_skb_any(adapter->ptp_tx_skb); 350 | adapter->ptp_tx_skb = NULL; 351 | adapter->tx_hwtstamp_timeouts++; 352 | clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state); 353 | /* Clear the tx valid bit in TSYNCTXCTL register to enable interrupt. */ 354 | rd32(IGC_TXSTMPH); 355 | netdev_warn(adapter->netdev, "Tx timestamp timeout\n"); 356 | } 357 | 358 | void igc_ptp_tx_hang(struct igc_adapter *adapter) 359 | { 360 | bool timeout = time_is_before_jiffies(adapter->ptp_tx_start + 361 | IGC_PTP_TX_TIMEOUT); 362 | 363 | if (!test_bit(__IGC_PTP_TX_IN_PROGRESS, &adapter->state)) 364 | return; 365 | 366 | /* If we haven't received a timestamp within the timeout, it is 367 | * reasonable to assume that it will never occur, so we can unlock the 368 | * timestamp bit when this occurs. 369 | */ 370 | if (timeout) { 371 | cancel_work_sync(&adapter->ptp_tx_work); 372 | igc_ptp_tx_timeout(adapter); 373 | } 374 | } 375 | 376 | /** 377 | * igc_ptp_tx_hwtstamp - utility function which checks for TX time stamp 378 | * @adapter: Board private structure 379 | * 380 | * If we were asked to do hardware stamping and such a time stamp is 381 | * available, then it must have been for this skb here because we only 382 | * allow only one such packet into the queue. 383 | */ 384 | static void igc_ptp_tx_hwtstamp(struct igc_adapter *adapter) 385 | { 386 | struct sk_buff *skb = adapter->ptp_tx_skb; 387 | struct skb_shared_hwtstamps shhwtstamps; 388 | struct igc_hw *hw = &adapter->hw; 389 | int adjust = 0; 390 | u64 regval; 391 | 392 | if (WARN_ON_ONCE(!skb)) 393 | return; 394 | 395 | regval = rd32(IGC_TXSTMPL); 396 | regval |= (u64)rd32(IGC_TXSTMPH) << 32; 397 | igc_ptp_systim_to_hwtstamp(adapter, &shhwtstamps, regval); 398 | 399 | switch (adapter->link_speed) { 400 | case SPEED_10: 401 | adjust = IGC_I225_TX_LATENCY_10; 402 | break; 403 | case SPEED_100: 404 | adjust = IGC_I225_TX_LATENCY_100; 405 | break; 406 | case SPEED_1000: 407 | adjust = IGC_I225_TX_LATENCY_1000; 408 | break; 409 | case SPEED_2500: 410 | adjust = IGC_I225_TX_LATENCY_2500; 411 | break; 412 | } 413 | 414 | shhwtstamps.hwtstamp = 415 | ktime_add_ns(shhwtstamps.hwtstamp, adjust); 416 | 417 | /* Clear the lock early before calling skb_tstamp_tx so that 418 | * applications are not woken up before the lock bit is clear. We use 419 | * a copy of the skb pointer to ensure other threads can't change it 420 | * while we're notifying the stack. 421 | */ 422 | adapter->ptp_tx_skb = NULL; 423 | clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state); 424 | 425 | /* Notify the stack and free the skb after we've unlocked */ 426 | skb_tstamp_tx(skb, &shhwtstamps); 427 | dev_kfree_skb_any(skb); 428 | } 429 | 430 | /** 431 | * igc_ptp_tx_work 432 | * @work: pointer to work struct 433 | * 434 | * This work function polls the TSYNCTXCTL valid bit to determine when a 435 | * timestamp has been taken for the current stored skb. 436 | */ 437 | static void igc_ptp_tx_work(struct work_struct *work) 438 | { 439 | struct igc_adapter *adapter = container_of(work, struct igc_adapter, 440 | ptp_tx_work); 441 | struct igc_hw *hw = &adapter->hw; 442 | u32 tsynctxctl; 443 | 444 | if (!test_bit(__IGC_PTP_TX_IN_PROGRESS, &adapter->state)) 445 | return; 446 | 447 | tsynctxctl = rd32(IGC_TSYNCTXCTL); 448 | if (WARN_ON_ONCE(!(tsynctxctl & IGC_TSYNCTXCTL_TXTT_0))) 449 | return; 450 | 451 | igc_ptp_tx_hwtstamp(adapter); 452 | } 453 | 454 | /** 455 | * igc_ptp_set_ts_config - set hardware time stamping config 456 | * @netdev: network interface device structure 457 | * @ifr: interface request data 458 | * 459 | **/ 460 | int igc_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr) 461 | { 462 | struct igc_adapter *adapter = netdev_priv(netdev); 463 | struct hwtstamp_config config; 464 | int err; 465 | 466 | if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) 467 | return -EFAULT; 468 | 469 | err = igc_ptp_set_timestamp_mode(adapter, &config); 470 | if (err) 471 | return err; 472 | 473 | /* save these settings for future reference */ 474 | memcpy(&adapter->tstamp_config, &config, 475 | sizeof(adapter->tstamp_config)); 476 | 477 | return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? 478 | -EFAULT : 0; 479 | } 480 | 481 | /** 482 | * igc_ptp_get_ts_config - get hardware time stamping config 483 | * @netdev: network interface device structure 484 | * @ifr: interface request data 485 | * 486 | * Get the hwtstamp_config settings to return to the user. Rather than attempt 487 | * to deconstruct the settings from the registers, just return a shadow copy 488 | * of the last known settings. 489 | **/ 490 | int igc_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr) 491 | { 492 | struct igc_adapter *adapter = netdev_priv(netdev); 493 | struct hwtstamp_config *config = &adapter->tstamp_config; 494 | 495 | return copy_to_user(ifr->ifr_data, config, sizeof(*config)) ? 496 | -EFAULT : 0; 497 | } 498 | 499 | /** 500 | * igc_ptp_init - Initialize PTP functionality 501 | * @adapter: Board private structure 502 | * 503 | * This function is called at device probe to initialize the PTP 504 | * functionality. 505 | */ 506 | void igc_ptp_init(struct igc_adapter *adapter) 507 | { 508 | struct net_device *netdev = adapter->netdev; 509 | struct igc_hw *hw = &adapter->hw; 510 | 511 | switch (hw->mac.type) { 512 | case igc_i225: 513 | snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr); 514 | adapter->ptp_caps.owner = THIS_MODULE; 515 | adapter->ptp_caps.max_adj = 62499999; 516 | // adapter->ptp_caps.adjfine = igc_ptp_adjfine_i225; 517 | adapter->ptp_caps.adjtime = igc_ptp_adjtime_i225; 518 | adapter->ptp_caps.gettime64 = igc_ptp_gettimex64_i225; 519 | adapter->ptp_caps.settime64 = igc_ptp_settime_i225; 520 | adapter->ptp_caps.enable = igc_ptp_feature_enable_i225; 521 | break; 522 | default: 523 | adapter->ptp_clock = NULL; 524 | return; 525 | } 526 | 527 | spin_lock_init(&adapter->tmreg_lock); 528 | INIT_WORK(&adapter->ptp_tx_work, igc_ptp_tx_work); 529 | 530 | adapter->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE; 531 | adapter->tstamp_config.tx_type = HWTSTAMP_TX_OFF; 532 | 533 | adapter->prev_ptp_time = ktime_to_timespec64(ktime_get_real()); 534 | adapter->ptp_reset_start = ktime_get(); 535 | 536 | adapter->ptp_clock = ptp_clock_register(&adapter->ptp_caps, 537 | &adapter->pdev->dev); 538 | if (IS_ERR(adapter->ptp_clock)) { 539 | adapter->ptp_clock = NULL; 540 | netdev_err(netdev, "ptp_clock_register failed\n"); 541 | } else if (adapter->ptp_clock) { 542 | netdev_info(netdev, "PHC added\n"); 543 | adapter->ptp_flags |= IGC_PTP_ENABLED; 544 | } 545 | } 546 | 547 | static void igc_ptp_time_save(struct igc_adapter *adapter) 548 | { 549 | igc_ptp_read(adapter, &adapter->prev_ptp_time); 550 | adapter->ptp_reset_start = ktime_get(); 551 | } 552 | 553 | static void igc_ptp_time_restore(struct igc_adapter *adapter) 554 | { 555 | struct timespec64 ts = adapter->prev_ptp_time; 556 | ktime_t delta; 557 | 558 | delta = ktime_sub(ktime_get(), adapter->ptp_reset_start); 559 | 560 | timespec64_add_ns(&ts, ktime_to_ns(delta)); 561 | 562 | igc_ptp_write_i225(adapter, &ts); 563 | } 564 | 565 | static void igc_ptm_stop(struct igc_adapter *adapter) 566 | { 567 | struct igc_hw *hw = &adapter->hw; 568 | u32 ctrl; 569 | 570 | ctrl = rd32(IGC_PTM_CTRL); 571 | ctrl &= ~IGC_PTM_CTRL_EN; 572 | 573 | wr32(IGC_PTM_CTRL, ctrl); 574 | } 575 | 576 | /** 577 | * igc_ptp_suspend - Disable PTP work items and prepare for suspend 578 | * @adapter: Board private structure 579 | * 580 | * This function stops the overflow check work and PTP Tx timestamp work, and 581 | * will prepare the device for OS suspend. 582 | */ 583 | void igc_ptp_suspend(struct igc_adapter *adapter) 584 | { 585 | if (!(adapter->ptp_flags & IGC_PTP_ENABLED)) 586 | return; 587 | 588 | cancel_work_sync(&adapter->ptp_tx_work); 589 | dev_kfree_skb_any(adapter->ptp_tx_skb); 590 | adapter->ptp_tx_skb = NULL; 591 | clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state); 592 | 593 | if (pci_device_is_present(adapter->pdev)) { 594 | igc_ptp_time_save(adapter); 595 | igc_ptm_stop(adapter); 596 | } 597 | } 598 | 599 | /** 600 | * igc_ptp_stop - Disable PTP device and stop the overflow check. 601 | * @adapter: Board private structure. 602 | * 603 | * This function stops the PTP support and cancels the delayed work. 604 | **/ 605 | void igc_ptp_stop(struct igc_adapter *adapter) 606 | { 607 | igc_ptp_suspend(adapter); 608 | 609 | if (adapter->ptp_clock) { 610 | ptp_clock_unregister(adapter->ptp_clock); 611 | netdev_info(adapter->netdev, "PHC removed\n"); 612 | adapter->ptp_flags &= ~IGC_PTP_ENABLED; 613 | } 614 | } 615 | 616 | /** 617 | * igc_ptp_reset - Re-enable the adapter for PTP following a reset. 618 | * @adapter: Board private structure. 619 | * 620 | * This function handles the reset work required to re-enable the PTP device. 621 | **/ 622 | void igc_ptp_reset(struct igc_adapter *adapter) 623 | { 624 | struct igc_hw *hw = &adapter->hw; 625 | unsigned long flags; 626 | 627 | /* reset the tstamp_config */ 628 | igc_ptp_set_timestamp_mode(adapter, &adapter->tstamp_config); 629 | 630 | spin_lock_irqsave(&adapter->tmreg_lock, flags); 631 | 632 | switch (adapter->hw.mac.type) { 633 | case igc_i225: 634 | wr32(IGC_TSAUXC, 0x0); 635 | wr32(IGC_TSSDP, 0x0); 636 | wr32(IGC_TSIM, IGC_TSICR_INTERRUPTS); 637 | wr32(IGC_IMS, IGC_IMS_TS); 638 | break; 639 | default: 640 | /* No work to do. */ 641 | goto out; 642 | } 643 | 644 | /* Re-initialize the timer. */ 645 | if (hw->mac.type == igc_i225) { 646 | igc_ptp_time_restore(adapter); 647 | } else { 648 | timecounter_init(&adapter->tc, &adapter->cc, 649 | ktime_to_ns(ktime_get_real())); 650 | } 651 | out: 652 | spin_unlock_irqrestore(&adapter->tmreg_lock, flags); 653 | 654 | wrfl(); 655 | } 656 | -------------------------------------------------------------------------------- /igc_regs.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | /* Copyright (c) 2018 Intel Corporation */ 3 | 4 | #ifndef _IGC_REGS_H_ 5 | #define _IGC_REGS_H_ 6 | 7 | /* General Register Descriptions */ 8 | #define IGC_CTRL 0x00000 /* Device Control - RW */ 9 | #define IGC_STATUS 0x00008 /* Device Status - RO */ 10 | #define IGC_EECD 0x00010 /* EEPROM/Flash Control - RW */ 11 | #define IGC_CTRL_EXT 0x00018 /* Extended Device Control - RW */ 12 | #define IGC_MDIC 0x00020 /* MDI Control - RW */ 13 | #define IGC_MDICNFG 0x00E04 /* MDC/MDIO Configuration - RW */ 14 | #define IGC_CONNSW 0x00034 /* Copper/Fiber switch control - RW */ 15 | #define IGC_I225_PHPM 0x00E14 /* I225 PHY Power Management */ 16 | #define IGC_GPHY_VERSION 0x0001E /* I225 gPHY Firmware Version */ 17 | 18 | /* Internal Packet Buffer Size Registers */ 19 | #define IGC_RXPBS 0x02404 /* Rx Packet Buffer Size - RW */ 20 | #define IGC_TXPBS 0x03404 /* Tx Packet Buffer Size - RW */ 21 | 22 | /* NVM Register Descriptions */ 23 | #define IGC_EERD 0x12014 /* EEprom mode read - RW */ 24 | #define IGC_EEWR 0x12018 /* EEprom mode write - RW */ 25 | 26 | /* Flow Control Register Descriptions */ 27 | #define IGC_FCAL 0x00028 /* FC Address Low - RW */ 28 | #define IGC_FCAH 0x0002C /* FC Address High - RW */ 29 | #define IGC_FCT 0x00030 /* FC Type - RW */ 30 | #define IGC_FCTTV 0x00170 /* FC Transmit Timer - RW */ 31 | #define IGC_FCRTL 0x02160 /* FC Receive Threshold Low - RW */ 32 | #define IGC_FCRTH 0x02168 /* FC Receive Threshold High - RW */ 33 | #define IGC_FCRTV 0x02460 /* FC Refresh Timer Value - RW */ 34 | 35 | /* Semaphore registers */ 36 | #define IGC_SW_FW_SYNC 0x05B5C /* SW-FW Synchronization - RW */ 37 | #define IGC_SWSM 0x05B50 /* SW Semaphore */ 38 | #define IGC_FWSM 0x05B54 /* FW Semaphore */ 39 | 40 | /* Function Active and Power State to MNG */ 41 | #define IGC_FACTPS 0x05B30 42 | 43 | /* Interrupt Register Description */ 44 | #define IGC_EICR 0x01580 /* Ext. Interrupt Cause read - W0 */ 45 | #define IGC_EICS 0x01520 /* Ext. Interrupt Cause Set - W0 */ 46 | #define IGC_EIMS 0x01524 /* Ext. Interrupt Mask Set/Read - RW */ 47 | #define IGC_EIMC 0x01528 /* Ext. Interrupt Mask Clear - WO */ 48 | #define IGC_EIAC 0x0152C /* Ext. Interrupt Auto Clear - RW */ 49 | #define IGC_EIAM 0x01530 /* Ext. Interrupt Auto Mask - RW */ 50 | #define IGC_ICR 0x01500 /* Intr Cause Read - RC/W1C */ 51 | #define IGC_ICS 0x01504 /* Intr Cause Set - WO */ 52 | #define IGC_IMS 0x01508 /* Intr Mask Set/Read - RW */ 53 | #define IGC_IMC 0x0150C /* Intr Mask Clear - WO */ 54 | #define IGC_IAM 0x01510 /* Intr Ack Auto Mask- RW */ 55 | /* Intr Throttle - RW */ 56 | #define IGC_EITR(_n) (0x01680 + (0x4 * (_n))) 57 | /* Interrupt Vector Allocation - RW */ 58 | #define IGC_IVAR0 0x01700 59 | #define IGC_IVAR_MISC 0x01740 /* IVAR for "other" causes - RW */ 60 | #define IGC_GPIE 0x01514 /* General Purpose Intr Enable - RW */ 61 | 62 | /* MSI-X Table Register Descriptions */ 63 | #define IGC_PBACL 0x05B68 /* MSIx PBA Clear - R/W 1 to clear */ 64 | 65 | /* RSS registers */ 66 | #define IGC_MRQC 0x05818 /* Multiple Receive Control - RW */ 67 | 68 | /* Filtering Registers */ 69 | #define IGC_ETQF(_n) (0x05CB0 + (4 * (_n))) /* EType Queue Fltr */ 70 | 71 | /* ETQF register bit definitions */ 72 | #define IGC_ETQF_FILTER_ENABLE BIT(26) 73 | #define IGC_ETQF_QUEUE_ENABLE BIT(31) 74 | #define IGC_ETQF_QUEUE_SHIFT 16 75 | #define IGC_ETQF_QUEUE_MASK 0x00070000 76 | #define IGC_ETQF_ETYPE_MASK 0x0000FFFF 77 | 78 | /* Redirection Table - RW Array */ 79 | #define IGC_RETA(_i) (0x05C00 + ((_i) * 4)) 80 | /* RSS Random Key - RW Array */ 81 | #define IGC_RSSRK(_i) (0x05C80 + ((_i) * 4)) 82 | 83 | /* Receive Register Descriptions */ 84 | #define IGC_RCTL 0x00100 /* Rx Control - RW */ 85 | #define IGC_SRRCTL(_n) (0x0C00C + ((_n) * 0x40)) 86 | #define IGC_PSRTYPE(_i) (0x05480 + ((_i) * 4)) 87 | #define IGC_RDBAL(_n) (0x0C000 + ((_n) * 0x40)) 88 | #define IGC_RDBAH(_n) (0x0C004 + ((_n) * 0x40)) 89 | #define IGC_RDLEN(_n) (0x0C008 + ((_n) * 0x40)) 90 | #define IGC_RDH(_n) (0x0C010 + ((_n) * 0x40)) 91 | #define IGC_RDT(_n) (0x0C018 + ((_n) * 0x40)) 92 | #define IGC_RXDCTL(_n) (0x0C028 + ((_n) * 0x40)) 93 | #define IGC_RQDPC(_n) (0x0C030 + ((_n) * 0x40)) 94 | #define IGC_RXCSUM 0x05000 /* Rx Checksum Control - RW */ 95 | #define IGC_RLPML 0x05004 /* Rx Long Packet Max Length */ 96 | #define IGC_RFCTL 0x05008 /* Receive Filter Control*/ 97 | #define IGC_MTA 0x05200 /* Multicast Table Array - RW Array */ 98 | #define IGC_RA 0x05400 /* Receive Address - RW Array */ 99 | #define IGC_UTA 0x0A000 /* Unicast Table Array - RW */ 100 | #define IGC_RAL(_n) (0x05400 + ((_n) * 0x08)) 101 | #define IGC_RAH(_n) (0x05404 + ((_n) * 0x08)) 102 | #define IGC_VLANPQF 0x055B0 /* VLAN Priority Queue Filter - RW */ 103 | 104 | /* Transmit Register Descriptions */ 105 | #define IGC_TCTL 0x00400 /* Tx Control - RW */ 106 | #define IGC_TIPG 0x00410 /* Tx Inter-packet gap - RW */ 107 | #define IGC_TDBAL(_n) (0x0E000 + ((_n) * 0x40)) 108 | #define IGC_TDBAH(_n) (0x0E004 + ((_n) * 0x40)) 109 | #define IGC_TDLEN(_n) (0x0E008 + ((_n) * 0x40)) 110 | #define IGC_TDH(_n) (0x0E010 + ((_n) * 0x40)) 111 | #define IGC_TDT(_n) (0x0E018 + ((_n) * 0x40)) 112 | #define IGC_TXDCTL(_n) (0x0E028 + ((_n) * 0x40)) 113 | 114 | /* MMD Register Descriptions */ 115 | #define IGC_MMDAC 13 /* MMD Access Control */ 116 | #define IGC_MMDAAD 14 /* MMD Access Address/Data */ 117 | 118 | /* Statistics Register Descriptions */ 119 | #define IGC_CRCERRS 0x04000 /* CRC Error Count - R/clr */ 120 | #define IGC_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */ 121 | #define IGC_RXERRC 0x0400C /* Receive Error Count - R/clr */ 122 | #define IGC_MPC 0x04010 /* Missed Packet Count - R/clr */ 123 | #define IGC_SCC 0x04014 /* Single Collision Count - R/clr */ 124 | #define IGC_ECOL 0x04018 /* Excessive Collision Count - R/clr */ 125 | #define IGC_MCC 0x0401C /* Multiple Collision Count - R/clr */ 126 | #define IGC_LATECOL 0x04020 /* Late Collision Count - R/clr */ 127 | #define IGC_COLC 0x04028 /* Collision Count - R/clr */ 128 | #define IGC_RERC 0x0402C /* Receive Error Count - R/clr */ 129 | #define IGC_DC 0x04030 /* Defer Count - R/clr */ 130 | #define IGC_TNCRS 0x04034 /* Tx-No CRS - R/clr */ 131 | #define IGC_HTDPMC 0x0403C /* Host Transmit Discarded by MAC - R/clr */ 132 | #define IGC_RLEC 0x04040 /* Receive Length Error Count - R/clr */ 133 | #define IGC_XONRXC 0x04048 /* XON Rx Count - R/clr */ 134 | #define IGC_XONTXC 0x0404C /* XON Tx Count - R/clr */ 135 | #define IGC_XOFFRXC 0x04050 /* XOFF Rx Count - R/clr */ 136 | #define IGC_XOFFTXC 0x04054 /* XOFF Tx Count - R/clr */ 137 | #define IGC_FCRUC 0x04058 /* Flow Control Rx Unsupported Count- R/clr */ 138 | #define IGC_PRC64 0x0405C /* Packets Rx (64 bytes) - R/clr */ 139 | #define IGC_PRC127 0x04060 /* Packets Rx (65-127 bytes) - R/clr */ 140 | #define IGC_PRC255 0x04064 /* Packets Rx (128-255 bytes) - R/clr */ 141 | #define IGC_PRC511 0x04068 /* Packets Rx (255-511 bytes) - R/clr */ 142 | #define IGC_PRC1023 0x0406C /* Packets Rx (512-1023 bytes) - R/clr */ 143 | #define IGC_PRC1522 0x04070 /* Packets Rx (1024-1522 bytes) - R/clr */ 144 | #define IGC_GPRC 0x04074 /* Good Packets Rx Count - R/clr */ 145 | #define IGC_BPRC 0x04078 /* Broadcast Packets Rx Count - R/clr */ 146 | #define IGC_MPRC 0x0407C /* Multicast Packets Rx Count - R/clr */ 147 | #define IGC_GPTC 0x04080 /* Good Packets Tx Count - R/clr */ 148 | #define IGC_GORCL 0x04088 /* Good Octets Rx Count Low - R/clr */ 149 | #define IGC_GORCH 0x0408C /* Good Octets Rx Count High - R/clr */ 150 | #define IGC_GOTCL 0x04090 /* Good Octets Tx Count Low - R/clr */ 151 | #define IGC_GOTCH 0x04094 /* Good Octets Tx Count High - R/clr */ 152 | #define IGC_RNBC 0x040A0 /* Rx No Buffers Count - R/clr */ 153 | #define IGC_RUC 0x040A4 /* Rx Undersize Count - R/clr */ 154 | #define IGC_RFC 0x040A8 /* Rx Fragment Count - R/clr */ 155 | #define IGC_ROC 0x040AC /* Rx Oversize Count - R/clr */ 156 | #define IGC_RJC 0x040B0 /* Rx Jabber Count - R/clr */ 157 | #define IGC_MGTPRC 0x040B4 /* Management Packets Rx Count - R/clr */ 158 | #define IGC_MGTPDC 0x040B8 /* Management Packets Dropped Count - R/clr */ 159 | #define IGC_MGTPTC 0x040BC /* Management Packets Tx Count - R/clr */ 160 | #define IGC_TORL 0x040C0 /* Total Octets Rx Low - R/clr */ 161 | #define IGC_TORH 0x040C4 /* Total Octets Rx High - R/clr */ 162 | #define IGC_TOTL 0x040C8 /* Total Octets Tx Low - R/clr */ 163 | #define IGC_TOTH 0x040CC /* Total Octets Tx High - R/clr */ 164 | #define IGC_TPR 0x040D0 /* Total Packets Rx - R/clr */ 165 | #define IGC_TPT 0x040D4 /* Total Packets Tx - R/clr */ 166 | #define IGC_PTC64 0x040D8 /* Packets Tx (64 bytes) - R/clr */ 167 | #define IGC_PTC127 0x040DC /* Packets Tx (65-127 bytes) - R/clr */ 168 | #define IGC_PTC255 0x040E0 /* Packets Tx (128-255 bytes) - R/clr */ 169 | #define IGC_PTC511 0x040E4 /* Packets Tx (256-511 bytes) - R/clr */ 170 | #define IGC_PTC1023 0x040E8 /* Packets Tx (512-1023 bytes) - R/clr */ 171 | #define IGC_PTC1522 0x040EC /* Packets Tx (1024-1522 Bytes) - R/clr */ 172 | #define IGC_MPTC 0x040F0 /* Multicast Packets Tx Count - R/clr */ 173 | #define IGC_BPTC 0x040F4 /* Broadcast Packets Tx Count - R/clr */ 174 | #define IGC_TSCTC 0x040F8 /* TCP Segmentation Context Tx - R/clr */ 175 | #define IGC_IAC 0x04100 /* Interrupt Assertion Count */ 176 | #define IGC_RPTHC 0x04104 /* Rx Packets To Host */ 177 | #define IGC_TLPIC 0x04148 /* EEE Tx LPI Count */ 178 | #define IGC_RLPIC 0x0414C /* EEE Rx LPI Count */ 179 | #define IGC_HGPTC 0x04118 /* Host Good Packets Tx Count */ 180 | #define IGC_RXDMTC 0x04120 /* Rx Descriptor Minimum Threshold Count */ 181 | #define IGC_HGORCL 0x04128 /* Host Good Octets Received Count Low */ 182 | #define IGC_HGORCH 0x0412C /* Host Good Octets Received Count High */ 183 | #define IGC_HGOTCL 0x04130 /* Host Good Octets Transmit Count Low */ 184 | #define IGC_HGOTCH 0x04134 /* Host Good Octets Transmit Count High */ 185 | #define IGC_LENERRS 0x04138 /* Length Errors Count */ 186 | 187 | /* Time sync registers */ 188 | #define IGC_TSICR 0x0B66C /* Time Sync Interrupt Cause */ 189 | #define IGC_TSIM 0x0B674 /* Time Sync Interrupt Mask Register */ 190 | #define IGC_TSAUXC 0x0B640 /* Timesync Auxiliary Control register */ 191 | #define IGC_TSYNCRXCTL 0x0B620 /* Rx Time Sync Control register - RW */ 192 | #define IGC_TSYNCTXCTL 0x0B614 /* Tx Time Sync Control register - RW */ 193 | #define IGC_TSYNCRXCFG 0x05F50 /* Time Sync Rx Configuration - RW */ 194 | #define IGC_TSSDP 0x0003C /* Time Sync SDP Configuration Register - RW */ 195 | 196 | #define IGC_IMIR(_i) (0x05A80 + ((_i) * 4)) /* Immediate Interrupt */ 197 | #define IGC_IMIREXT(_i) (0x05AA0 + ((_i) * 4)) /* Immediate INTR Ext*/ 198 | 199 | #define IGC_FTQF(_n) (0x059E0 + (4 * (_n))) /* 5-tuple Queue Fltr */ 200 | 201 | /* Transmit Scheduling Registers */ 202 | #define IGC_TQAVCTRL 0x3570 203 | #define IGC_TXQCTL(_n) (0x3344 + 0x4 * (_n)) 204 | #define IGC_BASET_L 0x3314 205 | #define IGC_BASET_H 0x3318 206 | #define IGC_QBVCYCLET 0x331C 207 | #define IGC_QBVCYCLET_S 0x3320 208 | 209 | #define IGC_STQT(_n) (0x3324 + 0x4 * (_n)) 210 | #define IGC_ENDQT(_n) (0x3334 + 0x4 * (_n)) 211 | #define IGC_DTXMXPKTSZ 0x355C 212 | 213 | /* System Time Registers */ 214 | #define IGC_SYSTIML 0x0B600 /* System time register Low - RO */ 215 | #define IGC_SYSTIMH 0x0B604 /* System time register High - RO */ 216 | #define IGC_SYSTIMR 0x0B6F8 /* System time register Residue */ 217 | #define IGC_TIMINCA 0x0B608 /* Increment attributes register - RW */ 218 | 219 | #define IGC_TXSTMPL 0x0B618 /* Tx timestamp value Low - RO */ 220 | #define IGC_TXSTMPH 0x0B61C /* Tx timestamp value High - RO */ 221 | 222 | /* PCIe Registers */ 223 | #define IGC_PTM_CTRL 0x12540 /* PTM Control */ 224 | #define IGC_PTM_STAT 0x12544 /* PTM Status */ 225 | #define IGC_PTM_CYCLE_CTRL 0x1254C /* PTM Cycle Control */ 226 | 227 | /* PTM Time registers */ 228 | #define IGC_PTM_T1_TIM0_L 0x12558 /* T1 on Timer 0 Low */ 229 | #define IGC_PTM_T1_TIM0_H 0x1255C /* T1 on Timer 0 High */ 230 | 231 | #define IGC_PTM_CURR_T2_L 0x1258C /* Current T2 Low */ 232 | #define IGC_PTM_CURR_T2_H 0x12590 /* Current T2 High */ 233 | #define IGC_PTM_PREV_T2_L 0x12584 /* Previous T2 Low */ 234 | #define IGC_PTM_PREV_T2_H 0x12588 /* Previous T2 High */ 235 | #define IGC_PTM_PREV_T4M1 0x12578 /* T4 Minus T1 on previous PTM Cycle */ 236 | #define IGC_PTM_CURR_T4M1 0x1257C /* T4 Minus T1 on this PTM Cycle */ 237 | #define IGC_PTM_PREV_T3M2 0x12580 /* T3 Minus T2 on previous PTM Cycle */ 238 | #define IGC_PTM_TDELAY 0x12594 /* PTM PCIe Link Delay */ 239 | 240 | #define IGC_PCIE_DIG_DELAY 0x12550 /* PCIe Digital Delay */ 241 | #define IGC_PCIE_PHY_DELAY 0x12554 /* PCIe PHY Delay */ 242 | 243 | /* Management registers */ 244 | #define IGC_MANC 0x05820 /* Management Control - RW */ 245 | 246 | /* Shadow Ram Write Register - RW */ 247 | #define IGC_SRWR 0x12018 248 | 249 | /* Wake Up registers */ 250 | #define IGC_WUC 0x05800 /* Wakeup Control - RW */ 251 | #define IGC_WUFC 0x05808 /* Wakeup Filter Control - RW */ 252 | #define IGC_WUS 0x05810 /* Wakeup Status - R/W1C */ 253 | #define IGC_WUPL 0x05900 /* Wakeup Packet Length - RW */ 254 | 255 | /* Wake Up packet memory */ 256 | #define IGC_WUPM_REG(_i) (0x05A00 + ((_i) * 4)) 257 | 258 | /* Energy Efficient Ethernet "EEE" registers */ 259 | #define IGC_EEER 0x0E30 /* Energy Efficient Ethernet "EEE"*/ 260 | #define IGC_IPCNFG 0x0E38 /* Internal PHY Configuration */ 261 | #define IGC_EEE_SU 0x0E34 /* EEE Setup */ 262 | 263 | /* LTR registers */ 264 | #define IGC_LTRC 0x01A0 /* Latency Tolerance Reporting Control */ 265 | #define IGC_DMACR 0x02508 /* DMA Coalescing Control Register */ 266 | #define IGC_LTRMINV 0x5BB0 /* LTR Minimum Value */ 267 | #define IGC_LTRMAXV 0x5BB4 /* LTR Maximum Value */ 268 | 269 | /* forward declaration */ 270 | struct igc_hw; 271 | u32 igc_rd32(struct igc_hw *hw, u32 reg); 272 | 273 | /* write operations, indexed using DWORDS */ 274 | #define wr32(reg, val) \ 275 | do { \ 276 | u8 __iomem *hw_addr = READ_ONCE((hw)->hw_addr); \ 277 | if (!IGC_REMOVED(hw_addr)) \ 278 | writel((val), &hw_addr[(reg)]); \ 279 | } while (0) 280 | 281 | #define rd32(reg) (igc_rd32(hw, reg)) 282 | 283 | #define wrfl() ((void)rd32(IGC_STATUS)) 284 | 285 | #define array_wr32(reg, offset, value) \ 286 | wr32((reg) + ((offset) << 2), (value)) 287 | 288 | #define array_rd32(reg, offset) (igc_rd32(hw, (reg) + ((offset) << 2))) 289 | 290 | #define IGC_REMOVED(h) unlikely(!(h)) 291 | 292 | #endif 293 | -------------------------------------------------------------------------------- /igc_tsn.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | /* Copyright (c) 2019 Intel Corporation */ 3 | 4 | #include "igc.h" 5 | #include "igc_tsn.h" 6 | 7 | static bool is_any_launchtime(struct igc_adapter *adapter) 8 | { 9 | int i; 10 | 11 | for (i = 0; i < adapter->num_tx_queues; i++) { 12 | struct igc_ring *ring = adapter->tx_ring[i]; 13 | 14 | if (ring->launchtime_enable) 15 | return true; 16 | } 17 | 18 | return false; 19 | } 20 | 21 | /* Returns the TSN specific registers to their default values after 22 | * TSN offloading is disabled. 23 | */ 24 | static int igc_tsn_disable_offload(struct igc_adapter *adapter) 25 | { 26 | struct igc_hw *hw = &adapter->hw; 27 | u32 tqavctrl; 28 | int i; 29 | 30 | if (!(adapter->flags & IGC_FLAG_TSN_QBV_ENABLED)) 31 | return 0; 32 | 33 | adapter->cycle_time.tv64 = 0; 34 | 35 | wr32(IGC_TXPBS, I225_TXPBSIZE_DEFAULT); 36 | wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_DEFAULT); 37 | 38 | tqavctrl = rd32(IGC_TQAVCTRL); 39 | tqavctrl &= ~(IGC_TQAVCTRL_TRANSMIT_MODE_TSN | 40 | IGC_TQAVCTRL_ENHANCED_QAV); 41 | wr32(IGC_TQAVCTRL, tqavctrl); 42 | 43 | for (i = 0; i < adapter->num_tx_queues; i++) { 44 | struct igc_ring *ring = adapter->tx_ring[i]; 45 | 46 | ring->start_time = 0; 47 | ring->end_time = 0; 48 | ring->launchtime_enable = false; 49 | 50 | wr32(IGC_TXQCTL(i), 0); 51 | wr32(IGC_STQT(i), 0); 52 | wr32(IGC_ENDQT(i), NSEC_PER_SEC); 53 | } 54 | 55 | wr32(IGC_QBVCYCLET_S, NSEC_PER_SEC); 56 | wr32(IGC_QBVCYCLET, NSEC_PER_SEC); 57 | 58 | adapter->flags &= ~IGC_FLAG_TSN_QBV_ENABLED; 59 | 60 | return 0; 61 | } 62 | 63 | static int igc_tsn_enable_offload(struct igc_adapter *adapter) 64 | { 65 | struct igc_hw *hw = &adapter->hw; 66 | u32 tqavctrl, baset_l, baset_h; 67 | u32 sec, nsec, cycle; 68 | ktime_t base_time, systim; 69 | int i; 70 | 71 | if (adapter->flags & IGC_FLAG_TSN_QBV_ENABLED) 72 | return 0; 73 | 74 | cycle = adapter->cycle_time.tv64; 75 | base_time = adapter->base_time; 76 | 77 | wr32(IGC_TSAUXC, 0); 78 | wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_TSN); 79 | wr32(IGC_TXPBS, IGC_TXPBSIZE_TSN); 80 | 81 | tqavctrl = rd32(IGC_TQAVCTRL); 82 | tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV; 83 | wr32(IGC_TQAVCTRL, tqavctrl); 84 | 85 | wr32(IGC_QBVCYCLET_S, cycle); 86 | wr32(IGC_QBVCYCLET, cycle); 87 | 88 | for (i = 0; i < adapter->num_tx_queues; i++) { 89 | struct igc_ring *ring = adapter->tx_ring[i]; 90 | u32 txqctl = 0; 91 | 92 | wr32(IGC_STQT(i), ring->start_time); 93 | wr32(IGC_ENDQT(i), ring->end_time); 94 | 95 | if (adapter->base_time.tv64) { 96 | /* If we have a base_time we are in "taprio" 97 | * mode and we need to be strict about the 98 | * cycles: only transmit a packet if it can be 99 | * completed during that cycle. 100 | */ 101 | txqctl |= IGC_TXQCTL_STRICT_CYCLE | 102 | IGC_TXQCTL_STRICT_END; 103 | } 104 | 105 | if (ring->launchtime_enable) 106 | txqctl |= IGC_TXQCTL_QUEUE_MODE_LAUNCHT; 107 | 108 | wr32(IGC_TXQCTL(i), txqctl); 109 | } 110 | 111 | nsec = rd32(IGC_SYSTIML); 112 | sec = rd32(IGC_SYSTIMH); 113 | 114 | systim = ktime_set(sec, nsec); 115 | 116 | if (ktime_compare(systim, base_time) > 0) { 117 | s64 n; 118 | 119 | ktime_t sub_time = ktime_sub(systim, base_time); 120 | n = div64_s64(sub_time.tv64, cycle); 121 | base_time = ktime_add_ns(base_time, (n + 1) * cycle); 122 | } 123 | 124 | baset_h = div_s64_rem(base_time.tv64, NSEC_PER_SEC, &baset_l); 125 | 126 | wr32(IGC_BASET_H, baset_h); 127 | wr32(IGC_BASET_L, baset_l); 128 | 129 | adapter->flags |= IGC_FLAG_TSN_QBV_ENABLED; 130 | 131 | return 0; 132 | } 133 | 134 | int igc_tsn_offload_apply(struct igc_adapter *adapter) 135 | { 136 | bool is_any_enabled = adapter->base_time.tv64 || is_any_launchtime(adapter); 137 | 138 | if (!(adapter->flags & IGC_FLAG_TSN_QBV_ENABLED) && !is_any_enabled) 139 | return 0; 140 | 141 | if (!is_any_enabled) { 142 | int err = igc_tsn_disable_offload(adapter); 143 | 144 | if (err < 0) 145 | return err; 146 | 147 | /* The BASET registers aren't cleared when writing 148 | * into them, force a reset if the interface is 149 | * running. 150 | */ 151 | if (netif_running(adapter->netdev)) 152 | schedule_work(&adapter->reset_task); 153 | 154 | return 0; 155 | } 156 | 157 | return igc_tsn_enable_offload(adapter); 158 | } 159 | -------------------------------------------------------------------------------- /igc_tsn.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | /* Copyright (c) 2020 Intel Corporation */ 3 | 4 | #ifndef _IGC_TSN_H_ 5 | #define _IGC_TSN_H_ 6 | 7 | int igc_tsn_offload_apply(struct igc_adapter *adapter); 8 | 9 | #endif /* _IGC_BASE_H */ 10 | --------------------------------------------------------------------------------