Merge Official Source

Signed-off-by: Tianling Shen <cnsztl@immortalwrt.org>
This commit is contained in:
Tianling Shen 2025-01-18 18:48:49 +08:00
commit fa9ca4d5cb
No known key found for this signature in database
GPG Key ID: 6850B6345C862176
55 changed files with 5884 additions and 245 deletions

View File

@ -447,9 +447,10 @@ $(eval $(call KernelPackage,phy-micrel))
define KernelPackage/phy-realtek
SUBMENU:=$(NETWORK_DEVICES_MENU)
TITLE:=Realtek Ethernet PHY driver
KCONFIG:=CONFIG_REALTEK_PHY
DEPENDS:=+kmod-libphy
FILES:=$(LINUX_DIR)/drivers/net/phy/realtek.ko
KCONFIG:=CONFIG_REALTEK_PHY \
CONFIG_REALTEK_PHY_HWMON=y
DEPENDS:=+kmod-libphy +kmod-hwmon-core
FILES:=$(LINUX_DIR)/drivers/net/phy/realtek/realtek.ko
AUTOLOAD:=$(call AutoLoad,18,realtek,1)
endef
@ -959,7 +960,7 @@ $(eval $(call KernelPackage,8139cp))
define KernelPackage/r8169
SUBMENU:=$(NETWORK_DEVICES_MENU)
TITLE:=RealTek RTL-8169 PCI Gigabit Ethernet Adapter kernel support
DEPENDS:=@PCI_SUPPORT +kmod-mii +r8169-firmware +kmod-phy-realtek +kmod-mdio-devres +kmod-hwmon-core
DEPENDS:=@PCI_SUPPORT +kmod-mii +r8169-firmware +kmod-phy-realtek +kmod-mdio-devres
KCONFIG:= \
CONFIG_R8169 \
CONFIG_R8169_LEDS=y

View File

@ -65,8 +65,9 @@ function cpu_mask(cpu)
return sprintf("%x", mask);
}
function set_netdev_cpu(dev, cpu) {
let queues = glob(`/sys/class/net/${dev}/queues/rx-*/rps_cpus`);
function set_netdev_cpu(dev, cpu, rx_queue) {
rx_queue ??= "rx-*";
let queues = glob(`/sys/class/net/${dev}/queues/${rx_queue}/rps_cpus`);
let val = cpu_mask(cpu);
if (disable)
val = 0;
@ -76,7 +77,7 @@ function set_netdev_cpu(dev, cpu) {
if (!do_nothing)
writefile(queue, `${val}`);
}
queues = glob(`/sys/class/net/${dev}/queues/rx-*/rps_flow_cnt`);
queues = glob(`/sys/class/net/${dev}/queues/${rx_queue}/rps_flow_cnt`);
for (let queue in queues) {
if (debug || do_nothing)
warn(`echo ${local_flows} > ${queue}\n`);
@ -160,6 +161,9 @@ for (let dev in netdevs) {
netdev: [],
phy: [],
tasks: [],
rx_tasks: [],
rx_queues: map(glob(`/sys/class/net/${dev}/queues/rx-*/rps_cpus`),
(v) => basename(dirname(v))),
};
}
@ -187,11 +191,51 @@ for (let path in glob("/proc/*/exe")) {
continue;
push(dev.tasks, pid);
let napi_match = match(name, /napi\/([^-]*)-(\d+)/);
if (napi_match && napi_match[2] > 0)
push(dev.rx_tasks, pid);
break;
}
}
function assign_dev_queues_cpu(dev) {
let num = length(dev.rx_queues);
if (num < length(dev.rx_tasks))
num = length(dev.rx_tasks);
for (let i = 0; i < num; i++) {
let cpu;
let task = dev.rx_tasks[i];
if (num >= length(cpus))
cpu = i % length(cpus);
else if (task)
cpu = get_next_cpu(napi_weight);
else
cpu = -1;
set_task_cpu(task, cpu);
let rxq = dev.rx_queues[i];
if (!rxq)
continue;
if (num >= length(cpus))
cpu = (i + 1) % length(cpus);
else if (all_cpus)
cpu = -1;
else
cpu = get_next_cpu(napi_weight, cpu);
for (let netdev in dev.netdev)
set_netdev_cpu(netdev, cpu, rxq);
}
}
function assign_dev_cpu(dev) {
if (length(dev.rx_queues) > 1 &&
length(dev.rx_tasks) > 1)
return assign_dev_queues_cpu(dev);
if (length(dev.tasks) > 0) {
let cpu = dev.napi_cpu = get_next_cpu(napi_weight);
for (let task in dev.tasks)
@ -204,7 +248,6 @@ function assign_dev_cpu(dev) {
cpu = -1;
else
cpu = get_next_cpu(rx_weight, dev.napi_cpu);
dev.rx_cpu = cpu;
for (let netdev in dev.netdev)
set_netdev_cpu(netdev, cpu);
}

View File

@ -71,12 +71,22 @@ export function parse_encryption(config) {
config.auth_type = 'eap2';
break;
case 'psk-mixed':
config.auth_type = "psk";
break;
case 'psk3':
config.auth_type = 'sae';
break;
case 'psk3-mixed':
case 'sae-mixed':
config.auth_type = 'psk-sae';
break;
case 'wpa':
case 'wpa2':
case 'wpa-mixed':
config.auth_type = 'eap';
break;
}

View File

@ -13,9 +13,9 @@ PKG_RELEASE:=1
PKG_SOURCE_URL=$(PROJECT_GIT)/project/uci.git
PKG_SOURCE_PROTO:=git
PKG_SOURCE_DATE:=2024-11-26
PKG_SOURCE_VERSION:=10f7996ec29449915640acca5d65b592365a4b14
PKG_MIRROR_HASH:=8556add0dd77b85a5702faa94feb811606390c045d7f5004317a4ab3e07f773b
PKG_SOURCE_DATE:=2025-01-17
PKG_SOURCE_VERSION:=fb3c2343b17b759b175f11aec5b3fbb1cf48bbc3
PKG_MIRROR_HASH:=c9302f4a1cb400134cb9fc0622fb6a04bbe8c55bcc83ec454caadb1e62f3257e
PKG_LICENSE:=LGPL-2.1
PKG_LICENSE_FILES:=
@ -33,7 +33,7 @@ define Package/libuci
CATEGORY:=Libraries
TITLE:=C library for the Unified Configuration Interface (UCI)
DEPENDS:=+libubox
ABI_VERSION:=20130104
ABI_VERSION:=20250117
endef
define Package/uci

View File

@ -0,0 +1,44 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=ucode-mod-pkgen
PKG_RELEASE:=1
PKG_LICENSE:=GPL-2.0-or-later
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/cmake.mk
CMAKE_INSTALL := 1
define Package/ucode-mod-pkgen
SECTION:=utils
CATEGORY:=Utilities
TITLE:=ucode module for generating public keys/certificates
DEPENDS:=+libucode +libmbedtls
endef
define Package/ucode-mod-pkgen/description
The pkgen module provides functionality for generating cryptographic keys and
(self-)signed certificates. It supports exporting PEM/DER format files, as
well as PKCS#12 bundle for client cert/key pairs with CA.
endef
define Package/pkgen
SECTION:=utils
CATEGORY:=Utilities
TITLE:=ucode script for generating public keys/certificates
DEPENDS:=+ucode +ucode-mod-pkgen +ucode-mod-fs
endef
define Package/ucode-mod-pkgen/install
$(INSTALL_DIR) $(1)/usr/lib/ucode
$(CP) $(PKG_INSTALL_DIR)/usr/lib/ucode/pkgen.so $(1)/usr/lib/ucode/
endef
define Package/pkgen/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) ./files/pkgen $(1)/usr/bin
endef
$(eval $(call BuildPackage,ucode-mod-pkgen))
$(eval $(call BuildPackage,pkgen))

View File

@ -0,0 +1,252 @@
#!/usr/bin/env ucode
'use strict';
import { basename, readfile, writefile, stdin } from "fs";
let pk = require("pkgen");
let valid_from = "20240101000000";
let valid_to = "21001231235959";
let subject, password, password_stdin;
let keytype = "ec";
let keylen = 2048;
let keyexp = 65537;
let keycurve = "secp256r1";
let no_ca;
let legacy;
const usage_message = `Usage: ${basename(sourcepath())} [<options>] <command> [<arguments>]
Commands:
ca <ca.pem>: Create a new CA.
(creates ca.pem, ca.key, ca.serial)
cert <ca.pem> <cert.pem>: Create a new certificate/key using the CA
from ca.pem. (creates cert.pem and ca.key)
cert_p12 <ca.pem> <cert.p12>: Create a new PKCS#12 certificate/key
using the CA from ca.pem. (creates ca.p12)
selfsigned <cert.pem>: Create a self-signed certificate
(creates cert.pem)
Options:
-C <curve> Set EC curve type (default: ${keycurve})
Possible values: secp521r1, secp384r1, secp256r1,
secp256k1, secp224r1, secp224k1, secp192r1,
secp192k1
-E <exponent> Set RSA key exponent (default: ${keyexp})
-L <len> Set RSA key length (default: ${keylen})
-N Omit CA certificate for PKCS#12 files
-p <password> Set PKCS#12 password to <password>
-P Read PKCS#12 password from stdin
(default: random password, printed to stdout)
-s <name> Set subject for generated certificate to <name>.
-t rsa|ec Set key type to rsa or ec (default: ec)
-V <from> <to> Set validity for generated certificates.
(default: ${valid_from} ${valid_to})
-W Use weaker PKCS#12 encryption for
compatibility with Windows and Apple systems
`;
function perror(msg) {
let err = pk.errno() == -1 ? "Invalid arguments" : pk.error();
warn(`${msg}: ${err}\n`);
exit(1);
}
function usage() {
warn(usage_message);
exit(1);
}
function check_pem_path(pem_file) {
if (substr(pem_file, -4) != ".pem") {
warn(`Path with .pem extension expected\n`);
exit(1);
}
return pem_file;
}
function gen_key() {
let key = pk.generate_key({
type: keytype,
curve: keycurve,
size: keylen,
exponent: keyexp,
});
if (!key)
perror("Failed to generate CA key");
return key;
}
function gen_cert(key, args) {
let cert = pk.generate_cert({
subject_name: subject,
subject_key: key,
validity: [ valid_from, valid_to ],
...args
});
if (!cert)
perror("Failed to generate certificate");
cert = cert.pem();
if (!cert)
perror("Failed to complete certificate");
return cert;
}
function gen_client_cert(ca_file, ca_data, key) {
let ca_base = substr(ca_file, 0, -4);
let ca_info = pk.cert_info(ca_data);
if (!length(ca_info))
perror("Failed to load CA certificate");
let ca_key = pk.load_key(readfile(ca_base + ".key"));
if (!ca_key)
perror("Failed to load CA key");
let ca_serial = +readfile(ca_base + ".serial");
if (!ca_serial)
perror("Failed to load CA serial");
let cert = gen_cert(key, {
serial: ++ca_serial,
issuer_name: ca_info[0].subject,
issuer_key: ca_key,
});
writefile(ca_base + ".serial", "" + ca_serial);
return cert;
}
let cmds = {
ca: function(args) {
let ca_file = check_pem_path(shift(args));
let ca_base = substr(ca_file, 0, -4);
let key = gen_key();
let ca_cert = gen_cert(key, {
ca: true,
serial: 1,
issuer_name: subject,
issuer_key: key,
key_usage: [ "key_cert_sign" ],
});
writefile(ca_file, ca_cert);
writefile(ca_base + ".key", key.pem());
writefile(ca_base + ".serial", "1");
},
cert: function (args) {
let ca_file = check_pem_path(shift(args));
let crt_file = check_pem_path(shift(args));
let crt_base = substr(crt_file, 0, -4);
let key = gen_key();
let ca_data = readfile(ca_file);
let cert = gen_client_cert(ca_file, ca_data, key);
writefile(crt_base + ".key", key.pem());
writefile(crt_file, cert);
},
cert_p12: function (args) {
let ca_file = check_pem_path(shift(args));
let p12_file = shift(args);
if (!p12_file)
usage();
let key = gen_key();
let ca_data = readfile(ca_file);
let cert = gen_client_cert(ca_file, ca_data, key);
if (password_stdin)
password = rtrim(stdin.read("line"));
else if (!password)
print((password = hexenc(readfile("/dev/urandom", 8))) + "\n");
let p12 = pk.generate_pkcs12({
password, cert, key, legacy,
extra: no_ca ? null : [ ca_data ],
});
writefile(p12_file, p12);
},
selfsigned: function(args) {
let crt_file = check_pem_path(shift(args));
let crt_base = substr(crt_file, 0, -4);
let key = gen_key();
let cert = gen_cert(key, {
serial: 1,
issuer_name: subject,
issuer_key: key,
});
writefile(crt_base + ".key", key.pem());
writefile(crt_file, cert);
},
};
while (substr(ARGV[0], 0, 1) == "-") {
let opt = substr(shift(ARGV), 1);
switch (opt) {
case 'C':
keycurve = shift(ARGV);
break;
case 'L':
keylen = +shift(ARGV);
break;
case 'N':
no_ca = true;
break;
case 'p':
password = shift(ARGV);
if (password_stdin)
usage();
break;
case 'P':
password_stdin = true;
if (password)
usage();
break;
case 's':
subject = shift(ARGV);
break;
case 't':
keytype = shift(ARGV);
if (keytype != "rsa" && keytype != "ec") {
warn(`Unsupported key type ${keytype}\n`);
exit(1);
}
break;
case 'V':
valid_from = shift(ARGV);
valid_to = shift(ARGV);
break;
case 'W':
legacy = true;
break;
default:
usage();
break;
}
}
let cmd = shift(ARGV);
if (!cmd || !cmds[cmd])
usage();
if (subject == null) {
warn(`Missing -s option\n`);
exit(1);
}
cmds[cmd](ARGV);

View File

@ -0,0 +1,35 @@
cmake_minimum_required(VERSION 3.13)
PROJECT(ucode-pkgen C)
ADD_DEFINITIONS(-Os -ggdb -Wall -Werror --std=gnu99 -ffunction-sections -fwrapv -D_GNU_SOURCE)
IF(CMAKE_C_COMPILER_VERSION VERSION_GREATER 6)
ADD_DEFINITIONS(-Wextra -Werror=implicit-function-declaration)
ADD_DEFINITIONS(-Wformat -Werror=format-security -Werror=format-nonliteral)
ENDIF()
ADD_DEFINITIONS(-Wmissing-declarations -Wno-error=unused-variable -Wno-unused-parameter)
IF(APPLE)
SET(UCODE_MODULE_LINK_OPTIONS "LINKER:-undefined,dynamic_lookup")
ELSE()
SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "-Wl,--gc-sections")
ENDIF()
IF(DEBUG)
ADD_DEFINITIONS(-DDEBUG -g3 -O0)
ELSE()
ADD_DEFINITIONS(-DNDEBUG)
ENDIF()
FIND_LIBRARY(mbedtls NAMES mbedtls)
FIND_LIBRARY(ucode NAMES ucode)
FIND_PATH(mbedtls_include_dir NAMES mbedtls/pk.h)
FIND_PATH(ucode_include_dir NAMES ucode/module.h)
INCLUDE_DIRECTORIES(${mbedtls_include_dir} ${ucode_include_dir})
ADD_LIBRARY(pkgen_lib MODULE ucode.c pkcs12.c)
SET_TARGET_PROPERTIES(pkgen_lib PROPERTIES OUTPUT_NAME pkgen PREFIX "")
TARGET_LINK_OPTIONS(pkgen_lib PRIVATE ${UCODE_MODULE_LINK_OPTIONS})
TARGET_LINK_LIBRARIES(pkgen_lib ${mbedtls})
INSTALL(TARGETS pkgen_lib LIBRARY DESTINATION lib/ucode)

View File

@ -0,0 +1,45 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2024 Felix Fietkau <nbd@nbd.name>
*/
#ifndef __UCODE_PK_H
#define __UCODE_PK_H
#include <ucode/lib.h>
#include <ucode/vm.h>
#include <mbedtls/bignum.h>
#include <mbedtls/pk.h>
#include <mbedtls/oid.h>
#include <mbedtls/error.h>
#include <mbedtls/version.h>
#if MBEDTLS_VERSION_MAJOR < 3
#define MBEDTLS_LEGACY
#endif
int random_cb(void *ctx, unsigned char *out, size_t len);
uc_value_t *uc_generate_pkcs12(uc_vm_t *vm, size_t nargs);
int64_t get_int_arg(uc_value_t *obj, const char *key, int64_t defval);
extern int mbedtls_errno;
extern char buf[32 * 1024];
#define C(ret) \
({ \
int __ret = (ret); \
mbedtls_errno = __ret < 0 ? __ret : 0; \
__ret; \
})
#define CHECK(ret) do { \
if (C(ret) < 0) \
return NULL; \
} while (0)
#define CHECK_INT(ret) do { \
if (C(ret) < 0) \
return -1; \
} while (0)
#define INVALID_ARG() do { C(-1); return NULL; } while (0)
#endif

