Update On Tue Jul 2 20:34:19 CEST 2024

This commit is contained in:
github-action[bot]
2024-07-02 20:34:19 +02:00
parent 91fe520152
commit 55a38739d4
630 changed files with 55392 additions and 5173 deletions
+1
View File
@@ -690,3 +690,4 @@ Update On Fri Jun 28 20:30:26 CEST 2024
Update On Sat Jun 29 20:29:36 CEST 2024
Update On Sun Jun 30 20:30:33 CEST 2024
Update On Mon Jul 1 20:30:34 CEST 2024
Update On Tue Jul 2 20:34:08 CEST 2024
+2 -2
View File
@@ -5178,9 +5178,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.119"
version = "1.0.120"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8eddb61f0697cc3989c5d64b452f5488e2b8a60fd7d5076a3045076ffef8cb0"
checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5"
dependencies = [
"indexmap 2.2.6",
"itoa 1.0.11",
@@ -35,8 +35,8 @@
"react": "18.3.1",
"react-dom": "18.3.1",
"react-error-boundary": "4.0.13",
"react-fast-marquee": "1.6.4",
"react-hook-form": "7.52.0",
"react-fast-marquee": "1.6.5",
"react-hook-form": "7.52.1",
"react-hook-form-mui": "7.0.0",
"react-i18next": "14.1.2",
"react-markdown": "9.0.1",
@@ -53,8 +53,8 @@
"@types/react": "18.3.3",
"@types/react-dom": "18.3.0",
"@types/react-transition-group": "4.4.10",
"@typescript-eslint/eslint-plugin": "7.14.1",
"@typescript-eslint/parser": "7.14.1",
"@typescript-eslint/eslint-plugin": "7.15.0",
"@typescript-eslint/parser": "7.15.0",
"@vitejs/plugin-react": "4.3.1",
"@vitejs/plugin-react-swc": "3.7.0",
"clsx": "2.1.1",
+2 -2
View File
@@ -1,7 +1,7 @@
{
"manifest_version": 1,
"latest": {
"mihomo": "v1.18.5",
"mihomo": "v1.18.6",
"mihomo_alpha": "alpha-0e22876",
"clash_rs": "v0.1.18",
"clash_premium": "2023-09-05-gdcc8d87"
@@ -36,5 +36,5 @@
"darwin-x64": "clash-darwin-amd64-n{}.gz"
}
},
"updated_at": "2024-06-28T22:20:05.617Z"
"updated_at": "2024-07-01T22:20:09.970Z"
}
+2 -2
View File
@@ -107,11 +107,11 @@
"stylelint-scss": "6.3.2",
"tailwindcss": "3.4.4",
"tsx": "4.16.0",
"typescript": "5.5.2"
"typescript": "5.5.3"
},
"packageManager": "pnpm@9.4.0",
"engines": {
"node": "22.3.0"
"node": "22.4.0"
},
"pnpm": {
"overrides": {
+128 -128
View File
@@ -24,7 +24,7 @@ importers:
devDependencies:
'@commitlint/cli':
specifier: 19.3.0
version: 19.3.0(@types/node@20.14.9)(typescript@5.5.2)
version: 19.3.0(@types/node@20.14.9)(typescript@5.5.3)
'@commitlint/config-conventional':
specifier: 19.2.2
version: 19.2.2
@@ -111,25 +111,25 @@ importers:
version: 5.3.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)
stylelint:
specifier: 16.6.1
version: 16.6.1(typescript@5.5.2)
version: 16.6.1(typescript@5.5.3)
stylelint-config-html:
specifier: 1.1.0
version: 1.1.0(postcss-html@1.7.0)(stylelint@16.6.1(typescript@5.5.2))
version: 1.1.0(postcss-html@1.7.0)(stylelint@16.6.1(typescript@5.5.3))
stylelint-config-recess-order:
specifier: 5.0.1
version: 5.0.1(stylelint@16.6.1(typescript@5.5.2))
version: 5.0.1(stylelint@16.6.1(typescript@5.5.3))
stylelint-config-standard:
specifier: 36.0.1
version: 36.0.1(stylelint@16.6.1(typescript@5.5.2))
version: 36.0.1(stylelint@16.6.1(typescript@5.5.3))
stylelint-declaration-block-no-ignored-properties:
specifier: 2.8.0
version: 2.8.0(stylelint@16.6.1(typescript@5.5.2))
version: 2.8.0(stylelint@16.6.1(typescript@5.5.3))
stylelint-order:
specifier: 6.0.4
version: 6.0.4(stylelint@16.6.1(typescript@5.5.2))
version: 6.0.4(stylelint@16.6.1(typescript@5.5.3))
stylelint-scss:
specifier: 6.3.2
version: 6.3.2(stylelint@16.6.1(typescript@5.5.2))
version: 6.3.2(stylelint@16.6.1(typescript@5.5.3))
tailwindcss:
specifier: 3.4.4
version: 3.4.4
@@ -137,8 +137,8 @@ importers:
specifier: 4.16.0
version: 4.16.0
typescript:
specifier: 5.5.2
version: 5.5.2
specifier: 5.5.3
version: 5.5.3
frontend/interface:
dependencies:
@@ -243,14 +243,14 @@ importers:
specifier: 4.0.13
version: 4.0.13(react@19.0.0-rc-fb9a90fa48-20240614)
react-fast-marquee:
specifier: 1.6.4
version: 1.6.4(react-dom@19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614)
specifier: 1.6.5
version: 1.6.5(react-dom@19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614)
react-hook-form:
specifier: 7.52.0
version: 7.52.0(react@19.0.0-rc-fb9a90fa48-20240614)
specifier: 7.52.1
version: 7.52.1(react@19.0.0-rc-fb9a90fa48-20240614)
react-hook-form-mui:
specifier: 7.0.0
version: 7.0.0(zwihrdjnuz7uekpqkqd7rvdhli)
version: 7.0.0(hnsbxdphojlfk7ty6r3hqlevge)
react-i18next:
specifier: 14.1.2
version: 14.1.2(i18next@23.11.5)(react-dom@19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614)
@@ -292,11 +292,11 @@ importers:
specifier: 4.4.10
version: 4.4.10
'@typescript-eslint/eslint-plugin':
specifier: 7.14.1
version: 7.14.1(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)(typescript@5.5.2)
specifier: 7.15.0
version: 7.15.0(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3)
'@typescript-eslint/parser':
specifier: 7.14.1
version: 7.14.1(eslint@8.57.0)(typescript@5.5.2)
specifier: 7.15.0
version: 7.15.0(eslint@8.57.0)(typescript@5.5.3)
'@vitejs/plugin-react':
specifier: 4.3.1
version: 4.3.1(vite@5.3.2(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0))
@@ -329,10 +329,10 @@ importers:
version: 1.3.22(postcss@8.4.39)(prettier@3.3.2)(sass@1.77.6)(vite@5.3.2(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0))
vite-plugin-svgr:
specifier: 4.2.0
version: 4.2.0(rollup@4.17.2)(typescript@5.5.2)(vite@5.3.2(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0))
version: 4.2.0(rollup@4.17.2)(typescript@5.5.3)(vite@5.3.2(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0))
vite-tsconfig-paths:
specifier: 4.3.2
version: 4.3.2(typescript@5.5.2)(vite@5.3.2(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0))
version: 4.3.2(typescript@5.5.3)(vite@5.3.2(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0))
frontend/ui:
dependencies:
@@ -381,7 +381,7 @@ importers:
version: 1.77.6
typescript-plugin-css-modules:
specifier: 5.1.0
version: 5.1.0(typescript@5.5.2)
version: 5.1.0(typescript@5.5.3)
scripts:
dependencies:
@@ -2103,8 +2103,8 @@ packages:
'@types/yauzl@2.10.3':
resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==}
'@typescript-eslint/eslint-plugin@7.14.1':
resolution: {integrity: sha512-aAJd6bIf2vvQRjUG3ZkNXkmBpN+J7Wd0mfQiiVCJMu9Z5GcZZdcc0j8XwN/BM97Fl7e3SkTXODSk4VehUv7CGw==}
'@typescript-eslint/eslint-plugin@7.15.0':
resolution: {integrity: sha512-uiNHpyjZtFrLwLDpHnzaDlP3Tt6sGMqTCiqmxaN4n4RP0EfYZDODJyddiFDF44Hjwxr5xAcaYxVKm9QKQFJFLA==}
engines: {node: ^18.18.0 || >=20.0.0}
peerDependencies:
'@typescript-eslint/parser': ^7.0.0
@@ -2114,8 +2114,8 @@ packages:
typescript:
optional: true
'@typescript-eslint/parser@7.14.1':
resolution: {integrity: sha512-8lKUOebNLcR0D7RvlcloOacTOWzOqemWEWkKSVpMZVF/XVcwjPR+3MD08QzbW9TCGJ+DwIc6zUSGZ9vd8cO1IA==}
'@typescript-eslint/parser@7.15.0':
resolution: {integrity: sha512-k9fYuQNnypLFcqORNClRykkGOMOj+pV6V91R4GO/l1FDGwpqmSwoOQrOHo3cGaH63e+D3ZiCAOsuS/D2c99j/A==}
engines: {node: ^18.18.0 || >=20.0.0}
peerDependencies:
eslint: ^8.56.0
@@ -2124,12 +2124,12 @@ packages:
typescript:
optional: true
'@typescript-eslint/scope-manager@7.14.1':
resolution: {integrity: sha512-gPrFSsoYcsffYXTOZ+hT7fyJr95rdVe4kGVX1ps/dJ+DfmlnjFN/GcMxXcVkeHDKqsq6uAcVaQaIi3cFffmAbA==}
'@typescript-eslint/scope-manager@7.15.0':
resolution: {integrity: sha512-Q/1yrF/XbxOTvttNVPihxh1b9fxamjEoz2Os/Pe38OHwxC24CyCqXxGTOdpb4lt6HYtqw9HetA/Rf6gDGaMPlw==}
engines: {node: ^18.18.0 || >=20.0.0}
'@typescript-eslint/type-utils@7.14.1':
resolution: {integrity: sha512-/MzmgNd3nnbDbOi3LfasXWWe292+iuo+umJ0bCCMCPc1jLO/z2BQmWUUUXvXLbrQey/JgzdF/OV+I5bzEGwJkQ==}
'@typescript-eslint/type-utils@7.15.0':
resolution: {integrity: sha512-SkgriaeV6PDvpA6253PDVep0qCqgbO1IOBiycjnXsszNTVQe5flN5wR5jiczoEoDEnAqYFSFFc9al9BSGVltkg==}
engines: {node: ^18.18.0 || >=20.0.0}
peerDependencies:
eslint: ^8.56.0
@@ -2138,12 +2138,12 @@ packages:
typescript:
optional: true
'@typescript-eslint/types@7.14.1':
resolution: {integrity: sha512-mL7zNEOQybo5R3AavY+Am7KLv8BorIv7HCYS5rKoNZKQD9tsfGUpO4KdAn3sSUvTiS4PQkr2+K0KJbxj8H9NDg==}
'@typescript-eslint/types@7.15.0':
resolution: {integrity: sha512-aV1+B1+ySXbQH0pLK0rx66I3IkiZNidYobyfn0WFsdGhSXw+P3YOqeTq5GED458SfB24tg+ux3S+9g118hjlTw==}
engines: {node: ^18.18.0 || >=20.0.0}
'@typescript-eslint/typescript-estree@7.14.1':
resolution: {integrity: sha512-k5d0VuxViE2ulIO6FbxxSZaxqDVUyMbXcidC8rHvii0I56XZPv8cq+EhMns+d/EVIL41sMXqRbK3D10Oza1bbA==}
'@typescript-eslint/typescript-estree@7.15.0':
resolution: {integrity: sha512-gjyB/rHAopL/XxfmYThQbXbzRMGhZzGw6KpcMbfe8Q3nNQKStpxnUKeXb0KiN/fFDR42Z43szs6rY7eHk0zdGQ==}
engines: {node: ^18.18.0 || >=20.0.0}
peerDependencies:
typescript: '*'
@@ -2151,14 +2151,14 @@ packages:
typescript:
optional: true
'@typescript-eslint/utils@7.14.1':
resolution: {integrity: sha512-CMmVVELns3nak3cpJhZosDkm63n+DwBlDX8g0k4QUa9BMnF+lH2lr3d130M1Zt1xxmB3LLk3NV7KQCq86ZBBhQ==}
'@typescript-eslint/utils@7.15.0':
resolution: {integrity: sha512-hfDMDqaqOqsUVGiEPSMLR/AjTSCsmJwjpKkYQRo1FNbmW4tBwBspYDwO9eh7sKSTwMQgBw9/T4DHudPaqshRWA==}
engines: {node: ^18.18.0 || >=20.0.0}
peerDependencies:
eslint: ^8.56.0
'@typescript-eslint/visitor-keys@7.14.1':
resolution: {integrity: sha512-Crb+F75U1JAEtBeQGxSKwI60hZmmzaqA3z9sYsVm8X7W5cwLEm5bRe0/uXS6+MR/y8CVpKSR/ontIAIEPFcEkA==}
'@typescript-eslint/visitor-keys@7.15.0':
resolution: {integrity: sha512-Hqgy/ETgpt2L5xueA/zHHIl4fJI2O4XUE9l4+OIfbJIRSnTJb/QscncdqqZzofQegIJugRIF57OJea1khw2SDw==}
engines: {node: ^18.18.0 || >=20.0.0}
'@ungap/structured-clone@1.2.0':
@@ -4872,8 +4872,8 @@ packages:
react-fast-compare@3.2.2:
resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==}
react-fast-marquee@1.6.4:
resolution: {integrity: sha512-LAgvhRmHdqaUQ8R5jCUwzEGFUIjnCCt3T3W8X7j7wF6DWe0SATlpP0JX1V0pp2qX3DYUezmn1Iz5AtRFdL2EWQ==}
react-fast-marquee@1.6.5:
resolution: {integrity: sha512-swDnPqrT2XISAih0o74zQVE2wQJFMvkx+9VZXYYNSLb/CUcAzU9pNj637Ar2+hyRw6b4tP6xh4GQZip2ZCpQpg==}
peerDependencies:
react: npm:react@rc
react-dom: npm:react-dom@rc
@@ -4893,8 +4893,8 @@ packages:
'@mui/x-date-pickers':
optional: true
react-hook-form@7.52.0:
resolution: {integrity: sha512-mJX506Xc6mirzLsmXUJyqlAI3Kj9Ph2RhplYhUVffeOQSnubK2uVqBFOBJmvKikvbFV91pxVXmDiR+QMF19x6A==}
react-hook-form@7.52.1:
resolution: {integrity: sha512-uNKIhaoICJ5KQALYZ4TOaOLElyM+xipord+Ha3crEFhTntdLvWZqVY49Wqd/0GiVCA/f9NjemLeiNPjG7Hpurg==}
engines: {node: '>=12.22.0'}
peerDependencies:
react: npm:react@rc
@@ -5557,8 +5557,8 @@ packages:
peerDependencies:
typescript: '>=4.0.0'
typescript@5.5.2:
resolution: {integrity: sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew==}
typescript@5.5.3:
resolution: {integrity: sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==}
engines: {node: '>=14.17'}
hasBin: true
@@ -6048,11 +6048,11 @@ snapshots:
'@babel/helper-validator-identifier': 7.24.5
to-fast-properties: 2.0.0
'@commitlint/cli@19.3.0(@types/node@20.14.9)(typescript@5.5.2)':
'@commitlint/cli@19.3.0(@types/node@20.14.9)(typescript@5.5.3)':
dependencies:
'@commitlint/format': 19.3.0
'@commitlint/lint': 19.2.2
'@commitlint/load': 19.2.0(@types/node@20.14.9)(typescript@5.5.2)
'@commitlint/load': 19.2.0(@types/node@20.14.9)(typescript@5.5.3)
'@commitlint/read': 19.2.1
'@commitlint/types': 19.0.3
execa: 8.0.1
@@ -6099,15 +6099,15 @@ snapshots:
'@commitlint/rules': 19.0.3
'@commitlint/types': 19.0.3
'@commitlint/load@19.2.0(@types/node@20.14.9)(typescript@5.5.2)':
'@commitlint/load@19.2.0(@types/node@20.14.9)(typescript@5.5.3)':
dependencies:
'@commitlint/config-validator': 19.0.3
'@commitlint/execute-rule': 19.0.0
'@commitlint/resolve-extends': 19.1.0
'@commitlint/types': 19.0.3
chalk: 5.3.0
cosmiconfig: 9.0.0(typescript@5.5.2)
cosmiconfig-typescript-loader: 5.0.0(@types/node@20.14.9)(cosmiconfig@9.0.0(typescript@5.5.2))(typescript@5.5.2)
cosmiconfig: 9.0.0(typescript@5.5.3)
cosmiconfig-typescript-loader: 5.0.0(@types/node@20.14.9)(cosmiconfig@9.0.0(typescript@5.5.3))(typescript@5.5.3)
lodash.isplainobject: 4.0.6
lodash.merge: 4.6.2
lodash.uniq: 4.5.0
@@ -7087,12 +7087,12 @@ snapshots:
'@svgr/babel-plugin-transform-react-native-svg': 8.1.0(@babel/core@7.24.5)
'@svgr/babel-plugin-transform-svg-component': 8.0.0(@babel/core@7.24.5)
'@svgr/core@8.1.0(typescript@5.5.2)':
'@svgr/core@8.1.0(typescript@5.5.3)':
dependencies:
'@babel/core': 7.24.5
'@svgr/babel-preset': 8.1.0(@babel/core@7.24.5)
camelcase: 6.3.0
cosmiconfig: 8.3.6(typescript@5.5.2)
cosmiconfig: 8.3.6(typescript@5.5.3)
snake-case: 3.0.4
transitivePeerDependencies:
- supports-color
@@ -7103,11 +7103,11 @@ snapshots:
'@babel/types': 7.24.5
entities: 4.5.0
'@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0(typescript@5.5.2))':
'@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0(typescript@5.5.3))':
dependencies:
'@babel/core': 7.24.5
'@svgr/babel-preset': 8.1.0(@babel/core@7.24.5)
'@svgr/core': 8.1.0(typescript@5.5.2)
'@svgr/core': 8.1.0(typescript@5.5.3)
'@svgr/hast-util-to-babel-ast': 8.0.0
svg-parser: 2.0.4
transitivePeerDependencies:
@@ -7463,85 +7463,85 @@ snapshots:
'@types/node': 20.14.9
optional: true
'@typescript-eslint/eslint-plugin@7.14.1(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)(typescript@5.5.2)':
'@typescript-eslint/eslint-plugin@7.15.0(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3)':
dependencies:
'@eslint-community/regexpp': 4.10.0
'@typescript-eslint/parser': 7.14.1(eslint@8.57.0)(typescript@5.5.2)
'@typescript-eslint/scope-manager': 7.14.1
'@typescript-eslint/type-utils': 7.14.1(eslint@8.57.0)(typescript@5.5.2)
'@typescript-eslint/utils': 7.14.1(eslint@8.57.0)(typescript@5.5.2)
'@typescript-eslint/visitor-keys': 7.14.1
'@typescript-eslint/parser': 7.15.0(eslint@8.57.0)(typescript@5.5.3)
'@typescript-eslint/scope-manager': 7.15.0
'@typescript-eslint/type-utils': 7.15.0(eslint@8.57.0)(typescript@5.5.3)
'@typescript-eslint/utils': 7.15.0(eslint@8.57.0)(typescript@5.5.3)
'@typescript-eslint/visitor-keys': 7.15.0
eslint: 8.57.0
graphemer: 1.4.0
ignore: 5.3.1
natural-compare: 1.4.0
ts-api-utils: 1.3.0(typescript@5.5.2)
ts-api-utils: 1.3.0(typescript@5.5.3)
optionalDependencies:
typescript: 5.5.2
typescript: 5.5.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.5.2)':
'@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3)':
dependencies:
'@typescript-eslint/scope-manager': 7.14.1
'@typescript-eslint/types': 7.14.1
'@typescript-eslint/typescript-estree': 7.14.1(typescript@5.5.2)
'@typescript-eslint/visitor-keys': 7.14.1
'@typescript-eslint/scope-manager': 7.15.0
'@typescript-eslint/types': 7.15.0
'@typescript-eslint/typescript-estree': 7.15.0(typescript@5.5.3)
'@typescript-eslint/visitor-keys': 7.15.0
debug: 4.3.4
eslint: 8.57.0
optionalDependencies:
typescript: 5.5.2
typescript: 5.5.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/scope-manager@7.14.1':
'@typescript-eslint/scope-manager@7.15.0':
dependencies:
'@typescript-eslint/types': 7.14.1
'@typescript-eslint/visitor-keys': 7.14.1
'@typescript-eslint/types': 7.15.0
'@typescript-eslint/visitor-keys': 7.15.0
'@typescript-eslint/type-utils@7.14.1(eslint@8.57.0)(typescript@5.5.2)':
'@typescript-eslint/type-utils@7.15.0(eslint@8.57.0)(typescript@5.5.3)':
dependencies:
'@typescript-eslint/typescript-estree': 7.14.1(typescript@5.5.2)
'@typescript-eslint/utils': 7.14.1(eslint@8.57.0)(typescript@5.5.2)
'@typescript-eslint/typescript-estree': 7.15.0(typescript@5.5.3)
'@typescript-eslint/utils': 7.15.0(eslint@8.57.0)(typescript@5.5.3)
debug: 4.3.4
eslint: 8.57.0
ts-api-utils: 1.3.0(typescript@5.5.2)
ts-api-utils: 1.3.0(typescript@5.5.3)
optionalDependencies:
typescript: 5.5.2
typescript: 5.5.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/types@7.14.1': {}
'@typescript-eslint/types@7.15.0': {}
'@typescript-eslint/typescript-estree@7.14.1(typescript@5.5.2)':
'@typescript-eslint/typescript-estree@7.15.0(typescript@5.5.3)':
dependencies:
'@typescript-eslint/types': 7.14.1
'@typescript-eslint/visitor-keys': 7.14.1
'@typescript-eslint/types': 7.15.0
'@typescript-eslint/visitor-keys': 7.15.0
debug: 4.3.4
globby: 11.1.0
is-glob: 4.0.3
minimatch: 9.0.4
semver: 7.6.1
ts-api-utils: 1.3.0(typescript@5.5.2)
ts-api-utils: 1.3.0(typescript@5.5.3)
optionalDependencies:
typescript: 5.5.2
typescript: 5.5.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/utils@7.14.1(eslint@8.57.0)(typescript@5.5.2)':
'@typescript-eslint/utils@7.15.0(eslint@8.57.0)(typescript@5.5.3)':
dependencies:
'@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0)
'@typescript-eslint/scope-manager': 7.14.1
'@typescript-eslint/types': 7.14.1
'@typescript-eslint/typescript-estree': 7.14.1(typescript@5.5.2)
'@typescript-eslint/scope-manager': 7.15.0
'@typescript-eslint/types': 7.15.0
'@typescript-eslint/typescript-estree': 7.15.0(typescript@5.5.3)
eslint: 8.57.0
transitivePeerDependencies:
- supports-color
- typescript
'@typescript-eslint/visitor-keys@7.14.1':
'@typescript-eslint/visitor-keys@7.15.0':
dependencies:
'@typescript-eslint/types': 7.14.1
'@typescript-eslint/types': 7.15.0
eslint-visitor-keys: 3.4.3
'@ungap/structured-clone@1.2.0': {}
@@ -8048,12 +8048,12 @@ snapshots:
dependencies:
is-what: 3.14.1
cosmiconfig-typescript-loader@5.0.0(@types/node@20.14.9)(cosmiconfig@9.0.0(typescript@5.5.2))(typescript@5.5.2):
cosmiconfig-typescript-loader@5.0.0(@types/node@20.14.9)(cosmiconfig@9.0.0(typescript@5.5.3))(typescript@5.5.3):
dependencies:
'@types/node': 20.14.9
cosmiconfig: 9.0.0(typescript@5.5.2)
cosmiconfig: 9.0.0(typescript@5.5.3)
jiti: 1.21.0
typescript: 5.5.2
typescript: 5.5.3
cosmiconfig@7.1.0:
dependencies:
@@ -8063,23 +8063,23 @@ snapshots:
path-type: 4.0.0
yaml: 1.10.2
cosmiconfig@8.3.6(typescript@5.5.2):
cosmiconfig@8.3.6(typescript@5.5.3):
dependencies:
import-fresh: 3.3.0
js-yaml: 4.1.0
parse-json: 5.2.0
path-type: 4.0.0
optionalDependencies:
typescript: 5.5.2
typescript: 5.5.3
cosmiconfig@9.0.0(typescript@5.5.2):
cosmiconfig@9.0.0(typescript@5.5.3):
dependencies:
env-paths: 2.2.1
import-fresh: 3.3.0
js-yaml: 4.1.0
parse-json: 5.2.0
optionalDependencies:
typescript: 5.5.2
typescript: 5.5.3
create-error-class@3.0.2:
dependencies:
@@ -10601,20 +10601,20 @@ snapshots:
react-fast-compare@3.2.2: {}
react-fast-marquee@1.6.4(react-dom@19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614):
react-fast-marquee@1.6.5(react-dom@19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614):
dependencies:
react: 19.0.0-rc-fb9a90fa48-20240614
react-dom: 19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614)
react-hook-form-mui@7.0.0(zwihrdjnuz7uekpqkqd7rvdhli):
react-hook-form-mui@7.0.0(hnsbxdphojlfk7ty6r3hqlevge):
dependencies:
'@mui/material': 5.15.21(@emotion/react@11.11.4(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(react-dom@19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1)
react: 19.0.0-rc-fb9a90fa48-20240614
react-hook-form: 7.52.0(react@19.0.0-rc-fb9a90fa48-20240614)
react-hook-form: 7.52.1(react@19.0.0-rc-fb9a90fa48-20240614)
optionalDependencies:
'@mui/icons-material': 5.15.21(@mui/material@5.15.21(@emotion/react@11.11.4(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1)
react-hook-form@7.52.0(react@19.0.0-rc-fb9a90fa48-20240614):
react-hook-form@7.52.1(react@19.0.0-rc-fb9a90fa48-20240614):
dependencies:
react: 19.0.0-rc-fb9a90fa48-20240614
@@ -11071,45 +11071,45 @@ snapshots:
dependencies:
inline-style-parser: 0.2.3
stylelint-config-html@1.1.0(postcss-html@1.7.0)(stylelint@16.6.1(typescript@5.5.2)):
stylelint-config-html@1.1.0(postcss-html@1.7.0)(stylelint@16.6.1(typescript@5.5.3)):
dependencies:
postcss-html: 1.7.0
stylelint: 16.6.1(typescript@5.5.2)
stylelint: 16.6.1(typescript@5.5.3)
stylelint-config-recess-order@5.0.1(stylelint@16.6.1(typescript@5.5.2)):
stylelint-config-recess-order@5.0.1(stylelint@16.6.1(typescript@5.5.3)):
dependencies:
stylelint: 16.6.1(typescript@5.5.2)
stylelint-order: 6.0.4(stylelint@16.6.1(typescript@5.5.2))
stylelint: 16.6.1(typescript@5.5.3)
stylelint-order: 6.0.4(stylelint@16.6.1(typescript@5.5.3))
stylelint-config-recommended@14.0.1(stylelint@16.6.1(typescript@5.5.2)):
stylelint-config-recommended@14.0.1(stylelint@16.6.1(typescript@5.5.3)):
dependencies:
stylelint: 16.6.1(typescript@5.5.2)
stylelint: 16.6.1(typescript@5.5.3)
stylelint-config-standard@36.0.1(stylelint@16.6.1(typescript@5.5.2)):
stylelint-config-standard@36.0.1(stylelint@16.6.1(typescript@5.5.3)):
dependencies:
stylelint: 16.6.1(typescript@5.5.2)
stylelint-config-recommended: 14.0.1(stylelint@16.6.1(typescript@5.5.2))
stylelint: 16.6.1(typescript@5.5.3)
stylelint-config-recommended: 14.0.1(stylelint@16.6.1(typescript@5.5.3))
stylelint-declaration-block-no-ignored-properties@2.8.0(stylelint@16.6.1(typescript@5.5.2)):
stylelint-declaration-block-no-ignored-properties@2.8.0(stylelint@16.6.1(typescript@5.5.3)):
dependencies:
stylelint: 16.6.1(typescript@5.5.2)
stylelint: 16.6.1(typescript@5.5.3)
stylelint-order@6.0.4(stylelint@16.6.1(typescript@5.5.2)):
stylelint-order@6.0.4(stylelint@16.6.1(typescript@5.5.3)):
dependencies:
postcss: 8.4.39
postcss-sorting: 8.0.2(postcss@8.4.39)
stylelint: 16.6.1(typescript@5.5.2)
stylelint: 16.6.1(typescript@5.5.3)
stylelint-scss@6.3.2(stylelint@16.6.1(typescript@5.5.2)):
stylelint-scss@6.3.2(stylelint@16.6.1(typescript@5.5.3)):
dependencies:
known-css-properties: 0.31.0
postcss-media-query-parser: 0.2.3
postcss-resolve-nested-selector: 0.1.1
postcss-selector-parser: 6.1.0
postcss-value-parser: 4.2.0
stylelint: 16.6.1(typescript@5.5.2)
stylelint: 16.6.1(typescript@5.5.3)
stylelint@16.6.1(typescript@5.5.2):
stylelint@16.6.1(typescript@5.5.3):
dependencies:
'@csstools/css-parser-algorithms': 2.6.3(@csstools/css-tokenizer@2.3.1)
'@csstools/css-tokenizer': 2.3.1
@@ -11118,7 +11118,7 @@ snapshots:
'@dual-bundle/import-meta-resolve': 4.1.0
balanced-match: 2.0.0
colord: 2.9.3
cosmiconfig: 9.0.0(typescript@5.5.2)
cosmiconfig: 9.0.0(typescript@5.5.3)
css-functions-list: 3.2.2
css-tree: 2.3.1
debug: 4.3.4
@@ -11332,17 +11332,17 @@ snapshots:
trough@2.2.0: {}
ts-api-utils@1.3.0(typescript@5.5.2):
ts-api-utils@1.3.0(typescript@5.5.3):
dependencies:
typescript: 5.5.2
typescript: 5.5.3
ts-custom-error@3.3.1: {}
ts-interface-checker@0.1.13: {}
tsconfck@3.0.3(typescript@5.5.2):
tsconfck@3.0.3(typescript@5.5.3):
optionalDependencies:
typescript: 5.5.2
typescript: 5.5.3
tsconfig-paths@3.15.0:
dependencies:
@@ -11423,7 +11423,7 @@ snapshots:
dependencies:
csstype: 3.1.3
typescript-plugin-css-modules@5.1.0(typescript@5.5.2):
typescript-plugin-css-modules@5.1.0(typescript@5.5.3):
dependencies:
'@types/postcss-modules-local-by-default': 4.0.2
'@types/postcss-modules-scope': 3.0.4
@@ -11441,12 +11441,12 @@ snapshots:
source-map-js: 1.2.0
stylus: 0.62.0
tsconfig-paths: 4.2.0
typescript: 5.5.2
typescript: 5.5.3
transitivePeerDependencies:
- supports-color
- ts-node
typescript@5.5.2: {}
typescript@5.5.3: {}
ufo@1.5.3: {}
@@ -11591,22 +11591,22 @@ snapshots:
sass: 1.77.6
vite: 5.3.2(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)
vite-plugin-svgr@4.2.0(rollup@4.17.2)(typescript@5.5.2)(vite@5.3.2(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)):
vite-plugin-svgr@4.2.0(rollup@4.17.2)(typescript@5.5.3)(vite@5.3.2(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)):
dependencies:
'@rollup/pluginutils': 5.1.0(rollup@4.17.2)
'@svgr/core': 8.1.0(typescript@5.5.2)
'@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.5.2))
'@svgr/core': 8.1.0(typescript@5.5.3)
'@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.5.3))
vite: 5.3.2(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)
transitivePeerDependencies:
- rollup
- supports-color
- typescript
vite-tsconfig-paths@4.3.2(typescript@5.5.2)(vite@5.3.2(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)):
vite-tsconfig-paths@4.3.2(typescript@5.5.3)(vite@5.3.2(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)):
dependencies:
debug: 4.3.4
globrex: 0.1.2
tsconfck: 3.0.3(typescript@5.5.2)
tsconfck: 3.0.3(typescript@5.5.3)
optionalDependencies:
vite: 5.3.2(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)
transitivePeerDependencies:
+1 -1
View File
@@ -2,4 +2,4 @@ pnpm install
pnpm check $INPUT_TARGET
sed -i "s/#openssl/openssl={version=\"0.10\",features=[\"vendored\"]}/g" src-tauri/Cargo.toml
cargo tauri build --target $INPUT_TARGET
pnpm build --target $INPUT_TARGET
-2
View File
@@ -5,8 +5,6 @@ tar -Jxvf ./node-v20.10.0-linux-x64.tar.xz
export PATH=$(pwd)/node-v20.10.0-linux-x64/bin:$PATH
npm install pnpm -g
cargo install --git https://github.com/tauri-apps/tauri --branch 1.x tauri-cli
rustup target add "$INPUT_TARGET"
if [ "$INPUT_TARGET" = "x86_64-unknown-linux-gnu" ]; then
+2 -16
View File
@@ -49,13 +49,6 @@ jobs:
cache-all-crates: true
cache-on-failure: true
- name: Install Tauri CLI
uses: baptiste0928/cargo-install@v3
with:
crate: tauri-cli
git: https://github.com/tauri-apps/tauri
branch: 1.x # `branch` and `commit` are also supported
- name: Install Node
uses: actions/setup-node@v4
with:
@@ -90,7 +83,7 @@ jobs:
releaseBody: "More new features are now supported."
releaseDraft: false
prerelease: true
tauriScript: cargo tauri
tauriScript: pnpm
args: --target ${{ matrix.target }}
- name: Portable Bundle
@@ -174,13 +167,6 @@ jobs:
cache-all-crates: true
cache-on-failure: true
- name: Install Tauri CLI
uses: baptiste0928/cargo-install@v3
with:
crate: tauri-cli
git: https://github.com/tauri-apps/tauri
branch: 1.x # `branch` and `commit` are also supported
- name: Install Node
uses: actions/setup-node@v4
with:
@@ -212,7 +198,7 @@ jobs:
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
with:
tauriScript: cargo tauri
tauriScript: pnpm
args: --target ${{ matrix.target }}
- name: Rename
+2 -16
View File
@@ -41,13 +41,6 @@ jobs:
workspaces: src-tauri
cache-all-crates: true
- name: Install Tauri CLI
uses: baptiste0928/cargo-install@v3
with:
crate: tauri-cli
git: https://github.com/tauri-apps/tauri
branch: 1.x # `branch` and `commit` are also supported
- name: Install Node
uses: actions/setup-node@v4
with:
@@ -80,7 +73,7 @@ jobs:
tagName: v__VERSION__
releaseName: "Clash Verge Rev v__VERSION__"
releaseBody: "More new features are now supported."
tauriScript: cargo tauri
tauriScript: pnpm
args: --target ${{ matrix.target }}
- name: Portable Bundle
@@ -160,13 +153,6 @@ jobs:
with:
workspaces: src-tauri
- name: Install Tauri CLI
uses: baptiste0928/cargo-install@v3
with:
crate: tauri-cli
git: https://github.com/tauri-apps/tauri
branch: 1.x # `branch` and `commit` are also supported
- name: Install Node
uses: actions/setup-node@v4
with:
@@ -198,7 +184,7 @@ jobs:
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
with:
tauriScript: cargo tauri
tauriScript: pnpm
args: --target ${{ matrix.target }}
- name: Rename
+35
View File
@@ -1,3 +1,38 @@
## v1.7.0
### Break Changes
- 此版本重构了 Merge/Script,更新前请先备份好自定义 Merge 和 Script(更新并不会删除配置文件,但是旧版 Merge 和 Script 在更新后无法从前端访问,备份以防万一)
- Merge 改名为 `扩展配置`,分为 `全局扩展配置``订阅扩展配置`,全局扩展配置对所有订阅生效,订阅扩展配置只对关联的订阅生效
- Script 改名为 `扩展脚本`,同样分为 `全局扩展脚本``订阅扩展脚本`
- 执行优先级为: 全局扩展配置 -> 全局扩展脚本 -> 订阅扩展配置 ->订阅扩展脚本
- MacOS 用户更新后请重新安装服务模式
### Features
- 移除内核授权,改为服务模式实现
- 自动填充本地订阅名称
- 添加重大更新处理逻辑
- 订阅单独指定扩展配置/脚本(需要重新导入订阅)
- 添加可视化规则编辑器(需要重新导入订阅)
- 编辑器新增工具栏按钮(格式化、最大化/最小化)
- WEBUI 使用最新版 metacubex,并解决无法自动登陆问问题
- 禁用部分 Webview2 快捷键
- 热键配置新增连接符 + 号
- 新增部分悬浮提示按钮,用于解释说明
- 当日志等级为`Debug`时(更改需重启软件生效),支持点击内存主动内存回收(绿色文字)
- 设置页面右上角新增 TG 频道链接
### Bugs Fixes
- 修复代理绕过格式检查
- 通过进程名称关闭进程
- 退出软件时恢复 DNS 设置
- 修复创建本地订阅时更新间隔无法保存
- 连接页面列宽无法调整
---
## v1.6.6
### Features
+12 -12
View File
@@ -1,6 +1,6 @@
{
"name": "clash-verge",
"version": "1.6.6",
"version": "1.7.0",
"license": "GPL-3.0-only",
"scripts": {
"dev": "tauri dev",
@@ -24,11 +24,11 @@
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.5",
"@juggle/resize-observer": "^3.4.0",
"@mui/icons-material": "^5.15.20",
"@mui/icons-material": "^5.15.21",
"@mui/lab": "5.0.0-alpha.149",
"@mui/material": "^5.15.20",
"@mui/x-data-grid": "^7.7.0",
"@tauri-apps/api": "^1.5.6",
"@mui/material": "^5.15.21",
"@mui/x-data-grid": "^7.8.0",
"@tauri-apps/api": "^1.6.0",
"@types/json-schema": "^7.0.15",
"ahooks": "^3.8.0",
"axios": "^1.7.2",
@@ -37,18 +37,18 @@
"i18next": "^23.11.5",
"js-yaml": "^4.1.0",
"lodash-es": "^4.17.21",
"meta-json-schema": "1.18.5-alpha6",
"meta-json-schema": "1.18.6",
"monaco-editor": "^0.49.0",
"monaco-yaml": "^5.2.0",
"nanoid": "^5.0.7",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-error-boundary": "^3.1.4",
"react-hook-form": "^7.52.0",
"react-hook-form": "^7.52.1",
"react-i18next": "^13.5.0",
"react-markdown": "^9.0.1",
"react-monaco-editor": "^0.55.0",
"react-router-dom": "^6.23.1",
"react-router-dom": "^6.24.0",
"react-transition-group": "^4.4.5",
"react-virtuoso": "^4.7.11",
"sockette": "^2.0.6",
@@ -58,7 +58,7 @@
},
"devDependencies": {
"@actions/github": "^5.1.1",
"@tauri-apps/cli": "^1.5.14",
"@tauri-apps/cli": "^1.6.0",
"@types/fs-extra": "^9.0.13",
"@types/js-cookie": "^3.0.6",
"@types/js-yaml": "^4.0.9",
@@ -76,10 +76,10 @@
"node-fetch": "^3.3.2",
"prettier": "^2.8.8",
"pretty-quick": "^3.3.1",
"sass": "^1.77.5",
"sass": "^1.77.6",
"terser": "^5.31.1",
"typescript": "^5.4.5",
"vite": "^5.3.1",
"typescript": "^5.5.3",
"vite": "^5.3.2",
"vite-plugin-monaco-editor": "^1.1.0",
"vite-plugin-svgr": "^4.2.0"
},
+192 -191
View File
File diff suppressed because it is too large Load Diff
+22 -15
View File
@@ -784,7 +784,7 @@ dependencies = [
[[package]]
name = "clash-verge"
version = "1.6.6"
version = "1.7.0"
dependencies = [
"anyhow",
"auto-launch",
@@ -5442,8 +5442,9 @@ checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f"
[[package]]
name = "tauri"
version = "1.6.7"
source = "git+https://github.com/tauri-apps/tauri?branch=1.x#c2d3afa4fbc0e6d118fe002a1b2ba97b4072438a"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e3b2c32de5bf5bed15a376064286643862b84e4e091d093f7bcdf1fda4b9758"
dependencies = [
"anyhow",
"base64 0.21.7",
@@ -5505,8 +5506,9 @@ dependencies = [
[[package]]
name = "tauri-build"
version = "1.5.2"
source = "git+https://github.com/tauri-apps/tauri?branch=1.x#c2d3afa4fbc0e6d118fe002a1b2ba97b4072438a"
version = "1.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0c6ec7a5c3296330c7818478948b422967ce4649094696c985f61d50076d29c"
dependencies = [
"anyhow",
"cargo_toml",
@@ -5523,8 +5525,9 @@ dependencies = [
[[package]]
name = "tauri-codegen"
version = "1.4.3"
source = "git+https://github.com/tauri-apps/tauri?branch=1.x#c2d3afa4fbc0e6d118fe002a1b2ba97b4072438a"
version = "1.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1aed706708ff1200ec12de9cfbf2582b5d8ec05f6a7293911091effbd22036b"
dependencies = [
"base64 0.21.7",
"brotli",
@@ -5548,8 +5551,9 @@ dependencies = [
[[package]]
name = "tauri-macros"
version = "1.4.4"
source = "git+https://github.com/tauri-apps/tauri?branch=1.x#c2d3afa4fbc0e6d118fe002a1b2ba97b4072438a"
version = "1.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b88f831d2973ae4f81a706a0004e67dac87f2e4439973bbe98efbd73825d8ede"
dependencies = [
"heck 0.5.0",
"proc-macro2",
@@ -5561,8 +5565,9 @@ dependencies = [
[[package]]
name = "tauri-runtime"
version = "0.14.3"
source = "git+https://github.com/tauri-apps/tauri?branch=1.x#c2d3afa4fbc0e6d118fe002a1b2ba97b4072438a"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3068ed62b63dedc705558f4248c7ecbd5561f0f8050949859ea0db2326f26012"
dependencies = [
"gtk",
"http 0.2.12",
@@ -5581,8 +5586,9 @@ dependencies = [
[[package]]
name = "tauri-runtime-wry"
version = "0.14.8"
source = "git+https://github.com/tauri-apps/tauri?branch=1.x#c2d3afa4fbc0e6d118fe002a1b2ba97b4072438a"
version = "0.14.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4c3db170233096aa30330feadcd895bf9317be97e624458560a20e814db7955"
dependencies = [
"arboard",
"cocoa 0.24.1",
@@ -5601,8 +5607,9 @@ dependencies = [
[[package]]
name = "tauri-utils"
version = "1.5.4"
source = "git+https://github.com/tauri-apps/tauri?branch=1.x#c2d3afa4fbc0e6d118fe002a1b2ba97b4072438a"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2826db448309d382dac14d520f0c0a40839b87b57b977e59cf5f296b3ace6a93"
dependencies = [
"brotli",
"ctor",
+3 -3
View File
@@ -1,6 +1,6 @@
[package]
name = "clash-verge"
version = "1.6.6"
version = "1.7.0"
description = "clash verge"
authors = ["zzzgydi", "wonfen", "MystiPanda"]
license = "GPL-3.0-only"
@@ -10,7 +10,7 @@ edition = "2021"
build = "build.rs"
[build-dependencies]
tauri-build = { git="https://github.com/tauri-apps/tauri",branch = "1.x", features = [] }
tauri-build = { version="1", features = [] }
[dependencies]
warp = "0.3"
@@ -37,7 +37,7 @@ tokio = { version = "1", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
reqwest = { version = "0.12", features = ["json", "rustls-tls"] }
sysproxy = { git="https://github.com/zzzgydi/sysproxy-rs", branch = "main" }
tauri = { git="https://github.com/tauri-apps/tauri",branch = "1.x", features = [ "fs-read-file", "fs-exists", "path-all", "protocol-asset", "dialog-open", "notification-all", "icon-png", "icon-ico", "clipboard-all", "global-shortcut-all", "process-all", "shell-all", "system-tray", "updater", "window-all", "devtools"] }
tauri = { version="1", features = [ "fs-read-file", "fs-exists", "path-all", "protocol-asset", "dialog-open", "notification-all", "icon-png", "icon-ico", "clipboard-all", "global-shortcut-all", "process-all", "shell-all", "system-tray", "updater", "window-all", "devtools"] }
[target.'cfg(windows)'.dependencies]
runas = "=1.2.0"
deelevate = "0.2.0"
@@ -428,8 +428,10 @@ impl PrfItem {
/// create the enhanced item by using `merge` rule
pub fn from_merge(uid: Option<String>) -> Result<PrfItem> {
let mut id = help::get_uid("m");
let mut template = tmpl::ITEM_MERGE_EMPTY.into();
if let Some(uid) = uid {
id = uid;
template = tmpl::ITEM_MERGE.into();
}
let file = format!("{id}.yaml");
@@ -445,7 +447,7 @@ impl PrfItem {
option: None,
home: None,
updated: Some(chrono::Local::now().timestamp() as usize),
file_data: Some(tmpl::ITEM_MERGE.into()),
file_data: Some(template),
})
}
+21 -22
View File
@@ -138,8 +138,28 @@ pub async fn enhance() -> (Mapping, Vec<String>, HashMap<String, ResultLog>) {
let mut result_map = HashMap::new(); // 保存脚本日志
let mut exists_keys = use_keys(&config); // 保存出现过的keys
// 处理用户的profile
// 全局Merge和Script
if let ChainType::Merge(merge) = global_merge.data {
exists_keys.extend(use_keys(&merge));
config = use_merge(merge, config.to_owned());
}
if let ChainType::Script(script) = global_script.data {
let mut logs = vec![];
match use_script(script, config.to_owned()) {
Ok((res_config, res_logs)) => {
exists_keys.extend(use_keys(&res_config));
config = res_config;
logs.extend(res_logs);
}
Err(err) => logs.push(("exception".into(), err.to_string())),
}
result_map.insert(global_script.uid, logs);
}
// 订阅关联的Merge、Script、Rules、Proxies、Groups
if let ChainType::Rules(rules) = rules_item.data {
config = use_seq(rules, config.to_owned(), "rules");
}
@@ -172,27 +192,6 @@ pub async fn enhance() -> (Mapping, Vec<String>, HashMap<String, ResultLog>) {
result_map.insert(script_item.uid, logs);
}
// 全局Merge和Script
if let ChainType::Merge(merge) = global_merge.data {
exists_keys.extend(use_keys(&merge));
config = use_merge(merge, config.to_owned());
}
if let ChainType::Script(script) = global_script.data {
let mut logs = vec![];
match use_script(script, config.to_owned()) {
Ok((res_config, res_logs)) => {
exists_keys.extend(use_keys(&res_config));
config = res_config;
logs.extend(res_logs);
}
Err(err) => logs.push(("exception".into(), err.to_string())),
}
result_map.insert(global_script.uid, logs);
}
// 合并默认的config
for (key, value) in clash_config.into_iter() {
if key.as_str() == Some("tun") {
@@ -15,6 +15,13 @@ pub const ITEM_MERGE: &str = "# Profile Enhancement Merge Template for Clash Ver
profile:
store-selected: true
dns:
use-system-hosts: false
";
pub const ITEM_MERGE_EMPTY: &str = "# Profile Enhancement Merge Template for Clash Verge
";
/// enhanced profile
+1 -1
View File
@@ -2,7 +2,7 @@
"$schema": "../node_modules/@tauri-apps/cli/schema.json",
"package": {
"productName": "Clash Verge",
"version": "1.6.6"
"version": "1.7.0"
},
"build": {
"distDir": "../dist",
@@ -9,6 +9,9 @@ import useRegularExpressionIcon from "@/assets/image/component/use_regular_expre
type SearchProps = {
placeholder?: string;
matchCase?: boolean;
matchWholeWord?: boolean;
useRegularExpression?: boolean;
onSearch: (
match: (content: string) => boolean,
state: {
@@ -23,9 +26,13 @@ type SearchProps = {
export const BaseSearchBox = styled((props: SearchProps) => {
const { t } = useTranslation();
const inputRef = useRef<HTMLInputElement>(null);
const [matchCase, setMatchCase] = useState(true);
const [matchWholeWord, setMatchWholeWord] = useState(false);
const [useRegularExpression, setUseRegularExpression] = useState(false);
const [matchCase, setMatchCase] = useState(props.matchCase ?? true);
const [matchWholeWord, setMatchWholeWord] = useState(
props.matchWholeWord ?? false
);
const [useRegularExpression, setUseRegularExpression] = useState(
props.useRegularExpression ?? false
);
const [errorMessage, setErrorMessage] = useState("");
const iconStyle = {
@@ -89,11 +96,11 @@ export const BaseSearchBox = styled((props: SearchProps) => {
return (
<Tooltip title={errorMessage} placement="bottom-start">
<TextField
autoComplete="off"
inputRef={inputRef}
hiddenLabel
fullWidth
size="small"
autoComplete="off"
variant="outlined"
spellCheck="false"
placeholder={props.placeholder ?? t("Filter conditions")}
@@ -6,10 +6,10 @@ export const BaseStyledTextField = styled((props: TextFieldProps) => {
return (
<TextField
autoComplete="off"
hiddenLabel
fullWidth
size="small"
autoComplete="off"
variant="outlined"
spellCheck="false"
placeholder={t("Filter conditions")}
@@ -1,184 +1,235 @@
import { ReactNode, useEffect, useRef } from "react";
import { ReactNode, useEffect, useRef, useState } from "react";
import { useLockFn } from "ahooks";
import { useTranslation } from "react-i18next";
import {
Button,
ButtonGroup,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
IconButton,
} from "@mui/material";
import FormatPaintIcon from "@mui/icons-material/FormatPaint";
import OpenInFullIcon from "@mui/icons-material/OpenInFull";
import CloseFullscreenIcon from "@mui/icons-material/CloseFullscreen";
import { useThemeMode } from "@/services/states";
import { readProfileFile, saveProfileFile } from "@/services/cmds";
import { Notice } from "@/components/base";
import { nanoid } from "nanoid";
import { appWindow } from "@tauri-apps/api/window";
import getSystem from "@/utils/get-system";
import * as monaco from "monaco-editor";
import { editor } from "monaco-editor/esm/vs/editor/editor.api";
import MonacoEditor from "react-monaco-editor";
import { configureMonacoYaml } from "monaco-yaml";
import { type JSONSchema7 } from "json-schema";
import metaSchema from "meta-json-schema/schemas/meta-json-schema.json";
import mergeSchema from "meta-json-schema/schemas/clash-verge-merge-json-schema.json";
import pac from "types-pac/pac.d.ts?raw";
interface Props {
title?: string | ReactNode;
mode: "profile" | "text";
property: string;
open: boolean;
readOnly?: boolean;
language: "yaml" | "javascript" | "css";
schema?: "clash" | "merge";
onClose: () => void;
onChange?: (prev?: string, curr?: string) => void;
type Language = "yaml" | "javascript" | "css";
type Schema<T extends Language> = LanguageSchemaMap[T];
interface LanguageSchemaMap {
yaml: "clash" | "merge";
javascript: never;
css: never;
}
// yaml worker
configureMonacoYaml(monaco, {
validate: true,
enableSchemaRequest: true,
schemas: [
{
uri: "http://example.com/meta-json-schema.json",
fileMatch: ["**/*.clash.yaml"],
//@ts-ignore
schema: metaSchema as JSONSchema7,
},
{
uri: "http://example.com/clash-verge-merge-json-schema.json",
fileMatch: ["**/*.merge.yaml"],
//@ts-ignore
schema: mergeSchema as JSONSchema7,
},
],
});
// PAC definition
monaco.languages.typescript.javascriptDefaults.addExtraLib(pac, "pac.d.ts");
monaco.languages.registerCompletionItemProvider("javascript", {
provideCompletionItems: (model, position) => ({
suggestions: [
interface Props<T extends Language> {
open: boolean;
title?: string | ReactNode;
initialData: Promise<string>;
readOnly?: boolean;
language: T;
schema?: Schema<T>;
onChange?: (prev?: string, curr?: string) => void;
onSave?: (prev?: string, curr?: string) => void;
onClose: () => void;
}
let initialized = false;
const monacoInitialization = () => {
if (initialized) return;
// configure yaml worker
configureMonacoYaml(monaco, {
validate: true,
enableSchemaRequest: true,
schemas: [
{
label: "%mixed-port%",
kind: monaco.languages.CompletionItemKind.Text,
insertText: "%mixed-port%",
range: {
startLineNumber: position.lineNumber,
endLineNumber: position.lineNumber,
startColumn: model.getWordUntilPosition(position).startColumn - 1,
endColumn: model.getWordUntilPosition(position).endColumn - 1,
},
uri: "http://example.com/meta-json-schema.json",
fileMatch: ["**/*.clash.yaml"],
// @ts-ignore
schema: metaSchema as JSONSchema7,
},
{
uri: "http://example.com/clash-verge-merge-json-schema.json",
fileMatch: ["**/*.merge.yaml"],
// @ts-ignore
schema: mergeSchema as JSONSchema7,
},
],
}),
});
});
// configure PAC definition
monaco.languages.typescript.javascriptDefaults.addExtraLib(pac, "pac.d.ts");
export const EditorViewer = (props: Props) => {
const {
title,
mode,
property,
open,
readOnly,
language,
schema,
onClose,
onChange,
} = props;
initialized = true;
};
export const EditorViewer = <T extends Language>(props: Props<T>) => {
const { t } = useTranslation();
const editorRef = useRef<any>();
const instanceRef = useRef<editor.IStandaloneCodeEditor | null>(null);
const themeMode = useThemeMode();
const prevData = useRef<string>();
const [isMaximized, setIsMaximized] = useState(false);
useEffect(() => {
if (!open) return;
const {
open = false,
title = t("Edit File"),
initialData = Promise.resolve(""),
readOnly = false,
language = "yaml",
schema,
onChange,
onSave,
onClose,
} = props;
let fetchContent;
switch (mode) {
case "profile": // profile文件
fetchContent = readProfileFile(property);
break;
case "text": // 文本内容
fetchContent = Promise.resolve(property);
break;
}
fetchContent.then((data) => {
const dom = editorRef.current;
const editorRef = useRef<monaco.editor.IStandaloneCodeEditor>();
const prevData = useRef<string | undefined>("");
const currData = useRef<string | undefined>("");
if (!dom) return;
const editorWillMount = () => {
monacoInitialization(); // initialize monaco
};
if (instanceRef.current) instanceRef.current.dispose();
const editorDidMount = async (
editor: monaco.editor.IStandaloneCodeEditor
) => {
editorRef.current = editor;
// retrieve initial data
await initialData.then((data) => {
prevData.current = data;
currData.current = data;
// create and set model
const uri = monaco.Uri.parse(`${nanoid()}.${schema}.${language}`);
const model = monaco.editor.createModel(data, language, uri);
instanceRef.current = editor.create(editorRef.current, {
model: model,
language: language,
tabSize: ["yaml", "javascript", "css"].includes(language) ? 2 : 4, // 根据语言类型设置缩进大小
theme: themeMode === "light" ? "vs" : "vs-dark",
minimap: { enabled: dom.clientWidth >= 1000 }, // 超过一定宽度显示minimap滚动条
mouseWheelZoom: true, // 按住Ctrl滚轮调节缩放比例
readOnly: readOnly, // 只读模式
readOnlyMessage: { value: t("ReadOnlyMessage") }, // 只读模式尝试编辑时的提示信息
renderValidationDecorations: "on", // 只读模式下显示校验信息
quickSuggestions: {
strings: true, // 字符串类型的建议
comments: true, // 注释类型的建议
other: true, // 其他类型的建议
},
padding: {
top: 33, // 顶部padding防止遮挡snippets
},
fontFamily: `Fira Code, JetBrains Mono, Roboto Mono, "Source Code Pro", Consolas, Menlo, Monaco, monospace, "Courier New", "Apple Color Emoji"${
getSystem() === "windows" ? ", twemoji mozilla" : ""
}`,
fontLigatures: true, // 连字符
smoothScrolling: true, // 平滑滚动
});
prevData.current = data;
editorRef.current?.setModel(model);
});
};
return () => {
if (instanceRef.current) {
instanceRef.current.dispose();
instanceRef.current = null;
}
};
}, [open]);
const onSave = useLockFn(async () => {
const currData = instanceRef.current?.getValue();
if (currData == null) return;
const handleChange = useLockFn(async (value: string | undefined) => {
try {
if (mode === "profile") {
await saveProfileFile(property, currData);
}
onChange?.(prevData.current, currData);
currData.current = value;
onChange?.(prevData.current, currData.current);
} catch (err: any) {
Notice.error(err.message || err.toString());
}
});
const handleSave = useLockFn(async () => {
try {
!readOnly && onSave?.(prevData.current, currData.current);
onClose();
} catch (err: any) {
Notice.error(err.message || err.toString());
}
});
const handleClose = useLockFn(async () => {
try {
onClose();
} catch (err: any) {
Notice.error(err.message || err.toString());
}
});
useEffect(() => {
const unlistenResized = appWindow.onResized(() => {
appWindow.isMaximized().then((maximized) => {
setIsMaximized(() => maximized);
});
});
return () => {
unlistenResized.then((fn) => fn());
editorRef.current?.dispose();
editorRef.current = undefined;
};
}, []);
return (
<Dialog open={open} onClose={onClose} maxWidth="xl" fullWidth>
<DialogTitle>{title ?? t("Edit File")}</DialogTitle>
<DialogTitle>{title}</DialogTitle>
<DialogContent sx={{ width: "auto", height: "100vh" }}>
<div style={{ width: "100%", height: "100%" }} ref={editorRef} />
<MonacoEditor
language={language}
theme={themeMode === "light" ? "vs" : "vs-dark"}
options={{
tabSize: ["yaml", "javascript", "css"].includes(language) ? 2 : 4, // 根据语言类型设置缩进大小
minimap: {
enabled: document.documentElement.clientWidth >= 1500, // 超过一定宽度显示minimap滚动条
},
mouseWheelZoom: true, // 按住Ctrl滚轮调节缩放比例
readOnly: readOnly, // 只读模式
readOnlyMessage: { value: t("ReadOnlyMessage") }, // 只读模式尝试编辑时的提示信息
renderValidationDecorations: "on", // 只读模式下显示校验信息
quickSuggestions: {
strings: true, // 字符串类型的建议
comments: true, // 注释类型的建议
other: true, // 其他类型的建议
},
padding: {
top: 33, // 顶部padding防止遮挡snippets
},
fontFamily: `Fira Code, JetBrains Mono, Roboto Mono, "Source Code Pro", Consolas, Menlo, Monaco, monospace, "Courier New", "Apple Color Emoji"${
getSystem() === "windows" ? ", twemoji mozilla" : ""
}`,
fontLigatures: true, // 连字符
smoothScrolling: true, // 平滑滚动
}}
editorWillMount={editorWillMount}
editorDidMount={editorDidMount}
onChange={handleChange}
/>
<ButtonGroup
variant="contained"
sx={{ position: "absolute", left: "14px", bottom: "8px" }}
>
<IconButton
size="medium"
color="inherit"
sx={{ display: readOnly ? "none" : "" }}
title={t("Format document")}
onClick={() =>
editorRef.current
?.getAction("editor.action.formatDocument")
?.run()
}
>
<FormatPaintIcon fontSize="inherit" />
</IconButton>
<IconButton
size="medium"
color="inherit"
title={t(isMaximized ? "Minimize" : "Maximize")}
onClick={() =>
appWindow.toggleMaximize().then(() => editorRef.current?.layout())
}
>
{isMaximized ? <CloseFullscreenIcon /> : <OpenInFullIcon />}
</IconButton>
</ButtonGroup>
</DialogContent>
<DialogActions>
<Button onClick={onClose} variant="outlined">
<Button onClick={handleClose} variant="outlined">
{t(readOnly ? "Close" : "Cancel")}
</Button>
{!readOnly && (
<Button onClick={onSave} variant="contained">
<Button onClick={handleSave} variant="contained">
{t("Save")}
</Button>
)}
@@ -17,7 +17,12 @@ import {
} from "@mui/material";
import { RefreshRounded, DragIndicator } from "@mui/icons-material";
import { useLoadingCache, useSetLoadingCache } from "@/services/states";
import { updateProfile, viewProfile } from "@/services/cmds";
import {
viewProfile,
readProfileFile,
updateProfile,
saveProfileFile,
} from "@/services/cmds";
import { Notice } from "@/components/base";
import { RulesEditorViewer } from "@/components/profile/rules-editor-viewer";
import { EditorViewer } from "@/components/profile/editor-viewer";
@@ -37,20 +42,13 @@ interface Props {
itemData: IProfileItem;
onSelect: (force: boolean) => void;
onEdit: () => void;
onChange?: (prev?: string, curr?: string) => void;
onSave?: (prev?: string, curr?: string) => void;
onDelete: () => void;
}
export const ProfileItem = (props: Props) => {
const {
selected,
activating,
itemData,
onSelect,
onEdit,
onChange,
onDelete,
} = props;
const { selected, activating, itemData, onSelect, onEdit, onSave, onDelete } =
props;
const { attributes, listeners, setNodeRef, transform, transition } =
useSortable({ id: props.id });
@@ -215,16 +213,16 @@ export const ProfileItem = (props: Props) => {
handler: onEditRules,
disabled: option?.rules === null,
},
{
label: "Edit Proxies",
handler: onEditProxies,
disabled: option?.proxies === null,
},
{
label: "Edit Groups",
handler: onEditGroups,
disabled: option?.groups === null,
},
// {
// label: "Edit Proxies",
// handler: onEditProxies,
// disabled: option?.proxies === null,
// },
// {
// label: "Edit Groups",
// handler: onEditGroups,
// disabled: option?.groups === null,
// },
{
label: "Extend Config",
handler: onEditMerge,
@@ -256,16 +254,16 @@ export const ProfileItem = (props: Props) => {
handler: onEditRules,
disabled: option?.rules === null,
},
{
label: "Edit Proxies",
handler: onEditProxies,
disabled: option?.proxies === null,
},
{
label: "Edit Groups",
handler: onEditGroups,
disabled: option?.groups === null,
},
// {
// label: "Edit Proxies",
// handler: onEditProxies,
// disabled: option?.proxies === null,
// },
// {
// label: "Edit Groups",
// handler: onEditGroups,
// disabled: option?.groups === null,
// },
{
label: "Extend Config",
handler: onEditMerge,
@@ -474,55 +472,62 @@ export const ProfileItem = (props: Props) => {
</Menu>
<EditorViewer
mode="profile"
property={uid}
open={fileOpen}
initialData={readProfileFile(uid)}
language="yaml"
schema="clash"
onChange={onChange}
onSave={async (prev, curr) => {
await saveProfileFile(uid, curr ?? "");
onSave && onSave(prev, curr);
}}
onClose={() => setFileOpen(false)}
/>
<RulesEditorViewer
profileUid={uid}
property={option?.rules ?? ""}
open={rulesOpen}
onChange={onChange}
onSave={onSave}
onClose={() => setRulesOpen(false)}
/>
<EditorViewer
mode="profile"
property={option?.proxies ?? ""}
open={proxiesOpen}
initialData={readProfileFile(option?.proxies ?? "")}
language="yaml"
schema={undefined}
onChange={onChange}
onSave={async (prev, curr) => {
await saveProfileFile(option?.proxies ?? "", curr ?? "");
onSave && onSave(prev, curr);
}}
onClose={() => setProxiesOpen(false)}
/>
<EditorViewer
mode="profile"
property={option?.groups ?? ""}
open={groupsOpen}
initialData={readProfileFile(option?.proxies ?? "")}
language="yaml"
schema={undefined}
onChange={onChange}
onSave={async (prev, curr) => {
await saveProfileFile(option?.proxies ?? "", curr ?? "");
onSave && onSave(prev, curr);
}}
onClose={() => setGroupsOpen(false)}
/>
<EditorViewer
mode="profile"
property={option?.merge ?? ""}
open={mergeOpen}
initialData={readProfileFile(option?.merge ?? "")}
language="yaml"
schema="merge"
onChange={onChange}
schema="clash"
onSave={async (prev, curr) => {
await saveProfileFile(option?.merge ?? "", curr ?? "");
onSave && onSave(prev, curr);
}}
onClose={() => setMergeOpen(false)}
/>
<EditorViewer
mode="profile"
property={option?.script ?? ""}
open={scriptOpen}
initialData={readProfileFile(option?.script ?? "")}
language="javascript"
schema={undefined}
onChange={onChange}
onSave={async (prev, curr) => {
await saveProfileFile(option?.script ?? "", curr ?? "");
onSave && onSave(prev, curr);
}}
onClose={() => setScriptOpen(false)}
/>
<ConfirmViewer
@@ -11,7 +11,7 @@ import {
IconButton,
} from "@mui/material";
import { FeaturedPlayListRounded } from "@mui/icons-material";
import { viewProfile } from "@/services/cmds";
import { viewProfile, readProfileFile, saveProfileFile } from "@/services/cmds";
import { Notice } from "@/components/base";
import { EditorViewer } from "@/components/profile/editor-viewer";
import { ProfileBox } from "./profile-box";
@@ -20,14 +20,14 @@ import { LogViewer } from "./log-viewer";
interface Props {
logInfo?: [string, string][];
id: "Merge" | "Script";
onChange?: (prev?: string, curr?: string) => void;
onSave?: (prev?: string, curr?: string) => void;
}
// profile enhanced item
export const ProfileMore = (props: Props) => {
const { id, logInfo = [], onChange } = props;
const { id, logInfo = [], onSave } = props;
const { t, i18n } = useTranslation();
const { t } = useTranslation();
const [anchorEl, setAnchorEl] = useState<any>(null);
const [position, setPosition] = useState({ left: 0, top: 0 });
const [fileOpen, setFileOpen] = useState(false);
@@ -169,12 +169,15 @@ export const ProfileMore = (props: Props) => {
</Menu>
<EditorViewer
mode="profile"
property={id}
open={fileOpen}
title={`${t("Global " + id)}`}
initialData={readProfileFile(id)}
language={id === "Merge" ? "yaml" : "javascript"}
schema={id === "Merge" ? "merge" : undefined}
onChange={onChange}
schema={id === "Merge" ? "clash" : undefined}
onSave={async (prev, curr) => {
await saveProfileFile(id, curr ?? "");
onSave && onSave(prev, curr);
}}
onClose={() => setFileOpen(false)}
/>
@@ -46,10 +46,14 @@ export const RuleItem = (props: Props) => {
primary={
<>
<Typography
sx={{ textDecoration: type === "delete" ? "line-through" : "" }}
sx={{
textDecoration: type === "delete" ? "line-through" : "",
overflow: "hidden",
whiteSpace: "nowrap",
textOverflow: "ellipsis",
}}
variant="h6"
component="span"
noWrap
title={rule.length === 3 ? rule[1] : "-"}
>
{rule.length === 3 ? rule[1] : "-"}
</Typography>
@@ -17,6 +17,7 @@ import {
} from "@dnd-kit/sortable";
import {
Autocomplete,
Box,
Button,
Dialog,
DialogActions,
@@ -33,6 +34,8 @@ import { readProfileFile, saveProfileFile } from "@/services/cmds";
import { Notice, Switch } from "@/components/base";
import getSystem from "@/utils/get-system";
import { RuleItem } from "@/components/profile/rule-item";
import { BaseSearchBox } from "../base/base-search-box";
import { Virtuoso } from "react-virtuoso";
interface Props {
profileUid: string;
@@ -40,103 +43,201 @@ interface Props {
property: string;
open: boolean;
onClose: () => void;
onChange?: (prev?: string, curr?: string) => void;
onSave?: (prev?: string, curr?: string) => void;
}
const RuleTypeList = [
"DOMAIN",
"DOMAIN-SUFFIX",
"DOMAIN-KEYWORD",
"DOMAIN-REGEX",
"GEOSITE",
"IP-CIDR",
"IP-SUFFIX",
"IP-ASN",
"GEOIP",
"SRC-GEOIP",
"SRC-IP-ASN",
"SRC-IP-CIDR",
"SRC-IP-SUFFIX",
"DST-PORT",
"SRC-PORT",
"IN-PORT",
"IN-TYPE",
"IN-USER",
"IN-NAME",
"PROCESS-PATH",
"PROCESS-PATH-REGEX",
"PROCESS-NAME",
"PROCESS-NAME-REGEX",
"UID",
"NETWORK",
"DSCP",
"RULE-SET",
"SUB-RULE",
"AND",
"OR",
"NOT",
"MATCH",
] as const;
const NoResolveList = [
"GEOIP",
"IP-ASN",
"IP-CIDR",
"IP-CIDR6",
"IP-SUFFIX",
"RULE-SET",
];
const ExampleMap = {
DOMAIN: "example.com",
"DOMAIN-SUFFIX": "example.com",
"DOMAIN-KEYWORD": "example",
"DOMAIN-REGEX": "example.*",
GEOSITE: "youtube",
"IP-CIDR": "127.0.0.0/8",
"IP-SUFFIX": "8.8.8.8/24",
"IP-ASN": "13335",
GEOIP: "CN",
"SRC-GEOIP": "cn",
"SRC-IP-ASN": "9808",
"SRC-IP-CIDR": "192.168.1.201/32",
"SRC-IP-SUFFIX": "192.168.1.201/8",
"DST-PORT": "80",
"SRC-PORT": "7777",
"IN-PORT": "7890",
"IN-TYPE": "SOCKS/HTTP",
"IN-USER": "mihomo",
"IN-NAME": "ss",
"PROCESS-PATH":
getSystem() === "windows"
? "C:Program FilesGoogleChromeApplicationchrome.exe"
: "/usr/bin/wget",
"PROCESS-PATH-REGEX":
getSystem() === "windows" ? "(?i).*Application\\chrome.*" : ".*bin/wget",
"PROCESS-NAME": getSystem() === "windows" ? "chrome.exe" : "curl",
"PROCESS-NAME-REGEX": ".*telegram.*",
UID: "1001",
NETWORK: "udp",
DSCP: "4",
"RULE-SET": "providername",
"SUB-RULE": "",
AND: "((DOMAIN,baidu.com),(NETWORK,UDP))",
OR: "((NETWORK,UDP),(DOMAIN,baidu.com))",
NOT: "((DOMAIN,baidu.com))",
MATCH: "",
const portValidator = (value: string): boolean => {
return new RegExp(
"^(?:[1-9]\\d{0,3}|[1-5]\\d{4}|6[0-4]\\d{3}|65[0-4]\\d{2}|655[0-2]\\d|6553[0-5])$"
).test(value);
};
const ipv4CIDRValidator = (value: string): boolean => {
return new RegExp(
"^(?:(?:[1-9]?[0-9]|1[0-9][0-9]|2(?:[0-4][0-9]|5[0-5]))\\.){3}(?:[1-9]?[0-9]|1[0-9][0-9]|2(?:[0-4][0-9]|5[0-5]))(?:\\/(?:[12]?[0-9]|3[0-2]))$"
).test(value);
};
const ipv6CIDRValidator = (value: string): boolean => {
return new RegExp(
"^([0-9a-fA-F]{1,4}(?::[0-9a-fA-F]{1,4}){7}|::|:(?::[0-9a-fA-F]{1,4}){1,6}|[0-9a-fA-F]{1,4}:(?::[0-9a-fA-F]{1,4}){1,5}|(?:[0-9a-fA-F]{1,4}:){2}(?::[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){3}(?::[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){4}(?::[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){5}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,6}:)\\/(?:12[0-8]|1[01][0-9]|[1-9]?[0-9])$"
).test(value);
};
const BuiltinProxyPolicyList = ["DIRECT", "REJECT", "REJECT-DROP", "PASS"];
const rules: {
name: string;
required?: boolean;
example?: string;
noResolve?: boolean;
validator?: (value: string) => boolean;
}[] = [
{
name: "DOMAIN",
example: "example.com",
},
{
name: "DOMAIN-SUFFIX",
example: "example.com",
},
{
name: "DOMAIN-KEYWORD",
example: "example",
},
{
name: "DOMAIN-REGEX",
example: "example.*",
},
{
name: "GEOSITE",
example: "youtube",
},
{
name: "GEOIP",
example: "CN",
noResolve: true,
},
{
name: "SRC-GEOIP",
example: "CN",
},
{
name: "IP-ASN",
example: "13335",
noResolve: true,
validator: (value) => (+value ? true : false),
},
{
name: "SRC-IP-ASN",
example: "9808",
validator: (value) => (+value ? true : false),
},
{
name: "IP-CIDR",
example: "127.0.0.0/8",
noResolve: true,
validator: (value) => ipv4CIDRValidator(value) || ipv6CIDRValidator(value),
},
{
name: "IP-CIDR6",
example: "2620:0:2d0:200::7/32",
noResolve: true,
validator: (value) => ipv4CIDRValidator(value) || ipv6CIDRValidator(value),
},
{
name: "SRC-IP-CIDR",
example: "192.168.1.201/32",
validator: (value) => ipv4CIDRValidator(value) || ipv6CIDRValidator(value),
},
{
name: "IP-SUFFIX",
example: "8.8.8.8/24",
noResolve: true,
validator: (value) => ipv4CIDRValidator(value) || ipv6CIDRValidator(value),
},
{
name: "SRC-IP-SUFFIX",
example: "192.168.1.201/8",
validator: (value) => ipv4CIDRValidator(value) || ipv6CIDRValidator(value),
},
{
name: "SRC-PORT",
example: "7777",
validator: (value) => portValidator(value),
},
{
name: "DST-PORT",
example: "80",
validator: (value) => portValidator(value),
},
{
name: "IN-PORT",
example: "7890",
validator: (value) => portValidator(value),
},
{
name: "DSCP",
example: "4",
},
{
name: "PROCESS-NAME",
example: getSystem() === "windows" ? "chrome.exe" : "curl",
},
{
name: "PROCESS-PATH",
example:
getSystem() === "windows"
? "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe"
: "/usr/bin/wget",
},
{
name: "PROCESS-NAME-REGEX",
example: ".*telegram.*",
},
{
name: "PROCESS-PATH-REGEX",
example:
getSystem() === "windows" ? "(?i).*Application\\chrome.*" : ".*bin/wget",
},
{
name: "NETWORK",
example: "udp",
validator: (value) => ["tcp", "udp"].includes(value),
},
{
name: "UID",
example: "1001",
validator: (value) => (+value ? true : false),
},
{
name: "IN-TYPE",
example: "SOCKS/HTTP",
},
{
name: "IN-USER",
example: "mihomo",
},
{
name: "IN-NAME",
example: "ss",
},
{
name: "SUB-RULE",
example: "(NETWORK,tcp)",
},
{
name: "RULE-SET",
example: "providername",
noResolve: true,
},
{
name: "AND",
example: "((DOMAIN,baidu.com),(NETWORK,UDP))",
},
{
name: "OR",
example: "((NETWORK,UDP),(DOMAIN,baidu.com))",
},
{
name: "NOT",
example: "((DOMAIN,baidu.com))",
},
{
name: "MATCH",
required: false,
},
];
const builtinProxyPolicies = ["DIRECT", "REJECT", "REJECT-DROP", "PASS"];
export const RulesEditorViewer = (props: Props) => {
const { title, profileUid, property, open, onClose, onChange } = props;
const { title, profileUid, property, open, onClose, onSave } = props;
const { t } = useTranslation();
const [prevData, setPrevData] = useState("");
const [ruleType, setRuleType] =
useState<(typeof RuleTypeList)[number]>("DOMAIN");
const [match, setMatch] = useState(() => (_: string) => true);
const [ruleType, setRuleType] = useState<(typeof rules)[number]>(rules[0]);
const [ruleContent, setRuleContent] = useState("");
const [noResolve, setNoResolve] = useState(false);
const [proxyPolicy, setProxyPolicy] = useState("DIRECT");
const [proxyPolicy, setProxyPolicy] = useState(builtinProxyPolicies[0]);
const [proxyPolicyList, setProxyPolicyList] = useState<string[]>([]);
const [ruleList, setRuleList] = useState<string[]>([]);
const [ruleSetList, setRuleSetList] = useState<string[]>([]);
@@ -195,7 +296,7 @@ export const RulesEditorViewer = (props: Props) => {
let ruleSetObj = yaml.load(data) as { "rule-providers": [] };
let subRuleObj = yaml.load(data) as { "sub-rules": [] };
setProxyPolicyList(
BuiltinProxyPolicyList.concat(
builtinProxyPolicies.concat(
groupsObj["proxy-groups"]
? groupsObj["proxy-groups"].map((item: any) => item.name)
: []
@@ -217,7 +318,20 @@ export const RulesEditorViewer = (props: Props) => {
fetchProfile();
}, [open]);
const onSave = useLockFn(async () => {
const validateRule = () => {
if ((ruleType.required ?? true) && !ruleContent) {
throw new Error(t("Rule Condition Required"));
}
if (ruleType.validator && !ruleType.validator(ruleContent)) {
throw new Error(t("Invalid Rule"));
}
return `${ruleType.name}${
ruleContent ? "," + ruleContent : ""
},${proxyPolicy}${ruleType.noResolve && noResolve ? ",no-resolve" : ""}`;
};
const handleSave = useLockFn(async () => {
try {
let currData = yaml.dump({
prepend: prependSeq,
@@ -225,7 +339,7 @@ export const RulesEditorViewer = (props: Props) => {
delete: deleteSeq,
});
await saveProfileFile(property, currData);
onChange?.(prevData, currData);
onSave?.(prevData, currData);
onClose();
} catch (err: any) {
Notice.error(err.message || err.toString());
@@ -237,106 +351,106 @@ export const RulesEditorViewer = (props: Props) => {
<DialogTitle>{title ?? t("Edit Rules")}</DialogTitle>
<DialogContent sx={{ display: "flex", width: "auto", height: "100vh" }}>
<div
style={{
<List
sx={{
height: "calc(100% - 16px)",
width: "50%",
height: "100%",
padding: "0 10px",
}}
>
<List>
<Item>
<ListItemText primary={t("Rule Type")} />
<Item>
<ListItemText primary={t("Rule Type")} />
<Autocomplete
size="small"
sx={{ minWidth: "240px" }}
renderInput={(params) => <TextField {...params} />}
options={rules}
value={ruleType}
getOptionLabel={(option) => option.name}
renderOption={(props, option) => (
<li {...props} title={t(option.name)}>
{option.name}
</li>
)}
onChange={(_, value) => value && setRuleType(value)}
/>
</Item>
<Item sx={{ display: !(ruleType.required ?? true) ? "none" : "" }}>
<ListItemText primary={t("Rule Content")} />
{ruleType.name === "RULE-SET" && (
<Autocomplete
size="small"
sx={{ minWidth: "240px" }}
value={ruleType}
options={RuleTypeList}
onChange={(_, v) => {
if (v) setRuleType(v);
}}
renderInput={(params) => <TextField {...params} />}
options={ruleSetList}
value={ruleContent}
onChange={(_, value) => value && setRuleContent(value)}
/>
</Item>
<Item>
<ListItemText primary={t("Rule Content")} />
{ruleType === "RULE-SET" && (
<Autocomplete
size="small"
sx={{ minWidth: "240px" }}
value={ruleContent}
options={ruleSetList}
onChange={(_, v) => {
if (v) setRuleContent(v);
}}
renderInput={(params) => <TextField {...params} />}
/>
)}
{ruleType === "SUB-RULE" && (
<Autocomplete
size="small"
sx={{ minWidth: "240px" }}
value={ruleContent}
options={subRuleList}
onChange={(_, v) => {
if (v) setRuleContent(v);
}}
renderInput={(params) => <TextField {...params} />}
/>
)}
{ruleType !== "RULE-SET" && ruleType !== "SUB-RULE" && (
<TextField
size="small"
sx={{ minWidth: "240px" }}
value={ruleContent}
placeholder={ExampleMap[ruleType]}
onChange={(e) => {
setRuleContent(e.target.value);
}}
/>
)}
</Item>
<Item>
<ListItemText primary={t("Proxy Policy")} />
<Autocomplete
size="small"
sx={{ minWidth: "240px" }}
value={proxyPolicy}
options={proxyPolicyList}
onChange={(_, v) => {
if (v) setProxyPolicy(v);
}}
renderInput={(params) => <TextField {...params} />}
/>
</Item>
{NoResolveList.includes(ruleType) && (
<Item>
<ListItemText primary={t("No Resolve")} />
<Switch
checked={noResolve}
onChange={() => {
setNoResolve(!noResolve);
}}
/>
</Item>
)}
</List>
{ruleType.name === "SUB-RULE" && (
<Autocomplete
size="small"
sx={{ minWidth: "240px" }}
renderInput={(params) => <TextField {...params} />}
options={subRuleList}
value={ruleContent}
onChange={(_, value) => value && setRuleContent(value)}
/>
)}
{ruleType.name !== "RULE-SET" && ruleType.name !== "SUB-RULE" && (
<TextField
autoComplete="off"
size="small"
sx={{ minWidth: "240px" }}
value={ruleContent}
required={ruleType.required ?? true}
error={(ruleType.required ?? true) && !ruleContent}
placeholder={ruleType.example}
onChange={(e) => setRuleContent(e.target.value)}
/>
)}
</Item>
<Item>
<ListItemText primary={t("Proxy Policy")} />
<Autocomplete
size="small"
sx={{ minWidth: "240px" }}
renderInput={(params) => <TextField {...params} />}
options={proxyPolicyList}
value={proxyPolicy}
renderOption={(props, option) => (
<li {...props} title={t(option)}>
{option}
</li>
)}
onChange={(_, value) => value && setProxyPolicy(value)}
/>
</Item>
{ruleType.noResolve && (
<Item>
<ListItemText primary={t("No Resolve")} />
<Switch
checked={noResolve}
onChange={() => setNoResolve(!noResolve)}
/>
</Item>
)}
<Item>
<Button
fullWidth
variant="contained"
onClick={() => {
let raw = `${ruleType}${
ruleType === "MATCH" ? "" : "," + ruleContent
},${proxyPolicy}${
NoResolveList.includes(ruleType) && noResolve
? ",no-resolve"
: ""
}`;
if (prependSeq.includes(raw)) return;
setPrependSeq([...prependSeq, raw]);
try {
let raw = validateRule();
if (prependSeq.includes(raw)) return;
setPrependSeq([...prependSeq, raw]);
} catch (err: any) {
Notice.error(err.message || err.toString());
}
}}
>
{t("Add Prepend Rule")}
{t("Prepend Rule")}
</Button>
</Item>
<Item>
@@ -344,107 +458,119 @@ export const RulesEditorViewer = (props: Props) => {
fullWidth
variant="contained"
onClick={() => {
let raw = `${ruleType}${
ruleType === "MATCH" ? "" : "," + ruleContent
},${proxyPolicy}${
NoResolveList.includes(ruleType) && noResolve
? ",no-resolve"
: ""
}`;
if (appendSeq.includes(raw)) return;
setAppendSeq([...appendSeq, raw]);
try {
let raw = validateRule();
if (appendSeq.includes(raw)) return;
setAppendSeq([...appendSeq, raw]);
} catch (err: any) {
Notice.error(err.message || err.toString());
}
}}
>
{t("Add Append Rule")}
{t("Append Rule")}
</Button>
</Item>
</div>
<div
style={{
display: "inline-block",
width: "50%",
height: "100%",
overflow: "auto",
marginLeft: "10px",
}}
</List>
<List
sx={{ height: "calc(100% - 16px)", width: "50%", padding: "0 10px" }}
>
{prependSeq.length > 0 && (
<DndContext
sensors={sensors}
collisionDetection={closestCenter}
onDragEnd={onPrependDragEnd}
>
<List sx={{ borderBottom: "solid 1px var(--divider-color)" }}>
<SortableContext
items={prependSeq.map((x) => {
return x;
})}
>
{prependSeq.map((item, index) => {
return (
<RuleItem
key={`${item}-${index}`}
type="prepend"
ruleRaw={item}
onDelete={() => {
setPrependSeq(prependSeq.filter((v) => v !== item));
}}
/>
);
})}
</SortableContext>
</List>
</DndContext>
)}
<List>
{ruleList.map((item, index) => {
return (
<RuleItem
key={`${item}-${index}`}
type={deleteSeq.includes(item) ? "delete" : "original"}
ruleRaw={item}
onDelete={() => {
if (deleteSeq.includes(item)) {
setDeleteSeq(deleteSeq.filter((v) => v !== item));
} else {
setDeleteSeq([...deleteSeq, item]);
<BaseSearchBox
matchCase={false}
onSearch={(match) => setMatch(() => match)}
/>
<Virtuoso
style={{ height: "calc(100% - 16px)", marginTop: "8px" }}
totalCount={
ruleList.length +
(prependSeq.length > 0 ? 1 : 0) +
(appendSeq.length > 0 ? 1 : 0)
}
increaseViewportBy={256}
itemContent={(index) => {
let shift = prependSeq.length > 0 ? 1 : 0;
if (prependSeq.length > 0 && index === 0) {
return (
<DndContext
sensors={sensors}
collisionDetection={closestCenter}
onDragEnd={onPrependDragEnd}
>
<SortableContext
items={prependSeq.map((x) => {
return x;
})}
>
{prependSeq.map((item, index) => {
return (
<RuleItem
key={`${item}-${index}`}
type="prepend"
ruleRaw={item}
onDelete={() => {
setPrependSeq(
prependSeq.filter((v) => v !== item)
);
}}
/>
);
})}
</SortableContext>
</DndContext>
);
} else if (index < ruleList.length + shift) {
let newIndex = index - shift;
return (
<RuleItem
key={`${ruleList[newIndex]}-${index}`}
type={
deleteSeq.includes(ruleList[newIndex])
? "delete"
: "original"
}
}}
/>
);
})}
</List>
{appendSeq.length > 0 && (
<DndContext
sensors={sensors}
collisionDetection={closestCenter}
onDragEnd={onAppendDragEnd}
>
<SortableContext
items={appendSeq.map((x) => {
return x;
})}
>
<List sx={{ borderTop: "solid 1px var(--divider-color)" }}>
{appendSeq.map((item, index) => {
return (
<RuleItem
key={`${item}-${index}`}
type="append"
ruleRaw={item}
onDelete={() => {
setAppendSeq(appendSeq.filter((v) => v !== item));
}}
/>
);
})}
</List>
</SortableContext>
</DndContext>
)}
</div>
ruleRaw={ruleList[newIndex]}
onDelete={() => {
if (deleteSeq.includes(ruleList[newIndex])) {
setDeleteSeq(
deleteSeq.filter((v) => v !== ruleList[newIndex])
);
} else {
setDeleteSeq((prev) => [...prev, ruleList[newIndex]]);
}
}}
/>
);
} else {
return (
<DndContext
sensors={sensors}
collisionDetection={closestCenter}
onDragEnd={onAppendDragEnd}
>
<SortableContext
items={appendSeq.map((x) => {
return x;
})}
>
{appendSeq.map((item, index) => {
return (
<RuleItem
key={`${item}-${index}`}
type="append"
ruleRaw={item}
onDelete={() => {
setAppendSeq(appendSeq.filter((v) => v !== item));
}}
/>
);
})}
</SortableContext>
</DndContext>
);
}
}}
/>
</List>
</DialogContent>
<DialogActions>
@@ -452,7 +578,7 @@ export const RulesEditorViewer = (props: Props) => {
{t("Cancel")}
</Button>
<Button onClick={onSave} variant="contained">
<Button onClick={handleSave} variant="contained">
{t("Save")}
</Button>
</DialogActions>
@@ -132,6 +132,7 @@ export const ProxyHead = (props: Props) => {
{textState === "filter" && (
<TextField
autoComplete="off"
autoFocus={autoFocus}
hiddenLabel
value={filterText}
@@ -145,10 +146,10 @@ export const ProxyHead = (props: Props) => {
{textState === "url" && (
<TextField
autoComplete="off"
autoFocus={autoFocus}
hiddenLabel
autoSave="off"
autoComplete="off"
value={testUrl}
size="small"
variant="outlined"
@@ -134,8 +134,8 @@ export const ClashPortViewer = forwardRef<DialogRef>((props, ref) => {
<ListItem sx={{ padding: "5px 2px" }}>
<ListItemText primary={t("Mixed Port")} />
<TextField
size="small"
autoComplete="off"
size="small"
sx={{ width: 135 }}
value={mixedPort}
onChange={(e) =>
@@ -146,8 +146,8 @@ export const ClashPortViewer = forwardRef<DialogRef>((props, ref) => {
<ListItem sx={{ padding: "5px 2px" }}>
<ListItemText primary={t("Socks Port")} />
<TextField
size="small"
autoComplete="off"
size="small"
sx={{ width: 135 }}
value={socksPort}
onChange={(e) =>
@@ -169,8 +169,8 @@ export const ClashPortViewer = forwardRef<DialogRef>((props, ref) => {
<ListItem sx={{ padding: "5px 2px" }}>
<ListItemText primary={t("Http Port")} />
<TextField
size="small"
autoComplete="off"
size="small"
sx={{ width: 135 }}
value={port}
onChange={(e) =>
@@ -193,8 +193,8 @@ export const ClashPortViewer = forwardRef<DialogRef>((props, ref) => {
<ListItem sx={{ padding: "5px 2px" }}>
<ListItemText primary={t("Redir Port")} />
<TextField
size="small"
autoComplete="off"
size="small"
sx={{ width: 135 }}
value={redirPort}
onChange={(e) =>
@@ -218,8 +218,8 @@ export const ClashPortViewer = forwardRef<DialogRef>((props, ref) => {
<ListItem sx={{ padding: "5px 2px" }}>
<ListItemText primary={t("Tproxy Port")} />
<TextField
size="small"
autoComplete="off"
size="small"
sx={{ width: 135 }}
value={tproxyPort}
onChange={(e) =>
@@ -22,15 +22,14 @@ export const ConfigViewer = forwardRef<DialogRef>((_, ref) => {
return (
<EditorViewer
open={open}
title={
<Box>
{t("Runtime Config")}
<Chip label={t("ReadOnly")} size="small" />
</Box>
}
mode="text"
property={runtimeConfig}
open={open}
initialData={Promise.resolve(runtimeConfig)}
readOnly
language="yaml"
schema="clash"
@@ -48,8 +48,8 @@ export const ControllerViewer = forwardRef<DialogRef>((props, ref) => {
<ListItem sx={{ padding: "5px 2px" }}>
<ListItemText primary={t("External Controller")} />
<TextField
size="small"
autoComplete="off"
size="small"
sx={{ width: 175 }}
value={controller}
placeholder="Required"
@@ -60,8 +60,8 @@ export const ControllerViewer = forwardRef<DialogRef>((props, ref) => {
<ListItem sx={{ padding: "5px 2px" }}>
<ListItemText primary={t("Core Secret")} />
<TextField
size="small"
autoComplete="off"
size="small"
sx={{ width: 175 }}
value={secret}
placeholder={t("Recommended")}
@@ -198,8 +198,8 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
/>
<TooltipIcon title={t("Default Latency Test Info")} />
<TextField
size="small"
autoComplete="off"
size="small"
autoCorrect="off"
autoCapitalize="off"
spellCheck="false"
@@ -215,9 +215,9 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
<ListItem sx={{ padding: "5px 2px" }}>
<ListItemText primary={t("Default Latency Timeout")} />
<TextField
autoComplete="off"
size="small"
type="number"
autoComplete="off"
autoCorrect="off"
autoCapitalize="off"
spellCheck="false"
@@ -188,6 +188,7 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
<ListItem sx={{ padding: "5px 2px" }}>
<ListItemText primary={t("Guard Duration")} />
<TextField
autoComplete="off"
disabled={!enabled}
size="small"
value={value.duration}
@@ -218,10 +219,10 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
<>
<ListItemText primary={t("Proxy Bypass")} />
<TextField
autoComplete="off"
error={value.bypass ? !validReg.test(value.bypass) : false}
disabled={!enabled}
size="small"
autoComplete="off"
multiline
rows={4}
sx={{ width: "100%" }}
@@ -233,9 +234,9 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
<ListItemText primary={t("Bypass")} />
<FlexBox>
<TextField
autoComplete="off"
disabled={true}
size="small"
autoComplete="off"
multiline
rows={4}
sx={{ width: "100%" }}
@@ -261,21 +262,18 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
{t("Edit")} PAC
</Button>
<EditorViewer
title={`${t("Edit")} PAC`}
mode="text"
property={value.pac_content ?? ""}
open={editorOpen}
title={`${t("Edit")} PAC`}
initialData={Promise.resolve(value.pac_content ?? "")}
language="javascript"
onChange={(_prev, curr) => {
onSave={(_prev, curr) => {
let pac = DEFAULT_PAC;
if (curr && curr.trim().length > 0) {
pac = curr;
}
setValue((v) => ({ ...v, pac_content: pac }));
}}
onClose={() => {
setEditorOpen(false);
}}
onClose={() => setEditorOpen(false)}
/>
</ListItem>
</>
@@ -124,12 +124,11 @@ export const ThemeViewer = forwardRef<DialogRef>((props, ref) => {
{t("Edit")} CSS
</Button>
<EditorViewer
title={`${t("Edit")} CSS`}
mode="text"
property={theme.css_injection ?? ""}
open={editorOpen}
title={`${t("Edit")} CSS`}
initialData={Promise.resolve(theme.css_injection ?? "")}
language="css"
onChange={(_prev, curr) => {
onSave={(_prev, curr) => {
theme.css_injection = curr;
handleChange("css_injection");
}}
@@ -144,8 +144,8 @@ export const TunViewer = forwardRef<DialogRef>((props, ref) => {
<ListItem sx={{ padding: "5px 2px" }}>
<ListItemText primary={t("Device")} />
<TextField
size="small"
autoComplete="off"
size="small"
autoCorrect="off"
autoCapitalize="off"
spellCheck="false"
@@ -190,8 +190,8 @@ export const TunViewer = forwardRef<DialogRef>((props, ref) => {
<ListItem sx={{ padding: "5px 2px" }}>
<ListItemText primary={t("DNS Hijack")} />
<TextField
size="small"
autoComplete="off"
size="small"
autoCorrect="off"
autoCapitalize="off"
spellCheck="false"
@@ -207,9 +207,9 @@ export const TunViewer = forwardRef<DialogRef>((props, ref) => {
<ListItem sx={{ padding: "5px 2px" }}>
<ListItemText primary={t("MTU")} />
<TextField
autoComplete="off"
size="small"
type="number"
autoComplete="off"
autoCorrect="off"
autoCapitalize="off"
spellCheck="false"
@@ -43,12 +43,12 @@ export const WebUIItem = (props: Props) => {
<>
<Stack spacing={0.75} direction="row" mt={1} mb={1} alignItems="center">
<TextField
autoComplete="off"
fullWidth
size="small"
value={editValue}
onChange={(e) => setEditValue(e.target.value)}
placeholder={t("Support %host, %port, %secret")}
autoComplete="off"
/>
<IconButton
size="small"
@@ -125,8 +125,8 @@ const SettingClash = ({ onError }: Props) => {
}
>
<TextField
disabled={enable_random_port}
autoComplete="off"
disabled={enable_random_port}
size="small"
value={verge_mixed_port ?? 7897}
sx={{ width: 100, input: { py: "7.5px", cursor: "pointer" } }}
+54 -7
View File
@@ -5,6 +5,9 @@
"Close": "Close",
"Cancel": "Cancel",
"Confirm": "Confirm",
"Maximize": "Maximize",
"Minimize": "Minimize",
"Format document": "Format document",
"Empty": "Empty",
"New": "New",
"Edit": "Edit",
@@ -54,11 +57,50 @@
"Edit Rules": "Edit Rules",
"Rule Type": "Rule Type",
"Rule Content": "Rule Content",
"Proxy Policy": "roxy Policy",
"Proxy Policy": "Proxy Policy",
"No Resolve": "No Resolve",
"Add Prepend Rule": "Add Prepend Rule",
"Add Append Rule": "Add Append Rule",
"Prepend Rule": "Prepend Rule",
"Append Rule": "Append Rule",
"Delete Rule": "Delete Rule",
"Rule Condition Required": "Rule Condition Required",
"Invalid Rule": "Invalid Rule",
"DOMAIN": "Matches the full domain name",
"DOMAIN-SUFFIX": "Matches the domain suffix",
"DOMAIN-KEYWORD": "Matches the domain keyword",
"DOMAIN-REGEX": "Matches the domain using regular expressions",
"GEOSITE": "Matches domains within the Geosite",
"GEOIP": "Matches the country code of the IP address",
"SRC-GEOIP": "Matches the country code of the source IP address",
"IP-ASN": "Matches the IP address's ASN",
"SRC-IP-ASN": "Matches the source IP address's ASN",
"IP-CIDR": "Matches the IP address range",
"IP-CIDR6": "Matches the IPv6 address range",
"SRC-IP-CIDR": "Matches the source IP address range",
"IP-SUFFIX": "Matches the IP address suffix range",
"SRC-IP-SUFFIX": "Matches the source IP address suffix range",
"SRC-PORT": "Matches the source port range",
"DST-PORT": "Matches the destination port range",
"IN-PORT": "Matches the inbound port",
"DSCP": "DSCP marking (only for tproxy UDP inbound)",
"PROCESS-NAME": "Matches the process name (Android package name)",
"PROCESS-PATH": "Matches the full process path",
"PROCESS-NAME-REGEX": "Matches the full process name using regular expressions (Android package name)",
"PROCESS-PATH-REGEX": "Matches the full process path using regular expressions",
"NETWORK": "Matches the transport protocol (tcp/udp)",
"UID": "Matches the Linux USER ID",
"IN-TYPE": "Matches the inbound type",
"IN-USER": "Matches the inbound username",
"IN-NAME": "Matches the inbound name",
"SUB-RULE": "Sub-rule",
"RULE-SET": "Matches the rule set",
"AND": "Logical AND",
"OR": "Logical OR",
"NOT": "Logical NOT",
"MATCH": "Matches all requests",
"DIRECT": "Data goes directly outbound",
"REJECT": "Intercepts requests",
"REJECT-DROP": "Discards requests",
"PASS": "Skips this rule when matched",
"Edit Groups": "Edit Proxy Groups",
"Extend Config": "Extend Config",
"Extend Script": "Extend Script",
@@ -162,12 +204,20 @@
"Auto Launch": "Auto Launch",
"Silent Start": "Silent Start",
"Silent Start Info": "Start the program in background mode without displaying the panel",
"TG Channel": "Telegram Channel",
"Manual": "Manual",
"Github Repo": "Github Repo",
"Clash Setting": "Clash Setting",
"Allow Lan": "Allow Lan",
"Allow Lan": "Allow LAN",
"IPv6": "IPv6",
"Log Level": "Log Level",
"Port Config": "Port Config",
"Random Port": "Random Port",
"Mixed Port": "Mixed Port",
"Socks Port": "Socks Port",
"Http Port": "Http(s) Port",
"Redir Port": "Redir Port",
"Tproxy Port": "Tproxy Port",
"External": "External",
"External Controller": "External Controller",
"Core Secret": "Core Secret",
@@ -185,9 +235,6 @@
"Open UWP tool": "Open UWP tool",
"Open UWP tool Info": "Since Windows 8, UWP apps (such as Microsoft Store) are restricted from directly accessing local host network services, and this tool can be used to bypass this restriction",
"Update GeoData": "Update GeoData",
"TG Channel": "Telegram Channel",
"Manual": "Manual",
"Github Repo": "Github Repo",
"Verge Setting": "Verge Setting",
"Language": "Language",
"Theme Mode": "Theme Mode",
+52
View File
@@ -5,6 +5,9 @@
"Close": "بستن",
"Cancel": "لغو",
"Confirm": "تأیید",
"Maximize": "بزرگ‌نمایی",
"Minimize": "کوچک‌نمایی",
"Format document": "فرمت‌بندی سند",
"Empty": "خالی خالی",
"New": "جدید",
"Edit": "ویرایش",
@@ -50,6 +53,55 @@
"Expire Time": "زمان انقضا",
"Create Profile": "ایجاد پروفایل",
"Edit Profile": "ویرایش پروفایل",
"Edit Proxies": "ویرایش پروکسی‌ها",
"Edit Rules": "ویرایش قوانین",
"Rule Type": "نوع قانون",
"Rule Content": "محتوای قانون",
"Proxy Policy": "سیاست پروکسی",
"No Resolve": "بدون حل",
"Prepend Rule": "اضافه کردن قانون به ابتدا",
"Append Rule": "اضافه کردن قانون به انتها",
"Delete Rule": "حذف قانون",
"Rule Condition Required": "شرط قانون الزامی است",
"Invalid Rule": "قانون نامعتبر",
"DOMAIN": "مطابقت با نام کامل دامنه",
"DOMAIN-SUFFIX": "مطابقت با پسوند دامنه",
"DOMAIN-KEYWORD": "مطابقت با کلمه کلیدی دامنه",
"DOMAIN-REGEX": "مطابقت با دامنه با استفاده از عبارات منظم",
"GEOSITE": "مطابقت با دامنه‌های درون Geosite",
"GEOIP": "مطابقت با کد کشور IP",
"SRC-GEOIP": "مطابقت با کد کشور IP مبدا",
"IP-ASN": "مطابقت با ASN آدرس IP",
"SRC-IP-ASN": "مطابقت با ASN آدرس IP مبدا",
"IP-CIDR": "مطابقت با محدوده آدرس IP",
"IP-CIDR6": "مطابقت با محدوده آدرس IPv6",
"SRC-IP-CIDR": "مطابقت با محدوده آدرس IP مبدا",
"IP-SUFFIX": "مطابقت با محدوده پسوند آدرس IP",
"SRC-IP-SUFFIX": "مطابقت با محدوده پسوند آدرس IP مبدا",
"SRC-PORT": "مطابقت با محدوده پورت مبدا",
"DST-PORT": "مطابقت با محدوده پورت مقصد",
"IN-PORT": "مطابقت با پورت ورودی",
"DSCP": "علامت‌گذاری DSCP (فقط برای tproxy UDP ورودی)",
"PROCESS-NAME": "مطابقت با نام فرآیند (نام بسته Android)",
"PROCESS-PATH": "مطابقت با مسیر کامل فرآیند",
"PROCESS-NAME-REGEX": "مطابقت با نام فرآیند با استفاده از عبارات منظم (نام بسته Android)",
"PROCESS-PATH-REGEX": "مطابقت با مسیر کامل فرآیند با استفاده از عبارات منظم",
"NETWORK": "مطابقت با پروتکل انتقال (tcp/udp)",
"UID": "مطابقت با شناسه کاربری Linux",
"IN-TYPE": "مطابقت با نوع ورودی",
"IN-USER": "مطابقت با نام کاربری ورودی",
"IN-NAME": "مطابقت با نام ورودی",
"SUB-RULE": "قانون فرعی",
"RULE-SET": "مطابقت با مجموعه قوانین",
"AND": "منطق AND",
"OR": "منطق OR",
"NOT": "منطق NOT",
"MATCH": "مطابقت با تمام درخواست‌ها",
"DIRECT": "داده‌ها به صورت مستقیم خروجی می‌شوند",
"REJECT": "درخواست‌ها را متوقف می‌کند",
"REJECT-DROP": "درخواست‌ها را نادیده می‌گیرد",
"PASS": "این قانون را در صورت تطابق نادیده می‌گیرد",
"Edit Groups": "ویرایش گروه‌های پروکسی",
"Extend Config": "توسعه پیکربندی",
"Extend Script": "ادغام اسکریپت",
"Global Merge": "تنظیمات گسترده‌ی سراسری",
+55 -3
View File
@@ -5,6 +5,9 @@
"Close": "Закрыть",
"Cancel": "Отмена",
"Confirm": "Подтвердить",
"Maximize": "Развернуть",
"Minimize": "Свернуть",
"Format document": "Форматировать документ",
"Empty": "Пусто",
"New": "Новый",
"Edit": "Редактировать",
@@ -50,6 +53,55 @@
"Expire Time": "Время окончания",
"Create Profile": "Создать профиль",
"Edit Profile": "Изменить профиль",
"Edit Proxies": "Редактировать прокси",
"Edit Rules": "Редактировать правила",
"Rule Type": "Тип правила",
"Rule Content": "Содержимое правила",
"Proxy Policy": "Политика прокси",
"No Resolve": "Без разрешения",
"Prepend Rule": "Добавить правило в начало",
"Append Rule": "Добавить правило в конец",
"Delete Rule": "Удалить правило",
"Rule Condition Required": "Требуется условие правила",
"Invalid Rule": "Недействительное правило",
"DOMAIN": "Соответствует полному доменному имени",
"DOMAIN-SUFFIX": "Соответствует суффиксу домена",
"DOMAIN-KEYWORD": "Соответствует ключевому слову домена",
"DOMAIN-REGEX": "Соответствует домену с использованием регулярных выражений",
"GEOSITE": "Соответствует доменам в Geosite",
"GEOIP": "Соответствует коду страны IP-адреса",
"SRC-GEOIP": "Соответствует коду страны исходного IP-адреса",
"IP-ASN": "Соответствует ASN IP-адреса",
"SRC-IP-ASN": "Соответствует ASN исходного IP-адреса",
"IP-CIDR": "Соответствует диапазону IP-адресов",
"IP-CIDR6": "Соответствует диапазону IPv6-адресов",
"SRC-IP-CIDR": "Соответствует диапазону исходных IP-адресов",
"IP-SUFFIX": "Соответствует диапазону суффиксов IP-адресов",
"SRC-IP-SUFFIX": "Соответствует диапазону суффиксов исходных IP-адресов",
"SRC-PORT": "Соответствует диапазону исходных портов",
"DST-PORT": "Соответствует диапазону целевых портов",
"IN-PORT": "Соответствует входящему порту",
"DSCP": "Маркировка DSCP (только для tproxy UDP входящего)",
"PROCESS-NAME": "Соответствует имени процесса (имя пакета Android)",
"PROCESS-PATH": "Соответствует полному пути процесса",
"PROCESS-NAME-REGEX": "Соответствует имени процесса с использованием регулярных выражений (имя пакета Android)",
"PROCESS-PATH-REGEX": "Соответствует полному пути процесса с использованием регулярных выражений",
"NETWORK": "Соответствует транспортному протоколу (tcp/udp)",
"UID": "Соответствует USER ID в Linux",
"IN-TYPE": "Соответствует типу входящего соединения",
"IN-USER": "Соответствует имени пользователя входящего соединения",
"IN-NAME": "Соответствует имени входящего соединения",
"SUB-RULE": "Подправило",
"RULE-SET": "Соответствует набору правил",
"AND": "Логическое И",
"OR": "Логическое ИЛИ",
"NOT": "Логическое НЕ",
"MATCH": "Соответствует всем запросам",
"DIRECT": "Данные направляются напрямую наружу",
"REJECT": "Перехватывает запросы",
"REJECT-DROP": "Отклоняет запросы",
"PASS": "Пропускает это правило при совпадении",
"Edit Groups": "Редактировать группы прокси",
"Extend Config": "Изменить Merge.",
"Extend Script": "Изменить Script",
"Global Merge": "Глобальный расширенный Настройки",
@@ -152,6 +204,9 @@
"Auto Launch": "Автозапуск",
"Silent Start": "Тихий запуск",
"Silent Start Info": "Запускать программу в фоновом режиме без отображения панели",
"TG Channel": "Канал Telegram",
"Manual": "Документация",
"Github Repo": "GitHub репозиторий",
"Clash Setting": "Настройки Clash",
"Allow Lan": "Разрешить локальную сеть",
"IPv6": "IPv6",
@@ -180,9 +235,6 @@
"Open UWP tool": "Открыть UWP инструмент",
"Open UWP tool Info": "С Windows 8 приложения UWP (такие как Microsoft Store) ограничены в прямом доступе к сетевым службам локального хоста, и этот инструмент позволяет обойти это ограничение",
"Update GeoData": "Обновление GeoData",
"TG Channel": "Канал Telegram",
"Manual": "Документация",
"Github Repo": "GitHub репозиторий",
"Verge Setting": "Настройки Verge",
"Language": "Язык",
"Theme Mode": "Режим темы",
+44 -2
View File
@@ -5,6 +5,9 @@
"Close": "关闭",
"Cancel": "取消",
"Confirm": "确认",
"Maximize": "最大化",
"Minimize": "最小化",
"Format document": "格式化文档",
"Empty": "空空如也",
"New": "新建",
"Edit": "编辑",
@@ -56,9 +59,48 @@
"Rule Content": "规则内容",
"Proxy Policy": "代理策略",
"No Resolve": "跳过DNS解析",
"Add Prepend Rule": "添加前置规则",
"Add Append Rule": "添加后置规则",
"Prepend Rule": "添加前置规则",
"Append Rule": "添加后置规则",
"Delete Rule": "删除规则",
"Rule Condition Required": "规则条件缺失",
"Invalid Rule": "无效规则",
"DOMAIN": "匹配完整域名",
"DOMAIN-SUFFIX": "匹配域名后缀",
"DOMAIN-KEYWORD": "匹配域名关键字",
"DOMAIN-REGEX": "匹配域名正则表达式",
"GEOSITE": "匹配Geosite内的域名",
"GEOIP": "匹配IP所属国家代码",
"SRC-GEOIP": "匹配来源IP所属国家代码",
"IP-ASN": "匹配IP所属ASN",
"SRC-IP-ASN": "匹配来源IP所属ASN",
"IP-CIDR": "匹配IP地址范围",
"IP-CIDR6": "匹配IP地址范围",
"SRC-IP-CIDR": "匹配来源IP地址范围",
"IP-SUFFIX": "匹配IP后缀范围",
"SRC-IP-SUFFIX": "匹配来源IP后缀范围",
"SRC-PORT": "匹配请求来源端口范围",
"DST-PORT": "匹配请求目标端口范围",
"IN-PORT": "匹配入站端口",
"DSCP": "DSCP标记(仅限tproxy udp入站)",
"PROCESS-NAME": "匹配进程名称(Android包名)",
"PROCESS-PATH": "匹配完整进程路径",
"PROCESS-NAME-REGEX": "正则匹配完整进程名称(Android包名)",
"PROCESS-PATH-REGEX": "正则匹配完整进程路径",
"NETWORK": "匹配传输协议(tcp/udp)",
"UID": "匹配Linux USER ID",
"IN-TYPE": "匹配入站类型",
"IN-USER": "匹配入站用户名",
"IN-NAME": "匹配入站名称",
"SUB-RULE": "子规则",
"RULE-SET": "匹配规则集",
"AND": "逻辑和",
"OR": "逻辑或",
"NOT": "逻辑非",
"MATCH": "匹配所有请求",
"DIRECT": "直连",
"REJECT": "拦截请求",
"REJECT-DROP": "抛弃请求",
"PASS": "跳过此规则",
"Edit Groups": "编辑代理组",
"Extend Config": "扩展配置",
"Extend Script": "扩展脚本",
+3 -4
View File
@@ -50,7 +50,6 @@ import { BaseStyledTextField } from "@/components/base/base-styled-text-field";
import { listen } from "@tauri-apps/api/event";
import { readTextFile } from "@tauri-apps/api/fs";
import { readText } from "@tauri-apps/api/clipboard";
import { EditorViewer } from "@/components/profile/editor-viewer";
const ProfilePage = () => {
const { t } = useTranslation();
@@ -378,7 +377,7 @@ const ProfilePage = () => {
itemData={item}
onSelect={(f) => onSelect(item.uid, f)}
onEdit={() => viewerRef.current?.edit(item)}
onChange={async (prev, curr) => {
onSave={async (prev, curr) => {
if (prev !== curr && profiles.current === item.uid) {
await onEnhance();
}
@@ -401,7 +400,7 @@ const ProfilePage = () => {
<Grid item xs={12} sm={6} md={6} lg={6}>
<ProfileMore
id="Merge"
onChange={async (prev, curr) => {
onSave={async (prev, curr) => {
if (prev !== curr) {
await onEnhance();
}
@@ -412,7 +411,7 @@ const ProfilePage = () => {
<ProfileMore
id="Script"
logInfo={chainLogs["Script"]}
onChange={async (prev, curr) => {
onSave={async (prev, curr) => {
if (prev !== curr) {
await onEnhance();
}
+2 -1
View File
@@ -26,7 +26,8 @@ jobs:
steps:
- id: set-matrix
run: |
echo '::set-output name=matrix::{"platform":["amd64","arm64"]}'
echo '{"platform": ["amd64", "arm64"]}' > matrix.json
echo "matrix=$(cat matrix.json)" >> $GITHUB_OUTPUT
build-bin:
runs-on: ubuntu-latest
+1 -1
View File
@@ -10,5 +10,5 @@ type Reloader interface {
type HealthChecker interface {
// get relay by ID and check the connection health
HealthCheck(ctx context.Context, RelayID string) error
HealthCheck(ctx context.Context, RelayID string) (int64, error)
}
+4
View File
@@ -55,6 +55,10 @@ func (r *Config) GetWSRemoteAddr(baseAddr string) (string, error) {
return addr, nil
}
func (r *Config) GetTCPRemotes() string {
return fmt.Sprintf("%v", r.TCPRemotes)
}
func (r *Config) Validate() error {
if r.Adjust() != nil {
return errors.New("adjust config failed")
+2 -2
View File
@@ -9,10 +9,10 @@ import (
var _ glue.HealthChecker = (*Server)(nil)
func (r *Server) HealthCheck(ctx context.Context, relayID string) error {
func (r *Server) HealthCheck(ctx context.Context, relayID string) (int64, error) {
rs, ok := r.relayM.Load(relayID)
if !ok {
return fmt.Errorf("label for relay: %s not found,can not health check", relayID)
return 0, fmt.Errorf("label for relay: %s not found,can not health check", relayID)
}
inner, _ := rs.(*Relay)
return inner.relayServer.HealthCheck(ctx)
+3 -2
View File
@@ -101,6 +101,7 @@ func (b *baseTransporter) RelayTCPConn(c net.Conn, handshakeF TCPHandShakeF) err
return relayConn.Transport(remote.Label)
}
func (b *baseTransporter) HealthCheck(ctx context.Context) error {
return b.relayer.HealthCheck(ctx, b.GetRemote().Clone())
func (b *baseTransporter) HealthCheck(ctx context.Context) (int64, error) {
remote := b.GetRemote().Clone()
return remote.HandShakeDuration.Milliseconds(), b.relayer.HealthCheck(ctx, remote)
}
+1 -1
View File
@@ -40,7 +40,7 @@ func newRelayClient(cfg *conf.Config) (RelayClient, error) {
type RelayServer interface {
ListenAndServe() error
Close() error
HealthCheck(ctx context.Context) error
HealthCheck(ctx context.Context) (int64, error) // latency in ms
}
func NewRelayServer(cfg *conf.Config, cmgr cmgr.Cmgr) (RelayServer, error) {
+10 -3
View File
@@ -103,11 +103,12 @@ func (s *Server) HandleHealthCheck(c echo.Context) error {
if relayLabel == "" {
return echo.NewHTTPError(http.StatusBadRequest, "relay_label is required")
}
if err := s.HealthCheck(c.Request().Context(), relayLabel); err != nil {
res := CommonResp{Message: err.Error()}
latency, err := s.HealthCheck(c.Request().Context(), relayLabel)
if err != nil {
res := HealthCheckResp{Message: err.Error(), ErrorCode: -1}
return c.JSON(http.StatusBadRequest, res)
}
return c.JSON(http.StatusOK, CommonResp{Message: "connect success"})
return c.JSON(http.StatusOK, HealthCheckResp{Message: "connect success", Latency: latency})
}
func (s *Server) CurrentConfig(c echo.Context) error {
@@ -158,3 +159,9 @@ func (s *Server) ListConnections(c echo.Context) error {
"AllCount": s.connMgr.CountConnection("active") + s.connMgr.CountConnection("closed"),
})
}
func (s *Server) ListRules(c echo.Context) error {
return c.Render(http.StatusOK, "rule_list.html", map[string]interface{}{
"Configs": s.cfg.RelayConfigs,
})
}
+1
View File
@@ -102,6 +102,7 @@ func NewServer(
e.GET("/", s.index)
e.GET("/connections/", s.ListConnections)
e.GET("/rules/", s.ListRules)
e.GET("/clash_proxy_provider/", s.HandleClashProxyProvider)
// api group
+7
View File
@@ -70,6 +70,13 @@
>Connections</a
>
</li>
<li>
<a
href="/rules/"
class="button is-info is-light"
>Rule List</a
>
</li>
<li>
<a
href="/api/v1/config/"
@@ -0,0 +1,86 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="ehco web" />
<meta name="keywords" content="ehco-relay" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/bulma/1.0.1/css/bulma.min.css"
/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<title>Rules</title>
</head>
<body>
<section class="section">
<div class="container">
<h1 class="title">Rules</h1>
<table class="table is-striped is-fullwidth">
<thead>
<tr>
<th>Label</th>
<th>Listen</th>
<th>Listen Type</th>
<th>Transport Type</th>
<th>Remote</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{{range .Configs}}
<tr>
<td>{{.Label}}</td>
<td>{{.Listen}}</td>
<td>{{.ListenType}}</td>
<td>{{.TransportType}}</td>
<td>{{.GetTCPRemotes}}</td>
<td>
<button
class="button is-small is-primary health-check"
data-label="{{.Label}}"
onclick="checkHealth('{{.Label}}')"
>
Check Health
</button>
</td>
</tr>
{{end}}
</tbody>
</table>
</div>
</section>
<script>
function checkHealth(label) {
$.ajax({
url: "/api/v1/health_check/?relay_label=" + label,
method: "GET",
success: function (response) {
// Check if the response includes an error code
if (response.error_code === 0) {
// If no error, show success message with latency
alert(
"Health Check for " +
label +
": " +
response.msg + // Use 'msg' as per Go struct
" (Latency: " +
response.latency + // Ensure this matches the Go struct field name
"ms)"
);
} else {
// If error code is not 0, show error message
alert("Error for " + label + ": " + response.msg);
}
},
error: function (xhr) {
// Parse the response JSON in case of HTTP error
var response = JSON.parse(xhr.responseText);
alert("Error: " + response.msg); // Use 'msg' as per Go struct
},
});
}
</script>
</body>
</html>
+4 -2
View File
@@ -1,5 +1,7 @@
package web
type CommonResp struct {
Message string `json:"msg"`
type HealthCheckResp struct {
ErrorCode int `json:"error_code"` // code = 0 means success
Message string `json:"msg"`
Latency int64 `json:"latency"`
}
+1 -1
View File
@@ -25,7 +25,7 @@ func (i *Instance) Init(configFile string) error {
var content []byte
var err error
configFile = strings.TrimSpace(configFile)
if strings.HasPrefix(configFile, "http://") || strings.HasPrefix(configFile, "https://") {
if strings.HasPrefix(strings.ToLower(configFile), "http://") || strings.HasPrefix(strings.ToLower(configFile), "https://") {
content, err = getRemoteURLContent(configFile)
} else {
content, err = os.ReadFile(configFile)
@@ -165,6 +165,23 @@ part_magic_fat() {
[ "$magic" = "FAT" ] || [ "$magic_fat32" = "FAT32" ]
}
fitblk_get_bootdev() {
[ -e /sys/firmware/devicetree/base/chosen/rootdisk ] || return
local rootdisk="$(cat /sys/firmware/devicetree/base/chosen/rootdisk)"
local handle bootdev
for handle in /sys/class/block/*/of_node/phandle /sys/class/block/*/device/of_node/phandle; do
[ ! -e "$handle" ] && continue
if [ "$rootdisk" = "$(cat $handle)" ]; then
bootdev="${handle%/of_node/phandle}"
bootdev="${bootdev%/device}"
bootdev="${bootdev#/sys/class/block/}"
echo "$bootdev"
break
fi
done
}
export_bootdevice() {
local cmdline uuid blockdev uevent line class
local MAJOR MINOR DEVNAME DEVTYPE
@@ -196,6 +213,7 @@ export_bootdevice() {
done
;;
/dev/*)
[ "$rootpart" = "/dev/fit0" ] && rootpart="$(fitblk_get_bootdev)"
uevent="/sys/class/block/${rootpart##*/}/../uevent"
;;
0x[a-f0-9][a-f0-9][a-f0-9] | 0x[a-f0-9][a-f0-9][a-f0-9][a-f0-9] | \
+314 -188
View File
@@ -7,6 +7,8 @@
CI_KERNPART="${CI_KERNPART:-kernel}"
# 'ubi' partition on NAND contains UBI
# There are also CI_KERN_UBIPART and CI_ROOT_UBIPART if kernel
# and rootfs are on separated UBIs.
CI_UBIPART="${CI_UBIPART:-ubi}"
# 'rootfs' UBI volume on NAND contains the rootfs
@@ -26,7 +28,7 @@ ubi_mknod() {
nand_find_volume() {
local ubidevdir ubivoldir
ubidevdir="/sys/devices/virtual/ubi/$1"
ubidevdir="/sys/class/ubi/"
[ ! -d "$ubidevdir" ] && return 1
for ubivoldir in $ubidevdir/${1}_*; do
[ ! -d "$ubivoldir" ] && continue
@@ -39,13 +41,12 @@ nand_find_volume() {
}
nand_find_ubi() {
local ubidevdir ubidev mtdnum
local ubidevdir ubidev mtdnum cmtdnum
mtdnum="$( find_mtd_index $1 )"
[ ! "$mtdnum" ] && return 1
for ubidevdir in /sys/devices/virtual/ubi/ubi*; do
[ ! -d "$ubidevdir" ] && continue
for ubidevdir in /sys/class/ubi/ubi*; do
[ ! -e "$ubidevdir/mtd_num" ] && continue
cmtdnum="$( cat $ubidevdir/mtd_num )"
[ ! "$mtdnum" ] && continue
if [ "$mtdnum" = "$cmtdnum" ]; then
ubidev=$( basename $ubidevdir )
ubi_mknod "$ubidevdir"
@@ -56,128 +57,175 @@ nand_find_ubi() {
}
nand_get_magic_long() {
dd if="$1" skip=$2 bs=4 count=1 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"'
(${3}cat "$1" | dd bs=4 "skip=${2:-0}" count=1 | hexdump -v -n 4 -e '1/1 "%02x"') 2> /dev/null
}
get_magic_long_tar() {
( tar xf $1 $2 -O | dd bs=4 count=1 | hexdump -v -n 4 -e '1/1 "%02x"') 2> /dev/null
(tar xO${3}f "$1" "$2" | dd bs=4 count=1 | hexdump -v -n 4 -e '1/1 "%02x"') 2> /dev/null
}
identify_magic() {
local magic=$1
case "$magic" in
"55424923")
echo "ubi"
;;
"31181006")
echo "ubifs"
;;
"68737173")
echo "squashfs"
;;
"d00dfeed")
echo "fit"
;;
"4349"*)
echo "combined"
;;
*)
echo "unknown $magic"
;;
esac
}
identify() {
identify_magic $(nand_get_magic_long "$1" "${2:-0}")
identify_magic_long $(nand_get_magic_long "$@")
}
identify_tar() {
identify_magic $(get_magic_long_tar "$1" "$2")
identify_magic_long $(get_magic_long_tar "$@")
}
identify_if_gzip() {
if [ "$(identify "$1")" = gzip ]; then echo -n z; fi
}
nand_restore_config() {
sync
local ubidev=$( nand_find_ubi $CI_UBIPART )
local ubidev=$( nand_find_ubi "${CI_ROOT_UBIPART:-$CI_UBIPART}" )
local ubivol="$( nand_find_volume $ubidev rootfs_data )"
[ ! "$ubivol" ] &&
ubivol="$( nand_find_volume $ubidev $CI_ROOTPART )"
if [ ! "$ubivol" ]; then
ubivol="$( nand_find_volume $ubidev "$CI_ROOTPART" )"
if [ ! "$ubivol" ]; then
echo "cannot find ubifs data volume"
return 1
fi
fi
mkdir /tmp/new_root
if ! mount -t ubifs /dev/$ubivol /tmp/new_root; then
echo "mounting ubifs $ubivol failed"
echo "cannot mount ubifs volume $ubivol"
rmdir /tmp/new_root
return 1
fi
mv "$1" "/tmp/new_root/$BACKUP_FILE"
umount /tmp/new_root
sync
if mv "$1" "/tmp/new_root/$BACKUP_FILE"; then
if umount /tmp/new_root; then
echo "configuration saved"
rmdir /tmp/new_root
return 0
fi
else
umount /tmp/new_root
fi
echo "could not save configuration to ubifs volume $ubivol"
rmdir /tmp/new_root
return 1
}
nand_remove_ubiblock() {
local ubivol="$1"
local ubiblk="ubiblock${ubivol:3}"
if [ -e "/dev/$ubiblk" ]; then
umount "/dev/$ubiblk" 2>/dev/null && echo "unmounted /dev/$ubiblk" || :
if ! ubiblock -r "/dev/$ubivol"; then
echo "cannot remove $ubiblk"
return 1
fi
fi
}
nand_attach_ubi() {
local ubipart="$1"
local has_env="${2:-0}"
local mtdnum="$( find_mtd_index "$ubipart" )"
if [ ! "$mtdnum" ]; then
>&2 echo "cannot find ubi mtd partition $ubipart"
return 1
fi
local ubidev="$( nand_find_ubi "$ubipart" )"
if [ ! "$ubidev" ]; then
>&2 ubiattach -m "$mtdnum"
ubidev="$( nand_find_ubi "$ubipart" )"
if [ ! "$ubidev" ]; then
>&2 ubiformat /dev/mtd$mtdnum -y
>&2 ubiattach -m "$mtdnum"
ubidev="$( nand_find_ubi "$ubipart" )"
if [ ! "$ubidev" ]; then
>&2 echo "cannot attach ubi mtd partition $ubipart"
return 1
fi
if [ "$has_env" -gt 0 ]; then
>&2 ubimkvol /dev/$ubidev -n 0 -N ubootenv -s 1MiB
>&2 ubimkvol /dev/$ubidev -n 1 -N ubootenv2 -s 1MiB
fi
fi
fi
echo "$ubidev"
return 0
}
nand_detach_ubi() {
local ubipart="$1"
local mtdnum="$( find_mtd_index "$ubipart" )"
if [ ! "$mtdnum" ]; then
echo "cannot find ubi mtd partition $ubipart"
return 1
fi
local ubidev="$( nand_find_ubi "$ubipart" )"
if [ "$ubidev" ]; then
for ubivol in $(find /dev -name "${ubidev}_*" -maxdepth 1 | sort); do
ubivol="${ubivol:5}"
nand_remove_ubiblock "$ubivol" || :
umount "/dev/$ubivol" && echo "unmounted /dev/$ubivol" || :
done
if ! ubidetach -m "$mtdnum"; then
echo "cannot detach ubi mtd partition $ubipart"
return 1
fi
fi
}
nand_upgrade_prepare_ubi() {
local rootfs_length="$1"
local rootfs_type="$2"
local rootfs_data_max="$(fw_printenv -n rootfs_data_max 2>/dev/null)"
local rootfs_data_max="$(fw_printenv -n rootfs_data_max 2> /dev/null)"
[ -n "$rootfs_data_max" ] && rootfs_data_max=$((rootfs_data_max))
local kernel_length="$3"
local has_env="${4:-0}"
local kern_ubidev
local root_ubidev
[ -n "$rootfs_length" -o -n "$kernel_length" ] || return 1
local mtdnum="$( find_mtd_index "$CI_UBIPART" )"
if [ ! "$mtdnum" ]; then
echo "cannot find ubi mtd partition $CI_UBIPART"
return 1
if [ -n "$CI_KERN_UBIPART" -a -n "$CI_ROOT_UBIPART" ]; then
kern_ubidev="$( nand_attach_ubi "$CI_KERN_UBIPART" "$has_env" )"
[ -n "$kern_ubidev" ] || return 1
root_ubidev="$( nand_attach_ubi "$CI_ROOT_UBIPART" )"
[ -n "$root_ubidev" ] || return 1
else
kern_ubidev="$( nand_attach_ubi "$CI_UBIPART" "$has_env" )"
[ -n "$kern_ubidev" ] || return 1
root_ubidev="$kern_ubidev"
fi
local ubidev="$( nand_find_ubi "$CI_UBIPART" )"
if [ ! "$ubidev" ]; then
ubiattach -m "$mtdnum"
sync
ubidev="$( nand_find_ubi "$CI_UBIPART" )"
fi
local kern_ubivol="$( nand_find_volume $kern_ubidev "$CI_KERNPART" )"
local root_ubivol="$( nand_find_volume $root_ubidev "$CI_ROOTPART" )"
local data_ubivol="$( nand_find_volume $root_ubidev rootfs_data )"
[ "$root_ubivol" = "$kern_ubivol" ] && root_ubivol=
if [ ! "$ubidev" ]; then
ubiformat /dev/mtd$mtdnum -y
ubiattach -m "$mtdnum"
sync
ubidev="$( nand_find_ubi "$CI_UBIPART" )"
[ "$has_env" -gt 0 ] && {
ubimkvol /dev/$ubidev -n 0 -N ubootenv -s 1MiB
ubimkvol /dev/$ubidev -n 1 -N ubootenv2 -s 1MiB
}
fi
local kern_ubivol="$( nand_find_volume $ubidev $CI_KERNPART )"
local root_ubivol="$( nand_find_volume $ubidev $CI_ROOTPART )"
local data_ubivol="$( nand_find_volume $ubidev rootfs_data )"
local ubiblk ubiblkvol
for ubiblk in /dev/ubiblock*_? ; do
[ -e "$ubiblk" ] || continue
echo "removing ubiblock${ubiblk:13}"
ubiblkvol=ubi${ubiblk:13}
if ! ubiblock -r /dev/$ubiblkvol; then
echo "cannot remove $ubiblk"
return 1
fi
done
# remove ubiblocks
[ "$kern_ubivol" ] && { nand_remove_ubiblock $kern_ubivol || return 1; }
[ "$root_ubivol" ] && { nand_remove_ubiblock $root_ubivol || return 1; }
[ "$data_ubivol" ] && { nand_remove_ubiblock $data_ubivol || return 1; }
# kill volumes
[ "$kern_ubivol" ] && ubirmvol /dev/$ubidev -N $CI_KERNPART || true
[ "$root_ubivol" -a "$root_ubivol" != "$kern_ubivol" ] && ubirmvol /dev/$ubidev -N $CI_ROOTPART || true
[ "$data_ubivol" ] && ubirmvol /dev/$ubidev -N rootfs_data || true
[ "$kern_ubivol" ] && ubirmvol /dev/$kern_ubidev -N "$CI_KERNPART" || :
[ "$root_ubivol" ] && ubirmvol /dev/$root_ubidev -N "$CI_ROOTPART" || :
[ "$data_ubivol" ] && ubirmvol /dev/$root_ubidev -N rootfs_data || :
# update kernel
# create kernel vol
if [ -n "$kernel_length" ]; then
if ! ubimkvol /dev/$ubidev -N $CI_KERNPART -s $kernel_length; then
if ! ubimkvol /dev/$kern_ubidev -N "$CI_KERNPART" -s $kernel_length; then
echo "cannot create kernel volume"
return 1;
fi
fi
# update rootfs
# create rootfs vol
if [ -n "$rootfs_length" ]; then
local rootfs_size_param
if [ "$rootfs_type" = "ubifs" ]; then
@@ -185,157 +233,224 @@ nand_upgrade_prepare_ubi() {
else
rootfs_size_param="-s $rootfs_length"
fi
if ! ubimkvol /dev/$ubidev -N $CI_ROOTPART $rootfs_size_param; then
if ! ubimkvol /dev/$root_ubidev -N "$CI_ROOTPART" $rootfs_size_param; then
echo "cannot create rootfs volume"
return 1;
fi
fi
# create rootfs_data for non-ubifs rootfs
# create rootfs_data vol for non-ubifs rootfs
if [ "$rootfs_type" != "ubifs" ]; then
local availeb=$(cat /sys/devices/virtual/ubi/$ubidev/avail_eraseblocks)
local ebsize=$(cat /sys/devices/virtual/ubi/$ubidev/eraseblock_size)
local avail_size=$((availeb * ebsize))
local rootfs_data_size_param="-m"
if [ -n "$rootfs_data_max" ] &&
[ "$rootfs_data_max" != "0" ] &&
[ "$rootfs_data_max" -le "$avail_size" ]; then
if [ -n "$rootfs_data_max" ]; then
rootfs_data_size_param="-s $rootfs_data_max"
fi
if ! ubimkvol /dev/$ubidev -N rootfs_data $rootfs_data_size_param; then
echo "cannot initialize rootfs_data volume"
return 1
if ! ubimkvol /dev/$root_ubidev -N rootfs_data $rootfs_data_size_param; then
if ! ubimkvol /dev/$root_ubidev -N rootfs_data -m; then
echo "cannot initialize rootfs_data volume"
return 1
fi
fi
fi
sync
return 0
}
nand_do_upgrade_success() {
local conf_tar="/tmp/sysupgrade.tgz"
sync
[ -f "$conf_tar" ] && nand_restore_config "$conf_tar"
echo "sysupgrade successful"
umount -a
reboot -f
}
# Flash the UBI image to MTD partition
# Write the UBI image to MTD ubi partition
nand_upgrade_ubinized() {
local ubi_file="$1"
local mtdnum="$(find_mtd_index "$CI_UBIPART")"
local gz="$2"
[ ! "$mtdnum" ] && {
CI_UBIPART="rootfs"
mtdnum="$(find_mtd_index "$CI_UBIPART")"
}
local ubi_length=$( (${gz}cat "$ubi_file" | wc -c) 2> /dev/null)
if [ ! "$mtdnum" ]; then
echo "cannot find mtd device $CI_UBIPART"
umount -a
reboot -f
fi
nand_detach_ubi "$CI_UBIPART" || return 1
local mtddev="/dev/mtd${mtdnum}"
ubidetach -p "${mtddev}" || true
sync
ubiformat "${mtddev}" -y -f "${ubi_file}"
ubiattach -p "${mtddev}"
nand_do_upgrade_success
local mtdnum="$( find_mtd_index "$CI_UBIPART" )"
${gz}cat "$ubi_file" | ubiformat "/dev/mtd$mtdnum" -S "$ubi_length" -y -f - && ubiattach -m "$mtdnum"
}
# Write the UBIFS image to UBI volume
# Write the UBIFS image to UBI rootfs volume
nand_upgrade_ubifs() {
local rootfs_length=$( (cat $1 | wc -c) 2> /dev/null)
local ubifs_file="$1"
local gz="$2"
nand_upgrade_prepare_ubi "$rootfs_length" "ubifs" "" ""
local ubifs_length=$( (${gz}cat "$ubifs_file" | wc -c) 2> /dev/null)
nand_upgrade_prepare_ubi "$ubifs_length" "ubifs" "" "" || return 1
local ubidev="$( nand_find_ubi "$CI_UBIPART" )"
local root_ubivol="$(nand_find_volume $ubidev $CI_ROOTPART)"
ubiupdatevol /dev/$root_ubivol -s $rootfs_length $1
nand_do_upgrade_success
local root_ubivol="$(nand_find_volume $ubidev "$CI_ROOTPART")"
${gz}cat "$ubifs_file" | ubiupdatevol /dev/$root_ubivol -s "$ubifs_length" -
}
# Write the FIT image to UBI kernel volume
nand_upgrade_fit() {
local fit_file="$1"
local fit_length="$(wc -c < "$fit_file")"
local gz="$2"
nand_upgrade_prepare_ubi "" "" "$fit_length" "1"
local fit_length=$( (${gz}cat "$fit_file" | wc -c) 2> /dev/null)
nand_upgrade_prepare_ubi "" "" "$fit_length" "1" || return 1
local fit_ubidev="$(nand_find_ubi "$CI_UBIPART")"
local fit_ubivol="$(nand_find_volume $fit_ubidev "$CI_KERNPART")"
ubiupdatevol /dev/$fit_ubivol -s $fit_length $fit_file
nand_do_upgrade_success
${gz}cat "$fit_file" | ubiupdatevol /dev/$fit_ubivol -s "$fit_length" -
}
# Write images in the TAR file to MTD partitions and/or UBI volumes as required
nand_upgrade_tar() {
local tar_file="$1"
local kernel_mtd="$(find_mtd_index $CI_KERNPART)"
local gz="$2"
local jffs2_markers="${CI_JFFS2_CLEAN_MARKERS:-0}"
local board_dir=$(tar tf "$tar_file" | grep -m 1 '^sysupgrade-.*/$')
board_dir=${board_dir%/}
# WARNING: This fails if tar contains more than one 'sysupgrade-*' directory.
local board_dir="$(tar t${gz}f "$tar_file" | grep -m 1 '^sysupgrade-.*/$')"
board_dir="${board_dir%/}"
kernel_length=$( (tar xf "$tar_file" ${board_dir}/kernel -O | wc -c) 2> /dev/null)
local has_rootfs=0
local rootfs_length
local kernel_mtd kernel_length
if [ "$CI_KERNPART" != "none" ]; then
kernel_mtd="$(find_mtd_index "$CI_KERNPART")"
kernel_length=$( (tar xO${gz}f "$tar_file" "$board_dir/kernel" | wc -c) 2> /dev/null)
[ "$kernel_length" = 0 ] && kernel_length=
fi
local rootfs_length=$( (tar xO${gz}f "$tar_file" "$board_dir/root" | wc -c) 2> /dev/null)
[ "$rootfs_length" = 0 ] && rootfs_length=
local rootfs_type
[ "$rootfs_length" ] && rootfs_type="$(identify_tar "$tar_file" "$board_dir/root" "$gz")"
tar tf "$tar_file" ${board_dir}/root 1>/dev/null 2>/dev/null && has_rootfs=1
[ "$has_rootfs" = "1" ] && {
rootfs_length=$( (tar xf "$tar_file" ${board_dir}/root -O | wc -c) 2> /dev/null)
rootfs_type="$(identify_tar "$tar_file" ${board_dir}/root)"
}
local ubi_kernel_length
if [ "$kernel_length" ]; then
if [ "$kernel_mtd" ]; then
# On some devices, the raw kernel and ubi partitions overlap.
# These devices brick if the kernel partition is erased.
# Hence only invalidate kernel for now.
dd if=/dev/zero bs=4096 count=1 2> /dev/null | \
mtd write - "$CI_KERNPART"
else
ubi_kernel_length="$kernel_length"
fi
fi
local has_kernel=1
local has_env=0
nand_upgrade_prepare_ubi "$rootfs_length" "$rootfs_type" "$ubi_kernel_length" "$has_env" || return 1
[ "$kernel_length" != 0 -a -n "$kernel_mtd" ] && {
tar xf "$tar_file" ${board_dir}/kernel -O | mtd write - $CI_KERNPART
}
[ "$kernel_length" = 0 -o ! -z "$kernel_mtd" ] && has_kernel=
if [ "$rootfs_length" ]; then
local ubidev="$( nand_find_ubi "${CI_ROOT_UBIPART:-$CI_UBIPART}" )"
local root_ubivol="$( nand_find_volume $ubidev "$CI_ROOTPART" )"
tar xO${gz}f "$tar_file" "$board_dir/root" | \
ubiupdatevol /dev/$root_ubivol -s "$rootfs_length" -
fi
if [ "$kernel_length" ]; then
if [ "$kernel_mtd" ]; then
if [ "$jffs2_markers" = 1 ]; then
flash_erase -j "/dev/mtd${kernel_mtd}" 0 0
tar xO${gz}f "$tar_file" "$board_dir/kernel" | \
nandwrite "/dev/mtd${kernel_mtd}" -
else
tar xO${gz}f "$tar_file" "$board_dir/kernel" | \
mtd write - "$CI_KERNPART"
fi
else
local ubidev="$( nand_find_ubi "${CI_KERN_UBIPART:-$CI_UBIPART}" )"
local kern_ubivol="$( nand_find_volume $ubidev "$CI_KERNPART" )"
tar xO${gz}f "$tar_file" "$board_dir/kernel" | \
ubiupdatevol /dev/$kern_ubivol -s "$kernel_length" -
fi
fi
nand_upgrade_prepare_ubi "$rootfs_length" "$rootfs_type" "${has_kernel:+$kernel_length}" "$has_env"
return 0
}
local ubidev="$( nand_find_ubi "$CI_UBIPART" )"
[ "$has_kernel" = "1" ] && {
local kern_ubivol="$( nand_find_volume $ubidev $CI_KERNPART )"
tar xf "$tar_file" ${board_dir}/kernel -O | \
ubiupdatevol /dev/$kern_ubivol -s $kernel_length -
}
nand_verify_if_gzip_file() {
local file="$1"
local gz="$2"
[ "$has_rootfs" = "1" ] && {
local root_ubivol="$( nand_find_volume $ubidev $CI_ROOTPART )"
tar xf "$tar_file" ${board_dir}/root -O | \
ubiupdatevol /dev/$root_ubivol -s $rootfs_length -
}
nand_do_upgrade_success
if [ "$gz" = z ]; then
echo "verifying compressed sysupgrade file integrity"
if ! gzip -t "$file"; then
echo "corrupted compressed sysupgrade file"
return 1
fi
fi
}
nand_verify_tar_file() {
local file="$1"
local gz="$2"
echo "verifying sysupgrade tar file integrity"
if ! tar xO${gz}f "$file" > /dev/null; then
echo "corrupted sysupgrade tar file"
return 1
fi
}
nand_do_flash_file() {
local file="$1"
local gz="$(identify_if_gzip "$file")"
local file_type="$(identify "$file" "" "$gz")"
[ ! "$(find_mtd_index "$CI_UBIPART")" ] && CI_UBIPART=rootfs
case "$file_type" in
"fit")
nand_verify_if_gzip_file "$file" "$gz" || return 1
nand_upgrade_fit "$file" "$gz"
;;
"ubi")
nand_verify_if_gzip_file "$file" "$gz" || return 1
nand_upgrade_ubinized "$file" "$gz"
;;
"ubifs")
nand_verify_if_gzip_file "$file" "$gz" || return 1
nand_upgrade_ubifs "$file" "$gz"
;;
*)
nand_verify_tar_file "$file" "$gz" || return 1
nand_upgrade_tar "$file" "$gz"
;;
esac
}
nand_do_restore_config() {
local conf_tar="/tmp/sysupgrade.tgz"
[ ! -f "$conf_tar" ] || nand_restore_config "$conf_tar"
}
# Recognize type of passed file and start the upgrade process
nand_do_upgrade() {
local file_type=$(identify $1)
local file="$1"
[ ! "$(find_mtd_index "$CI_UBIPART")" ] && CI_UBIPART="rootfs"
case "$file_type" in
"fit") nand_upgrade_fit $1;;
"ubi") nand_upgrade_ubinized $1;;
"ubifs") nand_upgrade_ubifs $1;;
*) nand_upgrade_tar $1;;
esac
sync
nand_do_flash_file "$file" && nand_do_upgrade_success
nand_do_upgrade_failed
}
# Check if passed file is a valid one for NAND sysupgrade. Currently it accepts
# 3 types of files:
# 1) UBI - should contain an ubinized image, header is checked for the proper
# MAGIC
# 2) UBIFS - should contain UBIFS partition that will replace "rootfs" volume,
# header is checked for the proper MAGIC
# 3) TAR - archive has to include "sysupgrade-BOARD" directory with a non-empty
# "CONTROL" file (at this point its content isn't verified)
nand_do_upgrade_success() {
if nand_do_restore_config && sync; then
echo "sysupgrade successful"
umount -a
reboot -f
fi
nand_do_upgrade_failed
}
nand_do_upgrade_failed() {
sync
echo "sysupgrade failed"
# Should we reboot or bring up some failsafe mode instead?
umount -a
reboot -f
}
# Check if passed file is a valid one for NAND sysupgrade.
# Currently it accepts 4 types of files:
# 1) UBI: a ubinized image containing required UBI volumes.
# 2) UBIFS: a UBIFS rootfs volume image.
# 3) FIT: a FIT image containing kernel and rootfs.
# 4) TAR: an archive that includes directory "sysupgrade-${BOARD_NAME}" containing
# a non-empty "CONTROL" file and required partition and/or volume images.
#
# You usually want to call this function in platform_check_image.
#
@@ -343,14 +458,25 @@ nand_do_upgrade() {
# $(2): file to be checked
nand_do_platform_check() {
local board_name="$1"
local tar_file="$2"
local control_length=$( (tar xf $tar_file sysupgrade-$board_name/CONTROL -O | wc -c) 2> /dev/null)
local file_type="$(identify $2)"
local file="$2"
[ "$control_length" = 0 -a "$file_type" != "ubi" -a "$file_type" != "ubifs" -a "$file_type" != "fit" ] && {
echo "Invalid sysupgrade file."
return 1
}
local gz="$(identify_if_gzip "$file")"
local file_type="$(identify "$file" "" "$gz")"
local control_length=$( (tar xO${gz}f "$file" "sysupgrade-${board_name//,/_}/CONTROL" | wc -c) 2> /dev/null)
if [ "$control_length" = 0 ]; then
control_length=$( (tar xO${gz}f "$file" "sysupgrade-${board_name//_/,}/CONTROL" | wc -c) 2> /dev/null)
fi
if [ "$control_length" != 0 ]; then
nand_verify_tar_file "$file" "$gz" || return 1
else
nand_verify_if_gzip_file "$file" "$gz" || return 1
if [ "$file_type" != "fit" -a "$file_type" != "ubi" -a "$file_type" != "ubifs" ]; then
echo "invalid sysupgrade file"
return 1
fi
fi
return 0
}
@@ -45,7 +45,8 @@ switch_to_ramfs() {
mtd partx losetup mkfs.ext4 nandwrite flash_erase \
ubiupdatevol ubiattach ubiblock ubiformat \
ubidetach ubirsvol ubirmvol ubimkvol \
snapshot snapshot_tool date \
snapshot snapshot_tool date logger \
/usr/sbin/fw_printenv /usr/bin/fwtool \
$RAMFS_COPY_LOSETUP $RAMFS_COPY_LVM \
$RAMFS_COPY_BIN
do
+4
View File
@@ -14,6 +14,10 @@ PKG_SOURCE_DATE:=2022-12-22
PKG_SOURCE_VERSION:=5b509e80384ab019ac11aa90c81ec0dbb5b0d7f2
PKG_MIRROR_HASH:=6fc25df4d28becd010ff4971b23731c08b53e69381a9e4c868091899712f78a9
PATCH_DIR:=./patches-5.4
else ifdef CONFIG_LINUX_6_1
PKG_SOURCE_DATE:=2024-02-03
PKG_SOURCE_VERSION:=9827df56b241601f29bf496b62545713c67afb61
PKG_MIRROR_HASH:=d758db4228eed55c93fff8f87ec92d482b8507a68698b28dcf273e12b02ddf5f
else ifdef CONFIG_LINUX_6_6
PKG_SOURCE_DATE:=2024-02-03
PKG_SOURCE_VERSION:=9827df56b241601f29bf496b62545713c67afb61
@@ -66,9 +66,7 @@ start()
ethtool -K $c tx-checksum-ipv4 on >/dev/null 2>&1
ethtool -K $c tx-checksum-ipv6 on >/dev/null 2>&1)
ethtool -K $c tx-scatter-gather on >/dev/null 2>&1
ethtool -K $c gso on >/dev/null 2>&1
ethtool -K $c tso on >/dev/null 2>&1
ethtool -K $c ufo on >/dev/null 2>&1
done
[ -f /etc/index.htm ] && mv /etc/index.htm /usr/lib/lua/luci/view/admin_status/index.htm
+6 -5
View File
@@ -12,15 +12,16 @@ PKG_RELEASE:=1
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL=$(PROJECT_GIT)/project/fstools.git
PKG_MIRROR_HASH:=edda9151c73c1adfe369f5e315347344727a540ad57d3e2b41b9f57f9d4313fe
PKG_SOURCE_DATE:=2023-01-22
PKG_SOURCE_VERSION:=1ea5855e980cd88766dd9f615e78e7dd6edfbb74
PKG_MIRROR_HASH:=32e39891455b602e9deb367c9ce2d099dc72353fad0bf0433307416925f7b393
PKG_SOURCE_DATE:=2024-01-22
PKG_SOURCE_VERSION:=08cd7083cac4bddf88459efa0881ee52858e7d0a
CMAKE_INSTALL:=1
PKG_LICENSE:=GPL-2.0
PKG_LICENSE_FILES:=
PKG_USE_MIPS16:=0
PKG_BUILD_FLAGS:=no-mips16
PKG_FLAGS:=nonshared
PKG_BUILD_DEPENDS := util-linux
@@ -48,7 +49,7 @@ define Package/fstools/config
depends on PACKAGE_fstools
depends on NAND_SUPPORT
bool "Support extroot functionality with UBIFS"
default n
default y
help
This option makes it possible to use extroot functionality if the root filesystem resides on an UBIFS partition
@@ -82,7 +83,7 @@ define Package/block-mount
SECTION:=base
CATEGORY:=Base system
TITLE:=Block device mounting and checking
DEPENDS:=+fstools +ubox +libubox +libuci +libblobmsg-json +libjson-c
DEPENDS:=+ubox +libubox +libuci +libblobmsg-json +libjson-c
endef
define Package/blockd
@@ -1,129 +0,0 @@
From: Qi Liu <liuqi_colin@msn.com>
In order to support extroot, block extroot command has to be able to
discover and properly mount the rootfs_data volume in order to discover
the extroot volume. Currently this process can only discover MTD devices.
This patch leverages libfstools in a similar way as mount_root to
discover, initialize, and mount rootfs_data volume. It would enable any
device with non-MTD rootfs_data volume to support extroot, including x86.
Signed-off-by: Qi Liu <liuqi_colin@msn.com>
---
CMakeLists.txt | 4 ++--
block.c | 40 ++++++++++++++++++++++++++++++++++++++++
libfstools/fstype.h | 12 ++++++++++++
libfstools/libfstools.h | 11 +----------
4 files changed, 55 insertions(+), 12 deletions(-)
create mode 100644 libfstools/fstype.h
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -78,9 +78,9 @@ INSTALL(TARGETS blockd RUNTIME DESTINATI
ADD_EXECUTABLE(block block.c probe.c probe-libblkid.c)
IF(DEFINED CMAKE_UBIFS_EXTROOT)
ADD_DEFINITIONS(-DUBIFS_EXTROOT)
- TARGET_LINK_LIBRARIES(block blkid-tiny dl uci ubox ubus blobmsg_json ubi-utils ${json})
+ TARGET_LINK_LIBRARIES(block fstools blkid-tiny dl uci ubox ubus blobmsg_json ubi-utils ${json})
ELSE(DEFINED CMAKE_UBIFS_EXTROOT)
- TARGET_LINK_LIBRARIES(block blkid-tiny dl uci ubox ubus blobmsg_json ${json})
+ TARGET_LINK_LIBRARIES(block fstools blkid-tiny dl uci ubox ubus blobmsg_json ${json})
ENDIF(DEFINED CMAKE_UBIFS_EXTROOT)
INSTALL(TARGETS block RUNTIME DESTINATION sbin)
--- a/block.c
+++ b/block.c
@@ -44,6 +44,8 @@
#include <libubox/vlist.h>
#include <libubus.h>
+#include "libfstools/fstype.h"
+#include "libfstools/volume.h"
#include "probe.h"
#define AUTOFS_MOUNT_PATH "/tmp/run/blockd/"
@@ -1696,6 +1698,44 @@ static int main_extroot(int argc, char *
}
#endif
+ /* Find volume using libfstools */
+ struct volume *data = volume_find("rootfs_data");
+ if (data) {
+ volume_init(data);
+
+ switch (volume_identify(data)) {
+ case FS_EXT4: {
+ char cfg[] = "/tmp/ext4_cfg";
+
+ /* Mount volume and try extroot (using fstab from that vol) */
+ mkdir_p(cfg, 0755);
+ if (!mount(data->blk, cfg, "ext4", MS_NOATIME, NULL)) {
+ err = mount_extroot(cfg);
+ umount2(cfg, MNT_DETACH);
+ }
+ if (err < 0)
+ rmdir("/tmp/overlay");
+ rmdir(cfg);
+ return err;
+ }
+
+ case FS_F2FS: {
+ char cfg[] = "/tmp/f2fs_cfg";
+
+ /* Mount volume and try extroot (using fstab from that vol) */
+ mkdir_p(cfg, 0755);
+ if (!mount(data->blk, cfg, "f2fs", MS_NOATIME, NULL)) {
+ err = mount_extroot(cfg);
+ umount2(cfg, MNT_DETACH);
+ }
+ if (err < 0)
+ rmdir("/tmp/overlay");
+ rmdir(cfg);
+ return err;
+ }
+ }
+ }
+
/* As a last resort look for /etc/config/fstab on "rootfs" partition */
return mount_extroot(NULL);
}
--- /dev/null
+++ b/libfstools/fstype.h
@@ -0,0 +1,13 @@
+#ifndef _FS_TYPE_H__
+#define _FS_TYPE_H__
+enum {
+ FS_NONE,
+ FS_SNAPSHOT,
+ FS_JFFS2,
+ FS_DEADCODE,
+ FS_UBIFS,
+ FS_F2FS,
+ FS_EXT4,
+ FS_TARGZ,
+};
+#endif
\ No newline at end of file
--- a/libfstools/libfstools.h
+++ b/libfstools/libfstools.h
@@ -18,20 +18,10 @@
#include <libubox/blob.h>
#include <libubox/ulog.h>
#include <libubox/utils.h>
+#include "fstype.h"
struct volume;
-enum {
- FS_NONE,
- FS_SNAPSHOT,
- FS_JFFS2,
- FS_DEADCODE,
- FS_UBIFS,
- FS_F2FS,
- FS_EXT4,
- FS_TARGZ,
-};
-
enum fs_state {
FS_STATE_UNKNOWN,
FS_STATE_PENDING,
+1 -1
View File
@@ -16,7 +16,7 @@ define Package/fitblk
SECTION:=base
CATEGORY:=Base system
TITLE:=fitblk firmware release tool
DEPENDS:=@LINUX_6_1
DEPENDS:=@!LINUX_5_15
endef
define Package/fitblk/description
@@ -0,0 +1,161 @@
From 66a5c40f60f5d88ad8d47ba6a4ba05892853fa1f Mon Sep 17 00:00:00 2001
From: Tanzir Hasan <tanzirh@google.com>
Date: Tue, 26 Dec 2023 18:00:00 +0000
Subject: [PATCH] kernel.h: removed REPEAT_BYTE from kernel.h
This patch creates wordpart.h and includes it in asm/word-at-a-time.h
for all architectures. WORD_AT_A_TIME_CONSTANTS depends on kernel.h
because of REPEAT_BYTE. Moving this to another header and including it
where necessary allows us to not include the bloated kernel.h. Making
this implicit dependency on REPEAT_BYTE explicit allows for later
improvements in the lib/string.c inclusion list.
Suggested-by: Al Viro <viro@zeniv.linux.org.uk>
Suggested-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: Tanzir Hasan <tanzirh@google.com>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Link: https://lore.kernel.org/r/20231226-libstringheader-v6-1-80aa08c7652c@google.com
Signed-off-by: Kees Cook <keescook@chromium.org>
---
arch/arm/include/asm/word-at-a-time.h | 3 ++-
arch/arm64/include/asm/word-at-a-time.h | 3 ++-
arch/powerpc/include/asm/word-at-a-time.h | 4 ++--
arch/riscv/include/asm/word-at-a-time.h | 3 ++-
arch/s390/include/asm/word-at-a-time.h | 3 ++-
arch/sh/include/asm/word-at-a-time.h | 2 ++
arch/x86/include/asm/word-at-a-time.h | 3 ++-
arch/x86/kvm/mmu/mmu.c | 1 +
fs/namei.c | 2 +-
include/asm-generic/word-at-a-time.h | 3 ++-
include/linux/kernel.h | 8 --------
include/linux/wordpart.h | 13 +++++++++++++
12 files changed, 31 insertions(+), 17 deletions(-)
create mode 100644 include/linux/wordpart.h
--- a/arch/arm/include/asm/word-at-a-time.h
+++ b/arch/arm/include/asm/word-at-a-time.h
@@ -8,7 +8,8 @@
* Little-endian word-at-a-time zero byte handling.
* Heavily based on the x86 algorithm.
*/
-#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/wordpart.h>
struct word_at_a_time {
const unsigned long one_bits, high_bits;
--- a/arch/arm64/include/asm/word-at-a-time.h
+++ b/arch/arm64/include/asm/word-at-a-time.h
@@ -9,7 +9,8 @@
#ifndef __AARCH64EB__
-#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/wordpart.h>
struct word_at_a_time {
const unsigned long one_bits, high_bits;
--- a/arch/powerpc/include/asm/word-at-a-time.h
+++ b/arch/powerpc/include/asm/word-at-a-time.h
@@ -4,8 +4,8 @@
/*
* Word-at-a-time interfaces for PowerPC.
*/
-
-#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/wordpart.h>
#include <asm/asm-compat.h>
#include <asm/extable.h>
--- a/arch/sh/include/asm/word-at-a-time.h
+++ b/arch/sh/include/asm/word-at-a-time.h
@@ -5,6 +5,8 @@
#ifdef CONFIG_CPU_BIG_ENDIAN
# include <asm-generic/word-at-a-time.h>
#else
+#include <linux/bitops.h>
+#include <linux/wordpart.h>
/*
* Little-endian version cribbed from x86.
*/
--- a/arch/x86/include/asm/word-at-a-time.h
+++ b/arch/x86/include/asm/word-at-a-time.h
@@ -2,7 +2,8 @@
#ifndef _ASM_WORD_AT_A_TIME_H
#define _ASM_WORD_AT_A_TIME_H
-#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/wordpart.h>
/*
* This is largely generic for little-endian machines, but the
--- a/arch/x86/kvm/mmu/mmu.c
+++ b/arch/x86/kvm/mmu/mmu.c
@@ -44,6 +44,7 @@
#include <linux/kern_levels.h>
#include <linux/kstrtox.h>
#include <linux/kthread.h>
+#include <linux/wordpart.h>
#include <asm/page.h>
#include <asm/memtype.h>
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -17,8 +17,8 @@
#include <linux/init.h>
#include <linux/export.h>
-#include <linux/kernel.h>
#include <linux/slab.h>
+#include <linux/wordpart.h>
#include <linux/fs.h>
#include <linux/namei.h>
#include <linux/pagemap.h>
--- a/include/asm-generic/word-at-a-time.h
+++ b/include/asm-generic/word-at-a-time.h
@@ -2,7 +2,8 @@
#ifndef _ASM_WORD_AT_A_TIME_H
#define _ASM_WORD_AT_A_TIME_H
-#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/wordpart.h>
#include <asm/byteorder.h>
#ifdef __BIG_ENDIAN
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -36,14 +36,6 @@
#define STACK_MAGIC 0xdeadbeef
-/**
- * REPEAT_BYTE - repeat the value @x multiple times as an unsigned long value
- * @x: value to repeat
- *
- * NOTE: @x is not checked for > 0xff; larger values produce odd results.
- */
-#define REPEAT_BYTE(x) ((~0ul / 0xff) * (x))
-
/* generic data direction definitions */
#define READ 0
#define WRITE 1
--- /dev/null
+++ b/include/linux/wordpart.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _LINUX_WORDPART_H
+#define _LINUX_WORDPART_H
+/**
+ * REPEAT_BYTE - repeat the value @x multiple times as an unsigned long value
+ * @x: value to repeat
+ *
+ * NOTE: @x is not checked for > 0xff; larger values produce odd results.
+ */
+#define REPEAT_BYTE(x) ((~0ul / 0xff) * (x))
+
+#endif // _LINUX_WORDPART_H
@@ -0,0 +1,107 @@
From adeb04362d74188c1e22ccb824b15a0a7b3de2f4 Mon Sep 17 00:00:00 2001
From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Date: Wed, 14 Feb 2024 19:26:32 +0200
Subject: [PATCH] kernel.h: Move upper_*_bits() and lower_*_bits() to
wordpart.h
The wordpart.h header is collecting APIs related to the handling
parts of the word (usually in byte granularity). The upper_*_bits()
and lower_*_bits() are good candidates to be moved to there.
This helps to clean up header dependency hell with regard to kernel.h
as the latter gathers completely unrelated stuff together and slows
down compilation (especially when it's included into other header).
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Link: https://lore.kernel.org/r/20240214172752.3605073-1-andriy.shevchenko@linux.intel.com
Reviewed-by: Randy Dunlap <rdunlap@infradead.org>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
include/linux/kernel.h | 30 ++----------------------------
include/linux/wordpart.h | 29 +++++++++++++++++++++++++++++
2 files changed, 31 insertions(+), 28 deletions(-)
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -30,6 +30,8 @@
#include <linux/build_bug.h>
#include <linux/static_call_types.h>
#include <linux/instruction_pointer.h>
+#include <linux/wordpart.h>
+
#include <asm/byteorder.h>
#include <uapi/linux/kernel.h>
@@ -55,34 +57,6 @@
} \
)
-/**
- * upper_32_bits - return bits 32-63 of a number
- * @n: the number we're accessing
- *
- * A basic shift-right of a 64- or 32-bit quantity. Use this to suppress
- * the "right shift count >= width of type" warning when that quantity is
- * 32-bits.
- */
-#define upper_32_bits(n) ((u32)(((n) >> 16) >> 16))
-
-/**
- * lower_32_bits - return bits 0-31 of a number
- * @n: the number we're accessing
- */
-#define lower_32_bits(n) ((u32)((n) & 0xffffffff))
-
-/**
- * upper_16_bits - return bits 16-31 of a number
- * @n: the number we're accessing
- */
-#define upper_16_bits(n) ((u16)((n) >> 16))
-
-/**
- * lower_16_bits - return bits 0-15 of a number
- * @n: the number we're accessing
- */
-#define lower_16_bits(n) ((u16)((n) & 0xffff))
-
struct completion;
struct user;
--- a/include/linux/wordpart.h
+++ b/include/linux/wordpart.h
@@ -2,6 +2,35 @@
#ifndef _LINUX_WORDPART_H
#define _LINUX_WORDPART_H
+
+/**
+ * upper_32_bits - return bits 32-63 of a number
+ * @n: the number we're accessing
+ *
+ * A basic shift-right of a 64- or 32-bit quantity. Use this to suppress
+ * the "right shift count >= width of type" warning when that quantity is
+ * 32-bits.
+ */
+#define upper_32_bits(n) ((u32)(((n) >> 16) >> 16))
+
+/**
+ * lower_32_bits - return bits 0-31 of a number
+ * @n: the number we're accessing
+ */
+#define lower_32_bits(n) ((u32)((n) & 0xffffffff))
+
+/**
+ * upper_16_bits - return bits 16-31 of a number
+ * @n: the number we're accessing
+ */
+#define upper_16_bits(n) ((u16)((n) >> 16))
+
+/**
+ * lower_16_bits - return bits 0-15 of a number
+ * @n: the number we're accessing
+ */
+#define lower_16_bits(n) ((u16)((n) & 0xffff))
+
/**
* REPEAT_BYTE - repeat the value @x multiple times as an unsigned long value
* @x: value to repeat
@@ -0,0 +1,36 @@
From 8e7daa85641c9559c113f6b217bdc923397de77c Mon Sep 17 00:00:00 2001
From: William Zhang <william.zhang@broadcom.com>
Date: Thu, 22 Feb 2024 19:47:58 -0800
Subject: [PATCH] mtd: rawnand: brcmnand: Support write protection setting from
dts
The write protection feature is controlled by the module parameter wp_on
with default set to enabled. But not all the board use this feature
especially in BCMBCA broadband board. And module parameter is not
sufficient as different board can have different option. Add a device
tree property and allow this feature to be configured through the board
dts on per board basis.
Signed-off-by: William Zhang <william.zhang@broadcom.com>
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
Reviewed-by: Kamal Dasu <kamal.dasu@broadcom.com>
Reviewed-by: David Regan <dregan@broadcom.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Link: https://lore.kernel.org/linux-mtd/20240223034758.13753-14-william.zhang@broadcom.com
---
drivers/mtd/nand/raw/brcmnand/brcmnand.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
+++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
@@ -3188,6 +3188,10 @@ int brcmnand_probe(struct platform_devic
/* Disable XOR addressing */
brcmnand_rmw_reg(ctrl, BRCMNAND_CS_XOR, 0xff, 0, 0);
+ /* Check if the board connects the WP pin */
+ if (of_property_read_bool(dn, "brcm,wp-not-connected"))
+ wp_on = 0;
+
if (ctrl->features & BRCMNAND_HAS_WP) {
/* Permanently disable write protection */
if (wp_on == 2)
@@ -10,7 +10,7 @@ This adds support for "linux,rootfs" binding that is used to mark flash
partition containing rootfs. It's useful for devices using device tree
that don't have bootloader passing root info in cmdline.
Signed-off-by: Rafa? Mi?ecki <rafal@milecki.pl>
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Link: https://lore.kernel.org/linux-mtd/20221022211318.32009-2-zajec5@gmail.com
---
@@ -0,0 +1,117 @@
From 773bbe10449731c9525457873e0c2342e5cf883b Mon Sep 17 00:00:00 2001
From: Michael Walle <michael@walle.cc>
Date: Thu, 11 Aug 2022 00:06:53 +0200
Subject: [PATCH] mtd: spi-nor: add generic flash driver
Our SFDP parsing is everything we need to support all basic operations
of a flash device. If the flash isn't found in our in-kernel flash
database, gracefully fall back to a driver described solely by its SFDP
tables.
Signed-off-by: Michael Walle <michael@walle.cc>
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
Tested-by: Tudor Ambarus <tudor.ambarus@microchip.com>
Reviewed-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
Link: https://lore.kernel.org/r/20220810220654.1297699-7-michael@walle.cc
---
drivers/mtd/spi-nor/core.c | 26 ++++++++++++++++++++++++--
drivers/mtd/spi-nor/core.h | 1 +
drivers/mtd/spi-nor/sfdp.c | 27 +++++++++++++++++++++++++++
3 files changed, 52 insertions(+), 2 deletions(-)
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -1636,6 +1636,16 @@ static const struct spi_nor_manufacturer
&spi_nor_xmc,
};
+static const struct flash_info spi_nor_generic_flash = {
+ .name = "spi-nor-generic",
+ /*
+ * JESD216 rev A doesn't specify the page size, therefore we need a
+ * sane default.
+ */
+ .page_size = 256,
+ .parse_sfdp = true,
+};
+
static const struct flash_info *spi_nor_match_id(struct spi_nor *nor,
const u8 *id)
{
@@ -1669,6 +1679,14 @@ static const struct flash_info *spi_nor_
}
info = spi_nor_match_id(nor, id);
+
+ /* Fallback to a generic flash described only by its SFDP data. */
+ if (!info) {
+ ret = spi_nor_check_sfdp_signature(nor);
+ if (!ret)
+ info = &spi_nor_generic_flash;
+ }
+
if (!info) {
dev_err(nor->dev, "unrecognized JEDEC id bytes: %*ph\n",
SPI_NOR_MAX_ID_LEN, id);
@@ -2105,8 +2123,12 @@ static int spi_nor_select_pp(struct spi_
* spi_nor_select_uniform_erase() - select optimum uniform erase type
* @map: the erase map of the SPI NOR
* @wanted_size: the erase type size to search for. Contains the value of
- * info->sector_size or of the "small sector" size in case
- * CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is defined.
+ * info->sector_size, the "small sector" size in case
+ * CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is defined or 0 if
+ * there is no information about the sector size. The
+ * latter is the case if the flash parameters are parsed
+ * solely by SFDP, then the largest supported erase type
+ * is selected.
*
* Once the optimum uniform sector erase command is found, disable all the
* other.
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -708,6 +708,8 @@ int spi_nor_controller_ops_read_reg(stru
int spi_nor_controller_ops_write_reg(struct spi_nor *nor, u8 opcode,
const u8 *buf, size_t len);
+int spi_nor_check_sfdp_signature(struct spi_nor *nor);
+
static inline struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd)
{
return container_of(mtd, struct spi_nor, mtd);
--- a/drivers/mtd/spi-nor/sfdp.c
+++ b/drivers/mtd/spi-nor/sfdp.c
@@ -1250,6 +1250,33 @@ static void spi_nor_post_sfdp_fixups(str
}
/**
+ * spi_nor_check_sfdp_signature() - check for a valid SFDP signature
+ * @nor: pointer to a 'struct spi_nor'
+ *
+ * Used to detect if the flash supports the RDSFDP command as well as the
+ * presence of a valid SFDP table.
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+int spi_nor_check_sfdp_signature(struct spi_nor *nor)
+{
+ u32 signature;
+ int err;
+
+ /* Get the SFDP header. */
+ err = spi_nor_read_sfdp_dma_unsafe(nor, 0, sizeof(signature),
+ &signature);
+ if (err < 0)
+ return err;
+
+ /* Check the SFDP signature. */
+ if (le32_to_cpu(signature) != SFDP_SIGNATURE)
+ return -EINVAL;
+
+ return 0;
+}
+
+/**
* spi_nor_parse_sfdp() - parse the Serial Flash Discoverable Parameters.
* @nor: pointer to a 'struct spi_nor'
*
@@ -1,13 +1,13 @@
From f7982c726e02001afc19052fe48f642dfcbc00b2 Mon Sep 17 00:00:00 2001
From c67d90e058550403a3e6f9b05bfcdcfa12b1815c Mon Sep 17 00:00:00 2001
From: Vincent Tremblay <vincent@vtremblay.dev>
Date: Mon, 26 Dec 2022 21:10:37 -0500
Subject: [PATCH 1/2] spidev: Add Silicon Labs EM3581 device compatible
Date: Mon, 26 Dec 2022 21:35:48 -0500
Subject: [PATCH] spidev: Add Silicon Labs EM3581 device compatible
Add compatible string for Silicon Labs EM3581 device.
Note: This patch is adapted from a patch submitted to the for-next branch (v6.3).
Signed-off-by: Vincent Tremblay <vincent@vtremblay.dev>
Link: https://lore.kernel.org/r/20221227023550.569547-2-vincent@vtremblay.dev
Signed-off-by: Mark Brown <broonie@kernel.org>
---
drivers/spi/spidev.c | 2 ++
1 file changed, 2 insertions(+)
@@ -1,13 +1,13 @@
From 536581825219e97fa2ae0c4de35605d2f6311416 Mon Sep 17 00:00:00 2001
From 6c9d1fd52956c3148e847a214bae9102b1811de5 Mon Sep 17 00:00:00 2001
From: Vincent Tremblay <vincent@vtremblay.dev>
Date: Tue, 27 Dec 2022 09:00:58 -0500
Subject: [PATCH 2/2] spidev: Add Silicon Labs SI3210 device compatible
Date: Tue, 27 Dec 2022 09:10:08 -0500
Subject: [PATCH] spidev: Add Silicon Labs SI3210 device compatible
Add compatible string for Silicon Labs SI3210 device.
Note: This patch is adapted from a patch submitted to the for-next branch (v6.3).
Signed-off-by: Vincent Tremblay <vincent@vtremblay.dev>
Link: https://lore.kernel.org/r/20221227141011.111410-2-vincent@vtremblay.dev
Signed-off-by: Mark Brown <broonie@kernel.org>
---
drivers/spi/spidev.c | 2 ++
1 file changed, 2 insertions(+)
@@ -0,0 +1,33 @@
From 1ecf9e390452e73a362ea7fbde8f3f0db83de856 Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Thu, 22 Dec 2022 19:33:04 +0000
Subject: [PATCH] mtd: ubi: wire-up parent MTD device
Wire up the device parent pointer of UBI devices to their lower MTD
device, typically an MTD partition or whole-chip device.
The most noticeable change is that in sysfs, previously ubi devices
would be could in /sys/devices/virtual/ubi while after this change they
would be correctly attached to their parent MTD device, e.g.
/sys/devices/platform/1100d000.spi/spi_master/spi1/spi1.0/mtd/mtd2/ubi0.
Locating UBI devices using /sys/class/ubi/ of course still works as
well.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/ubi/build.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -929,6 +929,7 @@ int ubi_attach_mtd_dev(struct mtd_info *
ubi->dev.release = dev_release;
ubi->dev.class = &ubi_class;
ubi->dev.groups = ubi_dev_groups;
+ ubi->dev.parent = &mtd->dev;
ubi->mtd = mtd;
ubi->ubi_num = ubi_num;
@@ -0,0 +1,49 @@
From 05b8773ca33253ea562be145cf3145b05ef19f86 Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Thu, 22 Dec 2022 19:33:31 +0000
Subject: [PATCH] mtd: ubi: block: wire-up device parent
ubiblock devices were previously only identifyable by their name, but
not connected to their parent UBI volume device e.g. in sysfs.
Properly parent ubiblock device as descendant of a UBI volume device
to reflect device model hierachy.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/ubi/block.c | 2 +-
drivers/mtd/ubi/kapi.c | 1 +
include/linux/mtd/ubi.h | 1 +
3 files changed, 3 insertions(+), 1 deletion(-)
--- a/drivers/mtd/ubi/block.c
+++ b/drivers/mtd/ubi/block.c
@@ -452,7 +452,7 @@ int ubiblock_create(struct ubi_volume_in
list_add_tail(&dev->list, &ubiblock_devices);
/* Must be the last step: anyone can call file ops from now on */
- ret = add_disk(dev->gd);
+ ret = device_add_disk(vi->dev, dev->gd, NULL);
if (ret)
goto out_destroy_wq;
--- a/drivers/mtd/ubi/kapi.c
+++ b/drivers/mtd/ubi/kapi.c
@@ -79,6 +79,7 @@ void ubi_do_get_volume_info(struct ubi_d
vi->name_len = vol->name_len;
vi->name = vol->name;
vi->cdev = vol->cdev.dev;
+ vi->dev = &vol->dev;
}
/**
--- a/include/linux/mtd/ubi.h
+++ b/include/linux/mtd/ubi.h
@@ -110,6 +110,7 @@ struct ubi_volume_info {
int name_len;
const char *name;
dev_t cdev;
+ struct device *dev;
};
/**
@@ -0,0 +1,183 @@
From e1fbfa4a995d42e02e22b0dff2f8b4fdee1504b3 Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Tue, 14 Nov 2023 15:08:42 +0100
Subject: [PATCH 2/3] net: phy: aquantia: move MMD_VEND define to header
Move MMD_VEND define to header to clean things up and in preparation for
firmware loading support that require some define placed in
aquantia_main.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/phy/aquantia/aquantia.h | 69 +++++++++++++++++++++++
drivers/net/phy/aquantia/aquantia_hwmon.c | 14 -----
drivers/net/phy/aquantia/aquantia_main.c | 55 ------------------
3 files changed, 69 insertions(+), 69 deletions(-)
--- a/drivers/net/phy/aquantia/aquantia.h
+++ b/drivers/net/phy/aquantia/aquantia.h
@@ -9,6 +9,75 @@
#include <linux/device.h>
#include <linux/phy.h>
+/* Vendor specific 1, MDIO_MMD_VEND1 */
+#define VEND1_GLOBAL_FW_ID 0x0020
+#define VEND1_GLOBAL_FW_ID_MAJOR GENMASK(15, 8)
+#define VEND1_GLOBAL_FW_ID_MINOR GENMASK(7, 0)
+
+/* The following registers all have similar layouts; first the registers... */
+#define VEND1_GLOBAL_CFG_10M 0x0310
+#define VEND1_GLOBAL_CFG_100M 0x031b
+#define VEND1_GLOBAL_CFG_1G 0x031c
+#define VEND1_GLOBAL_CFG_2_5G 0x031d
+#define VEND1_GLOBAL_CFG_5G 0x031e
+#define VEND1_GLOBAL_CFG_10G 0x031f
+/* ...and now the fields */
+#define VEND1_GLOBAL_CFG_RATE_ADAPT GENMASK(8, 7)
+#define VEND1_GLOBAL_CFG_RATE_ADAPT_NONE 0
+#define VEND1_GLOBAL_CFG_RATE_ADAPT_USX 1
+#define VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE 2
+
+/* Vendor specific 1, MDIO_MMD_VEND2 */
+#define VEND1_THERMAL_PROV_HIGH_TEMP_FAIL 0xc421
+#define VEND1_THERMAL_PROV_LOW_TEMP_FAIL 0xc422
+#define VEND1_THERMAL_PROV_HIGH_TEMP_WARN 0xc423
+#define VEND1_THERMAL_PROV_LOW_TEMP_WARN 0xc424
+#define VEND1_THERMAL_STAT1 0xc820
+#define VEND1_THERMAL_STAT2 0xc821
+#define VEND1_THERMAL_STAT2_VALID BIT(0)
+#define VEND1_GENERAL_STAT1 0xc830
+#define VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL BIT(14)
+#define VEND1_GENERAL_STAT1_LOW_TEMP_FAIL BIT(13)
+#define VEND1_GENERAL_STAT1_HIGH_TEMP_WARN BIT(12)
+#define VEND1_GENERAL_STAT1_LOW_TEMP_WARN BIT(11)
+
+#define VEND1_GLOBAL_GEN_STAT2 0xc831
+#define VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG BIT(15)
+
+#define VEND1_GLOBAL_RSVD_STAT1 0xc885
+#define VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID GENMASK(7, 4)
+#define VEND1_GLOBAL_RSVD_STAT1_PROV_ID GENMASK(3, 0)
+
+#define VEND1_GLOBAL_RSVD_STAT9 0xc88d
+#define VEND1_GLOBAL_RSVD_STAT9_MODE GENMASK(7, 0)
+#define VEND1_GLOBAL_RSVD_STAT9_1000BT2 0x23
+
+#define VEND1_GLOBAL_INT_STD_STATUS 0xfc00
+#define VEND1_GLOBAL_INT_VEND_STATUS 0xfc01
+
+#define VEND1_GLOBAL_INT_STD_MASK 0xff00
+#define VEND1_GLOBAL_INT_STD_MASK_PMA1 BIT(15)
+#define VEND1_GLOBAL_INT_STD_MASK_PMA2 BIT(14)
+#define VEND1_GLOBAL_INT_STD_MASK_PCS1 BIT(13)
+#define VEND1_GLOBAL_INT_STD_MASK_PCS2 BIT(12)
+#define VEND1_GLOBAL_INT_STD_MASK_PCS3 BIT(11)
+#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS1 BIT(10)
+#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS2 BIT(9)
+#define VEND1_GLOBAL_INT_STD_MASK_AN1 BIT(8)
+#define VEND1_GLOBAL_INT_STD_MASK_AN2 BIT(7)
+#define VEND1_GLOBAL_INT_STD_MASK_GBE BIT(6)
+#define VEND1_GLOBAL_INT_STD_MASK_ALL BIT(0)
+
+#define VEND1_GLOBAL_INT_VEND_MASK 0xff01
+#define VEND1_GLOBAL_INT_VEND_MASK_PMA BIT(15)
+#define VEND1_GLOBAL_INT_VEND_MASK_PCS BIT(14)
+#define VEND1_GLOBAL_INT_VEND_MASK_PHY_XS BIT(13)
+#define VEND1_GLOBAL_INT_VEND_MASK_AN BIT(12)
+#define VEND1_GLOBAL_INT_VEND_MASK_GBE BIT(11)
+#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL1 BIT(2)
+#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL2 BIT(1)
+#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 BIT(0)
+
#if IS_REACHABLE(CONFIG_HWMON)
int aqr_hwmon_probe(struct phy_device *phydev);
#else
--- a/drivers/net/phy/aquantia/aquantia_hwmon.c
+++ b/drivers/net/phy/aquantia/aquantia_hwmon.c
@@ -13,20 +13,6 @@
#include "aquantia.h"
-/* Vendor specific 1, MDIO_MMD_VEND2 */
-#define VEND1_THERMAL_PROV_HIGH_TEMP_FAIL 0xc421
-#define VEND1_THERMAL_PROV_LOW_TEMP_FAIL 0xc422
-#define VEND1_THERMAL_PROV_HIGH_TEMP_WARN 0xc423
-#define VEND1_THERMAL_PROV_LOW_TEMP_WARN 0xc424
-#define VEND1_THERMAL_STAT1 0xc820
-#define VEND1_THERMAL_STAT2 0xc821
-#define VEND1_THERMAL_STAT2_VALID BIT(0)
-#define VEND1_GENERAL_STAT1 0xc830
-#define VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL BIT(14)
-#define VEND1_GENERAL_STAT1_LOW_TEMP_FAIL BIT(13)
-#define VEND1_GENERAL_STAT1_HIGH_TEMP_WARN BIT(12)
-#define VEND1_GENERAL_STAT1_LOW_TEMP_WARN BIT(11)
-
#if IS_REACHABLE(CONFIG_HWMON)
static umode_t aqr_hwmon_is_visible(const void *data,
--- a/drivers/net/phy/aquantia/aquantia_main.c
+++ b/drivers/net/phy/aquantia/aquantia_main.c
@@ -89,61 +89,6 @@
#define MDIO_C22EXT_STAT_SGMII_TX_FRAME_ALIGN_ERR 0xd31a
#define MDIO_C22EXT_STAT_SGMII_TX_RUNT_FRAMES 0xd31b
-/* Vendor specific 1, MDIO_MMD_VEND1 */
-#define VEND1_GLOBAL_FW_ID 0x0020
-#define VEND1_GLOBAL_FW_ID_MAJOR GENMASK(15, 8)
-#define VEND1_GLOBAL_FW_ID_MINOR GENMASK(7, 0)
-
-#define VEND1_GLOBAL_GEN_STAT2 0xc831
-#define VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG BIT(15)
-
-/* The following registers all have similar layouts; first the registers... */
-#define VEND1_GLOBAL_CFG_10M 0x0310
-#define VEND1_GLOBAL_CFG_100M 0x031b
-#define VEND1_GLOBAL_CFG_1G 0x031c
-#define VEND1_GLOBAL_CFG_2_5G 0x031d
-#define VEND1_GLOBAL_CFG_5G 0x031e
-#define VEND1_GLOBAL_CFG_10G 0x031f
-/* ...and now the fields */
-#define VEND1_GLOBAL_CFG_RATE_ADAPT GENMASK(8, 7)
-#define VEND1_GLOBAL_CFG_RATE_ADAPT_NONE 0
-#define VEND1_GLOBAL_CFG_RATE_ADAPT_USX 1
-#define VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE 2
-
-#define VEND1_GLOBAL_RSVD_STAT1 0xc885
-#define VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID GENMASK(7, 4)
-#define VEND1_GLOBAL_RSVD_STAT1_PROV_ID GENMASK(3, 0)
-
-#define VEND1_GLOBAL_RSVD_STAT9 0xc88d
-#define VEND1_GLOBAL_RSVD_STAT9_MODE GENMASK(7, 0)
-#define VEND1_GLOBAL_RSVD_STAT9_1000BT2 0x23
-
-#define VEND1_GLOBAL_INT_STD_STATUS 0xfc00
-#define VEND1_GLOBAL_INT_VEND_STATUS 0xfc01
-
-#define VEND1_GLOBAL_INT_STD_MASK 0xff00
-#define VEND1_GLOBAL_INT_STD_MASK_PMA1 BIT(15)
-#define VEND1_GLOBAL_INT_STD_MASK_PMA2 BIT(14)
-#define VEND1_GLOBAL_INT_STD_MASK_PCS1 BIT(13)
-#define VEND1_GLOBAL_INT_STD_MASK_PCS2 BIT(12)
-#define VEND1_GLOBAL_INT_STD_MASK_PCS3 BIT(11)
-#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS1 BIT(10)
-#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS2 BIT(9)
-#define VEND1_GLOBAL_INT_STD_MASK_AN1 BIT(8)
-#define VEND1_GLOBAL_INT_STD_MASK_AN2 BIT(7)
-#define VEND1_GLOBAL_INT_STD_MASK_GBE BIT(6)
-#define VEND1_GLOBAL_INT_STD_MASK_ALL BIT(0)
-
-#define VEND1_GLOBAL_INT_VEND_MASK 0xff01
-#define VEND1_GLOBAL_INT_VEND_MASK_PMA BIT(15)
-#define VEND1_GLOBAL_INT_VEND_MASK_PCS BIT(14)
-#define VEND1_GLOBAL_INT_VEND_MASK_PHY_XS BIT(13)
-#define VEND1_GLOBAL_INT_VEND_MASK_AN BIT(12)
-#define VEND1_GLOBAL_INT_VEND_MASK_GBE BIT(11)
-#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL1 BIT(2)
-#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL2 BIT(1)
-#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 BIT(0)
-
/* Sleep and timeout for checking if the Processor-Intensive
* MDIO operation is finished
*/
@@ -0,0 +1,504 @@
From e93984ebc1c82bd34f7a1b3391efaceee0a8ae96 Mon Sep 17 00:00:00 2001
From: Robert Marko <robimarko@gmail.com>
Date: Tue, 14 Nov 2023 15:08:43 +0100
Subject: [PATCH 3/3] net: phy: aquantia: add firmware load support
Aquantia PHY-s require firmware to be loaded before they start operating.
It can be automatically loaded in case when there is a SPI-NOR connected
to Aquantia PHY-s or can be loaded from the host via MDIO.
This patch adds support for loading the firmware via MDIO as in most cases
there is no SPI-NOR being used to save on cost.
Firmware loading code itself is ported from mainline U-boot with cleanups.
The firmware has mixed values both in big and little endian.
PHY core itself is big-endian but it expects values to be in little-endian.
The firmware is little-endian but CRC-16 value for it is stored at the end
of firmware in big-endian.
It seems the PHY does the conversion internally from firmware that is
little-endian to the PHY that is big-endian on using the mailbox
but mailbox returns a big-endian CRC-16 to verify the written data
integrity.
Co-developed-by: Christian Marangi <ansuelsmth@gmail.com>
Signed-off-by: Robert Marko <robimarko@gmail.com>
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/phy/aquantia/Kconfig | 1 +
drivers/net/phy/aquantia/Makefile | 2 +-
drivers/net/phy/aquantia/aquantia.h | 32 ++
drivers/net/phy/aquantia/aquantia_firmware.c | 370 +++++++++++++++++++
drivers/net/phy/aquantia/aquantia_main.c | 6 +
5 files changed, 410 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/phy/aquantia/aquantia_firmware.c
--- a/drivers/net/phy/aquantia/Kconfig
+++ b/drivers/net/phy/aquantia/Kconfig
@@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
config AQUANTIA_PHY
tristate "Aquantia PHYs"
+ select CRC_CCITT
help
Currently supports the Aquantia AQ1202, AQ2104, AQR105, AQR405
--- a/drivers/net/phy/aquantia/Makefile
+++ b/drivers/net/phy/aquantia/Makefile
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
-aquantia-objs += aquantia_main.o
+aquantia-objs += aquantia_main.o aquantia_firmware.o
ifdef CONFIG_HWMON
aquantia-objs += aquantia_hwmon.o
endif
--- a/drivers/net/phy/aquantia/aquantia.h
+++ b/drivers/net/phy/aquantia/aquantia.h
@@ -10,10 +10,35 @@
#include <linux/phy.h>
/* Vendor specific 1, MDIO_MMD_VEND1 */
+#define VEND1_GLOBAL_SC 0x0
+#define VEND1_GLOBAL_SC_SOFT_RESET BIT(15)
+#define VEND1_GLOBAL_SC_LOW_POWER BIT(11)
+
#define VEND1_GLOBAL_FW_ID 0x0020
#define VEND1_GLOBAL_FW_ID_MAJOR GENMASK(15, 8)
#define VEND1_GLOBAL_FW_ID_MINOR GENMASK(7, 0)
+#define VEND1_GLOBAL_MAILBOX_INTERFACE1 0x0200
+#define VEND1_GLOBAL_MAILBOX_INTERFACE1_EXECUTE BIT(15)
+#define VEND1_GLOBAL_MAILBOX_INTERFACE1_WRITE BIT(14)
+#define VEND1_GLOBAL_MAILBOX_INTERFACE1_CRC_RESET BIT(12)
+#define VEND1_GLOBAL_MAILBOX_INTERFACE1_BUSY BIT(8)
+
+#define VEND1_GLOBAL_MAILBOX_INTERFACE2 0x0201
+#define VEND1_GLOBAL_MAILBOX_INTERFACE3 0x0202
+#define VEND1_GLOBAL_MAILBOX_INTERFACE3_MSW_ADDR_MASK GENMASK(15, 0)
+#define VEND1_GLOBAL_MAILBOX_INTERFACE3_MSW_ADDR(x) FIELD_PREP(VEND1_GLOBAL_MAILBOX_INTERFACE3_MSW_ADDR_MASK, (u16)((x) >> 16))
+#define VEND1_GLOBAL_MAILBOX_INTERFACE4 0x0203
+#define VEND1_GLOBAL_MAILBOX_INTERFACE4_LSW_ADDR_MASK GENMASK(15, 2)
+#define VEND1_GLOBAL_MAILBOX_INTERFACE4_LSW_ADDR(x) FIELD_PREP(VEND1_GLOBAL_MAILBOX_INTERFACE4_LSW_ADDR_MASK, (u16)(x))
+
+#define VEND1_GLOBAL_MAILBOX_INTERFACE5 0x0204
+#define VEND1_GLOBAL_MAILBOX_INTERFACE5_MSW_DATA_MASK GENMASK(15, 0)
+#define VEND1_GLOBAL_MAILBOX_INTERFACE5_MSW_DATA(x) FIELD_PREP(VEND1_GLOBAL_MAILBOX_INTERFACE5_MSW_DATA_MASK, (u16)((x) >> 16))
+#define VEND1_GLOBAL_MAILBOX_INTERFACE6 0x0205
+#define VEND1_GLOBAL_MAILBOX_INTERFACE6_LSW_DATA_MASK GENMASK(15, 0)
+#define VEND1_GLOBAL_MAILBOX_INTERFACE6_LSW_DATA(x) FIELD_PREP(VEND1_GLOBAL_MAILBOX_INTERFACE6_LSW_DATA_MASK, (u16)(x))
+
/* The following registers all have similar layouts; first the registers... */
#define VEND1_GLOBAL_CFG_10M 0x0310
#define VEND1_GLOBAL_CFG_100M 0x031b
@@ -28,6 +53,11 @@
#define VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE 2
/* Vendor specific 1, MDIO_MMD_VEND2 */
+#define VEND1_GLOBAL_CONTROL2 0xc001
+#define VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_RST BIT(15)
+#define VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_OVD BIT(6)
+#define VEND1_GLOBAL_CONTROL2_UP_RUN_STALL BIT(0)
+
#define VEND1_THERMAL_PROV_HIGH_TEMP_FAIL 0xc421
#define VEND1_THERMAL_PROV_LOW_TEMP_FAIL 0xc422
#define VEND1_THERMAL_PROV_HIGH_TEMP_WARN 0xc423
@@ -83,3 +113,5 @@ int aqr_hwmon_probe(struct phy_device *p
#else
static inline int aqr_hwmon_probe(struct phy_device *phydev) { return 0; }
#endif
+
+int aqr_firmware_load(struct phy_device *phydev);
--- /dev/null
+++ b/drivers/net/phy/aquantia/aquantia_firmware.c
@@ -0,0 +1,370 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/bitfield.h>
+#include <linux/of.h>
+#include <linux/firmware.h>
+#include <linux/crc-ccitt.h>
+#include <linux/nvmem-consumer.h>
+
+#include <asm/unaligned.h>
+
+#include "aquantia.h"
+
+#define UP_RESET_SLEEP 100
+
+/* addresses of memory segments in the phy */
+#define DRAM_BASE_ADDR 0x3FFE0000
+#define IRAM_BASE_ADDR 0x40000000
+
+/* firmware image format constants */
+#define VERSION_STRING_SIZE 0x40
+#define VERSION_STRING_OFFSET 0x0200
+/* primary offset is written at an offset from the start of the fw blob */
+#define PRIMARY_OFFSET_OFFSET 0x8
+/* primary offset needs to be then added to a base offset */
+#define PRIMARY_OFFSET_SHIFT 12
+#define PRIMARY_OFFSET(x) ((x) << PRIMARY_OFFSET_SHIFT)
+#define HEADER_OFFSET 0x300
+
+struct aqr_fw_header {
+ u32 padding;
+ u8 iram_offset[3];
+ u8 iram_size[3];
+ u8 dram_offset[3];
+ u8 dram_size[3];
+} __packed;
+
+enum aqr_fw_src {
+ AQR_FW_SRC_NVMEM = 0,
+ AQR_FW_SRC_FS,
+};
+
+static const char * const aqr_fw_src_string[] = {
+ [AQR_FW_SRC_NVMEM] = "NVMEM",
+ [AQR_FW_SRC_FS] = "FS",
+};
+
+/* AQR firmware doesn't have fixed offsets for iram and dram section
+ * but instead provide an header with the offset to use on reading
+ * and parsing the firmware.
+ *
+ * AQR firmware can't be trusted and each offset is validated to be
+ * not negative and be in the size of the firmware itself.
+ */
+static bool aqr_fw_validate_get(size_t size, size_t offset, size_t get_size)
+{
+ return offset + get_size <= size;
+}
+
+static int aqr_fw_get_be16(const u8 *data, size_t offset, size_t size, u16 *value)
+{
+ if (!aqr_fw_validate_get(size, offset, sizeof(u16)))
+ return -EINVAL;
+
+ *value = get_unaligned_be16(data + offset);
+
+ return 0;
+}
+
+static int aqr_fw_get_le16(const u8 *data, size_t offset, size_t size, u16 *value)
+{
+ if (!aqr_fw_validate_get(size, offset, sizeof(u16)))
+ return -EINVAL;
+
+ *value = get_unaligned_le16(data + offset);
+
+ return 0;
+}
+
+static int aqr_fw_get_le24(const u8 *data, size_t offset, size_t size, u32 *value)
+{
+ if (!aqr_fw_validate_get(size, offset, sizeof(u8) * 3))
+ return -EINVAL;
+
+ *value = get_unaligned_le24(data + offset);
+
+ return 0;
+}
+
+/* load data into the phy's memory */
+static int aqr_fw_load_memory(struct phy_device *phydev, u32 addr,
+ const u8 *data, size_t len)
+{
+ u16 crc = 0, up_crc;
+ size_t pos;
+
+ /* PHY expect addr in LE */
+ addr = (__force u32)cpu_to_le32(addr);
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1,
+ VEND1_GLOBAL_MAILBOX_INTERFACE1,
+ VEND1_GLOBAL_MAILBOX_INTERFACE1_CRC_RESET);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1,
+ VEND1_GLOBAL_MAILBOX_INTERFACE3,
+ VEND1_GLOBAL_MAILBOX_INTERFACE3_MSW_ADDR(addr));
+ phy_write_mmd(phydev, MDIO_MMD_VEND1,
+ VEND1_GLOBAL_MAILBOX_INTERFACE4,
+ VEND1_GLOBAL_MAILBOX_INTERFACE4_LSW_ADDR(addr));
+
+ /* We assume and enforce the size to be word aligned.
+ * If a firmware that is not word aligned is found, please report upstream.
+ */
+ for (pos = 0; pos < len; pos += sizeof(u32)) {
+ u32 word;
+
+ /* FW data is always stored in little-endian */
+ word = get_unaligned((const u32 *)(data + pos));
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_MAILBOX_INTERFACE5,
+ VEND1_GLOBAL_MAILBOX_INTERFACE5_MSW_DATA(word));
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_MAILBOX_INTERFACE6,
+ VEND1_GLOBAL_MAILBOX_INTERFACE6_LSW_DATA(word));
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_MAILBOX_INTERFACE1,
+ VEND1_GLOBAL_MAILBOX_INTERFACE1_EXECUTE |
+ VEND1_GLOBAL_MAILBOX_INTERFACE1_WRITE);
+
+ /* calculate CRC as we load data to the mailbox.
+ * We convert word to big-endian as PHY is BE and mailbox will
+ * return a BE CRC.
+ */
+ word = (__force u32)cpu_to_be32(word);
+ crc = crc_ccitt_false(crc, (u8 *)&word, sizeof(word));
+ }
+
+ up_crc = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_MAILBOX_INTERFACE2);
+ if (crc != up_crc) {
+ phydev_err(phydev, "CRC mismatch: calculated 0x%04x PHY 0x%04x\n",
+ crc, up_crc);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int aqr_fw_boot(struct phy_device *phydev, const u8 *data, size_t size,
+ enum aqr_fw_src fw_src)
+{
+ u16 calculated_crc, read_crc, read_primary_offset;
+ u32 iram_offset = 0, iram_size = 0;
+ u32 dram_offset = 0, dram_size = 0;
+ char version[VERSION_STRING_SIZE];
+ u32 primary_offset = 0;
+ int ret;
+
+ /* extract saved CRC at the end of the fw
+ * CRC is saved in big-endian as PHY is BE
+ */
+ ret = aqr_fw_get_be16(data, size - sizeof(u16), size, &read_crc);
+ if (ret) {
+ phydev_err(phydev, "bad firmware CRC in firmware\n");
+ return ret;
+ }
+ calculated_crc = crc_ccitt_false(0, data, size - sizeof(u16));
+ if (read_crc != calculated_crc) {
+ phydev_err(phydev, "bad firmware CRC: file 0x%04x calculated 0x%04x\n",
+ read_crc, calculated_crc);
+ return -EINVAL;
+ }
+
+ /* Get the primary offset to extract DRAM and IRAM sections. */
+ ret = aqr_fw_get_le16(data, PRIMARY_OFFSET_OFFSET, size, &read_primary_offset);
+ if (ret) {
+ phydev_err(phydev, "bad primary offset in firmware\n");
+ return ret;
+ }
+ primary_offset = PRIMARY_OFFSET(read_primary_offset);
+
+ /* Find the DRAM and IRAM sections within the firmware file.
+ * Make sure the fw_header is correctly in the firmware.
+ */
+ if (!aqr_fw_validate_get(size, primary_offset + HEADER_OFFSET,
+ sizeof(struct aqr_fw_header))) {
+ phydev_err(phydev, "bad fw_header in firmware\n");
+ return -EINVAL;
+ }
+
+ /* offset are in LE and values needs to be converted to cpu endian */
+ ret = aqr_fw_get_le24(data, primary_offset + HEADER_OFFSET +
+ offsetof(struct aqr_fw_header, iram_offset),
+ size, &iram_offset);
+ if (ret) {
+ phydev_err(phydev, "bad iram offset in firmware\n");
+ return ret;
+ }
+ ret = aqr_fw_get_le24(data, primary_offset + HEADER_OFFSET +
+ offsetof(struct aqr_fw_header, iram_size),
+ size, &iram_size);
+ if (ret) {
+ phydev_err(phydev, "invalid iram size in firmware\n");
+ return ret;
+ }
+ ret = aqr_fw_get_le24(data, primary_offset + HEADER_OFFSET +
+ offsetof(struct aqr_fw_header, dram_offset),
+ size, &dram_offset);
+ if (ret) {
+ phydev_err(phydev, "bad dram offset in firmware\n");
+ return ret;
+ }
+ ret = aqr_fw_get_le24(data, primary_offset + HEADER_OFFSET +
+ offsetof(struct aqr_fw_header, dram_size),
+ size, &dram_size);
+ if (ret) {
+ phydev_err(phydev, "invalid dram size in firmware\n");
+ return ret;
+ }
+
+ /* Increment the offset with the primary offset.
+ * Validate iram/dram offset and size.
+ */
+ iram_offset += primary_offset;
+ if (iram_size % sizeof(u32)) {
+ phydev_err(phydev, "iram size if not aligned to word size. Please report this upstream!\n");
+ return -EINVAL;
+ }
+ if (!aqr_fw_validate_get(size, iram_offset, iram_size)) {
+ phydev_err(phydev, "invalid iram offset for iram size\n");
+ return -EINVAL;
+ }
+
+ dram_offset += primary_offset;
+ if (dram_size % sizeof(u32)) {
+ phydev_err(phydev, "dram size if not aligned to word size. Please report this upstream!\n");
+ return -EINVAL;
+ }
+ if (!aqr_fw_validate_get(size, dram_offset, dram_size)) {
+ phydev_err(phydev, "invalid iram offset for iram size\n");
+ return -EINVAL;
+ }
+
+ phydev_dbg(phydev, "primary %d IRAM offset=%d size=%d DRAM offset=%d size=%d\n",
+ primary_offset, iram_offset, iram_size, dram_offset, dram_size);
+
+ if (!aqr_fw_validate_get(size, dram_offset + VERSION_STRING_OFFSET,
+ VERSION_STRING_SIZE)) {
+ phydev_err(phydev, "invalid version in firmware\n");
+ return -EINVAL;
+ }
+ strscpy(version, (char *)data + dram_offset + VERSION_STRING_OFFSET,
+ VERSION_STRING_SIZE);
+ if (version[0] == '\0') {
+ phydev_err(phydev, "invalid version in firmware\n");
+ return -EINVAL;
+ }
+ phydev_info(phydev, "loading firmware version '%s' from '%s'\n", version,
+ aqr_fw_src_string[fw_src]);
+
+ /* stall the microcprocessor */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_CONTROL2,
+ VEND1_GLOBAL_CONTROL2_UP_RUN_STALL | VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_OVD);
+
+ phydev_dbg(phydev, "loading DRAM 0x%08x from offset=%d size=%d\n",
+ DRAM_BASE_ADDR, dram_offset, dram_size);
+ ret = aqr_fw_load_memory(phydev, DRAM_BASE_ADDR, data + dram_offset,
+ dram_size);
+ if (ret)
+ return ret;
+
+ phydev_dbg(phydev, "loading IRAM 0x%08x from offset=%d size=%d\n",
+ IRAM_BASE_ADDR, iram_offset, iram_size);
+ ret = aqr_fw_load_memory(phydev, IRAM_BASE_ADDR, data + iram_offset,
+ iram_size);
+ if (ret)
+ return ret;
+
+ /* make sure soft reset and low power mode are clear */
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_SC,
+ VEND1_GLOBAL_SC_SOFT_RESET | VEND1_GLOBAL_SC_LOW_POWER);
+
+ /* Release the microprocessor. UP_RESET must be held for 100 usec. */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_CONTROL2,
+ VEND1_GLOBAL_CONTROL2_UP_RUN_STALL |
+ VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_OVD |
+ VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_RST);
+ usleep_range(UP_RESET_SLEEP, UP_RESET_SLEEP * 2);
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_CONTROL2,
+ VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_OVD);
+
+ return 0;
+}
+
+static int aqr_firmware_load_nvmem(struct phy_device *phydev)
+{
+ struct nvmem_cell *cell;
+ size_t size;
+ u8 *buf;
+ int ret;
+
+ cell = nvmem_cell_get(&phydev->mdio.dev, "firmware");
+ if (IS_ERR(cell))
+ return PTR_ERR(cell);
+
+ buf = nvmem_cell_read(cell, &size);
+ if (IS_ERR(buf)) {
+ ret = PTR_ERR(buf);
+ goto exit;
+ }
+
+ ret = aqr_fw_boot(phydev, buf, size, AQR_FW_SRC_NVMEM);
+ if (ret)
+ phydev_err(phydev, "firmware loading failed: %d\n", ret);
+
+ kfree(buf);
+exit:
+ nvmem_cell_put(cell);
+
+ return ret;
+}
+
+static int aqr_firmware_load_fs(struct phy_device *phydev)
+{
+ struct device *dev = &phydev->mdio.dev;
+ const struct firmware *fw;
+ const char *fw_name;
+ int ret;
+
+ ret = of_property_read_string(dev->of_node, "firmware-name",
+ &fw_name);
+ if (ret)
+ return ret;
+
+ ret = request_firmware(&fw, fw_name, dev);
+ if (ret) {
+ phydev_err(phydev, "failed to find FW file %s (%d)\n",
+ fw_name, ret);
+ return ret;
+ }
+
+ ret = aqr_fw_boot(phydev, fw->data, fw->size, AQR_FW_SRC_FS);
+ if (ret)
+ phydev_err(phydev, "firmware loading failed: %d\n", ret);
+
+ release_firmware(fw);
+
+ return ret;
+}
+
+int aqr_firmware_load(struct phy_device *phydev)
+{
+ int ret;
+
+ /* Check if the firmware is not already loaded by pooling
+ * the current version returned by the PHY. If 0 is returned,
+ * no firmware is loaded.
+ */
+ ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_FW_ID);
+ if (ret > 0)
+ goto exit;
+
+ ret = aqr_firmware_load_nvmem(phydev);
+ if (!ret)
+ goto exit;
+
+ ret = aqr_firmware_load_fs(phydev);
+ if (ret)
+ return ret;
+
+exit:
+ return 0;
+}
--- a/drivers/net/phy/aquantia/aquantia_main.c
+++ b/drivers/net/phy/aquantia/aquantia_main.c
@@ -656,11 +656,17 @@ static int aqr107_resume(struct phy_devi
static int aqr107_probe(struct phy_device *phydev)
{
+ int ret;
+
phydev->priv = devm_kzalloc(&phydev->mdio.dev,
sizeof(struct aqr107_priv), GFP_KERNEL);
if (!phydev->priv)
return -ENOMEM;
+ ret = aqr_firmware_load(phydev);
+ if (ret)
+ return ret;
+
return aqr_hwmon_probe(phydev);
}
@@ -0,0 +1,326 @@
From 4e4aafcddbbfcdd6eed5780e190fcbfac8b4685a Mon Sep 17 00:00:00 2001
From: Andrew Lunn <andrew@lunn.ch>
Date: Mon, 9 Jan 2023 16:30:41 +0100
Subject: [PATCH] net: mdio: Add dedicated C45 API to MDIO bus drivers
Currently C22 and C45 transactions are mixed over a combined API calls
which make use of a special bit in the reg address to indicate if a
C45 transaction should be performed. This makes it impossible to know
if the bus driver actually supports C45. Additionally, many C22 only
drivers don't return -EOPNOTSUPP when asked to perform a C45
transaction, they mistaking perform a C22 transaction.
This is the first step to cleanly separate C22 from C45. To maintain
backwards compatibility until all drivers which are capable of
performing C45 are converted to this new API, the helper functions
will fall back to the older API if the new API is not
supported. Eventually this fallback will be removed.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Michael Walle <michael@walle.cc>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/phy/mdio_bus.c | 189 +++++++++++++++++++++++++++++++++++++
include/linux/mdio.h | 39 ++++----
include/linux/phy.h | 5 +
3 files changed, 214 insertions(+), 19 deletions(-)
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -832,6 +832,100 @@ int __mdiobus_modify_changed(struct mii_
EXPORT_SYMBOL_GPL(__mdiobus_modify_changed);
/**
+ * __mdiobus_c45_read - Unlocked version of the mdiobus_c45_read function
+ * @bus: the mii_bus struct
+ * @addr: the phy address
+ * @devad: device address to read
+ * @regnum: register number to read
+ *
+ * Read a MDIO bus register. Caller must hold the mdio bus lock.
+ *
+ * NOTE: MUST NOT be called from interrupt context.
+ */
+int __mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum)
+{
+ int retval;
+
+ lockdep_assert_held_once(&bus->mdio_lock);
+
+ if (bus->read_c45)
+ retval = bus->read_c45(bus, addr, devad, regnum);
+ else
+ retval = bus->read(bus, addr, mdiobus_c45_addr(devad, regnum));
+
+ trace_mdio_access(bus, 1, addr, regnum, retval, retval);
+ mdiobus_stats_acct(&bus->stats[addr], true, retval);
+
+ return retval;
+}
+EXPORT_SYMBOL(__mdiobus_c45_read);
+
+/**
+ * __mdiobus_c45_write - Unlocked version of the mdiobus_write function
+ * @bus: the mii_bus struct
+ * @addr: the phy address
+ * @devad: device address to read
+ * @regnum: register number to write
+ * @val: value to write to @regnum
+ *
+ * Write a MDIO bus register. Caller must hold the mdio bus lock.
+ *
+ * NOTE: MUST NOT be called from interrupt context.
+ */
+int __mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum,
+ u16 val)
+{
+ int err;
+
+ lockdep_assert_held_once(&bus->mdio_lock);
+
+ if (bus->write_c45)
+ err = bus->write_c45(bus, addr, devad, regnum, val);
+ else
+ err = bus->write(bus, addr, mdiobus_c45_addr(devad, regnum),
+ val);
+
+ trace_mdio_access(bus, 0, addr, regnum, val, err);
+ mdiobus_stats_acct(&bus->stats[addr], false, err);
+
+ return err;
+}
+EXPORT_SYMBOL(__mdiobus_c45_write);
+
+/**
+ * __mdiobus_c45_modify_changed - Unlocked version of the mdiobus_modify function
+ * @bus: the mii_bus struct
+ * @addr: the phy address
+ * @devad: device address to read
+ * @regnum: register number to modify
+ * @mask: bit mask of bits to clear
+ * @set: bit mask of bits to set
+ *
+ * Read, modify, and if any change, write the register value back to the
+ * device. Any error returns a negative number.
+ *
+ * NOTE: MUST NOT be called from interrupt context.
+ */
+static int __mdiobus_c45_modify_changed(struct mii_bus *bus, int addr,
+ int devad, u32 regnum, u16 mask,
+ u16 set)
+{
+ int new, ret;
+
+ ret = __mdiobus_c45_read(bus, addr, devad, regnum);
+ if (ret < 0)
+ return ret;
+
+ new = (ret & ~mask) | set;
+ if (new == ret)
+ return 0;
+
+ ret = __mdiobus_c45_write(bus, addr, devad, regnum, new);
+
+ return ret < 0 ? ret : 1;
+}
+
+/**
* mdiobus_read_nested - Nested version of the mdiobus_read function
* @bus: the mii_bus struct
* @addr: the phy address
@@ -879,6 +973,29 @@ int mdiobus_read(struct mii_bus *bus, in
EXPORT_SYMBOL(mdiobus_read);
/**
+ * mdiobus_c45_read - Convenience function for reading a given MII mgmt register
+ * @bus: the mii_bus struct
+ * @addr: the phy address
+ * @devad: device address to read
+ * @regnum: register number to read
+ *
+ * NOTE: MUST NOT be called from interrupt context,
+ * because the bus read/write functions may wait for an interrupt
+ * to conclude the operation.
+ */
+int mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum)
+{
+ int retval;
+
+ mutex_lock(&bus->mdio_lock);
+ retval = __mdiobus_c45_read(bus, addr, devad, regnum);
+ mutex_unlock(&bus->mdio_lock);
+
+ return retval;
+}
+EXPORT_SYMBOL(mdiobus_c45_read);
+
+/**
* mdiobus_write_nested - Nested version of the mdiobus_write function
* @bus: the mii_bus struct
* @addr: the phy address
@@ -928,6 +1045,31 @@ int mdiobus_write(struct mii_bus *bus, i
EXPORT_SYMBOL(mdiobus_write);
/**
+ * mdiobus_c45_write - Convenience function for writing a given MII mgmt register
+ * @bus: the mii_bus struct
+ * @addr: the phy address
+ * @devad: device address to read
+ * @regnum: register number to write
+ * @val: value to write to @regnum
+ *
+ * NOTE: MUST NOT be called from interrupt context,
+ * because the bus read/write functions may wait for an interrupt
+ * to conclude the operation.
+ */
+int mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum,
+ u16 val)
+{
+ int err;
+
+ mutex_lock(&bus->mdio_lock);
+ err = __mdiobus_c45_write(bus, addr, devad, regnum, val);
+ mutex_unlock(&bus->mdio_lock);
+
+ return err;
+}
+EXPORT_SYMBOL(mdiobus_c45_write);
+
+/**
* mdiobus_modify - Convenience function for modifying a given mdio device
* register
* @bus: the mii_bus struct
@@ -949,6 +1091,30 @@ int mdiobus_modify(struct mii_bus *bus,
EXPORT_SYMBOL_GPL(mdiobus_modify);
/**
+ * mdiobus_c45_modify - Convenience function for modifying a given mdio device
+ * register
+ * @bus: the mii_bus struct
+ * @addr: the phy address
+ * @devad: device address to read
+ * @regnum: register number to write
+ * @mask: bit mask of bits to clear
+ * @set: bit mask of bits to set
+ */
+int mdiobus_c45_modify(struct mii_bus *bus, int addr, int devad, u32 regnum,
+ u16 mask, u16 set)
+{
+ int err;
+
+ mutex_lock(&bus->mdio_lock);
+ err = __mdiobus_c45_modify_changed(bus, addr, devad, regnum,
+ mask, set);
+ mutex_unlock(&bus->mdio_lock);
+
+ return err < 0 ? err : 0;
+}
+EXPORT_SYMBOL_GPL(mdiobus_c45_modify);
+
+/**
* mdiobus_modify_changed - Convenience function for modifying a given mdio
* device register and returning if it changed
* @bus: the mii_bus struct
@@ -971,6 +1137,29 @@ int mdiobus_modify_changed(struct mii_bu
EXPORT_SYMBOL_GPL(mdiobus_modify_changed);
/**
+ * mdiobus_c45_modify_changed - Convenience function for modifying a given mdio
+ * device register and returning if it changed
+ * @bus: the mii_bus struct
+ * @addr: the phy address
+ * @devad: device address to read
+ * @regnum: register number to write
+ * @mask: bit mask of bits to clear
+ * @set: bit mask of bits to set
+ */
+int mdiobus_c45_modify_changed(struct mii_bus *bus, int devad, int addr,
+ u32 regnum, u16 mask, u16 set)
+{
+ int err;
+
+ mutex_lock(&bus->mdio_lock);
+ err = __mdiobus_c45_modify_changed(bus, addr, devad, regnum, mask, set);
+ mutex_unlock(&bus->mdio_lock);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(mdiobus_c45_modify_changed);
+
+/**
* mdio_bus_match - determine if given MDIO driver supports the given
* MDIO device
* @dev: target MDIO device
--- a/include/linux/mdio.h
+++ b/include/linux/mdio.h
@@ -423,6 +423,17 @@ int mdiobus_modify(struct mii_bus *bus,
u16 set);
int mdiobus_modify_changed(struct mii_bus *bus, int addr, u32 regnum,
u16 mask, u16 set);
+int __mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum);
+int mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum);
+int __mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum,
+ u16 val);
+int mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum,
+ u16 val);
+int mdiobus_c45_modify(struct mii_bus *bus, int addr, int devad, u32 regnum,
+ u16 mask, u16 set);
+
+int mdiobus_c45_modify_changed(struct mii_bus *bus, int addr, int devad,
+ u32 regnum, u16 mask, u16 set);
static inline int mdiodev_read(struct mdio_device *mdiodev, u32 regnum)
{
@@ -463,29 +474,19 @@ static inline u16 mdiobus_c45_devad(u32
return FIELD_GET(MII_DEVADDR_C45_MASK, regnum);
}
-static inline int __mdiobus_c45_read(struct mii_bus *bus, int prtad, int devad,
- u16 regnum)
-{
- return __mdiobus_read(bus, prtad, mdiobus_c45_addr(devad, regnum));
-}
-
-static inline int __mdiobus_c45_write(struct mii_bus *bus, int prtad, int devad,
- u16 regnum, u16 val)
-{
- return __mdiobus_write(bus, prtad, mdiobus_c45_addr(devad, regnum),
- val);
-}
-
-static inline int mdiobus_c45_read(struct mii_bus *bus, int prtad, int devad,
- u16 regnum)
+static inline int mdiodev_c45_modify(struct mdio_device *mdiodev, int devad,
+ u32 regnum, u16 mask, u16 set)
{
- return mdiobus_read(bus, prtad, mdiobus_c45_addr(devad, regnum));
+ return mdiobus_c45_modify(mdiodev->bus, mdiodev->addr, devad, regnum,
+ mask, set);
}
-static inline int mdiobus_c45_write(struct mii_bus *bus, int prtad, int devad,
- u16 regnum, u16 val)
+static inline int mdiodev_c45_modify_changed(struct mdio_device *mdiodev,
+ int devad, u32 regnum, u16 mask,
+ u16 set)
{
- return mdiobus_write(bus, prtad, mdiobus_c45_addr(devad, regnum), val);
+ return mdiobus_c45_modify_changed(mdiodev->bus, mdiodev->addr, devad,
+ regnum, mask, set);
}
int mdiobus_register_device(struct mdio_device *mdiodev);
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -364,6 +364,11 @@ struct mii_bus {
int (*read)(struct mii_bus *bus, int addr, int regnum);
/** @write: Perform a write transfer on the bus */
int (*write)(struct mii_bus *bus, int addr, int regnum, u16 val);
+ /** @read_c45: Perform a C45 read transfer on the bus */
+ int (*read_c45)(struct mii_bus *bus, int addr, int devnum, int regnum);
+ /** @write_c45: Perform a C45 write transfer on the bus */
+ int (*write_c45)(struct mii_bus *bus, int addr, int devnum,
+ int regnum, u16 val);
/** @reset: Perform a reset of the bus */
int (*reset)(struct mii_bus *bus);
@@ -0,0 +1,105 @@
From 9a0e95e34e9c0a713ddfd48c3a88a20d2bdfd514 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <j4g8y7@gmail.com>
Date: Fri, 11 Aug 2023 13:10:07 +0200
Subject: [PATCH] net: phy: Introduce PSGMII PHY interface mode
The PSGMII interface is similar to QSGMII. The main difference
is that the PSGMII interface combines five SGMII lines into a
single link while in QSGMII only four lines are combined.
Similarly to the QSGMII, this interface mode might also needs
special handling within the MAC driver.
It is commonly used by Qualcomm with their QCA807x PHY series and
modern WiSoC-s.
Add definitions for the PHY layer to allow to express this type
of connection between the MAC and PHY.
Signed-off-by: Gabor Juhos <j4g8y7@gmail.com>
Signed-off-by: Robert Marko <robert.marko@sartura.hr>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
Documentation/networking/phy.rst | 4 ++++
drivers/net/phy/phy-core.c | 2 ++
drivers/net/phy/phylink.c | 3 +++
include/linux/phy.h | 4 ++++
4 files changed, 13 insertions(+)
--- a/Documentation/networking/phy.rst
+++ b/Documentation/networking/phy.rst
@@ -323,6 +323,10 @@ Some of the interface modes are describe
contrast with the 1000BASE-X phy mode used for Clause 38 and 39 PMDs, this
interface mode has different autonegotiation and only supports full duplex.
+``PHY_INTERFACE_MODE_PSGMII``
+ This is the Penta SGMII mode, it is similar to QSGMII but it combines 5
+ SGMII lines into a single link compared to 4 on QSGMII.
+
Pause frames / flow control
===========================
--- a/drivers/net/phy/phy-core.c
+++ b/drivers/net/phy/phy-core.c
@@ -140,6 +140,8 @@ int phy_interface_num_ports(phy_interfac
case PHY_INTERFACE_MODE_QSGMII:
case PHY_INTERFACE_MODE_QUSGMII:
return 4;
+ case PHY_INTERFACE_MODE_PSGMII:
+ return 5;
case PHY_INTERFACE_MODE_MAX:
WARN_ONCE(1, "PHY_INTERFACE_MODE_MAX isn't a valid interface mode");
return 0;
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -187,6 +187,7 @@ static int phylink_interface_max_speed(p
case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_PSGMII:
case PHY_INTERFACE_MODE_QSGMII:
case PHY_INTERFACE_MODE_QUSGMII:
case PHY_INTERFACE_MODE_SGMII:
@@ -448,6 +449,7 @@ unsigned long phylink_get_capabilities(p
case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_PSGMII:
case PHY_INTERFACE_MODE_QSGMII:
case PHY_INTERFACE_MODE_QUSGMII:
case PHY_INTERFACE_MODE_SGMII:
@@ -814,6 +816,7 @@ static int phylink_parse_mode(struct phy
switch (pl->link_config.interface) {
case PHY_INTERFACE_MODE_SGMII:
+ case PHY_INTERFACE_MODE_PSGMII:
case PHY_INTERFACE_MODE_QSGMII:
case PHY_INTERFACE_MODE_QUSGMII:
case PHY_INTERFACE_MODE_RGMII:
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -103,6 +103,7 @@ extern const int phy_10gbit_features_arr
* @PHY_INTERFACE_MODE_XGMII: 10 gigabit media-independent interface
* @PHY_INTERFACE_MODE_XLGMII:40 gigabit media-independent interface
* @PHY_INTERFACE_MODE_MOCA: Multimedia over Coax
+ * @PHY_INTERFACE_MODE_PSGMII: Penta SGMII
* @PHY_INTERFACE_MODE_QSGMII: Quad SGMII
* @PHY_INTERFACE_MODE_TRGMII: Turbo RGMII
* @PHY_INTERFACE_MODE_100BASEX: 100 BaseX
@@ -140,6 +141,7 @@ typedef enum {
PHY_INTERFACE_MODE_XGMII,
PHY_INTERFACE_MODE_XLGMII,
PHY_INTERFACE_MODE_MOCA,
+ PHY_INTERFACE_MODE_PSGMII,
PHY_INTERFACE_MODE_QSGMII,
PHY_INTERFACE_MODE_TRGMII,
PHY_INTERFACE_MODE_100BASEX,
@@ -247,6 +249,8 @@ static inline const char *phy_modes(phy_
return "xlgmii";
case PHY_INTERFACE_MODE_MOCA:
return "moca";
+ case PHY_INTERFACE_MODE_PSGMII:
+ return "psgmii";
case PHY_INTERFACE_MODE_QSGMII:
return "qsgmii";
case PHY_INTERFACE_MODE_TRGMII:
@@ -0,0 +1,32 @@
From a593a2fcfdfb92cfd0ffc54bc81b07e6bfaaaf46 Mon Sep 17 00:00:00 2001
From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Date: Thu, 16 Mar 2023 14:08:26 +0200
Subject: [PATCH] net: phy: at803x: Replace of_gpio.h with what indeed is used
of_gpio.h in this driver is solely used as a proxy to other headers.
This is incorrect usage of the of_gpio.h. Replace it .h with what
indeed is used in the code.
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/phy/at803x.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -13,12 +13,11 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool_netlink.h>
-#include <linux/of_gpio.h>
#include <linux/bitfield.h>
-#include <linux/gpio/consumer.h>
#include <linux/regulator/of_regulator.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/consumer.h>
+#include <linux/of.h>
#include <linux/phylink.h>
#include <linux/sfp.h>
#include <dt-bindings/net/qca-ar803x.h>
@@ -0,0 +1,70 @@
From 8b8bc13d89a7d23d14b0e041c73f037c9db997b1 Mon Sep 17 00:00:00 2001
From: Luo Jie <quic_luoj@quicinc.com>
Date: Sun, 16 Jul 2023 16:49:19 +0800
Subject: [PATCH 1/6] net: phy: at803x: support qca8081
genphy_c45_pma_read_abilities
qca8081 PHY supports to use genphy_c45_pma_read_abilities for
getting the PHY features supported except for the autoneg ability
but autoneg ability exists in MDIO_STAT1 instead of MMD7.1, add it
manually after calling genphy_c45_pma_read_abilities.
Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/phy/at803x.c | 28 ++++++++++++++++++----------
1 file changed, 18 insertions(+), 10 deletions(-)
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -902,15 +902,6 @@ static int at803x_get_features(struct ph
if (err)
return err;
- if (phydev->drv->phy_id == QCA8081_PHY_ID) {
- err = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_NG_EXTABLE);
- if (err < 0)
- return err;
-
- linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported,
- err & MDIO_PMA_NG_EXTABLE_2_5GBT);
- }
-
if (phydev->drv->phy_id != ATH8031_PHY_ID)
return 0;
@@ -1996,6 +1987,23 @@ static int qca808x_cable_test_get_status
return 0;
}
+static int qca808x_get_features(struct phy_device *phydev)
+{
+ int ret;
+
+ ret = genphy_c45_pma_read_abilities(phydev);
+ if (ret)
+ return ret;
+
+ /* The autoneg ability is not existed in bit3 of MMD7.1,
+ * but it is supported by qca808x PHY, so we add it here
+ * manually.
+ */
+ linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported);
+
+ return 0;
+}
+
static struct phy_driver at803x_driver[] = {
{
/* Qualcomm Atheros AR8035 */
@@ -2163,7 +2171,7 @@ static struct phy_driver at803x_driver[]
.set_tunable = at803x_set_tunable,
.set_wol = at803x_set_wol,
.get_wol = at803x_get_wol,
- .get_features = at803x_get_features,
+ .get_features = qca808x_get_features,
.config_aneg = at803x_config_aneg,
.suspend = genphy_suspend,
.resume = genphy_resume,
@@ -0,0 +1,73 @@
From f3db55ae860a82e1224a909072783ef850e5d228 Mon Sep 17 00:00:00 2001
From: Luo Jie <quic_luoj@quicinc.com>
Date: Sun, 16 Jul 2023 16:49:20 +0800
Subject: [PATCH 2/6] net: phy: at803x: merge qca8081 slave seed function
merge the seed enablement and seed value configuration into
one function, since the random seed value is needed to be
configured when the seed is enabled.
Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/phy/at803x.c | 29 +++++++++--------------------
1 file changed, 9 insertions(+), 20 deletions(-)
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -1730,24 +1730,19 @@ static int qca808x_phy_fast_retrain_conf
return 0;
}
-static int qca808x_phy_ms_random_seed_set(struct phy_device *phydev)
-{
- u16 seed_value = prandom_u32_max(QCA808X_MASTER_SLAVE_SEED_RANGE);
-
- return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED,
- QCA808X_MASTER_SLAVE_SEED_CFG,
- FIELD_PREP(QCA808X_MASTER_SLAVE_SEED_CFG, seed_value));
-}
-
static int qca808x_phy_ms_seed_enable(struct phy_device *phydev, bool enable)
{
- u16 seed_enable = 0;
+ u16 seed_value;
- if (enable)
- seed_enable = QCA808X_MASTER_SLAVE_SEED_ENABLE;
+ if (!enable)
+ return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED,
+ QCA808X_MASTER_SLAVE_SEED_ENABLE, 0);
+ seed_value = prandom_u32_max(QCA808X_MASTER_SLAVE_SEED_RANGE);
return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED,
- QCA808X_MASTER_SLAVE_SEED_ENABLE, seed_enable);
+ QCA808X_MASTER_SLAVE_SEED_CFG | QCA808X_MASTER_SLAVE_SEED_ENABLE,
+ FIELD_PREP(QCA808X_MASTER_SLAVE_SEED_CFG, seed_value) |
+ QCA808X_MASTER_SLAVE_SEED_ENABLE);
}
static int qca808x_config_init(struct phy_device *phydev)
@@ -1771,12 +1766,7 @@ static int qca808x_config_init(struct ph
if (ret)
return ret;
- /* Configure lower ramdom seed to make phy linked as slave mode */
- ret = qca808x_phy_ms_random_seed_set(phydev);
- if (ret)
- return ret;
-
- /* Enable seed */
+ /* Enable seed and configure lower ramdom seed to make phy linked as slave mode */
ret = qca808x_phy_ms_seed_enable(phydev, true);
if (ret)
return ret;
@@ -1821,7 +1811,6 @@ static int qca808x_read_status(struct ph
if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR) {
qca808x_phy_ms_seed_enable(phydev, false);
} else {
- qca808x_phy_ms_random_seed_set(phydev);
qca808x_phy_ms_seed_enable(phydev, true);
}
}
@@ -0,0 +1,76 @@
From 7cc3209558002d95c0d45a1276ba4f5f741eec42 Mon Sep 17 00:00:00 2001
From: Luo Jie <quic_luoj@quicinc.com>
Date: Sun, 16 Jul 2023 16:49:21 +0800
Subject: [PATCH 3/6] net: phy: at803x: enable qca8081 slave seed conditionally
qca8081 is the single port PHY, the slave prefer mode is used
by default.
if the phy master perfer mode is configured, the slave seed
configuration should not be enabled, since the slave seed
enablement is for making PHY linked as slave mode easily.
disable slave seed if the master mode is preferred.
Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/phy/at803x.c | 25 ++++++++++++++++++++-----
1 file changed, 20 insertions(+), 5 deletions(-)
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -1745,6 +1745,12 @@ static int qca808x_phy_ms_seed_enable(st
QCA808X_MASTER_SLAVE_SEED_ENABLE);
}
+static bool qca808x_is_prefer_master(struct phy_device *phydev)
+{
+ return (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_FORCE) ||
+ (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_PREFERRED);
+}
+
static int qca808x_config_init(struct phy_device *phydev)
{
int ret;
@@ -1766,11 +1772,17 @@ static int qca808x_config_init(struct ph
if (ret)
return ret;
- /* Enable seed and configure lower ramdom seed to make phy linked as slave mode */
- ret = qca808x_phy_ms_seed_enable(phydev, true);
- if (ret)
+ ret = genphy_read_master_slave(phydev);
+ if (ret < 0)
return ret;
+ if (!qca808x_is_prefer_master(phydev)) {
+ /* Enable seed and configure lower ramdom seed to make phy linked as slave mode */
+ ret = qca808x_phy_ms_seed_enable(phydev, true);
+ if (ret)
+ return ret;
+ }
+
/* Configure adc threshold as 100mv for the link 10M */
return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_ADC_THRESHOLD,
QCA808X_ADC_THRESHOLD_MASK, QCA808X_ADC_THRESHOLD_100MV);
@@ -1802,13 +1814,16 @@ static int qca808x_read_status(struct ph
phydev->interface = PHY_INTERFACE_MODE_SGMII;
} else {
/* generate seed as a lower random value to make PHY linked as SLAVE easily,
- * except for master/slave configuration fault detected.
+ * except for master/slave configuration fault detected or the master mode
+ * preferred.
+ *
* the reason for not putting this code into the function link_change_notify is
* the corner case where the link partner is also the qca8081 PHY and the seed
* value is configured as the same value, the link can't be up and no link change
* occurs.
*/
- if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR) {
+ if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR ||
+ qca808x_is_prefer_master(phydev)) {
qca808x_phy_ms_seed_enable(phydev, false);
} else {
qca808x_phy_ms_seed_enable(phydev, true);
@@ -0,0 +1,48 @@
From fea7cfb83d1a2782e39cd101dd44ed2548539de5 Mon Sep 17 00:00:00 2001
From: Luo Jie <quic_luoj@quicinc.com>
Date: Sun, 16 Jul 2023 16:49:22 +0800
Subject: [PATCH 4/6] net: phy: at803x: support qca8081 1G chip type
The qca8081 1G chip version does not support 2.5 capability, which
is distinguished from qca8081 2.5G chip according to the bit0 of
register mmd7.0x901d, the 1G version chip also has the same PHY ID
as the normal qca8081 2.5G chip.
Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/phy/at803x.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -272,6 +272,10 @@
#define QCA808X_CDT_STATUS_STAT_OPEN 2
#define QCA808X_CDT_STATUS_STAT_SHORT 3
+/* QCA808X 1G chip type */
+#define QCA808X_PHY_MMD7_CHIP_TYPE 0x901d
+#define QCA808X_PHY_CHIP_TYPE_1G BIT(0)
+
MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver");
MODULE_AUTHOR("Matus Ujhelyi");
MODULE_LICENSE("GPL");
@@ -2005,6 +2009,17 @@ static int qca808x_get_features(struct p
*/
linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported);
+ /* As for the qca8081 1G version chip, the 2500baseT ability is also
+ * existed in the bit0 of MMD1.21, we need to remove it manually if
+ * it is the qca8081 1G chip according to the bit0 of MMD7.0x901d.
+ */
+ ret = phy_read_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_CHIP_TYPE);
+ if (ret < 0)
+ return ret;
+
+ if (QCA808X_PHY_CHIP_TYPE_1G & ret)
+ linkmode_clear_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported);
+
return 0;
}
@@ -0,0 +1,98 @@
From df9401ff3e6eeaa42bfb06761967f1b71f5afce7 Mon Sep 17 00:00:00 2001
From: Luo Jie <quic_luoj@quicinc.com>
Date: Sun, 16 Jul 2023 16:49:23 +0800
Subject: [PATCH 5/6] net: phy: at803x: remove qca8081 1G fast retrain and
slave seed config
The fast retrain and slave seed configs are only applicable when the 2.5G
ability is supported.
Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/phy/at803x.c | 50 +++++++++++++++++++++++++---------------
1 file changed, 32 insertions(+), 18 deletions(-)
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -1755,6 +1755,11 @@ static bool qca808x_is_prefer_master(str
(phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_PREFERRED);
}
+static bool qca808x_has_fast_retrain_or_slave_seed(struct phy_device *phydev)
+{
+ return linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported);
+}
+
static int qca808x_config_init(struct phy_device *phydev)
{
int ret;
@@ -1771,20 +1776,24 @@ static int qca808x_config_init(struct ph
if (ret)
return ret;
- /* Config the fast retrain for the link 2500M */
- ret = qca808x_phy_fast_retrain_config(phydev);
- if (ret)
- return ret;
-
- ret = genphy_read_master_slave(phydev);
- if (ret < 0)
- return ret;
-
- if (!qca808x_is_prefer_master(phydev)) {
- /* Enable seed and configure lower ramdom seed to make phy linked as slave mode */
- ret = qca808x_phy_ms_seed_enable(phydev, true);
+ if (qca808x_has_fast_retrain_or_slave_seed(phydev)) {
+ /* Config the fast retrain for the link 2500M */
+ ret = qca808x_phy_fast_retrain_config(phydev);
if (ret)
return ret;
+
+ ret = genphy_read_master_slave(phydev);
+ if (ret < 0)
+ return ret;
+
+ if (!qca808x_is_prefer_master(phydev)) {
+ /* Enable seed and configure lower ramdom seed to make phy
+ * linked as slave mode.
+ */
+ ret = qca808x_phy_ms_seed_enable(phydev, true);
+ if (ret)
+ return ret;
+ }
}
/* Configure adc threshold as 100mv for the link 10M */
@@ -1826,11 +1835,13 @@ static int qca808x_read_status(struct ph
* value is configured as the same value, the link can't be up and no link change
* occurs.
*/
- if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR ||
- qca808x_is_prefer_master(phydev)) {
- qca808x_phy_ms_seed_enable(phydev, false);
- } else {
- qca808x_phy_ms_seed_enable(phydev, true);
+ if (qca808x_has_fast_retrain_or_slave_seed(phydev)) {
+ if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR ||
+ qca808x_is_prefer_master(phydev)) {
+ qca808x_phy_ms_seed_enable(phydev, false);
+ } else {
+ qca808x_phy_ms_seed_enable(phydev, true);
+ }
}
}
@@ -1845,7 +1856,10 @@ static int qca808x_soft_reset(struct phy
if (ret < 0)
return ret;
- return qca808x_phy_ms_seed_enable(phydev, true);
+ if (qca808x_has_fast_retrain_or_slave_seed(phydev))
+ ret = qca808x_phy_ms_seed_enable(phydev, true);
+
+ return ret;
}
static bool qca808x_cdt_fault_length_valid(int cdt_code)
@@ -0,0 +1,55 @@
From 723970affdd8766fa0d91cd34bf2ffc861538b5f Mon Sep 17 00:00:00 2001
From: Luo Jie <quic_luoj@quicinc.com>
Date: Sun, 16 Jul 2023 16:49:24 +0800
Subject: [PATCH 6/6] net: phy: at803x: add qca8081 fifo reset on the link
changed
The qca8081 sgmii fifo needs to be reset on link down and
released on the link up in case of any abnormal issue
such as the packet blocked on the PHY.
Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/phy/at803x.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -276,6 +276,9 @@
#define QCA808X_PHY_MMD7_CHIP_TYPE 0x901d
#define QCA808X_PHY_CHIP_TYPE_1G BIT(0)
+#define QCA8081_PHY_SERDES_MMD1_FIFO_CTRL 0x9072
+#define QCA8081_PHY_FIFO_RSTN BIT(11)
+
MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver");
MODULE_AUTHOR("Matus Ujhelyi");
MODULE_LICENSE("GPL");
@@ -2037,6 +2040,16 @@ static int qca808x_get_features(struct p
return 0;
}
+static void qca808x_link_change_notify(struct phy_device *phydev)
+{
+ /* Assert interface sgmii fifo on link down, deassert it on link up,
+ * the interface device address is always phy address added by 1.
+ */
+ mdiobus_c45_modify_changed(phydev->mdio.bus, phydev->mdio.addr + 1,
+ MDIO_MMD_PMAPMD, QCA8081_PHY_SERDES_MMD1_FIFO_CTRL,
+ QCA8081_PHY_FIFO_RSTN, phydev->link ? QCA8081_PHY_FIFO_RSTN : 0);
+}
+
static struct phy_driver at803x_driver[] = {
{
/* Qualcomm Atheros AR8035 */
@@ -2213,6 +2226,7 @@ static struct phy_driver at803x_driver[]
.soft_reset = qca808x_soft_reset,
.cable_test_start = qca808x_cable_test_start,
.cable_test_get_status = qca808x_cable_test_get_status,
+ .link_change_notify = qca808x_link_change_notify,
}, };
module_phy_driver(at803x_driver);
@@ -0,0 +1,69 @@
From 6a3b8c573b5a152a6aa7a0b54c5e18b84c6ba6f5 Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Fri, 8 Dec 2023 15:51:49 +0100
Subject: [PATCH 02/13] net: phy: at803x: move disable WOL to specific at8031
probe
Move the WOL disable call to specific at8031 probe to make at803x_probe
more generic and drop extra check for PHY ID.
Keep the same previous behaviour by first calling at803x_probe and then
disabling WOL.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/phy/at803x.c | 27 +++++++++++++++++----------
1 file changed, 17 insertions(+), 10 deletions(-)
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -886,15 +886,6 @@ static int at803x_probe(struct phy_devic
priv->is_fiber = true;
break;
}
-
- /* Disable WoL in 1588 register which is enabled
- * by default
- */
- ret = phy_modify_mmd(phydev, MDIO_MMD_PCS,
- AT803X_PHY_MMD3_WOL_CTRL,
- AT803X_WOL_EN, 0);
- if (ret)
- return ret;
}
return 0;
@@ -1591,6 +1582,22 @@ static int at803x_cable_test_start(struc
return 0;
}
+static int at8031_probe(struct phy_device *phydev)
+{
+ int ret;
+
+ ret = at803x_probe(phydev);
+ if (ret)
+ return ret;
+
+ /* Disable WoL in 1588 register which is enabled
+ * by default
+ */
+ return phy_modify_mmd(phydev, MDIO_MMD_PCS,
+ AT803X_PHY_MMD3_WOL_CTRL,
+ AT803X_WOL_EN, 0);
+}
+
static int qca83xx_config_init(struct phy_device *phydev)
{
u8 switch_revision;
@@ -2092,7 +2099,7 @@ static struct phy_driver at803x_driver[]
PHY_ID_MATCH_EXACT(ATH8031_PHY_ID),
.name = "Qualcomm Atheros AR8031/AR8033",
.flags = PHY_POLL_CABLE_TEST,
- .probe = at803x_probe,
+ .probe = at8031_probe,
.config_init = at803x_config_init,
.config_aneg = at803x_config_aneg,
.soft_reset = genphy_soft_reset,
@@ -0,0 +1,129 @@
From 07b1ad83b9ed6db1735ba10baf67b7a565ac0cef Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Fri, 8 Dec 2023 15:51:50 +0100
Subject: [PATCH 03/13] net: phy: at803x: raname hw_stats functions to qca83xx
specific name
The function and the struct related to hw_stats were specific to qca83xx
PHY but were called following the convention in the driver of calling
everything with at803x prefix.
To better organize the code, rename these function a more specific name
to better describe that they are specific to 83xx PHY family.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/phy/at803x.c | 44 ++++++++++++++++++++--------------------
1 file changed, 22 insertions(+), 22 deletions(-)
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -295,7 +295,7 @@ struct at803x_hw_stat {
enum stat_access_type access_type;
};
-static struct at803x_hw_stat at803x_hw_stats[] = {
+static struct at803x_hw_stat qca83xx_hw_stats[] = {
{ "phy_idle_errors", 0xa, GENMASK(7, 0), PHY},
{ "phy_receive_errors", 0x15, GENMASK(15, 0), PHY},
{ "eee_wake_errors", 0x16, GENMASK(15, 0), MMD},
@@ -311,7 +311,7 @@ struct at803x_priv {
bool is_1000basex;
struct regulator_dev *vddio_rdev;
struct regulator_dev *vddh_rdev;
- u64 stats[ARRAY_SIZE(at803x_hw_stats)];
+ u64 stats[ARRAY_SIZE(qca83xx_hw_stats)];
};
struct at803x_context {
@@ -529,24 +529,24 @@ static void at803x_get_wol(struct phy_de
wol->wolopts |= WAKE_MAGIC;
}
-static int at803x_get_sset_count(struct phy_device *phydev)
+static int qca83xx_get_sset_count(struct phy_device *phydev)
{
- return ARRAY_SIZE(at803x_hw_stats);
+ return ARRAY_SIZE(qca83xx_hw_stats);
}
-static void at803x_get_strings(struct phy_device *phydev, u8 *data)
+static void qca83xx_get_strings(struct phy_device *phydev, u8 *data)
{
int i;
- for (i = 0; i < ARRAY_SIZE(at803x_hw_stats); i++) {
+ for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++) {
strscpy(data + i * ETH_GSTRING_LEN,
- at803x_hw_stats[i].string, ETH_GSTRING_LEN);
+ qca83xx_hw_stats[i].string, ETH_GSTRING_LEN);
}
}
-static u64 at803x_get_stat(struct phy_device *phydev, int i)
+static u64 qca83xx_get_stat(struct phy_device *phydev, int i)
{
- struct at803x_hw_stat stat = at803x_hw_stats[i];
+ struct at803x_hw_stat stat = qca83xx_hw_stats[i];
struct at803x_priv *priv = phydev->priv;
int val;
u64 ret;
@@ -567,13 +567,13 @@ static u64 at803x_get_stat(struct phy_de
return ret;
}
-static void at803x_get_stats(struct phy_device *phydev,
- struct ethtool_stats *stats, u64 *data)
+static void qca83xx_get_stats(struct phy_device *phydev,
+ struct ethtool_stats *stats, u64 *data)
{
int i;
- for (i = 0; i < ARRAY_SIZE(at803x_hw_stats); i++)
- data[i] = at803x_get_stat(phydev, i);
+ for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++)
+ data[i] = qca83xx_get_stat(phydev, i);
}
static int at803x_suspend(struct phy_device *phydev)
@@ -2175,9 +2175,9 @@ static struct phy_driver at803x_driver[]
.flags = PHY_IS_INTERNAL,
.config_init = qca83xx_config_init,
.soft_reset = genphy_soft_reset,
- .get_sset_count = at803x_get_sset_count,
- .get_strings = at803x_get_strings,
- .get_stats = at803x_get_stats,
+ .get_sset_count = qca83xx_get_sset_count,
+ .get_strings = qca83xx_get_strings,
+ .get_stats = qca83xx_get_stats,
.suspend = qca83xx_suspend,
.resume = qca83xx_resume,
}, {
@@ -2191,9 +2191,9 @@ static struct phy_driver at803x_driver[]
.flags = PHY_IS_INTERNAL,
.config_init = qca83xx_config_init,
.soft_reset = genphy_soft_reset,
- .get_sset_count = at803x_get_sset_count,
- .get_strings = at803x_get_strings,
- .get_stats = at803x_get_stats,
+ .get_sset_count = qca83xx_get_sset_count,
+ .get_strings = qca83xx_get_strings,
+ .get_stats = qca83xx_get_stats,
.suspend = qca83xx_suspend,
.resume = qca83xx_resume,
}, {
@@ -2207,9 +2207,9 @@ static struct phy_driver at803x_driver[]
.flags = PHY_IS_INTERNAL,
.config_init = qca83xx_config_init,
.soft_reset = genphy_soft_reset,
- .get_sset_count = at803x_get_sset_count,
- .get_strings = at803x_get_strings,
- .get_stats = at803x_get_stats,
+ .get_sset_count = qca83xx_get_sset_count,
+ .get_strings = qca83xx_get_strings,
+ .get_stats = qca83xx_get_stats,
.suspend = qca83xx_suspend,
.resume = qca83xx_resume,
}, {
@@ -0,0 +1,155 @@
From d43cff3f82336c0bd965ea552232d9f4ddac71a6 Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Fri, 8 Dec 2023 15:51:51 +0100
Subject: [PATCH 04/13] net: phy: at803x: move qca83xx specific check in
dedicated functions
Rework qca83xx specific check to dedicated function to tidy things up
and drop useless phy_id check.
Also drop an useless link_change_notify for QCA8337 as it did nothing an
returned early.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/phy/at803x.c | 68 ++++++++++++++++++++++------------------
1 file changed, 37 insertions(+), 31 deletions(-)
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -1623,27 +1623,26 @@ static int qca83xx_config_init(struct ph
break;
}
+ /* Following original QCA sourcecode set port to prefer master */
+ phy_set_bits(phydev, MII_CTRL1000, CTL1000_PREFER_MASTER);
+
+ return 0;
+}
+
+static int qca8327_config_init(struct phy_device *phydev)
+{
/* QCA8327 require DAC amplitude adjustment for 100m set to +6%.
* Disable on init and enable only with 100m speed following
* qca original source code.
*/
- if (phydev->drv->phy_id == QCA8327_A_PHY_ID ||
- phydev->drv->phy_id == QCA8327_B_PHY_ID)
- at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL,
- QCA8327_DEBUG_MANU_CTRL_EN, 0);
+ at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL,
+ QCA8327_DEBUG_MANU_CTRL_EN, 0);
- /* Following original QCA sourcecode set port to prefer master */
- phy_set_bits(phydev, MII_CTRL1000, CTL1000_PREFER_MASTER);
-
- return 0;
+ return qca83xx_config_init(phydev);
}
static void qca83xx_link_change_notify(struct phy_device *phydev)
{
- /* QCA8337 doesn't require DAC Amplitude adjustement */
- if (phydev->drv->phy_id == QCA8337_PHY_ID)
- return;
-
/* Set DAC Amplitude adjustment to +6% for 100m on link running */
if (phydev->state == PHY_RUNNING) {
if (phydev->speed == SPEED_100)
@@ -1686,19 +1685,6 @@ static int qca83xx_resume(struct phy_dev
static int qca83xx_suspend(struct phy_device *phydev)
{
- u16 mask = 0;
-
- /* Only QCA8337 support actual suspend.
- * QCA8327 cause port unreliability when phy suspend
- * is set.
- */
- if (phydev->drv->phy_id == QCA8337_PHY_ID) {
- genphy_suspend(phydev);
- } else {
- mask |= ~(BMCR_SPEED1000 | BMCR_FULLDPLX);
- phy_modify(phydev, MII_BMCR, mask, 0);
- }
-
at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_GREEN,
AT803X_DEBUG_GATE_CLK_IN1000, 0);
@@ -1709,6 +1695,27 @@ static int qca83xx_suspend(struct phy_de
return 0;
}
+static int qca8337_suspend(struct phy_device *phydev)
+{
+ /* Only QCA8337 support actual suspend. */
+ genphy_suspend(phydev);
+
+ return qca83xx_suspend(phydev);
+}
+
+static int qca8327_suspend(struct phy_device *phydev)
+{
+ u16 mask = 0;
+
+ /* QCA8327 cause port unreliability when phy suspend
+ * is set.
+ */
+ mask |= ~(BMCR_SPEED1000 | BMCR_FULLDPLX);
+ phy_modify(phydev, MII_BMCR, mask, 0);
+
+ return qca83xx_suspend(phydev);
+}
+
static int qca808x_phy_fast_retrain_config(struct phy_device *phydev)
{
int ret;
@@ -2170,7 +2177,6 @@ static struct phy_driver at803x_driver[]
.phy_id_mask = QCA8K_PHY_ID_MASK,
.name = "Qualcomm Atheros 8337 internal PHY",
/* PHY_GBIT_FEATURES */
- .link_change_notify = qca83xx_link_change_notify,
.probe = at803x_probe,
.flags = PHY_IS_INTERNAL,
.config_init = qca83xx_config_init,
@@ -2178,7 +2184,7 @@ static struct phy_driver at803x_driver[]
.get_sset_count = qca83xx_get_sset_count,
.get_strings = qca83xx_get_strings,
.get_stats = qca83xx_get_stats,
- .suspend = qca83xx_suspend,
+ .suspend = qca8337_suspend,
.resume = qca83xx_resume,
}, {
/* QCA8327-A from switch QCA8327-AL1A */
@@ -2189,12 +2195,12 @@ static struct phy_driver at803x_driver[]
.link_change_notify = qca83xx_link_change_notify,
.probe = at803x_probe,
.flags = PHY_IS_INTERNAL,
- .config_init = qca83xx_config_init,
+ .config_init = qca8327_config_init,
.soft_reset = genphy_soft_reset,
.get_sset_count = qca83xx_get_sset_count,
.get_strings = qca83xx_get_strings,
.get_stats = qca83xx_get_stats,
- .suspend = qca83xx_suspend,
+ .suspend = qca8327_suspend,
.resume = qca83xx_resume,
}, {
/* QCA8327-B from switch QCA8327-BL1A */
@@ -2205,12 +2211,12 @@ static struct phy_driver at803x_driver[]
.link_change_notify = qca83xx_link_change_notify,
.probe = at803x_probe,
.flags = PHY_IS_INTERNAL,
- .config_init = qca83xx_config_init,
+ .config_init = qca8327_config_init,
.soft_reset = genphy_soft_reset,
.get_sset_count = qca83xx_get_sset_count,
.get_strings = qca83xx_get_strings,
.get_stats = qca83xx_get_stats,
- .suspend = qca83xx_suspend,
+ .suspend = qca8327_suspend,
.resume = qca83xx_resume,
}, {
/* Qualcomm QCA8081 */
@@ -0,0 +1,94 @@
From 900eef75cc5018e149c52fe305c9c3fe424c52a7 Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Fri, 8 Dec 2023 15:51:52 +0100
Subject: [PATCH 05/13] net: phy: at803x: move specific DT option for at8031 to
specific probe
Move specific DT options for at8031 to specific probe to tidy things up
and make at803x_parse_dt more generic.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/phy/at803x.c | 55 ++++++++++++++++++++++------------------
1 file changed, 31 insertions(+), 24 deletions(-)
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -825,30 +825,6 @@ static int at803x_parse_dt(struct phy_de
}
}
- /* Only supported on AR8031/AR8033, the AR8030/AR8035 use strapping
- * options.
- */
- if (phydev->drv->phy_id == ATH8031_PHY_ID) {
- if (of_property_read_bool(node, "qca,keep-pll-enabled"))
- priv->flags |= AT803X_KEEP_PLL_ENABLED;
-
- ret = at8031_register_regulators(phydev);
- if (ret < 0)
- return ret;
-
- ret = devm_regulator_get_enable_optional(&phydev->mdio.dev,
- "vddio");
- if (ret) {
- phydev_err(phydev, "failed to get VDDIO regulator\n");
- return ret;
- }
-
- /* Only AR8031/8033 support 1000Base-X for SFP modules */
- ret = phy_sfp_probe(phydev, &at803x_sfp_ops);
- if (ret < 0)
- return ret;
- }
-
return 0;
}
@@ -1582,6 +1558,30 @@ static int at803x_cable_test_start(struc
return 0;
}
+static int at8031_parse_dt(struct phy_device *phydev)
+{
+ struct device_node *node = phydev->mdio.dev.of_node;
+ struct at803x_priv *priv = phydev->priv;
+ int ret;
+
+ if (of_property_read_bool(node, "qca,keep-pll-enabled"))
+ priv->flags |= AT803X_KEEP_PLL_ENABLED;
+
+ ret = at8031_register_regulators(phydev);
+ if (ret < 0)
+ return ret;
+
+ ret = devm_regulator_get_enable_optional(&phydev->mdio.dev,
+ "vddio");
+ if (ret) {
+ phydev_err(phydev, "failed to get VDDIO regulator\n");
+ return ret;
+ }
+
+ /* Only AR8031/8033 support 1000Base-X for SFP modules */
+ return phy_sfp_probe(phydev, &at803x_sfp_ops);
+}
+
static int at8031_probe(struct phy_device *phydev)
{
int ret;
@@ -1590,6 +1590,13 @@ static int at8031_probe(struct phy_devic
if (ret)
return ret;
+ /* Only supported on AR8031/AR8033, the AR8030/AR8035 use strapping
+ * options.
+ */
+ ret = at8031_parse_dt(phydev);
+ if (ret)
+ return ret;
+
/* Disable WoL in 1588 register which is enabled
* by default
*/
@@ -0,0 +1,78 @@
From 25d2ba94005fac18fe68878cddff59a67e115554 Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Fri, 8 Dec 2023 15:51:53 +0100
Subject: [PATCH 06/13] net: phy: at803x: move specific at8031 probe mode check
to dedicated probe
Move specific at8031 probe mode check to dedicated probe to make
at803x_probe more generic and keep code tidy.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/phy/at803x.c | 39 +++++++++++++++++++--------------------
1 file changed, 19 insertions(+), 20 deletions(-)
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -844,26 +844,6 @@ static int at803x_probe(struct phy_devic
if (ret)
return ret;
- if (phydev->drv->phy_id == ATH8031_PHY_ID) {
- int ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG);
- int mode_cfg;
-
- if (ccr < 0)
- return ccr;
- mode_cfg = ccr & AT803X_MODE_CFG_MASK;
-
- switch (mode_cfg) {
- case AT803X_MODE_CFG_BX1000_RGMII_50OHM:
- case AT803X_MODE_CFG_BX1000_RGMII_75OHM:
- priv->is_1000basex = true;
- fallthrough;
- case AT803X_MODE_CFG_FX100_RGMII_50OHM:
- case AT803X_MODE_CFG_FX100_RGMII_75OHM:
- priv->is_fiber = true;
- break;
- }
- }
-
return 0;
}
@@ -1584,6 +1564,9 @@ static int at8031_parse_dt(struct phy_de
static int at8031_probe(struct phy_device *phydev)
{
+ struct at803x_priv *priv = phydev->priv;
+ int mode_cfg;
+ int ccr;
int ret;
ret = at803x_probe(phydev);
@@ -1597,6 +1580,22 @@ static int at8031_probe(struct phy_devic
if (ret)
return ret;
+ ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG);
+ if (ccr < 0)
+ return ccr;
+ mode_cfg = ccr & AT803X_MODE_CFG_MASK;
+
+ switch (mode_cfg) {
+ case AT803X_MODE_CFG_BX1000_RGMII_50OHM:
+ case AT803X_MODE_CFG_BX1000_RGMII_75OHM:
+ priv->is_1000basex = true;
+ fallthrough;
+ case AT803X_MODE_CFG_FX100_RGMII_50OHM:
+ case AT803X_MODE_CFG_FX100_RGMII_75OHM:
+ priv->is_fiber = true;
+ break;
+ }
+
/* Disable WoL in 1588 register which is enabled
* by default
*/
@@ -0,0 +1,86 @@
From 3ae3bc426eaf57ca8f53d75777d9a5ef779bc7b7 Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Fri, 8 Dec 2023 15:51:54 +0100
Subject: [PATCH 07/13] net: phy: at803x: move specific at8031 config_init to
dedicated function
Move specific at8031 config_init to dedicated function to make
at803x_config_init more generic and tidy things up.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/phy/at803x.c | 45 ++++++++++++++++++++++------------------
1 file changed, 25 insertions(+), 20 deletions(-)
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -951,27 +951,8 @@ static int at803x_hibernation_mode_confi
static int at803x_config_init(struct phy_device *phydev)
{
- struct at803x_priv *priv = phydev->priv;
int ret;
- if (phydev->drv->phy_id == ATH8031_PHY_ID) {
- /* Some bootloaders leave the fiber page selected.
- * Switch to the appropriate page (fiber or copper), as otherwise we
- * read the PHY capabilities from the wrong page.
- */
- phy_lock_mdio_bus(phydev);
- ret = at803x_write_page(phydev,
- priv->is_fiber ? AT803X_PAGE_FIBER :
- AT803X_PAGE_COPPER);
- phy_unlock_mdio_bus(phydev);
- if (ret)
- return ret;
-
- ret = at8031_pll_config(phydev);
- if (ret < 0)
- return ret;
- }
-
/* The RX and TX delay default is:
* after HW reset: RX delay enabled and TX delay disabled
* after SW reset: RX delay enabled, while TX delay retains the
@@ -1604,6 +1585,30 @@ static int at8031_probe(struct phy_devic
AT803X_WOL_EN, 0);
}
+static int at8031_config_init(struct phy_device *phydev)
+{
+ struct at803x_priv *priv = phydev->priv;
+ int ret;
+
+ /* Some bootloaders leave the fiber page selected.
+ * Switch to the appropriate page (fiber or copper), as otherwise we
+ * read the PHY capabilities from the wrong page.
+ */
+ phy_lock_mdio_bus(phydev);
+ ret = at803x_write_page(phydev,
+ priv->is_fiber ? AT803X_PAGE_FIBER :
+ AT803X_PAGE_COPPER);
+ phy_unlock_mdio_bus(phydev);
+ if (ret)
+ return ret;
+
+ ret = at8031_pll_config(phydev);
+ if (ret < 0)
+ return ret;
+
+ return at803x_config_init(phydev);
+}
+
static int qca83xx_config_init(struct phy_device *phydev)
{
u8 switch_revision;
@@ -2113,7 +2118,7 @@ static struct phy_driver at803x_driver[]
.name = "Qualcomm Atheros AR8031/AR8033",
.flags = PHY_POLL_CABLE_TEST,
.probe = at8031_probe,
- .config_init = at803x_config_init,
+ .config_init = at8031_config_init,
.config_aneg = at803x_config_aneg,
.soft_reset = genphy_soft_reset,
.set_wol = at803x_set_wol,
@@ -0,0 +1,92 @@
From 27b89c9dc1b0393090d68d651b82f30ad2696baa Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Fri, 8 Dec 2023 15:51:55 +0100
Subject: [PATCH 08/13] net: phy: at803x: move specific at8031 WOL bits to
dedicated function
Move specific at8031 WOL enable/disable to dedicated function to make
at803x_set_wol more generic.
This is needed in preparation for PHY driver split as qca8081 share the
same function to toggle WOL settings.
In this new implementation WOL module in at8031 is enabled after the
generic interrupt is setup. This should not cause any problem as the
WOL_INT has a separate implementation and only relay on MAC bits.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/phy/at803x.c | 42 ++++++++++++++++++++++++----------------
1 file changed, 25 insertions(+), 17 deletions(-)
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -466,27 +466,11 @@ static int at803x_set_wol(struct phy_dev
phy_write_mmd(phydev, MDIO_MMD_PCS, offsets[i],
mac[(i * 2) + 1] | (mac[(i * 2)] << 8));
- /* Enable WOL function for 1588 */
- if (phydev->drv->phy_id == ATH8031_PHY_ID) {
- ret = phy_modify_mmd(phydev, MDIO_MMD_PCS,
- AT803X_PHY_MMD3_WOL_CTRL,
- 0, AT803X_WOL_EN);
- if (ret)
- return ret;
- }
/* Enable WOL interrupt */
ret = phy_modify(phydev, AT803X_INTR_ENABLE, 0, AT803X_INTR_ENABLE_WOL);
if (ret)
return ret;
} else {
- /* Disable WoL function for 1588 */
- if (phydev->drv->phy_id == ATH8031_PHY_ID) {
- ret = phy_modify_mmd(phydev, MDIO_MMD_PCS,
- AT803X_PHY_MMD3_WOL_CTRL,
- AT803X_WOL_EN, 0);
- if (ret)
- return ret;
- }
/* Disable WOL interrupt */
ret = phy_modify(phydev, AT803X_INTR_ENABLE, AT803X_INTR_ENABLE_WOL, 0);
if (ret)
@@ -1609,6 +1593,30 @@ static int at8031_config_init(struct phy
return at803x_config_init(phydev);
}
+static int at8031_set_wol(struct phy_device *phydev,
+ struct ethtool_wolinfo *wol)
+{
+ int ret;
+
+ /* First setup MAC address and enable WOL interrupt */
+ ret = at803x_set_wol(phydev, wol);
+ if (ret)
+ return ret;
+
+ if (wol->wolopts & WAKE_MAGIC)
+ /* Enable WOL function for 1588 */
+ ret = phy_modify_mmd(phydev, MDIO_MMD_PCS,
+ AT803X_PHY_MMD3_WOL_CTRL,
+ 0, AT803X_WOL_EN);
+ else
+ /* Disable WoL function for 1588 */
+ ret = phy_modify_mmd(phydev, MDIO_MMD_PCS,
+ AT803X_PHY_MMD3_WOL_CTRL,
+ AT803X_WOL_EN, 0);
+
+ return ret;
+}
+
static int qca83xx_config_init(struct phy_device *phydev)
{
u8 switch_revision;
@@ -2121,7 +2129,7 @@ static struct phy_driver at803x_driver[]
.config_init = at8031_config_init,
.config_aneg = at803x_config_aneg,
.soft_reset = genphy_soft_reset,
- .set_wol = at803x_set_wol,
+ .set_wol = at8031_set_wol,
.get_wol = at803x_get_wol,
.suspend = at803x_suspend,
.resume = at803x_resume,
@@ -0,0 +1,78 @@
From 30dd62191d3dd97c08f7f9dc9ce77ffab457e4fb Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Fri, 8 Dec 2023 15:51:56 +0100
Subject: [PATCH 09/13] net: phy: at803x: move specific at8031 config_intr to
dedicated function
Move specific at8031 config_intr bits to dedicated function to make
at803x_config_initr more generic.
This is needed in preparation for PHY driver split as qca8081 share the
same function to setup interrupts.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/phy/at803x.c | 30 ++++++++++++++++++++++++------
1 file changed, 24 insertions(+), 6 deletions(-)
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -990,7 +990,6 @@ static int at803x_ack_interrupt(struct p
static int at803x_config_intr(struct phy_device *phydev)
{
- struct at803x_priv *priv = phydev->priv;
int err;
int value;
@@ -1007,10 +1006,6 @@ static int at803x_config_intr(struct phy
value |= AT803X_INTR_ENABLE_DUPLEX_CHANGED;
value |= AT803X_INTR_ENABLE_LINK_FAIL;
value |= AT803X_INTR_ENABLE_LINK_SUCCESS;
- if (priv->is_fiber) {
- value |= AT803X_INTR_ENABLE_LINK_FAIL_BX;
- value |= AT803X_INTR_ENABLE_LINK_SUCCESS_BX;
- }
err = phy_write(phydev, AT803X_INTR_ENABLE, value);
} else {
@@ -1617,6 +1612,29 @@ static int at8031_set_wol(struct phy_dev
return ret;
}
+static int at8031_config_intr(struct phy_device *phydev)
+{
+ struct at803x_priv *priv = phydev->priv;
+ int err, value = 0;
+
+ if (phydev->interrupts == PHY_INTERRUPT_ENABLED &&
+ priv->is_fiber) {
+ /* Clear any pending interrupts */
+ err = at803x_ack_interrupt(phydev);
+ if (err)
+ return err;
+
+ value |= AT803X_INTR_ENABLE_LINK_FAIL_BX;
+ value |= AT803X_INTR_ENABLE_LINK_SUCCESS_BX;
+
+ err = phy_set_bits(phydev, AT803X_INTR_ENABLE, value);
+ if (err)
+ return err;
+ }
+
+ return at803x_config_intr(phydev);
+}
+
static int qca83xx_config_init(struct phy_device *phydev)
{
u8 switch_revision;
@@ -2137,7 +2155,7 @@ static struct phy_driver at803x_driver[]
.write_page = at803x_write_page,
.get_features = at803x_get_features,
.read_status = at803x_read_status,
- .config_intr = at803x_config_intr,
+ .config_intr = at8031_config_intr,
.handle_interrupt = at803x_handle_interrupt,
.get_tunable = at803x_get_tunable,
.set_tunable = at803x_set_tunable,
@@ -0,0 +1,78 @@
From a5ab9d8e7ae0da8328ac1637a9755311508dc8ab Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Fri, 8 Dec 2023 15:51:57 +0100
Subject: [PATCH 10/13] net: phy: at803x: make at8031 related DT functions name
more specific
Rename at8031 related DT function name to a more specific name
referencing they are only related to at8031 and not to the generic
at803x PHY family.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/phy/at803x.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -583,7 +583,7 @@ static int at803x_resume(struct phy_devi
return phy_modify(phydev, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE, 0);
}
-static int at803x_rgmii_reg_set_voltage_sel(struct regulator_dev *rdev,
+static int at8031_rgmii_reg_set_voltage_sel(struct regulator_dev *rdev,
unsigned int selector)
{
struct phy_device *phydev = rdev_get_drvdata(rdev);
@@ -596,7 +596,7 @@ static int at803x_rgmii_reg_set_voltage_
AT803X_DEBUG_RGMII_1V8, 0);
}
-static int at803x_rgmii_reg_get_voltage_sel(struct regulator_dev *rdev)
+static int at8031_rgmii_reg_get_voltage_sel(struct regulator_dev *rdev)
{
struct phy_device *phydev = rdev_get_drvdata(rdev);
int val;
@@ -610,8 +610,8 @@ static int at803x_rgmii_reg_get_voltage_
static const struct regulator_ops vddio_regulator_ops = {
.list_voltage = regulator_list_voltage_table,
- .set_voltage_sel = at803x_rgmii_reg_set_voltage_sel,
- .get_voltage_sel = at803x_rgmii_reg_get_voltage_sel,
+ .set_voltage_sel = at8031_rgmii_reg_set_voltage_sel,
+ .get_voltage_sel = at8031_rgmii_reg_get_voltage_sel,
};
static const unsigned int vddio_voltage_table[] = {
@@ -666,7 +666,7 @@ static int at8031_register_regulators(st
return 0;
}
-static int at803x_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
+static int at8031_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
{
struct phy_device *phydev = upstream;
__ETHTOOL_DECLARE_LINK_MODE_MASK(phy_support);
@@ -710,10 +710,10 @@ static int at803x_sfp_insert(void *upstr
return 0;
}
-static const struct sfp_upstream_ops at803x_sfp_ops = {
+static const struct sfp_upstream_ops at8031_sfp_ops = {
.attach = phy_sfp_attach,
.detach = phy_sfp_detach,
- .module_insert = at803x_sfp_insert,
+ .module_insert = at8031_sfp_insert,
};
static int at803x_parse_dt(struct phy_device *phydev)
@@ -1519,7 +1519,7 @@ static int at8031_parse_dt(struct phy_de
}
/* Only AR8031/8033 support 1000Base-X for SFP modules */
- return phy_sfp_probe(phydev, &at803x_sfp_ops);
+ return phy_sfp_probe(phydev, &at8031_sfp_ops);
}
static int at8031_probe(struct phy_device *phydev)
@@ -0,0 +1,297 @@
From f932a6dc8bae0dae9645b5b1b4c65aed8a8acb2a Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Fri, 8 Dec 2023 15:51:58 +0100
Subject: [PATCH 11/13] net: phy: at803x: move at8031 functions in dedicated
section
Move at8031 functions in dedicated section with dedicated at8031
parse_dt and probe.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/phy/at803x.c | 266 +++++++++++++++++++--------------------
1 file changed, 133 insertions(+), 133 deletions(-)
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -583,139 +583,6 @@ static int at803x_resume(struct phy_devi
return phy_modify(phydev, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE, 0);
}
-static int at8031_rgmii_reg_set_voltage_sel(struct regulator_dev *rdev,
- unsigned int selector)
-{
- struct phy_device *phydev = rdev_get_drvdata(rdev);
-
- if (selector)
- return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F,
- 0, AT803X_DEBUG_RGMII_1V8);
- else
- return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F,
- AT803X_DEBUG_RGMII_1V8, 0);
-}
-
-static int at8031_rgmii_reg_get_voltage_sel(struct regulator_dev *rdev)
-{
- struct phy_device *phydev = rdev_get_drvdata(rdev);
- int val;
-
- val = at803x_debug_reg_read(phydev, AT803X_DEBUG_REG_1F);
- if (val < 0)
- return val;
-
- return (val & AT803X_DEBUG_RGMII_1V8) ? 1 : 0;
-}
-
-static const struct regulator_ops vddio_regulator_ops = {
- .list_voltage = regulator_list_voltage_table,
- .set_voltage_sel = at8031_rgmii_reg_set_voltage_sel,
- .get_voltage_sel = at8031_rgmii_reg_get_voltage_sel,
-};
-
-static const unsigned int vddio_voltage_table[] = {
- 1500000,
- 1800000,
-};
-
-static const struct regulator_desc vddio_desc = {
- .name = "vddio",
- .of_match = of_match_ptr("vddio-regulator"),
- .n_voltages = ARRAY_SIZE(vddio_voltage_table),
- .volt_table = vddio_voltage_table,
- .ops = &vddio_regulator_ops,
- .type = REGULATOR_VOLTAGE,
- .owner = THIS_MODULE,
-};
-
-static const struct regulator_ops vddh_regulator_ops = {
-};
-
-static const struct regulator_desc vddh_desc = {
- .name = "vddh",
- .of_match = of_match_ptr("vddh-regulator"),
- .n_voltages = 1,
- .fixed_uV = 2500000,
- .ops = &vddh_regulator_ops,
- .type = REGULATOR_VOLTAGE,
- .owner = THIS_MODULE,
-};
-
-static int at8031_register_regulators(struct phy_device *phydev)
-{
- struct at803x_priv *priv = phydev->priv;
- struct device *dev = &phydev->mdio.dev;
- struct regulator_config config = { };
-
- config.dev = dev;
- config.driver_data = phydev;
-
- priv->vddio_rdev = devm_regulator_register(dev, &vddio_desc, &config);
- if (IS_ERR(priv->vddio_rdev)) {
- phydev_err(phydev, "failed to register VDDIO regulator\n");
- return PTR_ERR(priv->vddio_rdev);
- }
-
- priv->vddh_rdev = devm_regulator_register(dev, &vddh_desc, &config);
- if (IS_ERR(priv->vddh_rdev)) {
- phydev_err(phydev, "failed to register VDDH regulator\n");
- return PTR_ERR(priv->vddh_rdev);
- }
-
- return 0;
-}
-
-static int at8031_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
-{
- struct phy_device *phydev = upstream;
- __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_support);
- __ETHTOOL_DECLARE_LINK_MODE_MASK(sfp_support);
- DECLARE_PHY_INTERFACE_MASK(interfaces);
- phy_interface_t iface;
-
- linkmode_zero(phy_support);
- phylink_set(phy_support, 1000baseX_Full);
- phylink_set(phy_support, 1000baseT_Full);
- phylink_set(phy_support, Autoneg);
- phylink_set(phy_support, Pause);
- phylink_set(phy_support, Asym_Pause);
-
- linkmode_zero(sfp_support);
- sfp_parse_support(phydev->sfp_bus, id, sfp_support, interfaces);
- /* Some modules support 10G modes as well as others we support.
- * Mask out non-supported modes so the correct interface is picked.
- */
- linkmode_and(sfp_support, phy_support, sfp_support);
-
- if (linkmode_empty(sfp_support)) {
- dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n");
- return -EINVAL;
- }
-
- iface = sfp_select_interface(phydev->sfp_bus, sfp_support);
-
- /* Only 1000Base-X is supported by AR8031/8033 as the downstream SerDes
- * interface for use with SFP modules.
- * However, some copper modules detected as having a preferred SGMII
- * interface do default to and function in 1000Base-X mode, so just
- * print a warning and allow such modules, as they may have some chance
- * of working.
- */
- if (iface == PHY_INTERFACE_MODE_SGMII)
- dev_warn(&phydev->mdio.dev, "module may not function if 1000Base-X not supported\n");
- else if (iface != PHY_INTERFACE_MODE_1000BASEX)
- return -EINVAL;
-
- return 0;
-}
-
-static const struct sfp_upstream_ops at8031_sfp_ops = {
- .attach = phy_sfp_attach,
- .detach = phy_sfp_detach,
- .module_insert = at8031_sfp_insert,
-};
-
static int at803x_parse_dt(struct phy_device *phydev)
{
struct device_node *node = phydev->mdio.dev.of_node;
@@ -1498,6 +1365,139 @@ static int at803x_cable_test_start(struc
return 0;
}
+static int at8031_rgmii_reg_set_voltage_sel(struct regulator_dev *rdev,
+ unsigned int selector)
+{
+ struct phy_device *phydev = rdev_get_drvdata(rdev);
+
+ if (selector)
+ return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F,
+ 0, AT803X_DEBUG_RGMII_1V8);
+ else
+ return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F,
+ AT803X_DEBUG_RGMII_1V8, 0);
+}
+
+static int at8031_rgmii_reg_get_voltage_sel(struct regulator_dev *rdev)
+{
+ struct phy_device *phydev = rdev_get_drvdata(rdev);
+ int val;
+
+ val = at803x_debug_reg_read(phydev, AT803X_DEBUG_REG_1F);
+ if (val < 0)
+ return val;
+
+ return (val & AT803X_DEBUG_RGMII_1V8) ? 1 : 0;
+}
+
+static const struct regulator_ops vddio_regulator_ops = {
+ .list_voltage = regulator_list_voltage_table,
+ .set_voltage_sel = at8031_rgmii_reg_set_voltage_sel,
+ .get_voltage_sel = at8031_rgmii_reg_get_voltage_sel,
+};
+
+static const unsigned int vddio_voltage_table[] = {
+ 1500000,
+ 1800000,
+};
+
+static const struct regulator_desc vddio_desc = {
+ .name = "vddio",
+ .of_match = of_match_ptr("vddio-regulator"),
+ .n_voltages = ARRAY_SIZE(vddio_voltage_table),
+ .volt_table = vddio_voltage_table,
+ .ops = &vddio_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+};
+
+static const struct regulator_ops vddh_regulator_ops = {
+};
+
+static const struct regulator_desc vddh_desc = {
+ .name = "vddh",
+ .of_match = of_match_ptr("vddh-regulator"),
+ .n_voltages = 1,
+ .fixed_uV = 2500000,
+ .ops = &vddh_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+};
+
+static int at8031_register_regulators(struct phy_device *phydev)
+{
+ struct at803x_priv *priv = phydev->priv;
+ struct device *dev = &phydev->mdio.dev;
+ struct regulator_config config = { };
+
+ config.dev = dev;
+ config.driver_data = phydev;
+
+ priv->vddio_rdev = devm_regulator_register(dev, &vddio_desc, &config);
+ if (IS_ERR(priv->vddio_rdev)) {
+ phydev_err(phydev, "failed to register VDDIO regulator\n");
+ return PTR_ERR(priv->vddio_rdev);
+ }
+
+ priv->vddh_rdev = devm_regulator_register(dev, &vddh_desc, &config);
+ if (IS_ERR(priv->vddh_rdev)) {
+ phydev_err(phydev, "failed to register VDDH regulator\n");
+ return PTR_ERR(priv->vddh_rdev);
+ }
+
+ return 0;
+}
+
+static int at8031_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
+{
+ struct phy_device *phydev = upstream;
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_support);
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(sfp_support);
+ DECLARE_PHY_INTERFACE_MASK(interfaces);
+ phy_interface_t iface;
+
+ linkmode_zero(phy_support);
+ phylink_set(phy_support, 1000baseX_Full);
+ phylink_set(phy_support, 1000baseT_Full);
+ phylink_set(phy_support, Autoneg);
+ phylink_set(phy_support, Pause);
+ phylink_set(phy_support, Asym_Pause);
+
+ linkmode_zero(sfp_support);
+ sfp_parse_support(phydev->sfp_bus, id, sfp_support, interfaces);
+ /* Some modules support 10G modes as well as others we support.
+ * Mask out non-supported modes so the correct interface is picked.
+ */
+ linkmode_and(sfp_support, phy_support, sfp_support);
+
+ if (linkmode_empty(sfp_support)) {
+ dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n");
+ return -EINVAL;
+ }
+
+ iface = sfp_select_interface(phydev->sfp_bus, sfp_support);
+
+ /* Only 1000Base-X is supported by AR8031/8033 as the downstream SerDes
+ * interface for use with SFP modules.
+ * However, some copper modules detected as having a preferred SGMII
+ * interface do default to and function in 1000Base-X mode, so just
+ * print a warning and allow such modules, as they may have some chance
+ * of working.
+ */
+ if (iface == PHY_INTERFACE_MODE_SGMII)
+ dev_warn(&phydev->mdio.dev, "module may not function if 1000Base-X not supported\n");
+ else if (iface != PHY_INTERFACE_MODE_1000BASEX)
+ return -EINVAL;
+
+ return 0;
+}
+
+static const struct sfp_upstream_ops at8031_sfp_ops = {
+ .attach = phy_sfp_attach,
+ .detach = phy_sfp_detach,
+ .module_insert = at8031_sfp_insert,
+};
+
static int at8031_parse_dt(struct phy_device *phydev)
{
struct device_node *node = phydev->mdio.dev.of_node;
@@ -0,0 +1,114 @@
From 21a2802a8365cfa82cc02187c1f95136d85592ad Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Fri, 8 Dec 2023 15:51:59 +0100
Subject: [PATCH 12/13] net: phy: at803x: move at8035 specific DT parse to
dedicated probe
Move at8035 specific DT parse for clock out frequency to dedicated probe
to make at803x probe function more generic.
This is to tidy code and no behaviour change are intended.
Detection logic is changed, we check if the clk 25m mask is set and if
it's not zero, we assume the qca,clk-out-frequency property is set.
The property is checked in the generic at803x_parse_dt called by
at803x_probe.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/phy/at803x.c | 60 +++++++++++++++++++++++++++-------------
1 file changed, 41 insertions(+), 19 deletions(-)
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -638,23 +638,6 @@ static int at803x_parse_dt(struct phy_de
priv->clk_25m_reg |= FIELD_PREP(AT803X_CLK_OUT_MASK, sel);
priv->clk_25m_mask |= AT803X_CLK_OUT_MASK;
-
- /* Fixup for the AR8030/AR8035. This chip has another mask and
- * doesn't support the DSP reference. Eg. the lowest bit of the
- * mask. The upper two bits select the same frequencies. Mask
- * the lowest bit here.
- *
- * Warning:
- * There was no datasheet for the AR8030 available so this is
- * just a guess. But the AR8035 is listed as pin compatible
- * to the AR8030 so there might be a good chance it works on
- * the AR8030 too.
- */
- if (phydev->drv->phy_id == ATH8030_PHY_ID ||
- phydev->drv->phy_id == ATH8035_PHY_ID) {
- priv->clk_25m_reg &= AT8035_CLK_OUT_MASK;
- priv->clk_25m_mask &= AT8035_CLK_OUT_MASK;
- }
}
ret = of_property_read_u32(node, "qca,clk-out-strength", &strength);
@@ -1635,6 +1618,45 @@ static int at8031_config_intr(struct phy
return at803x_config_intr(phydev);
}
+static int at8035_parse_dt(struct phy_device *phydev)
+{
+ struct at803x_priv *priv = phydev->priv;
+
+ /* Mask is set by the generic at803x_parse_dt
+ * if property is set. Assume property is set
+ * with the mask not zero.
+ */
+ if (priv->clk_25m_mask) {
+ /* Fixup for the AR8030/AR8035. This chip has another mask and
+ * doesn't support the DSP reference. Eg. the lowest bit of the
+ * mask. The upper two bits select the same frequencies. Mask
+ * the lowest bit here.
+ *
+ * Warning:
+ * There was no datasheet for the AR8030 available so this is
+ * just a guess. But the AR8035 is listed as pin compatible
+ * to the AR8030 so there might be a good chance it works on
+ * the AR8030 too.
+ */
+ priv->clk_25m_reg &= AT8035_CLK_OUT_MASK;
+ priv->clk_25m_mask &= AT8035_CLK_OUT_MASK;
+ }
+
+ return 0;
+}
+
+/* AR8030 and AR8035 shared the same special mask for clk_25m */
+static int at8035_probe(struct phy_device *phydev)
+{
+ int ret;
+
+ ret = at803x_probe(phydev);
+ if (ret)
+ return ret;
+
+ return at8035_parse_dt(phydev);
+}
+
static int qca83xx_config_init(struct phy_device *phydev)
{
u8 switch_revision;
@@ -2107,7 +2129,7 @@ static struct phy_driver at803x_driver[]
PHY_ID_MATCH_EXACT(ATH8035_PHY_ID),
.name = "Qualcomm Atheros AR8035",
.flags = PHY_POLL_CABLE_TEST,
- .probe = at803x_probe,
+ .probe = at8035_probe,
.config_aneg = at803x_config_aneg,
.config_init = at803x_config_init,
.soft_reset = genphy_soft_reset,
@@ -2128,7 +2150,7 @@ static struct phy_driver at803x_driver[]
.phy_id = ATH8030_PHY_ID,
.name = "Qualcomm Atheros AR8030",
.phy_id_mask = AT8030_PHY_ID_MASK,
- .probe = at803x_probe,
+ .probe = at8035_probe,
.config_init = at803x_config_init,
.link_change_notify = at803x_link_change_notify,
.set_wol = at803x_set_wol,
@@ -0,0 +1,219 @@
From ef9df47b449e32e06501a11272809be49019bdb6 Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Fri, 8 Dec 2023 15:52:00 +0100
Subject: [PATCH 13/13] net: phy: at803x: drop specific PHY ID check from cable
test functions
Drop specific PHY ID check for cable test functions for at803x. This is
done to make functions more generic. While at it better describe what
the functions does by using more symbolic function names.
PHYs that requires to set additional reg are moved to specific function
calling the more generic one.
cdt_start and cdt_wait_for_completion are changed to take an additional
arg to pass specific values specific to the PHY.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/phy/at803x.c | 95 +++++++++++++++++++++-------------------
1 file changed, 50 insertions(+), 45 deletions(-)
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -1222,31 +1222,16 @@ static int at803x_cdt_fault_length(u16 s
return (dt * 824) / 10;
}
-static int at803x_cdt_start(struct phy_device *phydev, int pair)
+static int at803x_cdt_start(struct phy_device *phydev,
+ u32 cdt_start)
{
- u16 cdt;
-
- /* qca8081 takes the different bit 15 to enable CDT test */
- if (phydev->drv->phy_id == QCA8081_PHY_ID)
- cdt = QCA808X_CDT_ENABLE_TEST |
- QCA808X_CDT_LENGTH_UNIT |
- QCA808X_CDT_INTER_CHECK_DIS;
- else
- cdt = FIELD_PREP(AT803X_CDT_MDI_PAIR_MASK, pair) |
- AT803X_CDT_ENABLE_TEST;
-
- return phy_write(phydev, AT803X_CDT, cdt);
+ return phy_write(phydev, AT803X_CDT, cdt_start);
}
-static int at803x_cdt_wait_for_completion(struct phy_device *phydev)
+static int at803x_cdt_wait_for_completion(struct phy_device *phydev,
+ u32 cdt_en)
{
int val, ret;
- u16 cdt_en;
-
- if (phydev->drv->phy_id == QCA8081_PHY_ID)
- cdt_en = QCA808X_CDT_ENABLE_TEST;
- else
- cdt_en = AT803X_CDT_ENABLE_TEST;
/* One test run takes about 25ms */
ret = phy_read_poll_timeout(phydev, AT803X_CDT, val,
@@ -1266,11 +1251,13 @@ static int at803x_cable_test_one_pair(st
};
int ret, val;
- ret = at803x_cdt_start(phydev, pair);
+ val = FIELD_PREP(AT803X_CDT_MDI_PAIR_MASK, pair) |
+ AT803X_CDT_ENABLE_TEST;
+ ret = at803x_cdt_start(phydev, val);
if (ret)
return ret;
- ret = at803x_cdt_wait_for_completion(phydev);
+ ret = at803x_cdt_wait_for_completion(phydev, AT803X_CDT_ENABLE_TEST);
if (ret)
return ret;
@@ -1292,19 +1279,11 @@ static int at803x_cable_test_one_pair(st
}
static int at803x_cable_test_get_status(struct phy_device *phydev,
- bool *finished)
+ bool *finished, unsigned long pair_mask)
{
- unsigned long pair_mask;
int retries = 20;
int pair, ret;
- if (phydev->phy_id == ATH9331_PHY_ID ||
- phydev->phy_id == ATH8032_PHY_ID ||
- phydev->phy_id == QCA9561_PHY_ID)
- pair_mask = 0x3;
- else
- pair_mask = 0xf;
-
*finished = false;
/* According to the datasheet the CDT can be performed when
@@ -1331,7 +1310,7 @@ static int at803x_cable_test_get_status(
return 0;
}
-static int at803x_cable_test_start(struct phy_device *phydev)
+static void at803x_cable_test_autoneg(struct phy_device *phydev)
{
/* Enable auto-negotiation, but advertise no capabilities, no link
* will be established. A restart of the auto-negotiation is not
@@ -1339,11 +1318,11 @@ static int at803x_cable_test_start(struc
*/
phy_write(phydev, MII_BMCR, BMCR_ANENABLE);
phy_write(phydev, MII_ADVERTISE, ADVERTISE_CSMA);
- if (phydev->phy_id != ATH9331_PHY_ID &&
- phydev->phy_id != ATH8032_PHY_ID &&
- phydev->phy_id != QCA9561_PHY_ID)
- phy_write(phydev, MII_CTRL1000, 0);
+}
+static int at803x_cable_test_start(struct phy_device *phydev)
+{
+ at803x_cable_test_autoneg(phydev);
/* we do all the (time consuming) work later */
return 0;
}
@@ -1618,6 +1597,29 @@ static int at8031_config_intr(struct phy
return at803x_config_intr(phydev);
}
+/* AR8031 and AR8035 share the same cable test get status reg */
+static int at8031_cable_test_get_status(struct phy_device *phydev,
+ bool *finished)
+{
+ return at803x_cable_test_get_status(phydev, finished, 0xf);
+}
+
+/* AR8031 and AR8035 share the same cable test start logic */
+static int at8031_cable_test_start(struct phy_device *phydev)
+{
+ at803x_cable_test_autoneg(phydev);
+ phy_write(phydev, MII_CTRL1000, 0);
+ /* we do all the (time consuming) work later */
+ return 0;
+}
+
+/* AR8032, AR9331 and QCA9561 share the same cable test get status reg */
+static int at8032_cable_test_get_status(struct phy_device *phydev,
+ bool *finished)
+{
+ return at803x_cable_test_get_status(phydev, finished, 0x3);
+}
+
static int at8035_parse_dt(struct phy_device *phydev)
{
struct at803x_priv *priv = phydev->priv;
@@ -2041,11 +2043,14 @@ static int qca808x_cable_test_get_status
*finished = false;
- ret = at803x_cdt_start(phydev, 0);
+ val = QCA808X_CDT_ENABLE_TEST |
+ QCA808X_CDT_LENGTH_UNIT |
+ QCA808X_CDT_INTER_CHECK_DIS;
+ ret = at803x_cdt_start(phydev, val);
if (ret)
return ret;
- ret = at803x_cdt_wait_for_completion(phydev);
+ ret = at803x_cdt_wait_for_completion(phydev, QCA808X_CDT_ENABLE_TEST);
if (ret)
return ret;
@@ -2143,8 +2148,8 @@ static struct phy_driver at803x_driver[]
.handle_interrupt = at803x_handle_interrupt,
.get_tunable = at803x_get_tunable,
.set_tunable = at803x_set_tunable,
- .cable_test_start = at803x_cable_test_start,
- .cable_test_get_status = at803x_cable_test_get_status,
+ .cable_test_start = at8031_cable_test_start,
+ .cable_test_get_status = at8031_cable_test_get_status,
}, {
/* Qualcomm Atheros AR8030 */
.phy_id = ATH8030_PHY_ID,
@@ -2181,8 +2186,8 @@ static struct phy_driver at803x_driver[]
.handle_interrupt = at803x_handle_interrupt,
.get_tunable = at803x_get_tunable,
.set_tunable = at803x_set_tunable,
- .cable_test_start = at803x_cable_test_start,
- .cable_test_get_status = at803x_cable_test_get_status,
+ .cable_test_start = at8031_cable_test_start,
+ .cable_test_get_status = at8031_cable_test_get_status,
}, {
/* Qualcomm Atheros AR8032 */
PHY_ID_MATCH_EXACT(ATH8032_PHY_ID),
@@ -2197,7 +2202,7 @@ static struct phy_driver at803x_driver[]
.config_intr = at803x_config_intr,
.handle_interrupt = at803x_handle_interrupt,
.cable_test_start = at803x_cable_test_start,
- .cable_test_get_status = at803x_cable_test_get_status,
+ .cable_test_get_status = at8032_cable_test_get_status,
}, {
/* ATHEROS AR9331 */
PHY_ID_MATCH_EXACT(ATH9331_PHY_ID),
@@ -2210,7 +2215,7 @@ static struct phy_driver at803x_driver[]
.config_intr = at803x_config_intr,
.handle_interrupt = at803x_handle_interrupt,
.cable_test_start = at803x_cable_test_start,
- .cable_test_get_status = at803x_cable_test_get_status,
+ .cable_test_get_status = at8032_cable_test_get_status,
.read_status = at803x_read_status,
.soft_reset = genphy_soft_reset,
.config_aneg = at803x_config_aneg,
@@ -2226,7 +2231,7 @@ static struct phy_driver at803x_driver[]
.config_intr = at803x_config_intr,
.handle_interrupt = at803x_handle_interrupt,
.cable_test_start = at803x_cable_test_start,
- .cable_test_get_status = at803x_cable_test_get_status,
+ .cable_test_get_status = at8032_cable_test_get_status,
.read_status = at803x_read_status,
.soft_reset = genphy_soft_reset,
.config_aneg = at803x_config_aneg,
@@ -0,0 +1,116 @@
From 8e732f1c6f2dc5e18f766d0f1b11df9db2dd044a Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Thu, 14 Dec 2023 01:44:31 +0100
Subject: [PATCH 1/2] net: phy: at803x: move specific qca808x config_aneg to
dedicated function
Move specific qca808x config_aneg to dedicated function to permit easier
split of qca808x portion from at803x driver.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/phy/at803x.c | 66 ++++++++++++++++++++++++----------------
1 file changed, 40 insertions(+), 26 deletions(-)
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -1045,9 +1045,8 @@ static int at803x_config_mdix(struct phy
FIELD_PREP(AT803X_SFC_MDI_CROSSOVER_MODE_M, val));
}
-static int at803x_config_aneg(struct phy_device *phydev)
+static int at803x_prepare_config_aneg(struct phy_device *phydev)
{
- struct at803x_priv *priv = phydev->priv;
int ret;
ret = at803x_config_mdix(phydev, phydev->mdix_ctrl);
@@ -1064,33 +1063,22 @@ static int at803x_config_aneg(struct phy
return ret;
}
- if (priv->is_1000basex)
- return genphy_c37_config_aneg(phydev);
-
- /* Do not restart auto-negotiation by setting ret to 0 defautly,
- * when calling __genphy_config_aneg later.
- */
- ret = 0;
-
- if (phydev->drv->phy_id == QCA8081_PHY_ID) {
- int phy_ctrl = 0;
+ return 0;
+}
- /* The reg MII_BMCR also needs to be configured for force mode, the
- * genphy_config_aneg is also needed.
- */
- if (phydev->autoneg == AUTONEG_DISABLE)
- genphy_c45_pma_setup_forced(phydev);
+static int at803x_config_aneg(struct phy_device *phydev)
+{
+ struct at803x_priv *priv = phydev->priv;
+ int ret;
- if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->advertising))
- phy_ctrl = MDIO_AN_10GBT_CTRL_ADV2_5G;
+ ret = at803x_prepare_config_aneg(phydev);
+ if (ret)
+ return ret;
- ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
- MDIO_AN_10GBT_CTRL_ADV2_5G, phy_ctrl);
- if (ret < 0)
- return ret;
- }
+ if (priv->is_1000basex)
+ return genphy_c37_config_aneg(phydev);
- return __genphy_config_aneg(phydev, ret);
+ return genphy_config_aneg(phydev);
}
static int at803x_get_downshift(struct phy_device *phydev, u8 *d)
@@ -2118,6 +2106,32 @@ static int qca808x_get_features(struct p
return 0;
}
+static int qca808x_config_aneg(struct phy_device *phydev)
+{
+ int phy_ctrl = 0;
+ int ret;
+
+ ret = at803x_prepare_config_aneg(phydev);
+ if (ret)
+ return ret;
+
+ /* The reg MII_BMCR also needs to be configured for force mode, the
+ * genphy_config_aneg is also needed.
+ */
+ if (phydev->autoneg == AUTONEG_DISABLE)
+ genphy_c45_pma_setup_forced(phydev);
+
+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->advertising))
+ phy_ctrl = MDIO_AN_10GBT_CTRL_ADV2_5G;
+
+ ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
+ MDIO_AN_10GBT_CTRL_ADV2_5G, phy_ctrl);
+ if (ret < 0)
+ return ret;
+
+ return __genphy_config_aneg(phydev, ret);
+}
+
static void qca808x_link_change_notify(struct phy_device *phydev)
{
/* Assert interface sgmii fifo on link down, deassert it on link up,
@@ -2295,7 +2309,7 @@ static struct phy_driver at803x_driver[]
.set_wol = at803x_set_wol,
.get_wol = at803x_get_wol,
.get_features = qca808x_get_features,
- .config_aneg = at803x_config_aneg,
+ .config_aneg = qca808x_config_aneg,
.suspend = genphy_suspend,
.resume = genphy_resume,
.read_status = qca808x_read_status,
@@ -0,0 +1,97 @@
From 38eb804e8458ba181a03a0498ce4bf84eebd1931 Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Thu, 14 Dec 2023 01:44:32 +0100
Subject: [PATCH 2/2] net: phy: at803x: make read specific status function more
generic
Rework read specific status function to be more generic. The function
apply different speed mask based on the PHY ID. Make it more generic by
adding an additional arg to pass the specific speed (ss) mask and use
the provided mask to parse the speed value.
This is needed to permit an easier deatch of qca808x code from the
at803x driver.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/phy/at803x.c | 26 ++++++++++++++++++--------
1 file changed, 18 insertions(+), 8 deletions(-)
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -301,6 +301,11 @@ static struct at803x_hw_stat qca83xx_hw_
{ "eee_wake_errors", 0x16, GENMASK(15, 0), MMD},
};
+struct at803x_ss_mask {
+ u16 speed_mask;
+ u8 speed_shift;
+};
+
struct at803x_priv {
int flags;
u16 clk_25m_reg;
@@ -921,7 +926,8 @@ static void at803x_link_change_notify(st
}
}
-static int at803x_read_specific_status(struct phy_device *phydev)
+static int at803x_read_specific_status(struct phy_device *phydev,
+ struct at803x_ss_mask ss_mask)
{
int ss;
@@ -940,11 +946,8 @@ static int at803x_read_specific_status(s
if (sfc < 0)
return sfc;
- /* qca8081 takes the different bits for speed value from at803x */
- if (phydev->drv->phy_id == QCA8081_PHY_ID)
- speed = FIELD_GET(QCA808X_SS_SPEED_MASK, ss);
- else
- speed = FIELD_GET(AT803X_SS_SPEED_MASK, ss);
+ speed = ss & ss_mask.speed_mask;
+ speed >>= ss_mask.speed_shift;
switch (speed) {
case AT803X_SS_SPEED_10:
@@ -989,6 +992,7 @@ static int at803x_read_specific_status(s
static int at803x_read_status(struct phy_device *phydev)
{
struct at803x_priv *priv = phydev->priv;
+ struct at803x_ss_mask ss_mask = { 0 };
int err, old_link = phydev->link;
if (priv->is_1000basex)
@@ -1012,7 +1016,9 @@ static int at803x_read_status(struct phy
if (err < 0)
return err;
- err = at803x_read_specific_status(phydev);
+ ss_mask.speed_mask = AT803X_SS_SPEED_MASK;
+ ss_mask.speed_shift = __bf_shf(AT803X_SS_SPEED_MASK);
+ err = at803x_read_specific_status(phydev, ss_mask);
if (err < 0)
return err;
@@ -1869,6 +1875,7 @@ static int qca808x_config_init(struct ph
static int qca808x_read_status(struct phy_device *phydev)
{
+ struct at803x_ss_mask ss_mask = { 0 };
int ret;
ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_STAT);
@@ -1882,7 +1889,10 @@ static int qca808x_read_status(struct ph
if (ret)
return ret;
- ret = at803x_read_specific_status(phydev);
+ /* qca8081 takes the different bits for speed value from at803x */
+ ss_mask.speed_mask = QCA808X_SS_SPEED_MASK;
+ ss_mask.speed_shift = __bf_shf(QCA808X_SS_SPEED_MASK);
+ ret = at803x_read_specific_status(phydev, ss_mask);
if (ret < 0)
return ret;
@@ -0,0 +1,27 @@
From fc9d7264ddc32eaa647d6bfcdc25cdf9f786fde0 Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Mon, 18 Dec 2023 00:27:39 +0100
Subject: [PATCH 1/2] net: phy: at803x: remove extra space after cast
Remove extra space after cast as reported by checkpatch to keep code
clean.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://lore.kernel.org/r/20231217232739.27065-1-ansuelsmth@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
---
drivers/net/phy/at803x.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -462,7 +462,7 @@ static int at803x_set_wol(struct phy_dev
if (!ndev)
return -ENODEV;
- mac = (const u8 *) ndev->dev_addr;
+ mac = (const u8 *)ndev->dev_addr;
if (!is_valid_ether_addr(mac))
return -EINVAL;
@@ -0,0 +1,38 @@
From 3ab5720881a924fb6405d9e6a3b09f1026467c47 Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Mon, 18 Dec 2023 00:25:08 +0100
Subject: [PATCH 2/2] net: phy: at803x: replace msleep(1) with usleep_range
Replace msleep(1) with usleep_range as suggested by timers-howto guide.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://lore.kernel.org/r/20231217232508.26470-1-ansuelsmth@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
---
drivers/net/phy/at803x.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -916,9 +916,9 @@ static void at803x_link_change_notify(st
at803x_context_save(phydev, &context);
phy_device_reset(phydev, 1);
- msleep(1);
+ usleep_range(1000, 2000);
phy_device_reset(phydev, 0);
- msleep(1);
+ usleep_range(1000, 2000);
at803x_context_restore(phydev, &context);
@@ -1733,7 +1733,7 @@ static int qca83xx_resume(struct phy_dev
if (ret)
return ret;
- msleep(1);
+ usleep_range(1000, 2000);
return 0;
}
@@ -0,0 +1,152 @@
From 7961ef1fa10ec35ad6923fb5751877116e4b035b Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Tue, 19 Dec 2023 21:21:24 +0100
Subject: [PATCH] net: phy: at803x: better align function varibles to open
parenthesis
Better align function variables to open parenthesis as suggested by
checkpatch script for qca808x function to make code cleaner.
For cable_test_get_status function some additional rework was needed to
handle too long functions.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/phy/at803x.c | 67 ++++++++++++++++++++++------------------
1 file changed, 37 insertions(+), 30 deletions(-)
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -1781,27 +1781,27 @@ static int qca808x_phy_fast_retrain_conf
return ret;
phy_write_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_TOP_OPTION1,
- QCA808X_TOP_OPTION1_DATA);
+ QCA808X_TOP_OPTION1_DATA);
phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_20DB,
- QCA808X_MSE_THRESHOLD_20DB_VALUE);
+ QCA808X_MSE_THRESHOLD_20DB_VALUE);
phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_17DB,
- QCA808X_MSE_THRESHOLD_17DB_VALUE);
+ QCA808X_MSE_THRESHOLD_17DB_VALUE);
phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_27DB,
- QCA808X_MSE_THRESHOLD_27DB_VALUE);
+ QCA808X_MSE_THRESHOLD_27DB_VALUE);
phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_28DB,
- QCA808X_MSE_THRESHOLD_28DB_VALUE);
+ QCA808X_MSE_THRESHOLD_28DB_VALUE);
phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_1,
- QCA808X_MMD3_DEBUG_1_VALUE);
+ QCA808X_MMD3_DEBUG_1_VALUE);
phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_4,
- QCA808X_MMD3_DEBUG_4_VALUE);
+ QCA808X_MMD3_DEBUG_4_VALUE);
phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_5,
- QCA808X_MMD3_DEBUG_5_VALUE);
+ QCA808X_MMD3_DEBUG_5_VALUE);
phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_3,
- QCA808X_MMD3_DEBUG_3_VALUE);
+ QCA808X_MMD3_DEBUG_3_VALUE);
phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_6,
- QCA808X_MMD3_DEBUG_6_VALUE);
+ QCA808X_MMD3_DEBUG_6_VALUE);
phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_2,
- QCA808X_MMD3_DEBUG_2_VALUE);
+ QCA808X_MMD3_DEBUG_2_VALUE);
return 0;
}
@@ -1838,13 +1838,14 @@ static int qca808x_config_init(struct ph
/* Active adc&vga on 802.3az for the link 1000M and 100M */
ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_ADDR_CLD_CTRL7,
- QCA808X_8023AZ_AFE_CTRL_MASK, QCA808X_8023AZ_AFE_EN);
+ QCA808X_8023AZ_AFE_CTRL_MASK, QCA808X_8023AZ_AFE_EN);
if (ret)
return ret;
/* Adjust the threshold on 802.3az for the link 1000M */
ret = phy_write_mmd(phydev, MDIO_MMD_PCS,
- QCA808X_PHY_MMD3_AZ_TRAINING_CTRL, QCA808X_MMD3_AZ_TRAINING_VAL);
+ QCA808X_PHY_MMD3_AZ_TRAINING_CTRL,
+ QCA808X_MMD3_AZ_TRAINING_VAL);
if (ret)
return ret;
@@ -1870,7 +1871,8 @@ static int qca808x_config_init(struct ph
/* Configure adc threshold as 100mv for the link 10M */
return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_ADC_THRESHOLD,
- QCA808X_ADC_THRESHOLD_MASK, QCA808X_ADC_THRESHOLD_100MV);
+ QCA808X_ADC_THRESHOLD_MASK,
+ QCA808X_ADC_THRESHOLD_100MV);
}
static int qca808x_read_status(struct phy_device *phydev)
@@ -1883,7 +1885,7 @@ static int qca808x_read_status(struct ph
return ret;
linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->lp_advertising,
- ret & MDIO_AN_10GBT_STAT_LP2_5G);
+ ret & MDIO_AN_10GBT_STAT_LP2_5G);
ret = genphy_read_status(phydev);
if (ret)
@@ -1913,7 +1915,7 @@ static int qca808x_read_status(struct ph
*/
if (qca808x_has_fast_retrain_or_slave_seed(phydev)) {
if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR ||
- qca808x_is_prefer_master(phydev)) {
+ qca808x_is_prefer_master(phydev)) {
qca808x_phy_ms_seed_enable(phydev, false);
} else {
qca808x_phy_ms_seed_enable(phydev, true);
@@ -2070,18 +2072,22 @@ static int qca808x_cable_test_get_status
ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_D,
qca808x_cable_test_result_trans(pair_d));
- if (qca808x_cdt_fault_length_valid(pair_a))
- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A,
- qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A));
- if (qca808x_cdt_fault_length_valid(pair_b))
- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_B,
- qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_B));
- if (qca808x_cdt_fault_length_valid(pair_c))
- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_C,
- qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_C));
- if (qca808x_cdt_fault_length_valid(pair_d))
- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_D,
- qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_D));
+ if (qca808x_cdt_fault_length_valid(pair_a)) {
+ val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A);
+ ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A, val);
+ }
+ if (qca808x_cdt_fault_length_valid(pair_b)) {
+ val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_B);
+ ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_B, val);
+ }
+ if (qca808x_cdt_fault_length_valid(pair_c)) {
+ val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_C);
+ ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_C, val);
+ }
+ if (qca808x_cdt_fault_length_valid(pair_d)) {
+ val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_D);
+ ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_D, val);
+ }
*finished = true;
@@ -2148,8 +2154,9 @@ static void qca808x_link_change_notify(s
* the interface device address is always phy address added by 1.
*/
mdiobus_c45_modify_changed(phydev->mdio.bus, phydev->mdio.addr + 1,
- MDIO_MMD_PMAPMD, QCA8081_PHY_SERDES_MMD1_FIFO_CTRL,
- QCA8081_PHY_FIFO_RSTN, phydev->link ? QCA8081_PHY_FIFO_RSTN : 0);
+ MDIO_MMD_PMAPMD, QCA8081_PHY_SERDES_MMD1_FIFO_CTRL,
+ QCA8081_PHY_FIFO_RSTN,
+ phydev->link ? QCA8081_PHY_FIFO_RSTN : 0);
}
static struct phy_driver at803x_driver[] = {

Some files were not shown because too many files have changed in this diff Show More