mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-10-30 13:05:13 +08:00
🚀 Sync 2026-06-07 17:45:31
This commit is contained in:
1 parent
a9100725c5
commit
9c74cc341d
13 files changed
+6
-3779
No files matched your search
@@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-passwall
|
||||
PKG_VERSION:=26.6.2
|
||||
PKG_RELEASE:=155
|
||||
PKG_RELEASE:=156
|
||||
PKG_PO_VERSION:=$(PKG_VERSION)
|
||||
|
||||
PKG_CONFIG_DEPENDS:= \
|
||||
|
||||
@@ -94,7 +94,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
<div class="block pure-g">
|
||||
<div class="pure-u-1-3">
|
||||
<div class="img-con">
|
||||
<img src="data:image/png;base64,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 truncated
|
||||
<img src='data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiDQoJIHZpZXdCb3g9IjAgMCA1MTIgNTEyIiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA1MTIgNTEyOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPg0KCS5zdDB7ZmlsbDojMjBiOGQ0O30NCgkuc3Qxe2ZpbGw6I0ZGRkZGRjt9DQoJLnN0MntmaWxsOiNEMkU1RjE7fQ0KCS5zdDN7ZmlsbDojQjVDRkU0O30NCjwvc3R5bGU+DQo8Zz4NCgk8Y2lyY2xlIGNsYXNzPSJzdDAiIGN4PSIyNTYiIGN5PSIyNTYiIHI9IjI1NiIvPg0KCTxwYXRoIGNsYXNzPSJzdDEiIGQ9Ik0zODAuNiwxNDcuM2wtNDUuNywyMzAuNWMwLDAtNi40LDE2LTI0LDguM2wtMTA1LjUtODAuOUwxNjcsMjg2LjdsLTY0LjYtMjEuN2MwLDAtOS45LTMuNS0xMC45LTExLjINCgkJYy0xLTcuNywxMS4yLTExLjgsMTEuMi0xMS44bDI1Ni44LTEwMC43QzM1OS41LDE0MS4yLDM4MC42LDEzMS45LDM4MC42LDE0Ny4zIi8+DQoJPHBhdGggY2xhc3M9InN0MiIgZD0iTTE5Ny4yLDM3NS4yYzAsMC0zLjEtMC4zLTYuOS0xMi40Yy0zLjgtMTIuMi0yMy4zLTc2LjEtMjMuMy03Ni4xbDE1NS4xLTk4LjVjMCwwLDktNS40LDguNiwwDQoJCWMwLDAsMS42LDEtMy4yLDUuNGMtNC44LDQuNS0xMjEuOCwxMDkuNy0xMjEuOCwxMDkuNyIvPg0KCTxwYXRoIGNsYXNzPSJzdDMiIGQ9Ik0yNDUuOCwzMzYuMmwtNDEuNywzOC4xYzAsMC0zLjMsMi41LTYuOCwwLjlsOC03MC43Ii8+DQo8L2c+DQo8L3N2Zz4NCg=='/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pure-u-2-3">
|
||||
@@ -118,7 +118,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
<div class="block pure-g">
|
||||
<div class="pure-u-1-3">
|
||||
<div class="img-con">
|
||||
<img src="data:image/png;base64,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 truncated
|
||||
<img src='data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAwIDEwMDAiPg0KICA8c3R5bGU+DQogICAgLnN0MXtmaWxsOiNmZmZ9DQogICAgLnN0MntmaWxsOiMwMTk1ZGV9DQogICAgLnN0NHtmaWxsOiNmMmYyZjJ9DQogIDwvc3R5bGU+DQogIDxjbGlwUGF0aCBpZD0iY2xpcENpcmNsZSI+DQogICAgPGNpcmNsZSBjeD0iNTAwIiBjeT0iNTAwIiByPSI0ODAiLz4NCiAgPC9jbGlwUGF0aD4NCiAgPGNpcmNsZSBjeD0iNTAwIiBjeT0iNTAwIiByPSI0ODAiIGZpbGw9IiMwMGEwZWYiLz4NCiAgPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXBDaXJjbGUpIj4NCiAgICA8cGF0aCBkPSJNMTI5LjUgMzQ1aDkwLjljMTkuOCAwIDM1LjYgMiA0Ny40IDRhNzcuNSA3Ny41IDAgMCAxIDM3LjYgMjMuNyAxMzEgMTMxIDAgMCAxIDIzLjcgMzkuNWM1LjkgMTUuOCA3LjkgMzUuNiA3LjkgNTkuMyAwIDE5LjgtMiAzNy42LTcuOSA1My40YTExNC45IDExNC45IDAgMCAxLTI1LjcgNDMuNSA3NyA3NyAwIDAgMS0zNS42IDE5LjhjLTExLjkgNC0yNS43IDUuOS00My41IDUuOWgtOTQuOVYzNDVoLjF6bTUxLjQgNDMuNXYxNjQuMWgzNy42YzEzLjggMCAyMy43IDAgMjkuNy0yIDcuOS0yIDE1LjgtNS45IDE5LjgtOS45IDUuOS00IDkuOS0xMy44IDEzLjgtMjMuNyA0LTExLjkgNS45LTI1LjcgNS45LTQ1LjVzLTItMzMuNi01LjktNDMuNWE2OSA2OSAwIDAgMC0xMy44LTIzLjcgNDUuMyA0NS4zIDAgMCAwLTIzLjctMTEuOWMtNy45LTItMTkuOC0yLTQxLjUtMmgtMjEuN3YtMS45aC0uMnpNMzgwLjYgNTk0LjFWMzQ1SDQzMGwxMDAuOCAxNjYuMVYzNDVoNDcuNHYyNDkuMWgtNDkuNEw0MjggNDMydjE2Mi4xaC00Ny40ek02MTcuOCA1MTMuMWw0OS40LTRjMiAxNS44IDcuOSAyNy43IDE3LjggMzUuNmE1NS4yIDU1LjIgMCAwIDAgMzUuNiAxMS45IDU5IDU5IDAgMCAwIDM1LjYtOS45IDMwLjkgMzAuOSAwIDAgMCAxMS45LTIzLjdjMC01LjktMi05LjktNS45LTE1LjgtNC00LTkuOS03LjktMTcuOC05LjktNS45LTItMTkuOC01LjktMzkuNS05LjlhMTU4LjcgMTU4LjcgMCAwIDEtNTcuMy0yMy43IDYyLjcgNjIuNyAwIDAgMS0yMy43LTQ5LjQgODEgODEgMCAwIDEgOS45LTM1LjYgNjcuNiA2Ny42IDAgMCAxIDMxLjYtMjUuNyAxMjQgMTI0IDAgMCAxIDQ5LjQtNy45YzMxLjYgMCA1NS40IDUuOSA3MS4yIDE5LjhzMjMuNyAzMS42IDI1LjcgNTUuNGwtNDkuNCAyYy0yLTExLjktNS45LTIxLjctMTMuOC0yNy43LTcuOS01LjktMTcuOC03LjktMzEuNi03LjlzLTI1LjcgNC0zMy42IDkuOWMtNS45IDQtNy45IDkuOS03LjkgMTUuOHMyIDExLjkgNy45IDE1LjhjNS45IDUuOSAyMS43IDkuOSA0NS41IDE1LjggMjMuNyA1LjkgNDEuNSAxMS45IDUzLjQgMTcuOHMyMS43IDEzLjggMjcuNyAyNS43YTc4LjEgNzguMSAwIDAgMSA5LjkgMzkuNWMwIDEzLjgtNCAyNy43LTExLjkgMzkuNWE3Ny42IDc3LjYgMCAwIDEtMzMuNiAyNy43IDEzNS42IDEzNS42IDAgMCAxLTUzLjQgOS45Yy0zMS42IDAtNTcuMS01LjktNzMuMi0yMS43LTE4LjItMTcuOS0yNS45LTQxLjctMjkuOS02OS4zeiIgY2xhc3M9InN0MSIvPg0KICAgIDxnPg0KICAgICAgPHBhdGggZD0iTTI0OC4xIDU1MC42YzcuOS0yIDE1LjgtNS45IDE5LjgtOS45IDUuOS00IDkuOS0xMy44IDEzLjgtMjMuNyA0LTExLjkgNS45LTI1LjcgNS45LTQ1LjVzLTItMzMuNi01LjktNDMuNWE2OSA2OSAwIDAgMC0xMy44LTIzLjcgNDUuMyA0NS4zIDAgMCAwLTIzLjctMTEuOWMtNy45LTItMTkuOC0yLTQxLjUtMkgxODF2MTYyLjFoMzcuNmMxMy43LjEgMjMuNi4xIDI5LjUtMS45eiIgY2xhc3M9InN0MiIvPg0KICAgICAgPHBhdGggZD0iTTQ3Ni42IDk0OUg4NzBhNzkuMyA3OS4zIDAgMCAwIDc5LjEtNzkuMVY1MTUuMUw3OTMuMSAzNzJhNzkuNSA3OS41IDAgMCAxIDE4LjUgNDguMWwtNDkuNCAyYy0yLTExLjktNS45LTIxLjctMTMuOC0yNy43LTcuOS01LjktMTcuOC03LjktMzEuNi03LjlzLTI1LjcgNC0zMy42IDkuOWMtNS45IDQtNy45IDkuOS03LjkgMTUuOHMyIDExLjkgNy45IDE1LjhjNS45IDUuOSAyMS43IDkuOSA0NS41IDE1LjhzNDEuNSAxMS45IDUzLjQgMTcuOCAyMS43IDEzLjggMjcuNyAyNS43YTc4LjEgNzguMSAwIDAgMSA5LjkgMzkuNWMwIDEzLjgtNCAyNy43LTExLjkgMzkuNWE3Ny42IDc3LjYgMCAwIDEtMzMuNiAyNy43IDEzNS42IDEzNS42IDAgMCAxLTUzLjQgOS45Yy0zMS42IDAtNTcuMS01LjktNzMuMi0yMS43LTE4LTE3LjgtMjUuNy00MS41LTI5LjctNjkuMmw0OS40LTRjMiAxNS44IDcuOSAyNy43IDE3LjggMzUuNmE1NS4yIDU1LjIgMCAwIDAgMzUuNiAxMS45IDU5IDU5IDAgMCAwIDM1LjYtOS45IDMwLjkgMzAuOSAwIDAgMCAxMS45LTIzLjdjMC01LjktMi05LjktNS45LTE1LjgtNC00LTkuOS03LjktMTcuOC05LjktNS45LTItMTkuOC01LjktMzkuNS05LjlhMTU4LjcgMTU4LjcgMCAwIDEtNTcuMy0yMy43IDYyLjcgNjIuNyAwIDAgMS0xOS4zLTcyLjJsLTQ5LjgtNDUuNnYyNDguNGgtNDkuNEw0MjggNDMydjE2Mi4xaC00Ny40VjQ1Mi4zbC01MS40LTQwLjFjNS45IDE1LjggNy45IDM1LjYgNy45IDU5LjMgMCAxOS44LTIgMzcuNi03LjkgNTMuNGExMTQuOSAxMTQuOSAwIDAgMS0yNS43IDQzLjUgNzcgNzcgMCAwIDEtMzUuNiAxOS44Yy0xMS45IDQtMjUuNyA1LjktNDMuNSA1LjloLTk0Ljl2LTYuOWwtLjQgNi45TDQ3Ni42IDk0OXoiIGNsYXNzPSJzdDIiLz4NCiAgICA8L2c+DQogIDwvZz4NCjwvc3ZnPg0K'/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pure-u-2-3">
|
||||
@@ -130,7 +130,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
<div class="block pure-g">
|
||||
<div class="pure-u-1-3">
|
||||
<div class="img-con">
|
||||
<img src="data:image/png;base64,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 truncated
|
||||
<img src='data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbDpzcGFjZT0icHJlc2VydmUiIGlkPSJMYXllcl8xIiB4PSIwIiB5PSIwIiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCA1MTIgNTEyIj48c3R5bGU+LnN0MCwuc3Qxe2ZpbGw6bm9uZTtzdHJva2U6IzI4NGE2YTtzdHJva2Utd2lkdGg6LjI2O3N0cm9rZS1taXRlcmxpbWl0OjEwfS5zdDF7c3Ryb2tlLXdpZHRoOi4xM30uc3Q0e2ZpbGw6IzMzNzhiY30uc3Q1e2ZpbGw6IzE2OWJkNn0uc3Q2e2ZpbGw6IzAwYThkYX08L3N0eWxlPjxwYXRoIGQ9Im0yNTUuOCAxODkuNS01My4yLTYwLjEiIGNsYXNzPSJzdDAiLz48cGF0aCBkPSJtODggMTQzLjMgNDEuNiA2MC44IiBjbGFzcz0ic3QxIi8+PHBhdGggZD0ibTI1NS44IDE4OS42IDUyLjYtNjAuOG0xMSAxMjcuOSA2Mi41LTUyLjZtLTYyLjUgNTIuNSA2Mi41IDU0LjlNMzA5IDM4MWwtNTMuMi01OW0tNTMuMiA1OSA1My4yLTU5bS0xMjYuMS0xMi44IDYwLjEtNTIuNk0xMjkuNyAyMDRsNjAuMSA1Mi42bTY2LTY3LjFMMTI5LjcgMjA0bTEyNi4xLTE0LjVMMzgxLjkgMjA0bS02Mi41IDUyLjYtMTEtMTI3LjhtMTEgMTI3LjhMMzA5IDM4MW03Mi44LTY5LjQtMTI2IDEwLjRtLTEyNi4xLTEyLjhMMjU1LjggMzIybS01My4yIDU5LTEyLjgtMTI0LjNtMTIuOC0xMjcuMy0xMi44IDEyNy4yIiBjbGFzcz0ic3QwIi8+PHBhdGggZD0ibTcxLjkgMjIwLjIgNTcuOC0xNi4ybTEyLjEtMTE4IDYwLjggNDMuNG0xMy45LTcwLjYtMTMuOSA3MC42bTEzLjktNzAuNiA5MS45IDcwbS0xMy45LTcwIDEzLjkgNzBNMzY5LjEgODZsLTYwLjggNDIuOG0xMTUuMiAxNC41LTExNS4xLTE0LjVtNzMuNCA3NS4yIDQxLjYtNjAuOE0zODEuOCAyMDRsNTkgMTYuMm0tNTktMTYuMiA1Ny44IDg3LjlNMjk0LjUgNTguOGwtOTIgNzAuNk0zODEuOCAyMDQgMzY5IDg2bTEyLjggMjI1LjYgNTcuOC0xOS43bS01Ny44IDE5LjcgNTktOTEuNG0tNTkgOTEuNCA0MS42IDU2LjFtLTQxLjYtNTYuMUwzNjkgNDI0LjlNMzA5IDM4MWw2MC4xIDQ0TTMwOSAzODFsMTE0LjUtMTMuM00zMDkgMzgxbC0xMy44IDcxbTEzLjgtNzEtOTIuNSA3MW0tMTMuOS03MSAxMy45IDcxLjJNMjAyLjYgMzgxbDkyLjYgNzFtLTkyLjUtNzEtNjAuOCA0NG02MC44LTQ0TDg4IDM2OC4ybTQxLjctNTktNDEuNyA1OW00MS43LTU5IDEyLjEgMTE1LjdtLTEyLjEtMTE1LjctNTguNC0xNy45bTU4LjQtODcuMy01OC40IDg3LjNtNTguNCAxNy45LTU3LjgtODkuMU0xNDEuOCA4NmwtMTIuMSAxMThNODggMTQzLjNsMTE0LjUtMTMuOSIgY2xhc3M9InN0MSIvPjxwYXRoIGQ9Ik0xNDEuOCA4NiA5Ny4zIDY1LjJNMTQxLjggODZsLTMuNS00OC42bTc4LjIgMjEuNC03OC4xLTIxLjRtNzguMSAyMS40TDE4MyAxNy43bTMzLjUgNDEuMSAxMy45LTQ5LjJNMTQxLjggODZsNDEuMS02OC4ybTExMS42IDQxTDIzMC4zIDkuNm02NC4yIDQ5LjJMMjgwIDcuOW0tNjMuNiA1MC45TDI4MCA3LjltMTQuNSA1MC45TDMyOCAxNy43TTM2OS4xIDg2IDMyOCAxNy44TTM2OS4xIDg2bDQtNDguNm0tNzguNiAyMS40IDc4LjYtMjEuNG0tNCA0OC42IDQ1LjYtMjMuMU0zNjkuMSA4Nmw3OS4yIDEyLjFtLTI0LjggNDUuMiAyNC45LTQ1LjFtLTI0LjkgNDUuMS04LjctODAuNG04LjcgODAuNCA1Mi00bS01MiA0IDcxLjIgNDAuNW0tNTMuOSAzNi40IDM0LjctODFtLTM0LjcgODEgNTMuOC0zNi40bS01My44IDM2LjQgNjAuMSAxMi4xbS02MS4yIDU5LjYgNjEuMy01OS42bS02MS4zIDU5LjYgNjMtMTEuNm0tNjEuOS02MC4xIDYxLjkgNjAuMW0tNjMgMTEuNiA1My44IDM1LjltLTcwIDM5LjggNzAtMzkuOW0tNzAgMzkuOSA1MS41IDUuMm0tMzUuMi04MC45IDM1LjIgODFtLTUxLjQtNS4zIDI0LjMgNDUuNm0tMjQuMy00NS42LTkuMyA3OS44bS0uMS4xLTQ1LjEtMjIuNm0wIDAgMy41IDUwLjRtLTMuNS01MC40IDc4LjYtMTEuNm0tNzguNiAxMS42TDMyOCA0OTQuM00yOTUuMiA0NTJsMzIuOCA0Mi4yTTI5NS4yIDQ1Mmw3Ny41IDIzLjFNMjk1LjIgNDUyIDI4MCA1MDRtMTUuMi01Mi02NC44IDUybS0xMy45LTUyIDEzLjkgNTJtLTEzLjktNTIgNjMuNSA1Mm0tNjMuNS01Mi0zMyA0Mi4ybS00MS43LTY5LjMgNDEuNiA2OS40bTMzLjEtNDIuMy03OC42IDI0LjNtMy45LTUxLjQtNCA1MS41bTQtNTEuNS00NS4xIDI0LjlNODggMzY4LjJsOC43IDgxLjVtNDUuMS0yNC44LTc5LjItMTFNODggMzY4LjJsLTI1LjQgNDUuNk04OCAzNjguMmwtNTIgNS4ybTUyLTUuMi03MS42LTM5LjltNTQuOS0zNy01NC45IDM3bTU0LjktMzctNjIuNS0xMW02Mi41IDExLTM1LjIgODIuMW0zNS44LTE1My4yLTYzIDYwLjFtNjIuNCAxMS02Mi41LTU5bTYzLjEtMTIuMS01My44LTM1LjltNTMuOCAzNS45LTYzIDEyLjFtNjMtMTIuMS0zNS45LTgxbTUyIDQuMS01Mi00bTUyIDQtNjkuOSA0MS4xTTg4IDE0My4zbC0yNC44LTQyLjhNODggMTQzLjNsOS4zLTc4LjFNMTQxLjggODZsLTc4LjcgMTQuNSIgc3R5bGU9ImZpbGw6bm9uZTtzdHJva2UtbWl0ZXJsaW1pdDoxMDtzdHJva2U6IzI0NDA1ZDtzdHJva2Utd2lkdGg6LjEwMSIvPjxwYXRoIGQ9Im0xNTguOSAyODYuNy40LTYwLjggNjAuOC40LS40IDYwLjh6bTY1LjgtNjcgLjQtNjAuOCA2MC44LjQtLjQgNjAuOHptMCAxMzMuNC40LTYwLjggNjAuOC40LS40IDYwLjh6bTY2LjQtNjcgLjQtNjAuOCA2MC44LjQtLjQgNjAuOHoiIHN0eWxlPSJmaWxsOiMyNTZlYTUiLz48cGF0aCBkPSJtMjg3LjYgMTUwIC4zLTQyLjIgNDIuNC4zLS4zIDQyLjJ6bS0xMDYtLjEuMy00Mi4yIDQyLjQuMy0uMyA0Mi4yem0tNzMuNCA3NS4yLjMtNDIuMiA0Mi40LjMtLjMgNDIuMnptMCAxMDYuMS40LTQyLjIgNDIuNC40LS40IDQyLjJ6bTI1Mi44LS44LjMtNDIuMiA0Mi40LjMtLjMgNDIuMnptLjgtMTA1IC40LTQyLjIgNDIuNC40LS40IDQyLjJ6IiBjbGFzcz0ic3Q0Ii8+PHBhdGggZD0ibTczLjkgMTU3IC4yLTI3LjggMjcuNy4yLS4yIDI3Ljh6bTU0LjEtNTYuNS4yLTI3LjggMjcuNy4yLS4yIDI3Ljh6bTc0LjYtMjcuOS4yLTI3LjggMjcuNy4yLS4yIDI3Ljh6TTU3LjUgMjMzLjlsLjItMjcuOCAyNy41LjItLjIgMjcuOHptMzUyLTEwNC4yIDI3LjgtLjIuMiAyNy43LTI3LjguMnptLTU0LjItNTcuNSAyNy44LS4yLjIgMjcuNy0yNy44LjJ6TTI4MC41IDQ1bDI3LjgtLjIuMiAyNy43LTI3LjguMnptMTQ1LjEgMTYxLjUgMjcuOC0uMi4yIDI3LjctMjcuOC4yeiIgY2xhc3M9InN0NSIvPjxwYXRoIGQ9Im0xODEgNDAzLjIuMy00Mi4yIDQyLjQuMy0uMyA0Mi4yem0xMDYgMCAuMy00Mi4yIDQyLjQuMy0uMyA0Mi4yeiIgY2xhc3M9InN0NCIvPjxwYXRoIGQ9Im00MDkuMyAzODEuOC4yLTI3LjggMjcuNy4yLS4yIDI3Ljh6bS01My42IDU3LjEuMi0yNy44IDI3LjcuMi0uMiAyNy44em0tNzQuNSAyNy40LjItMjcuOCAyNy43LjItLjIgMjcuOHpNNDI1LjYgMzA1bC4yLTI3LjggMjcuNy4yLS4yIDI3Ljh6TTczLjkgMzU0LjFsMjcuOC0uMi4yIDI3LjctMjcuOC4yem01NC4yIDU2LjggMjcuOC0uMi4yIDI3LjctMjcuOC4yem03NC4yIDI3LjMgMjcuOC0uMi4yIDI3LjctMjcuOC4yek01Ny44IDI3Ny4zbDI3LjgtLjIuMiAyNy43LTI3LjkuMnoiIGNsYXNzPSJzdDUiLz48cGF0aCBpZD0iQiIgZD0ibTQ2Ny41IDE0Ni43LjEtMTUgMTUuMy4xLS4xIDE1eiIgY2xhc3M9InN0NiIvPjxwYXRoIGlkPSJCXzAwMDAwMDk3NTAxNDU3OTIwNjU5ODgxODMwMDAwMLine truncated
|
||||
</div>
|
||||
</div>
|
||||
<div class="pure-u-2-3">
|
||||
@@ -154,7 +154,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
<div class="block pure-g">
|
||||
<div class="pure-u-1-3">
|
||||
<div class="img-con">
|
||||
<img src="data:image/png;base64,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 truncated
|
||||
<img src="data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgc3R5bGU9ImZsZXg6bm9uZTtsaW5lLWhlaWdodDoxIiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxZW0iIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHRpdGxlPkdvb2dsZTwvdGl0bGU+PHBhdGggZD0iTTIzIDEyLjI0NWMwLS45MDUtLjA3NS0xLjU2NS0uMjM2LTIuMjVoLTEwLjU0djQuMDgzaDYuMTg2Yy0uMTI0IDEuMDE0LS43OTcgMi41NDItMi4yOTQgMy41NjlsLS4wMjEuMTM2IDMuMzMyIDIuNTMuMjMuMDIyQzIxLjc3OSAxOC40MTcgMjMgMTUuNTkzIDIzIDEyLjI0NXoiIGZpbGw9IiM0Mjg1RjQiPjwvcGF0aD48cGF0aCBkPSJNMTIuMjI1IDIzYzMuMDMgMCA1LjU3NC0uOTc4IDcuNDMzLTIuNjY1bC0zLjU0Mi0yLjY4OGMtLjk0OC42NDgtMi4yMiAxLjEtMy44OTEgMS4xYTYuNzQ1IDYuNzQ1IDAgMDEtNi4zODYtNC41NzJsLS4xMzIuMDExLTMuNDY1IDIuNjI4LS4wNDUuMTI0QzQuMDQzIDIwLjUzMSA3LjgzNSAyMyAxMi4yMjUgMjN6IiBmaWxsPSIjMzRBODUzIj48L3BhdGg+PHBhdGggZD0iTTUuODQgMTQuMTc1QTYuNjUgNi42NSAwIDAxNS40NjMgMTJjMC0uNzU4LjEzOC0xLjQ5MS4zNjEtMi4xNzVsLS4wMDYtLjE0Ny0zLjUwOC0yLjY3LS4xMTUuMDU0QTEwLjgzMSAxMC44MzEgMCAwMDEgMTJjMCAxLjc3Mi40MzYgMy40NDcgMS4xOTcgNC45MzhsMy42NDItMi43NjN6IiBmaWxsPSIjRkJCQzA1Ij48L3BhdGg+PHBhdGggZD0iTTEyLjIyNSA1LjI1M2MyLjEwOCAwIDMuNTI5Ljg5MiA0LjM0IDEuNjM4bDMuMTY3LTMuMDMxQzE3Ljc4NyAyLjA4OCAxNS4yNTUgMSAxMi4yMjUgMSA3LjgzNCAxIDQuMDQzIDMuNDY5IDIuMTk3IDcuMDYybDMuNjMgMi43NjNhNi43NyA2Ljc3IDAgMDE2LjM5OC00LjU3MnoiIGZpbGw9IiNFQjQzMzUiPjwvcGF0aD48L3N2Zz4=" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="pure-u-2-3">
|
||||
@@ -166,7 +166,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
<div class="block pure-g">
|
||||
<div class="pure-u-1-3">
|
||||
<div class="img-con">
|
||||
<img src="data:image/png;base64,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 truncated
|
||||
<img src="data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI1MDAiIHZpZXdCb3g9IjAgLTMuMSAyNDkwLjMgMjQ5MyIgd2lkdGg9IjI0OTQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGVsbGlwc2UgY3g9IjEyNDUuMiIgY3k9IjEyNDMuNCIgZmlsbD0iI2ZmZiIgcng9IjEyMTcuNiIgcnk9IjEyNDYuNSIvPjxwYXRoIGQ9Im0xMjQ1LjIgMS42Yy02ODcuNiAwLTEyNDUuMiA1NTcuNC0xMjQ1LjIgMTI0NS4xIDAgNTUwLjIgMzU2LjggMTAxNi45IDg1MS41IDExODEuNSA2Mi4yIDExLjUgODUuMS0yNyA4NS4xLTU5LjkgMC0yOS43LTEuMi0xMjcuOC0xLjctMjMxLjgtMzQ2LjQgNzUuMy00MTkuNS0xNDYuOS00MTkuNS0xNDYuOS01Ni42LTE0My45LTEzOC4zLTE4Mi4yLTEzOC4zLTE4Mi4yLTExMy03Ny4zIDguNS03NS43IDguNS03NS43IDEyNSA4LjggMTkwLjkgMTI4LjMgMTkwLjkgMTI4LjMgMTExLjEgMTkwLjQgMjkxLjMgMTM1LjMgMzYyLjMgMTAzLjUgMTEuMi04MC41IDQzLjQtMTM1LjQgNzkuMS0xNjYuNS0yNzYuNi0zMS41LTU2Ny4zLTEzOC4zLTU2Ny4zLTYxNS40IDAtMTM1LjkgNDguNi0yNDcgMTI4LjMtMzM0LjItMTIuOS0zMS4zLTU1LjUtMTU3LjkgMTIuMS0zMjkuNCAwIDAgMTA0LjYtMzMuNSAzNDIuNSAxMjcuNiA5OS4zLTI3LjYgMjA1LjgtNDEuNCAzMTEuNy00MS45IDEwNS44LjUgMjEyLjQgMTQuMyAzMTEuOSA0MS45IDIzNy43LTE2MS4xIDM0Mi4xLTEyNy42IDM0Mi4xLTEyNy42IDY3LjggMTcxLjUgMjUuMSAyOTguMiAxMi4yIDMyOS41IDc5LjggODcuMiAxMjguMSAxOTguMyAxMjguMSAzMzQuMiAwIDQ3OC4yLTI5MS4zIDU4My42LTU2OC42IDYxNC40IDQ0LjcgMzguNiA4NC41IDExNC40IDg0LjUgMjMwLjYgMCAxNjYuNi0xLjQgMzAwLjctMS40IDM0MS43IDAgMzMuMSAyMi40IDcyIDg1LjUgNTkuNyA0OTQuNS0xNjQuOCA4NTAuOC02MzEuNCA4NTAuOC0xMTgxLjQgMC02ODcuNy01NTcuNS0xMjQ1LjEtMTI0NS4xLTEyNDUuMSIgZmlsbD0iIzVjNmJjMCIvPjwvc3ZnPg==" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="pure-u-2-3">
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=quectel-qmi-wwan
|
||||
PKG_VERSION:=1.2.9
|
||||
PKG_RELEASE:=1
|
||||
|
||||
include $(INCLUDE_DIR)/kernel.mk
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define KernelPackage/usb-net-qmi-wwan-quectel
|
||||
SUBMENU:=USB Support
|
||||
TITLE:=QMI WWAN driver for Quectel modules
|
||||
DEPENDS:=+kmod-usb-net +kmod-usb-wdm
|
||||
FILES:=$(PKG_BUILD_DIR)/qmi_wwan_q.ko
|
||||
AUTOLOAD:=$(call AutoLoad,81,qmi_wwan_q)
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
+$(KERNEL_MAKE) M="$(PKG_BUILD_DIR)" modules
|
||||
endef
|
||||
|
||||
$(eval $(call KernelPackage,usb-net-qmi-wwan-quectel))
|
||||
@@ -1,13 +0,0 @@
|
||||
--- a/qmi_wwan_q.c
|
||||
+++ b/qmi_wwan_q.c
|
||||
@@ -62,9 +62,8 @@ struct rmnet_nss_cb {
|
||||
int (*nss_tx)(struct sk_buff *skb);
|
||||
};
|
||||
static struct rmnet_nss_cb __read_mostly *nss_cb = NULL;
|
||||
-#if defined(CONFIG_PINCTRL_IPQ807x) || defined(CONFIG_PINCTRL_IPQ5018) || defined(CONFIG_PINCTRL_IPQ8074)
|
||||
+#if defined(CONFIG_QCA_NSS_DRV)
|
||||
//#ifdef CONFIG_RMNET_DATA //spf12.x none, not effect for spf11.x
|
||||
-#define CONFIG_QCA_NSS_DRV
|
||||
/* define at qsdk/qca/src/linux-4.4/net/rmnet_data/rmnet_data_main.c */ //for spf11.x
|
||||
/* define at qsdk/qca/src/datarmnet/core/rmnet_config.c */ //for spf12.x
|
||||
/* set at qsdk/qca/src/data-kernel/drivers/rmnet-nss/rmnet_nss.c */
|
||||
@@ -1,44 +0,0 @@
|
||||
--- a/qmi_wwan_q.c
|
||||
+++ b/qmi_wwan_q.c
|
||||
@@ -896,7 +896,7 @@ static void usbnet_bh(unsigned long data
|
||||
struct tasklet_struct *t = &pQmapDev->usbnet_bh;
|
||||
bool use_callback = false;
|
||||
|
||||
-#if (LINUX_VERSION_CODE > KERNEL_VERSION( 5,8,0 )) //c955e329bb9d44fab75cf2116542fcc0de0473c5
|
||||
+#if (LINUX_VERSION_CODE > KERNEL_VERSION( 5,8,0 )) && (LINUX_VERSION_CODE < KERNEL_VERSION( 6,17,0 ))
|
||||
use_callback = t->use_callback;
|
||||
if (use_callback)
|
||||
t->callback(&pQmapDev->mpNetDev->bh);
|
||||
@@ -1368,8 +1368,12 @@ static int qmap_register_device(sQmiWwan
|
||||
#endif
|
||||
priv->agg_skb = NULL;
|
||||
priv->agg_count = 0;
|
||||
+#if LINUX_VERSION_CODE < KERNEL_VERSION(6,18,0)
|
||||
hrtimer_init(&priv->agg_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||
priv->agg_hrtimer.function = rmnet_usb_tx_agg_timer_cb;
|
||||
+#else
|
||||
+ hrtimer_setup(&priv->agg_hrtimer, rmnet_usb_tx_agg_timer_cb, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||
+#endif
|
||||
INIT_WORK(&priv->agg_wq, rmnet_usb_tx_agg_work);
|
||||
ktime_get_ts64(&priv->agg_time);
|
||||
spin_lock_init(&priv->agg_lock);
|
||||
@@ -1472,7 +1476,7 @@ typedef struct {
|
||||
} BRMAC_SETTING;
|
||||
#endif
|
||||
|
||||
-int qma_setting_store(struct device *dev, QMAP_SETTING *qmap_settings, size_t size) {
|
||||
+static int qma_setting_store(struct device *dev, QMAP_SETTING *qmap_settings, size_t size) {
|
||||
struct net_device *netdev = to_net_dev(dev);
|
||||
struct usbnet * usbnetdev = netdev_priv( netdev );
|
||||
struct qmi_wwan_state *info = (void *)&usbnetdev->data;
|
||||
@@ -2266,8 +2270,10 @@ static int qmi_wwan_bind(struct usbnet *
|
||||
}
|
||||
|
||||
if (pQmapDev->use_rmnet_usb && !one_card_mode) {
|
||||
+#if (LINUX_VERSION_CODE < KERNEL_VERSION( 6,17,0 ))
|
||||
pQmapDev->usbnet_bh = dev->bh;
|
||||
tasklet_init(&dev->bh, usbnet_bh, (unsigned long)pQmapDev);
|
||||
+#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
From 85990e155cb684ec6380bcf70f588255ec41dc69 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?=E7=80=AC=E5=90=8D=E7=94=B1=E5=B8=8C?=
|
||||
<wanglei199909210927@gmail.com>
|
||||
Date: Wed, 5 Nov 2025 14:16:56 +0800
|
||||
Subject: [PATCH] qmi_wwan: return correct tx/rx stats in kernel 6.10+ (#130)
|
||||
|
||||
---
|
||||
driver/fibocom_QMI_WWAN/src/qmi_wwan_f.c | 9 ++++++++-
|
||||
driver/quectel_QMI_WWAN/src/qmi_wwan_q.c | 7 +++++++
|
||||
2 files changed, 15 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/qmi_wwan_q.c
|
||||
+++ b/qmi_wwan_q.c
|
||||
@@ -2153,7 +2153,14 @@ static int qmi_wwan_bind(struct usbnet *
|
||||
#endif
|
||||
}
|
||||
if (!_usbnet_get_stats64)
|
||||
+#if (LINUX_VERSION_CODE < KERNEL_VERSION( 6,10,0 ))
|
||||
_usbnet_get_stats64 = dev->net->netdev_ops->ndo_get_stats64;
|
||||
+#else
|
||||
+ /* From kernel 6.10+, usbnet sets pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS (352f5b3282), but removed ndo_get_stats64 (9cb3d523c1) */
|
||||
+ /* Use dev_get_tstats64 to read per-CPU stats when NETDEV_PCPU_STAT_TSTATS was set */
|
||||
+ if (dev->net->pcpu_stat_type == NETDEV_PCPU_STAT_TSTATS)
|
||||
+ _usbnet_get_stats64 = dev_get_tstats64;
|
||||
+#endif
|
||||
dev->net->netdev_ops = &qmi_wwan_netdev_ops;
|
||||
|
||||
ql_net_ethtool_ops = *dev->net->ethtool_ops;
|
||||
@@ -1,16 +0,0 @@
|
||||
--- a/qmi_wwan_q.c
|
||||
+++ b/qmi_wwan_q.c
|
||||
@@ -2563,6 +2563,13 @@ static const struct usb_device_id produc
|
||||
{ QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0800, 4, sdx55) }, /* Quectel RG500 */
|
||||
{ QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0801, 4, sdx55) }, /* Quectel RG520 */
|
||||
{ QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0122, 4, sdx55) }, /* Quectel RG650 */
|
||||
+ { QMI_FIXED_RAWIP_INTF(0x05c6, 0x90d5, 3, sdx55) }, /* Foxconn T99W240T00 */
|
||||
+ { QMI_FIXED_RAWIP_INTF(0x05c6, 0x90db, 2, sdx55) }, /* SIM8200 */
|
||||
+ { QMI_FIXED_RAWIP_INTF(0x02dee, 0x4d22, 5, sdx55) }, /* Meige SRM815 */
|
||||
+ { QMI_FIXED_RAWIP_INTF(0x305a, 0x1421, 3, sdx55) }, /* gm800 */
|
||||
+ { QMI_FIXED_RAWIP_INTF(0x305a, 0x1403, 3, sdx55) }, /* gm800 */
|
||||
+ { QMI_FIXED_RAWIP_INTF(0x05C6, 0x9025, 4, sdx55) },
|
||||
+ { QMI_FIXED_RAWIP_INTF(0x05C6, 0x9091, 2, sdx55) },
|
||||
{ } /* END */
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, products);
|
||||
@@ -1,36 +0,0 @@
|
||||
obj-m += qmi_wwan_q.o
|
||||
|
||||
DIR := $(shell pwd)
|
||||
OUTPUTDIR=/lib/modules/`uname -r`/kernel/drivers/net/usb/
|
||||
|
||||
ifeq ($(ARCH),)
|
||||
ARCH := $(shell uname -m)
|
||||
endif
|
||||
ifeq ($(CROSS_COMPILE),)
|
||||
CROSS_COMPILE :=
|
||||
endif
|
||||
ifeq ($(KDIR),)
|
||||
KDIR := /lib/modules/$(shell uname -r)/build
|
||||
ifeq ($(ARCH),i686)
|
||||
ifeq ($(wildcard $KDIR/arch/$ARCH),)
|
||||
ARCH=i386
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(findstring &,${DIR}),)
|
||||
$(warning "${DIR}")
|
||||
$(warning "current directory contain special char '&' !")
|
||||
$(error "please remove it!")
|
||||
endif
|
||||
|
||||
default:
|
||||
$(MAKE) ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} -C $(KDIR) M=$(DIR) modules
|
||||
|
||||
install: default
|
||||
cp $(DIR)/qmi_wwan_q.ko /lib/modules/$(shell uname -r)/kernel/drivers/net/usb/
|
||||
depmod
|
||||
|
||||
clean:
|
||||
rm -rf *~ .tmp_versions modules.order Module.symvers
|
||||
find . -type f -name "*~" -o -name "*.o" -o -name "*.ko" -o -name "*.cmd" -o -name "*.mod.c" | xargs rm -rf
|
||||
@@ -1,177 +0,0 @@
|
||||
Release Notes
|
||||
|
||||
[V1.2.7]
|
||||
Date: 1/12/2024
|
||||
enhancement:
|
||||
1. support SDX35 platform
|
||||
fix:
|
||||
|
||||
[V1.2.6]
|
||||
Date: 5/25/2023
|
||||
enhancement:
|
||||
1. support Linux 6.1
|
||||
fix:
|
||||
|
||||
[V1.2.5]
|
||||
Date: 5/4/2023
|
||||
enhancement:
|
||||
1. support Linux 5.19
|
||||
2. NSS not effect on SPF12.x and support SFE on 9574
|
||||
fix:
|
||||
|
||||
[V1.2.4]
|
||||
Date: 4/14/2023
|
||||
enhancement:
|
||||
1. support SDX7X platform
|
||||
fix:
|
||||
|
||||
[V1.2.3]
|
||||
Date: 9/20/2022
|
||||
enhancement:
|
||||
1. support 9x07(pid 0x030E) platform
|
||||
fix:
|
||||
|
||||
[V1.2.2]
|
||||
Date: 9/7/2022
|
||||
enhancement:
|
||||
1. Optimization, the network card send queue wakeup is changed from callback to tasklet
|
||||
2. Add the function of returning LAN packets in bridge mode
|
||||
3. support ndo ioctl on kernel>5.14
|
||||
4. Allow setting MTU greater than 1500
|
||||
fix:
|
||||
|
||||
[V1.2.1]
|
||||
Date: 9/26/2021
|
||||
enhancement:
|
||||
1. support IPQ5018's NSS
|
||||
2. use 'qsdk/qca/src/data-kernel/drivers/rmnet-nss/rmnet_nss.c' instead myself rmnet_nss.c
|
||||
and qmi_wwan_q.ko must load after rmnet_nss.ko
|
||||
fix:
|
||||
|
||||
[V1.2.0.25]
|
||||
Date: 9/17/2021
|
||||
enhancement:
|
||||
fix:
|
||||
1. add sdx6x platfrom support
|
||||
|
||||
[V1.2.0.24]
|
||||
Date: 9/6/2021
|
||||
enhancement:
|
||||
fix:
|
||||
1. add BG95 support
|
||||
2. support Linux 5.14.0
|
||||
|
||||
[V1.2.0.23]
|
||||
Date: 3/23/2021
|
||||
enhancement:
|
||||
fix:
|
||||
1. add sdx12 platfrom support
|
||||
|
||||
[V1.2.0.22]
|
||||
Date: 2/5/2021
|
||||
enhancement:
|
||||
fix:
|
||||
1. fix panic (memory-access-after-free) when do modem reboot stress test
|
||||
|
||||
[V1.2.0.21]
|
||||
Date: 2/4/2021
|
||||
enhancement:
|
||||
1. Code refactoring - QMAP and rmnet
|
||||
fix:
|
||||
1. qmap_qmi_wwan_rx_fixup: change skb_dequeue to __skb_dequeue
|
||||
|
||||
[V1.2.0.20]
|
||||
Date: 11/2/2020
|
||||
enhancement:
|
||||
fix:
|
||||
1. LTE-A modems can not obtain IP by DHCP
|
||||
|
||||
[V1.2.0.19]
|
||||
Date: 10/9/2020
|
||||
enhancement:
|
||||
fix:
|
||||
1. X55 can not access internet after usb resume
|
||||
|
||||
[V1.2.0.18]
|
||||
Date: 10/9/2020
|
||||
enhancement:
|
||||
fix:
|
||||
1. X55: rename rmnet_usb0.1 to wwan0_1
|
||||
1.1 if there is '.', openwrt will think it is vlan, and auto create vlan
|
||||
1.2 if there is '.', android will think it is not vaild
|
||||
1.3 if named as rmnet_usb0, and SOC is QCOM, QCOM's netmgr will auto manager it
|
||||
|
||||
[V1.2.0.17]
|
||||
Date: 9/14/2020
|
||||
enhancement:
|
||||
1. Code refactoring - QMAP size and version
|
||||
fix:
|
||||
|
||||
[V1.2.0.16]
|
||||
Date: 9/14/2020
|
||||
enhancement:
|
||||
1. rx_fixup() check if this is enough skb_headroom() to fill ethernet header
|
||||
fix:
|
||||
1. fix "WARNING: suspicious RCU usage"
|
||||
|
||||
[V1.2.0.15]
|
||||
Date: 9/10/2020
|
||||
enhancement:
|
||||
fix:
|
||||
1. fix compile errors on kernel 3.10~3.13
|
||||
|
||||
[V1.2.0.14]
|
||||
Date: 7/24/2020
|
||||
enhancement:
|
||||
fix:
|
||||
1. fix QMAP V5 bug on Big Endian CPU
|
||||
|
||||
[V1.2.0.13]
|
||||
Date: 6/22/2020
|
||||
enhancement:
|
||||
fix:
|
||||
1. fix no data traffic when do Upload TPUT test
|
||||
|
||||
[V1.2.0.12]
|
||||
Date: 5/29/2020
|
||||
enhancement:
|
||||
fix:
|
||||
1. IPQ8074: when enable hyfi, quectel-CM will crash system crash
|
||||
|
||||
[V1.2.0.9]
|
||||
Date: 5/13/2020
|
||||
enhancement:
|
||||
fix:
|
||||
1. IPQ8074: enable CONFIG_QCA_NSS_DRV by CONFIG_PINCTRL_IPQ807x (from CONFIG_ARCH_IPQ807x)
|
||||
|
||||
[V1.2.0.8]
|
||||
Date: 5/9/2020
|
||||
enhancement:
|
||||
fix:
|
||||
1. fix compile errors on kernel V3.10
|
||||
|
||||
[V1.2.0.7]
|
||||
Date: 4/25/2020
|
||||
enhancement:
|
||||
1. X55 support bridge mode
|
||||
fix:
|
||||
|
||||
[V1.2.0.6]
|
||||
Date: 4/20/2020
|
||||
enhancement:
|
||||
1. add stat64, or the rx/tx statics will become to 0 when data > 4G
|
||||
2. do not use skb_clone, will make QCOM's NSS and SFE 's cpu loading very high
|
||||
fix:
|
||||
|
||||
[V1.2.0.5]
|
||||
Date: 4/8/2020
|
||||
enhancement:
|
||||
1. add attrite link_state, change carrier state accoring link_state
|
||||
quectel-CM will set link_state to 1 when QMI setup call success.
|
||||
fix:
|
||||
|
||||
[V1.2.0.4]
|
||||
Date: 4/8/2020
|
||||
enhancement:
|
||||
1. support X55's QMAP V5
|
||||
fix:
|
||||
@@ -1,68 +0,0 @@
|
||||
1. Enable QUECTEL_BRIDGE_MODE in qmi_wwan_q.c
|
||||
|
||||
2. Guide to use ....
|
||||
Welcome to Buildroot for the Orange Pi Zero
|
||||
OrangePi_Zero login: root
|
||||
# insmod qmi_wwan_q.ko
|
||||
[ 90.591841] qmi_wwan_q 3-1:1.4: cdc-wdm0: USB WDM device
|
||||
[ 90.597185] qmi_wwan_q 3-1:1.4: Quectel EC25&EC21&EG91&EG95&EG06&EP06&EM06&EG12&EP12&EM12&EG16&EG18&BG96&AG35 work on RawIP mode
|
||||
[ 90.610176] qmi_wwan_q 3-1:1.4: rx_urb_size = 32768
|
||||
[ 90.620589] qmi_wwan_q 3-1:1.4 wwan0: register 'qmi_wwan_q' at usb-1c1b000.usb-1, WWAN/QMI device, 96:42:59:a9:f5:e4
|
||||
[ 90.631293] usbcore: registered new interface driver qmi_wwan_q
|
||||
# brctl addbr br0
|
||||
# brctl addif br0 eth0
|
||||
[ 100.413071] br0: port 1(eth0) entered blocking state
|
||||
[ 100.418081] br0: port 1(eth0) entered disabled state
|
||||
[ 100.423356] device eth0 entered promiscuous mode
|
||||
# brctl addif br0 wwan0
|
||||
[ 102.696724] br0: port 2(wwan0) entered blocking state
|
||||
[ 102.701823] br0: port 2(wwan0) entered disabled state
|
||||
[ 102.707182] device wwan0 entered promiscuous mode
|
||||
# ifconfig br0 up
|
||||
[ 110.405561] br0: port 1(eth0) entered blocking state
|
||||
[ 110.410567] br0: port 1(eth0) entered forwarding state
|
||||
# brctl show
|
||||
bridge name bridge id STP enabled interfaces
|
||||
br0 8000.0242b22e80d8 no eth0
|
||||
wwan0
|
||||
# ./quectel-CM &
|
||||
# [01-01_06:37:02:386] Quectel_QConnectManager_Linux_V1.4.3
|
||||
[01-01_06:37:02:388] Find /sys/bus/usb/devices/3-1 idVendor=0x2c7c idProduct=0x512
|
||||
[01-01_06:37:02:388] Auto find qmichannel = /dev/cdc-wdm0
|
||||
[01-01_06:37:02:388] Auto find usbnet_adapter = wwan0
|
||||
[01-01_06:37:02:389] qmap_mode = 1, muxid = 0x81, qmap_netcard = wwan0
|
||||
[01-01_06:37:02:389] Modem works in QMI mode
|
||||
[01-01_06:37:02:389] qmap_mode = 1, muxid = 0x81, qmap_netcard = wwan0
|
||||
[01-01_06:37:02:394] cdc_wdm_fd = 7
|
||||
[01-01_06:37:02:561] Get clientWDS = 18
|
||||
[01-01_06:37:02:633] Get clientDMS = 1
|
||||
[01-01_06:37:02:689] Get clientNAS = 2
|
||||
[01-01_06:37:02:753] Get clientUIM = 1
|
||||
[01-01_06:37:02:817] Get clientWDA = 1
|
||||
[01-01_06:37:02:881] requestBaseBandVersion EM12GBATE1127
|
||||
[01-01_06:37:02:945] qmap_settings.rx_urb_size = 16384
|
||||
[01-01_06:37:03:201] requestGetSIMStatus SIMStatus: SIM_READY
|
||||
[01-01_06:37:03:265] requestGetProfile[1] ctnet///0
|
||||
[01-01_06:37:03:329] requestRegistrationState2 MCC: 460, MNC: 11, PS: Attached, DataCap: LTE
|
||||
[01-01_06:37:03:393] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED
|
||||
[01-01_06:37:03:457] requestSetupDataCall WdsConnectionIPv4Handle: 0x192a5ed0
|
||||
[01-01_06:37:03:717] ifconfig wwan0 up
|
||||
[01-01_06:37:03:747] echo '0x64b69855' > /sys/module/qmi_wwan_q/parameters/bridge_ipv4
|
||||
|
||||
[ 117.030116] net wwan0: link_state 0x0 -> 0x1
|
||||
[ 117.041259] br0: port 2(wwan0) entered blocking state
|
||||
[ 117.046326] br0: port 2(wwan0) entered forwarding state
|
||||
[ 117.336688] net wwan0: sip = 100.182.152.85, tip=100.182.152.86, ipv4=100.182.152.85
|
||||
[ 121.612281] random: crng init done
|
||||
[ 128.143645] net wwan0: PC Mac Address: 5e:6b:82:fa:ab:c3
|
||||
[ 128.151936] net wwan0: rx_pkts=1, rx_len=312
|
||||
[ 128.203578] net wwan0: PC Mac Address: 5e:6b:82:fa:ab:c3
|
||||
[ 131.012891] net wwan0: sip = 100.182.152.85, tip=100.182.152.86, ipv4=100.182.152.85
|
||||
[ 131.341780] net wwan0: rx_pkts=1, rx_len=316
|
||||
[ 131.434642] net wwan0: rx_pkts=1, rx_len=1404
|
||||
[ 131.439416] net wwan0: rx_pkts=3, rx_len=4212
|
||||
[ 131.512782] net wwan0: rx_pkts=4, rx_len=5616
|
||||
[ 131.535345] net wwan0: rx_pkts=7, rx_len=9828
|
||||
[ 133.778699] net wwan0: rx_pkts=8, rx_len=11232
|
||||
[ 134.143941] net wwan0: rx_pkts=9, rx_len=12636
|
||||
[ 140.053957] net wwan0: rx_pkts=11, rx_len=15444
|
||||
@@ -1,234 +0,0 @@
|
||||
1. Enable QUECTEL_BRIDGE_MODE in qmi_wwan_q.c
|
||||
|
||||
2. set qmap_mode to 4
|
||||
|
||||
3. if you want add wwan0.2 to br2, wwan0.3 to br3
|
||||
set bridge_mode to BIT(1)|BIT(2)
|
||||
|
||||
4. Guide to use ....
|
||||
# insmod qmi_wwan_q.ko qmap_mode=4 bridge_mode=6
|
||||
[243467.331669] qmi_wwan_q 3-1:1.4: cdc-wdm0: USB WDM device
|
||||
[243467.337136] qmi_wwan_q 3-1:1.4: Quectel EC25&EC21&EG91&EG95&EG06&EP06&EM06&EG12&EP12&EM12&EG16&EG18&BG96&AG35 work on RawIP mode
|
||||
[243467.349471] qmi_wwan_q 3-1:1.4: rx_urb_size = 32768
|
||||
[243467.364803] qmi_wwan_q 3-1:1.4 wwan0: register 'qmi_wwan_q' at usb-1c1b000.usb-1, WWAN/QMI device, 96:42:59:a9:f5:e4
|
||||
[243467.376025] net wwan0: qmap_register_device wwan0.1
|
||||
[243467.381658] net wwan0: qmap_register_device wwan0.2
|
||||
[243467.387281] net wwan0: qmap_register_device wwan0.3
|
||||
[243467.392851] net wwan0: qmap_register_device wwan0.4
|
||||
[243467.398106] usbcore: registered new interface driver qmi_wwan_q
|
||||
|
||||
# cat /sys/class/net/wwan0.2/bridge_mode
|
||||
1
|
||||
|
||||
# cat /sys/class/net/wwan0.3/bridge_mode
|
||||
1
|
||||
|
||||
# brctl addbr br2
|
||||
# brctl addif br2 wwan0.2
|
||||
[243492.518563] br2: port 1(wwan0.2) entered blocking state
|
||||
[243492.523888] br2: port 1(wwan0.2) entered disabled state
|
||||
[243492.535948] device wwan0.2 entered promiscuous mode
|
||||
|
||||
# brctl addbr br3
|
||||
# brctl addif br3 wwan0.3
|
||||
[243507.486717] br3: port 1(wwan0.3) entered blocking state
|
||||
[243507.492248] br3: port 1(wwan0.3) entered disabled state
|
||||
[243507.497982] device wwan0.3 entered promiscuous mode
|
||||
|
||||
# brctl show
|
||||
bridge name bridge id STP enabled interfaces
|
||||
br2 8000.964259a9f5e4 no wwan0.2
|
||||
br3 8000.964259a9f5e4 no wwan0.3
|
||||
|
||||
# ./quectel-qmi-proxy &
|
||||
# Find /sys/bus/usb/devices/3-1 idVendor=2c7c idProduct=0512
|
||||
Find /sys/bus/usb/devices/3-1:1.4/usbmisc/cdc-wdm0
|
||||
Will use cdc-wdm /dev/cdc-wdm0
|
||||
qmi_proxy_init enter
|
||||
qmi_proxy_loop enter
|
||||
link_prot 2
|
||||
ul_data_aggregation_protocol 5
|
||||
dl_data_aggregation_protocol 5
|
||||
dl_data_aggregation_max_datagrams 32
|
||||
dl_data_aggregation_max_size 16384
|
||||
ul_data_aggregation_max_datagrams 16
|
||||
ul_data_aggregation_max_size 3072
|
||||
qmi_proxy_init finished, rx_urb_size is 16384
|
||||
local server: quectel-qmi-proxy sockfd = 4
|
||||
qmi_start_server: qmi_proxy_server_fd = 4
|
||||
|
||||
# ./quectel-CM -n 2 &
|
||||
# [01-04_02:13:53:053] Quectel_QConnectManager_Linux_V1.4.3
|
||||
[01-04_02:13:53:056] Find /sys/bus/usb/devices/3-1 idVendor=0x2c7c idProduct=0x512
|
||||
[01-04_02:13:53:056] Auto find qmichannel = /dev/cdc-wdm0
|
||||
[01-04_02:13:53:056] Auto find usbnet_adapter = wwan0
|
||||
[01-04_02:13:53:056] qmap_mode = 4, muxid = 0x82, qmap_netcard = wwan0.2
|
||||
[01-04_02:13:53:057] Modem works in QMI mode
|
||||
[01-04_02:13:53:057] qmap_mode = 4, muxid = 0x82, qmap_netcard = wwan0.2
|
||||
+++ ClientFd=5
|
||||
[01-04_02:13:53:058] connect to quectel-qmi-proxy sockfd = 7
|
||||
|
||||
[01-04_02:13:53:058] cdc_wdm_fd = 7
|
||||
+++ ClientFd=5 QMIType=1 ClientId=18
|
||||
[01-04_02:13:53:130] Get clientWDS = 18
|
||||
+++ ClientFd=5 QMIType=2 ClientId=1
|
||||
[01-04_02:13:53:194] Get clientDMS = 1
|
||||
+++ ClientFd=5 QMIType=3 ClientId=2
|
||||
[01-04_02:13:53:258] Get clientNAS = 2
|
||||
+++ ClientFd=5 QMIType=11 ClientId=2
|
||||
[01-04_02:13:53:333] Get clientUIM = 2
|
||||
[01-04_02:13:53:386] requestBaseBandVersion EM12GBATE1127
|
||||
[01-04_02:13:53:642] requestGetSIMStatus SIMStatus: SIM_READY
|
||||
[01-04_02:13:53:706] requestGetProfile[2] IMS///0
|
||||
[01-04_02:13:53:770] requestRegistrationState2 MCC: 460, MNC: 11, PS: Attached, DataCap: LTE
|
||||
[01-04_02:13:53:841] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED
|
||||
[01-04_02:13:54:058] requestSetupDataCall WdsConnectionIPv4Handle: 0x78a3aba0
|
||||
[243527.630628] net wwan0: link_state 0x0 -> 0x2
|
||||
[01-04_02:13:54:319] ifconfig wwan0 up
|
||||
[01-04_02:13:54:325] ifconfig wwan0.2 up
|
||||
[01-04_02:13:54:330] echo '0x645026c8' > /sys/class/net/wwan0.2/bridge_ipv4
|
||||
|
||||
# udhcpc -i br2
|
||||
udhcpc: started, v1.29.3
|
||||
[243532.653027] br2: port 1(wwan0.2) entered blocking state
|
||||
[243532.658384] br2: port 1(wwan0.2) entered forwarding state
|
||||
udhcpc: sending discover
|
||||
[243532.784337] wwan0.2 PC Mac Address: 96:42:59:a9:f5:e4
|
||||
[243532.794813] net wwan0: rx_pkts=1, rx_len=312
|
||||
udhcpc: sending select for 100.80.38.200
|
||||
[243532.894325] wwan0.2 PC Mac Address: 96:42:59:a9:f5:e4
|
||||
udhcpc: lease of 100.80.38.200 obtained, lease time 7200
|
||||
deleting routers
|
||||
adding dns 202.102.213.68
|
||||
adding dns 61.132.163.68
|
||||
|
||||
|
||||
# ./quectel-CM -n 3 &
|
||||
# [01-04_02:14:03:645] Quectel_QConnectManager_Linux_V1.4.3
|
||||
[01-04_02:14:03:648] Find /sys/bus/usb/devices/3-1 idVendor=0x2c7c idProduct=0x512
|
||||
[01-04_02:14:03:648] Auto find qmichannel = /dev/cdc-wdm0
|
||||
[01-04_02:14:03:648] Auto find usbnet_adapter = wwan0
|
||||
[01-04_02:14:03:649] qmap_mode = 4, muxid = 0x83, qmap_netcard = wwan0.3
|
||||
[01-04_02:14:03:649] Modem works in QMI mode
|
||||
[01-04_02:14:03:649] qmap_mode = 4, muxid = 0x83, qmap_netcard = wwan0.3
|
||||
[01-04_02:14:03:650] connect to quectel-qmi-proxy sockfd = 7
|
||||
|
||||
+++ ClientFd=6
|
||||
[01-04_02:14:03:650] cdc_wdm_fd = 7
|
||||
+++ ClientFd=6 QMIType=1 ClientId=19
|
||||
[01-04_02:14:03:722] Get clientWDS = 19
|
||||
+++ ClientFd=6 QMIType=2 ClientId=2
|
||||
[01-04_02:14:03:786] Get clientDMS = 2
|
||||
+++ ClientFd=6 QMIType=3 ClientId=3
|
||||
[01-04_02:14:03:850] Get clientNAS = 3
|
||||
+++ ClientFd=6 QMIType=11 ClientId=3
|
||||
[01-04_02:14:03:914] Get clientUIM = 3
|
||||
[01-04_02:14:03:978] requestBaseBandVersion EM12GBATE1127
|
||||
[01-04_02:14:04:235] requestGetSIMStatus SIMStatus: SIM_READY
|
||||
[01-04_02:14:04:298] requestGetProfile[3] lte///0
|
||||
[01-04_02:14:04:362] requestRegistrationState2 MCC: 460, MNC: 11, PS: Attached, DataCap: LTE
|
||||
[01-04_02:14:04:426] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED
|
||||
[01-04_02:14:04:555] requestSetupDataCall WdsConnectionIPv4Handle: 0x78a5c850
|
||||
[243538.126755] net wwan0: link_state 0x2 -> 0x6
|
||||
[01-04_02:14:04:815] ifconfig wwan0 up
|
||||
[01-04_02:14:04:824] ifconfig wwan0.3 up
|
||||
[01-04_02:14:04:829] echo '0x64548ae0' > /sys/class/net/wwan0.3/bridge_ipv4
|
||||
|
||||
# udhcpc -i br3
|
||||
udhcpc: started, v1.29.3
|
||||
[243541.850178] br3: port 1(wwan0.3) entered blocking state
|
||||
[243541.855509] br3: port 1(wwan0.3) entered forwarding state
|
||||
udhcpc: sending discover
|
||||
[243541.976693] wwan0.3 PC Mac Address: 96:42:59:a9:f5:e4
|
||||
udhcpc: sending select for 100.84.138.224
|
||||
[243542.056668] wwan0.3 PC Mac Address: 96:42:59:a9:f5:e4
|
||||
udhcpc: lease of 100.84.138.224 obtained, lease time 7200
|
||||
deleting routers
|
||||
adding dns 202.102.213.68
|
||||
adding dns 61.132.163.68
|
||||
|
||||
# ./quectel-CM -n 1 &
|
||||
# [01-04_02:14:12:742] Quectel_QConnectManager_Linux_V1.4.3
|
||||
[01-04_02:14:12:744] Find /sys/bus/usb/devices/3-1 idVendor=0x2c7c idProduct=0x512
|
||||
[01-04_02:14:12:745] Auto find qmichannel = /dev/cdc-wdm0
|
||||
[01-04_02:14:12:745] Auto find usbnet_adapter = wwan0
|
||||
[01-04_02:14:12:745] qmap_mode = 4, muxid = 0x81, qmap_netcard = wwan0.1
|
||||
[01-04_02:14:12:745] Modem works in QMI mode
|
||||
[01-04_02:14:12:746] qmap_mode = 4, muxid = 0x81, qmap_netcard = wwan0.1
|
||||
[01-04_02:14:12:746] connect to quectel-qmi-proxy sockfd = 7
|
||||
|
||||
+++ ClientFd=7
|
||||
[01-04_02:14:12:746] cdc_wdm_fd = 7
|
||||
+++ ClientFd=7 QMIType=1 ClientId=20
|
||||
[01-04_02:14:12:842] Get clientWDS = 20
|
||||
+++ ClientFd=7 QMIType=2 ClientId=3
|
||||
[01-04_02:14:12:906] Get clientDMS = 3
|
||||
+++ ClientFd=7 QMIType=3 ClientId=4
|
||||
[01-04_02:14:12:970] Get clientNAS = 4
|
||||
+++ ClientFd=7 QMIType=11 ClientId=4
|
||||
[01-04_02:14:13:034] Get clientUIM = 4
|
||||
[01-04_02:14:13:098] requestBaseBandVersion EM12GBATE1127
|
||||
[01-04_02:14:13:354] requestGetSIMStatus SIMStatus: SIM_READY
|
||||
[01-04_02:14:13:418] requestGetProfile[1] ctnet///0
|
||||
[01-04_02:14:13:483] requestRegistrationState2 MCC: 460, MNC: 11, PS: Attached, DataCap: LTE
|
||||
[01-04_02:14:13:546] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED
|
||||
[01-04_02:14:13:610] requestSetupDataCall WdsConnectionIPv4Handle: 0x78a92b30
|
||||
[243547.182801] net wwan0: link_state 0x6 -> 0x7
|
||||
[01-04_02:14:13:874] ifconfig wwan0 up
|
||||
[01-04_02:14:13:880] ifconfig wwan0.1 up
|
||||
[01-04_02:14:13:885] busybox udhcpc -f -n -q -t 5 -i wwan0.1
|
||||
udhcpc: started, v1.29.3
|
||||
udhcpc: sending discover
|
||||
udhcpc: sending select for 10.175.212.85
|
||||
udhcpc: lease of 10.175.212.85 obtained, lease time 7200
|
||||
[01-04_02:14:14:175] deleting routers
|
||||
[01-04_02:14:14:194] adding dns 202.102.213.68
|
||||
[01-04_02:14:14:195] adding dns 61.132.163.68
|
||||
|
||||
# ifconfig
|
||||
|
||||
br2 Link encap:Ethernet HWaddr 96:42:59:A9:F5:E4
|
||||
inet addr:100.80.38.200 Bcast:100.80.38.207 Mask:255.255.255.240
|
||||
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
|
||||
RX packets:2 errors:0 dropped:0 overruns:0 frame:0
|
||||
TX packets:2 errors:0 dropped:0 overruns:0 carrier:0
|
||||
collisions:0 txqueuelen:1000
|
||||
RX bytes:612 (612.0 B) TX bytes:684 (684.0 B)
|
||||
|
||||
br3 Link encap:Ethernet HWaddr 96:42:59:A9:F5:E4
|
||||
inet addr:100.84.138.224 Bcast:100.84.138.255 Mask:255.255.255.192
|
||||
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
|
||||
RX packets:2 errors:0 dropped:0 overruns:0 frame:0
|
||||
TX packets:2 errors:0 dropped:0 overruns:0 carrier:0
|
||||
collisions:0 txqueuelen:1000
|
||||
RX bytes:612 (612.0 B) TX bytes:684 (684.0 B)
|
||||
|
||||
|
||||
wwan0 Link encap:Ethernet HWaddr 96:42:59:A9:F5:E4
|
||||
UP BROADCAST RUNNING NOARP MULTICAST MTU:1500 Metric:1
|
||||
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
|
||||
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
|
||||
collisions:0 txqueuelen:1000
|
||||
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
|
||||
|
||||
wwan0.1 Link encap:Ethernet HWaddr 96:42:59:A9:F5:E4
|
||||
inet addr:10.175.212.85 Bcast:10.175.212.87 Mask:255.255.255.252
|
||||
UP BROADCAST RUNNING NOARP MULTICAST MTU:1500 Metric:1
|
||||
RX packets:2 errors:0 dropped:0 overruns:0 frame:0
|
||||
TX packets:2 errors:0 dropped:0 overruns:0 carrier:0
|
||||
collisions:0 txqueuelen:1000
|
||||
RX bytes:612 (612.0 B) TX bytes:664 (664.0 B)
|
||||
|
||||
wwan0.2 Link encap:Ethernet HWaddr 96:42:59:A9:F5:E4
|
||||
UP BROADCAST RUNNING NOARP MULTICAST MTU:1500 Metric:1
|
||||
RX packets:2 errors:0 dropped:0 overruns:0 frame:0
|
||||
TX packets:2 errors:0 dropped:0 overruns:0 carrier:0
|
||||
collisions:0 txqueuelen:1000
|
||||
RX bytes:612 (612.0 B) TX bytes:664 (664.0 B)
|
||||
|
||||
wwan0.3 Link encap:Ethernet HWaddr 96:42:59:A9:F5:E4
|
||||
UP BROADCAST RUNNING NOARP MULTICAST MTU:1500 Metric:1
|
||||
RX packets:2 errors:0 dropped:0 overruns:0 frame:0
|
||||
TX packets:2 errors:0 dropped:0 overruns:0 carrier:0
|
||||
collisions:0 txqueuelen:1000
|
||||
RX bytes:612 (612.0 B) TX bytes:664 (664.0 B)
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,428 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2023, The Linux Foundation. All rights reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/ormodify it under the terms of the GNU General
|
||||
Public licenseas published byFree Software Foundation; either version 2theof the License,(at your option)
|
||||
any later version.O1
|
||||
This program isdistributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the
|
||||
implied warranty ofOr FITNESS FOR A PARTICULAR PURPOSE.MERCHANTABILITYSee theGNU General Public License
|
||||
for more details.
|
||||
You should have received a copy of the GNU General Public licensealong withthis program; if not, write to
|
||||
the Free SoftwareFoundation, Inc.r51 Franklin Street,Fifth Floor,Boston,MA 02110-1301,USA.
|
||||
|
||||
Based on version modification, the author is Quectel <fae-support@quectel.com>
|
||||
*/
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/hashtable.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/ip.h>
|
||||
#include <qca-nss-drv/nss_api_if.h>
|
||||
|
||||
#include <linux/rmnet_nss.h>
|
||||
|
||||
#define RMNET_NSS_HASH_BITS 8
|
||||
#define hash_add_ptr(table, node, key) \
|
||||
hlist_add_head(node, &table[hash_ptr(key, HASH_BITS(table))])
|
||||
|
||||
static DEFINE_HASHTABLE(rmnet_nss_ctx_hashtable, RMNET_NSS_HASH_BITS);
|
||||
|
||||
struct rmnet_nss_ctx {
|
||||
struct hlist_node hnode;
|
||||
struct net_device *rmnet_dev;
|
||||
struct nss_rmnet_rx_handle *nss_ctx;
|
||||
};
|
||||
|
||||
enum __rmnet_nss_stat {
|
||||
RMNET_NSS_RX_ETH,
|
||||
RMNET_NSS_RX_FAIL,
|
||||
RMNET_NSS_RX_NON_ETH,
|
||||
RMNET_NSS_RX_BUSY,
|
||||
RMNET_NSS_TX_NO_CTX,
|
||||
RMNET_NSS_TX_SUCCESS,
|
||||
RMNET_NSS_TX_FAIL,
|
||||
RMNET_NSS_TX_NONLINEAR,
|
||||
RMNET_NSS_TX_BAD_IP,
|
||||
RMNET_NSS_EXCEPTIONS,
|
||||
RMNET_NSS_EX_BAD_HDR,
|
||||
RMNET_NSS_EX_BAD_IP,
|
||||
RMNET_NSS_EX_SUCCESS,
|
||||
RMNET_NSS_TX_BAD_FRAGS,
|
||||
RMNET_NSS_TX_LINEARIZE_FAILS,
|
||||
RMNET_NSS_TX_NON_ZERO_HEADLEN_FRAGS,
|
||||
RMNET_NSS_TX_BUSY_LOOP,
|
||||
RMNET_NSS_NUM_STATS,
|
||||
};
|
||||
|
||||
static unsigned long rmnet_nss_stats[RMNET_NSS_NUM_STATS];
|
||||
|
||||
#define RMNET_NSS_STAT(name, counter, desc) \
|
||||
module_param_named(name, rmnet_nss_stats[counter], ulong, 0444); \
|
||||
MODULE_PARM_DESC(name, desc)
|
||||
|
||||
RMNET_NSS_STAT(rmnet_nss_rx_ethernet, RMNET_NSS_RX_ETH,
|
||||
"Number of Ethernet headers successfully removed");
|
||||
RMNET_NSS_STAT(rmnet_nss_rx_fail, RMNET_NSS_RX_FAIL,
|
||||
"Number of Ethernet headers that could not be removed");
|
||||
RMNET_NSS_STAT(rmnet_nss_rx_non_ethernet, RMNET_NSS_RX_NON_ETH,
|
||||
"Number of non-Ethernet packets received");
|
||||
RMNET_NSS_STAT(rmnet_nss_rx_busy, RMNET_NSS_RX_BUSY,
|
||||
"Number of packets dropped decause rmnet_data device was busy");
|
||||
RMNET_NSS_STAT(rmnet_nss_tx_slow, RMNET_NSS_TX_NO_CTX,
|
||||
"Number of packets sent over non-NSS-accelerated rmnet device");
|
||||
RMNET_NSS_STAT(rmnet_nss_tx_fast, RMNET_NSS_TX_SUCCESS,
|
||||
"Number of packets sent over NSS-accelerated rmnet device");
|
||||
RMNET_NSS_STAT(rmnet_nss_tx_fail, RMNET_NSS_TX_FAIL,
|
||||
"Number of packets that NSS could not transmit");
|
||||
RMNET_NSS_STAT(rmnet_nss_tx_nonlinear, RMNET_NSS_TX_NONLINEAR,
|
||||
"Number of non linear sent over NSS-accelerated rmnet device");
|
||||
RMNET_NSS_STAT(rmnet_nss_tx_invalid_ip, RMNET_NSS_TX_BAD_IP,
|
||||
"Number of ingress packets with invalid IP headers");
|
||||
RMNET_NSS_STAT(rmnet_nss_tx_invalid_frags, RMNET_NSS_TX_BAD_FRAGS,
|
||||
"Number of ingress packets with invalid frag format");
|
||||
RMNET_NSS_STAT(rmnet_nss_tx_linearize_fail, RMNET_NSS_TX_LINEARIZE_FAILS,
|
||||
"Number of ingress packets where linearize in tx fails");
|
||||
RMNET_NSS_STAT(rmnet_nss_tx_exceptions, RMNET_NSS_EXCEPTIONS,
|
||||
"Number of times our DL exception handler was invoked");
|
||||
RMNET_NSS_STAT(rmnet_nss_exception_non_ethernet, RMNET_NSS_EX_BAD_HDR,
|
||||
"Number of non-Ethernet exception packets");
|
||||
RMNET_NSS_STAT(rmnet_nss_exception_invalid_ip, RMNET_NSS_EX_BAD_IP,
|
||||
"Number of exception packets with invalid IP headers");
|
||||
RMNET_NSS_STAT(rmnet_nss_exception_success, RMNET_NSS_EX_SUCCESS,
|
||||
"Number of exception packets handled successfully");
|
||||
RMNET_NSS_STAT(rmnet_nss_tx_non_zero_headlen_frags, RMNET_NSS_TX_NON_ZERO_HEADLEN_FRAGS,
|
||||
"Number of packets with non zero headlen");
|
||||
RMNET_NSS_STAT(rmnet_nss_tx_busy_loop, RMNET_NSS_TX_BUSY_LOOP,
|
||||
"Number of times tx packets busy looped");
|
||||
|
||||
static void rmnet_nss_inc_stat(enum __rmnet_nss_stat stat)
|
||||
{
|
||||
if (stat >= 0 && stat < RMNET_NSS_NUM_STATS)
|
||||
rmnet_nss_stats[stat]++;
|
||||
}
|
||||
|
||||
static struct rmnet_nss_ctx *rmnet_nss_find_ctx(struct net_device *dev)
|
||||
{
|
||||
struct rmnet_nss_ctx *ctx;
|
||||
struct hlist_head *bucket;
|
||||
u32 hash;
|
||||
|
||||
hash = hash_ptr(dev, HASH_BITS(rmnet_nss_ctx_hashtable));
|
||||
bucket = &rmnet_nss_ctx_hashtable[hash];
|
||||
hlist_for_each_entry(ctx, bucket, hnode) {
|
||||
if (ctx->rmnet_dev == dev)
|
||||
return ctx;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void rmnet_nss_free_ctx(struct rmnet_nss_ctx *ctx)
|
||||
{
|
||||
if (ctx) {
|
||||
hash_del(&ctx->hnode);
|
||||
nss_rmnet_rx_xmit_callback_unregister(ctx->nss_ctx);
|
||||
nss_rmnet_rx_destroy_sync(ctx->nss_ctx);
|
||||
kfree(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/* Pull off an ethernet header, if possible */
|
||||
static int rmnet_nss_ethhdr_pull(struct sk_buff *skb)
|
||||
{
|
||||
if (!skb->protocol || skb->protocol == htons(ETH_P_802_3)) {
|
||||
void *ret = skb_pull(skb, sizeof(struct ethhdr));
|
||||
|
||||
rmnet_nss_inc_stat((ret) ? RMNET_NSS_RX_ETH :
|
||||
RMNET_NSS_RX_FAIL);
|
||||
return !ret;
|
||||
}
|
||||
|
||||
rmnet_nss_inc_stat(RMNET_NSS_RX_NON_ETH);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Copy headers to linear section for non linear packets */
|
||||
static int rmnet_nss_adjust_header(struct sk_buff *skb)
|
||||
{
|
||||
struct iphdr *iph;
|
||||
skb_frag_t *frag;
|
||||
int bytes = 0;
|
||||
u8 transport;
|
||||
|
||||
if (skb_shinfo(skb)->nr_frags != 1) {
|
||||
rmnet_nss_inc_stat(RMNET_NSS_TX_BAD_FRAGS);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (skb_headlen(skb)) {
|
||||
rmnet_nss_inc_stat(RMNET_NSS_TX_NON_ZERO_HEADLEN_FRAGS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
frag = &skb_shinfo(skb)->frags[0];
|
||||
|
||||
iph = (struct iphdr *)(skb_frag_address(frag));
|
||||
|
||||
if (iph->version == 4) {
|
||||
bytes = iph->ihl*4;
|
||||
transport = iph->protocol;
|
||||
} else if (iph->version == 6) {
|
||||
struct ipv6hdr *ip6h = (struct ipv6hdr *)iph;
|
||||
|
||||
bytes = sizeof(struct ipv6hdr);
|
||||
/* Dont have to account for extension headers yet */
|
||||
transport = ip6h->nexthdr;
|
||||
} else {
|
||||
rmnet_nss_inc_stat(RMNET_NSS_TX_BAD_IP);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (transport == IPPROTO_TCP) {
|
||||
struct tcphdr *th;
|
||||
|
||||
th = (struct tcphdr *)((u8 *)iph + bytes);
|
||||
bytes += th->doff * 4;
|
||||
} else if (transport == IPPROTO_UDP) {
|
||||
bytes += sizeof(struct udphdr);
|
||||
} else {
|
||||
/* cant do anything else here unfortunately so linearize */
|
||||
if (skb_linearize(skb)) {
|
||||
rmnet_nss_inc_stat(RMNET_NSS_TX_LINEARIZE_FAILS);
|
||||
return -EINVAL;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (bytes > skb_frag_size(frag)) {
|
||||
rmnet_nss_inc_stat(RMNET_NSS_TX_BAD_FRAGS);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
skb_push(skb, bytes);
|
||||
memcpy(skb->data, iph, bytes);
|
||||
|
||||
/* subtract to account for skb_push */
|
||||
skb->len -= bytes;
|
||||
|
||||
frag->page_offset += bytes;
|
||||
skb_frag_size_sub(frag, bytes);
|
||||
|
||||
/* subtract to account for skb_frag_size_sub */
|
||||
skb->data_len -= bytes;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Main downlink handler
|
||||
* Looks up NSS contex associated with the device. If the context is found,
|
||||
* we add a dummy ethernet header with the approriate protocol field set,
|
||||
* the pass the packet off to NSS for hardware acceleration.
|
||||
*/
|
||||
int rmnet_nss_tx(struct sk_buff *skb)
|
||||
{
|
||||
struct ethhdr *eth;
|
||||
struct rmnet_nss_ctx *ctx;
|
||||
struct net_device *dev = skb->dev;
|
||||
nss_tx_status_t rc;
|
||||
unsigned int len;
|
||||
u8 version;
|
||||
|
||||
if (skb_is_nonlinear(skb)) {
|
||||
if (rmnet_nss_adjust_header(skb))
|
||||
goto fail;
|
||||
else
|
||||
rmnet_nss_inc_stat(RMNET_NSS_TX_NONLINEAR);
|
||||
}
|
||||
|
||||
version = ((struct iphdr *)skb->data)->version;
|
||||
|
||||
ctx = rmnet_nss_find_ctx(dev);
|
||||
if (!ctx) {
|
||||
rmnet_nss_inc_stat(RMNET_NSS_TX_NO_CTX);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
eth = (struct ethhdr *)skb_push(skb, sizeof(*eth));
|
||||
memset(ð->h_dest, 0, ETH_ALEN * 2);
|
||||
if (version == 4) {
|
||||
eth->h_proto = htons(ETH_P_IP);
|
||||
} else if (version == 6) {
|
||||
eth->h_proto = htons(ETH_P_IPV6);
|
||||
} else {
|
||||
rmnet_nss_inc_stat(RMNET_NSS_TX_BAD_IP);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
skb->protocol = htons(ETH_P_802_3);
|
||||
/* Get length including ethhdr */
|
||||
len = skb->len;
|
||||
|
||||
transmit:
|
||||
rc = nss_rmnet_rx_tx_buf(ctx->nss_ctx, skb);
|
||||
if (rc == NSS_TX_SUCCESS) {
|
||||
/* Increment rmnet_data device stats.
|
||||
* Don't call rmnet_data_vnd_rx_fixup() to do this, as
|
||||
* there's no guarantee the skb pointer is still valid.
|
||||
*/
|
||||
dev->stats.rx_packets++;
|
||||
dev->stats.rx_bytes += len;
|
||||
rmnet_nss_inc_stat(RMNET_NSS_TX_SUCCESS);
|
||||
return 0;
|
||||
} else if (rc == NSS_TX_FAILURE_QUEUE) {
|
||||
rmnet_nss_inc_stat(RMNET_NSS_TX_BUSY_LOOP);
|
||||
goto transmit;
|
||||
}
|
||||
|
||||
fail:
|
||||
rmnet_nss_inc_stat(RMNET_NSS_TX_FAIL);
|
||||
kfree_skb(skb);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Called by NSS in the DL exception case.
|
||||
* Since the packet cannot be sent over the accelerated path, we need to
|
||||
* handle it. Remove the ethernet header and pass it onward to the stack
|
||||
* if possible.
|
||||
*/
|
||||
void rmnet_nss_receive(struct net_device *dev, struct sk_buff *skb,
|
||||
struct napi_struct *napi)
|
||||
{
|
||||
rmnet_nss_inc_stat(RMNET_NSS_EXCEPTIONS);
|
||||
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
if (rmnet_nss_ethhdr_pull(skb)) {
|
||||
rmnet_nss_inc_stat(RMNET_NSS_EX_BAD_HDR);
|
||||
goto drop;
|
||||
}
|
||||
|
||||
/* reset header pointers */
|
||||
skb_reset_transport_header(skb);
|
||||
skb_reset_network_header(skb);
|
||||
skb_reset_mac_header(skb);
|
||||
|
||||
/* reset packet type */
|
||||
skb->pkt_type = PACKET_HOST;
|
||||
|
||||
skb->dev = dev;
|
||||
|
||||
/* reset protocol type */
|
||||
switch (skb->data[0] & 0xF0) {
|
||||
case 0x40:
|
||||
skb->protocol = htons(ETH_P_IP);
|
||||
break;
|
||||
case 0x60:
|
||||
skb->protocol = htons(ETH_P_IPV6);
|
||||
break;
|
||||
default:
|
||||
rmnet_nss_inc_stat(RMNET_NSS_EX_BAD_IP);
|
||||
goto drop;
|
||||
}
|
||||
|
||||
rmnet_nss_inc_stat(RMNET_NSS_EX_SUCCESS);
|
||||
|
||||
/* Set this so that we dont loop around netif_receive_skb */
|
||||
|
||||
skb->cb[0] = 1;
|
||||
|
||||
netif_receive_skb(skb);
|
||||
return;
|
||||
|
||||
drop:
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
/* Called by NSS in the UL acceleration case.
|
||||
* We are guaranteed to have an ethernet packet here from the NSS hardware,
|
||||
* We need to pull the header off and invoke our ndo_start_xmit function
|
||||
* to handle transmitting the packet to the network stack.
|
||||
*/
|
||||
void rmnet_nss_xmit(struct net_device *dev, struct sk_buff *skb)
|
||||
{
|
||||
netdev_tx_t ret;
|
||||
|
||||
skb_pull(skb, sizeof(struct ethhdr));
|
||||
rmnet_nss_inc_stat(RMNET_NSS_RX_ETH);
|
||||
|
||||
/* NSS takes care of shaping, so bypassing Qdiscs like this is OK */
|
||||
ret = dev->netdev_ops->ndo_start_xmit(skb, dev);
|
||||
if (unlikely(ret == NETDEV_TX_BUSY)) {
|
||||
dev_kfree_skb_any(skb);
|
||||
rmnet_nss_inc_stat(RMNET_NSS_RX_BUSY);
|
||||
}
|
||||
}
|
||||
|
||||
/* Create and register an NSS context for an rmnet_data device */
|
||||
int rmnet_nss_create_vnd(struct net_device *dev)
|
||||
{
|
||||
struct rmnet_nss_ctx *ctx;
|
||||
|
||||
ctx = kzalloc(sizeof(*ctx), GFP_ATOMIC);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
ctx->rmnet_dev = dev;
|
||||
ctx->nss_ctx = nss_rmnet_rx_create_sync_nexthop(dev, NSS_N2H_INTERFACE,
|
||||
NSS_C2C_TX_INTERFACE);
|
||||
if (!ctx->nss_ctx) {
|
||||
kfree(ctx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
nss_rmnet_rx_register(ctx->nss_ctx, rmnet_nss_receive, dev);
|
||||
nss_rmnet_rx_xmit_callback_register(ctx->nss_ctx, rmnet_nss_xmit);
|
||||
hash_add_ptr(rmnet_nss_ctx_hashtable, &ctx->hnode, dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Unregister and destroy the NSS context for an rmnet_data device */
|
||||
int rmnet_nss_free_vnd(struct net_device *dev)
|
||||
{
|
||||
struct rmnet_nss_ctx *ctx;
|
||||
|
||||
ctx = rmnet_nss_find_ctx(dev);
|
||||
rmnet_nss_free_ctx(ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct rmnet_nss_cb rmnet_nss = {
|
||||
.nss_create = rmnet_nss_create_vnd,
|
||||
.nss_free = rmnet_nss_free_vnd,
|
||||
.nss_tx = rmnet_nss_tx,
|
||||
};
|
||||
|
||||
int __init rmnet_nss_init(void)
|
||||
{
|
||||
pr_err("%s(): initializing rmnet_nss\n", __func__);
|
||||
RCU_INIT_POINTER(rmnet_nss_callbacks, &rmnet_nss);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __exit rmnet_nss_exit(void)
|
||||
{
|
||||
struct hlist_node *tmp;
|
||||
struct rmnet_nss_ctx *ctx;
|
||||
int bkt;
|
||||
|
||||
pr_err("%s(): exiting rmnet_nss\n", __func__);
|
||||
RCU_INIT_POINTER(rmnet_nss_callbacks, NULL);
|
||||
|
||||
/* Tear down all NSS contexts */
|
||||
hash_for_each_safe(rmnet_nss_ctx_hashtable, bkt, tmp, ctx, hnode)
|
||||
rmnet_nss_free_ctx(ctx);
|
||||
}
|
||||
|
||||
#if 0
|
||||
MODULE_LICENSE("GPL v2");
|
||||
module_init(rmnet_nss_init);
|
||||
module_exit(rmnet_nss_exit);
|
||||
#endif
|
||||
Reference in new issue
Block a user