View File

@ -0,0 +1,612 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2024 Felix Fietkau <nbd@nbd.name>
*/
#include "pk.h"
#include <mbedtls/x509_crt.h>
#include <mbedtls/ecp.h>
#include <mbedtls/rsa.h>
#include <mbedtls/asn1write.h>
#include <mbedtls/pkcs5.h>
#include <mbedtls/pkcs12.h>
#include <mbedtls/base64.h>
#include <mbedtls/sha1.h>
#define OID_TAG(n) MBEDTLS_OID_##n, MBEDTLS_OID_SIZE(MBEDTLS_OID_##n)
#ifndef MBEDTLS_OID_AES_256_CBC
#define MBEDTLS_OID_AES_256_CBC MBEDTLS_OID_AES "\x2a"
#endif
#define MBEDTLS_OID_PKCS9_LOCAL_KEY_ID MBEDTLS_OID_PKCS9 "\x15"
#define MBEDTLS_OID_PKCS9_CERT_TYPE MBEDTLS_OID_PKCS9 "\x16"
#define MBEDTLS_OID_PKCS9_CERT_TYPE_X509 MBEDTLS_OID_PKCS9_CERT_TYPE "\x01"
#define MBEDTLS_OID_PKCS12_KEY_BAG MBEDTLS_OID_PKCS12 "\x0a\x01\x01"
#define MBEDTLS_OID_PKCS12_SHROUDED_KEY_BAG MBEDTLS_OID_PKCS12 "\x0a\x01\x02"
#define MBEDTLS_OID_PKCS12_CERT_BAG MBEDTLS_OID_PKCS12 "\x0a\x01\x03"
#ifndef MBEDTLS_OID_PKCS7
#define MBEDTLS_OID_PKCS7 MBEDTLS_OID_PKCS "\x07"
#define MBEDTLS_OID_PKCS7_DATA MBEDTLS_OID_PKCS7 "\x01"
#define MBEDTLS_OID_PKCS7_ENCRYPTED_DATA MBEDTLS_OID_PKCS7 "\x06"
#endif
#define NUM_ITER 2048
#define SALT_LEN 16
#define IV_LEN 16
#define IV_LEN_LEGACY 8
#define KEY_LEN 32
#define CERT_HASH_LEN 20
#define CONTEXT_TAG(n) (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | (n))
#define SEQUENCE_TAG (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)
#define SET_TAG (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)
#define CTX_ADD(ctx, n) \
do { \
int __n = (n); \
if ((ctx)->p - (ctx)->start <= __n) \
return -1; \
(ctx)->p -= __n; \
} while (0)
struct pkcs12_ctx {
uint8_t *p, *start;
uint8_t cert_hash[20];
uint8_t *key_cert_hash;
uint8_t salt[SALT_LEN];
uint8_t iv[IV_LEN];
const char *password;
uint8_t *pwd;
size_t pwd_len;
bool legacy;
};
#ifdef MBEDTLS_LEGACY
static inline int
mbedtls_pkcs5_pbkdf2_hmac_ext(mbedtls_md_type_t md_alg, const unsigned char *password,
size_t plen, const unsigned char *salt, size_t slen,
unsigned int iteration_count,
uint32_t key_length, unsigned char *output)
{
mbedtls_md_context_t md_ctx;
const mbedtls_md_info_t *md_info;
int ret;
md_info = mbedtls_md_info_from_type(md_alg);
if (!md_info)
return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE;
mbedtls_md_init(&md_ctx);
ret = mbedtls_md_setup(&md_ctx, md_info, 1);
if (ret)
goto out;
ret = mbedtls_pkcs5_pbkdf2_hmac(&md_ctx, password, plen, salt, slen,
iteration_count, key_length, output);
out:
mbedtls_md_free(&md_ctx);
return ret;
}
#endif
static void
uc_p12_add_tag(struct pkcs12_ctx *ctx, uint8_t *end, uint8_t tag)
{
mbedtls_asn1_write_len(&ctx->p, ctx->start, end - ctx->p);
mbedtls_asn1_write_tag(&ctx->p, ctx->start, tag);
}
static void
uc_p12_add_sequence(struct pkcs12_ctx *ctx, uint8_t *end)
{
uc_p12_add_tag(ctx, end, SEQUENCE_TAG);
}
static void
uc_p12_add_algo(struct pkcs12_ctx *ctx, const char *oid, size_t oid_len, size_t par_len)
{
mbedtls_asn1_write_algorithm_identifier(&ctx->p, ctx->start, oid, oid_len, par_len);
}
static void
uc_p12_add_attribute(struct pkcs12_ctx *ctx, uint8_t *end, const char *oid, size_t oid_len)
{
uc_p12_add_tag(ctx, end, SET_TAG);
mbedtls_asn1_write_oid(&ctx->p, ctx->start, oid, oid_len);
uc_p12_add_sequence(ctx, end);
}
static void
uc_p12_add_localkeyid(struct pkcs12_ctx *ctx, bool key)
{
uint8_t *end = ctx->p;
ctx->p -= CERT_HASH_LEN;
if (key)
ctx->key_cert_hash = ctx->p;
else if (ctx->key_cert_hash)
memcpy(ctx->p, ctx->key_cert_hash, CERT_HASH_LEN);
uc_p12_add_tag(ctx, end, MBEDTLS_ASN1_OCTET_STRING);
uc_p12_add_attribute(ctx, end, OID_TAG(PKCS9_LOCAL_KEY_ID));
}
static void
uc_p12_add_bag(struct pkcs12_ctx *ctx, uint8_t *data_end, uint8_t *end, const char *oid, size_t oid_len)
{
uc_p12_add_tag(ctx, data_end, CONTEXT_TAG(0));
mbedtls_asn1_write_oid(&ctx->p, ctx->start, oid, oid_len);
uc_p12_add_sequence(ctx, end);
}
static int
uc_p12_enc_setup(struct pkcs12_ctx *ctx, mbedtls_cipher_context_t *cipher)
{
const mbedtls_cipher_info_t *cipher_info;
uint8_t key[KEY_LEN];
int ret;
random_cb(NULL, ctx->iv, IV_LEN);
ret = mbedtls_pkcs5_pbkdf2_hmac_ext(MBEDTLS_MD_SHA256,
(void *)ctx->password, strlen(ctx->password),
ctx->salt, SALT_LEN, NUM_ITER,
KEY_LEN, key);
if (ret < 0)
return ret;
cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_CBC);
ret = mbedtls_cipher_setup(cipher, cipher_info);
if (ret < 0)
return ret;
return mbedtls_cipher_setkey(cipher, key, 8 * KEY_LEN, MBEDTLS_ENCRYPT);
}
static int
uc_p12_enc_legacy(struct pkcs12_ctx *ctx, mbedtls_cipher_context_t *cipher)
{
const mbedtls_cipher_info_t *cipher_info;
uint8_t key[24];
int ret;
ret = mbedtls_pkcs12_derivation(key, sizeof(key), ctx->pwd, ctx->pwd_len,
ctx->salt, SALT_LEN, MBEDTLS_MD_SHA1,
MBEDTLS_PKCS12_DERIVE_KEY, NUM_ITER);
if (ret < 0)
return ret;
ret = mbedtls_pkcs12_derivation(ctx->iv, IV_LEN_LEGACY, ctx->pwd, ctx->pwd_len,
ctx->salt, SALT_LEN, MBEDTLS_MD_SHA1,
MBEDTLS_PKCS12_DERIVE_IV, NUM_ITER);
if (ret < 0)
return ret;
cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_DES_EDE3_CBC);
ret = mbedtls_cipher_setup(cipher, cipher_info);
if (ret < 0)
return ret;
return mbedtls_cipher_setkey(cipher, key, 8 * sizeof(key), MBEDTLS_ENCRYPT);
}
static int
uc_p12_encrypt(struct pkcs12_ctx *ctx, uint8_t *end)
{
mbedtls_cipher_context_t cipher;
size_t iv_len = ctx->legacy ? IV_LEN_LEGACY : IV_LEN;
size_t out_len = 0;
int ret;
random_cb(NULL, ctx->salt, SALT_LEN);
if (ctx->legacy)
ret = uc_p12_enc_legacy(ctx, &cipher);
else
ret = uc_p12_enc_setup(ctx, &cipher);
if (ret < 0)
goto out;
ret = mbedtls_cipher_set_padding_mode(&cipher, MBEDTLS_PADDING_PKCS7);
if (ret < 0)
goto out;
ret = mbedtls_cipher_crypt(&cipher, ctx->iv, iv_len, ctx->p, end - ctx->p,
(void *)buf, &out_len);
if (ret < 0)
goto out;
CTX_ADD(ctx, out_len - (end - ctx->p));
memcpy(ctx->p, buf, out_len);
uc_p12_add_tag(ctx, end, MBEDTLS_ASN1_OCTET_STRING);
out:
mbedtls_cipher_free(&cipher);
return ret;
}
static int
uc_p12_add_enc_params(struct pkcs12_ctx *ctx)
{
uint8_t *par_end = ctx->p;
uint8_t *kdf_end;
if (ctx->legacy) {
mbedtls_asn1_write_int(&ctx->p, ctx->start, NUM_ITER);
CTX_ADD(ctx, SALT_LEN);
memcpy(ctx->p, ctx->salt, SALT_LEN);
uc_p12_add_tag(ctx, ctx->p + SALT_LEN, MBEDTLS_ASN1_OCTET_STRING);
uc_p12_add_sequence(ctx, par_end);
uc_p12_add_algo(ctx, OID_TAG(PKCS12_PBE_SHA1_DES3_EDE_CBC), par_end - ctx->p);
} else {
CTX_ADD(ctx, IV_LEN);
memcpy(ctx->p, ctx->iv, IV_LEN);
uc_p12_add_tag(ctx, par_end, MBEDTLS_ASN1_OCTET_STRING);
uc_p12_add_algo(ctx, OID_TAG(AES_256_CBC), par_end - ctx->p);
kdf_end = ctx->p;
uc_p12_add_algo(ctx, OID_TAG(HMAC_SHA256), 0);
mbedtls_asn1_write_int(&ctx->p, ctx->start, NUM_ITER);
CTX_ADD(ctx, SALT_LEN);
memcpy(ctx->p, ctx->salt, SALT_LEN);
uc_p12_add_tag(ctx, ctx->p + SALT_LEN, MBEDTLS_ASN1_OCTET_STRING);
uc_p12_add_sequence(ctx, kdf_end);
uc_p12_add_algo(ctx, OID_TAG(PKCS5_PBKDF2), kdf_end - ctx->p);
uc_p12_add_sequence(ctx, par_end);
uc_p12_add_algo(ctx, OID_TAG(PKCS5_PBES2), par_end - ctx->p);
}
return 0;
}
static int
uc_p12_add_cert(struct pkcs12_ctx *ctx, uc_value_t *arg, bool ca)
{
const char *str = ucv_string_get(arg), *str_end;
uint8_t *bag_end, *end;
size_t len;
int ret;
#define START_TAG "-----BEGIN CERTIFICATE-----"
#define END_TAG "-----END CERTIFICATE-----"
if (!str)
return -1;
str = strstr(str, START_TAG);
if (!str)
return -1;
str += sizeof(START_TAG);
str_end = strstr(str, END_TAG);
if (!str_end)
return -1;
if ((size_t)(str_end - str) > sizeof(buf) / 2)
return -1;
ret = mbedtls_base64_decode((void *)buf, sizeof(buf) / 2, &len,
(const void *)str, str_end - str);
if (ret)
return ret;
bag_end = ctx->p;
if (!ca && ctx->key_cert_hash) {
mbedtls_sha1((const void *)buf, len, ctx->key_cert_hash);
uc_p12_add_localkeyid(ctx, false);
uc_p12_add_tag(ctx, bag_end, SET_TAG);
}
end = ctx->p;
CTX_ADD(ctx, len);
memcpy(ctx->p, buf, len);
uc_p12_add_tag(ctx, end, MBEDTLS_ASN1_OCTET_STRING);
/* CertBag */
uc_p12_add_tag(ctx, end, CONTEXT_TAG(0));
mbedtls_asn1_write_oid(&ctx->p, ctx->start, OID_TAG(PKCS9_CERT_TYPE_X509));
uc_p12_add_sequence(ctx, end);
uc_p12_add_bag(ctx, end, bag_end, OID_TAG(PKCS12_CERT_BAG));
return 0;
}
static int
uc_p12_add_key(struct pkcs12_ctx *ctx, uc_value_t *arg)
{
mbedtls_pk_context *pk = ucv_resource_data(arg, "mbedtls.pk");
uint8_t *bag_end, *end;
uint8_t *param = NULL;
size_t param_len = 0;
const char *oid;
size_t oid_len = 0;
int ret, len;
if (!pk)
return -1;
bag_end = ctx->p;
uc_p12_add_localkeyid(ctx, true);
uc_p12_add_tag(ctx, bag_end, SET_TAG);
end = ctx->p;
len = mbedtls_pk_write_key_der(pk, (void *)ctx->start, end - ctx->start);
if (len < 0)
return len;
ctx->p -= len;
/* Convert EC key contents to PKCS#8 style */
if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_ECKEY) {
mbedtls_ecp_group_id grp_id;
mbedtls_asn1_buf tag_buf;
uint8_t *pkey_start, *pkey_end;
size_t seq_len, pkey_len, param_tag_len;
uint8_t *p = ctx->p;
uint8_t *_end = end;
uint8_t *_start;
int version;
ret = mbedtls_asn1_get_tag(&p, end, &seq_len, SEQUENCE_TAG);
if (ret < 0)
return ret;
_start = p;
_end = p + seq_len;
ret = mbedtls_asn1_get_int(&p, _end, &version);
if (ret < 0)
return ret;
/* private key */
ret = mbedtls_asn1_get_tag(&p, _end, &pkey_len, MBEDTLS_ASN1_OCTET_STRING);
if (ret < 0)
return ret;
pkey_start = p;
p += pkey_len;
pkey_end = p;
/* parameters */
ret = mbedtls_asn1_get_tag(&p, _end, &param_len, CONTEXT_TAG(0));
if (ret < 0)
return ret;
param = memcpy(buf, p, param_len);
p += param_len;
/* overwrite parameters */
param_tag_len = p - pkey_end;
ctx->p += param_tag_len;
_start += param_tag_len;
memmove(ctx->p, ctx->p - param_tag_len, p - ctx->p);
/* replace sequence tag */
ctx->p = _start;
uc_p12_add_sequence(ctx, end);
/* check for Curve25519 or Curve448 */
tag_buf = (mbedtls_asn1_buf){
.p = (uint8_t *)buf,
.len = param_len,
};
tag_buf.tag = *tag_buf.p;
ret = mbedtls_asn1_get_tag(&tag_buf.p, tag_buf.p + param_len, &tag_buf.len, tag_buf.tag);
if (ret < 0)
return ret;
oid = MBEDTLS_OID_EC_ALG_UNRESTRICTED;
oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_ALG_UNRESTRICTED);
#ifdef MBEDTLS_LEGACY
(void)pkey_start;
(void)grp_id;
#else
ret = mbedtls_oid_get_ec_grp_algid(&tag_buf, &grp_id);
if (!ret && (grp_id == MBEDTLS_ECP_DP_CURVE25519 ||
grp_id == MBEDTLS_ECP_DP_CURVE448)) {
ctx->p = end - pkey_len;
memmove(ctx->p, pkey_start, pkey_len);
uc_p12_add_tag(ctx, end, MBEDTLS_ASN1_OCTET_STRING);
}
#endif
} else {
mbedtls_oid_get_oid_by_pk_alg(mbedtls_pk_get_type(pk), &oid, &oid_len);
}
uc_p12_add_tag(ctx, end, MBEDTLS_ASN1_OCTET_STRING);
/* KeyBag */
if (param_len) {
CTX_ADD(ctx, param_len);
memcpy(ctx->p, param, param_len);
}
uc_p12_add_algo(ctx, oid, oid_len, param_len);
mbedtls_asn1_write_int(&ctx->p, ctx->start, 0);
uc_p12_add_sequence(ctx, end);
ret = uc_p12_encrypt(ctx, end);
if (ret < 0)
return ret;
ret = uc_p12_add_enc_params(ctx);
if (ret < 0)
return ret;
uc_p12_add_sequence(ctx, end);
uc_p12_add_bag(ctx, end, bag_end, OID_TAG(PKCS12_SHROUDED_KEY_BAG));
return 0;
}
static int
uc_p12_add_authsafe(struct pkcs12_ctx *ctx, uc_value_t *arg)
{
uc_value_t *extra;
uint8_t *end = ctx->p;
size_t len;
int ret;
/* authSafe contents */
extra = ucv_object_get(arg, "extra", NULL);
if (extra) {
size_t len;
if (ucv_type(extra) != UC_ARRAY)
return -1;
len = ucv_array_length(extra);
for (size_t i = 0; i < len; i++) {
ret = uc_p12_add_cert(ctx, ucv_array_get(extra, i), true);
if (ret < 0)
return ret;
}
}
ret = uc_p12_add_key(ctx, ucv_object_get(arg, "key", NULL));
if (ret < 0)
return ret;
ret = uc_p12_add_cert(ctx, ucv_object_get(arg, "cert", NULL), false);
if (ret < 0)
return ret;
/* encrypted */
uc_p12_add_sequence(ctx, end);
ret = uc_p12_encrypt(ctx, end);
if (ret < 0)
return ret;
uc_p12_add_tag(ctx, end, CONTEXT_TAG(0));
ret = uc_p12_add_enc_params(ctx);
if (ret < 0)
return ret;
mbedtls_asn1_write_oid(&ctx->p, ctx->start, OID_TAG(PKCS7_DATA));
uc_p12_add_sequence(ctx, end);
mbedtls_asn1_write_int(&ctx->p, ctx->start, 0);
uc_p12_add_sequence(ctx, end);
uc_p12_add_tag(ctx, end, CONTEXT_TAG(0));
mbedtls_asn1_write_oid(&ctx->p, ctx->start, OID_TAG(PKCS7_ENCRYPTED_DATA));
uc_p12_add_sequence(ctx, end);
/* authSafe contents */
uc_p12_add_sequence(ctx, end);
/* authSafe header */
len = end - ctx->p;
uc_p12_add_tag(ctx, end, MBEDTLS_ASN1_OCTET_STRING);
uc_p12_add_tag(ctx, end, CONTEXT_TAG(0));
mbedtls_asn1_write_oid(&ctx->p, ctx->start, OID_TAG(PKCS7_DATA));
uc_p12_add_sequence(ctx, end);
return len;
}
static void *
uc_p12_add_mac_digest_info(struct pkcs12_ctx *ctx)
{
uint8_t *end = ctx->p;
size_t len = 20;
ctx->p -= len;
uc_p12_add_tag(ctx, end, MBEDTLS_ASN1_OCTET_STRING);
uc_p12_add_algo(ctx, OID_TAG(DIGEST_ALG_SHA1), 0);
uc_p12_add_sequence(ctx, end);
return end - len;
}
uc_value_t *uc_generate_pkcs12(uc_vm_t *vm, size_t nargs)
{
uc_value_t *arg = uc_fn_arg(0), *pwd_arg;
mbedtls_md_context_t hmac;
uint8_t *end = (uint8_t *)&buf[sizeof(buf)];
struct pkcs12_ctx ctx = {
.start = (uint8_t *)&buf[sizeof(buf) / 2],
.p = end,
};
uint8_t *hash, *data;
uint8_t key[20], *salt;
size_t salt_len = 8;
int data_len;
uc_value_t *ret = NULL;
const char *passwd;
if (ucv_type(arg) != UC_OBJECT)
INVALID_ARG();
ctx.legacy = ucv_is_truish(ucv_object_get(arg, "legacy", NULL));
mbedtls_md_init(&hmac);
pwd_arg = ucv_object_get(arg, "password", NULL);
passwd = ucv_string_get(pwd_arg);
if (!passwd)
INVALID_ARG();
/* password is expected to be a UTF-16 string */
ctx.password = passwd;
ctx.pwd_len = 2 * strlen(passwd) + 2;
ctx.pwd = malloc(ctx.pwd_len);
for (size_t i = 0; i < ctx.pwd_len; i += 2) {
ctx.pwd[i] = 0;
ctx.pwd[i + 1] = passwd[i / 2];
}
/* MacData */
mbedtls_asn1_write_int(&ctx.p, ctx.start, NUM_ITER);
ctx.p -= salt_len;
salt = ctx.p;
random_cb(NULL, salt, salt_len);
uc_p12_add_tag(&ctx, salt + salt_len, MBEDTLS_ASN1_OCTET_STRING);
hash = uc_p12_add_mac_digest_info(&ctx);
uc_p12_add_sequence(&ctx, end);
data = ctx.p;
data_len = uc_p12_add_authsafe(&ctx, arg);
if (C(data_len) < 0)
goto out;
data -= data_len;
mbedtls_asn1_write_int(&ctx.p, ctx.start, 3);
uc_p12_add_sequence(&ctx, end);
if (C(mbedtls_pkcs12_derivation(key, sizeof(key), ctx.pwd, ctx.pwd_len,
salt, salt_len, MBEDTLS_MD_SHA1,
MBEDTLS_PKCS12_DERIVE_MAC_KEY, NUM_ITER)))
goto out;
if (C(mbedtls_md_setup(&hmac, mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), 1)))
goto out;
if (C(mbedtls_md_hmac_starts(&hmac, key, sizeof(key))))
goto out;
if (C(mbedtls_md_hmac_update(&hmac, data, data_len)))
goto out;
if (C(mbedtls_md_hmac_finish(&hmac, hash)))
goto out;
ret = ucv_string_new_length((char *)ctx.p, end - ctx.p);
out:
free(ctx.pwd);
mbedtls_md_free(&hmac);
return ret;
}

View File

@ -0,0 +1,598 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2024 Felix Fietkau <nbd@nbd.name>
*/
#include <sys/types.h>
#include <sys/random.h>
#include <stdint.h>
#include <limits.h>
#include <errno.h>
#include <mbedtls/entropy.h>
#include <mbedtls/x509_crt.h>
#include <mbedtls/ecp.h>
#include <mbedtls/rsa.h>
#include <ucode/module.h>
#include "pk.h"
/* mbedtls < 3.x compat */
#ifdef MBEDTLS_LEGACY
#define mbedtls_pk_parse_key(pk, key, keylen, passwd, passwdlen, random, random_ctx) \
mbedtls_pk_parse_key(pk, key, keylen, passwd, passwdlen)
#endif
static uc_resource_type_t *uc_pk_type, *uc_crt_type;
static uc_value_t *registry;
char buf[32 * 1024];
int mbedtls_errno;
struct uc_cert_wr {
mbedtls_x509write_cert crt; /* must be first */
mbedtls_mpi mpi;
unsigned int reg;
};
static unsigned int uc_reg_add(uc_value_t *val)
{
size_t i = 0;
while (ucv_array_get(registry, i))
i++;
ucv_array_set(registry, i, ucv_get(val));
return i;
}
int random_cb(void *ctx, unsigned char *out, size_t len)
{
#ifdef linux
if (getrandom(out, len, 0) != (ssize_t) len)
return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
#else
static FILE *f;
if (!f)
f = fopen("/dev/urandom", "r");
if (fread(out, len, 1, f) != 1)
return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
#endif
return 0;
}
int64_t get_int_arg(uc_value_t *obj, const char *key, int64_t defval)
{
uc_value_t *uval = ucv_object_get(obj, key, NULL);
int64_t val;
if (!uval)
return defval;
val = ucv_int64_get(uval);
if (errno || val < 0 || val > INT_MAX)
return INT_MIN;
return val ? val : defval;
}
static int
gen_rsa_key(mbedtls_pk_context *pk, uc_value_t *arg)
{
int64_t key_size, exp;
key_size = get_int_arg(arg, "size", 2048);
exp = get_int_arg(arg, "exponent", 65537);
if (key_size < 0 || exp < 0)
return -1;
return mbedtls_rsa_gen_key(mbedtls_pk_rsa(*pk), random_cb, NULL, key_size, exp);
}
static int
gen_ec_key(mbedtls_pk_context *pk, uc_value_t *arg)
{
mbedtls_ecp_group_id curve;
const char *c_name;
uc_value_t *c_arg;
c_arg = ucv_object_get(arg, "curve", NULL);
if (c_arg && ucv_type(c_arg) != UC_STRING)
return -1;
c_name = ucv_string_get(c_arg);
if (!c_name)
curve = MBEDTLS_ECP_DP_SECP256R1;
else {
const mbedtls_ecp_curve_info *curve_info;
curve_info = mbedtls_ecp_curve_info_from_name(c_name);
if (!curve_info)
return MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE;
curve = curve_info->grp_id;
}
return mbedtls_ecp_gen_key(curve, mbedtls_pk_ec(*pk), random_cb, NULL);
}
static void free_pk(void *pk)
{
if (!pk)
return;
mbedtls_pk_free(pk);
free(pk);
}
static void free_crt(void *ptr)
{
struct uc_cert_wr *crt = ptr;
if (!crt)
return;
mbedtls_x509write_crt_free(&crt->crt);
mbedtls_mpi_free(&crt->mpi);
ucv_array_set(registry, crt->reg, NULL);
free(crt);
}
static uc_value_t *
uc_generate_key(uc_vm_t *vm, size_t nargs)
{
uc_value_t *cur, *arg = uc_fn_arg(0);
mbedtls_pk_type_t pk_type;
mbedtls_pk_context *pk;
const char *type;
int ret;
if (ucv_type(arg) != UC_OBJECT)
INVALID_ARG();
cur = ucv_object_get(arg, "type", NULL);
type = ucv_string_get(cur);
if (!type)
INVALID_ARG();
if (!strcmp(type, "rsa"))
pk_type = MBEDTLS_PK_RSA;
else if (!strcmp(type, "ec"))
pk_type = MBEDTLS_PK_ECKEY;
else
INVALID_ARG();
pk = calloc(1, sizeof(*pk));
mbedtls_pk_init(pk);
mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(pk_type));
switch (pk_type) {
case MBEDTLS_PK_RSA:
ret = C(gen_rsa_key(pk, arg));
break;
case MBEDTLS_PK_ECKEY:
ret = C(gen_ec_key(pk, arg));
break;
default:
ret = -1;
}
if (ret) {
free_pk(pk);
return NULL;
}
return uc_resource_new(uc_pk_type, pk);
}
static uc_value_t *
uc_load_key(uc_vm_t *vm, size_t nargs)
{
uc_value_t *keystr = uc_fn_arg(0);
uc_value_t *pub = uc_fn_arg(1);
uc_value_t *passwd = uc_fn_arg(2);
mbedtls_pk_context *pk;
int ret;
if (ucv_type(keystr) != UC_STRING ||
(pub && ucv_type(pub) != UC_BOOLEAN) ||
(passwd && ucv_type(passwd) != UC_STRING))
INVALID_ARG();
pk = calloc(1, sizeof(*pk));
mbedtls_pk_init(pk);
if (ucv_is_truish(pub))
ret = C(mbedtls_pk_parse_public_key(pk, (const uint8_t *)ucv_string_get(keystr),
ucv_string_length(keystr) + 1));
else
ret = C(mbedtls_pk_parse_key(pk, (const uint8_t *)ucv_string_get(keystr),
ucv_string_length(keystr) + 1,
(const uint8_t *)ucv_string_get(passwd),
ucv_string_length(passwd) + 1,
random_cb, NULL));
if (ret) {
free_pk(pk);
return NULL;
}
return uc_resource_new(uc_pk_type, pk);
}
static void
uc_cert_info_add(uc_value_t *info, const char *name, int len)
{
uc_value_t *val;
if (len < 0)
return;
val = ucv_string_new_length(buf, len);
ucv_object_add(info, name, ucv_get(val));
}
static void
uc_cert_info_add_name(uc_value_t *info, const char *name, mbedtls_x509_name *dn)
{
int len;
len = mbedtls_x509_dn_gets(buf, sizeof(buf), dn);
uc_cert_info_add(info, name, len);
}
static void
uc_cert_info_add_time(uc_value_t *info, const char *name, mbedtls_x509_time *t)
{
int len;
len = snprintf(buf, sizeof(buf), "%04d%02d%02d%02d%02d%02d",
t->year, t->mon, t->day, t->hour, t->min, t->sec);
uc_cert_info_add(info, name, len);
}
static uc_value_t *
uc_cert_info(uc_vm_t *vm, size_t nargs)
{
uc_value_t *arg = uc_fn_arg(0);
mbedtls_x509_crt crt, *cur;
uc_value_t *ret = NULL;
if (ucv_type(arg) != UC_STRING)
return NULL;
mbedtls_x509_crt_init(&crt);
if (C(mbedtls_x509_crt_parse(&crt, (const void *)ucv_string_get(arg), ucv_string_length(arg) + 1)) < 0)
goto out;
ret = ucv_array_new(vm);
for (cur = &crt; cur && cur->version != 0; cur = cur->next) {
uc_value_t *info = ucv_object_new(vm);
int len;
ucv_array_push(ret, ucv_get(info));
ucv_object_add(info, "version", ucv_int64_new(cur->version));
uc_cert_info_add_name(info, "issuer", &cur->issuer);
uc_cert_info_add_name(info, "subject", &cur->issuer);
uc_cert_info_add_time(info, "valid_from", &cur->valid_from);
uc_cert_info_add_time(info, "valid_to", &cur->valid_to);
len = mbedtls_x509_serial_gets(buf, sizeof(buf), &cur->serial);
uc_cert_info_add(info, "serial", len);
}
out:
mbedtls_x509_crt_free(&crt);
return ret;
}
static uc_value_t *
uc_pk_pem(uc_vm_t *vm, size_t nargs)
{
mbedtls_pk_context *pk = uc_fn_thisval("mbedtls.pk");
uc_value_t *pub = uc_fn_arg(0);
if (!pk)
return NULL;
if (ucv_is_truish(pub))
CHECK(mbedtls_pk_write_pubkey_pem(pk, (void *)buf, sizeof(buf)));
else
CHECK(mbedtls_pk_write_key_pem(pk, (void *)buf, sizeof(buf)));
return ucv_string_new(buf);
}
static uc_value_t *
uc_pk_der(uc_vm_t *vm, size_t nargs)
{
mbedtls_pk_context *pk = uc_fn_thisval("mbedtls.pk");
uc_value_t *pub = uc_fn_arg(0);
int len;
if (!pk)
return NULL;
if (ucv_is_truish(pub))
len = mbedtls_pk_write_pubkey_der(pk, (void *)buf, sizeof(buf));
else
len = mbedtls_pk_write_key_der(pk, (void *)buf, sizeof(buf));
if (len < 0)
CHECK(len);
return ucv_string_new_length(buf + sizeof(buf) - len, len);
}
static uc_value_t *
uc_crt_pem(uc_vm_t *vm, size_t nargs)
{
mbedtls_x509write_cert *crt = uc_fn_thisval("mbedtls.crt");
if (!crt)
return NULL;
CHECK(mbedtls_x509write_crt_pem(crt, (void *)buf, sizeof(buf), random_cb, NULL));
return ucv_string_new(buf);
}
static uc_value_t *
uc_crt_der(uc_vm_t *vm, size_t nargs)
{
mbedtls_x509write_cert *crt = uc_fn_thisval("mbedtls.crt");
int len;
if (!crt)
return NULL;
len = mbedtls_x509write_crt_der(crt, (void *)buf, sizeof(buf), random_cb, NULL);
if (len < 0)
CHECK(len);
return ucv_string_new_length(buf, len);
}
static int
uc_cert_set_validity(mbedtls_x509write_cert *crt, uc_value_t *arg)
{
uc_value_t *from = ucv_array_get(arg, 0);
uc_value_t *to = ucv_array_get(arg, 1);
if (ucv_type(from) != UC_STRING || ucv_type(to) != UC_STRING)
return -1;
return mbedtls_x509write_crt_set_validity(crt, ucv_string_get(from), ucv_string_get(to));
}
static int
uc_cert_init(mbedtls_x509write_cert *crt, mbedtls_mpi *mpi, uc_value_t *reg, uc_value_t *arg)
{
uc_value_t *cur;
int64_t serial;
int path_len;
int version;
bool ca;
mbedtls_mpi_init(mpi);
mbedtls_x509write_crt_init(crt);
mbedtls_x509write_crt_set_md_alg(crt, MBEDTLS_MD_SHA256);
ca = ucv_is_truish(ucv_object_get(arg, "ca", NULL));
path_len = get_int_arg(arg, "max_pathlen", ca ? -1 : 0);
if (path_len < -1)
return -1;
version = get_int_arg(arg, "version", 3);
if (version < 0 || version > 3)
return -1;
serial = get_int_arg(arg, "serial", 1);
if (serial < 0)
return -1;
mbedtls_mpi_lset(mpi, serial);
mbedtls_x509write_crt_set_serial(crt, mpi);
mbedtls_x509write_crt_set_version(crt, version - 1);
CHECK_INT(mbedtls_x509write_crt_set_basic_constraints(crt, ca, path_len));
cur = ucv_object_get(arg, "subject_name", NULL);
if (ucv_type(cur) == UC_STRING)
CHECK_INT(mbedtls_x509write_crt_set_subject_name(crt, ucv_string_get(cur)));
else
return -1;
cur = ucv_object_get(arg, "subject_key", NULL);
if (cur) {
mbedtls_pk_context *key = ucv_resource_data(cur, "mbedtls.pk");
if (!key)
return -1;
ucv_array_set(reg, 0, ucv_get(cur));
mbedtls_x509write_crt_set_subject_key(crt, key);
mbedtls_x509write_crt_set_subject_key_identifier(crt);
} else
return -1;
cur = ucv_object_get(arg, "issuer_name", NULL);
if (ucv_type(cur) == UC_STRING)
CHECK_INT(mbedtls_x509write_crt_set_issuer_name(crt, ucv_string_get(cur)));
else
return -1;
cur = ucv_object_get(arg, "issuer_key", NULL);
if (cur) {
mbedtls_pk_context *key = ucv_resource_data(cur, "mbedtls.pk");
if (!key)
return -1;
ucv_array_set(reg, 1, ucv_get(cur));
mbedtls_x509write_crt_set_issuer_key(crt, key);
mbedtls_x509write_crt_set_authority_key_identifier(crt);
} else
return -1;
cur = ucv_object_get(arg, "validity", NULL);
if (ucv_type(cur) != UC_ARRAY || ucv_array_length(cur) != 2)
return -1;
if (uc_cert_set_validity(crt, cur))
return -1;
cur = ucv_object_get(arg, "key_usage", NULL);
if (ucv_type(cur) == UC_ARRAY) {
static const struct {
const char *name;
uint8_t val;
} key_flags[] = {
{ "digital_signature", MBEDTLS_X509_KU_DIGITAL_SIGNATURE },
{ "non_repudiation", MBEDTLS_X509_KU_NON_REPUDIATION },
{ "key_encipherment", MBEDTLS_X509_KU_KEY_ENCIPHERMENT },
{ "data_encipherment", MBEDTLS_X509_KU_DATA_ENCIPHERMENT },
{ "key_agreement", MBEDTLS_X509_KU_KEY_AGREEMENT },
{ "key_cert_sign", MBEDTLS_X509_KU_KEY_CERT_SIGN },
{ "crl_sign", MBEDTLS_X509_KU_CRL_SIGN },
};
uint8_t key_usage = 0;
size_t len = ucv_array_length(cur);
for (size_t i = 0; i < len; i++) {
uc_value_t *val = ucv_array_get(cur, i);
const char *str;
size_t k;
str = ucv_string_get(val);
if (!str)
return -1;
for (k = 0; k < ARRAY_SIZE(key_flags); k++)
if (!strcmp(str, key_flags[k].name))
break;
if (k == ARRAY_SIZE(key_flags))
return -1;
key_usage |= key_flags[k].val;
}
CHECK_INT(mbedtls_x509write_crt_set_key_usage(crt, key_usage));
} else if (cur)
return -1;
#ifndef MBEDTLS_LEGACY
cur = ucv_object_get(arg, "ext_key_usage", NULL);
if (ucv_type(cur) == UC_ARRAY && ucv_array_length(cur)) {
static const struct {
const char *name;
struct mbedtls_asn1_buf val;
} key_flags[] = {
#define __oid(name, val) \
{ \
name, \
{ \
.tag = MBEDTLS_ASN1_OID, \
.len = sizeof(MBEDTLS_OID_##val), \
.p = (uint8_t *)MBEDTLS_OID_##val, \
} \
}
__oid("server_auth", SERVER_AUTH),
__oid("client_auth", CLIENT_AUTH),
__oid("code_signing", CODE_SIGNING),
__oid("email_protection", EMAIL_PROTECTION),
__oid("time_stamping", TIME_STAMPING),
__oid("ocsp_signing", OCSP_SIGNING),
__oid("any", ANY_EXTENDED_KEY_USAGE)
};
struct mbedtls_asn1_sequence *elem;
size_t len = ucv_array_length(cur);
elem = calloc(len, sizeof(*elem));
for (size_t i = 0; i < len; i++) {
uc_value_t *val = ucv_array_get(cur, i);
const char *str;
size_t k;
str = ucv_string_get(val);
if (!str)
return -1;
for (k = 0; k < ARRAY_SIZE(key_flags); k++)
if (!strcmp(str, key_flags[k].name))
break;
if (k == ARRAY_SIZE(key_flags)) {
free(elem);
return -1;
}
elem[i].buf = key_flags[k].val;
if (i + 1 < len)
elem[i].next = &elem[i + 1];
}
CHECK_INT(mbedtls_x509write_crt_set_ext_key_usage(crt, elem));
} else if (cur)
return -1;
#endif
return 0;
}
static uc_value_t *
uc_generate_cert(uc_vm_t *vm, size_t nargs)
{
struct uc_cert_wr *crt;
uc_value_t *arg = uc_fn_arg(0);
uc_value_t *reg;
if (ucv_type(arg) != UC_OBJECT)
return NULL;
reg = ucv_array_new(vm);
crt = calloc(1, sizeof(*crt));
if (C(uc_cert_init(&crt->crt, &crt->mpi, reg, arg))) {
free(crt);
return NULL;
}
crt->reg = uc_reg_add(reg);
return uc_resource_new(uc_crt_type, crt);
}
static uc_value_t *
uc_mbedtls_error(uc_vm_t *vm, size_t nargs)
{
mbedtls_strerror(mbedtls_errno, buf, sizeof(buf));
return ucv_string_new(buf);
}
static uc_value_t *
uc_mbedtls_errno(uc_vm_t *vm, size_t nargs)
{
return ucv_int64_new(mbedtls_errno);
}
static const uc_function_list_t pk_fns[] = {
{ "pem", uc_pk_pem },
{ "der", uc_pk_der },
};
static const uc_function_list_t crt_fns[] = {
{ "pem", uc_crt_pem },
{ "der", uc_crt_der },
};
static const uc_function_list_t global_fns[] = {
{ "load_key", uc_load_key },
{ "cert_info", uc_cert_info },
{ "generate_key", uc_generate_key },
{ "generate_cert", uc_generate_cert },
{ "generate_pkcs12", uc_generate_pkcs12 },
{ "errno", uc_mbedtls_errno },
{ "error", uc_mbedtls_error },
};
void uc_module_init(uc_vm_t *vm, uc_value_t *scope)
{
uc_pk_type = uc_type_declare(vm, "mbedtls.pk", pk_fns, free_pk);
uc_crt_type = uc_type_declare(vm, "mbedtls.crt", crt_fns, free_crt);
uc_function_list_register(scope, global_fns);
registry = ucv_array_new(vm);
uc_vm_registry_set(vm, "pkgen.registry", registry);
}

View File

@ -0,0 +1,53 @@
From b56e4d660a9688ff83f5cbdc6e3ea063352d0d79 Mon Sep 17 00:00:00 2001
From: Lorenzo Bianconi <lorenzo@kernel.org>
Date: Sun, 12 Jan 2025 19:32:45 +0100
Subject: [PATCH] net: airoha: Enforce ETS Qdisc priomap
EN7581 SoC supports fixed QoS band priority where WRR queues have lowest
priorities with respect to SP ones.
E.g: WRR0, WRR1, .., WRRm, SP0, SP1, .., SPn
Enforce ETS Qdisc priomap according to the hw capabilities.
Suggested-by: Davide Caratti <dcaratti@redhat.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Reviewed-by: Davide Caratti <dcaratti@redhat.com>
Link: https://patch.msgid.link/20250112-airoha_ets_priomap-v1-1-fb616de159ba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/mediatek/airoha_eth.c | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
@@ -2786,7 +2786,7 @@ static int airoha_qdma_set_tx_ets_sched(
struct tc_ets_qopt_offload_replace_params *p = &opt->replace_params;
enum tx_sched_mode mode = TC_SCH_SP;
u16 w[AIROHA_NUM_QOS_QUEUES] = {};
- int i, nstrict = 0;
+ int i, nstrict = 0, nwrr, qidx;
if (p->bands > AIROHA_NUM_QOS_QUEUES)
return -EINVAL;
@@ -2800,7 +2800,20 @@ static int airoha_qdma_set_tx_ets_sched(
if (nstrict == AIROHA_NUM_QOS_QUEUES - 1)
return -EINVAL;
- for (i = 0; i < p->bands - nstrict; i++)
+ /* EN7581 SoC supports fixed QoS band priority where WRR queues have
+ * lowest priorities with respect to SP ones.
+ * e.g: WRR0, WRR1, .., WRRm, SP0, SP1, .., SPn
+ */
+ nwrr = p->bands - nstrict;
+ qidx = nstrict && nwrr ? nstrict : 0;
+ for (i = 1; i <= p->bands; i++) {
+ if (p->priomap[i % AIROHA_NUM_QOS_QUEUES] != qidx)
+ return -EINVAL;
+
+ qidx = i == nwrr ? 0 : qidx + 1;
+ }
+
+ for (i = 0; i < nwrr; i++)
w[i] = p->weights[nstrict + i];
if (!nstrict)

View File

@ -86,7 +86,7 @@ Best regards,
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
@@ -2833,11 +2833,14 @@ static int airoha_qdma_get_tx_ets_stats(
@@ -2846,11 +2846,14 @@ static int airoha_qdma_get_tx_ets_stats(
static int airoha_tc_setup_qdisc_ets(struct airoha_gdm_port *port,
struct tc_ets_qopt_offload *opt)
{

View File

@ -0,0 +1,58 @@
From 0e7a622da17da0042294860cdb7a2fac091d25b1 Mon Sep 17 00:00:00 2001
Message-ID: <0e7a622da17da0042294860cdb7a2fac091d25b1.1736960708.git.lorenzo@kernel.org>
From: Lorenzo Bianconi <lorenzo@kernel.org>
Date: Wed, 8 Jan 2025 10:50:40 +0100
Subject: [PATCH 1/6] PCI: mediatek-gen3: Rely on clk_bulk_prepare_enable() in
mtk_pcie_en7581_power_up()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Replace clk_bulk_prepare() and clk_bulk_enable() with
clk_bulk_prepare_enable() in mtk_pcie_en7581_power_up() routine.
Link: https://lore.kernel.org/r/20250108-pcie-en7581-fixes-v6-1-21ac939a3b9b@kernel.org
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
---
drivers/pci/controller/pcie-mediatek-gen3.c | 14 +++-----------
1 file changed, 3 insertions(+), 11 deletions(-)
--- a/drivers/pci/controller/pcie-mediatek-gen3.c
+++ b/drivers/pci/controller/pcie-mediatek-gen3.c
@@ -907,12 +907,6 @@ static int mtk_pcie_en7581_power_up(stru
pm_runtime_enable(dev);
pm_runtime_get_sync(dev);
- err = clk_bulk_prepare(pcie->num_clks, pcie->clks);
- if (err) {
- dev_err(dev, "failed to prepare clock\n");
- goto err_clk_prepare;
- }
-
val = FIELD_PREP(PCIE_VAL_LN0_DOWNSTREAM, 0x47) |
FIELD_PREP(PCIE_VAL_LN1_DOWNSTREAM, 0x47) |
FIELD_PREP(PCIE_VAL_LN0_UPSTREAM, 0x41) |
@@ -925,17 +919,15 @@ static int mtk_pcie_en7581_power_up(stru
FIELD_PREP(PCIE_K_FINETUNE_MAX, 0xf);
writel_relaxed(val, pcie->base + PCIE_PIPE4_PIE8_REG);
- err = clk_bulk_enable(pcie->num_clks, pcie->clks);
+ err = clk_bulk_prepare_enable(pcie->num_clks, pcie->clks);
if (err) {
dev_err(dev, "failed to prepare clock\n");
- goto err_clk_enable;
+ goto err_clk_prepare_enable;
}
return 0;
-err_clk_enable:
- clk_bulk_unprepare(pcie->num_clks, pcie->clks);
-err_clk_prepare:
+err_clk_prepare_enable:
pm_runtime_put_sync(dev);
pm_runtime_disable(dev);
reset_control_bulk_assert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);

View File

@ -0,0 +1,89 @@
From e4c7dfd953f7618f0ccb70d87c1629634f306fab Mon Sep 17 00:00:00 2001
Message-ID: <e4c7dfd953f7618f0ccb70d87c1629634f306fab.1736960708.git.lorenzo@kernel.org>
In-Reply-To: <0e7a622da17da0042294860cdb7a2fac091d25b1.1736960708.git.lorenzo@kernel.org>
References: <0e7a622da17da0042294860cdb7a2fac091d25b1.1736960708.git.lorenzo@kernel.org>
From: Lorenzo Bianconi <lorenzo@kernel.org>
Date: Wed, 8 Jan 2025 10:50:41 +0100
Subject: [PATCH 2/6] PCI: mediatek-gen3: Move reset/assert callbacks in
.power_up()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
In order to make the code more readable, the reset_control_bulk_assert()
function for PHY reset lines is moved to make it pair with
reset_control_bulk_deassert() in mtk_pcie_power_up() and
mtk_pcie_en7581_power_up(). The same change is done for
reset_control_assert() used to assert MAC reset line.
Introduce PCIE_MTK_RESET_TIME_US macro for the time needed to
complete PCIe reset on MediaTek controller.
Link: https://lore.kernel.org/r/20250108-pcie-en7581-fixes-v6-2-21ac939a3b9b@kernel.org
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
---
drivers/pci/controller/pcie-mediatek-gen3.c | 28 +++++++++++++--------
1 file changed, 18 insertions(+), 10 deletions(-)
--- a/drivers/pci/controller/pcie-mediatek-gen3.c
+++ b/drivers/pci/controller/pcie-mediatek-gen3.c
@@ -120,6 +120,8 @@
#define MAX_NUM_PHY_RESETS 3
+#define PCIE_MTK_RESET_TIME_US 10
+
/* Time in ms needed to complete PCIe reset on EN7581 SoC */
#define PCIE_EN7581_RESET_TIME_MS 100
@@ -875,9 +877,14 @@ static int mtk_pcie_en7581_power_up(stru
u32 val;
/*
- * Wait for the time needed to complete the bulk assert in
- * mtk_pcie_setup for EN7581 SoC.
+ * The controller may have been left out of reset by the bootloader
+ * so make sure that we get a clean start by asserting resets here.
*/
+ reset_control_bulk_assert(pcie->soc->phy_resets.num_resets,
+ pcie->phy_resets);
+ reset_control_assert(pcie->mac_reset);
+
+ /* Wait for the time needed to complete the reset lines assert. */
mdelay(PCIE_EN7581_RESET_TIME_MS);
err = phy_init(pcie->phy);
@@ -944,6 +951,15 @@ static int mtk_pcie_power_up(struct mtk_
struct device *dev = pcie->dev;
int err;
+ /*
+ * The controller may have been left out of reset by the bootloader
+ * so make sure that we get a clean start by asserting resets here.
+ */
+ reset_control_bulk_assert(pcie->soc->phy_resets.num_resets,
+ pcie->phy_resets);
+ reset_control_assert(pcie->mac_reset);
+ usleep_range(PCIE_MTK_RESET_TIME_US, 2 * PCIE_MTK_RESET_TIME_US);
+
/* PHY power on and enable pipe clock */
err = reset_control_bulk_deassert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);
if (err) {
@@ -1016,14 +1032,6 @@ static int mtk_pcie_setup(struct mtk_gen
* counter since the bulk is shared.
*/
reset_control_bulk_deassert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);
- /*
- * The controller may have been left out of reset by the bootloader
- * so make sure that we get a clean start by asserting resets here.
- */
- reset_control_bulk_assert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);
-
- reset_control_assert(pcie->mac_reset);
- usleep_range(10, 20);
/* Don't touch the hardware registers before power up */
err = pcie->soc->power_up(pcie);

View File

@ -0,0 +1,38 @@
From 0c9d2d2ef0d916b490a9222ed20ff4616fca876d Mon Sep 17 00:00:00 2001
Message-ID: <0c9d2d2ef0d916b490a9222ed20ff4616fca876d.1736960708.git.lorenzo@kernel.org>
In-Reply-To: <0e7a622da17da0042294860cdb7a2fac091d25b1.1736960708.git.lorenzo@kernel.org>
References: <0e7a622da17da0042294860cdb7a2fac091d25b1.1736960708.git.lorenzo@kernel.org>
From: Lorenzo Bianconi <lorenzo@kernel.org>
Date: Wed, 8 Jan 2025 10:50:42 +0100
Subject: [PATCH 3/6] PCI: mediatek-gen3: Add comment about initialization
order in mtk_pcie_en7581_power_up()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Add a comment in mtk_pcie_en7581_power_up() to clarify, unlike the other
MediaTek Gen3 controllers, the Airoha EN7581 requires PHY initialization
and power-on before PHY reset deassert.
Link: https://lore.kernel.org/r/20250108-pcie-en7581-fixes-v6-3-21ac939a3b9b@kernel.org
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
drivers/pci/controller/pcie-mediatek-gen3.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/drivers/pci/controller/pcie-mediatek-gen3.c
+++ b/drivers/pci/controller/pcie-mediatek-gen3.c
@@ -887,6 +887,10 @@ static int mtk_pcie_en7581_power_up(stru
/* Wait for the time needed to complete the reset lines assert. */
mdelay(PCIE_EN7581_RESET_TIME_MS);
+ /*
+ * Unlike the other MediaTek Gen3 controllers, the Airoha EN7581
+ * requires PHY initialization and power-on before PHY reset deassert.
+ */
err = phy_init(pcie->phy);
if (err) {
dev_err(dev, "failed to initialize PHY\n");

View File

@ -0,0 +1,62 @@
From 90d4e466c9ea2010f33880a36317a8486ccbe082 Mon Sep 17 00:00:00 2001
Message-ID: <90d4e466c9ea2010f33880a36317a8486ccbe082.1736960708.git.lorenzo@kernel.org>
In-Reply-To: <0e7a622da17da0042294860cdb7a2fac091d25b1.1736960708.git.lorenzo@kernel.org>
References: <0e7a622da17da0042294860cdb7a2fac091d25b1.1736960708.git.lorenzo@kernel.org>
From: Lorenzo Bianconi <lorenzo@kernel.org>
Date: Wed, 8 Jan 2025 10:50:43 +0100
Subject: [PATCH 4/6] PCI: mediatek-gen3: Move reset delay in
mtk_pcie_en7581_power_up()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Airoha EN7581 has a hw bug asserting/releasing PCIE_PE_RSTB signal
causing occasional PCIe link down issues. In order to overcome the
problem, PCIe block is reset using REG_PCI_CONTROL (0x88) and
REG_RESET_CONTROL (0x834) registers available in the clock module
running clk_bulk_prepare_enable() in mtk_pcie_en7581_power_up().
In order to make the code more readable, move the wait for the time
needed to complete the PCIe reset from en7581_pci_enable() to
mtk_pcie_en7581_power_up().
Reduce reset timeout from 250ms to the standard PCIE_T_PVPERL_MS value
(100ms) since it has no impact on the driver behavior.
Link: https://lore.kernel.org/r/20250108-pcie-en7581-fixes-v6-4-21ac939a3b9b@kernel.org
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Acked-by: Stephen Boyd <sboyd@kernel.org>
---
drivers/clk/clk-en7523.c | 1 -
drivers/pci/controller/pcie-mediatek-gen3.c | 7 +++++++
2 files changed, 7 insertions(+), 1 deletion(-)
--- a/drivers/clk/clk-en7523.c
+++ b/drivers/clk/clk-en7523.c
@@ -489,7 +489,6 @@ static int en7581_pci_enable(struct clk_
REG_PCI_CONTROL_PERSTOUT;
val = readl(np_base + REG_PCI_CONTROL);
writel(val | mask, np_base + REG_PCI_CONTROL);
- msleep(250);
return 0;
}
--- a/drivers/pci/controller/pcie-mediatek-gen3.c
+++ b/drivers/pci/controller/pcie-mediatek-gen3.c
@@ -936,6 +936,13 @@ static int mtk_pcie_en7581_power_up(stru
goto err_clk_prepare_enable;
}
+ /*
+ * Airoha EN7581 performs PCIe reset via clk callbacks since it has a
+ * hw issue with PCIE_PE_RSTB signal. Add wait for the time needed to
+ * complete the PCIe reset.
+ */
+ msleep(PCIE_T_PVPERL_MS);
+
return 0;
err_clk_prepare_enable:

View File

@ -0,0 +1,44 @@
From c98bee18d0a094e37100c85effe5e161418f8644 Mon Sep 17 00:00:00 2001
Message-ID: <c98bee18d0a094e37100c85effe5e161418f8644.1736960708.git.lorenzo@kernel.org>
In-Reply-To: <0e7a622da17da0042294860cdb7a2fac091d25b1.1736960708.git.lorenzo@kernel.org>
References: <0e7a622da17da0042294860cdb7a2fac091d25b1.1736960708.git.lorenzo@kernel.org>
From: Lorenzo Bianconi <lorenzo@kernel.org>
Date: Wed, 8 Jan 2025 10:50:44 +0100
Subject: [PATCH 5/6] PCI: mediatek-gen3: Rely on msleep() in
mtk_pcie_en7581_power_up()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Since mtk_pcie_en7581_power_up() runs in non-atomic context, rely on
msleep() routine instead of mdelay().
Link: https://lore.kernel.org/r/20250108-pcie-en7581-fixes-v6-5-21ac939a3b9b@kernel.org
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
---
drivers/pci/controller/pcie-mediatek-gen3.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/pci/controller/pcie-mediatek-gen3.c
+++ b/drivers/pci/controller/pcie-mediatek-gen3.c
@@ -885,7 +885,7 @@ static int mtk_pcie_en7581_power_up(stru
reset_control_assert(pcie->mac_reset);
/* Wait for the time needed to complete the reset lines assert. */
- mdelay(PCIE_EN7581_RESET_TIME_MS);
+ msleep(PCIE_EN7581_RESET_TIME_MS);
/*
* Unlike the other MediaTek Gen3 controllers, the Airoha EN7581
@@ -913,7 +913,7 @@ static int mtk_pcie_en7581_power_up(stru
* Wait for the time needed to complete the bulk de-assert above.
* This time is specific for EN7581 SoC.
*/
- mdelay(PCIE_EN7581_RESET_TIME_MS);
+ msleep(PCIE_EN7581_RESET_TIME_MS);
pm_runtime_enable(dev);
pm_runtime_get_sync(dev);

View File

@ -0,0 +1,131 @@
From 491cb9c5084790aafa02e843349492c284373231 Mon Sep 17 00:00:00 2001
Message-ID: <491cb9c5084790aafa02e843349492c284373231.1736960708.git.lorenzo@kernel.org>
In-Reply-To: <0e7a622da17da0042294860cdb7a2fac091d25b1.1736960708.git.lorenzo@kernel.org>
References: <0e7a622da17da0042294860cdb7a2fac091d25b1.1736960708.git.lorenzo@kernel.org>
From: Lorenzo Bianconi <lorenzo@kernel.org>
Date: Thu, 9 Jan 2025 00:30:45 +0100
Subject: [PATCH 6/6] PCI: mediatek-gen3: Avoid PCIe resetting via PERST# for
Airoha EN7581 SoC
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Airoha EN7581 has a hw bug asserting/releasing PERST# signal causing
occasional PCIe link down issues. In order to overcome the problem,
PERST# signal is not asserted/released during device probe or
suspend/resume phase and the PCIe block is reset using
en7523_reset_assert() and en7581_pci_enable().
Introduce flags field in the mtk_gen3_pcie_pdata struct in order to
specify per-SoC capabilities.
Link: https://lore.kernel.org/r/20250109-pcie-en7581-rst-fix-v4-1-4a45c89fb143@kernel.org
Tested-by: Hui Ma <hui.ma@airoha.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
---
drivers/pci/controller/pcie-mediatek-gen3.c | 59 ++++++++++++++-------
1 file changed, 41 insertions(+), 18 deletions(-)
--- a/drivers/pci/controller/pcie-mediatek-gen3.c
+++ b/drivers/pci/controller/pcie-mediatek-gen3.c
@@ -127,10 +127,18 @@
struct mtk_gen3_pcie;
+enum mtk_gen3_pcie_flags {
+ SKIP_PCIE_RSTB = BIT(0), /* Skip PERST# assertion during device
+ * probing or suspend/resume phase to
+ * avoid hw bugs/issues.
+ */
+};
+
/**
* struct mtk_gen3_pcie_pdata - differentiate between host generations
* @power_up: pcie power_up callback
* @phy_resets: phy reset lines SoC data.
+ * @flags: pcie device flags.
*/
struct mtk_gen3_pcie_pdata {
int (*power_up)(struct mtk_gen3_pcie *pcie);
@@ -138,6 +146,7 @@ struct mtk_gen3_pcie_pdata {
const char *id[MAX_NUM_PHY_RESETS];
int num_resets;
} phy_resets;
+ u32 flags;
};
/**
@@ -404,22 +413,33 @@ static int mtk_pcie_startup_port(struct
val |= PCIE_DISABLE_DVFSRC_VLT_REQ;
writel_relaxed(val, pcie->base + PCIE_MISC_CTRL_REG);
- /* Assert all reset signals */
- val = readl_relaxed(pcie->base + PCIE_RST_CTRL_REG);
- val |= PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB | PCIE_PE_RSTB;
- writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG);
-
/*
- * Described in PCIe CEM specification sections 2.2 (PERST# Signal)
- * and 2.2.1 (Initial Power-Up (G3 to S0)).
- * The deassertion of PERST# should be delayed 100ms (TPVPERL)
- * for the power and clock to become stable.
+ * Airoha EN7581 has a hw bug asserting/releasing PCIE_PE_RSTB signal
+ * causing occasional PCIe link down. In order to overcome the issue,
+ * PCIE_RSTB signals are not asserted/released at this stage and the
+ * PCIe block is reset using en7523_reset_assert() and
+ * en7581_pci_enable().
*/
- msleep(100);
-
- /* De-assert reset signals */
- val &= ~(PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB | PCIE_PE_RSTB);
- writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG);
+ if (!(pcie->soc->flags & SKIP_PCIE_RSTB)) {
+ /* Assert all reset signals */
+ val = readl_relaxed(pcie->base + PCIE_RST_CTRL_REG);
+ val |= PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB |
+ PCIE_PE_RSTB;
+ writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG);
+
+ /*
+ * Described in PCIe CEM specification revision 6.0.
+ *
+ * The deassertion of PERST# should be delayed 100ms (TPVPERL)
+ * for the power and clock to become stable.
+ */
+ msleep(PCIE_T_PVPERL_MS);
+
+ /* De-assert reset signals */
+ val &= ~(PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB |
+ PCIE_PE_RSTB);
+ writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG);
+ }
/* Check if the link is up or not */
err = readl_poll_timeout(pcie->base + PCIE_LINK_STATUS_REG, val,
@@ -1178,10 +1198,12 @@ static int mtk_pcie_suspend_noirq(struct
return err;
}
- /* Pull down the PERST# pin */
- val = readl_relaxed(pcie->base + PCIE_RST_CTRL_REG);
- val |= PCIE_PE_RSTB;
- writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG);
+ if (!(pcie->soc->flags & SKIP_PCIE_RSTB)) {
+ /* Assert the PERST# pin */
+ val = readl_relaxed(pcie->base + PCIE_RST_CTRL_REG);
+ val |= PCIE_PE_RSTB;
+ writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG);
+ }
dev_dbg(pcie->dev, "entered L2 states successfully");
@@ -1232,6 +1254,7 @@ static const struct mtk_gen3_pcie_pdata
.id[2] = "phy-lane2",
.num_resets = 3,
},
+ .flags = SKIP_PCIE_RSTB,
};
static const struct of_device_id mtk_pcie_of_match[] = {

View File

@ -1,11 +1,9 @@
From 2285d3b428c7d8f1c4fda2fb995e7e46a05350e0 Mon Sep 17 00:00:00 2001
Message-ID: <2285d3b428c7d8f1c4fda2fb995e7e46a05350e0.1736324542.git.lorenzo@kernel.org>
In-Reply-To: <0c0ae72f5c84c5a29495337b254ac3cc2d5c16bb.1736324541.git.lorenzo@kernel.org>
References: <0c0ae72f5c84c5a29495337b254ac3cc2d5c16bb.1736324541.git.lorenzo@kernel.org>
From ca4217f3117dceb2d01e179d02031a8758404624 Mon Sep 17 00:00:00 2001
Message-ID: <ca4217f3117dceb2d01e179d02031a8758404624.1736961235.git.lorenzo@kernel.org>
From: Lorenzo Bianconi <lorenzo@kernel.org>
Date: Tue, 3 Sep 2024 23:14:02 +0200
Subject: [PATCH 2/2] PCI: mediatek-gen3: configure PBUS_CSR registers for
EN7581 SoC
Subject: [PATCH] PCI: mediatek-gen3: Configure PBUS_CSR registers for EN7581
SoC
Configure PBus base address and address mask in order to allow the hw
detecting if a given address is on PCIE0, PCIE1 or PCIE2.
@ -33,9 +31,9 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
#include <linux/reset.h>
#include "../pci.h"
@@ -120,6 +122,13 @@
@@ -122,6 +124,13 @@
#define MAX_NUM_PHY_RESETS 3
#define PCIE_MTK_RESET_TIME_US 10
+#define PCIE_EN7581_PBUS_ADDR(_n) (0x00 + ((_n) << 3))
+#define PCIE_EN7581_PBUS_ADDR_MASK(_n) (0x04 + ((_n) << 3))
@ -47,7 +45,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
/* Time in ms needed to complete PCIe reset on EN7581 SoC */
#define PCIE_EN7581_RESET_TIME_MS 100
@@ -871,7 +880,8 @@ static int mtk_pcie_parse_port(struct mt
@@ -893,7 +902,8 @@ static int mtk_pcie_parse_port(struct mt
static int mtk_pcie_en7581_power_up(struct mtk_gen3_pcie *pcie)
{
struct device *dev = pcie->dev;
@ -57,9 +55,9 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
u32 val;
/*
@@ -880,6 +890,23 @@ static int mtk_pcie_en7581_power_up(stru
*/
mdelay(PCIE_EN7581_RESET_TIME_MS);
@@ -907,6 +917,23 @@ static int mtk_pcie_en7581_power_up(stru
/* Wait for the time needed to complete the reset lines assert. */
msleep(PCIE_EN7581_RESET_TIME_MS);
+ map = syscon_regmap_lookup_by_compatible("airoha,en7581-pbus-csr");
+ if (IS_ERR(map))
@ -78,6 +76,6 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+ regmap_write(map, PCIE_EN7581_PBUS_ADDR_MASK(slot),
+ PCIE_EN7581_PBUS_BASE_ADDR_MASK);
+
err = phy_init(pcie->phy);
if (err) {
dev_err(dev, "failed to initialize PHY\n");
/*
* Unlike the other MediaTek Gen3 controllers, the Airoha EN7581
* requires PHY initialization and power-on before PHY reset deassert.

View File

@ -0,0 +1,26 @@
From c4defe43ce17a87e6341d126ba736d9f7ebdc541 Mon Sep 17 00:00:00 2001
Message-ID: <c4defe43ce17a87e6341d126ba736d9f7ebdc541.1736962769.git.lorenzo@kernel.org>
From: Lorenzo Bianconi <lorenzo@kernel.org>
Date: Wed, 15 Jan 2025 18:36:26 +0100
Subject: [PATCH] PCI: mediatek-gen3: Remove mac_reset assert leftover for
Airoha EN7581 SoC.
Remove a leftover assert for mac_reset line in mtk_pcie_en7581_power_up().
This is not armful since EN7581 does not requires mac_reset and
mac_reset is not defined in EN7581 device tree.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/pci/controller/pcie-mediatek-gen3.c | 1 -
1 file changed, 1 deletion(-)
--- a/drivers/pci/controller/pcie-mediatek-gen3.c
+++ b/drivers/pci/controller/pcie-mediatek-gen3.c
@@ -912,7 +912,6 @@ static int mtk_pcie_en7581_power_up(stru
*/
reset_control_bulk_assert(pcie->soc->phy_resets.num_resets,
pcie->phy_resets);
- reset_control_assert(pcie->mac_reset);
/* Wait for the time needed to complete the reset lines assert. */
msleep(PCIE_EN7581_RESET_TIME_MS);

View File

@ -1,83 +0,0 @@
From 1ffcc8d41306fd2e5f140b276820714a26a11cc4 Mon Sep 17 00:00:00 2001
From: Heiner Kallweit <hkallweit1@gmail.com>
Date: Mon, 7 Oct 2024 20:34:12 +0200
Subject: [PATCH] r8169: add support for the temperature sensor being available
from RTL8125B
This adds support for the temperature sensor being available from
RTL8125B. Register information was taken from r8125 vendor driver.
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/ethernet/realtek/r8169_main.c | 44 +++++++++++++++++++++++
1 file changed, 44 insertions(+)
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -16,6 +16,7 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/ethtool.h>
+#include <linux/hwmon.h>
#include <linux/phy.h>
#include <linux/if_vlan.h>
#include <linux/in.h>
@@ -5373,6 +5374,43 @@ static bool rtl_aspm_is_safe(struct rtl8
return false;
}
+static umode_t r8169_hwmon_is_visible(const void *drvdata,
+ enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ return 0444;
+}
+
+static int r8169_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ struct rtl8169_private *tp = dev_get_drvdata(dev);
+ int val_raw;
+
+ val_raw = phy_read_paged(tp->phydev, 0xbd8, 0x12) & 0x3ff;
+ if (val_raw >= 512)
+ val_raw -= 1024;
+
+ *val = 1000 * val_raw / 2;
+
+ return 0;
+}
+
+static const struct hwmon_ops r8169_hwmon_ops = {
+ .is_visible = r8169_hwmon_is_visible,
+ .read = r8169_hwmon_read,
+};
+
+static const struct hwmon_channel_info * const r8169_hwmon_info[] = {
+ HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
+ NULL
+};
+
+static const struct hwmon_chip_info r8169_hwmon_chip_info = {
+ .ops = &r8169_hwmon_ops,
+ .info = r8169_hwmon_info,
+};
+
static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct rtl8169_private *tp;
@@ -5547,6 +5585,12 @@ static int rtl_init_one(struct pci_dev *
if (rc)
return rc;
+ /* The temperature sensor is available from RTl8125B */
+ if (IS_REACHABLE(CONFIG_HWMON) && tp->mac_version >= RTL_GIGA_MAC_VER_63)
+ /* ignore errors */
+ devm_hwmon_device_register_with_info(&pdev->dev, "nic_temp", tp,
+ &r8169_hwmon_chip_info,
+ NULL);
rc = register_netdev(dev);
if (rc)
return rc;

View File

@ -19,7 +19,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -4779,11 +4779,7 @@ static void r8169_phylink_handler(struct
@@ -4778,11 +4778,7 @@ static void r8169_phylink_handler(struct
if (netif_carrier_ok(ndev)) {
rtl_link_chg_patch(tp);
pm_request_resume(d);

View File

@ -20,7 +20,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -5529,11 +5529,6 @@ static int rtl_init_one(struct pci_dev *
@@ -5491,11 +5491,6 @@ static int rtl_init_one(struct pci_dev *
dev->features |= dev->hw_features;
@ -32,7 +32,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
if (rtl_chip_supports_csum_v2(tp)) {
dev->hw_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6;
netif_set_tso_max_size(dev, RTL_GSO_MAX_SIZE_V2);
@@ -5544,6 +5539,17 @@ static int rtl_init_one(struct pci_dev *
@@ -5506,6 +5501,17 @@ static int rtl_init_one(struct pci_dev *
netif_set_tso_max_segs(dev, RTL_GSO_MAX_SEGS_V1);
}

View File

@ -16,7 +16,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -2162,6 +2162,19 @@ static void rtl8169_get_ringparam(struct
@@ -2161,6 +2161,19 @@ static void rtl8169_get_ringparam(struct
data->tx_pending = NUM_TX_DESC;
}
@ -36,7 +36,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
static void rtl8169_get_pauseparam(struct net_device *dev,
struct ethtool_pauseparam *data)
{
@@ -2188,6 +2201,69 @@ static int rtl8169_set_pauseparam(struct
@@ -2187,6 +2200,69 @@ static int rtl8169_set_pauseparam(struct
return 0;
}
@ -106,7 +106,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
static const struct ethtool_ops rtl8169_ethtool_ops = {
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
ETHTOOL_COALESCE_MAX_FRAMES,
@@ -2209,8 +2285,11 @@ static const struct ethtool_ops rtl8169_
@@ -2208,8 +2284,11 @@ static const struct ethtool_ops rtl8169_
.get_link_ksettings = phy_ethtool_get_link_ksettings,
.set_link_ksettings = phy_ethtool_set_link_ksettings,
.get_ringparam = rtl8169_get_ringparam,
@ -118,7 +118,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
};
static enum mac_version rtl8169_get_mac_version(u16 xid, bool gmii)
@@ -3895,6 +3974,9 @@ static void rtl_hw_start_8125(struct rtl
@@ -3894,6 +3973,9 @@ static void rtl_hw_start_8125(struct rtl
break;
}

View File

@ -18,7 +18,7 @@ Signed-off-by: Andrew Lunn <andrew@lunn.ch>
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -4802,10 +4802,8 @@ static void rtl_task(struct work_struct
@@ -4801,10 +4801,8 @@ static void rtl_task(struct work_struct
container_of(work, struct rtl8169_private, wk.work);
int ret;
@ -30,7 +30,7 @@ Signed-off-by: Andrew Lunn <andrew@lunn.ch>
if (test_and_clear_bit(RTL_FLAG_TASK_TX_TIMEOUT, tp->wk.flags)) {
/* if chip isn't accessible, reset bus to revive it */
@@ -4814,7 +4812,7 @@ static void rtl_task(struct work_struct
@@ -4813,7 +4811,7 @@ static void rtl_task(struct work_struct
if (ret < 0) {
netdev_err(tp->dev, "Can't reset secondary PCI bus, detach NIC\n");
netif_device_detach(tp->dev);
@ -39,7 +39,7 @@ Signed-off-by: Andrew Lunn <andrew@lunn.ch>
}
}
@@ -4833,8 +4831,6 @@ reset:
@@ -4832,8 +4830,6 @@ reset:
} else if (test_and_clear_bit(RTL_FLAG_TASK_RESET_NO_QUEUE_WAKE, tp->wk.flags)) {
rtl_reset_work(tp);
}

View File

@ -15,7 +15,7 @@ Signed-off-by: Andrew Lunn <andrew@lunn.ch>
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -1347,40 +1347,19 @@ static void rtl8168ep_stop_cmac(struct r
@@ -1346,40 +1346,19 @@ static void rtl8168ep_stop_cmac(struct r
RTL_W8(tp, IBCR0, RTL_R8(tp, IBCR0) & ~0x01);
}
@ -60,7 +60,7 @@ Signed-off-by: Andrew Lunn <andrew@lunn.ch>
}
static void rtl8168_driver_start(struct rtl8169_private *tp)
@@ -1394,7 +1373,8 @@ static void rtl8168_driver_start(struct
@@ -1393,7 +1372,8 @@ static void rtl8168_driver_start(struct
static void rtl8168dp_driver_stop(struct rtl8169_private *tp)
{
r8168dp_oob_notify(tp, OOB_CMD_DRIVER_STOP);
@ -70,7 +70,7 @@ Signed-off-by: Andrew Lunn <andrew@lunn.ch>
}
static void rtl8168ep_driver_stop(struct rtl8169_private *tp)
@@ -1402,7 +1382,8 @@ static void rtl8168ep_driver_stop(struct
@@ -1401,7 +1381,8 @@ static void rtl8168ep_driver_stop(struct
rtl8168ep_stop_cmac(tp);
r8168ep_ocp_write(tp, 0x01, 0x180, OOB_CMD_DRIVER_STOP);
r8168ep_ocp_write(tp, 0x01, 0x30, r8168ep_ocp_read(tp, 0x30) | 0x01);

View File

@ -29,7 +29,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
RTL_GIGA_MAC_NONE
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -56,6 +56,7 @@
@@ -55,6 +55,7 @@
#define FIRMWARE_8107E_2 "rtl_nic/rtl8107e-2.fw"
#define FIRMWARE_8125A_3 "rtl_nic/rtl8125a-3.fw"
#define FIRMWARE_8125B_2 "rtl_nic/rtl8125b-2.fw"
@ -37,7 +37,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
#define FIRMWARE_8126A_2 "rtl_nic/rtl8126a-2.fw"
#define FIRMWARE_8126A_3 "rtl_nic/rtl8126a-3.fw"
@@ -139,6 +140,7 @@ static const struct {
@@ -138,6 +139,7 @@ static const struct {
[RTL_GIGA_MAC_VER_61] = {"RTL8125A", FIRMWARE_8125A_3},
/* reserve 62 for CFG_METHOD_4 in the vendor driver */
[RTL_GIGA_MAC_VER_63] = {"RTL8125B", FIRMWARE_8125B_2},
@ -45,7 +45,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
[RTL_GIGA_MAC_VER_65] = {"RTL8126A", FIRMWARE_8126A_2},
[RTL_GIGA_MAC_VER_66] = {"RTL8126A", FIRMWARE_8126A_3},
};
@@ -708,6 +710,7 @@ MODULE_FIRMWARE(FIRMWARE_8168FP_3);
@@ -707,6 +709,7 @@ MODULE_FIRMWARE(FIRMWARE_8168FP_3);
MODULE_FIRMWARE(FIRMWARE_8107E_2);
MODULE_FIRMWARE(FIRMWARE_8125A_3);
MODULE_FIRMWARE(FIRMWARE_8125B_2);
@ -53,7 +53,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
MODULE_FIRMWARE(FIRMWARE_8126A_2);
MODULE_FIRMWARE(FIRMWARE_8126A_3);
@@ -2080,10 +2083,7 @@ static void rtl_set_eee_txidle_timer(str
@@ -2079,10 +2082,7 @@ static void rtl_set_eee_txidle_timer(str
tp->tx_lpi_timer = timer_val;
r8168_mac_ocp_write(tp, 0xe048, timer_val);
break;
@ -65,7 +65,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
tp->tx_lpi_timer = timer_val;
RTL_W16(tp, EEE_TXIDLE_TIMER_8125, timer_val);
break;
@@ -2295,6 +2295,9 @@ static enum mac_version rtl8169_get_mac_
@@ -2294,6 +2294,9 @@ static enum mac_version rtl8169_get_mac_
{ 0x7cf, 0x64a, RTL_GIGA_MAC_VER_66 },
{ 0x7cf, 0x649, RTL_GIGA_MAC_VER_65 },
@ -75,7 +75,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
/* 8125B family. */
{ 0x7cf, 0x641, RTL_GIGA_MAC_VER_63 },
@@ -2562,9 +2565,7 @@ static void rtl_init_rxcfg(struct rtl816
@@ -2561,9 +2564,7 @@ static void rtl_init_rxcfg(struct rtl816
case RTL_GIGA_MAC_VER_61:
RTL_W32(tp, RxConfig, RX_FETCH_DFLT_8125 | RX_DMA_BURST);
break;
@ -86,7 +86,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
RTL_W32(tp, RxConfig, RX_FETCH_DFLT_8125 | RX_DMA_BURST |
RX_PAUSE_SLOT_ON);
break;
@@ -3876,6 +3877,12 @@ static void rtl_hw_start_8125b(struct rt
@@ -3875,6 +3876,12 @@ static void rtl_hw_start_8125b(struct rt
rtl_hw_start_8125_common(tp);
}
@ -99,7 +99,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
static void rtl_hw_start_8126a(struct rtl8169_private *tp)
{
rtl_set_def_aspm_entry_latency(tp);
@@ -3924,6 +3931,7 @@ static void rtl_hw_config(struct rtl8169
@@ -3923,6 +3930,7 @@ static void rtl_hw_config(struct rtl8169
[RTL_GIGA_MAC_VER_53] = rtl_hw_start_8117,
[RTL_GIGA_MAC_VER_61] = rtl_hw_start_8125a_2,
[RTL_GIGA_MAC_VER_63] = rtl_hw_start_8125b,
@ -107,7 +107,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
[RTL_GIGA_MAC_VER_65] = rtl_hw_start_8126a,
[RTL_GIGA_MAC_VER_66] = rtl_hw_start_8126a,
};
@@ -3941,6 +3949,7 @@ static void rtl_hw_start_8125(struct rtl
@@ -3940,6 +3948,7 @@ static void rtl_hw_start_8125(struct rtl
/* disable interrupt coalescing */
switch (tp->mac_version) {
case RTL_GIGA_MAC_VER_61:

View File

@ -19,7 +19,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -2227,7 +2227,7 @@ static void rtl8169_get_eth_mac_stats(st
@@ -2226,7 +2226,7 @@ static void rtl8169_get_eth_mac_stats(st
le64_to_cpu(tp->counters->tx_broadcast64);
mac_stats->MulticastFramesReceivedOK =
le64_to_cpu(tp->counters->rx_multicast64);

View File

@ -16,7 +16,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -347,6 +347,8 @@ enum rtl8125_registers {
@@ -346,6 +346,8 @@ enum rtl8125_registers {
TxPoll_8125 = 0x90,
LEDSEL3 = 0x96,
MAC0_BKP = 0x19e0,
@ -25,7 +25,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
EEE_TXIDLE_TIMER_8125 = 0x6048,
};
@@ -3770,8 +3772,8 @@ static void rtl_hw_start_8125_common(str
@@ -3769,8 +3771,8 @@ static void rtl_hw_start_8125_common(str
rtl_pcie_state_l2l3_disable(tp);
RTL_W16(tp, 0x382, 0x221b);

View File

@ -15,7 +15,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -663,13 +663,9 @@ struct rtl8169_private {
@@ -662,13 +662,9 @@ struct rtl8169_private {
struct work_struct work;
} wk;
@ -29,7 +29,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
unsigned supports_gmii:1;
unsigned aspm_manageable:1;
unsigned dash_enabled:1;
@@ -723,22 +719,12 @@ static inline struct device *tp_to_dev(s
@@ -722,22 +718,12 @@ static inline struct device *tp_to_dev(s
static void rtl_lock_config_regs(struct rtl8169_private *tp)
{
@ -54,7 +54,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
}
static void rtl_pci_commit(struct rtl8169_private *tp)
@@ -749,24 +735,18 @@ static void rtl_pci_commit(struct rtl816
@@ -748,24 +734,18 @@ static void rtl_pci_commit(struct rtl816
static void rtl_mod_config2(struct rtl8169_private *tp, u8 clear, u8 set)
{
@ -79,7 +79,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
}
static bool rtl_is_8125(struct rtl8169_private *tp)
@@ -1572,7 +1552,6 @@ static void __rtl8169_set_wol(struct rtl
@@ -1571,7 +1551,6 @@ static void __rtl8169_set_wol(struct rtl
{ WAKE_MAGIC, Config3, MagicPacket }
};
unsigned int i, tmp = ARRAY_SIZE(cfg);
@ -87,7 +87,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
u8 options;
rtl_unlock_config_regs(tp);
@@ -1591,14 +1570,12 @@ static void __rtl8169_set_wol(struct rtl
@@ -1590,14 +1569,12 @@ static void __rtl8169_set_wol(struct rtl
r8168_mac_ocp_modify(tp, 0xc0b6, BIT(0), 0);
}
@ -102,7 +102,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
switch (tp->mac_version) {
case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06:
@@ -5498,8 +5475,6 @@ static int rtl_init_one(struct pci_dev *
@@ -5460,8 +5437,6 @@ static int rtl_init_one(struct pci_dev *
tp->supports_gmii = ent->driver_data == RTL_CFG_NO_GBIT ? 0 : 1;
tp->ocp_base = OCP_STD_PHY_BASE;

View File

@ -16,7 +16,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -749,6 +749,20 @@ static void rtl_mod_config5(struct rtl81
@@ -748,6 +748,20 @@ static void rtl_mod_config5(struct rtl81
RTL_W8(tp, Config5, (val & ~clear) | set);
}
@ -37,7 +37,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
static bool rtl_is_8125(struct rtl8169_private *tp)
{
return tp->mac_version >= RTL_GIGA_MAC_VER_61;
@@ -1539,58 +1553,37 @@ static void rtl8169_get_wol(struct net_d
@@ -1538,58 +1552,37 @@ static void rtl8169_get_wol(struct net_d
static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
{

View File

@ -17,7 +17,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -1432,19 +1432,11 @@ static enum rtl_dash_type rtl_get_dash_t
@@ -1431,19 +1431,11 @@ static enum rtl_dash_type rtl_get_dash_t
static void rtl_set_d3_pll_down(struct rtl8169_private *tp, bool enable)
{

View File

@ -17,7 +17,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -1563,6 +1563,9 @@ static void __rtl8169_set_wol(struct rtl
@@ -1562,6 +1562,9 @@ static void __rtl8169_set_wol(struct rtl
}
r8169_mod_reg8_cond(tp, Config3, LinkUp, wolopts & WAKE_PHY);

View File

@ -17,7 +17,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -2547,86 +2547,31 @@ static void rtl8169_init_ring_indexes(st
@@ -2546,86 +2546,31 @@ static void rtl8169_init_ring_indexes(st
tp->dirty_tx = tp->cur_tx = tp->cur_rx = 0;
}

View File

@ -0,0 +1,52 @@
From 34d5a86ff7bbe225fba3ad91f9b4dc85fb408e18 Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Wed, 15 Jan 2025 14:43:35 +0000
Subject: [PATCH] net: phy: realtek: clear 1000Base-T lpa if link is down
Only read 1000Base-T link partner advertisement if autonegotiation has
completed and otherwise 1000Base-T link partner advertisement bits.
This fixes bogus 1000Base-T link partner advertisement after link goes
down (eg. by disconnecting the wire).
Fixes: 5cb409b3960e ("net: phy: realtek: clear 1000Base-T link partner advertisement")
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Reviewed-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/phy/realtek.c | 19 ++++++++-----------
1 file changed, 8 insertions(+), 11 deletions(-)
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -1023,23 +1023,20 @@ static int rtl822x_c45_read_status(struc
{
int ret, val;
- ret = genphy_c45_read_status(phydev);
- if (ret < 0)
- return ret;
-
- if (phydev->autoneg == AUTONEG_DISABLE ||
- !genphy_c45_aneg_done(phydev))
- mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, 0);
-
/* Vendor register as C45 has no standardized support for 1000BaseT */
- if (phydev->autoneg == AUTONEG_ENABLE) {
+ if (phydev->autoneg == AUTONEG_ENABLE && genphy_c45_aneg_done(phydev)) {
val = phy_read_mmd(phydev, MDIO_MMD_VEND2,
RTL822X_VND2_GANLPAR);
if (val < 0)
return val;
-
- mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, val);
+ } else {
+ val = 0;
}
+ mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, val);
+
+ ret = genphy_c45_read_status(phydev);
+ if (ret < 0)
+ return ret;
if (!phydev->link)
return 0;

View File

@ -0,0 +1,35 @@
From ea8318cb33e593bbfc59d637eae45a69732c5387 Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Wed, 15 Jan 2025 14:43:43 +0000
Subject: [PATCH] net: phy: realtek: clear master_slave_state if link is down
rtlgen_decode_physr() which sets master_slave_state isn't called in case
the link is down and other than rtlgen_read_status(),
rtl822x_c45_read_status() doesn't implicitely clear master_slave_state.
Avoid stale master_slave_state by always setting it to
MASTER_SLAVE_STATE_UNKNOWN in rtl822x_c45_read_status() in case the link
is down.
Fixes: 081c9c0265c9 ("net: phy: realtek: read duplex and gbit master from PHYSR register")
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Reviewed-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/phy/realtek.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -1038,8 +1038,10 @@ static int rtl822x_c45_read_status(struc
if (ret < 0)
return ret;
- if (!phydev->link)
+ if (!phydev->link) {
+ phydev->master_slave_state = MASTER_SLAVE_STATE_UNKNOWN;
return 0;
+ }
/* Read actual speed from vendor register. */
val = phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL_VND2_PHYSR);

View File

@ -0,0 +1,42 @@
From d3eb58549842c60ed46f37da7f4da969e3d6ecd3 Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Wed, 15 Jan 2025 14:45:00 +0000
Subject: [PATCH] net: phy: realtek: always clear NBase-T lpa
Clear NBase-T link partner advertisement before calling
rtlgen_read_status() to avoid phy_resolve_aneg_linkmode() wrongly
setting speed and duplex.
This fixes bogus 2.5G/5G/10G link partner advertisement and thus
speed and duplex being set by phy_resolve_aneg_linkmode() due to stale
NBase-T lpa.
Fixes: 68d5cd09e891 ("net: phy: realtek: change order of calls in C22 read_status()")
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Reviewed-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/phy/realtek.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -952,15 +952,15 @@ static int rtl822x_read_status(struct ph
{
int lpadv, ret;
+ mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, 0);
+
ret = rtlgen_read_status(phydev);
if (ret < 0)
return ret;
if (phydev->autoneg == AUTONEG_DISABLE ||
- !phydev->autoneg_complete) {
- mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, 0);
+ !phydev->autoneg_complete)
return 0;
- }
lpadv = phy_read_paged(phydev, 0xa5d, 0x13);
if (lpadv < 0)

View File

@ -0,0 +1,47 @@
From 3d483a10327f38595f714f9f9e9dde43a622cb0f Mon Sep 17 00:00:00 2001
From: Heiner Kallweit <hkallweit1@gmail.com>
Date: Sat, 11 Jan 2025 21:49:31 +0100
Subject: [PATCH] net: phy: realtek: add support for reading MDIO_MMD_VEND2
regs on RTL8125/RTL8126
RTL8125/RTL8126 don't support MMD access to the internal PHY, but
provide a mechanism to access at least all MDIO_MMD_VEND2 registers.
By exposing this mechanism standard MMD access functions can be used
to access the MDIO_MMD_VEND2 registers.
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://patch.msgid.link/e821b302-5fe6-49ab-aabd-05da500581c0@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/phy/realtek.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -736,7 +736,11 @@ static int rtlgen_read_mmd(struct phy_de
{
int ret;
- if (devnum == MDIO_MMD_PCS && regnum == MDIO_PCS_EEE_ABLE) {
+ if (devnum == MDIO_MMD_VEND2) {
+ rtl821x_write_page(phydev, regnum >> 4);
+ ret = __phy_read(phydev, 0x10 + ((regnum & 0xf) >> 1));
+ rtl821x_write_page(phydev, 0);
+ } else if (devnum == MDIO_MMD_PCS && regnum == MDIO_PCS_EEE_ABLE) {
rtl821x_write_page(phydev, 0xa5c);
ret = __phy_read(phydev, 0x12);
rtl821x_write_page(phydev, 0);
@@ -760,7 +764,11 @@ static int rtlgen_write_mmd(struct phy_d
{
int ret;
- if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV) {
+ if (devnum == MDIO_MMD_VEND2) {
+ rtl821x_write_page(phydev, regnum >> 4);
+ ret = __phy_write(phydev, 0x10 + ((regnum & 0xf) >> 1), val);
+ rtl821x_write_page(phydev, 0);
+ } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV) {
rtl821x_write_page(phydev, 0xa5d);
ret = __phy_write(phydev, 0x10, val);
rtl821x_write_page(phydev, 0);

View File

@ -0,0 +1,180 @@
From 33700ca45b7d2e1655d4cad95e25671e8a94e2f0 Mon Sep 17 00:00:00 2001
From: Heiner Kallweit <hkallweit1@gmail.com>
Date: Sat, 11 Jan 2025 21:51:24 +0100
Subject: [PATCH] net: phy: realtek: add hwmon support for temp sensor on
RTL822x
This adds hwmon support for the temperature sensor on RTL822x.
It's available on the standalone versions of the PHY's, and on
the integrated PHY's in RTL8125B/RTL8125D/RTL8126.
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://patch.msgid.link/ad6bfe9f-6375-4a00-84b4-bfb38a21bd71@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/phy/realtek/Kconfig | 6 ++
drivers/net/phy/realtek/Makefile | 1 +
drivers/net/phy/realtek/realtek.h | 10 ++++
drivers/net/phy/realtek/realtek_hwmon.c | 79 +++++++++++++++++++++++++
drivers/net/phy/realtek/realtek_main.c | 12 ++++
5 files changed, 108 insertions(+)
create mode 100644 drivers/net/phy/realtek/realtek.h
create mode 100644 drivers/net/phy/realtek/realtek_hwmon.c
--- a/drivers/net/phy/realtek/Kconfig
+++ b/drivers/net/phy/realtek/Kconfig
@@ -3,3 +3,9 @@ config REALTEK_PHY
tristate "Realtek PHYs"
help
Currently supports RTL821x/RTL822x and fast ethernet PHYs
+
+config REALTEK_PHY_HWMON
+ def_bool REALTEK_PHY && HWMON
+ depends on !(REALTEK_PHY=y && HWMON=m)
+ help
+ Optional hwmon support for the temperature sensor
--- a/drivers/net/phy/realtek/Makefile
+++ b/drivers/net/phy/realtek/Makefile
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
realtek-y += realtek_main.o
+realtek-$(CONFIG_REALTEK_PHY_HWMON) += realtek_hwmon.o
obj-$(CONFIG_REALTEK_PHY) += realtek.o
--- /dev/null
+++ b/drivers/net/phy/realtek/realtek.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef REALTEK_H
+#define REALTEK_H
+
+#include <linux/phy.h>
+
+int rtl822x_hwmon_init(struct phy_device *phydev);
+
+#endif /* REALTEK_H */
--- /dev/null
+++ b/drivers/net/phy/realtek/realtek_hwmon.c
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * HWMON support for Realtek PHY's
+ *
+ * Author: Heiner Kallweit <hkallweit1@gmail.com>
+ */
+
+#include <linux/hwmon.h>
+#include <linux/phy.h>
+
+#include "realtek.h"
+
+#define RTL822X_VND2_TSALRM 0xa662
+#define RTL822X_VND2_TSRR 0xbd84
+#define RTL822X_VND2_TSSR 0xb54c
+
+static umode_t rtl822x_hwmon_is_visible(const void *drvdata,
+ enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ return 0444;
+}
+
+static int rtl822x_hwmon_get_temp(int raw)
+{
+ if (raw >= 512)
+ raw -= 1024;
+
+ return 1000 * raw / 2;
+}
+
+static int rtl822x_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ struct phy_device *phydev = dev_get_drvdata(dev);
+ int raw;
+
+ switch (attr) {
+ case hwmon_temp_input:
+ raw = phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL822X_VND2_TSRR) & 0x3ff;
+ *val = rtl822x_hwmon_get_temp(raw);
+ break;
+ case hwmon_temp_max:
+ /* Chip reduces speed to 1G if threshold is exceeded */
+ raw = phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL822X_VND2_TSSR) >> 6;
+ *val = rtl822x_hwmon_get_temp(raw);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct hwmon_ops rtl822x_hwmon_ops = {
+ .is_visible = rtl822x_hwmon_is_visible,
+ .read = rtl822x_hwmon_read,
+};
+
+static const struct hwmon_channel_info * const rtl822x_hwmon_info[] = {
+ HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_MAX),
+ NULL
+};
+
+static const struct hwmon_chip_info rtl822x_hwmon_chip_info = {
+ .ops = &rtl822x_hwmon_ops,
+ .info = rtl822x_hwmon_info,
+};
+
+int rtl822x_hwmon_init(struct phy_device *phydev)
+{
+ struct device *hwdev, *dev = &phydev->mdio.dev;
+ const char *name;
+
+ /* Ensure over-temp alarm is reset. */
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, RTL822X_VND2_TSALRM, 3);
+
+ name = devm_hwmon_sanitize_name(dev, dev_name(dev));
+ if (IS_ERR(name))
+ return PTR_ERR(name);
+
+ hwdev = devm_hwmon_device_register_with_info(dev, name, phydev,
+ &rtl822x_hwmon_chip_info,
+ NULL);
+ return PTR_ERR_OR_ZERO(hwdev);
+}
--- a/drivers/net/phy/realtek/realtek_main.c
+++ b/drivers/net/phy/realtek/realtek_main.c
@@ -14,6 +14,8 @@
#include <linux/delay.h>
#include <linux/clk.h>
+#include "realtek.h"
+
#define RTL821x_PHYSR 0x11
#define RTL821x_PHYSR_DUPLEX BIT(13)
#define RTL821x_PHYSR_SPEED GENMASK(15, 14)
@@ -820,6 +822,15 @@ static int rtl822x_write_mmd(struct phy_
return ret;
}
+static int rtl822x_probe(struct phy_device *phydev)
+{
+ if (IS_ENABLED(CONFIG_REALTEK_PHY_HWMON) &&
+ phydev->phy_id != RTL_GENERIC_PHYID)
+ return rtl822x_hwmon_init(phydev);
+
+ return 0;
+}
+
static int rtl822xb_config_init(struct phy_device *phydev)
{
bool has_2500, has_sgmii;
@@ -1518,6 +1529,7 @@ static struct phy_driver realtek_drvs[]
.match_phy_device = rtl_internal_nbaset_match_phy_device,
.name = "Realtek Internal NBASE-T PHY",
.flags = PHY_IS_INTERNAL,
+ .probe = rtl822x_probe,
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
.read_status = rtl822x_read_status,

View File

@ -10,12 +10,12 @@ the PHY.
Reported-by: Yevhen Kolomeiko <jarvis2709@gmail.com>
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
drivers/net/phy/realtek.c | 6 ++++++
drivers/net/phy/realtek/realtek_main.c | 6 ++++++
1 file changed, 6 insertions(+)
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -1412,6 +1412,7 @@ static struct phy_driver realtek_drvs[]
--- a/drivers/net/phy/realtek/realtek_main.c
+++ b/drivers/net/phy/realtek/realtek_main.c
@@ -1430,6 +1430,7 @@ static struct phy_driver realtek_drvs[]
}, {
.name = "RTL8226 2.5Gbps PHY",
.match_phy_device = rtl8226_match_phy_device,
@ -23,7 +23,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
.read_status = rtl822x_read_status,
@@ -1422,6 +1423,7 @@ static struct phy_driver realtek_drvs[]
@@ -1440,6 +1441,7 @@ static struct phy_driver realtek_drvs[]
}, {
.match_phy_device = rtl8221b_match_phy_device,
.name = "RTL8226B_RTL8221B 2.5Gbps PHY",
@ -31,7 +31,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
.config_init = rtl822xb_config_init,
@@ -1434,6 +1436,7 @@ static struct phy_driver realtek_drvs[]
@@ -1452,6 +1454,7 @@ static struct phy_driver realtek_drvs[]
}, {
PHY_ID_MATCH_EXACT(0x001cc838),
.name = "RTL8226-CG 2.5Gbps PHY",
@ -39,7 +39,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
.read_status = rtl822x_read_status,
@@ -1444,6 +1447,7 @@ static struct phy_driver realtek_drvs[]
@@ -1462,6 +1465,7 @@ static struct phy_driver realtek_drvs[]
}, {
PHY_ID_MATCH_EXACT(0x001cc848),
.name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY",
@ -47,7 +47,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
.config_init = rtl822xb_config_init,
@@ -1456,6 +1460,7 @@ static struct phy_driver realtek_drvs[]
@@ -1474,6 +1478,7 @@ static struct phy_driver realtek_drvs[]
}, {
.match_phy_device = rtl8221b_vb_cg_c22_match_phy_device,
.name = "RTL8221B-VB-CG 2.5Gbps PHY (C22)",
@ -55,7 +55,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
.config_init = rtl822xb_config_init,
@@ -1468,6 +1473,7 @@ static struct phy_driver realtek_drvs[]
@@ -1486,6 +1491,7 @@ static struct phy_driver realtek_drvs[]
}, {
.match_phy_device = rtl8221b_vb_cg_c45_match_phy_device,
.name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)",
@ -63,7 +63,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
.config_init = rtl822xb_config_init,
.get_rate_matching = rtl822xb_get_rate_matching,
.get_features = rtl822x_c45_get_features,
@@ -1478,6 +1484,7 @@ static struct phy_driver realtek_drvs[]
@@ -1496,6 +1502,7 @@ static struct phy_driver realtek_drvs[]
}, {
.match_phy_device = rtl8221b_vn_cg_c22_match_phy_device,
.name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)",
@ -71,7 +71,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
.config_init = rtl822xb_config_init,
@@ -1490,6 +1497,7 @@ static struct phy_driver realtek_drvs[]
@@ -1508,6 +1515,7 @@ static struct phy_driver realtek_drvs[]
}, {
.match_phy_device = rtl8221b_vn_cg_c45_match_phy_device,
.name = "RTL8221B-VN-CG 2.5Gbps PHY (C45)",

View File

@ -15,12 +15,12 @@ Reported-by: Yevhen Kolomeiko <jarvis2709@gmail.com>
Tested-by: Yevhen Kolomeiko <jarvis2709@gmail.com>
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
drivers/net/phy/realtek.c | 27 +++++++++++++++++++++++++--
drivers/net/phy/realtek/realtek_main.c | 27 +++++++++++++++++++++++++--
1 file changed, 25 insertions(+), 2 deletions(-)
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -815,8 +815,8 @@ static int rtl822x_write_mmd(struct phy_
--- a/drivers/net/phy/realtek/realtek_main.c
+++ b/drivers/net/phy/realtek/realtek_main.c
@@ -834,8 +834,8 @@ static int rtl822x_probe(struct phy_devi
static int rtl822xb_config_init(struct phy_device *phydev)
{
bool has_2500, has_sgmii;
@ -30,7 +30,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
has_2500 = test_bit(PHY_INTERFACE_MODE_2500BASEX,
phydev->host_interfaces) ||
@@ -866,7 +866,29 @@ static int rtl822xb_config_init(struct p
@@ -885,7 +885,29 @@ static int rtl822xb_config_init(struct p
if (ret < 0)
return ret;

View File

@ -13,12 +13,12 @@ rtl821x_write_page instead of 3 individually locked MDIO bus operations.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
drivers/net/phy/realtek.c | 8 +++++---
drivers/net/phy/realtek/realtek_main.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -1093,9 +1093,11 @@ static bool rtlgen_supports_2_5gbps(stru
--- a/drivers/net/phy/realtek/realtek_main.c
+++ b/drivers/net/phy/realtek/realtek_main.c
@@ -1111,9 +1111,11 @@ static bool rtlgen_supports_2_5gbps(stru
{
int val;

View File

@ -8,12 +8,12 @@ just like for RTL821x 1GE PHYs.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
drivers/net/phy/realtek.c | 11 +++++++++++
drivers/net/phy/realtek/realtek_main.c | 11 +++++++++++
1 file changed, 11 insertions(+)
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -80,6 +80,10 @@
--- a/drivers/net/phy/realtek/realtek_main.c
+++ b/drivers/net/phy/realtek/realtek_main.c
@@ -82,6 +82,10 @@
#define RTL822X_VND2_GANLPAR 0xa414
@ -24,11 +24,11 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
#define RTL8366RB_POWER_SAVE 0x15
#define RTL8366RB_POWER_SAVE_ON BIT(12)
@@ -1189,6 +1193,25 @@ static int rtl8251b_c45_match_phy_device
@@ -1207,6 +1211,25 @@ static int rtl8251b_c45_match_phy_device
return rtlgen_is_c45_match(phydev, RTL_8251B, true);
}
+static int rtl822x_probe(struct phy_device *phydev)
+static int rtl822x_aldps_probe(struct phy_device *phydev)
+{
+ struct device *dev = &phydev->mdio.dev;
+ int val;
@ -50,51 +50,51 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
static int rtlgen_resume(struct phy_device *phydev)
{
int ret = genphy_resume(phydev);
@@ -1460,6 +1483,7 @@ static struct phy_driver realtek_drvs[]
@@ -1478,6 +1501,7 @@ static struct phy_driver realtek_drvs[]
}, {
PHY_ID_MATCH_EXACT(0x001cc838),
.name = "RTL8226-CG 2.5Gbps PHY",
+ .probe = rtl822x_probe,
+ .probe = rtl822x_aldps_probe,
.soft_reset = genphy_soft_reset,
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
@@ -1471,6 +1495,7 @@ static struct phy_driver realtek_drvs[]
@@ -1489,6 +1513,7 @@ static struct phy_driver realtek_drvs[]
}, {
PHY_ID_MATCH_EXACT(0x001cc848),
.name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY",
+ .probe = rtl822x_probe,
+ .probe = rtl822x_aldps_probe,
.soft_reset = genphy_soft_reset,
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
@@ -1484,6 +1509,7 @@ static struct phy_driver realtek_drvs[]
@@ -1502,6 +1527,7 @@ static struct phy_driver realtek_drvs[]
}, {
.match_phy_device = rtl8221b_vb_cg_c22_match_phy_device,
.name = "RTL8221B-VB-CG 2.5Gbps PHY (C22)",
+ .probe = rtl822x_probe,
+ .probe = rtl822x_aldps_probe,
.soft_reset = genphy_soft_reset,
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
@@ -1497,6 +1523,7 @@ static struct phy_driver realtek_drvs[]
@@ -1515,6 +1541,7 @@ static struct phy_driver realtek_drvs[]
}, {
.match_phy_device = rtl8221b_vb_cg_c45_match_phy_device,
.name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)",
+ .probe = rtl822x_probe,
+ .probe = rtl822x_aldps_probe,
.soft_reset = genphy_soft_reset,
.config_init = rtl822xb_config_init,
.get_rate_matching = rtl822xb_get_rate_matching,
@@ -1508,6 +1535,7 @@ static struct phy_driver realtek_drvs[]
@@ -1526,6 +1553,7 @@ static struct phy_driver realtek_drvs[]
}, {
.match_phy_device = rtl8221b_vn_cg_c22_match_phy_device,
.name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)",
+ .probe = rtl822x_probe,
+ .probe = rtl822x_aldps_probe,
.soft_reset = genphy_soft_reset,
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
@@ -1521,6 +1549,7 @@ static struct phy_driver realtek_drvs[]
@@ -1539,6 +1567,7 @@ static struct phy_driver realtek_drvs[]
}, {
.match_phy_device = rtl8221b_vn_cg_c45_match_phy_device,
.name = "RTL8221B-VN-CG 2.5Gbps PHY (C45)",
+ .probe = rtl822x_probe,
+ .probe = rtl822x_aldps_probe,
.soft_reset = genphy_soft_reset,
.config_init = rtl822xb_config_init,
.get_rate_matching = rtl822xb_get_rate_matching,

View File

@ -12,9 +12,9 @@ over the implemented MMDs.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
[forward-port by @namiltd]
Signed-off-by: Mieczyslaw Nalewaj <namiltd@yahoo.com>
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -1139,10 +1139,32 @@ static int rtl8226_match_phy_device(stru
--- a/drivers/net/phy/realtek/realtek_main.c
+++ b/drivers/net/phy/realtek/realtek_main.c
@@ -1157,10 +1157,32 @@ static int rtl8226_match_phy_device(stru
static int rtlgen_is_c45_match(struct phy_device *phydev, unsigned int id,
bool is_c45)
{

View File

@ -7,12 +7,12 @@ This commit introduces interrupt support for RTL8221B.
Signed-off-by: Jianhui Zhao <zhaojh329@gmail.com>
---
drivers/net/phy/realtek.c | 47 +++++++++++++++++++++++++++++++++++++++
drivers/net/phy/realtek/realtek_main.c | 47 +++++++++++++++++++++++++++++++++++++++
1 file changed, 47 insertions(+)
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -1369,6 +1369,51 @@ static irqreturn_t rtl9000a_handle_inter
--- a/drivers/net/phy/realtek/realtek_main.c
+++ b/drivers/net/phy/realtek/realtek_main.c
@@ -1387,6 +1387,51 @@ static irqreturn_t rtl9000a_handle_inter
return IRQ_HANDLED;
}
@ -64,39 +64,39 @@ Signed-off-by: Jianhui Zhao <zhaojh329@gmail.com>
static struct phy_driver realtek_drvs[] = {
{
PHY_ID_MATCH_EXACT(0x00008201),
@@ -1531,6 +1576,8 @@ static struct phy_driver realtek_drvs[]
@@ -1549,6 +1594,8 @@ static struct phy_driver realtek_drvs[]
}, {
.match_phy_device = rtl8221b_vb_cg_c22_match_phy_device,
.name = "RTL8221B-VB-CG 2.5Gbps PHY (C22)",
+ .config_intr = rtl8221b_config_intr,
+ .handle_interrupt = rtl8221b_handle_interrupt,
.probe = rtl822x_probe,
.probe = rtl822x_aldps_probe,
.soft_reset = genphy_soft_reset,
.get_features = rtl822x_get_features,
@@ -1545,6 +1592,8 @@ static struct phy_driver realtek_drvs[]
@@ -1563,6 +1610,8 @@ static struct phy_driver realtek_drvs[]
}, {
.match_phy_device = rtl8221b_vb_cg_c45_match_phy_device,
.name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)",
+ .config_intr = rtl8221b_config_intr,
+ .handle_interrupt = rtl8221b_handle_interrupt,
.probe = rtl822x_probe,
.probe = rtl822x_aldps_probe,
.soft_reset = genphy_soft_reset,
.config_init = rtl822xb_config_init,
@@ -1557,6 +1606,8 @@ static struct phy_driver realtek_drvs[]
@@ -1575,6 +1624,8 @@ static struct phy_driver realtek_drvs[]
}, {
.match_phy_device = rtl8221b_vn_cg_c22_match_phy_device,
.name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)",
+ .config_intr = rtl8221b_config_intr,
+ .handle_interrupt = rtl8221b_handle_interrupt,
.probe = rtl822x_probe,
.probe = rtl822x_aldps_probe,
.soft_reset = genphy_soft_reset,
.get_features = rtl822x_get_features,
@@ -1571,6 +1622,8 @@ static struct phy_driver realtek_drvs[]
@@ -1589,6 +1640,8 @@ static struct phy_driver realtek_drvs[]
}, {
.match_phy_device = rtl8221b_vn_cg_c45_match_phy_device,
.name = "RTL8221B-VN-CG 2.5Gbps PHY (C45)",
+ .config_intr = rtl8221b_config_intr,
+ .handle_interrupt = rtl8221b_handle_interrupt,
.probe = rtl822x_probe,
.probe = rtl822x_aldps_probe,
.soft_reset = genphy_soft_reset,
.config_init = rtl822xb_config_init,

View File

@ -1,14 +0,0 @@
[ ifup = "$ACTION" ] && {
[ -n "$DEVICE" ] && {
if [ "$INTERFACE" == "lan" ]; then
if [ -f /usr/sbin/ethtool ]; then
ifname=eth0
lan_ip=`uci -q get network.lan.ipaddr`
ethdrv=`ethtool -i $ifname | grep mtk_soc_eth`
[ -n "$ethdrv" ] && {
ethtool -N $ifname flow-type tcp4 dst-ip $lan_ip loc 0
}
fi
fi
}
}

View File

@ -1,6 +0,0 @@
set_rps_sock_flow() {
echo 1024 > /proc/sys/net/core/rps_sock_flow_entries
}
boot_hook_add preinit_main set_rps_sock_flow

View File

@ -1,6 +1,6 @@
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -419,6 +419,12 @@ config ROCKCHIP_PHY
@@ -416,6 +416,12 @@ config ROCKCHIP_PHY
help
Currently supports the integrated Ethernet PHY.
@ -16,7 +16,7 @@
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -102,6 +102,7 @@ obj-$(CONFIG_QSEMI_PHY) += qsemi.o
obj-$(CONFIG_REALTEK_PHY) += realtek.o
obj-$(CONFIG_REALTEK_PHY) += realtek/
obj-$(CONFIG_RENESAS_PHY) += uPD60620.o
obj-$(CONFIG_ROCKCHIP_PHY) += rockchip.o
+obj-$(CONFIG_RTL8367S_GSW) += rtk/

View File

@ -1,8 +1,8 @@
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -399,6 +399,8 @@ config REALTEK_PHY
help
Supports the Realtek 821x PHY.
@@ -396,6 +396,8 @@ config QSEMI_PHY
source "drivers/net/phy/realtek/Kconfig"
+source "drivers/net/phy/rtl8261n/Kconfig"
+
@ -14,7 +14,7 @@
@@ -100,6 +100,7 @@ obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja
obj-y += qcom/
obj-$(CONFIG_QSEMI_PHY) += qsemi.o
obj-$(CONFIG_REALTEK_PHY) += realtek.o
obj-$(CONFIG_REALTEK_PHY) += realtek/
+obj-y += rtl8261n/
obj-$(CONFIG_RENESAS_PHY) += uPD60620.o
obj-$(CONFIG_ROCKCHIP_PHY) += rockchip.o

View File

@ -16,9 +16,9 @@ Signed-off-by: Yangyu Chen <cyy@cyyself.name>
drivers/net/phy/realtek.c | 28 +++++++++++++++++++++++++++-
1 file changed, 27 insertions(+), 1 deletion(-)
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -84,6 +84,12 @@
--- a/drivers/net/phy/realtek/realtek_main.c
+++ b/drivers/net/phy/realtek/realtek_main.c
@@ -86,6 +86,12 @@
#define RTL8221B_PHYCR1_ALDPS_EN BIT(2)
#define RTL8221B_PHYCR1_ALDPS_XTAL_OFF_EN BIT(12)
@ -31,8 +31,8 @@ Signed-off-by: Yangyu Chen <cyy@cyyself.name>
#define RTL8366RB_POWER_SAVE 0x15
#define RTL8366RB_POWER_SAVE_ON BIT(12)
@@ -815,6 +821,45 @@ static int rtl822x_write_mmd(struct phy_
return ret;
@@ -835,6 +841,45 @@ static int rtl822x_probe(struct phy_devi
return 0;
}
+static int rtl8221b_config_led(struct phy_device *phydev) {
@ -77,7 +77,7 @@ Signed-off-by: Yangyu Chen <cyy@cyyself.name>
static int rtl822xb_config_init(struct phy_device *phydev)
{
bool has_2500, has_sgmii;
@@ -891,7 +936,7 @@ static int rtl822xb_config_init(struct p
@@ -911,7 +956,7 @@ static int rtl822xb_config_init(struct p
if (ret < 0)
return ret;

View File

@ -14,9 +14,9 @@ Submitted-by: Birger Koblitz <mail@birger-koblitz.de>
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -410,6 +410,12 @@ config REALTEK_PHY
help
Supports the Realtek 821x PHY.
@@ -407,6 +407,12 @@ config QSEMI_PHY
source "drivers/net/phy/realtek/Kconfig"
+config REALTEK_SOC_PHY
+ tristate "Realtek SoC PHYs"
@ -32,7 +32,7 @@ Submitted-by: Birger Koblitz <mail@birger-koblitz.de>
@@ -100,6 +100,7 @@ obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja
obj-y += qcom/
obj-$(CONFIG_QSEMI_PHY) += qsemi.o
obj-$(CONFIG_REALTEK_PHY) += realtek.o
obj-$(CONFIG_REALTEK_PHY) += realtek/
+obj-$(CONFIG_REALTEK_SOC_PHY) += rtl83xx-phy.o
obj-$(CONFIG_RENESAS_PHY) += uPD60620.o
obj-$(CONFIG_ROCKCHIP_PHY) += rockchip.o

View File

@ -103,7 +103,7 @@ Signed-off-by: Sander Vanheule <sander@svanheule.net>
+ if (err)
+ return err;
+
+ err = regmap_read_poll_timeout(ctrl->map, ctrl->cmd_reg, run, (run != cmd), 3, 100);
+ err = regmap_read_poll_timeout_atomic(ctrl->map, ctrl->cmd_reg, run, (run != cmd), 3, 100);
+
+ if ((run & ~mask_volatile) != (cmd & ~mask_volatile)) {
+ dev_err(ctrl->dev, "Command modified. Is offloading still active?");

View File

@ -1,6 +1,6 @@
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -22,6 +22,7 @@
@@ -21,6 +21,7 @@
#include <linux/in.h>
#include <linux/io.h>
#include <linux/ip.h>
@ -8,7 +8,7 @@
#include <linux/tcp.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
@@ -5393,6 +5394,7 @@ static int rtl_init_one(struct pci_dev *
@@ -5355,6 +5356,7 @@ static int rtl_init_one(struct pci_dev *
int jumbo_max, region, rc;
enum mac_version chipset;
struct net_device *dev;
@ -16,7 +16,7 @@
u32 txconfig;
u16 xid;
@@ -5400,6 +5402,9 @@ static int rtl_init_one(struct pci_dev *
@@ -5362,6 +5364,9 @@ static int rtl_init_one(struct pci_dev *
if (!dev)
return -ENOMEM;

View File

@ -7,9 +7,9 @@ Subject: [PATCH] net: phy: realtek: add LED configuration from OF for 8211f
drivers/net/phy/realtek.c | 9 +++++++++
1 file changed, 9 insertions(+)
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -32,6 +32,7 @@
--- a/drivers/net/phy/realtek/realtek_main.c
+++ b/drivers/net/phy/realtek/realtek_main.c
@@ -34,6 +34,7 @@
#define RTL8211F_PHYCR2 0x19
#define RTL8211F_INSR 0x1d
@ -17,7 +17,7 @@ Subject: [PATCH] net: phy: realtek: add LED configuration from OF for 8211f
#define RTL8211F_LEDCR 0x10
#define RTL8211F_LEDCR_MODE BIT(15)
#define RTL8211F_LEDCR_ACT_TXRX BIT(4)
@@ -380,6 +381,7 @@ static int rtl8211f_config_init(struct p
@@ -382,6 +383,7 @@ static int rtl8211f_config_init(struct p
struct rtl821x_priv *priv = phydev->priv;
struct device *dev = &phydev->mdio.dev;
u16 val_txdly, val_rxdly;
@ -25,7 +25,7 @@ Subject: [PATCH] net: phy: realtek: add LED configuration from OF for 8211f
int ret;
ret = phy_modify_paged_changed(phydev, 0xa43, RTL8211F_PHYCR1,
@@ -446,6 +448,15 @@ static int rtl8211f_config_init(struct p
@@ -448,6 +450,15 @@ static int rtl8211f_config_init(struct p
val_rxdly ? "enabled" : "disabled");
}