Merge branch 'openwrt:master' into master
This commit is contained in:
commit
c656b5b077
91 changed files with 6358 additions and 156 deletions
|
@ -1,50 +0,0 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
# Copyright (C) 2022-2023 Enéas Ulir de Queiroz
|
||||
|
||||
ENGINES_DIR=engines-3
|
||||
|
||||
define Package/openssl/engine/Default
|
||||
SECTION:=libs
|
||||
CATEGORY:=Libraries
|
||||
SUBMENU:=SSL
|
||||
DEPENDS:=libopenssl @OPENSSL_ENGINE +libopenssl-conf
|
||||
endef
|
||||
|
||||
# 1 = engine name
|
||||
# 2 - package name, defaults to libopenssl-$(1)
|
||||
define Package/openssl/add-engine
|
||||
OSSL_ENG_PKG:=$(if $(2),$(2),libopenssl-$(1))
|
||||
Package/$$(OSSL_ENG_PKG)/conffiles:=/etc/ssl/engines.cnf.d/$(1).cnf
|
||||
|
||||
define Package/$$(OSSL_ENG_PKG)/install
|
||||
$$(INSTALL_DIR) $$(1)/usr/lib/$(ENGINES_DIR)
|
||||
$$(INSTALL_BIN) $$(PKG_INSTALL_DIR)/usr/lib/$(ENGINES_DIR)/$(1).so \
|
||||
$$(1)/usr/lib/$(ENGINES_DIR)
|
||||
$$(INSTALL_DIR) $$(1)/etc/ssl/engines.cnf.d
|
||||
$$(INSTALL_DATA) ./files/$(1).cnf $$(1)/etc/ssl/engines.cnf.d/
|
||||
endef
|
||||
|
||||
define Package/$$(OSSL_ENG_PKG)/postinst :=
|
||||
#!/bin/sh
|
||||
OPENSSL_UCI="$$$${IPKG_INSTROOT}/etc/config/openssl"
|
||||
|
||||
[ -z "$$$${IPKG_INSTROOT}" ] && uci -q get openssl.$(1) >/dev/null && exit 0
|
||||
|
||||
cat << EOF >> "$$$${OPENSSL_UCI}"
|
||||
|
||||
config engine '$(1)'
|
||||
option enabled '1'
|
||||
EOF
|
||||
|
||||
[ -n "$$$${IPKG_INSTROOT}" ] || /etc/init.d/openssl reload
|
||||
endef
|
||||
|
||||
define Package/$$(OSSL_ENG_PKG)/postrm :=
|
||||
#!/bin/sh
|
||||
[ -n "$$$${IPKG_INSTROOT}" ] && exit 0
|
||||
uci delete openssl.$(1)
|
||||
uci commit openssl
|
||||
/etc/init.d/openssl reload
|
||||
endef
|
||||
endef
|
79
include/openssl-module.mk
Normal file
79
include/openssl-module.mk
Normal file
|
@ -0,0 +1,79 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
# Copyright (C) 2022-2023 Enéas Ulir de Queiroz
|
||||
|
||||
ENGINES_DIR=engines-3
|
||||
|
||||
define Package/openssl/module/Default
|
||||
SECTION:=libs
|
||||
CATEGORY:=Libraries
|
||||
SUBMENU:=SSL
|
||||
DEPENDS:=libopenssl +libopenssl-conf
|
||||
endef
|
||||
|
||||
define Package/openssl/engine/Default
|
||||
$(Package/openssl/module/Default)
|
||||
DEPENDS+=@OPENSSL_ENGINE
|
||||
endef
|
||||
|
||||
|
||||
# 1 = moudule type (engine|provider)
|
||||
# 2 = module name
|
||||
# 3 = directory to save .so file
|
||||
# 4 = [ package name, defaults to libopenssl-$(2) ]
|
||||
define Package/openssl/add-module
|
||||
$(eval MOD_TYPE:=$(1))
|
||||
$(eval MOD_NAME:=$(2))
|
||||
$(eval MOD_DIR:=$(3))
|
||||
$(eval OSSL_PKG:=$(if $(4),$(4),libopenssl-$(MOD_NAME)))
|
||||
$(info Package/openssl/add-module 1='$(1)'; 2='$(2)'; 3='$(3)' 4='$(4)')
|
||||
$(info MOD_TYPE='$(MOD_TYPE)'; MOD_NAME='$(MOD_NAME)'; MOD_DIR='$(MOD_DIR)' OSSL_PKG='$(OSSL_PKG)')
|
||||
Package/$(OSSL_PKG)/conffiles:=/etc/ssl/modules.cnf.d/$(MOD_NAME).cnf
|
||||
|
||||
define Package/$(OSSL_PKG)/install
|
||||
$$(INSTALL_DIR) $$(1)/$(MOD_DIR)
|
||||
$$(INSTALL_BIN) $$(PKG_INSTALL_DIR)/$(MOD_DIR)/$(MOD_NAME).so \
|
||||
$$(1)/$(MOD_DIR)
|
||||
$$(INSTALL_DIR) $$(1)/etc/ssl/modules.cnf.d
|
||||
$$(INSTALL_DATA) ./files/$(MOD_NAME).cnf $$(1)/etc/ssl/modules.cnf.d/
|
||||
endef
|
||||
|
||||
define Package/$(OSSL_PKG)/postinst
|
||||
#!/bin/sh
|
||||
OPENSSL_UCI="$$$${IPKG_INSTROOT}/etc/config/openssl"
|
||||
|
||||
[ -z "$$$${IPKG_INSTROOT}" ] \
|
||||
&& uci -q get openssl.$(MOD_NAME) >/dev/null \
|
||||
&& exit 0
|
||||
|
||||
cat << EOF >> "$$$${OPENSSL_UCI}"
|
||||
|
||||
config $(MOD_TYPE) '$(MOD_NAME)'
|
||||
option enabled '1'
|
||||
EOF
|
||||
|
||||
[ -n "$$$${IPKG_INSTROOT}" ] || /etc/init.d/openssl reload
|
||||
exit 0
|
||||
endef
|
||||
|
||||
define Package/$(OSSL_PKG)/postrm
|
||||
#!/bin/sh
|
||||
[ -n "$$$${IPKG_INSTROOT}" ] && exit 0
|
||||
uci -q delete openssl.$(MOD_NAME) && uci commit openssl
|
||||
/etc/init.d/openssl reload
|
||||
exit 0
|
||||
endef
|
||||
endef
|
||||
|
||||
# 1 = engine name
|
||||
# 2 - package name, defaults to libopenssl-$(1)
|
||||
define Package/openssl/add-engine
|
||||
$(call Package/openssl/add-module,engine,$(1),/usr/lib/$(ENGINES_DIR),$(2))
|
||||
endef
|
||||
|
||||
# 1 = provider name
|
||||
# 2 = [ package name, defaults to libopenssl-$(1) ]
|
||||
define Package/openssl/add-provider
|
||||
$(call Package/openssl/add-module,provider,$(1),/usr/lib/ossl-modules,$(2))
|
||||
endef
|
||||
|
|
@ -8,13 +8,13 @@
|
|||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=ath11k-firmware
|
||||
PKG_SOURCE_DATE:=2022-12-14
|
||||
PKG_SOURCE_VERSION:=ab1229f94591ec4ffb16410e359b7f618be75a33
|
||||
PKG_MIRROR_HASH:=48a2526971e56a3be1c80b72cd82b9932c196b4ab9b7d5dc35117f0548a8fe57
|
||||
PKG_SOURCE_DATE:=2023-03-31
|
||||
PKG_SOURCE_VERSION:=a039049a9349722fa5c74185452ab04644a0d351
|
||||
PKG_MIRROR_HASH:=ed401e3f6e91d70565b3396139193f7e815f410db93700697205ac8ed1b828c5
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL:=https://github.com/kvalo/ath11k-firmware.git
|
||||
PKG_SOURCE_URL:=https://github.com/quic/upstream-wifi-fw.git
|
||||
|
||||
PKG_LICENSE_FILES:=LICENSE.qca_firmware
|
||||
|
||||
|
@ -46,20 +46,31 @@ define Build/Compile
|
|||
|
||||
endef
|
||||
|
||||
QCN9074_BOARD_REV:=8e140c65f36137714b6d8934e09dcd73cb05c2f6
|
||||
QCN9074_BOARD_FILE:=board-2.bin.$(QCN9074_BOARD_REV)
|
||||
|
||||
define Download/qcn9074-board
|
||||
URL:=https://github.com/kvalo/ath11k-firmware/raw/master/QCN9074/hw1.0/
|
||||
URL_FILE:=board-2.bin
|
||||
FILE:=$(QCN9074_BOARD_FILE)
|
||||
HASH:=dbf0ca14aa1229eccd48f26f1026901b9718b143bd30b51b8ea67c84ba6207f1
|
||||
endef
|
||||
$(eval $(call Download,qcn9074-board))
|
||||
|
||||
define Package/ath11k-firmware-ipq8074/install
|
||||
$(INSTALL_DIR) $(1)/lib/firmware/IPQ8074
|
||||
$(INSTALL_DATA) \
|
||||
$(PKG_BUILD_DIR)/IPQ8074/hw2.0/2.5.0.1/WLAN.HK.2.5.0.1-01208-QCAHKSWPL_SILICONZ-1/* \
|
||||
$(PKG_BUILD_DIR)/ath11k-firmware/IPQ8074/hw2.0/testing/2.9.0.1/WLAN.HK.2.9.0.1-01385-QCAHKSWPL_SILICONZ-1/* \
|
||||
$(1)/lib/firmware/IPQ8074/
|
||||
endef
|
||||
|
||||
define Package/ath11k-firmware-qcn9074/install
|
||||
$(INSTALL_DIR) $(1)/lib/firmware/ath11k/QCN9074/hw1.0
|
||||
$(INSTALL_DATA) \
|
||||
$(PKG_BUILD_DIR)/QCN9074/hw1.0/2.5.0.1/WLAN.HK.2.5.0.1-01208-QCAHKSWPL_SILICONZ-1/* \
|
||||
$(PKG_BUILD_DIR)/ath11k-firmware/QCN9074/hw1.0/testing/2.9.0.1/WLAN.HK.2.9.0.1-01385-QCAHKSWPL_SILICONZ-1/* \
|
||||
$(1)/lib/firmware/ath11k/QCN9074/hw1.0/
|
||||
$(INSTALL_BIN) \
|
||||
$(PKG_BUILD_DIR)/QCN9074/hw1.0/board-2.bin $(1)/lib/firmware/ath11k/QCN9074/hw1.0/board-2.bin
|
||||
$(DL_DIR)/$(QCN9074_BOARD_FILE) $(1)/lib/firmware/ath11k/QCN9074/hw1.0/board-2.bin
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,ath11k-firmware-ipq8074))
|
||||
|
|
|
@ -0,0 +1,202 @@
|
|||
From patchwork Mon Mar 20 13:38:40 2023
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
X-Patchwork-Submitter: Nagarajan Maran <quic_nmaran@quicinc.com>
|
||||
X-Patchwork-Id: 13181272
|
||||
X-Patchwork-Delegate: kvalo@adurom.com
|
||||
Return-Path: <linux-wireless-owner@vger.kernel.org>
|
||||
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on
|
||||
aws-us-west-2-korg-lkml-1.web.codeaurora.org
|
||||
Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
|
||||
by smtp.lore.kernel.org (Postfix) with ESMTP id 6F899C6FD1D
|
||||
for <linux-wireless@archiver.kernel.org>;
|
||||
Mon, 20 Mar 2023 13:39:52 +0000 (UTC)
|
||||
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
|
||||
id S231824AbjCTNjm (ORCPT
|
||||
<rfc822;linux-wireless@archiver.kernel.org>);
|
||||
Mon, 20 Mar 2023 09:39:42 -0400
|
||||
Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44860 "EHLO
|
||||
lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
|
||||
with ESMTP id S231795AbjCTNjT (ORCPT
|
||||
<rfc822;linux-wireless@vger.kernel.org>);
|
||||
Mon, 20 Mar 2023 09:39:19 -0400
|
||||
Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com
|
||||
[205.220.180.131])
|
||||
by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CD4CC1A66C
|
||||
for <linux-wireless@vger.kernel.org>;
|
||||
Mon, 20 Mar 2023 06:39:10 -0700 (PDT)
|
||||
Received: from pps.filterd (m0279872.ppops.net [127.0.0.1])
|
||||
by mx0a-0031df01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id
|
||||
32KBvFZ2004731;
|
||||
Mon, 20 Mar 2023 13:39:05 GMT
|
||||
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com;
|
||||
h=from : to : cc :
|
||||
subject : date : message-id : mime-version : content-type; s=qcppdkim1;
|
||||
bh=jMz2u2+gyjJJcj5tuRPYVv0di+sn1S5ni8sqhMu/9Kg=;
|
||||
b=BNz+KGi99iSZhDkes9KWF52w7CzSYjHOAYXTfBPlCQk7pM1ZZAIsxB8H3zGnapUkas/r
|
||||
1FfSr/9GpQ+5F6LsOEhJ4KF4Us8wsGi/jZnw25FoCqH4jPqhHPQzcC4jaVzVtNdjiA/0
|
||||
PlEKhMhP6ULKuRkpbM7RDNigSEYSRmhgqbWkVUL69mwPEJi2oHbhQgxFGFO75Rmfk+Gt
|
||||
8w4fd4JPJXA1PNOxL3X8nGYxxzxTsUvQi80R1Tm683dJg7fwBKlNOyD/BlmnrBGBeIqv
|
||||
CMVmf/KTnEUEFt7WWsvQInmEBZG+JH8TvwUAZ9ndRKqA4kCNXqS5+79KGzUuBP80f3yv ow==
|
||||
Received: from nalasppmta01.qualcomm.com (Global_NAT1.qualcomm.com
|
||||
[129.46.96.20])
|
||||
by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3pen6hrh12-1
|
||||
(version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256
|
||||
verify=NOT);
|
||||
Mon, 20 Mar 2023 13:39:05 +0000
|
||||
Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com
|
||||
[10.47.209.196])
|
||||
by NALASPPMTA01.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTPS id
|
||||
32KDd4H6010152
|
||||
(version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256
|
||||
verify=NOT);
|
||||
Mon, 20 Mar 2023 13:39:04 GMT
|
||||
Received: from nmaran-linux.qualcomm.com (10.80.80.8) by
|
||||
nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server
|
||||
(version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id
|
||||
15.2.986.41; Mon, 20 Mar 2023 06:39:02 -0700
|
||||
From: Nagarajan Maran <quic_nmaran@quicinc.com>
|
||||
To: <ath11k@lists.infradead.org>
|
||||
CC: <linux-wireless@vger.kernel.org>,
|
||||
Bhagavathi Perumal S <quic_bperumal@quicinc.com>,
|
||||
Nagarajan Maran <quic_nmaran@quicinc.com>
|
||||
Subject: [PATCH] wifi: ath11k: Fix invalid management rx frame length issue
|
||||
Date: Mon, 20 Mar 2023 19:08:40 +0530
|
||||
Message-ID: <20230320133840.30162-1-quic_nmaran@quicinc.com>
|
||||
X-Mailer: git-send-email 2.17.1
|
||||
MIME-Version: 1.0
|
||||
X-Originating-IP: [10.80.80.8]
|
||||
X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To
|
||||
nalasex01a.na.qualcomm.com (10.47.209.196)
|
||||
X-QCInternal: smtphost
|
||||
X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800
|
||||
signatures=585085
|
||||
X-Proofpoint-ORIG-GUID: 8NkXcGNm6eXVpjTaeMT1e0VxZ9FeT59R
|
||||
X-Proofpoint-GUID: 8NkXcGNm6eXVpjTaeMT1e0VxZ9FeT59R
|
||||
X-Proofpoint-Virus-Version: vendor=baseguard
|
||||
engine=ICAP:2.0.254,Aquarius:18.0.942,Hydra:6.0.573,FMLib:17.11.170.22
|
||||
definitions=2023-03-20_09,2023-03-20_02,2023-02-09_01
|
||||
X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0
|
||||
mlxlogscore=999
|
||||
malwarescore=0 priorityscore=1501 mlxscore=0 bulkscore=0 adultscore=0
|
||||
spamscore=0 impostorscore=0 phishscore=0 clxscore=1011 suspectscore=0
|
||||
lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1
|
||||
engine=8.12.0-2303150002 definitions=main-2303200115
|
||||
Precedence: bulk
|
||||
List-ID: <linux-wireless.vger.kernel.org>
|
||||
X-Mailing-List: linux-wireless@vger.kernel.org
|
||||
|
||||
From: Bhagavathi Perumal S <quic_bperumal@quicinc.com>
|
||||
|
||||
The WMI management rx event has multiple arrays of TLVs, however the common
|
||||
WMI TLV parser won't handle multiple TLV tags of same type.
|
||||
So the multiple array tags of WMI management rx TLV is parsed incorrectly
|
||||
and the length calculated becomes wrong when the target sends multiple
|
||||
array tags.
|
||||
|
||||
Add separate TLV parser to handle multiple arrays for WMI management rx
|
||||
TLV. This fixes invalid length issue when the target sends multiple array
|
||||
tags.
|
||||
|
||||
Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1
|
||||
|
||||
Signed-off-by: Bhagavathi Perumal S <quic_bperumal@quicinc.com>
|
||||
Co-developed-by: Nagarajan Maran <quic_nmaran@quicinc.com>
|
||||
Signed-off-by: Nagarajan Maran <quic_nmaran@quicinc.com>
|
||||
---
|
||||
drivers/net/wireless/ath/ath11k/wmi.c | 45 +++++++++++++++++++++------
|
||||
1 file changed, 35 insertions(+), 10 deletions(-)
|
||||
|
||||
|
||||
base-commit: 3df3715e556027e94246b2cb30986563362a65f4
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath11k/wmi.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
|
||||
@@ -82,6 +82,12 @@ struct wmi_tlv_fw_stats_parse {
|
||||
bool chain_rssi_done;
|
||||
};
|
||||
|
||||
+struct wmi_tlv_mgmt_rx_parse {
|
||||
+ const struct wmi_mgmt_rx_hdr *fixed;
|
||||
+ const u8 *frame_buf;
|
||||
+ bool frame_buf_done;
|
||||
+};
|
||||
+
|
||||
static const struct wmi_tlv_policy wmi_tlv_policies[] = {
|
||||
[WMI_TAG_ARRAY_BYTE]
|
||||
= { .min_len = 0 },
|
||||
@@ -5633,28 +5639,49 @@ static int ath11k_pull_vdev_stopped_para
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int ath11k_wmi_tlv_mgmt_rx_parse(struct ath11k_base *ab,
|
||||
+ u16 tag, u16 len,
|
||||
+ const void *ptr, void *data)
|
||||
+{
|
||||
+ struct wmi_tlv_mgmt_rx_parse *parse = data;
|
||||
+
|
||||
+ switch (tag) {
|
||||
+ case WMI_TAG_MGMT_RX_HDR:
|
||||
+ parse->fixed = ptr;
|
||||
+ break;
|
||||
+ case WMI_TAG_ARRAY_BYTE:
|
||||
+ if (!parse->frame_buf_done) {
|
||||
+ parse->frame_buf = ptr;
|
||||
+ parse->frame_buf_done = true;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int ath11k_pull_mgmt_rx_params_tlv(struct ath11k_base *ab,
|
||||
struct sk_buff *skb,
|
||||
struct mgmt_rx_event_params *hdr)
|
||||
{
|
||||
- const void **tb;
|
||||
+ struct wmi_tlv_mgmt_rx_parse parse = { };
|
||||
const struct wmi_mgmt_rx_hdr *ev;
|
||||
const u8 *frame;
|
||||
int ret;
|
||||
|
||||
- tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
- if (IS_ERR(tb)) {
|
||||
- ret = PTR_ERR(tb);
|
||||
- ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
+ ret = ath11k_wmi_tlv_iter(ab, skb->data, skb->len,
|
||||
+ ath11k_wmi_tlv_mgmt_rx_parse,
|
||||
+ &parse);
|
||||
+ if (ret) {
|
||||
+ ath11k_warn(ab, "failed to parse mgmt rx tlv %d\n",
|
||||
+ ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
- ev = tb[WMI_TAG_MGMT_RX_HDR];
|
||||
- frame = tb[WMI_TAG_ARRAY_BYTE];
|
||||
+ ev = parse.fixed;
|
||||
+ frame = parse.frame_buf;
|
||||
|
||||
if (!ev || !frame) {
|
||||
ath11k_warn(ab, "failed to fetch mgmt rx hdr");
|
||||
- kfree(tb);
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
@@ -5673,7 +5700,6 @@ static int ath11k_pull_mgmt_rx_params_tl
|
||||
|
||||
if (skb->len < (frame - skb->data) + hdr->buf_len) {
|
||||
ath11k_warn(ab, "invalid length in mgmt rx hdr ev");
|
||||
- kfree(tb);
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
@@ -5685,7 +5711,6 @@ static int ath11k_pull_mgmt_rx_params_tl
|
||||
|
||||
ath11k_ce_byte_swap(skb->data, hdr->buf_len);
|
||||
|
||||
- kfree(tb);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -12,9 +12,23 @@ config OPENSSL_OPTIMIZE_SPEED
|
|||
The increase in performance and size depends on the
|
||||
target CPU. EC and AES seem to benefit the most.
|
||||
|
||||
config OPENSSL_SMALL_FOOTPRINT
|
||||
bool
|
||||
depends on !OPENSSL_OPTIMIZE_SPEED
|
||||
default y if SMALL_FLASH || LOW_MEMORY_FOOTPRINT
|
||||
prompt "Build with OPENSSL_SMALL_FOOTPRINT (read help)"
|
||||
help
|
||||
This turns on -DOPENSSL_SMALL_FOOTPRINT. This will save only
|
||||
1-3% of of the ipk size. The performance drop depends on
|
||||
architecture and algorithm. MIPS drops 13% of performance for
|
||||
a 3% decrease in ipk size. On Aarch64, for a 1% reduction in
|
||||
size, ghash and GCM performance decreases 90%, while
|
||||
Chacha20-Poly1305 is 15% slower. X86_64 drops 1% of its size
|
||||
for 3% of performance. Other arches have not been tested.
|
||||
|
||||
config OPENSSL_WITH_ASM
|
||||
bool
|
||||
default y if !SMALL_FLASH || !arm
|
||||
default y
|
||||
prompt "Compile with optimized assembly code"
|
||||
depends on !arc
|
||||
help
|
||||
|
@ -46,7 +60,7 @@ config OPENSSL_NO_DEPRECATED
|
|||
|
||||
config OPENSSL_WITH_ERROR_MESSAGES
|
||||
bool
|
||||
default y if !SMALL_FLASH && !LOW_MEMORY_FOOTPRINT
|
||||
default y if !OPENSSL_SMALL_FOOTPRINT || (!SMALL_FLASH && !LOW_MEMORY_FOOTPRINT)
|
||||
prompt "Include error messages"
|
||||
help
|
||||
This option aids debugging, but increases package size and
|
||||
|
@ -153,16 +167,24 @@ config OPENSSL_WITH_CAMELLIA
|
|||
|
||||
config OPENSSL_WITH_IDEA
|
||||
bool
|
||||
prompt "Enable IDEA cipher support"
|
||||
default y if !SMALL_FLASH
|
||||
prompt "Enable IDEA cipher support (needs legacy provider)"
|
||||
help
|
||||
IDEA is a block cipher with 128-bit keys.
|
||||
To use the cipher, one must install the libopenssl-legacy
|
||||
package, using a main libopenssl package compiled with this
|
||||
option enabled as well.
|
||||
|
||||
config OPENSSL_WITH_SEED
|
||||
bool
|
||||
prompt "Enable SEED cipher support"
|
||||
default y if !SMALL_FLASH
|
||||
prompt "Enable SEED cipher support (needs legacy provider)"
|
||||
help
|
||||
SEED is a block cipher with 128-bit keys broadly used in
|
||||
South Korea, but seldom found elsewhere.
|
||||
To use the cipher, one must install the libopenssl-legacy
|
||||
package, using a main libopenssl package compiled with this
|
||||
option enabled as well.
|
||||
|
||||
config OPENSSL_WITH_SM234
|
||||
bool
|
||||
|
@ -183,11 +205,21 @@ config OPENSSL_WITH_BLAKE2
|
|||
|
||||
config OPENSSL_WITH_MDC2
|
||||
bool
|
||||
prompt "Enable MDC2 digest support"
|
||||
default y if !SMALL_FLASH
|
||||
prompt "Enable MDC2 digest support (needs legacy provider)"
|
||||
help
|
||||
To use the digest, one must install the libopenssl-legacy
|
||||
package, using a main libopenssl package compiled with this
|
||||
option enabled as well.
|
||||
|
||||
config OPENSSL_WITH_WHIRLPOOL
|
||||
bool
|
||||
prompt "Enable Whirlpool digest support"
|
||||
default y if !SMALL_FLASH
|
||||
prompt "Enable Whirlpool digest support (needs legacy provider)"
|
||||
help
|
||||
To use the digest, one must install the libopenssl-legacy
|
||||
package, using a main libopenssl package compiled with this
|
||||
option enabled as well.
|
||||
|
||||
config OPENSSL_WITH_COMPRESSION
|
||||
bool
|
||||
|
|
|
@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
|
|||
|
||||
PKG_NAME:=openssl
|
||||
PKG_VERSION:=3.0.8
|
||||
PKG_RELEASE:=4
|
||||
PKG_RELEASE:=8
|
||||
PKG_BUILD_FLAGS:=no-mips16 gc-sections
|
||||
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
|
@ -39,6 +39,7 @@ PKG_CONFIG_DEPENDS:= \
|
|||
CONFIG_OPENSSL_NO_DEPRECATED \
|
||||
CONFIG_OPENSSL_OPTIMIZE_SPEED \
|
||||
CONFIG_OPENSSL_PREFER_CHACHA_OVER_GCM \
|
||||
CONFIG_OPENSSL_SMALL_FOOTPRINT \
|
||||
CONFIG_OPENSSL_WITH_ARIA \
|
||||
CONFIG_OPENSSL_WITH_ASM \
|
||||
CONFIG_OPENSSL_WITH_ASYNC \
|
||||
|
@ -63,7 +64,7 @@ PKG_CONFIG_DEPENDS:= \
|
|||
CONFIG_OPENSSL_WITH_WHIRLPOOL
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(INCLUDE_DIR)/openssl-engine.mk
|
||||
include $(INCLUDE_DIR)/openssl-module.mk
|
||||
|
||||
ifneq ($(CONFIG_CCACHE),)
|
||||
HOSTCC=$(HOSTCC_NOCACHE)
|
||||
|
@ -128,8 +129,8 @@ endef
|
|||
|
||||
define Package/libopenssl-conf/conffiles
|
||||
/etc/ssl/openssl.cnf
|
||||
$(if $(CONFIG_OPENSSL_ENGINE_BUILTIN_DEVCRYPTO),/etc/ssl/engines.cnf.d/devcrypto.cnf)
|
||||
$(if $(CONFIG_OPENSSL_ENGINE_BUILTIN_PADLOCK),/etc/ssl/engines.cnf.d/padlock.cnf)
|
||||
$(if $(CONFIG_OPENSSL_ENGINE_BUILTIN_DEVCRYPTO),/etc/ssl/modules.cnf.d/devcrypto.cnf)
|
||||
$(if $(CONFIG_OPENSSL_ENGINE_BUILTIN_PADLOCK),/etc/ssl/modules.cnf.d/padlock.cnf)
|
||||
endef
|
||||
|
||||
define Package/libopenssl-conf/description
|
||||
|
@ -137,6 +138,44 @@ $(call Package/openssl/Default/description)
|
|||
This package installs the OpenSSL configuration file /etc/ssl/openssl.cnf.
|
||||
endef
|
||||
|
||||
ifneq ($(CONFIG_OPENSSL_ENGINE_BUILTIN_PADLOCK)$(CONFIG_OPENSSL_ENGINE_BUILTIN_DEVCRYPTO),)
|
||||
define Package/libopenssl-conf/postinst
|
||||
#!/bin/sh
|
||||
OPENSSL_UCI="$${IPKG_INSTROOT}/etc/config/openssl"
|
||||
|
||||
add_engine_config() {
|
||||
if [ -z "$${IPKG_INSTROOT}" ] && uci -q get "openssl.$$1" >/dev/null; then
|
||||
[ "$$(uci -q get "openssl.$$1.builtin")" = 1 ] && return
|
||||
uci set "openssl.$$1.builtin=1" && uci commit openssl
|
||||
return
|
||||
fi
|
||||
{
|
||||
echo "engine '$$1'"
|
||||
echo " option enabled '1'"
|
||||
echo " option builtin '1'"
|
||||
echo
|
||||
} >>"$${OPENSSL_UCI}"
|
||||
}
|
||||
|
||||
$(if $(CONFIG_OPENSSL_ENGINE_BUILTIN_DEVCRYPTO),add_engine_config devcrypto)
|
||||
$(if $(CONFIG_OPENSSL_ENGINE_BUILTIN_PADLOCK),add_engine_config padlock)
|
||||
endef
|
||||
endif
|
||||
|
||||
$(eval $(call Package/openssl/add-provider,legacy))
|
||||
define Package/libopenssl-legacy
|
||||
$(call Package/openssl/Default)
|
||||
$(call Package/openssl/module/Default)
|
||||
TITLE:=OpenSSL legacy provider
|
||||
endef
|
||||
|
||||
define Package/libopenssl-legacy/description
|
||||
The OpenSSL legacy provider supplies OpenSSL implementations of algorithms that
|
||||
have been deemed legacy. Such algorithms have commonly fallen out of use, have
|
||||
been deemed insecure by the cryptography community, or something similar. See
|
||||
https://www.openssl.org/docs/man3.0/man7/OSSL_PROVIDER-legacy.html
|
||||
endef
|
||||
|
||||
$(eval $(call Package/openssl/add-engine,afalg))
|
||||
define Package/libopenssl-afalg
|
||||
$(call Package/openssl/Default)
|
||||
|
@ -149,7 +188,7 @@ endef
|
|||
define Package/libopenssl-afalg/description
|
||||
This package adds an engine that enables hardware acceleration
|
||||
through the AF_ALG kernel interface.
|
||||
See https://www.openssl.org/docs/man1.1.1/man5/config.html#Engine-Configuration-Module
|
||||
See https://www.openssl.org/docs/man3.0/man5/config.html#Engine-Configuration
|
||||
and https://openwrt.org/docs/techref/hardware/cryptographic.hardware.accelerators
|
||||
The engine_id is "afalg"
|
||||
endef
|
||||
|
@ -165,7 +204,7 @@ endef
|
|||
define Package/libopenssl-devcrypto/description
|
||||
This package adds an engine that enables hardware acceleration
|
||||
through the /dev/crypto kernel interface.
|
||||
See https://www.openssl.org/docs/man1.1.1/man5/config.html#Engine-Configuration-Module
|
||||
See https://www.openssl.org/docs/man3.0/man5/config.html#Engine-Configuration
|
||||
and https://openwrt.org/docs/techref/hardware/cryptographic.hardware.accelerators
|
||||
The engine_id is "devcrypto"
|
||||
endef
|
||||
|
@ -181,7 +220,7 @@ endef
|
|||
|
||||
define Package/libopenssl-padlock/description
|
||||
This package adds an engine that enables VIA Padlock hardware acceleration.
|
||||
See https://www.openssl.org/docs/man1.1.1/man5/config.html#Engine-Configuration-Module
|
||||
See https://www.openssl.org/docs/man3.0/man5/config.html#Engine-Configuration
|
||||
and https://openwrt.org/docs/techref/hardware/cryptographic.hardware.accelerators
|
||||
The engine_id is "padlock"
|
||||
endef
|
||||
|
@ -258,7 +297,9 @@ endif
|
|||
|
||||
ifeq ($(CONFIG_OPENSSL_OPTIMIZE_SPEED),y)
|
||||
TARGET_CFLAGS := $(filter-out -O%,$(TARGET_CFLAGS)) -O3
|
||||
else
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_OPENSSL_SMALL_FOOTPRINT),y)
|
||||
OPENSSL_OPTIONS += -DOPENSSL_SMALL_FOOTPRINT
|
||||
endif
|
||||
|
||||
|
@ -376,16 +417,16 @@ define Package/libopenssl/install
|
|||
endef
|
||||
|
||||
define Package/libopenssl-conf/install
|
||||
$(INSTALL_DIR) $(1)/etc/ssl/engines.cnf.d $(1)/etc/config $(1)/etc/init.d
|
||||
$(INSTALL_DIR) $(1)/etc/ssl/modules.cnf.d $(1)/etc/config $(1)/etc/init.d
|
||||
$(CP) $(PKG_INSTALL_DIR)/etc/ssl/openssl.cnf $(1)/etc/ssl/
|
||||
$(INSTALL_BIN) ./files/openssl.init $(1)/etc/init.d/openssl
|
||||
$(SED) 's!%ENGINES_DIR%!/usr/lib/$(ENGINES_DIR)!' $(1)/etc/init.d/openssl
|
||||
touch $(1)/etc/config/openssl
|
||||
$(if $(CONFIG_OPENSSL_ENGINE_BUILTIN_DEVCRYPTO),
|
||||
$(CP) ./files/devcrypto.cnf $(1)/etc/ssl/engines.cnf.d/
|
||||
$(CP) ./files/devcrypto.cnf $(1)/etc/ssl/modules.cnf.d/
|
||||
echo -e "config engine 'devcrypto'\n\toption enabled '1'" >> $(1)/etc/config/openssl)
|
||||
$(if $(CONFIG_OPENSSL_ENGINE_BUILTIN_PADLOCK),
|
||||
$(CP) ./files/padlock.cnf $(1)/etc/ssl/engines.cnf.d/
|
||||
$(CP) ./files/padlock.cnf $(1)/etc/ssl/modules.cnf.d/
|
||||
echo -e "\nconfig engine 'padlock'\n\toption enabled '1'" >> $(1)/etc/config/openssl)
|
||||
endef
|
||||
|
||||
|
@ -398,5 +439,6 @@ $(eval $(call BuildPackage,libopenssl))
|
|||
$(eval $(call BuildPackage,libopenssl-conf))
|
||||
$(eval $(call BuildPackage,libopenssl-afalg))
|
||||
$(eval $(call BuildPackage,libopenssl-devcrypto))
|
||||
$(eval $(call BuildPackage,libopenssl-legacy))
|
||||
$(eval $(call BuildPackage,libopenssl-padlock))
|
||||
$(eval $(call BuildPackage,openssl-util))
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
[afalg]
|
||||
[afalg_sect]
|
||||
default_algorithms = ALL
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
[devcrypto]
|
||||
[devcrypto_sect]
|
||||
# Leave this alone and configure algorithms with CIPERS/DIGESTS below
|
||||
default_algorithms = ALL
|
||||
|
||||
|
|
3
package/libs/openssl/files/legacy.cnf
Normal file
3
package/libs/openssl/files/legacy.cnf
Normal file
|
@ -0,0 +1,3 @@
|
|||
[legacy_sect]
|
||||
activate = 1
|
||||
|
|
@ -1,31 +1,72 @@
|
|||
#!/bin/sh /etc/rc.common
|
||||
|
||||
START=13
|
||||
ENGINES_CNF_D="/etc/ssl/engines.cnf.d"
|
||||
ENGINES_CNF="/var/etc/ssl/engines.cnf"
|
||||
ENGINES_DIR="%ENGINES_DIR%"
|
||||
ENGINES_CNF=/var/etc/ssl/engines.cnf
|
||||
ENGINES_DIR=%ENGINES_DIR%
|
||||
MODULES_DIR=/usr/lib/ossl-modules
|
||||
PROVIDERS_CNF=/var/etc/ssl/providers.cnf
|
||||
|
||||
config_engine() {
|
||||
local enabled force
|
||||
#1: cnf file
|
||||
write_cnf_header() {
|
||||
mkdir -p "$(dirname "$1")" && \
|
||||
echo "# This file is automatically generated from /etc/config/openssl." >"$1" || {
|
||||
echo "Error writing to $1."
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#1: module name
|
||||
#2: output cnf file
|
||||
#3: module.so
|
||||
enable_module() {
|
||||
local builtin enabled force
|
||||
|
||||
config_get_bool builtin "$1" builtin 0
|
||||
config_get_bool enabled "$1" enabled 1
|
||||
config_get_bool force "$1" force 0
|
||||
[ "$enabled" = 0 ] && return
|
||||
if [ "$force" = 0 ] && \
|
||||
[ ! -f "${ENGINES_CNF_D}/$1.cnf" ] && \
|
||||
[ ! -f "${ENGINES_DIR}/$1.so" ]; then
|
||||
echo Skipping engine "$1": not installed
|
||||
return
|
||||
|
||||
if [ "$enabled" = 0 ]; then
|
||||
[ "$builtin" = 0 ] && return 1
|
||||
echo "Engine $1 is built into the libcrypto library and can't be disabled through UCI."
|
||||
echo "If the engine was not built-in, remove 'config builtin' from /etc/config/openssl."
|
||||
elif [ "$force" = 1 ]; then
|
||||
printf "[Forced] "
|
||||
elif ! grep -q "\\[ *$1_sect *]" /etc/ssl/modules.cnf.d/*; then
|
||||
echo "$1: Could not find section [$1] in config files."
|
||||
return 1
|
||||
elif [ "$builtin" = 1 ]; then
|
||||
printf "[Builtin] "
|
||||
elif [ ! -f "$3" ];then
|
||||
echo "Skipping $1: $3 not found."
|
||||
return 1
|
||||
fi
|
||||
echo Enabling engine "$1"
|
||||
echo "$1=$1" >> "${ENGINES_CNF}"
|
||||
echo "Enabling $1"
|
||||
echo "$1=$1_sect" >>"$2"
|
||||
}
|
||||
|
||||
config_engine() {
|
||||
enable_module "$1" "$ENGINES_CNF" \
|
||||
"${ENGINES_DIR}/${1}.so"
|
||||
}
|
||||
|
||||
config_provider() {
|
||||
enable_module "$1" "$PROVIDERS_CNF" \
|
||||
"${MODULES_DIR}/${1}.so"
|
||||
}
|
||||
|
||||
start() {
|
||||
mkdir -p "$(dirname "${ENGINES_CNF}")" || exit 1
|
||||
echo Generating engines.cnf
|
||||
echo "# This file is automatically generated from /etc/config/openssl." \
|
||||
> "${ENGINES_CNF}" || \
|
||||
{ echo Error writing ${ENGINES_CNF} >&2; exit 1; }
|
||||
local ret=0
|
||||
|
||||
config_load openssl
|
||||
config_foreach config_engine engine
|
||||
|
||||
echo Generating engines.cnf
|
||||
write_cnf_header "${ENGINES_CNF}" && \
|
||||
config_foreach config_engine engine || ret=$?
|
||||
|
||||
echo Generating providers.cnf
|
||||
write_cnf_header "${PROVIDERS_CNF}" && \
|
||||
config_foreach config_provider provider || ret=$?
|
||||
|
||||
return $ret
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
[padlock]
|
||||
[padlock_sect]
|
||||
default_algorithms = ALL
|
||||
|
||||
|
|
|
@ -10,20 +10,32 @@ Signed-off-by: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
|||
|
||||
--- a/apps/openssl.cnf
|
||||
+++ b/apps/openssl.cnf
|
||||
@@ -30,6 +30,16 @@ oid_section = new_oids
|
||||
# (Alternatively, use a configuration file that has only
|
||||
# X.509v3 extensions in its main [= default] section.)
|
||||
@@ -52,10 +52,13 @@ tsa_policy3 = 1.2.3.4.5.7
|
||||
|
||||
+openssl_conf=openssl_conf
|
||||
[openssl_init]
|
||||
providers = provider_sect
|
||||
+engines = engines_sect
|
||||
|
||||
# List of providers to load
|
||||
[provider_sect]
|
||||
default = default_sect
|
||||
+.include /var/etc/ssl/providers.cnf
|
||||
+
|
||||
+[openssl_conf]
|
||||
+engines=engines
|
||||
# The fips section name should match the section name inside the
|
||||
# included fipsmodule.cnf.
|
||||
# fips = fips_sect
|
||||
@@ -69,7 +72,13 @@ default = default_sect
|
||||
# OpenSSL may not work correctly which could lead to significant system
|
||||
# problems including inability to remotely access the system.
|
||||
[default_sect]
|
||||
-# activate = 1
|
||||
+activate = 1
|
||||
+
|
||||
+[engines]
|
||||
+[engines_sect]
|
||||
+.include /var/etc/ssl/engines.cnf
|
||||
+
|
||||
+.include /etc/ssl/engines.cnf.d
|
||||
+.include /etc/ssl/modules.cnf.d
|
||||
+
|
||||
[ new_oids ]
|
||||
# We can add new OIDs in here for use by 'ca', 'req' and 'ts'.
|
||||
# Add a simple OID like this:
|
||||
|
||||
|
||||
####################################################################
|
||||
|
|
|
@ -0,0 +1,207 @@
|
|||
From 959c59c7a0164117e7f8366466a32bb1f8d77ff1 Mon Sep 17 00:00:00 2001
|
||||
From: Pauli <pauli@openssl.org>
|
||||
Date: Wed, 8 Mar 2023 15:28:20 +1100
|
||||
Subject: [PATCH] x509: excessive resource use verifying policy constraints
|
||||
|
||||
A security vulnerability has been identified in all supported versions
|
||||
of OpenSSL related to the verification of X.509 certificate chains
|
||||
that include policy constraints. Attackers may be able to exploit this
|
||||
vulnerability by creating a malicious certificate chain that triggers
|
||||
exponential use of computational resources, leading to a denial-of-service
|
||||
(DoS) attack on affected systems.
|
||||
|
||||
Fixes CVE-2023-0464
|
||||
|
||||
Reviewed-by: Tomas Mraz <tomas@openssl.org>
|
||||
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
|
||||
(Merged from https://github.com/openssl/openssl/pull/20568)
|
||||
|
||||
--- a/crypto/x509/pcy_local.h
|
||||
+++ b/crypto/x509/pcy_local.h
|
||||
@@ -111,6 +111,11 @@ struct X509_POLICY_LEVEL_st {
|
||||
};
|
||||
|
||||
struct X509_POLICY_TREE_st {
|
||||
+ /* The number of nodes in the tree */
|
||||
+ size_t node_count;
|
||||
+ /* The maximum number of nodes in the tree */
|
||||
+ size_t node_maximum;
|
||||
+
|
||||
/* This is the tree 'level' data */
|
||||
X509_POLICY_LEVEL *levels;
|
||||
int nlevel;
|
||||
@@ -157,7 +162,8 @@ X509_POLICY_NODE *ossl_policy_tree_find_
|
||||
X509_POLICY_NODE *ossl_policy_level_add_node(X509_POLICY_LEVEL *level,
|
||||
X509_POLICY_DATA *data,
|
||||
X509_POLICY_NODE *parent,
|
||||
- X509_POLICY_TREE *tree);
|
||||
+ X509_POLICY_TREE *tree,
|
||||
+ int extra_data);
|
||||
void ossl_policy_node_free(X509_POLICY_NODE *node);
|
||||
int ossl_policy_node_match(const X509_POLICY_LEVEL *lvl,
|
||||
const X509_POLICY_NODE *node, const ASN1_OBJECT *oid);
|
||||
--- a/crypto/x509/pcy_node.c
|
||||
+++ b/crypto/x509/pcy_node.c
|
||||
@@ -59,10 +59,15 @@ X509_POLICY_NODE *ossl_policy_level_find
|
||||
X509_POLICY_NODE *ossl_policy_level_add_node(X509_POLICY_LEVEL *level,
|
||||
X509_POLICY_DATA *data,
|
||||
X509_POLICY_NODE *parent,
|
||||
- X509_POLICY_TREE *tree)
|
||||
+ X509_POLICY_TREE *tree,
|
||||
+ int extra_data)
|
||||
{
|
||||
X509_POLICY_NODE *node;
|
||||
|
||||
+ /* Verify that the tree isn't too large. This mitigates CVE-2023-0464 */
|
||||
+ if (tree->node_maximum > 0 && tree->node_count >= tree->node_maximum)
|
||||
+ return NULL;
|
||||
+
|
||||
node = OPENSSL_zalloc(sizeof(*node));
|
||||
if (node == NULL) {
|
||||
ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
|
||||
@@ -70,7 +75,7 @@ X509_POLICY_NODE *ossl_policy_level_add_
|
||||
}
|
||||
node->data = data;
|
||||
node->parent = parent;
|
||||
- if (level) {
|
||||
+ if (level != NULL) {
|
||||
if (OBJ_obj2nid(data->valid_policy) == NID_any_policy) {
|
||||
if (level->anyPolicy)
|
||||
goto node_error;
|
||||
@@ -90,7 +95,7 @@ X509_POLICY_NODE *ossl_policy_level_add_
|
||||
}
|
||||
}
|
||||
|
||||
- if (tree) {
|
||||
+ if (extra_data) {
|
||||
if (tree->extra_data == NULL)
|
||||
tree->extra_data = sk_X509_POLICY_DATA_new_null();
|
||||
if (tree->extra_data == NULL){
|
||||
@@ -103,6 +108,7 @@ X509_POLICY_NODE *ossl_policy_level_add_
|
||||
}
|
||||
}
|
||||
|
||||
+ tree->node_count++;
|
||||
if (parent)
|
||||
parent->nchild++;
|
||||
|
||||
--- a/crypto/x509/pcy_tree.c
|
||||
+++ b/crypto/x509/pcy_tree.c
|
||||
@@ -14,6 +14,17 @@
|
||||
|
||||
#include "pcy_local.h"
|
||||
|
||||
+/*
|
||||
+ * If the maximum number of nodes in the policy tree isn't defined, set it to
|
||||
+ * a generous default of 1000 nodes.
|
||||
+ *
|
||||
+ * Defining this to be zero means unlimited policy tree growth which opens the
|
||||
+ * door on CVE-2023-0464.
|
||||
+ */
|
||||
+#ifndef OPENSSL_POLICY_TREE_NODES_MAX
|
||||
+# define OPENSSL_POLICY_TREE_NODES_MAX 1000
|
||||
+#endif
|
||||
+
|
||||
static void expected_print(BIO *channel,
|
||||
X509_POLICY_LEVEL *lev, X509_POLICY_NODE *node,
|
||||
int indent)
|
||||
@@ -163,6 +174,9 @@ static int tree_init(X509_POLICY_TREE **
|
||||
return X509_PCY_TREE_INTERNAL;
|
||||
}
|
||||
|
||||
+ /* Limit the growth of the tree to mitigate CVE-2023-0464 */
|
||||
+ tree->node_maximum = OPENSSL_POLICY_TREE_NODES_MAX;
|
||||
+
|
||||
/*
|
||||
* http://tools.ietf.org/html/rfc5280#section-6.1.2, figure 3.
|
||||
*
|
||||
@@ -180,7 +194,7 @@ static int tree_init(X509_POLICY_TREE **
|
||||
if ((data = ossl_policy_data_new(NULL,
|
||||
OBJ_nid2obj(NID_any_policy), 0)) == NULL)
|
||||
goto bad_tree;
|
||||
- if (ossl_policy_level_add_node(level, data, NULL, tree) == NULL) {
|
||||
+ if (ossl_policy_level_add_node(level, data, NULL, tree, 1) == NULL) {
|
||||
ossl_policy_data_free(data);
|
||||
goto bad_tree;
|
||||
}
|
||||
@@ -239,7 +253,8 @@ static int tree_init(X509_POLICY_TREE **
|
||||
* Return value: 1 on success, 0 otherwise
|
||||
*/
|
||||
static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr,
|
||||
- X509_POLICY_DATA *data)
|
||||
+ X509_POLICY_DATA *data,
|
||||
+ X509_POLICY_TREE *tree)
|
||||
{
|
||||
X509_POLICY_LEVEL *last = curr - 1;
|
||||
int i, matched = 0;
|
||||
@@ -249,13 +264,13 @@ static int tree_link_matching_nodes(X509
|
||||
X509_POLICY_NODE *node = sk_X509_POLICY_NODE_value(last->nodes, i);
|
||||
|
||||
if (ossl_policy_node_match(last, node, data->valid_policy)) {
|
||||
- if (ossl_policy_level_add_node(curr, data, node, NULL) == NULL)
|
||||
+ if (ossl_policy_level_add_node(curr, data, node, tree, 0) == NULL)
|
||||
return 0;
|
||||
matched = 1;
|
||||
}
|
||||
}
|
||||
if (!matched && last->anyPolicy) {
|
||||
- if (ossl_policy_level_add_node(curr, data, last->anyPolicy, NULL) == NULL)
|
||||
+ if (ossl_policy_level_add_node(curr, data, last->anyPolicy, tree, 0) == NULL)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -268,7 +283,8 @@ static int tree_link_matching_nodes(X509
|
||||
* Return value: 1 on success, 0 otherwise.
|
||||
*/
|
||||
static int tree_link_nodes(X509_POLICY_LEVEL *curr,
|
||||
- const X509_POLICY_CACHE *cache)
|
||||
+ const X509_POLICY_CACHE *cache,
|
||||
+ X509_POLICY_TREE *tree)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -276,7 +292,7 @@ static int tree_link_nodes(X509_POLICY_L
|
||||
X509_POLICY_DATA *data = sk_X509_POLICY_DATA_value(cache->data, i);
|
||||
|
||||
/* Look for matching nodes in previous level */
|
||||
- if (!tree_link_matching_nodes(curr, data))
|
||||
+ if (!tree_link_matching_nodes(curr, data, tree))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -307,7 +323,7 @@ static int tree_add_unmatched(X509_POLIC
|
||||
/* Curr may not have anyPolicy */
|
||||
data->qualifier_set = cache->anyPolicy->qualifier_set;
|
||||
data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
|
||||
- if (ossl_policy_level_add_node(curr, data, node, tree) == NULL) {
|
||||
+ if (ossl_policy_level_add_node(curr, data, node, tree, 1) == NULL) {
|
||||
ossl_policy_data_free(data);
|
||||
return 0;
|
||||
}
|
||||
@@ -370,7 +386,7 @@ static int tree_link_any(X509_POLICY_LEV
|
||||
/* Finally add link to anyPolicy */
|
||||
if (last->anyPolicy &&
|
||||
ossl_policy_level_add_node(curr, cache->anyPolicy,
|
||||
- last->anyPolicy, NULL) == NULL)
|
||||
+ last->anyPolicy, tree, 0) == NULL)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
@@ -553,7 +569,7 @@ static int tree_calculate_user_set(X509_
|
||||
extra->flags = POLICY_DATA_FLAG_SHARED_QUALIFIERS
|
||||
| POLICY_DATA_FLAG_EXTRA_NODE;
|
||||
node = ossl_policy_level_add_node(NULL, extra, anyPolicy->parent,
|
||||
- tree);
|
||||
+ tree, 1);
|
||||
}
|
||||
if (!tree->user_policies) {
|
||||
tree->user_policies = sk_X509_POLICY_NODE_new_null();
|
||||
@@ -580,7 +596,7 @@ static int tree_evaluate(X509_POLICY_TRE
|
||||
|
||||
for (i = 1; i < tree->nlevel; i++, curr++) {
|
||||
cache = ossl_policy_cache_set(curr->cert);
|
||||
- if (!tree_link_nodes(curr, cache))
|
||||
+ if (!tree_link_nodes(curr, cache, tree))
|
||||
return X509_PCY_TREE_INTERNAL;
|
||||
|
||||
if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY)
|
|
@ -0,0 +1,44 @@
|
|||
From 1dd43e0709fece299b15208f36cc7c76209ba0bb Mon Sep 17 00:00:00 2001
|
||||
From: Matt Caswell <matt@openssl.org>
|
||||
Date: Tue, 7 Mar 2023 16:52:55 +0000
|
||||
Subject: [PATCH] Ensure that EXFLAG_INVALID_POLICY is checked even in leaf
|
||||
certs
|
||||
|
||||
Even though we check the leaf cert to confirm it is valid, we
|
||||
later ignored the invalid flag and did not notice that the leaf
|
||||
cert was bad.
|
||||
|
||||
Fixes: CVE-2023-0465
|
||||
|
||||
Reviewed-by: Hugo Landau <hlandau@openssl.org>
|
||||
Reviewed-by: Tomas Mraz <tomas@openssl.org>
|
||||
(Merged from https://github.com/openssl/openssl/pull/20587)
|
||||
|
||||
--- a/crypto/x509/x509_vfy.c
|
||||
+++ b/crypto/x509/x509_vfy.c
|
||||
@@ -1654,15 +1654,23 @@ static int check_policy(X509_STORE_CTX *
|
||||
goto memerr;
|
||||
/* Invalid or inconsistent extensions */
|
||||
if (ret == X509_PCY_TREE_INVALID) {
|
||||
- int i;
|
||||
+ int i, cbcalled = 0;
|
||||
|
||||
/* Locate certificates with bad extensions and notify callback. */
|
||||
- for (i = 1; i < sk_X509_num(ctx->chain); i++) {
|
||||
+ for (i = 0; i < sk_X509_num(ctx->chain); i++) {
|
||||
X509 *x = sk_X509_value(ctx->chain, i);
|
||||
|
||||
+ if ((x->ex_flags & EXFLAG_INVALID_POLICY) != 0)
|
||||
+ cbcalled = 1;
|
||||
CB_FAIL_IF((x->ex_flags & EXFLAG_INVALID_POLICY) != 0,
|
||||
ctx, x, i, X509_V_ERR_INVALID_POLICY_EXTENSION);
|
||||
}
|
||||
+ if (!cbcalled) {
|
||||
+ /* Should not be able to get here */
|
||||
+ ERR_raise(ERR_LIB_X509, ERR_R_INTERNAL_ERROR);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ /* The callback ignored the error so we return success */
|
||||
return 1;
|
||||
}
|
||||
if (ret == X509_PCY_TREE_FAILURE) {
|
|
@ -12,9 +12,9 @@ PKG_RELEASE:=1
|
|||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL=$(PROJECT_GIT)/project/odhcpd.git
|
||||
PKG_MIRROR_HASH:=f95c2edfa6756e2a6522cd9d3e0560bfc1cbc2aed9e0c3763c5f6081b153eb49
|
||||
PKG_SOURCE_DATE:=2023-03-24
|
||||
PKG_SOURCE_VERSION:=29c934d7ab98ca0b5da0e3757b885a1d3c19a2f4
|
||||
PKG_MIRROR_HASH:=c2851b577d1ee632c902eca1864444fa22cad98956bfa852019e6d621c0f8d2a
|
||||
PKG_SOURCE_DATE:=2023-04-05
|
||||
PKG_SOURCE_VERSION:=40ab806bf4c8698ac925d094ce11ce1d57ae2e46
|
||||
|
||||
PKG_MAINTAINER:=Hans Dedecker <dedeckeh@gmail.com>
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
|
|
|
@ -106,7 +106,7 @@ configfs: New of_overlay API
|
|||
+++ b/drivers/of/Makefile
|
||||
@@ -1,6 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-y = base.o device.o platform.o property.o
|
||||
obj-y = base.o device.o module.o platform.o property.o
|
||||
obj-$(CONFIG_OF_KOBJ) += kobj.o
|
||||
+obj-$(CONFIG_OF_CONFIGFS) += configfs.o
|
||||
obj-$(CONFIG_OF_DYNAMIC) += dynamic.o
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
From bcd1fe07def0f070eb5f31594620aaee6f81d31a Mon Sep 17 00:00:00 2001
|
||||
From: Nick Alcock <nick.alcock@oracle.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:11 +0100
|
||||
Subject: [PATCH] nvmem: xilinx: zynqmp: make modular
|
||||
|
||||
This driver has a MODULE_LICENSE but is not tristate so cannot be
|
||||
built as a module, unlike all its peers: make it modular to match.
|
||||
|
||||
Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
|
||||
Suggested-by: Michal Simek <michal.simek@amd.com>
|
||||
Cc: Luis Chamberlain <mcgrof@kernel.org>
|
||||
Cc: linux-modules@vger.kernel.org
|
||||
Cc: linux-kernel@vger.kernel.org
|
||||
Cc: Hitomi Hasegawa <hasegawa-hitomi@fujitsu.com>
|
||||
Cc: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Cc: Michal Simek <michal.simek@xilinx.com>
|
||||
Cc: linux-arm-kernel@lists.infradead.org
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-4-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/Kconfig | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/nvmem/Kconfig
|
||||
+++ b/drivers/nvmem/Kconfig
|
||||
@@ -368,7 +368,7 @@ config NVMEM_VF610_OCOTP
|
||||
be called nvmem-vf610-ocotp.
|
||||
|
||||
config NVMEM_ZYNQMP
|
||||
- bool "Xilinx ZYNQMP SoC nvmem firmware support"
|
||||
+ tristate "Xilinx ZYNQMP SoC nvmem firmware support"
|
||||
depends on ARCH_ZYNQMP
|
||||
help
|
||||
This is a driver to access hardware related data like
|
|
@ -0,0 +1,387 @@
|
|||
From 266570f496b90dea8fda893c2cf7c28d63ae2bd9 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Walle <michael@walle.cc>
|
||||
Date: Tue, 4 Apr 2023 18:21:21 +0100
|
||||
Subject: [PATCH] nvmem: core: introduce NVMEM layouts
|
||||
|
||||
NVMEM layouts are used to generate NVMEM cells during runtime. Think of
|
||||
an EEPROM with a well-defined conent. For now, the content can be
|
||||
described by a device tree or a board file. But this only works if the
|
||||
offsets and lengths are static and don't change. One could also argue
|
||||
that putting the layout of the EEPROM in the device tree is the wrong
|
||||
place. Instead, the device tree should just have a specific compatible
|
||||
string.
|
||||
|
||||
Right now there are two use cases:
|
||||
(1) The NVMEM cell needs special processing. E.g. if it only specifies
|
||||
a base MAC address offset and you need to add an offset, or it
|
||||
needs to parse a MAC from ASCII format or some proprietary format.
|
||||
(Post processing of cells is added in a later commit).
|
||||
(2) u-boot environment parsing. The cells don't have a particular
|
||||
offset but it needs parsing the content to determine the offsets
|
||||
and length.
|
||||
|
||||
Co-developed-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Signed-off-by: Michael Walle <michael@walle.cc>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-14-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
Documentation/driver-api/nvmem.rst | 15 ++++
|
||||
drivers/nvmem/Kconfig | 4 +
|
||||
drivers/nvmem/Makefile | 1 +
|
||||
drivers/nvmem/core.c | 120 +++++++++++++++++++++++++++++
|
||||
drivers/nvmem/layouts/Kconfig | 5 ++
|
||||
drivers/nvmem/layouts/Makefile | 4 +
|
||||
include/linux/nvmem-consumer.h | 7 ++
|
||||
include/linux/nvmem-provider.h | 51 ++++++++++++
|
||||
8 files changed, 207 insertions(+)
|
||||
create mode 100644 drivers/nvmem/layouts/Kconfig
|
||||
create mode 100644 drivers/nvmem/layouts/Makefile
|
||||
|
||||
--- a/Documentation/driver-api/nvmem.rst
|
||||
+++ b/Documentation/driver-api/nvmem.rst
|
||||
@@ -189,3 +189,18 @@ ex::
|
||||
=====================
|
||||
|
||||
See Documentation/devicetree/bindings/nvmem/nvmem.txt
|
||||
+
|
||||
+8. NVMEM layouts
|
||||
+================
|
||||
+
|
||||
+NVMEM layouts are yet another mechanism to create cells. With the device
|
||||
+tree binding it is possible to specify simple cells by using an offset
|
||||
+and a length. Sometimes, the cells doesn't have a static offset, but
|
||||
+the content is still well defined, e.g. tag-length-values. In this case,
|
||||
+the NVMEM device content has to be first parsed and the cells need to
|
||||
+be added accordingly. Layouts let you read the content of the NVMEM device
|
||||
+and let you add cells dynamically.
|
||||
+
|
||||
+Another use case for layouts is the post processing of cells. With layouts,
|
||||
+it is possible to associate a custom post processing hook to a cell. It
|
||||
+even possible to add this hook to cells not created by the layout itself.
|
||||
--- a/drivers/nvmem/Kconfig
|
||||
+++ b/drivers/nvmem/Kconfig
|
||||
@@ -21,6 +21,10 @@ config NVMEM_SYSFS
|
||||
This interface is mostly used by userspace applications to
|
||||
read/write directly into nvmem.
|
||||
|
||||
+# Layouts
|
||||
+
|
||||
+source "drivers/nvmem/layouts/Kconfig"
|
||||
+
|
||||
# Devices
|
||||
|
||||
config NVMEM_APPLE_EFUSES
|
||||
--- a/drivers/nvmem/Makefile
|
||||
+++ b/drivers/nvmem/Makefile
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
obj-$(CONFIG_NVMEM) += nvmem_core.o
|
||||
nvmem_core-y := core.o
|
||||
+obj-y += layouts/
|
||||
|
||||
# Devices
|
||||
obj-$(CONFIG_NVMEM_APPLE_EFUSES) += nvmem-apple-efuses.o
|
||||
--- a/drivers/nvmem/core.c
|
||||
+++ b/drivers/nvmem/core.c
|
||||
@@ -40,6 +40,7 @@ struct nvmem_device {
|
||||
nvmem_reg_write_t reg_write;
|
||||
nvmem_cell_post_process_t cell_post_process;
|
||||
struct gpio_desc *wp_gpio;
|
||||
+ struct nvmem_layout *layout;
|
||||
void *priv;
|
||||
};
|
||||
|
||||
@@ -74,6 +75,9 @@ static LIST_HEAD(nvmem_lookup_list);
|
||||
|
||||
static BLOCKING_NOTIFIER_HEAD(nvmem_notifier);
|
||||
|
||||
+static DEFINE_SPINLOCK(nvmem_layout_lock);
|
||||
+static LIST_HEAD(nvmem_layouts);
|
||||
+
|
||||
static int __nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset,
|
||||
void *val, size_t bytes)
|
||||
{
|
||||
@@ -728,6 +732,101 @@ static int nvmem_add_cells_from_of(struc
|
||||
return 0;
|
||||
}
|
||||
|
||||
+int __nvmem_layout_register(struct nvmem_layout *layout, struct module *owner)
|
||||
+{
|
||||
+ layout->owner = owner;
|
||||
+
|
||||
+ spin_lock(&nvmem_layout_lock);
|
||||
+ list_add(&layout->node, &nvmem_layouts);
|
||||
+ spin_unlock(&nvmem_layout_lock);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(__nvmem_layout_register);
|
||||
+
|
||||
+void nvmem_layout_unregister(struct nvmem_layout *layout)
|
||||
+{
|
||||
+ spin_lock(&nvmem_layout_lock);
|
||||
+ list_del(&layout->node);
|
||||
+ spin_unlock(&nvmem_layout_lock);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(nvmem_layout_unregister);
|
||||
+
|
||||
+static struct nvmem_layout *nvmem_layout_get(struct nvmem_device *nvmem)
|
||||
+{
|
||||
+ struct device_node *layout_np, *np = nvmem->dev.of_node;
|
||||
+ struct nvmem_layout *l, *layout = NULL;
|
||||
+
|
||||
+ layout_np = of_get_child_by_name(np, "nvmem-layout");
|
||||
+ if (!layout_np)
|
||||
+ return NULL;
|
||||
+
|
||||
+ spin_lock(&nvmem_layout_lock);
|
||||
+
|
||||
+ list_for_each_entry(l, &nvmem_layouts, node) {
|
||||
+ if (of_match_node(l->of_match_table, layout_np)) {
|
||||
+ if (try_module_get(l->owner))
|
||||
+ layout = l;
|
||||
+
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ spin_unlock(&nvmem_layout_lock);
|
||||
+ of_node_put(layout_np);
|
||||
+
|
||||
+ return layout;
|
||||
+}
|
||||
+
|
||||
+static void nvmem_layout_put(struct nvmem_layout *layout)
|
||||
+{
|
||||
+ if (layout)
|
||||
+ module_put(layout->owner);
|
||||
+}
|
||||
+
|
||||
+static int nvmem_add_cells_from_layout(struct nvmem_device *nvmem)
|
||||
+{
|
||||
+ struct nvmem_layout *layout = nvmem->layout;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (layout && layout->add_cells) {
|
||||
+ ret = layout->add_cells(&nvmem->dev, nvmem, layout);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#if IS_ENABLED(CONFIG_OF)
|
||||
+/**
|
||||
+ * of_nvmem_layout_get_container() - Get OF node to layout container.
|
||||
+ *
|
||||
+ * @nvmem: nvmem device.
|
||||
+ *
|
||||
+ * Return: a node pointer with refcount incremented or NULL if no
|
||||
+ * container exists. Use of_node_put() on it when done.
|
||||
+ */
|
||||
+struct device_node *of_nvmem_layout_get_container(struct nvmem_device *nvmem)
|
||||
+{
|
||||
+ return of_get_child_by_name(nvmem->dev.of_node, "nvmem-layout");
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(of_nvmem_layout_get_container);
|
||||
+#endif
|
||||
+
|
||||
+const void *nvmem_layout_get_match_data(struct nvmem_device *nvmem,
|
||||
+ struct nvmem_layout *layout)
|
||||
+{
|
||||
+ struct device_node __maybe_unused *layout_np;
|
||||
+ const struct of_device_id *match;
|
||||
+
|
||||
+ layout_np = of_nvmem_layout_get_container(nvmem);
|
||||
+ match = of_match_node(layout->of_match_table, layout_np);
|
||||
+
|
||||
+ return match ? match->data : NULL;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(nvmem_layout_get_match_data);
|
||||
+
|
||||
/**
|
||||
* nvmem_register() - Register a nvmem device for given nvmem_config.
|
||||
* Also creates a binary entry in /sys/bus/nvmem/devices/dev-name/nvmem
|
||||
@@ -834,6 +933,12 @@ struct nvmem_device *nvmem_register(cons
|
||||
goto err_put_device;
|
||||
}
|
||||
|
||||
+ /*
|
||||
+ * If the driver supplied a layout by config->layout, the module
|
||||
+ * pointer will be NULL and nvmem_layout_put() will be a noop.
|
||||
+ */
|
||||
+ nvmem->layout = config->layout ?: nvmem_layout_get(nvmem);
|
||||
+
|
||||
if (config->cells) {
|
||||
rval = nvmem_add_cells(nvmem, config->cells, config->ncells);
|
||||
if (rval)
|
||||
@@ -854,12 +959,17 @@ struct nvmem_device *nvmem_register(cons
|
||||
if (rval)
|
||||
goto err_remove_cells;
|
||||
|
||||
+ rval = nvmem_add_cells_from_layout(nvmem);
|
||||
+ if (rval)
|
||||
+ goto err_remove_cells;
|
||||
+
|
||||
blocking_notifier_call_chain(&nvmem_notifier, NVMEM_ADD, nvmem);
|
||||
|
||||
return nvmem;
|
||||
|
||||
err_remove_cells:
|
||||
nvmem_device_remove_all_cells(nvmem);
|
||||
+ nvmem_layout_put(nvmem->layout);
|
||||
if (config->compat)
|
||||
nvmem_sysfs_remove_compat(nvmem, config);
|
||||
err_put_device:
|
||||
@@ -881,6 +991,7 @@ static void nvmem_device_release(struct
|
||||
device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom);
|
||||
|
||||
nvmem_device_remove_all_cells(nvmem);
|
||||
+ nvmem_layout_put(nvmem->layout);
|
||||
device_unregister(&nvmem->dev);
|
||||
}
|
||||
|
||||
@@ -1246,6 +1357,15 @@ struct nvmem_cell *of_nvmem_cell_get(str
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
+ /* nvmem layouts produce cells within the nvmem-layout container */
|
||||
+ if (of_node_name_eq(nvmem_np, "nvmem-layout")) {
|
||||
+ nvmem_np = of_get_next_parent(nvmem_np);
|
||||
+ if (!nvmem_np) {
|
||||
+ of_node_put(cell_np);
|
||||
+ return ERR_PTR(-EINVAL);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
nvmem = __nvmem_device_get(nvmem_np, device_match_of_node);
|
||||
of_node_put(nvmem_np);
|
||||
if (IS_ERR(nvmem)) {
|
||||
--- /dev/null
|
||||
+++ b/drivers/nvmem/layouts/Kconfig
|
||||
@@ -0,0 +1,5 @@
|
||||
+# SPDX-License-Identifier: GPL-2.0
|
||||
+
|
||||
+menu "Layout Types"
|
||||
+
|
||||
+endmenu
|
||||
--- /dev/null
|
||||
+++ b/drivers/nvmem/layouts/Makefile
|
||||
@@ -0,0 +1,4 @@
|
||||
+# SPDX-License-Identifier: GPL-2.0
|
||||
+#
|
||||
+# Makefile for nvmem layouts.
|
||||
+#
|
||||
--- a/include/linux/nvmem-consumer.h
|
||||
+++ b/include/linux/nvmem-consumer.h
|
||||
@@ -225,6 +225,7 @@ struct nvmem_cell *of_nvmem_cell_get(str
|
||||
const char *id);
|
||||
struct nvmem_device *of_nvmem_device_get(struct device_node *np,
|
||||
const char *name);
|
||||
+struct device_node *of_nvmem_layout_get_container(struct nvmem_device *nvmem);
|
||||
#else
|
||||
static inline struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
|
||||
const char *id)
|
||||
@@ -237,6 +238,12 @@ static inline struct nvmem_device *of_nv
|
||||
{
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
+
|
||||
+static inline struct device_node *
|
||||
+of_nvmem_layout_get_container(struct nvmem_device *nvmem)
|
||||
+{
|
||||
+ return ERR_PTR(-EOPNOTSUPP);
|
||||
+}
|
||||
#endif /* CONFIG_NVMEM && CONFIG_OF */
|
||||
|
||||
#endif /* ifndef _LINUX_NVMEM_CONSUMER_H */
|
||||
--- a/include/linux/nvmem-provider.h
|
||||
+++ b/include/linux/nvmem-provider.h
|
||||
@@ -88,6 +88,7 @@ struct nvmem_cell_info {
|
||||
* @stride: Minimum read/write access stride.
|
||||
* @priv: User context passed to read/write callbacks.
|
||||
* @ignore_wp: Write Protect pin is managed by the provider.
|
||||
+ * @layout: Fixed layout associated with this nvmem device.
|
||||
*
|
||||
* Note: A default "nvmem<id>" name will be assigned to the device if
|
||||
* no name is specified in its configuration. In such case "<id>" is
|
||||
@@ -110,6 +111,7 @@ struct nvmem_config {
|
||||
bool root_only;
|
||||
struct device_node *of_node;
|
||||
bool ignore_wp;
|
||||
+ struct nvmem_layout *layout;
|
||||
bool no_of_node;
|
||||
nvmem_reg_read_t reg_read;
|
||||
nvmem_reg_write_t reg_write;
|
||||
@@ -142,6 +144,33 @@ struct nvmem_cell_table {
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
+/**
|
||||
+ * struct nvmem_layout - NVMEM layout definitions
|
||||
+ *
|
||||
+ * @name: Layout name.
|
||||
+ * @of_match_table: Open firmware match table.
|
||||
+ * @add_cells: Will be called if a nvmem device is found which
|
||||
+ * has this layout. The function will add layout
|
||||
+ * specific cells with nvmem_add_one_cell().
|
||||
+ * @owner: Pointer to struct module.
|
||||
+ * @node: List node.
|
||||
+ *
|
||||
+ * A nvmem device can hold a well defined structure which can just be
|
||||
+ * evaluated during runtime. For example a TLV list, or a list of "name=val"
|
||||
+ * pairs. A nvmem layout can parse the nvmem device and add appropriate
|
||||
+ * cells.
|
||||
+ */
|
||||
+struct nvmem_layout {
|
||||
+ const char *name;
|
||||
+ const struct of_device_id *of_match_table;
|
||||
+ int (*add_cells)(struct device *dev, struct nvmem_device *nvmem,
|
||||
+ struct nvmem_layout *layout);
|
||||
+
|
||||
+ /* private */
|
||||
+ struct module *owner;
|
||||
+ struct list_head node;
|
||||
+};
|
||||
+
|
||||
#if IS_ENABLED(CONFIG_NVMEM)
|
||||
|
||||
struct nvmem_device *nvmem_register(const struct nvmem_config *cfg);
|
||||
@@ -156,6 +185,14 @@ void nvmem_del_cell_table(struct nvmem_c
|
||||
int nvmem_add_one_cell(struct nvmem_device *nvmem,
|
||||
const struct nvmem_cell_info *info);
|
||||
|
||||
+int __nvmem_layout_register(struct nvmem_layout *layout, struct module *owner);
|
||||
+#define nvmem_layout_register(layout) \
|
||||
+ __nvmem_layout_register(layout, THIS_MODULE)
|
||||
+void nvmem_layout_unregister(struct nvmem_layout *layout);
|
||||
+
|
||||
+const void *nvmem_layout_get_match_data(struct nvmem_device *nvmem,
|
||||
+ struct nvmem_layout *layout);
|
||||
+
|
||||
#else
|
||||
|
||||
static inline struct nvmem_device *nvmem_register(const struct nvmem_config *c)
|
||||
@@ -179,5 +216,19 @@ static inline int nvmem_add_one_cell(str
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
+static inline int nvmem_layout_register(struct nvmem_layout *layout)
|
||||
+{
|
||||
+ return -EOPNOTSUPP;
|
||||
+}
|
||||
+
|
||||
+static inline void nvmem_layout_unregister(struct nvmem_layout *layout) {}
|
||||
+
|
||||
+static inline const void *
|
||||
+nvmem_layout_get_match_data(struct nvmem_device *nvmem,
|
||||
+ struct nvmem_layout *layout)
|
||||
+{
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
#endif /* CONFIG_NVMEM */
|
||||
#endif /* ifndef _LINUX_NVMEM_PROVIDER_H */
|
|
@ -0,0 +1,61 @@
|
|||
From 6468a6f45148fb5e95c86b4efebf63f9abcd2137 Mon Sep 17 00:00:00 2001
|
||||
From: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:22 +0100
|
||||
Subject: [PATCH] nvmem: core: handle the absence of expected layouts
|
||||
|
||||
Make nvmem_layout_get() return -EPROBE_DEFER while the expected layout
|
||||
is not available. This condition cannot be triggered today as nvmem
|
||||
layout drivers are initialed as part of an early init call, but soon
|
||||
these drivers will be converted into modules and be initialized with a
|
||||
standard priority, so the unavailability of the drivers might become a
|
||||
reality that must be taken care of.
|
||||
|
||||
Let's anticipate this by telling the caller the layout might not yet be
|
||||
available. A probe deferral is requested in this case.
|
||||
|
||||
Please note this does not affect any nvmem device not using layouts,
|
||||
because an early check against the "nvmem-layout" container presence
|
||||
will return NULL in this case.
|
||||
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Tested-by: Michael Walle <michael@walle.cc>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-15-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/core.c | 10 +++++++++-
|
||||
1 file changed, 9 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/nvmem/core.c
|
||||
+++ b/drivers/nvmem/core.c
|
||||
@@ -755,7 +755,7 @@ EXPORT_SYMBOL_GPL(nvmem_layout_unregiste
|
||||
static struct nvmem_layout *nvmem_layout_get(struct nvmem_device *nvmem)
|
||||
{
|
||||
struct device_node *layout_np, *np = nvmem->dev.of_node;
|
||||
- struct nvmem_layout *l, *layout = NULL;
|
||||
+ struct nvmem_layout *l, *layout = ERR_PTR(-EPROBE_DEFER);
|
||||
|
||||
layout_np = of_get_child_by_name(np, "nvmem-layout");
|
||||
if (!layout_np)
|
||||
@@ -938,6 +938,13 @@ struct nvmem_device *nvmem_register(cons
|
||||
* pointer will be NULL and nvmem_layout_put() will be a noop.
|
||||
*/
|
||||
nvmem->layout = config->layout ?: nvmem_layout_get(nvmem);
|
||||
+ if (IS_ERR(nvmem->layout)) {
|
||||
+ rval = PTR_ERR(nvmem->layout);
|
||||
+ nvmem->layout = NULL;
|
||||
+
|
||||
+ if (rval == -EPROBE_DEFER)
|
||||
+ goto err_teardown_compat;
|
||||
+ }
|
||||
|
||||
if (config->cells) {
|
||||
rval = nvmem_add_cells(nvmem, config->cells, config->ncells);
|
||||
@@ -970,6 +977,7 @@ struct nvmem_device *nvmem_register(cons
|
||||
err_remove_cells:
|
||||
nvmem_device_remove_all_cells(nvmem);
|
||||
nvmem_layout_put(nvmem->layout);
|
||||
+err_teardown_compat:
|
||||
if (config->compat)
|
||||
nvmem_sysfs_remove_compat(nvmem, config);
|
||||
err_put_device:
|
|
@ -0,0 +1,52 @@
|
|||
From b1c37bec1ccfe5ccab72bc0ddc0dfa45c43e2de2 Mon Sep 17 00:00:00 2001
|
||||
From: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:23 +0100
|
||||
Subject: [PATCH] nvmem: core: request layout modules loading
|
||||
|
||||
When a storage device like an eeprom or an mtd device probes, it
|
||||
registers an nvmem device if the nvmem subsystem has been enabled (bool
|
||||
symbol). During nvmem registration, if the device is using layouts to
|
||||
expose dynamic nvmem cells, the core will first try to get a reference
|
||||
over the layout driver callbacks. In practice there is not relationship
|
||||
that can be described between the storage driver and the nvmem
|
||||
layout. So there is no way we can enforce both drivers will be built-in
|
||||
or both will be modules. If the storage device driver is built-in but
|
||||
the layout is built as a module, instead of badly failing with an
|
||||
endless probe deferral loop, lets just make a modprobe call in case the
|
||||
driver was made available in an initramfs with
|
||||
of_device_node_request_module(), and offer a fully functional system to
|
||||
the user.
|
||||
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Tested-by: Michael Walle <michael@walle.cc>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-16-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/core.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
--- a/drivers/nvmem/core.c
|
||||
+++ b/drivers/nvmem/core.c
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <linux/nvmem-provider.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/of.h>
|
||||
+#include <linux/of_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
struct nvmem_device {
|
||||
@@ -761,6 +762,13 @@ static struct nvmem_layout *nvmem_layout
|
||||
if (!layout_np)
|
||||
return NULL;
|
||||
|
||||
+ /*
|
||||
+ * In case the nvmem device was built-in while the layout was built as a
|
||||
+ * module, we shall manually request the layout driver loading otherwise
|
||||
+ * we'll never have any match.
|
||||
+ */
|
||||
+ of_request_module(layout_np);
|
||||
+
|
||||
spin_lock(&nvmem_layout_lock);
|
||||
|
||||
list_for_each_entry(l, &nvmem_layouts, node) {
|
|
@ -0,0 +1,86 @@
|
|||
From 345ec382cd4b736c36e01f155d08c913b225b736 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Walle <michael@walle.cc>
|
||||
Date: Tue, 4 Apr 2023 18:21:24 +0100
|
||||
Subject: [PATCH] nvmem: core: add per-cell post processing
|
||||
|
||||
Instead of relying on the name the consumer is using for the cell, like
|
||||
it is done for the nvmem .cell_post_process configuration parameter,
|
||||
provide a per-cell post processing hook. This can then be populated by
|
||||
the NVMEM provider (or the NVMEM layout) when adding the cell.
|
||||
|
||||
Signed-off-by: Michael Walle <michael@walle.cc>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-17-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/core.c | 17 +++++++++++++++++
|
||||
include/linux/nvmem-provider.h | 3 +++
|
||||
2 files changed, 20 insertions(+)
|
||||
|
||||
--- a/drivers/nvmem/core.c
|
||||
+++ b/drivers/nvmem/core.c
|
||||
@@ -54,6 +54,7 @@ struct nvmem_cell_entry {
|
||||
int bytes;
|
||||
int bit_offset;
|
||||
int nbits;
|
||||
+ nvmem_cell_post_process_t read_post_process;
|
||||
struct device_node *np;
|
||||
struct nvmem_device *nvmem;
|
||||
struct list_head node;
|
||||
@@ -470,6 +471,7 @@ static int nvmem_cell_info_to_nvmem_cell
|
||||
cell->offset = info->offset;
|
||||
cell->bytes = info->bytes;
|
||||
cell->name = info->name;
|
||||
+ cell->read_post_process = info->read_post_process;
|
||||
|
||||
cell->bit_offset = info->bit_offset;
|
||||
cell->nbits = info->nbits;
|
||||
@@ -1563,6 +1565,13 @@ static int __nvmem_cell_read(struct nvme
|
||||
if (cell->bit_offset || cell->nbits)
|
||||
nvmem_shift_read_buffer_in_place(cell, buf);
|
||||
|
||||
+ if (cell->read_post_process) {
|
||||
+ rc = cell->read_post_process(nvmem->priv, id, index,
|
||||
+ cell->offset, buf, cell->bytes);
|
||||
+ if (rc)
|
||||
+ return rc;
|
||||
+ }
|
||||
+
|
||||
if (nvmem->cell_post_process) {
|
||||
rc = nvmem->cell_post_process(nvmem->priv, id, index,
|
||||
cell->offset, buf, cell->bytes);
|
||||
@@ -1671,6 +1680,14 @@ static int __nvmem_cell_entry_write(stru
|
||||
(cell->bit_offset == 0 && len != cell->bytes))
|
||||
return -EINVAL;
|
||||
|
||||
+ /*
|
||||
+ * Any cells which have a read_post_process hook are read-only because
|
||||
+ * we cannot reverse the operation and it might affect other cells,
|
||||
+ * too.
|
||||
+ */
|
||||
+ if (cell->read_post_process)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
if (cell->bit_offset || cell->nbits) {
|
||||
buf = nvmem_cell_prepare_write_buffer(cell, buf, len);
|
||||
if (IS_ERR(buf))
|
||||
--- a/include/linux/nvmem-provider.h
|
||||
+++ b/include/linux/nvmem-provider.h
|
||||
@@ -54,6 +54,8 @@ struct nvmem_keepout {
|
||||
* @bit_offset: Bit offset if cell is smaller than a byte.
|
||||
* @nbits: Number of bits.
|
||||
* @np: Optional device_node pointer.
|
||||
+ * @read_post_process: Callback for optional post processing of cell data
|
||||
+ * on reads.
|
||||
*/
|
||||
struct nvmem_cell_info {
|
||||
const char *name;
|
||||
@@ -62,6 +64,7 @@ struct nvmem_cell_info {
|
||||
unsigned int bit_offset;
|
||||
unsigned int nbits;
|
||||
struct device_node *np;
|
||||
+ nvmem_cell_post_process_t read_post_process;
|
||||
};
|
||||
|
||||
/**
|
|
@ -0,0 +1,59 @@
|
|||
From de12c9691501ccba41a154c223869f82be4c12fd Mon Sep 17 00:00:00 2001
|
||||
From: Michael Walle <michael@walle.cc>
|
||||
Date: Tue, 4 Apr 2023 18:21:25 +0100
|
||||
Subject: [PATCH] nvmem: core: allow to modify a cell before adding it
|
||||
|
||||
Provide a way to modify a cell before it will get added. This is useful
|
||||
to attach a custom post processing hook via a layout.
|
||||
|
||||
Signed-off-by: Michael Walle <michael@walle.cc>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-18-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/core.c | 4 ++++
|
||||
include/linux/nvmem-provider.h | 5 +++++
|
||||
2 files changed, 9 insertions(+)
|
||||
|
||||
--- a/drivers/nvmem/core.c
|
||||
+++ b/drivers/nvmem/core.c
|
||||
@@ -695,6 +695,7 @@ static int nvmem_validate_keepouts(struc
|
||||
|
||||
static int nvmem_add_cells_from_of(struct nvmem_device *nvmem)
|
||||
{
|
||||
+ struct nvmem_layout *layout = nvmem->layout;
|
||||
struct device *dev = &nvmem->dev;
|
||||
struct device_node *child;
|
||||
const __be32 *addr;
|
||||
@@ -724,6 +725,9 @@ static int nvmem_add_cells_from_of(struc
|
||||
|
||||
info.np = of_node_get(child);
|
||||
|
||||
+ if (layout && layout->fixup_cell_info)
|
||||
+ layout->fixup_cell_info(nvmem, layout, &info);
|
||||
+
|
||||
ret = nvmem_add_one_cell(nvmem, &info);
|
||||
kfree(info.name);
|
||||
if (ret) {
|
||||
--- a/include/linux/nvmem-provider.h
|
||||
+++ b/include/linux/nvmem-provider.h
|
||||
@@ -155,6 +155,8 @@ struct nvmem_cell_table {
|
||||
* @add_cells: Will be called if a nvmem device is found which
|
||||
* has this layout. The function will add layout
|
||||
* specific cells with nvmem_add_one_cell().
|
||||
+ * @fixup_cell_info: Will be called before a cell is added. Can be
|
||||
+ * used to modify the nvmem_cell_info.
|
||||
* @owner: Pointer to struct module.
|
||||
* @node: List node.
|
||||
*
|
||||
@@ -168,6 +170,9 @@ struct nvmem_layout {
|
||||
const struct of_device_id *of_match_table;
|
||||
int (*add_cells)(struct device *dev, struct nvmem_device *nvmem,
|
||||
struct nvmem_layout *layout);
|
||||
+ void (*fixup_cell_info)(struct nvmem_device *nvmem,
|
||||
+ struct nvmem_layout *layout,
|
||||
+ struct nvmem_cell_info *cell);
|
||||
|
||||
/* private */
|
||||
struct module *owner;
|
|
@ -0,0 +1,81 @@
|
|||
From 6c56a82d7895a213a43182a5d01a21a906a79847 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Walle <michael@walle.cc>
|
||||
Date: Tue, 4 Apr 2023 18:21:26 +0100
|
||||
Subject: [PATCH] nvmem: imx-ocotp: replace global post processing with layouts
|
||||
|
||||
In preparation of retiring the global post processing hook change this
|
||||
driver to use layouts. The layout will be supplied during registration
|
||||
and will be used to add the post processing hook to all added cells.
|
||||
|
||||
Signed-off-by: Michael Walle <michael@walle.cc>
|
||||
Tested-by: Michael Walle <michael@walle.cc> # on kontron-pitx-imx8m
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-19-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/imx-ocotp.c | 30 +++++++++++++++++++-----------
|
||||
1 file changed, 19 insertions(+), 11 deletions(-)
|
||||
|
||||
--- a/drivers/nvmem/imx-ocotp.c
|
||||
+++ b/drivers/nvmem/imx-ocotp.c
|
||||
@@ -225,18 +225,13 @@ read_end:
|
||||
static int imx_ocotp_cell_pp(void *context, const char *id, int index,
|
||||
unsigned int offset, void *data, size_t bytes)
|
||||
{
|
||||
- struct ocotp_priv *priv = context;
|
||||
+ u8 *buf = data;
|
||||
+ int i;
|
||||
|
||||
/* Deal with some post processing of nvmem cell data */
|
||||
- if (id && !strcmp(id, "mac-address")) {
|
||||
- if (priv->params->reverse_mac_address) {
|
||||
- u8 *buf = data;
|
||||
- int i;
|
||||
-
|
||||
- for (i = 0; i < bytes/2; i++)
|
||||
- swap(buf[i], buf[bytes - i - 1]);
|
||||
- }
|
||||
- }
|
||||
+ if (id && !strcmp(id, "mac-address"))
|
||||
+ for (i = 0; i < bytes / 2; i++)
|
||||
+ swap(buf[i], buf[bytes - i - 1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -488,7 +483,6 @@ static struct nvmem_config imx_ocotp_nvm
|
||||
.stride = 1,
|
||||
.reg_read = imx_ocotp_read,
|
||||
.reg_write = imx_ocotp_write,
|
||||
- .cell_post_process = imx_ocotp_cell_pp,
|
||||
};
|
||||
|
||||
static const struct ocotp_params imx6q_params = {
|
||||
@@ -595,6 +589,17 @@ static const struct of_device_id imx_oco
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, imx_ocotp_dt_ids);
|
||||
|
||||
+static void imx_ocotp_fixup_cell_info(struct nvmem_device *nvmem,
|
||||
+ struct nvmem_layout *layout,
|
||||
+ struct nvmem_cell_info *cell)
|
||||
+{
|
||||
+ cell->read_post_process = imx_ocotp_cell_pp;
|
||||
+}
|
||||
+
|
||||
+struct nvmem_layout imx_ocotp_layout = {
|
||||
+ .fixup_cell_info = imx_ocotp_fixup_cell_info,
|
||||
+};
|
||||
+
|
||||
static int imx_ocotp_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
@@ -619,6 +624,9 @@ static int imx_ocotp_probe(struct platfo
|
||||
imx_ocotp_nvmem_config.size = 4 * priv->params->nregs;
|
||||
imx_ocotp_nvmem_config.dev = dev;
|
||||
imx_ocotp_nvmem_config.priv = priv;
|
||||
+ if (priv->params->reverse_mac_address)
|
||||
+ imx_ocotp_nvmem_config.layout = &imx_ocotp_layout;
|
||||
+
|
||||
priv->config = &imx_ocotp_nvmem_config;
|
||||
|
||||
clk_prepare_enable(priv->clk);
|
|
@ -0,0 +1,68 @@
|
|||
From 011e40a166fdaa65fb9946b7cd91efec85b70dbb Mon Sep 17 00:00:00 2001
|
||||
From: Michael Walle <michael@walle.cc>
|
||||
Date: Tue, 4 Apr 2023 18:21:27 +0100
|
||||
Subject: [PATCH] nvmem: cell: drop global cell_post_process
|
||||
|
||||
There are no users anymore for the global cell_post_process callback
|
||||
anymore. New users should use proper nvmem layouts.
|
||||
|
||||
Signed-off-by: Michael Walle <michael@walle.cc>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-20-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/core.c | 9 ---------
|
||||
include/linux/nvmem-provider.h | 2 --
|
||||
2 files changed, 11 deletions(-)
|
||||
|
||||
--- a/drivers/nvmem/core.c
|
||||
+++ b/drivers/nvmem/core.c
|
||||
@@ -39,7 +39,6 @@ struct nvmem_device {
|
||||
unsigned int nkeepout;
|
||||
nvmem_reg_read_t reg_read;
|
||||
nvmem_reg_write_t reg_write;
|
||||
- nvmem_cell_post_process_t cell_post_process;
|
||||
struct gpio_desc *wp_gpio;
|
||||
struct nvmem_layout *layout;
|
||||
void *priv;
|
||||
@@ -903,7 +902,6 @@ struct nvmem_device *nvmem_register(cons
|
||||
nvmem->type = config->type;
|
||||
nvmem->reg_read = config->reg_read;
|
||||
nvmem->reg_write = config->reg_write;
|
||||
- nvmem->cell_post_process = config->cell_post_process;
|
||||
nvmem->keepout = config->keepout;
|
||||
nvmem->nkeepout = config->nkeepout;
|
||||
if (config->of_node)
|
||||
@@ -1575,13 +1573,6 @@ static int __nvmem_cell_read(struct nvme
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
-
|
||||
- if (nvmem->cell_post_process) {
|
||||
- rc = nvmem->cell_post_process(nvmem->priv, id, index,
|
||||
- cell->offset, buf, cell->bytes);
|
||||
- if (rc)
|
||||
- return rc;
|
||||
- }
|
||||
|
||||
if (len)
|
||||
*len = cell->bytes;
|
||||
--- a/include/linux/nvmem-provider.h
|
||||
+++ b/include/linux/nvmem-provider.h
|
||||
@@ -85,7 +85,6 @@ struct nvmem_cell_info {
|
||||
* @no_of_node: Device should not use the parent's of_node even if it's !NULL.
|
||||
* @reg_read: Callback to read data.
|
||||
* @reg_write: Callback to write data.
|
||||
- * @cell_post_process: Callback for vendor specific post processing of cell data
|
||||
* @size: Device size.
|
||||
* @word_size: Minimum read/write access granularity.
|
||||
* @stride: Minimum read/write access stride.
|
||||
@@ -118,7 +117,6 @@ struct nvmem_config {
|
||||
bool no_of_node;
|
||||
nvmem_reg_read_t reg_read;
|
||||
nvmem_reg_write_t reg_write;
|
||||
- nvmem_cell_post_process_t cell_post_process;
|
||||
int size;
|
||||
int word_size;
|
||||
int stride;
|
|
@ -0,0 +1,76 @@
|
|||
From 8a134fd9f9323f4c39ec27055b3d3723cfb5c1e9 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Walle <michael@walle.cc>
|
||||
Date: Tue, 4 Apr 2023 18:21:28 +0100
|
||||
Subject: [PATCH] nvmem: core: provide own priv pointer in post process
|
||||
callback
|
||||
|
||||
It doesn't make any more sense to have a opaque pointer set up by the
|
||||
nvmem device. Usually, the layout isn't associated with a particular
|
||||
nvmem device. Instead, let the caller who set the post process callback
|
||||
provide the priv pointer.
|
||||
|
||||
Signed-off-by: Michael Walle <michael@walle.cc>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-21-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/core.c | 4 +++-
|
||||
include/linux/nvmem-provider.h | 5 ++++-
|
||||
2 files changed, 7 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/nvmem/core.c
|
||||
+++ b/drivers/nvmem/core.c
|
||||
@@ -54,6 +54,7 @@ struct nvmem_cell_entry {
|
||||
int bit_offset;
|
||||
int nbits;
|
||||
nvmem_cell_post_process_t read_post_process;
|
||||
+ void *priv;
|
||||
struct device_node *np;
|
||||
struct nvmem_device *nvmem;
|
||||
struct list_head node;
|
||||
@@ -471,6 +472,7 @@ static int nvmem_cell_info_to_nvmem_cell
|
||||
cell->bytes = info->bytes;
|
||||
cell->name = info->name;
|
||||
cell->read_post_process = info->read_post_process;
|
||||
+ cell->priv = info->priv;
|
||||
|
||||
cell->bit_offset = info->bit_offset;
|
||||
cell->nbits = info->nbits;
|
||||
@@ -1568,7 +1570,7 @@ static int __nvmem_cell_read(struct nvme
|
||||
nvmem_shift_read_buffer_in_place(cell, buf);
|
||||
|
||||
if (cell->read_post_process) {
|
||||
- rc = cell->read_post_process(nvmem->priv, id, index,
|
||||
+ rc = cell->read_post_process(cell->priv, id, index,
|
||||
cell->offset, buf, cell->bytes);
|
||||
if (rc)
|
||||
return rc;
|
||||
--- a/include/linux/nvmem-provider.h
|
||||
+++ b/include/linux/nvmem-provider.h
|
||||
@@ -20,7 +20,8 @@ typedef int (*nvmem_reg_write_t)(void *p
|
||||
void *val, size_t bytes);
|
||||
/* used for vendor specific post processing of cell data */
|
||||
typedef int (*nvmem_cell_post_process_t)(void *priv, const char *id, int index,
|
||||
- unsigned int offset, void *buf, size_t bytes);
|
||||
+ unsigned int offset, void *buf,
|
||||
+ size_t bytes);
|
||||
|
||||
enum nvmem_type {
|
||||
NVMEM_TYPE_UNKNOWN = 0,
|
||||
@@ -56,6 +57,7 @@ struct nvmem_keepout {
|
||||
* @np: Optional device_node pointer.
|
||||
* @read_post_process: Callback for optional post processing of cell data
|
||||
* on reads.
|
||||
+ * @priv: Opaque data passed to the read_post_process hook.
|
||||
*/
|
||||
struct nvmem_cell_info {
|
||||
const char *name;
|
||||
@@ -65,6 +67,7 @@ struct nvmem_cell_info {
|
||||
unsigned int nbits;
|
||||
struct device_node *np;
|
||||
nvmem_cell_post_process_t read_post_process;
|
||||
+ void *priv;
|
||||
};
|
||||
|
||||
/**
|
|
@ -0,0 +1,215 @@
|
|||
From d9fae023fe86069750092fc1c2f3a73e2fb18512 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Walle <michael@walle.cc>
|
||||
Date: Tue, 4 Apr 2023 18:21:29 +0100
|
||||
Subject: [PATCH] nvmem: layouts: sl28vpd: Add new layout driver
|
||||
|
||||
This layout applies to the VPD of the Kontron sl28 boards. The VPD only
|
||||
contains a base MAC address. Therefore, we have to add an individual
|
||||
offset to it. This is done by taking the second argument of the nvmem
|
||||
phandle into account. Also this let us checking the VPD version and the
|
||||
checksum.
|
||||
|
||||
Signed-off-by: Michael Walle <michael@walle.cc>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-22-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/layouts/Kconfig | 9 ++
|
||||
drivers/nvmem/layouts/Makefile | 2 +
|
||||
drivers/nvmem/layouts/sl28vpd.c | 165 ++++++++++++++++++++++++++++++++
|
||||
3 files changed, 176 insertions(+)
|
||||
create mode 100644 drivers/nvmem/layouts/sl28vpd.c
|
||||
|
||||
--- a/drivers/nvmem/layouts/Kconfig
|
||||
+++ b/drivers/nvmem/layouts/Kconfig
|
||||
@@ -2,4 +2,13 @@
|
||||
|
||||
menu "Layout Types"
|
||||
|
||||
+config NVMEM_LAYOUT_SL28_VPD
|
||||
+ tristate "Kontron sl28 VPD layout support"
|
||||
+ select CRC8
|
||||
+ help
|
||||
+ Say Y here if you want to support the VPD layout of the Kontron
|
||||
+ SMARC-sAL28 boards.
|
||||
+
|
||||
+ If unsure, say N.
|
||||
+
|
||||
endmenu
|
||||
--- a/drivers/nvmem/layouts/Makefile
|
||||
+++ b/drivers/nvmem/layouts/Makefile
|
||||
@@ -2,3 +2,5 @@
|
||||
#
|
||||
# Makefile for nvmem layouts.
|
||||
#
|
||||
+
|
||||
+obj-$(CONFIG_NVMEM_LAYOUT_SL28_VPD) += sl28vpd.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/nvmem/layouts/sl28vpd.c
|
||||
@@ -0,0 +1,165 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+
|
||||
+#include <linux/crc8.h>
|
||||
+#include <linux/etherdevice.h>
|
||||
+#include <linux/nvmem-consumer.h>
|
||||
+#include <linux/nvmem-provider.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <uapi/linux/if_ether.h>
|
||||
+
|
||||
+#define SL28VPD_MAGIC 'V'
|
||||
+
|
||||
+struct sl28vpd_header {
|
||||
+ u8 magic;
|
||||
+ u8 version;
|
||||
+} __packed;
|
||||
+
|
||||
+struct sl28vpd_v1 {
|
||||
+ struct sl28vpd_header header;
|
||||
+ char serial_number[15];
|
||||
+ u8 base_mac_address[ETH_ALEN];
|
||||
+ u8 crc8;
|
||||
+} __packed;
|
||||
+
|
||||
+static int sl28vpd_mac_address_pp(void *priv, const char *id, int index,
|
||||
+ unsigned int offset, void *buf,
|
||||
+ size_t bytes)
|
||||
+{
|
||||
+ if (bytes != ETH_ALEN)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (index < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (!is_valid_ether_addr(buf))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ eth_addr_add(buf, index);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct nvmem_cell_info sl28vpd_v1_entries[] = {
|
||||
+ {
|
||||
+ .name = "serial-number",
|
||||
+ .offset = offsetof(struct sl28vpd_v1, serial_number),
|
||||
+ .bytes = sizeof_field(struct sl28vpd_v1, serial_number),
|
||||
+ },
|
||||
+ {
|
||||
+ .name = "base-mac-address",
|
||||
+ .offset = offsetof(struct sl28vpd_v1, base_mac_address),
|
||||
+ .bytes = sizeof_field(struct sl28vpd_v1, base_mac_address),
|
||||
+ .read_post_process = sl28vpd_mac_address_pp,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static int sl28vpd_v1_check_crc(struct device *dev, struct nvmem_device *nvmem)
|
||||
+{
|
||||
+ struct sl28vpd_v1 data_v1;
|
||||
+ u8 table[CRC8_TABLE_SIZE];
|
||||
+ int ret;
|
||||
+ u8 crc;
|
||||
+
|
||||
+ crc8_populate_msb(table, 0x07);
|
||||
+
|
||||
+ ret = nvmem_device_read(nvmem, 0, sizeof(data_v1), &data_v1);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ else if (ret != sizeof(data_v1))
|
||||
+ return -EIO;
|
||||
+
|
||||
+ crc = crc8(table, (void *)&data_v1, sizeof(data_v1) - 1, 0);
|
||||
+
|
||||
+ if (crc != data_v1.crc8) {
|
||||
+ dev_err(dev,
|
||||
+ "Checksum is invalid (got %02x, expected %02x).\n",
|
||||
+ crc, data_v1.crc8);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int sl28vpd_add_cells(struct device *dev, struct nvmem_device *nvmem,
|
||||
+ struct nvmem_layout *layout)
|
||||
+{
|
||||
+ const struct nvmem_cell_info *pinfo;
|
||||
+ struct nvmem_cell_info info = {0};
|
||||
+ struct device_node *layout_np;
|
||||
+ struct sl28vpd_header hdr;
|
||||
+ int ret, i;
|
||||
+
|
||||
+ /* check header */
|
||||
+ ret = nvmem_device_read(nvmem, 0, sizeof(hdr), &hdr);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ else if (ret != sizeof(hdr))
|
||||
+ return -EIO;
|
||||
+
|
||||
+ if (hdr.magic != SL28VPD_MAGIC) {
|
||||
+ dev_err(dev, "Invalid magic value (%02x)\n", hdr.magic);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (hdr.version != 1) {
|
||||
+ dev_err(dev, "Version %d is unsupported.\n", hdr.version);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ ret = sl28vpd_v1_check_crc(dev, nvmem);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ layout_np = of_nvmem_layout_get_container(nvmem);
|
||||
+ if (!layout_np)
|
||||
+ return -ENOENT;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(sl28vpd_v1_entries); i++) {
|
||||
+ pinfo = &sl28vpd_v1_entries[i];
|
||||
+
|
||||
+ info.name = pinfo->name;
|
||||
+ info.offset = pinfo->offset;
|
||||
+ info.bytes = pinfo->bytes;
|
||||
+ info.read_post_process = pinfo->read_post_process;
|
||||
+ info.np = of_get_child_by_name(layout_np, pinfo->name);
|
||||
+
|
||||
+ ret = nvmem_add_one_cell(nvmem, &info);
|
||||
+ if (ret) {
|
||||
+ of_node_put(layout_np);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ of_node_put(layout_np);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id sl28vpd_of_match_table[] = {
|
||||
+ { .compatible = "kontron,sl28-vpd" },
|
||||
+ {},
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, sl28vpd_of_match_table);
|
||||
+
|
||||
+struct nvmem_layout sl28vpd_layout = {
|
||||
+ .name = "sl28-vpd",
|
||||
+ .of_match_table = sl28vpd_of_match_table,
|
||||
+ .add_cells = sl28vpd_add_cells,
|
||||
+};
|
||||
+
|
||||
+static int __init sl28vpd_init(void)
|
||||
+{
|
||||
+ return nvmem_layout_register(&sl28vpd_layout);
|
||||
+}
|
||||
+
|
||||
+static void __exit sl28vpd_exit(void)
|
||||
+{
|
||||
+ nvmem_layout_unregister(&sl28vpd_layout);
|
||||
+}
|
||||
+
|
||||
+module_init(sl28vpd_init);
|
||||
+module_exit(sl28vpd_exit);
|
||||
+
|
||||
+MODULE_LICENSE("GPL");
|
||||
+MODULE_AUTHOR("Michael Walle <michael@walle.cc>");
|
||||
+MODULE_DESCRIPTION("NVMEM layout driver for the VPD of Kontron sl28 boards");
|
|
@ -0,0 +1,306 @@
|
|||
From d3c0d12f6474216bf386101e2449cc73e5c5b61d Mon Sep 17 00:00:00 2001
|
||||
From: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:31 +0100
|
||||
Subject: [PATCH] nvmem: layouts: onie-tlv: Add new layout driver
|
||||
|
||||
This layout applies on top of any non volatile storage device containing
|
||||
an ONIE table factory flashed. This table follows the tlv
|
||||
(type-length-value) organization described in the link below. We cannot
|
||||
afford using regular parsers because the content of these tables is
|
||||
manufacturer specific and must be dynamically discovered.
|
||||
|
||||
Link: https://opencomputeproject.github.io/onie/design-spec/hw_requirements.html
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-24-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/layouts/Kconfig | 9 ++
|
||||
drivers/nvmem/layouts/Makefile | 1 +
|
||||
drivers/nvmem/layouts/onie-tlv.c | 257 +++++++++++++++++++++++++++++++
|
||||
3 files changed, 267 insertions(+)
|
||||
create mode 100644 drivers/nvmem/layouts/onie-tlv.c
|
||||
|
||||
--- a/drivers/nvmem/layouts/Kconfig
|
||||
+++ b/drivers/nvmem/layouts/Kconfig
|
||||
@@ -11,4 +11,13 @@ config NVMEM_LAYOUT_SL28_VPD
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
+config NVMEM_LAYOUT_ONIE_TLV
|
||||
+ tristate "ONIE tlv support"
|
||||
+ select CRC32
|
||||
+ help
|
||||
+ Say Y here if you want to support the Open Compute Project ONIE
|
||||
+ Type-Length-Value standard table.
|
||||
+
|
||||
+ If unsure, say N.
|
||||
+
|
||||
endmenu
|
||||
--- a/drivers/nvmem/layouts/Makefile
|
||||
+++ b/drivers/nvmem/layouts/Makefile
|
||||
@@ -4,3 +4,4 @@
|
||||
#
|
||||
|
||||
obj-$(CONFIG_NVMEM_LAYOUT_SL28_VPD) += sl28vpd.o
|
||||
+obj-$(CONFIG_NVMEM_LAYOUT_ONIE_TLV) += onie-tlv.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/nvmem/layouts/onie-tlv.c
|
||||
@@ -0,0 +1,257 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-only
|
||||
+/*
|
||||
+ * ONIE tlv NVMEM cells provider
|
||||
+ *
|
||||
+ * Copyright (C) 2022 Open Compute Group ONIE
|
||||
+ * Author: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
+ * Based on the nvmem driver written by: Vadym Kochan <vadym.kochan@plvision.eu>
|
||||
+ * Inspired by the first layout written by: Rafał Miłecki <rafal@milecki.pl>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/crc32.h>
|
||||
+#include <linux/etherdevice.h>
|
||||
+#include <linux/nvmem-consumer.h>
|
||||
+#include <linux/nvmem-provider.h>
|
||||
+#include <linux/of.h>
|
||||
+
|
||||
+#define ONIE_TLV_MAX_LEN 2048
|
||||
+#define ONIE_TLV_CRC_FIELD_SZ 6
|
||||
+#define ONIE_TLV_CRC_SZ 4
|
||||
+#define ONIE_TLV_HDR_ID "TlvInfo"
|
||||
+
|
||||
+struct onie_tlv_hdr {
|
||||
+ u8 id[8];
|
||||
+ u8 version;
|
||||
+ __be16 data_len;
|
||||
+} __packed;
|
||||
+
|
||||
+struct onie_tlv {
|
||||
+ u8 type;
|
||||
+ u8 len;
|
||||
+} __packed;
|
||||
+
|
||||
+static const char *onie_tlv_cell_name(u8 type)
|
||||
+{
|
||||
+ switch (type) {
|
||||
+ case 0x21:
|
||||
+ return "product-name";
|
||||
+ case 0x22:
|
||||
+ return "part-number";
|
||||
+ case 0x23:
|
||||
+ return "serial-number";
|
||||
+ case 0x24:
|
||||
+ return "mac-address";
|
||||
+ case 0x25:
|
||||
+ return "manufacture-date";
|
||||
+ case 0x26:
|
||||
+ return "device-version";
|
||||
+ case 0x27:
|
||||
+ return "label-revision";
|
||||
+ case 0x28:
|
||||
+ return "platform-name";
|
||||
+ case 0x29:
|
||||
+ return "onie-version";
|
||||
+ case 0x2A:
|
||||
+ return "num-macs";
|
||||
+ case 0x2B:
|
||||
+ return "manufacturer";
|
||||
+ case 0x2C:
|
||||
+ return "country-code";
|
||||
+ case 0x2D:
|
||||
+ return "vendor";
|
||||
+ case 0x2E:
|
||||
+ return "diag-version";
|
||||
+ case 0x2F:
|
||||
+ return "service-tag";
|
||||
+ case 0xFD:
|
||||
+ return "vendor-extension";
|
||||
+ case 0xFE:
|
||||
+ return "crc32";
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static int onie_tlv_mac_read_cb(void *priv, const char *id, int index,
|
||||
+ unsigned int offset, void *buf,
|
||||
+ size_t bytes)
|
||||
+{
|
||||
+ eth_addr_add(buf, index);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static nvmem_cell_post_process_t onie_tlv_read_cb(u8 type, u8 *buf)
|
||||
+{
|
||||
+ switch (type) {
|
||||
+ case 0x24:
|
||||
+ return &onie_tlv_mac_read_cb;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static int onie_tlv_add_cells(struct device *dev, struct nvmem_device *nvmem,
|
||||
+ size_t data_len, u8 *data)
|
||||
+{
|
||||
+ struct nvmem_cell_info cell = {};
|
||||
+ struct device_node *layout;
|
||||
+ struct onie_tlv tlv;
|
||||
+ unsigned int hdr_len = sizeof(struct onie_tlv_hdr);
|
||||
+ unsigned int offset = 0;
|
||||
+ int ret;
|
||||
+
|
||||
+ layout = of_nvmem_layout_get_container(nvmem);
|
||||
+ if (!layout)
|
||||
+ return -ENOENT;
|
||||
+
|
||||
+ while (offset < data_len) {
|
||||
+ memcpy(&tlv, data + offset, sizeof(tlv));
|
||||
+ if (offset + tlv.len >= data_len) {
|
||||
+ dev_err(dev, "Out of bounds field (0x%x bytes at 0x%x)\n",
|
||||
+ tlv.len, hdr_len + offset);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ cell.name = onie_tlv_cell_name(tlv.type);
|
||||
+ if (!cell.name)
|
||||
+ continue;
|
||||
+
|
||||
+ cell.offset = hdr_len + offset + sizeof(tlv.type) + sizeof(tlv.len);
|
||||
+ cell.bytes = tlv.len;
|
||||
+ cell.np = of_get_child_by_name(layout, cell.name);
|
||||
+ cell.read_post_process = onie_tlv_read_cb(tlv.type, data + offset + sizeof(tlv));
|
||||
+
|
||||
+ ret = nvmem_add_one_cell(nvmem, &cell);
|
||||
+ if (ret) {
|
||||
+ of_node_put(layout);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ offset += sizeof(tlv) + tlv.len;
|
||||
+ }
|
||||
+
|
||||
+ of_node_put(layout);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static bool onie_tlv_hdr_is_valid(struct device *dev, struct onie_tlv_hdr *hdr)
|
||||
+{
|
||||
+ if (memcmp(hdr->id, ONIE_TLV_HDR_ID, sizeof(hdr->id))) {
|
||||
+ dev_err(dev, "Invalid header\n");
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (hdr->version != 0x1) {
|
||||
+ dev_err(dev, "Invalid version number\n");
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static bool onie_tlv_crc_is_valid(struct device *dev, size_t table_len, u8 *table)
|
||||
+{
|
||||
+ struct onie_tlv crc_hdr;
|
||||
+ u32 read_crc, calc_crc;
|
||||
+ __be32 crc_be;
|
||||
+
|
||||
+ memcpy(&crc_hdr, table + table_len - ONIE_TLV_CRC_FIELD_SZ, sizeof(crc_hdr));
|
||||
+ if (crc_hdr.type != 0xfe || crc_hdr.len != ONIE_TLV_CRC_SZ) {
|
||||
+ dev_err(dev, "Invalid CRC field\n");
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ /* The table contains a JAMCRC, which is XOR'ed compared to the original
|
||||
+ * CRC32 implementation as known in the Ethernet world.
|
||||
+ */
|
||||
+ memcpy(&crc_be, table + table_len - ONIE_TLV_CRC_SZ, ONIE_TLV_CRC_SZ);
|
||||
+ read_crc = be32_to_cpu(crc_be);
|
||||
+ calc_crc = crc32(~0, table, table_len - ONIE_TLV_CRC_SZ) ^ 0xFFFFFFFF;
|
||||
+ if (read_crc != calc_crc) {
|
||||
+ dev_err(dev, "Invalid CRC read: 0x%08x, expected: 0x%08x\n",
|
||||
+ read_crc, calc_crc);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static int onie_tlv_parse_table(struct device *dev, struct nvmem_device *nvmem,
|
||||
+ struct nvmem_layout *layout)
|
||||
+{
|
||||
+ struct onie_tlv_hdr hdr;
|
||||
+ size_t table_len, data_len, hdr_len;
|
||||
+ u8 *table, *data;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = nvmem_device_read(nvmem, 0, sizeof(hdr), &hdr);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ if (!onie_tlv_hdr_is_valid(dev, &hdr)) {
|
||||
+ dev_err(dev, "Invalid ONIE TLV header\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ hdr_len = sizeof(hdr.id) + sizeof(hdr.version) + sizeof(hdr.data_len);
|
||||
+ data_len = be16_to_cpu(hdr.data_len);
|
||||
+ table_len = hdr_len + data_len;
|
||||
+ if (table_len > ONIE_TLV_MAX_LEN) {
|
||||
+ dev_err(dev, "Invalid ONIE TLV data length\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ table = devm_kmalloc(dev, table_len, GFP_KERNEL);
|
||||
+ if (!table)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ ret = nvmem_device_read(nvmem, 0, table_len, table);
|
||||
+ if (ret != table_len)
|
||||
+ return ret;
|
||||
+
|
||||
+ if (!onie_tlv_crc_is_valid(dev, table_len, table))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ data = table + hdr_len;
|
||||
+ ret = onie_tlv_add_cells(dev, nvmem, data_len, data);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id onie_tlv_of_match_table[] = {
|
||||
+ { .compatible = "onie,tlv-layout", },
|
||||
+ {},
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, onie_tlv_of_match_table);
|
||||
+
|
||||
+static struct nvmem_layout onie_tlv_layout = {
|
||||
+ .name = "ONIE tlv layout",
|
||||
+ .of_match_table = onie_tlv_of_match_table,
|
||||
+ .add_cells = onie_tlv_parse_table,
|
||||
+};
|
||||
+
|
||||
+static int __init onie_tlv_init(void)
|
||||
+{
|
||||
+ return nvmem_layout_register(&onie_tlv_layout);
|
||||
+}
|
||||
+
|
||||
+static void __exit onie_tlv_exit(void)
|
||||
+{
|
||||
+ nvmem_layout_unregister(&onie_tlv_layout);
|
||||
+}
|
||||
+
|
||||
+module_init(onie_tlv_init);
|
||||
+module_exit(onie_tlv_exit);
|
||||
+
|
||||
+MODULE_LICENSE("GPL");
|
||||
+MODULE_AUTHOR("Miquel Raynal <miquel.raynal@bootlin.com>");
|
||||
+MODULE_DESCRIPTION("NVMEM layout driver for Onie TLV table parsing");
|
||||
+MODULE_ALIAS("NVMEM layout driver for Onie TLV table parsing");
|
|
@ -0,0 +1,32 @@
|
|||
From a4fb434ef96ace5af758ca2c52c3a3f8f3abc87c Mon Sep 17 00:00:00 2001
|
||||
From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
Date: Tue, 4 Apr 2023 18:21:34 +0100
|
||||
Subject: [PATCH] nvmem: stm32-romem: mark OF related data as maybe unused
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The driver can be compile tested with !CONFIG_OF making certain data
|
||||
unused:
|
||||
|
||||
drivers/nvmem/stm32-romem.c:271:34: error: ‘stm32_romem_of_match’ defined but not used [-Werror=unused-const-variable=]
|
||||
|
||||
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-27-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/stm32-romem.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/nvmem/stm32-romem.c
|
||||
+++ b/drivers/nvmem/stm32-romem.c
|
||||
@@ -268,7 +268,7 @@ static const struct stm32_romem_cfg stm3
|
||||
.ta = true,
|
||||
};
|
||||
|
||||
-static const struct of_device_id stm32_romem_of_match[] = {
|
||||
+static const struct of_device_id stm32_romem_of_match[] __maybe_unused = {
|
||||
{ .compatible = "st,stm32f4-otp", }, {
|
||||
.compatible = "st,stm32mp15-bsec",
|
||||
.data = (void *)&stm32mp15_bsec_cfg,
|
|
@ -0,0 +1,120 @@
|
|||
From de6e05097f7db066afb0ad4c88b730949f7b7749 Mon Sep 17 00:00:00 2001
|
||||
From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:35 +0100
|
||||
Subject: [PATCH] nvmem: mtk-efuse: Support postprocessing for GPU speed
|
||||
binning data
|
||||
|
||||
On some MediaTek SoCs GPU speed binning data is available for read
|
||||
in the SoC's eFuse array but it has a format that is incompatible
|
||||
with what the OPP API expects, as we read a number from 0 to 7 but
|
||||
opp-supported-hw is expecting a bitmask to enable an OPP entry:
|
||||
being what we read limited to 0-7, it's straightforward to simply
|
||||
convert the value to BIT(value) as a post-processing action.
|
||||
|
||||
So, introduce post-processing support and enable it by evaluating
|
||||
the newly introduced platform data's `uses_post_processing` member,
|
||||
currently enabled only for MT8186.
|
||||
|
||||
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-28-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/mtk-efuse.c | 53 +++++++++++++++++++++++++++++++++++++--
|
||||
1 file changed, 51 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/nvmem/mtk-efuse.c
|
||||
+++ b/drivers/nvmem/mtk-efuse.c
|
||||
@@ -10,6 +10,11 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/nvmem-provider.h>
|
||||
#include <linux/platform_device.h>
|
||||
+#include <linux/property.h>
|
||||
+
|
||||
+struct mtk_efuse_pdata {
|
||||
+ bool uses_post_processing;
|
||||
+};
|
||||
|
||||
struct mtk_efuse_priv {
|
||||
void __iomem *base;
|
||||
@@ -29,6 +34,37 @@ static int mtk_reg_read(void *context,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int mtk_efuse_gpu_speedbin_pp(void *context, const char *id, int index,
|
||||
+ unsigned int offset, void *data, size_t bytes)
|
||||
+{
|
||||
+ u8 *val = data;
|
||||
+
|
||||
+ if (val[0] < 8)
|
||||
+ val[0] = BIT(val[0]);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void mtk_efuse_fixup_cell_info(struct nvmem_device *nvmem,
|
||||
+ struct nvmem_layout *layout,
|
||||
+ struct nvmem_cell_info *cell)
|
||||
+{
|
||||
+ size_t sz = strlen(cell->name);
|
||||
+
|
||||
+ /*
|
||||
+ * On some SoCs, the GPU speedbin is not read as bitmask but as
|
||||
+ * a number with range [0-7] (max 3 bits): post process to use
|
||||
+ * it in OPP tables to describe supported-hw.
|
||||
+ */
|
||||
+ if (cell->nbits <= 3 &&
|
||||
+ strncmp(cell->name, "gpu-speedbin", min(sz, strlen("gpu-speedbin"))) == 0)
|
||||
+ cell->read_post_process = mtk_efuse_gpu_speedbin_pp;
|
||||
+}
|
||||
+
|
||||
+static struct nvmem_layout mtk_efuse_layout = {
|
||||
+ .fixup_cell_info = mtk_efuse_fixup_cell_info,
|
||||
+};
|
||||
+
|
||||
static int mtk_efuse_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
@@ -36,6 +72,7 @@ static int mtk_efuse_probe(struct platfo
|
||||
struct nvmem_device *nvmem;
|
||||
struct nvmem_config econfig = {};
|
||||
struct mtk_efuse_priv *priv;
|
||||
+ const struct mtk_efuse_pdata *pdata;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
@@ -45,20 +82,32 @@ static int mtk_efuse_probe(struct platfo
|
||||
if (IS_ERR(priv->base))
|
||||
return PTR_ERR(priv->base);
|
||||
|
||||
+ pdata = device_get_match_data(dev);
|
||||
econfig.stride = 1;
|
||||
econfig.word_size = 1;
|
||||
econfig.reg_read = mtk_reg_read;
|
||||
econfig.size = resource_size(res);
|
||||
econfig.priv = priv;
|
||||
econfig.dev = dev;
|
||||
+ if (pdata->uses_post_processing)
|
||||
+ econfig.layout = &mtk_efuse_layout;
|
||||
nvmem = devm_nvmem_register(dev, &econfig);
|
||||
|
||||
return PTR_ERR_OR_ZERO(nvmem);
|
||||
}
|
||||
|
||||
+static const struct mtk_efuse_pdata mtk_mt8186_efuse_pdata = {
|
||||
+ .uses_post_processing = true,
|
||||
+};
|
||||
+
|
||||
+static const struct mtk_efuse_pdata mtk_efuse_pdata = {
|
||||
+ .uses_post_processing = false,
|
||||
+};
|
||||
+
|
||||
static const struct of_device_id mtk_efuse_of_match[] = {
|
||||
- { .compatible = "mediatek,mt8173-efuse",},
|
||||
- { .compatible = "mediatek,efuse",},
|
||||
+ { .compatible = "mediatek,mt8173-efuse", .data = &mtk_efuse_pdata },
|
||||
+ { .compatible = "mediatek,mt8186-efuse", .data = &mtk_mt8186_efuse_pdata },
|
||||
+ { .compatible = "mediatek,efuse", .data = &mtk_efuse_pdata },
|
||||
{/* sentinel */},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mtk_efuse_of_match);
|
|
@ -0,0 +1,39 @@
|
|||
From 1dc552fa33cf98af3e784dbc0500da93cae3b24a Mon Sep 17 00:00:00 2001
|
||||
From: Yang Li <yang.lee@linux.alibaba.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:38 +0100
|
||||
Subject: [PATCH] nvmem: bcm-ocotp: Use devm_platform_ioremap_resource()
|
||||
|
||||
According to commit 7945f929f1a7 ("drivers: provide
|
||||
devm_platform_ioremap_resource()"), convert platform_get_resource(),
|
||||
devm_ioremap_resource() to a single call to use
|
||||
devm_platform_ioremap_resource(), as this is exactly what this function
|
||||
does.
|
||||
|
||||
Signed-off-by: Yang Li <yang.lee@linux.alibaba.com>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-31-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/bcm-ocotp.c | 4 +---
|
||||
1 file changed, 1 insertion(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/nvmem/bcm-ocotp.c
|
||||
+++ b/drivers/nvmem/bcm-ocotp.c
|
||||
@@ -254,7 +254,6 @@ MODULE_DEVICE_TABLE(acpi, bcm_otpc_acpi_
|
||||
static int bcm_otpc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
- struct resource *res;
|
||||
struct otpc_priv *priv;
|
||||
struct nvmem_device *nvmem;
|
||||
int err;
|
||||
@@ -269,8 +268,7 @@ static int bcm_otpc_probe(struct platfor
|
||||
return -ENODEV;
|
||||
|
||||
/* Get OTP base address register. */
|
||||
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
- priv->base = devm_ioremap_resource(dev, res);
|
||||
+ priv->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(priv->base)) {
|
||||
dev_err(dev, "unable to map I/O memory\n");
|
||||
return PTR_ERR(priv->base);
|
|
@ -0,0 +1,39 @@
|
|||
From 649409990d2e93fac657be7c6960c28a2c601d65 Mon Sep 17 00:00:00 2001
|
||||
From: Yang Li <yang.lee@linux.alibaba.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:39 +0100
|
||||
Subject: [PATCH] nvmem: nintendo-otp: Use devm_platform_ioremap_resource()
|
||||
|
||||
According to commit 7945f929f1a7 ("drivers: provide
|
||||
devm_platform_ioremap_resource()"), convert platform_get_resource(),
|
||||
devm_ioremap_resource() to a single call to use
|
||||
devm_platform_ioremap_resource(), as this is exactly what this function
|
||||
does.
|
||||
|
||||
Signed-off-by: Yang Li <yang.lee@linux.alibaba.com>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-32-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/nintendo-otp.c | 4 +---
|
||||
1 file changed, 1 insertion(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/nvmem/nintendo-otp.c
|
||||
+++ b/drivers/nvmem/nintendo-otp.c
|
||||
@@ -76,7 +76,6 @@ static int nintendo_otp_probe(struct pla
|
||||
struct device *dev = &pdev->dev;
|
||||
const struct of_device_id *of_id =
|
||||
of_match_device(nintendo_otp_of_table, dev);
|
||||
- struct resource *res;
|
||||
struct nvmem_device *nvmem;
|
||||
struct nintendo_otp_priv *priv;
|
||||
|
||||
@@ -92,8 +91,7 @@ static int nintendo_otp_probe(struct pla
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
- priv->regs = devm_ioremap_resource(dev, res);
|
||||
+ priv->regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(priv->regs))
|
||||
return PTR_ERR(priv->regs);
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
From c2367aa60d5e34d48582362c6de34b4131d92be7 Mon Sep 17 00:00:00 2001
|
||||
From: Yang Li <yang.lee@linux.alibaba.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:40 +0100
|
||||
Subject: [PATCH] nvmem: vf610-ocotp: Use
|
||||
devm_platform_get_and_ioremap_resource()
|
||||
|
||||
According to commit 890cc39a8799 ("drivers: provide
|
||||
devm_platform_get_and_ioremap_resource()"), convert
|
||||
platform_get_resource(), devm_ioremap_resource() to a single
|
||||
call to devm_platform_get_and_ioremap_resource(), as this is exactly
|
||||
what this function does.
|
||||
|
||||
Signed-off-by: Yang Li <yang.lee@linux.alibaba.com>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-33-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/vf610-ocotp.c | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/nvmem/vf610-ocotp.c
|
||||
+++ b/drivers/nvmem/vf610-ocotp.c
|
||||
@@ -219,8 +219,7 @@ static int vf610_ocotp_probe(struct plat
|
||||
if (!ocotp_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
- ocotp_dev->base = devm_ioremap_resource(dev, res);
|
||||
+ ocotp_dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
|
||||
if (IS_ERR(ocotp_dev->base))
|
||||
return PTR_ERR(ocotp_dev->base);
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
From 55d4980ce55b6bb4be66877de4dbec513911b988 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||||
Date: Tue, 4 Apr 2023 18:21:42 +0100
|
||||
Subject: [PATCH] nvmem: core: support specifying both: cell raw data & post
|
||||
read lengths
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Callback .read_post_process() is designed to modify raw cell content
|
||||
before providing it to the consumer. So far we were dealing with
|
||||
modifications that didn't affect cell size (length). In some cases
|
||||
however cell content needs to be reformatted and resized.
|
||||
|
||||
It's required e.g. to provide properly formatted MAC address in case
|
||||
it's stored in a non-binary format (e.g. using ASCII).
|
||||
|
||||
There were few discussions how to optimally handle that. Following
|
||||
possible solutions were considered:
|
||||
1. Allow .read_post_process() to realloc (resize) content buffer
|
||||
2. Allow .read_post_process() to adjust (decrease) just buffer length
|
||||
3. Register NVMEM cells using post-read sizes
|
||||
|
||||
The preferred solution was the last one. The problem is that simply
|
||||
adjusting "bytes" in NVMEM providers would result in core code NOT
|
||||
passing whole raw data to .read_post_process() callbacks. It means
|
||||
callback functions couldn't do their job without somehow manually
|
||||
reading original cell content on their own.
|
||||
|
||||
This patch deals with that by registering NVMEM cells with both lengths:
|
||||
raw content one and post read one. It allows:
|
||||
1. Core code to read whole raw cell content
|
||||
2. Callbacks to return content they want
|
||||
|
||||
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-35-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/core.c | 11 +++++++----
|
||||
include/linux/nvmem-provider.h | 2 ++
|
||||
2 files changed, 9 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/nvmem/core.c
|
||||
+++ b/drivers/nvmem/core.c
|
||||
@@ -50,6 +50,7 @@ struct nvmem_device {
|
||||
struct nvmem_cell_entry {
|
||||
const char *name;
|
||||
int offset;
|
||||
+ size_t raw_len;
|
||||
int bytes;
|
||||
int bit_offset;
|
||||
int nbits;
|
||||
@@ -469,6 +470,7 @@ static int nvmem_cell_info_to_nvmem_cell
|
||||
{
|
||||
cell->nvmem = nvmem;
|
||||
cell->offset = info->offset;
|
||||
+ cell->raw_len = info->raw_len ?: info->bytes;
|
||||
cell->bytes = info->bytes;
|
||||
cell->name = info->name;
|
||||
cell->read_post_process = info->read_post_process;
|
||||
@@ -1560,7 +1562,7 @@ static int __nvmem_cell_read(struct nvme
|
||||
{
|
||||
int rc;
|
||||
|
||||
- rc = nvmem_reg_read(nvmem, cell->offset, buf, cell->bytes);
|
||||
+ rc = nvmem_reg_read(nvmem, cell->offset, buf, cell->raw_len);
|
||||
|
||||
if (rc)
|
||||
return rc;
|
||||
@@ -1571,7 +1573,7 @@ static int __nvmem_cell_read(struct nvme
|
||||
|
||||
if (cell->read_post_process) {
|
||||
rc = cell->read_post_process(cell->priv, id, index,
|
||||
- cell->offset, buf, cell->bytes);
|
||||
+ cell->offset, buf, cell->raw_len);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
@@ -1594,14 +1596,15 @@ static int __nvmem_cell_read(struct nvme
|
||||
*/
|
||||
void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len)
|
||||
{
|
||||
- struct nvmem_device *nvmem = cell->entry->nvmem;
|
||||
+ struct nvmem_cell_entry *entry = cell->entry;
|
||||
+ struct nvmem_device *nvmem = entry->nvmem;
|
||||
u8 *buf;
|
||||
int rc;
|
||||
|
||||
if (!nvmem)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
- buf = kzalloc(cell->entry->bytes, GFP_KERNEL);
|
||||
+ buf = kzalloc(max_t(size_t, entry->raw_len, entry->bytes), GFP_KERNEL);
|
||||
if (!buf)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
--- a/include/linux/nvmem-provider.h
|
||||
+++ b/include/linux/nvmem-provider.h
|
||||
@@ -51,6 +51,7 @@ struct nvmem_keepout {
|
||||
* struct nvmem_cell_info - NVMEM cell description
|
||||
* @name: Name.
|
||||
* @offset: Offset within the NVMEM device.
|
||||
+ * @raw_len: Length of raw data (without post processing).
|
||||
* @bytes: Length of the cell.
|
||||
* @bit_offset: Bit offset if cell is smaller than a byte.
|
||||
* @nbits: Number of bits.
|
||||
@@ -62,6 +63,7 @@ struct nvmem_keepout {
|
||||
struct nvmem_cell_info {
|
||||
const char *name;
|
||||
unsigned int offset;
|
||||
+ size_t raw_len;
|
||||
unsigned int bytes;
|
||||
unsigned int bit_offset;
|
||||
unsigned int nbits;
|
|
@ -0,0 +1,81 @@
|
|||
From c49f1a8af6bcf6d18576bca898f8083ca4b129e1 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||||
Date: Tue, 4 Apr 2023 18:21:43 +0100
|
||||
Subject: [PATCH] nvmem: u-boot-env: post-process "ethaddr" env variable
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
U-Boot environment variables are stored in ASCII format so "ethaddr"
|
||||
requires parsing into binary to make it work with Ethernet interfaces.
|
||||
|
||||
This includes support for indexes to support #nvmem-cell-cells = <1>.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-36-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/Kconfig | 1 +
|
||||
drivers/nvmem/u-boot-env.c | 26 ++++++++++++++++++++++++++
|
||||
2 files changed, 27 insertions(+)
|
||||
|
||||
--- a/drivers/nvmem/Kconfig
|
||||
+++ b/drivers/nvmem/Kconfig
|
||||
@@ -340,6 +340,7 @@ config NVMEM_U_BOOT_ENV
|
||||
tristate "U-Boot environment variables support"
|
||||
depends on OF && MTD
|
||||
select CRC32
|
||||
+ select GENERIC_NET_UTILS
|
||||
help
|
||||
U-Boot stores its setup as environment variables. This driver adds
|
||||
support for verifying & exporting such data. It also exposes variables
|
||||
--- a/drivers/nvmem/u-boot-env.c
|
||||
+++ b/drivers/nvmem/u-boot-env.c
|
||||
@@ -4,6 +4,8 @@
|
||||
*/
|
||||
|
||||
#include <linux/crc32.h>
|
||||
+#include <linux/etherdevice.h>
|
||||
+#include <linux/if_ether.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
@@ -70,6 +72,25 @@ static int u_boot_env_read(void *context
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int u_boot_env_read_post_process_ethaddr(void *context, const char *id, int index,
|
||||
+ unsigned int offset, void *buf, size_t bytes)
|
||||
+{
|
||||
+ u8 mac[ETH_ALEN];
|
||||
+
|
||||
+ if (bytes != 3 * ETH_ALEN - 1)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (!mac_pton(buf, mac))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (index)
|
||||
+ eth_addr_add(mac, index);
|
||||
+
|
||||
+ ether_addr_copy(buf, mac);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int u_boot_env_add_cells(struct u_boot_env *priv, uint8_t *buf,
|
||||
size_t data_offset, size_t data_len)
|
||||
{
|
||||
@@ -101,6 +122,11 @@ static int u_boot_env_add_cells(struct u
|
||||
priv->cells[idx].offset = data_offset + value - data;
|
||||
priv->cells[idx].bytes = strlen(value);
|
||||
priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name);
|
||||
+ if (!strcmp(var, "ethaddr")) {
|
||||
+ priv->cells[idx].raw_len = strlen(value);
|
||||
+ priv->cells[idx].bytes = ETH_ALEN;
|
||||
+ priv->cells[idx].read_post_process = u_boot_env_read_post_process_ethaddr;
|
||||
+ }
|
||||
}
|
||||
|
||||
if (WARN_ON(idx != priv->ncells))
|
|
@ -0,0 +1,42 @@
|
|||
From 814c978f02db17f16e6aa2efa2a929372f06da09 Mon Sep 17 00:00:00 2001
|
||||
From: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:44 +0100
|
||||
Subject: [PATCH] nvmem: Add macro to register nvmem layout drivers
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Provide a module_nvmem_layout_driver() macro at the end of the
|
||||
nvmem-provider.h header to reduce the boilerplate when registering nvmem
|
||||
layout drivers.
|
||||
|
||||
Suggested-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Acked-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-37-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
include/linux/nvmem-provider.h | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
--- a/include/linux/nvmem-provider.h
|
||||
+++ b/include/linux/nvmem-provider.h
|
||||
@@ -9,6 +9,7 @@
|
||||
#ifndef _LINUX_NVMEM_PROVIDER_H
|
||||
#define _LINUX_NVMEM_PROVIDER_H
|
||||
|
||||
+#include <linux/device/driver.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
@@ -242,4 +243,9 @@ nvmem_layout_get_match_data(struct nvmem
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NVMEM */
|
||||
+
|
||||
+#define module_nvmem_layout_driver(__layout_driver) \
|
||||
+ module_driver(__layout_driver, nvmem_layout_register, \
|
||||
+ nvmem_layout_unregister)
|
||||
+
|
||||
#endif /* ifndef _LINUX_NVMEM_PROVIDER_H */
|
|
@ -0,0 +1,39 @@
|
|||
From 0abdf99fe0c86252ba274703425f8d543d7e7f0d Mon Sep 17 00:00:00 2001
|
||||
From: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:45 +0100
|
||||
Subject: [PATCH] nvmem: layouts: sl28vpd: Use module_nvmem_layout_driver()
|
||||
|
||||
Stop open-coding the module init/exit functions. Use the
|
||||
module_nvmem_layout_driver() instead.
|
||||
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-38-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/layouts/sl28vpd.c | 14 +-------------
|
||||
1 file changed, 1 insertion(+), 13 deletions(-)
|
||||
|
||||
--- a/drivers/nvmem/layouts/sl28vpd.c
|
||||
+++ b/drivers/nvmem/layouts/sl28vpd.c
|
||||
@@ -146,19 +146,7 @@ struct nvmem_layout sl28vpd_layout = {
|
||||
.of_match_table = sl28vpd_of_match_table,
|
||||
.add_cells = sl28vpd_add_cells,
|
||||
};
|
||||
-
|
||||
-static int __init sl28vpd_init(void)
|
||||
-{
|
||||
- return nvmem_layout_register(&sl28vpd_layout);
|
||||
-}
|
||||
-
|
||||
-static void __exit sl28vpd_exit(void)
|
||||
-{
|
||||
- nvmem_layout_unregister(&sl28vpd_layout);
|
||||
-}
|
||||
-
|
||||
-module_init(sl28vpd_init);
|
||||
-module_exit(sl28vpd_exit);
|
||||
+module_nvmem_layout_driver(sl28vpd_layout);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Michael Walle <michael@walle.cc>");
|
|
@ -0,0 +1,39 @@
|
|||
From d119eb38faab61125aaa4f63c74eef61585cf34c Mon Sep 17 00:00:00 2001
|
||||
From: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:46 +0100
|
||||
Subject: [PATCH] nvmem: layouts: onie-tlv: Use module_nvmem_layout_driver()
|
||||
|
||||
Stop open-coding the module init/exit functions. Use the
|
||||
module_nvmem_layout_driver() instead.
|
||||
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-39-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/layouts/onie-tlv.c | 14 +-------------
|
||||
1 file changed, 1 insertion(+), 13 deletions(-)
|
||||
|
||||
--- a/drivers/nvmem/layouts/onie-tlv.c
|
||||
+++ b/drivers/nvmem/layouts/onie-tlv.c
|
||||
@@ -237,19 +237,7 @@ static struct nvmem_layout onie_tlv_layo
|
||||
.of_match_table = onie_tlv_of_match_table,
|
||||
.add_cells = onie_tlv_parse_table,
|
||||
};
|
||||
-
|
||||
-static int __init onie_tlv_init(void)
|
||||
-{
|
||||
- return nvmem_layout_register(&onie_tlv_layout);
|
||||
-}
|
||||
-
|
||||
-static void __exit onie_tlv_exit(void)
|
||||
-{
|
||||
- nvmem_layout_unregister(&onie_tlv_layout);
|
||||
-}
|
||||
-
|
||||
-module_init(onie_tlv_init);
|
||||
-module_exit(onie_tlv_exit);
|
||||
+module_nvmem_layout_driver(onie_tlv_layout);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Miquel Raynal <miquel.raynal@bootlin.com>");
|
|
@ -0,0 +1,24 @@
|
|||
From 6b13e4b6a9a45028ac730e550380077df1845912 Mon Sep 17 00:00:00 2001
|
||||
From: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:47 +0100
|
||||
Subject: [PATCH] nvmem: layouts: onie-tlv: Drop wrong module alias
|
||||
|
||||
The MODULE_ALIAS macro is misused here as it carries the
|
||||
description. There is currently no relevant alias to provide so let's
|
||||
just drop it.
|
||||
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-40-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/layouts/onie-tlv.c | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
--- a/drivers/nvmem/layouts/onie-tlv.c
|
||||
+++ b/drivers/nvmem/layouts/onie-tlv.c
|
||||
@@ -242,4 +242,3 @@ module_nvmem_layout_driver(onie_tlv_layo
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Miquel Raynal <miquel.raynal@bootlin.com>");
|
||||
MODULE_DESCRIPTION("NVMEM layout driver for Onie TLV table parsing");
|
||||
-MODULE_ALIAS("NVMEM layout driver for Onie TLV table parsing");
|
|
@ -0,0 +1,31 @@
|
|||
From a8642cd11635a35a5f1dc31857887900d6610778 Mon Sep 17 00:00:00 2001
|
||||
From: Tom Rix <trix@redhat.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:48 +0100
|
||||
Subject: [PATCH] nvmem: layouts: sl28vpd: set varaiable sl28vpd_layout
|
||||
storage-class-specifier to static
|
||||
|
||||
smatch reports
|
||||
drivers/nvmem/layouts/sl28vpd.c:144:21: warning: symbol
|
||||
'sl28vpd_layout' was not declared. Should it be static?
|
||||
|
||||
This variable is only used in one file so it should be static.
|
||||
|
||||
Signed-off-by: Tom Rix <trix@redhat.com>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-41-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/layouts/sl28vpd.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/nvmem/layouts/sl28vpd.c
|
||||
+++ b/drivers/nvmem/layouts/sl28vpd.c
|
||||
@@ -141,7 +141,7 @@ static const struct of_device_id sl28vpd
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sl28vpd_of_match_table);
|
||||
|
||||
-struct nvmem_layout sl28vpd_layout = {
|
||||
+static struct nvmem_layout sl28vpd_layout = {
|
||||
.name = "sl28-vpd",
|
||||
.of_match_table = sl28vpd_of_match_table,
|
||||
.add_cells = sl28vpd_add_cells,
|
|
@ -0,0 +1,70 @@
|
|||
From b19a4266c52de78496fe40f0b37580a3b762e67d Mon Sep 17 00:00:00 2001
|
||||
From: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:09 +0100
|
||||
Subject: [PATCH] of: Fix modalias string generation
|
||||
|
||||
The helper generating an OF based modalias (of_device_get_modalias())
|
||||
works fine, but due to the use of snprintf() internally it needs a
|
||||
buffer one byte longer than what should be needed just for the entire
|
||||
string (excluding the '\0'). Most users of this helper are sysfs hooks
|
||||
providing the modalias string to users. They all provide a PAGE_SIZE
|
||||
buffer which is way above the number of bytes required to fit the
|
||||
modalias string and hence do not suffer from this issue.
|
||||
|
||||
There is another user though, of_device_request_module(), which is only
|
||||
called by drivers/usb/common/ulpi.c. This request module function is
|
||||
faulty, but maybe because in most cases there is an alternative, ULPI
|
||||
driver users have not noticed it.
|
||||
|
||||
In this function, of_device_get_modalias() is called twice. The first
|
||||
time without buffer just to get the number of bytes required by the
|
||||
modalias string (excluding the null byte), and a second time, after
|
||||
buffer allocation, to fill the buffer. The allocation asks for an
|
||||
additional byte, in order to store the trailing '\0'. However, the
|
||||
buffer *length* provided to of_device_get_modalias() excludes this extra
|
||||
byte. The internal use of snprintf() with a length that is exactly the
|
||||
number of bytes to be written has the effect of using the last available
|
||||
byte to store a '\0', which then smashes the last character of the
|
||||
modalias string.
|
||||
|
||||
Provide the actual size of the buffer to of_device_get_modalias() to fix
|
||||
this issue.
|
||||
|
||||
Note: the "str[size - 1] = '\0';" line is not really needed as snprintf
|
||||
will anyway end the string with a null byte, but there is a possibility
|
||||
that this function might be called on a struct device_node without
|
||||
compatible, in this case snprintf() would not be executed. So we keep it
|
||||
just to avoid possible unbounded strings.
|
||||
|
||||
Cc: Stephen Boyd <sboyd@kernel.org>
|
||||
Cc: Peter Chen <peter.chen@kernel.org>
|
||||
Fixes: 9c829c097f2f ("of: device: Support loading a module with OF based modalias")
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Reviewed-by: Rob Herring <robh@kernel.org>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-2-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/of/device.c | 7 +++++--
|
||||
1 file changed, 5 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/of/device.c
|
||||
+++ b/drivers/of/device.c
|
||||
@@ -264,12 +264,15 @@ int of_device_request_module(struct devi
|
||||
if (size < 0)
|
||||
return size;
|
||||
|
||||
- str = kmalloc(size + 1, GFP_KERNEL);
|
||||
+ /* Reserve an additional byte for the trailing '\0' */
|
||||
+ size++;
|
||||
+
|
||||
+ str = kmalloc(size, GFP_KERNEL);
|
||||
if (!str)
|
||||
return -ENOMEM;
|
||||
|
||||
of_device_get_modalias(dev, str, size);
|
||||
- str[size] = '\0';
|
||||
+ str[size - 1] = '\0';
|
||||
ret = request_module(str);
|
||||
kfree(str);
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
From 5c3d15e127ebfc0754cd18def7124633b6d46672 Mon Sep 17 00:00:00 2001
|
||||
From: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:15 +0100
|
||||
Subject: [PATCH] of: Update of_device_get_modalias()
|
||||
|
||||
This function only needs a "struct device_node" to work, but for
|
||||
convenience the author (and only user) of this helper did use a "struct
|
||||
device" and put it in device.c.
|
||||
|
||||
Let's convert this helper to take a "struct device node" instead. This
|
||||
change asks for two additional changes: renaming it "of_modalias()"
|
||||
to fit the current naming, and moving it outside of device.c which will
|
||||
be done in a follow-up commit.
|
||||
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Reviewed-by: Rob Herring <robh@kernel.org>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-8-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/of/device.c | 29 +++++++++++++++++------------
|
||||
1 file changed, 17 insertions(+), 12 deletions(-)
|
||||
|
||||
--- a/drivers/of/device.c
|
||||
+++ b/drivers/of/device.c
|
||||
@@ -215,7 +215,7 @@ const void *of_device_get_match_data(con
|
||||
}
|
||||
EXPORT_SYMBOL(of_device_get_match_data);
|
||||
|
||||
-static ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len)
|
||||
+static ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len)
|
||||
{
|
||||
const char *compat;
|
||||
char *c;
|
||||
@@ -223,19 +223,16 @@ static ssize_t of_device_get_modalias(st
|
||||
ssize_t csize;
|
||||
ssize_t tsize;
|
||||
|
||||
- if ((!dev) || (!dev->of_node) || dev->of_node_reused)
|
||||
- return -ENODEV;
|
||||
-
|
||||
/* Name & Type */
|
||||
/* %p eats all alphanum characters, so %c must be used here */
|
||||
- csize = snprintf(str, len, "of:N%pOFn%c%s", dev->of_node, 'T',
|
||||
- of_node_get_device_type(dev->of_node));
|
||||
+ csize = snprintf(str, len, "of:N%pOFn%c%s", np, 'T',
|
||||
+ of_node_get_device_type(np));
|
||||
tsize = csize;
|
||||
len -= csize;
|
||||
if (str)
|
||||
str += csize;
|
||||
|
||||
- of_property_for_each_string(dev->of_node, "compatible", p, compat) {
|
||||
+ of_property_for_each_string(np, "compatible", p, compat) {
|
||||
csize = strlen(compat) + 1;
|
||||
tsize += csize;
|
||||
if (csize > len)
|
||||
@@ -260,7 +257,10 @@ int of_device_request_module(struct devi
|
||||
ssize_t size;
|
||||
int ret;
|
||||
|
||||
- size = of_device_get_modalias(dev, NULL, 0);
|
||||
+ if (!dev || !dev->of_node)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ size = of_modalias(dev->of_node, NULL, 0);
|
||||
if (size < 0)
|
||||
return size;
|
||||
|
||||
@@ -271,7 +271,7 @@ int of_device_request_module(struct devi
|
||||
if (!str)
|
||||
return -ENOMEM;
|
||||
|
||||
- of_device_get_modalias(dev, str, size);
|
||||
+ of_modalias(dev->of_node, str, size);
|
||||
str[size - 1] = '\0';
|
||||
ret = request_module(str);
|
||||
kfree(str);
|
||||
@@ -285,7 +285,12 @@ EXPORT_SYMBOL_GPL(of_device_request_modu
|
||||
*/
|
||||
ssize_t of_device_modalias(struct device *dev, char *str, ssize_t len)
|
||||
{
|
||||
- ssize_t sl = of_device_get_modalias(dev, str, len - 2);
|
||||
+ ssize_t sl;
|
||||
+
|
||||
+ if (!dev || !dev->of_node || dev->of_node_reused)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ sl = of_modalias(dev->of_node, str, len - 2);
|
||||
if (sl < 0)
|
||||
return sl;
|
||||
if (sl > len - 2)
|
||||
@@ -348,8 +353,8 @@ int of_device_uevent_modalias(struct dev
|
||||
if (add_uevent_var(env, "MODALIAS="))
|
||||
return -ENOMEM;
|
||||
|
||||
- sl = of_device_get_modalias(dev, &env->buf[env->buflen-1],
|
||||
- sizeof(env->buf) - env->buflen);
|
||||
+ sl = of_modalias(dev->of_node, &env->buf[env->buflen-1],
|
||||
+ sizeof(env->buf) - env->buflen);
|
||||
if (sl < 0)
|
||||
return sl;
|
||||
if (sl >= (sizeof(env->buf) - env->buflen))
|
|
@ -0,0 +1,173 @@
|
|||
From 673aa1ed1c9b6710bf24e3f0957d85e2f46c77db Mon Sep 17 00:00:00 2001
|
||||
From: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:16 +0100
|
||||
Subject: [PATCH] of: Rename of_modalias_node()
|
||||
|
||||
This helper does not produce a real modalias, but tries to get the
|
||||
"product" compatible part of the "vendor,product" compatibles only. It
|
||||
is far from creating a purely useful modalias string and does not seem
|
||||
to be used like that directly anyway, so let's try to give this helper a
|
||||
more meaningful name before moving there a real modalias helper (already
|
||||
existing under of/device.c).
|
||||
|
||||
Also update the various documentations to refer to the strings as
|
||||
"aliases" rather than "modaliases" which has a real meaning in the Linux
|
||||
kernel.
|
||||
|
||||
There is no functional change.
|
||||
|
||||
Cc: Rafael J. Wysocki <rafael@kernel.org>
|
||||
Cc: Len Brown <lenb@kernel.org>
|
||||
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
|
||||
Cc: Maxime Ripard <mripard@kernel.org>
|
||||
Cc: Thomas Zimmermann <tzimmermann@suse.de>
|
||||
Cc: Sebastian Reichel <sre@kernel.org>
|
||||
Cc: Wolfram Sang <wsa@kernel.org>
|
||||
Cc: Mark Brown <broonie@kernel.org>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Reviewed-by: Rob Herring <robh@kernel.org>
|
||||
Acked-by: Mark Brown <broonie@kernel.org>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Acked-by: Sebastian Reichel <sre@kernel.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-9-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/acpi/bus.c | 7 ++++---
|
||||
drivers/gpu/drm/drm_mipi_dsi.c | 2 +-
|
||||
drivers/hsi/hsi_core.c | 2 +-
|
||||
drivers/i2c/busses/i2c-powermac.c | 2 +-
|
||||
drivers/i2c/i2c-core-of.c | 2 +-
|
||||
drivers/of/base.c | 18 +++++++++++-------
|
||||
drivers/spi/spi.c | 4 ++--
|
||||
include/linux/of.h | 3 ++-
|
||||
8 files changed, 23 insertions(+), 17 deletions(-)
|
||||
|
||||
--- a/drivers/acpi/bus.c
|
||||
+++ b/drivers/acpi/bus.c
|
||||
@@ -693,9 +693,10 @@ static bool acpi_of_modalias(struct acpi
|
||||
* @modalias: Pointer to buffer that modalias value will be copied into
|
||||
* @len: Length of modalias buffer
|
||||
*
|
||||
- * This is a counterpart of of_modalias_node() for struct acpi_device objects.
|
||||
- * If there is a compatible string for @adev, it will be copied to @modalias
|
||||
- * with the vendor prefix stripped; otherwise, @default_id will be used.
|
||||
+ * This is a counterpart of of_alias_from_compatible() for struct acpi_device
|
||||
+ * objects. If there is a compatible string for @adev, it will be copied to
|
||||
+ * @modalias with the vendor prefix stripped; otherwise, @default_id will be
|
||||
+ * used.
|
||||
*/
|
||||
void acpi_set_modalias(struct acpi_device *adev, const char *default_id,
|
||||
char *modalias, size_t len)
|
||||
--- a/drivers/gpu/drm/drm_mipi_dsi.c
|
||||
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
|
||||
@@ -160,7 +160,7 @@ of_mipi_dsi_device_add(struct mipi_dsi_h
|
||||
int ret;
|
||||
u32 reg;
|
||||
|
||||
- if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
|
||||
+ if (of_alias_from_compatible(node, info.type, sizeof(info.type)) < 0) {
|
||||
drm_err(host, "modalias failure on %pOF\n", node);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
--- a/drivers/hsi/hsi_core.c
|
||||
+++ b/drivers/hsi/hsi_core.c
|
||||
@@ -207,7 +207,7 @@ static void hsi_add_client_from_dt(struc
|
||||
if (!cl)
|
||||
return;
|
||||
|
||||
- err = of_modalias_node(client, name, sizeof(name));
|
||||
+ err = of_alias_from_compatible(client, name, sizeof(name));
|
||||
if (err)
|
||||
goto err;
|
||||
|
||||
--- a/drivers/i2c/busses/i2c-powermac.c
|
||||
+++ b/drivers/i2c/busses/i2c-powermac.c
|
||||
@@ -289,7 +289,7 @@ static bool i2c_powermac_get_type(struct
|
||||
*/
|
||||
|
||||
/* First try proper modalias */
|
||||
- if (of_modalias_node(node, tmp, sizeof(tmp)) >= 0) {
|
||||
+ if (of_alias_from_compatible(node, tmp, sizeof(tmp)) >= 0) {
|
||||
snprintf(type, type_size, "MAC,%s", tmp);
|
||||
return true;
|
||||
}
|
||||
--- a/drivers/i2c/i2c-core-of.c
|
||||
+++ b/drivers/i2c/i2c-core-of.c
|
||||
@@ -27,7 +27,7 @@ int of_i2c_get_board_info(struct device
|
||||
|
||||
memset(info, 0, sizeof(*info));
|
||||
|
||||
- if (of_modalias_node(node, info->type, sizeof(info->type)) < 0) {
|
||||
+ if (of_alias_from_compatible(node, info->type, sizeof(info->type)) < 0) {
|
||||
dev_err(dev, "of_i2c: modalias failure on %pOF\n", node);
|
||||
return -EINVAL;
|
||||
}
|
||||
--- a/drivers/of/base.c
|
||||
+++ b/drivers/of/base.c
|
||||
@@ -1160,19 +1160,23 @@ struct device_node *of_find_matching_nod
|
||||
EXPORT_SYMBOL(of_find_matching_node_and_match);
|
||||
|
||||
/**
|
||||
- * of_modalias_node - Lookup appropriate modalias for a device node
|
||||
+ * of_alias_from_compatible - Lookup appropriate alias for a device node
|
||||
+ * depending on compatible
|
||||
* @node: pointer to a device tree node
|
||||
- * @modalias: Pointer to buffer that modalias value will be copied into
|
||||
- * @len: Length of modalias value
|
||||
+ * @alias: Pointer to buffer that alias value will be copied into
|
||||
+ * @len: Length of alias value
|
||||
*
|
||||
* Based on the value of the compatible property, this routine will attempt
|
||||
- * to choose an appropriate modalias value for a particular device tree node.
|
||||
+ * to choose an appropriate alias value for a particular device tree node.
|
||||
* It does this by stripping the manufacturer prefix (as delimited by a ',')
|
||||
* from the first entry in the compatible list property.
|
||||
*
|
||||
+ * Note: The matching on just the "product" side of the compatible is a relic
|
||||
+ * from I2C and SPI. Please do not add any new user.
|
||||
+ *
|
||||
* Return: This routine returns 0 on success, <0 on failure.
|
||||
*/
|
||||
-int of_modalias_node(struct device_node *node, char *modalias, int len)
|
||||
+int of_alias_from_compatible(const struct device_node *node, char *alias, int len)
|
||||
{
|
||||
const char *compatible, *p;
|
||||
int cplen;
|
||||
@@ -1181,10 +1185,10 @@ int of_modalias_node(struct device_node
|
||||
if (!compatible || strlen(compatible) > cplen)
|
||||
return -ENODEV;
|
||||
p = strchr(compatible, ',');
|
||||
- strlcpy(modalias, p ? p + 1 : compatible, len);
|
||||
+ strlcpy(alias, p ? p + 1 : compatible, len);
|
||||
return 0;
|
||||
}
|
||||
-EXPORT_SYMBOL_GPL(of_modalias_node);
|
||||
+EXPORT_SYMBOL_GPL(of_alias_from_compatible);
|
||||
|
||||
/**
|
||||
* of_find_node_by_phandle - Find a node given a phandle
|
||||
--- a/drivers/spi/spi.c
|
||||
+++ b/drivers/spi/spi.c
|
||||
@@ -2038,8 +2038,8 @@ of_register_spi_device(struct spi_contro
|
||||
}
|
||||
|
||||
/* Select device driver */
|
||||
- rc = of_modalias_node(nc, spi->modalias,
|
||||
- sizeof(spi->modalias));
|
||||
+ rc = of_alias_from_compatible(nc, spi->modalias,
|
||||
+ sizeof(spi->modalias));
|
||||
if (rc < 0) {
|
||||
dev_err(&ctlr->dev, "cannot find modalias for %pOF\n", nc);
|
||||
goto err_out;
|
||||
--- a/include/linux/of.h
|
||||
+++ b/include/linux/of.h
|
||||
@@ -361,7 +361,8 @@ extern int of_n_addr_cells(struct device
|
||||
extern int of_n_size_cells(struct device_node *np);
|
||||
extern const struct of_device_id *of_match_node(
|
||||
const struct of_device_id *matches, const struct device_node *node);
|
||||
-extern int of_modalias_node(struct device_node *node, char *modalias, int len);
|
||||
+extern int of_alias_from_compatible(const struct device_node *node, char *alias,
|
||||
+ int len);
|
||||
extern void of_print_phandle_args(const char *msg, const struct of_phandle_args *args);
|
||||
extern int __of_parse_phandle_with_args(const struct device_node *np,
|
||||
const char *list_name, const char *cells_name, int cell_count,
|
|
@ -0,0 +1,160 @@
|
|||
From bd7a7ed774afd1a4174df34227626c95573be517 Mon Sep 17 00:00:00 2001
|
||||
From: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:17 +0100
|
||||
Subject: [PATCH] of: Move of_modalias() to module.c
|
||||
|
||||
Create a specific .c file for OF related module handling.
|
||||
Move of_modalias() inside as a first step.
|
||||
|
||||
The helper is exposed through of.h even though it is only used by core
|
||||
files because the users from device.c will soon be split into an OF-only
|
||||
helper in module.c as well as a device-oriented inline helper in
|
||||
of_device.h. Putting this helper in of_private.h would require to
|
||||
include of_private.h from of_device.h, which is not acceptable.
|
||||
|
||||
Suggested-by: Rob Herring <robh+dt@kernel.org>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Reviewed-by: Rob Herring <robh@kernel.org>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-10-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/of/Makefile | 2 +-
|
||||
drivers/of/device.c | 37 -------------------------------------
|
||||
drivers/of/module.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
|
||||
include/linux/of.h | 9 +++++++++
|
||||
4 files changed, 54 insertions(+), 38 deletions(-)
|
||||
create mode 100644 drivers/of/module.c
|
||||
|
||||
--- a/drivers/of/Makefile
|
||||
+++ b/drivers/of/Makefile
|
||||
@@ -1,5 +1,5 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
-obj-y = base.o device.o platform.o property.o
|
||||
+obj-y = base.o device.o module.o platform.o property.o
|
||||
obj-$(CONFIG_OF_KOBJ) += kobj.o
|
||||
obj-$(CONFIG_OF_DYNAMIC) += dynamic.o
|
||||
obj-$(CONFIG_OF_FLATTREE) += fdt.o
|
||||
--- a/drivers/of/device.c
|
||||
+++ b/drivers/of/device.c
|
||||
@@ -1,5 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
-#include <linux/string.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
@@ -215,42 +214,6 @@ const void *of_device_get_match_data(con
|
||||
}
|
||||
EXPORT_SYMBOL(of_device_get_match_data);
|
||||
|
||||
-static ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len)
|
||||
-{
|
||||
- const char *compat;
|
||||
- char *c;
|
||||
- struct property *p;
|
||||
- ssize_t csize;
|
||||
- ssize_t tsize;
|
||||
-
|
||||
- /* Name & Type */
|
||||
- /* %p eats all alphanum characters, so %c must be used here */
|
||||
- csize = snprintf(str, len, "of:N%pOFn%c%s", np, 'T',
|
||||
- of_node_get_device_type(np));
|
||||
- tsize = csize;
|
||||
- len -= csize;
|
||||
- if (str)
|
||||
- str += csize;
|
||||
-
|
||||
- of_property_for_each_string(np, "compatible", p, compat) {
|
||||
- csize = strlen(compat) + 1;
|
||||
- tsize += csize;
|
||||
- if (csize > len)
|
||||
- continue;
|
||||
-
|
||||
- csize = snprintf(str, len, "C%s", compat);
|
||||
- for (c = str; c; ) {
|
||||
- c = strchr(c, ' ');
|
||||
- if (c)
|
||||
- *c++ = '_';
|
||||
- }
|
||||
- len -= csize;
|
||||
- str += csize;
|
||||
- }
|
||||
-
|
||||
- return tsize;
|
||||
-}
|
||||
-
|
||||
int of_device_request_module(struct device *dev)
|
||||
{
|
||||
char *str;
|
||||
--- /dev/null
|
||||
+++ b/drivers/of/module.c
|
||||
@@ -0,0 +1,44 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/*
|
||||
+ * Linux kernel module helpers.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/string.h>
|
||||
+
|
||||
+ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len)
|
||||
+{
|
||||
+ const char *compat;
|
||||
+ char *c;
|
||||
+ struct property *p;
|
||||
+ ssize_t csize;
|
||||
+ ssize_t tsize;
|
||||
+
|
||||
+ /* Name & Type */
|
||||
+ /* %p eats all alphanum characters, so %c must be used here */
|
||||
+ csize = snprintf(str, len, "of:N%pOFn%c%s", np, 'T',
|
||||
+ of_node_get_device_type(np));
|
||||
+ tsize = csize;
|
||||
+ len -= csize;
|
||||
+ if (str)
|
||||
+ str += csize;
|
||||
+
|
||||
+ of_property_for_each_string(np, "compatible", p, compat) {
|
||||
+ csize = strlen(compat) + 1;
|
||||
+ tsize += csize;
|
||||
+ if (csize > len)
|
||||
+ continue;
|
||||
+
|
||||
+ csize = snprintf(str, len, "C%s", compat);
|
||||
+ for (c = str; c; ) {
|
||||
+ c = strchr(c, ' ');
|
||||
+ if (c)
|
||||
+ *c++ = '_';
|
||||
+ }
|
||||
+ len -= csize;
|
||||
+ str += csize;
|
||||
+ }
|
||||
+
|
||||
+ return tsize;
|
||||
+}
|
||||
--- a/include/linux/of.h
|
||||
+++ b/include/linux/of.h
|
||||
@@ -373,6 +373,9 @@ extern int of_parse_phandle_with_args_ma
|
||||
extern int of_count_phandle_with_args(const struct device_node *np,
|
||||
const char *list_name, const char *cells_name);
|
||||
|
||||
+/* module functions */
|
||||
+extern ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len);
|
||||
+
|
||||
/* phandle iterator functions */
|
||||
extern int of_phandle_iterator_init(struct of_phandle_iterator *it,
|
||||
const struct device_node *np,
|
||||
@@ -878,6 +881,12 @@ static inline int of_count_phandle_with_
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
+static inline ssize_t of_modalias(const struct device_node *np, char *str,
|
||||
+ ssize_t len)
|
||||
+{
|
||||
+ return -ENODEV;
|
||||
+}
|
||||
+
|
||||
static inline int of_phandle_iterator_init(struct of_phandle_iterator *it,
|
||||
const struct device_node *np,
|
||||
const char *list_name,
|
|
@ -0,0 +1,131 @@
|
|||
From e6506f06d5e82765666902ccf9e9162f3e31d518 Mon Sep 17 00:00:00 2001
|
||||
From: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:18 +0100
|
||||
Subject: [PATCH] of: Move the request module helper logic to module.c
|
||||
|
||||
Depending on device.c for pure OF handling is considered
|
||||
backwards. Let's extract the content of of_device_request_module() to
|
||||
have the real logic under module.c.
|
||||
|
||||
The next step will be to convert users of of_device_request_module() to
|
||||
use the new helper.
|
||||
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Reviewed-by: Rob Herring <robh@kernel.org>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-11-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/of/device.c | 25 ++-----------------------
|
||||
drivers/of/module.c | 30 ++++++++++++++++++++++++++++++
|
||||
include/linux/of.h | 6 ++++++
|
||||
3 files changed, 38 insertions(+), 23 deletions(-)
|
||||
|
||||
--- a/drivers/of/device.c
|
||||
+++ b/drivers/of/device.c
|
||||
@@ -7,7 +7,6 @@
|
||||
#include <linux/dma-direct.h> /* for bus_dma_region */
|
||||
#include <linux/dma-map-ops.h>
|
||||
#include <linux/init.h>
|
||||
-#include <linux/module.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/platform_device.h>
|
||||
@@ -216,30 +215,10 @@ EXPORT_SYMBOL(of_device_get_match_data);
|
||||
|
||||
int of_device_request_module(struct device *dev)
|
||||
{
|
||||
- char *str;
|
||||
- ssize_t size;
|
||||
- int ret;
|
||||
-
|
||||
- if (!dev || !dev->of_node)
|
||||
+ if (!dev)
|
||||
return -ENODEV;
|
||||
|
||||
- size = of_modalias(dev->of_node, NULL, 0);
|
||||
- if (size < 0)
|
||||
- return size;
|
||||
-
|
||||
- /* Reserve an additional byte for the trailing '\0' */
|
||||
- size++;
|
||||
-
|
||||
- str = kmalloc(size, GFP_KERNEL);
|
||||
- if (!str)
|
||||
- return -ENOMEM;
|
||||
-
|
||||
- of_modalias(dev->of_node, str, size);
|
||||
- str[size - 1] = '\0';
|
||||
- ret = request_module(str);
|
||||
- kfree(str);
|
||||
-
|
||||
- return ret;
|
||||
+ return of_request_module(dev->of_node);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_device_request_module);
|
||||
|
||||
--- a/drivers/of/module.c
|
||||
+++ b/drivers/of/module.c
|
||||
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/of.h>
|
||||
+#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
@@ -42,3 +43,32 @@ ssize_t of_modalias(const struct device_
|
||||
|
||||
return tsize;
|
||||
}
|
||||
+
|
||||
+int of_request_module(const struct device_node *np)
|
||||
+{
|
||||
+ char *str;
|
||||
+ ssize_t size;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (!np)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ size = of_modalias(np, NULL, 0);
|
||||
+ if (size < 0)
|
||||
+ return size;
|
||||
+
|
||||
+ /* Reserve an additional byte for the trailing '\0' */
|
||||
+ size++;
|
||||
+
|
||||
+ str = kmalloc(size, GFP_KERNEL);
|
||||
+ if (!str)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ of_modalias(np, str, size);
|
||||
+ str[size - 1] = '\0';
|
||||
+ ret = request_module(str);
|
||||
+ kfree(str);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(of_request_module);
|
||||
--- a/include/linux/of.h
|
||||
+++ b/include/linux/of.h
|
||||
@@ -375,6 +375,7 @@ extern int of_count_phandle_with_args(co
|
||||
|
||||
/* module functions */
|
||||
extern ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len);
|
||||
+extern int of_request_module(const struct device_node *np);
|
||||
|
||||
/* phandle iterator functions */
|
||||
extern int of_phandle_iterator_init(struct of_phandle_iterator *it,
|
||||
@@ -886,6 +887,11 @@ static inline ssize_t of_modalias(const
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
+
|
||||
+static inline int of_request_module(const struct device_node *np)
|
||||
+{
|
||||
+ return -ENODEV;
|
||||
+}
|
||||
|
||||
static inline int of_phandle_iterator_init(struct of_phandle_iterator *it,
|
||||
const struct device_node *np,
|
|
@ -0,0 +1,43 @@
|
|||
From 1cd9ceaa5282ff10ea20a7fbadde5a476a1cc99e Mon Sep 17 00:00:00 2001
|
||||
From: Michael Walle <michael@walle.cc>
|
||||
Date: Wed, 8 Mar 2023 09:20:18 +0100
|
||||
Subject: [PATCH] mtd: core: provide unique name for nvmem device, take two
|
||||
|
||||
Commit c048b60d39e1 ("mtd: core: provide unique name for nvmem device")
|
||||
tries to give the nvmem device a unique name, but fails badly if the mtd
|
||||
device doesn't have a "struct device" associated with it, i.e. if
|
||||
CONFIG_MTD_PARTITIONED_MASTER is not set. This will result in the name
|
||||
"(null)-user-otp", which is not unique. It seems the best we can do is
|
||||
to use the compatible name together with a unique identifier added by
|
||||
the nvmem subsystem by using NVMEM_DEVID_AUTO.
|
||||
|
||||
Fixes: c048b60d39e1 ("mtd: core: provide unique name for nvmem device")
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Michael Walle <michael@walle.cc>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Link: https://lore.kernel.org/linux-mtd/20230308082021.870459-1-michael@walle.cc
|
||||
---
|
||||
drivers/mtd/mtdcore.c | 5 ++---
|
||||
1 file changed, 2 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/mtd/mtdcore.c
|
||||
+++ b/drivers/mtd/mtdcore.c
|
||||
@@ -895,8 +895,8 @@ static struct nvmem_device *mtd_otp_nvme
|
||||
|
||||
/* OTP nvmem will be registered on the physical device */
|
||||
config.dev = mtd->dev.parent;
|
||||
- config.name = kasprintf(GFP_KERNEL, "%s-%s", dev_name(&mtd->dev), compatible);
|
||||
- config.id = NVMEM_DEVID_NONE;
|
||||
+ config.name = compatible;
|
||||
+ config.id = NVMEM_DEVID_AUTO;
|
||||
config.owner = THIS_MODULE;
|
||||
config.type = NVMEM_TYPE_OTP;
|
||||
config.root_only = true;
|
||||
@@ -912,7 +912,6 @@ static struct nvmem_device *mtd_otp_nvme
|
||||
nvmem = NULL;
|
||||
|
||||
of_node_put(np);
|
||||
- kfree(config.name);
|
||||
|
||||
return nvmem;
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
From 8bd1d24e6ca3c599dd455b0e1b22f77bab8290eb Mon Sep 17 00:00:00 2001
|
||||
From: Michael Walle <michael@walle.cc>
|
||||
Date: Wed, 8 Mar 2023 09:20:19 +0100
|
||||
Subject: [PATCH] mtd: core: fix nvmem error reporting
|
||||
|
||||
The master MTD will only have an associated device if
|
||||
CONFIG_MTD_PARTITIONED_MASTER is set, thus we cannot use dev_err() on
|
||||
mtd->dev. Instead use the parent device which is the physical flash
|
||||
memory.
|
||||
|
||||
Fixes: 4b361cfa8624 ("mtd: core: add OTP nvmem provider support")
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Michael Walle <michael@walle.cc>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Link: https://lore.kernel.org/linux-mtd/20230308082021.870459-2-michael@walle.cc
|
||||
---
|
||||
drivers/mtd/mtdcore.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/mtd/mtdcore.c
|
||||
+++ b/drivers/mtd/mtdcore.c
|
||||
@@ -946,6 +946,7 @@ static int mtd_nvmem_fact_otp_reg_read(v
|
||||
|
||||
static int mtd_otp_nvmem_add(struct mtd_info *mtd)
|
||||
{
|
||||
+ struct device *dev = mtd->dev.parent;
|
||||
struct nvmem_device *nvmem;
|
||||
ssize_t size;
|
||||
int err;
|
||||
@@ -959,7 +960,7 @@ static int mtd_otp_nvmem_add(struct mtd_
|
||||
nvmem = mtd_otp_nvmem_register(mtd, "user-otp", size,
|
||||
mtd_nvmem_user_otp_reg_read);
|
||||
if (IS_ERR(nvmem)) {
|
||||
- dev_err(&mtd->dev, "Failed to register OTP NVMEM device\n");
|
||||
+ dev_err(dev, "Failed to register OTP NVMEM device\n");
|
||||
return PTR_ERR(nvmem);
|
||||
}
|
||||
mtd->otp_user_nvmem = nvmem;
|
||||
@@ -977,7 +978,7 @@ static int mtd_otp_nvmem_add(struct mtd_
|
||||
nvmem = mtd_otp_nvmem_register(mtd, "factory-otp", size,
|
||||
mtd_nvmem_fact_otp_reg_read);
|
||||
if (IS_ERR(nvmem)) {
|
||||
- dev_err(&mtd->dev, "Failed to register OTP NVMEM device\n");
|
||||
+ dev_err(dev, "Failed to register OTP NVMEM device\n");
|
||||
err = PTR_ERR(nvmem);
|
||||
goto err;
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
From e0489f6e221f5ddee6cb3bd51b992b790c5fa4b9 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Walle <michael@walle.cc>
|
||||
Date: Wed, 8 Mar 2023 09:20:20 +0100
|
||||
Subject: [PATCH] mtd: core: fix error path for nvmem provider
|
||||
|
||||
If mtd_otp_nvmem_add() fails, the partitions won't be removed
|
||||
because there is simply no call to del_mtd_partitions().
|
||||
Unfortunately, add_mtd_partitions() will print all partitions to
|
||||
the kernel console. If mtd_otp_nvmem_add() returns -EPROBE_DEFER
|
||||
this would print the partitions multiple times to the kernel
|
||||
console. Instead move mtd_otp_nvmem_add() to the beginning of the
|
||||
function.
|
||||
|
||||
Fixes: 4b361cfa8624 ("mtd: core: add OTP nvmem provider support")
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Michael Walle <michael@walle.cc>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Link: https://lore.kernel.org/linux-mtd/20230308082021.870459-3-michael@walle.cc
|
||||
---
|
||||
drivers/mtd/mtdcore.c | 13 ++++++++++---
|
||||
1 file changed, 10 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/mtd/mtdcore.c
|
||||
+++ b/drivers/mtd/mtdcore.c
|
||||
@@ -1031,10 +1031,14 @@ int mtd_device_parse_register(struct mtd
|
||||
|
||||
mtd_set_dev_defaults(mtd);
|
||||
|
||||
+ ret = mtd_otp_nvmem_add(mtd);
|
||||
+ if (ret)
|
||||
+ goto out;
|
||||
+
|
||||
if (IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER)) {
|
||||
ret = add_mtd_device(mtd);
|
||||
if (ret)
|
||||
- return ret;
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
/* Prefer parsed partitions over driver-provided fallback */
|
||||
@@ -1069,9 +1073,12 @@ int mtd_device_parse_register(struct mtd
|
||||
register_reboot_notifier(&mtd->reboot_notifier);
|
||||
}
|
||||
|
||||
- ret = mtd_otp_nvmem_add(mtd);
|
||||
-
|
||||
out:
|
||||
+ if (ret) {
|
||||
+ nvmem_unregister(mtd->otp_user_nvmem);
|
||||
+ nvmem_unregister(mtd->otp_factory_nvmem);
|
||||
+ }
|
||||
+
|
||||
if (ret && device_is_registered(&mtd->dev))
|
||||
del_mtd_device(mtd);
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
From 281f7a6c1a33fffcde32001bacbb4f672140fbf9 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Walle <michael@walle.cc>
|
||||
Date: Wed, 8 Mar 2023 09:20:21 +0100
|
||||
Subject: [PATCH] mtd: core: prepare mtd_otp_nvmem_add() to handle
|
||||
-EPROBE_DEFER
|
||||
|
||||
NVMEM soon will get the ability for nvmem layouts and these might
|
||||
not be ready when nvmem_register() is called and thus it might
|
||||
return -EPROBE_DEFER. Don't print the error message in this case.
|
||||
|
||||
Signed-off-by: Michael Walle <michael@walle.cc>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Link: https://lore.kernel.org/linux-mtd/20230308082021.870459-4-michael@walle.cc
|
||||
---
|
||||
drivers/mtd/mtdcore.c | 7 +++----
|
||||
1 file changed, 3 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/mtd/mtdcore.c
|
||||
+++ b/drivers/mtd/mtdcore.c
|
||||
@@ -960,8 +960,8 @@ static int mtd_otp_nvmem_add(struct mtd_
|
||||
nvmem = mtd_otp_nvmem_register(mtd, "user-otp", size,
|
||||
mtd_nvmem_user_otp_reg_read);
|
||||
if (IS_ERR(nvmem)) {
|
||||
- dev_err(dev, "Failed to register OTP NVMEM device\n");
|
||||
- return PTR_ERR(nvmem);
|
||||
+ err = PTR_ERR(nvmem);
|
||||
+ goto err;
|
||||
}
|
||||
mtd->otp_user_nvmem = nvmem;
|
||||
}
|
||||
@@ -978,7 +978,6 @@ static int mtd_otp_nvmem_add(struct mtd_
|
||||
nvmem = mtd_otp_nvmem_register(mtd, "factory-otp", size,
|
||||
mtd_nvmem_fact_otp_reg_read);
|
||||
if (IS_ERR(nvmem)) {
|
||||
- dev_err(dev, "Failed to register OTP NVMEM device\n");
|
||||
err = PTR_ERR(nvmem);
|
||||
goto err;
|
||||
}
|
||||
@@ -991,7 +990,7 @@ static int mtd_otp_nvmem_add(struct mtd_
|
||||
err:
|
||||
if (mtd->otp_user_nvmem)
|
||||
nvmem_unregister(mtd->otp_user_nvmem);
|
||||
- return err;
|
||||
+ return dev_err_probe(dev, err, "Failed to register OTP NVMEM device\n");
|
||||
}
|
||||
|
||||
/**
|
|
@ -0,0 +1,35 @@
|
|||
From bcd1fe07def0f070eb5f31594620aaee6f81d31a Mon Sep 17 00:00:00 2001
|
||||
From: Nick Alcock <nick.alcock@oracle.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:11 +0100
|
||||
Subject: [PATCH] nvmem: xilinx: zynqmp: make modular
|
||||
|
||||
This driver has a MODULE_LICENSE but is not tristate so cannot be
|
||||
built as a module, unlike all its peers: make it modular to match.
|
||||
|
||||
Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
|
||||
Suggested-by: Michal Simek <michal.simek@amd.com>
|
||||
Cc: Luis Chamberlain <mcgrof@kernel.org>
|
||||
Cc: linux-modules@vger.kernel.org
|
||||
Cc: linux-kernel@vger.kernel.org
|
||||
Cc: Hitomi Hasegawa <hasegawa-hitomi@fujitsu.com>
|
||||
Cc: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Cc: Michal Simek <michal.simek@xilinx.com>
|
||||
Cc: linux-arm-kernel@lists.infradead.org
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-4-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/Kconfig | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/nvmem/Kconfig
|
||||
+++ b/drivers/nvmem/Kconfig
|
||||
@@ -368,7 +368,7 @@ config NVMEM_VF610_OCOTP
|
||||
be called nvmem-vf610-ocotp.
|
||||
|
||||
config NVMEM_ZYNQMP
|
||||
- bool "Xilinx ZYNQMP SoC nvmem firmware support"
|
||||
+ tristate "Xilinx ZYNQMP SoC nvmem firmware support"
|
||||
depends on ARCH_ZYNQMP
|
||||
help
|
||||
This is a driver to access hardware related data like
|
|
@ -0,0 +1,387 @@
|
|||
From 266570f496b90dea8fda893c2cf7c28d63ae2bd9 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Walle <michael@walle.cc>
|
||||
Date: Tue, 4 Apr 2023 18:21:21 +0100
|
||||
Subject: [PATCH] nvmem: core: introduce NVMEM layouts
|
||||
|
||||
NVMEM layouts are used to generate NVMEM cells during runtime. Think of
|
||||
an EEPROM with a well-defined conent. For now, the content can be
|
||||
described by a device tree or a board file. But this only works if the
|
||||
offsets and lengths are static and don't change. One could also argue
|
||||
that putting the layout of the EEPROM in the device tree is the wrong
|
||||
place. Instead, the device tree should just have a specific compatible
|
||||
string.
|
||||
|
||||
Right now there are two use cases:
|
||||
(1) The NVMEM cell needs special processing. E.g. if it only specifies
|
||||
a base MAC address offset and you need to add an offset, or it
|
||||
needs to parse a MAC from ASCII format or some proprietary format.
|
||||
(Post processing of cells is added in a later commit).
|
||||
(2) u-boot environment parsing. The cells don't have a particular
|
||||
offset but it needs parsing the content to determine the offsets
|
||||
and length.
|
||||
|
||||
Co-developed-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Signed-off-by: Michael Walle <michael@walle.cc>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-14-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
Documentation/driver-api/nvmem.rst | 15 ++++
|
||||
drivers/nvmem/Kconfig | 4 +
|
||||
drivers/nvmem/Makefile | 1 +
|
||||
drivers/nvmem/core.c | 120 +++++++++++++++++++++++++++++
|
||||
drivers/nvmem/layouts/Kconfig | 5 ++
|
||||
drivers/nvmem/layouts/Makefile | 4 +
|
||||
include/linux/nvmem-consumer.h | 7 ++
|
||||
include/linux/nvmem-provider.h | 51 ++++++++++++
|
||||
8 files changed, 207 insertions(+)
|
||||
create mode 100644 drivers/nvmem/layouts/Kconfig
|
||||
create mode 100644 drivers/nvmem/layouts/Makefile
|
||||
|
||||
--- a/Documentation/driver-api/nvmem.rst
|
||||
+++ b/Documentation/driver-api/nvmem.rst
|
||||
@@ -189,3 +189,18 @@ ex::
|
||||
=====================
|
||||
|
||||
See Documentation/devicetree/bindings/nvmem/nvmem.txt
|
||||
+
|
||||
+8. NVMEM layouts
|
||||
+================
|
||||
+
|
||||
+NVMEM layouts are yet another mechanism to create cells. With the device
|
||||
+tree binding it is possible to specify simple cells by using an offset
|
||||
+and a length. Sometimes, the cells doesn't have a static offset, but
|
||||
+the content is still well defined, e.g. tag-length-values. In this case,
|
||||
+the NVMEM device content has to be first parsed and the cells need to
|
||||
+be added accordingly. Layouts let you read the content of the NVMEM device
|
||||
+and let you add cells dynamically.
|
||||
+
|
||||
+Another use case for layouts is the post processing of cells. With layouts,
|
||||
+it is possible to associate a custom post processing hook to a cell. It
|
||||
+even possible to add this hook to cells not created by the layout itself.
|
||||
--- a/drivers/nvmem/Kconfig
|
||||
+++ b/drivers/nvmem/Kconfig
|
||||
@@ -21,6 +21,10 @@ config NVMEM_SYSFS
|
||||
This interface is mostly used by userspace applications to
|
||||
read/write directly into nvmem.
|
||||
|
||||
+# Layouts
|
||||
+
|
||||
+source "drivers/nvmem/layouts/Kconfig"
|
||||
+
|
||||
# Devices
|
||||
|
||||
config NVMEM_APPLE_EFUSES
|
||||
--- a/drivers/nvmem/Makefile
|
||||
+++ b/drivers/nvmem/Makefile
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
obj-$(CONFIG_NVMEM) += nvmem_core.o
|
||||
nvmem_core-y := core.o
|
||||
+obj-y += layouts/
|
||||
|
||||
# Devices
|
||||
obj-$(CONFIG_NVMEM_APPLE_EFUSES) += nvmem-apple-efuses.o
|
||||
--- a/drivers/nvmem/core.c
|
||||
+++ b/drivers/nvmem/core.c
|
||||
@@ -40,6 +40,7 @@ struct nvmem_device {
|
||||
nvmem_reg_write_t reg_write;
|
||||
nvmem_cell_post_process_t cell_post_process;
|
||||
struct gpio_desc *wp_gpio;
|
||||
+ struct nvmem_layout *layout;
|
||||
void *priv;
|
||||
};
|
||||
|
||||
@@ -74,6 +75,9 @@ static LIST_HEAD(nvmem_lookup_list);
|
||||
|
||||
static BLOCKING_NOTIFIER_HEAD(nvmem_notifier);
|
||||
|
||||
+static DEFINE_SPINLOCK(nvmem_layout_lock);
|
||||
+static LIST_HEAD(nvmem_layouts);
|
||||
+
|
||||
static int __nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset,
|
||||
void *val, size_t bytes)
|
||||
{
|
||||
@@ -728,6 +732,101 @@ static int nvmem_add_cells_from_of(struc
|
||||
return 0;
|
||||
}
|
||||
|
||||
+int __nvmem_layout_register(struct nvmem_layout *layout, struct module *owner)
|
||||
+{
|
||||
+ layout->owner = owner;
|
||||
+
|
||||
+ spin_lock(&nvmem_layout_lock);
|
||||
+ list_add(&layout->node, &nvmem_layouts);
|
||||
+ spin_unlock(&nvmem_layout_lock);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(__nvmem_layout_register);
|
||||
+
|
||||
+void nvmem_layout_unregister(struct nvmem_layout *layout)
|
||||
+{
|
||||
+ spin_lock(&nvmem_layout_lock);
|
||||
+ list_del(&layout->node);
|
||||
+ spin_unlock(&nvmem_layout_lock);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(nvmem_layout_unregister);
|
||||
+
|
||||
+static struct nvmem_layout *nvmem_layout_get(struct nvmem_device *nvmem)
|
||||
+{
|
||||
+ struct device_node *layout_np, *np = nvmem->dev.of_node;
|
||||
+ struct nvmem_layout *l, *layout = NULL;
|
||||
+
|
||||
+ layout_np = of_get_child_by_name(np, "nvmem-layout");
|
||||
+ if (!layout_np)
|
||||
+ return NULL;
|
||||
+
|
||||
+ spin_lock(&nvmem_layout_lock);
|
||||
+
|
||||
+ list_for_each_entry(l, &nvmem_layouts, node) {
|
||||
+ if (of_match_node(l->of_match_table, layout_np)) {
|
||||
+ if (try_module_get(l->owner))
|
||||
+ layout = l;
|
||||
+
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ spin_unlock(&nvmem_layout_lock);
|
||||
+ of_node_put(layout_np);
|
||||
+
|
||||
+ return layout;
|
||||
+}
|
||||
+
|
||||
+static void nvmem_layout_put(struct nvmem_layout *layout)
|
||||
+{
|
||||
+ if (layout)
|
||||
+ module_put(layout->owner);
|
||||
+}
|
||||
+
|
||||
+static int nvmem_add_cells_from_layout(struct nvmem_device *nvmem)
|
||||
+{
|
||||
+ struct nvmem_layout *layout = nvmem->layout;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (layout && layout->add_cells) {
|
||||
+ ret = layout->add_cells(&nvmem->dev, nvmem, layout);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#if IS_ENABLED(CONFIG_OF)
|
||||
+/**
|
||||
+ * of_nvmem_layout_get_container() - Get OF node to layout container.
|
||||
+ *
|
||||
+ * @nvmem: nvmem device.
|
||||
+ *
|
||||
+ * Return: a node pointer with refcount incremented or NULL if no
|
||||
+ * container exists. Use of_node_put() on it when done.
|
||||
+ */
|
||||
+struct device_node *of_nvmem_layout_get_container(struct nvmem_device *nvmem)
|
||||
+{
|
||||
+ return of_get_child_by_name(nvmem->dev.of_node, "nvmem-layout");
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(of_nvmem_layout_get_container);
|
||||
+#endif
|
||||
+
|
||||
+const void *nvmem_layout_get_match_data(struct nvmem_device *nvmem,
|
||||
+ struct nvmem_layout *layout)
|
||||
+{
|
||||
+ struct device_node __maybe_unused *layout_np;
|
||||
+ const struct of_device_id *match;
|
||||
+
|
||||
+ layout_np = of_nvmem_layout_get_container(nvmem);
|
||||
+ match = of_match_node(layout->of_match_table, layout_np);
|
||||
+
|
||||
+ return match ? match->data : NULL;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(nvmem_layout_get_match_data);
|
||||
+
|
||||
/**
|
||||
* nvmem_register() - Register a nvmem device for given nvmem_config.
|
||||
* Also creates a binary entry in /sys/bus/nvmem/devices/dev-name/nvmem
|
||||
@@ -834,6 +933,12 @@ struct nvmem_device *nvmem_register(cons
|
||||
goto err_put_device;
|
||||
}
|
||||
|
||||
+ /*
|
||||
+ * If the driver supplied a layout by config->layout, the module
|
||||
+ * pointer will be NULL and nvmem_layout_put() will be a noop.
|
||||
+ */
|
||||
+ nvmem->layout = config->layout ?: nvmem_layout_get(nvmem);
|
||||
+
|
||||
if (config->cells) {
|
||||
rval = nvmem_add_cells(nvmem, config->cells, config->ncells);
|
||||
if (rval)
|
||||
@@ -854,12 +959,17 @@ struct nvmem_device *nvmem_register(cons
|
||||
if (rval)
|
||||
goto err_remove_cells;
|
||||
|
||||
+ rval = nvmem_add_cells_from_layout(nvmem);
|
||||
+ if (rval)
|
||||
+ goto err_remove_cells;
|
||||
+
|
||||
blocking_notifier_call_chain(&nvmem_notifier, NVMEM_ADD, nvmem);
|
||||
|
||||
return nvmem;
|
||||
|
||||
err_remove_cells:
|
||||
nvmem_device_remove_all_cells(nvmem);
|
||||
+ nvmem_layout_put(nvmem->layout);
|
||||
if (config->compat)
|
||||
nvmem_sysfs_remove_compat(nvmem, config);
|
||||
err_put_device:
|
||||
@@ -881,6 +991,7 @@ static void nvmem_device_release(struct
|
||||
device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom);
|
||||
|
||||
nvmem_device_remove_all_cells(nvmem);
|
||||
+ nvmem_layout_put(nvmem->layout);
|
||||
device_unregister(&nvmem->dev);
|
||||
}
|
||||
|
||||
@@ -1246,6 +1357,15 @@ struct nvmem_cell *of_nvmem_cell_get(str
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
+ /* nvmem layouts produce cells within the nvmem-layout container */
|
||||
+ if (of_node_name_eq(nvmem_np, "nvmem-layout")) {
|
||||
+ nvmem_np = of_get_next_parent(nvmem_np);
|
||||
+ if (!nvmem_np) {
|
||||
+ of_node_put(cell_np);
|
||||
+ return ERR_PTR(-EINVAL);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
nvmem = __nvmem_device_get(nvmem_np, device_match_of_node);
|
||||
of_node_put(nvmem_np);
|
||||
if (IS_ERR(nvmem)) {
|
||||
--- /dev/null
|
||||
+++ b/drivers/nvmem/layouts/Kconfig
|
||||
@@ -0,0 +1,5 @@
|
||||
+# SPDX-License-Identifier: GPL-2.0
|
||||
+
|
||||
+menu "Layout Types"
|
||||
+
|
||||
+endmenu
|
||||
--- /dev/null
|
||||
+++ b/drivers/nvmem/layouts/Makefile
|
||||
@@ -0,0 +1,4 @@
|
||||
+# SPDX-License-Identifier: GPL-2.0
|
||||
+#
|
||||
+# Makefile for nvmem layouts.
|
||||
+#
|
||||
--- a/include/linux/nvmem-consumer.h
|
||||
+++ b/include/linux/nvmem-consumer.h
|
||||
@@ -239,6 +239,7 @@ struct nvmem_cell *of_nvmem_cell_get(str
|
||||
const char *id);
|
||||
struct nvmem_device *of_nvmem_device_get(struct device_node *np,
|
||||
const char *name);
|
||||
+struct device_node *of_nvmem_layout_get_container(struct nvmem_device *nvmem);
|
||||
#else
|
||||
static inline struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
|
||||
const char *id)
|
||||
@@ -251,6 +252,12 @@ static inline struct nvmem_device *of_nv
|
||||
{
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
+
|
||||
+static inline struct device_node *
|
||||
+of_nvmem_layout_get_container(struct nvmem_device *nvmem)
|
||||
+{
|
||||
+ return ERR_PTR(-EOPNOTSUPP);
|
||||
+}
|
||||
#endif /* CONFIG_NVMEM && CONFIG_OF */
|
||||
|
||||
#endif /* ifndef _LINUX_NVMEM_CONSUMER_H */
|
||||
--- a/include/linux/nvmem-provider.h
|
||||
+++ b/include/linux/nvmem-provider.h
|
||||
@@ -88,6 +88,7 @@ struct nvmem_cell_info {
|
||||
* @stride: Minimum read/write access stride.
|
||||
* @priv: User context passed to read/write callbacks.
|
||||
* @ignore_wp: Write Protect pin is managed by the provider.
|
||||
+ * @layout: Fixed layout associated with this nvmem device.
|
||||
*
|
||||
* Note: A default "nvmem<id>" name will be assigned to the device if
|
||||
* no name is specified in its configuration. In such case "<id>" is
|
||||
@@ -109,6 +110,7 @@ struct nvmem_config {
|
||||
bool read_only;
|
||||
bool root_only;
|
||||
bool ignore_wp;
|
||||
+ struct nvmem_layout *layout;
|
||||
struct device_node *of_node;
|
||||
bool no_of_node;
|
||||
nvmem_reg_read_t reg_read;
|
||||
@@ -142,6 +144,33 @@ struct nvmem_cell_table {
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
+/**
|
||||
+ * struct nvmem_layout - NVMEM layout definitions
|
||||
+ *
|
||||
+ * @name: Layout name.
|
||||
+ * @of_match_table: Open firmware match table.
|
||||
+ * @add_cells: Will be called if a nvmem device is found which
|
||||
+ * has this layout. The function will add layout
|
||||
+ * specific cells with nvmem_add_one_cell().
|
||||
+ * @owner: Pointer to struct module.
|
||||
+ * @node: List node.
|
||||
+ *
|
||||
+ * A nvmem device can hold a well defined structure which can just be
|
||||
+ * evaluated during runtime. For example a TLV list, or a list of "name=val"
|
||||
+ * pairs. A nvmem layout can parse the nvmem device and add appropriate
|
||||
+ * cells.
|
||||
+ */
|
||||
+struct nvmem_layout {
|
||||
+ const char *name;
|
||||
+ const struct of_device_id *of_match_table;
|
||||
+ int (*add_cells)(struct device *dev, struct nvmem_device *nvmem,
|
||||
+ struct nvmem_layout *layout);
|
||||
+
|
||||
+ /* private */
|
||||
+ struct module *owner;
|
||||
+ struct list_head node;
|
||||
+};
|
||||
+
|
||||
#if IS_ENABLED(CONFIG_NVMEM)
|
||||
|
||||
struct nvmem_device *nvmem_register(const struct nvmem_config *cfg);
|
||||
@@ -156,6 +185,14 @@ void nvmem_del_cell_table(struct nvmem_c
|
||||
int nvmem_add_one_cell(struct nvmem_device *nvmem,
|
||||
const struct nvmem_cell_info *info);
|
||||
|
||||
+int __nvmem_layout_register(struct nvmem_layout *layout, struct module *owner);
|
||||
+#define nvmem_layout_register(layout) \
|
||||
+ __nvmem_layout_register(layout, THIS_MODULE)
|
||||
+void nvmem_layout_unregister(struct nvmem_layout *layout);
|
||||
+
|
||||
+const void *nvmem_layout_get_match_data(struct nvmem_device *nvmem,
|
||||
+ struct nvmem_layout *layout);
|
||||
+
|
||||
#else
|
||||
|
||||
static inline struct nvmem_device *nvmem_register(const struct nvmem_config *c)
|
||||
@@ -179,5 +216,19 @@ static inline int nvmem_add_one_cell(str
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
+static inline int nvmem_layout_register(struct nvmem_layout *layout)
|
||||
+{
|
||||
+ return -EOPNOTSUPP;
|
||||
+}
|
||||
+
|
||||
+static inline void nvmem_layout_unregister(struct nvmem_layout *layout) {}
|
||||
+
|
||||
+static inline const void *
|
||||
+nvmem_layout_get_match_data(struct nvmem_device *nvmem,
|
||||
+ struct nvmem_layout *layout)
|
||||
+{
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
#endif /* CONFIG_NVMEM */
|
||||
#endif /* ifndef _LINUX_NVMEM_PROVIDER_H */
|
|
@ -0,0 +1,61 @@
|
|||
From 6468a6f45148fb5e95c86b4efebf63f9abcd2137 Mon Sep 17 00:00:00 2001
|
||||
From: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:22 +0100
|
||||
Subject: [PATCH] nvmem: core: handle the absence of expected layouts
|
||||
|
||||
Make nvmem_layout_get() return -EPROBE_DEFER while the expected layout
|
||||
is not available. This condition cannot be triggered today as nvmem
|
||||
layout drivers are initialed as part of an early init call, but soon
|
||||
these drivers will be converted into modules and be initialized with a
|
||||
standard priority, so the unavailability of the drivers might become a
|
||||
reality that must be taken care of.
|
||||
|
||||
Let's anticipate this by telling the caller the layout might not yet be
|
||||
available. A probe deferral is requested in this case.
|
||||
|
||||
Please note this does not affect any nvmem device not using layouts,
|
||||
because an early check against the "nvmem-layout" container presence
|
||||
will return NULL in this case.
|
||||
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Tested-by: Michael Walle <michael@walle.cc>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-15-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/core.c | 10 +++++++++-
|
||||
1 file changed, 9 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/nvmem/core.c
|
||||
+++ b/drivers/nvmem/core.c
|
||||
@@ -755,7 +755,7 @@ EXPORT_SYMBOL_GPL(nvmem_layout_unregiste
|
||||
static struct nvmem_layout *nvmem_layout_get(struct nvmem_device *nvmem)
|
||||
{
|
||||
struct device_node *layout_np, *np = nvmem->dev.of_node;
|
||||
- struct nvmem_layout *l, *layout = NULL;
|
||||
+ struct nvmem_layout *l, *layout = ERR_PTR(-EPROBE_DEFER);
|
||||
|
||||
layout_np = of_get_child_by_name(np, "nvmem-layout");
|
||||
if (!layout_np)
|
||||
@@ -938,6 +938,13 @@ struct nvmem_device *nvmem_register(cons
|
||||
* pointer will be NULL and nvmem_layout_put() will be a noop.
|
||||
*/
|
||||
nvmem->layout = config->layout ?: nvmem_layout_get(nvmem);
|
||||
+ if (IS_ERR(nvmem->layout)) {
|
||||
+ rval = PTR_ERR(nvmem->layout);
|
||||
+ nvmem->layout = NULL;
|
||||
+
|
||||
+ if (rval == -EPROBE_DEFER)
|
||||
+ goto err_teardown_compat;
|
||||
+ }
|
||||
|
||||
if (config->cells) {
|
||||
rval = nvmem_add_cells(nvmem, config->cells, config->ncells);
|
||||
@@ -970,6 +977,7 @@ struct nvmem_device *nvmem_register(cons
|
||||
err_remove_cells:
|
||||
nvmem_device_remove_all_cells(nvmem);
|
||||
nvmem_layout_put(nvmem->layout);
|
||||
+err_teardown_compat:
|
||||
if (config->compat)
|
||||
nvmem_sysfs_remove_compat(nvmem, config);
|
||||
err_put_device:
|
|
@ -0,0 +1,52 @@
|
|||
From b1c37bec1ccfe5ccab72bc0ddc0dfa45c43e2de2 Mon Sep 17 00:00:00 2001
|
||||
From: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:23 +0100
|
||||
Subject: [PATCH] nvmem: core: request layout modules loading
|
||||
|
||||
When a storage device like an eeprom or an mtd device probes, it
|
||||
registers an nvmem device if the nvmem subsystem has been enabled (bool
|
||||
symbol). During nvmem registration, if the device is using layouts to
|
||||
expose dynamic nvmem cells, the core will first try to get a reference
|
||||
over the layout driver callbacks. In practice there is not relationship
|
||||
that can be described between the storage driver and the nvmem
|
||||
layout. So there is no way we can enforce both drivers will be built-in
|
||||
or both will be modules. If the storage device driver is built-in but
|
||||
the layout is built as a module, instead of badly failing with an
|
||||
endless probe deferral loop, lets just make a modprobe call in case the
|
||||
driver was made available in an initramfs with
|
||||
of_device_node_request_module(), and offer a fully functional system to
|
||||
the user.
|
||||
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Tested-by: Michael Walle <michael@walle.cc>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-16-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/core.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
--- a/drivers/nvmem/core.c
|
||||
+++ b/drivers/nvmem/core.c
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <linux/nvmem-provider.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/of.h>
|
||||
+#include <linux/of_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
struct nvmem_device {
|
||||
@@ -761,6 +762,13 @@ static struct nvmem_layout *nvmem_layout
|
||||
if (!layout_np)
|
||||
return NULL;
|
||||
|
||||
+ /*
|
||||
+ * In case the nvmem device was built-in while the layout was built as a
|
||||
+ * module, we shall manually request the layout driver loading otherwise
|
||||
+ * we'll never have any match.
|
||||
+ */
|
||||
+ of_request_module(layout_np);
|
||||
+
|
||||
spin_lock(&nvmem_layout_lock);
|
||||
|
||||
list_for_each_entry(l, &nvmem_layouts, node) {
|
|
@ -0,0 +1,86 @@
|
|||
From 345ec382cd4b736c36e01f155d08c913b225b736 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Walle <michael@walle.cc>
|
||||
Date: Tue, 4 Apr 2023 18:21:24 +0100
|
||||
Subject: [PATCH] nvmem: core: add per-cell post processing
|
||||
|
||||
Instead of relying on the name the consumer is using for the cell, like
|
||||
it is done for the nvmem .cell_post_process configuration parameter,
|
||||
provide a per-cell post processing hook. This can then be populated by
|
||||
the NVMEM provider (or the NVMEM layout) when adding the cell.
|
||||
|
||||
Signed-off-by: Michael Walle <michael@walle.cc>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-17-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/core.c | 17 +++++++++++++++++
|
||||
include/linux/nvmem-provider.h | 3 +++
|
||||
2 files changed, 20 insertions(+)
|
||||
|
||||
--- a/drivers/nvmem/core.c
|
||||
+++ b/drivers/nvmem/core.c
|
||||
@@ -54,6 +54,7 @@ struct nvmem_cell_entry {
|
||||
int bytes;
|
||||
int bit_offset;
|
||||
int nbits;
|
||||
+ nvmem_cell_post_process_t read_post_process;
|
||||
struct device_node *np;
|
||||
struct nvmem_device *nvmem;
|
||||
struct list_head node;
|
||||
@@ -470,6 +471,7 @@ static int nvmem_cell_info_to_nvmem_cell
|
||||
cell->offset = info->offset;
|
||||
cell->bytes = info->bytes;
|
||||
cell->name = info->name;
|
||||
+ cell->read_post_process = info->read_post_process;
|
||||
|
||||
cell->bit_offset = info->bit_offset;
|
||||
cell->nbits = info->nbits;
|
||||
@@ -1563,6 +1565,13 @@ static int __nvmem_cell_read(struct nvme
|
||||
if (cell->bit_offset || cell->nbits)
|
||||
nvmem_shift_read_buffer_in_place(cell, buf);
|
||||
|
||||
+ if (cell->read_post_process) {
|
||||
+ rc = cell->read_post_process(nvmem->priv, id, index,
|
||||
+ cell->offset, buf, cell->bytes);
|
||||
+ if (rc)
|
||||
+ return rc;
|
||||
+ }
|
||||
+
|
||||
if (nvmem->cell_post_process) {
|
||||
rc = nvmem->cell_post_process(nvmem->priv, id, index,
|
||||
cell->offset, buf, cell->bytes);
|
||||
@@ -1671,6 +1680,14 @@ static int __nvmem_cell_entry_write(stru
|
||||
(cell->bit_offset == 0 && len != cell->bytes))
|
||||
return -EINVAL;
|
||||
|
||||
+ /*
|
||||
+ * Any cells which have a read_post_process hook are read-only because
|
||||
+ * we cannot reverse the operation and it might affect other cells,
|
||||
+ * too.
|
||||
+ */
|
||||
+ if (cell->read_post_process)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
if (cell->bit_offset || cell->nbits) {
|
||||
buf = nvmem_cell_prepare_write_buffer(cell, buf, len);
|
||||
if (IS_ERR(buf))
|
||||
--- a/include/linux/nvmem-provider.h
|
||||
+++ b/include/linux/nvmem-provider.h
|
||||
@@ -54,6 +54,8 @@ struct nvmem_keepout {
|
||||
* @bit_offset: Bit offset if cell is smaller than a byte.
|
||||
* @nbits: Number of bits.
|
||||
* @np: Optional device_node pointer.
|
||||
+ * @read_post_process: Callback for optional post processing of cell data
|
||||
+ * on reads.
|
||||
*/
|
||||
struct nvmem_cell_info {
|
||||
const char *name;
|
||||
@@ -62,6 +64,7 @@ struct nvmem_cell_info {
|
||||
unsigned int bit_offset;
|
||||
unsigned int nbits;
|
||||
struct device_node *np;
|
||||
+ nvmem_cell_post_process_t read_post_process;
|
||||
};
|
||||
|
||||
/**
|
|
@ -0,0 +1,59 @@
|
|||
From de12c9691501ccba41a154c223869f82be4c12fd Mon Sep 17 00:00:00 2001
|
||||
From: Michael Walle <michael@walle.cc>
|
||||
Date: Tue, 4 Apr 2023 18:21:25 +0100
|
||||
Subject: [PATCH] nvmem: core: allow to modify a cell before adding it
|
||||
|
||||
Provide a way to modify a cell before it will get added. This is useful
|
||||
to attach a custom post processing hook via a layout.
|
||||
|
||||
Signed-off-by: Michael Walle <michael@walle.cc>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-18-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/core.c | 4 ++++
|
||||
include/linux/nvmem-provider.h | 5 +++++
|
||||
2 files changed, 9 insertions(+)
|
||||
|
||||
--- a/drivers/nvmem/core.c
|
||||
+++ b/drivers/nvmem/core.c
|
||||
@@ -695,6 +695,7 @@ static int nvmem_validate_keepouts(struc
|
||||
|
||||
static int nvmem_add_cells_from_of(struct nvmem_device *nvmem)
|
||||
{
|
||||
+ struct nvmem_layout *layout = nvmem->layout;
|
||||
struct device *dev = &nvmem->dev;
|
||||
struct device_node *child;
|
||||
const __be32 *addr;
|
||||
@@ -724,6 +725,9 @@ static int nvmem_add_cells_from_of(struc
|
||||
|
||||
info.np = of_node_get(child);
|
||||
|
||||
+ if (layout && layout->fixup_cell_info)
|
||||
+ layout->fixup_cell_info(nvmem, layout, &info);
|
||||
+
|
||||
ret = nvmem_add_one_cell(nvmem, &info);
|
||||
kfree(info.name);
|
||||
if (ret) {
|
||||
--- a/include/linux/nvmem-provider.h
|
||||
+++ b/include/linux/nvmem-provider.h
|
||||
@@ -155,6 +155,8 @@ struct nvmem_cell_table {
|
||||
* @add_cells: Will be called if a nvmem device is found which
|
||||
* has this layout. The function will add layout
|
||||
* specific cells with nvmem_add_one_cell().
|
||||
+ * @fixup_cell_info: Will be called before a cell is added. Can be
|
||||
+ * used to modify the nvmem_cell_info.
|
||||
* @owner: Pointer to struct module.
|
||||
* @node: List node.
|
||||
*
|
||||
@@ -168,6 +170,9 @@ struct nvmem_layout {
|
||||
const struct of_device_id *of_match_table;
|
||||
int (*add_cells)(struct device *dev, struct nvmem_device *nvmem,
|
||||
struct nvmem_layout *layout);
|
||||
+ void (*fixup_cell_info)(struct nvmem_device *nvmem,
|
||||
+ struct nvmem_layout *layout,
|
||||
+ struct nvmem_cell_info *cell);
|
||||
|
||||
/* private */
|
||||
struct module *owner;
|
|
@ -0,0 +1,81 @@
|
|||
From 6c56a82d7895a213a43182a5d01a21a906a79847 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Walle <michael@walle.cc>
|
||||
Date: Tue, 4 Apr 2023 18:21:26 +0100
|
||||
Subject: [PATCH] nvmem: imx-ocotp: replace global post processing with layouts
|
||||
|
||||
In preparation of retiring the global post processing hook change this
|
||||
driver to use layouts. The layout will be supplied during registration
|
||||
and will be used to add the post processing hook to all added cells.
|
||||
|
||||
Signed-off-by: Michael Walle <michael@walle.cc>
|
||||
Tested-by: Michael Walle <michael@walle.cc> # on kontron-pitx-imx8m
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-19-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/imx-ocotp.c | 30 +++++++++++++++++++-----------
|
||||
1 file changed, 19 insertions(+), 11 deletions(-)
|
||||
|
||||
--- a/drivers/nvmem/imx-ocotp.c
|
||||
+++ b/drivers/nvmem/imx-ocotp.c
|
||||
@@ -225,18 +225,13 @@ read_end:
|
||||
static int imx_ocotp_cell_pp(void *context, const char *id, int index,
|
||||
unsigned int offset, void *data, size_t bytes)
|
||||
{
|
||||
- struct ocotp_priv *priv = context;
|
||||
+ u8 *buf = data;
|
||||
+ int i;
|
||||
|
||||
/* Deal with some post processing of nvmem cell data */
|
||||
- if (id && !strcmp(id, "mac-address")) {
|
||||
- if (priv->params->reverse_mac_address) {
|
||||
- u8 *buf = data;
|
||||
- int i;
|
||||
-
|
||||
- for (i = 0; i < bytes/2; i++)
|
||||
- swap(buf[i], buf[bytes - i - 1]);
|
||||
- }
|
||||
- }
|
||||
+ if (id && !strcmp(id, "mac-address"))
|
||||
+ for (i = 0; i < bytes / 2; i++)
|
||||
+ swap(buf[i], buf[bytes - i - 1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -488,7 +483,6 @@ static struct nvmem_config imx_ocotp_nvm
|
||||
.stride = 1,
|
||||
.reg_read = imx_ocotp_read,
|
||||
.reg_write = imx_ocotp_write,
|
||||
- .cell_post_process = imx_ocotp_cell_pp,
|
||||
};
|
||||
|
||||
static const struct ocotp_params imx6q_params = {
|
||||
@@ -595,6 +589,17 @@ static const struct of_device_id imx_oco
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, imx_ocotp_dt_ids);
|
||||
|
||||
+static void imx_ocotp_fixup_cell_info(struct nvmem_device *nvmem,
|
||||
+ struct nvmem_layout *layout,
|
||||
+ struct nvmem_cell_info *cell)
|
||||
+{
|
||||
+ cell->read_post_process = imx_ocotp_cell_pp;
|
||||
+}
|
||||
+
|
||||
+struct nvmem_layout imx_ocotp_layout = {
|
||||
+ .fixup_cell_info = imx_ocotp_fixup_cell_info,
|
||||
+};
|
||||
+
|
||||
static int imx_ocotp_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
@@ -619,6 +624,9 @@ static int imx_ocotp_probe(struct platfo
|
||||
imx_ocotp_nvmem_config.size = 4 * priv->params->nregs;
|
||||
imx_ocotp_nvmem_config.dev = dev;
|
||||
imx_ocotp_nvmem_config.priv = priv;
|
||||
+ if (priv->params->reverse_mac_address)
|
||||
+ imx_ocotp_nvmem_config.layout = &imx_ocotp_layout;
|
||||
+
|
||||
priv->config = &imx_ocotp_nvmem_config;
|
||||
|
||||
clk_prepare_enable(priv->clk);
|
|
@ -0,0 +1,68 @@
|
|||
From 011e40a166fdaa65fb9946b7cd91efec85b70dbb Mon Sep 17 00:00:00 2001
|
||||
From: Michael Walle <michael@walle.cc>
|
||||
Date: Tue, 4 Apr 2023 18:21:27 +0100
|
||||
Subject: [PATCH] nvmem: cell: drop global cell_post_process
|
||||
|
||||
There are no users anymore for the global cell_post_process callback
|
||||
anymore. New users should use proper nvmem layouts.
|
||||
|
||||
Signed-off-by: Michael Walle <michael@walle.cc>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-20-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/core.c | 9 ---------
|
||||
include/linux/nvmem-provider.h | 2 --
|
||||
2 files changed, 11 deletions(-)
|
||||
|
||||
--- a/drivers/nvmem/core.c
|
||||
+++ b/drivers/nvmem/core.c
|
||||
@@ -39,7 +39,6 @@ struct nvmem_device {
|
||||
unsigned int nkeepout;
|
||||
nvmem_reg_read_t reg_read;
|
||||
nvmem_reg_write_t reg_write;
|
||||
- nvmem_cell_post_process_t cell_post_process;
|
||||
struct gpio_desc *wp_gpio;
|
||||
struct nvmem_layout *layout;
|
||||
void *priv;
|
||||
@@ -903,7 +902,6 @@ struct nvmem_device *nvmem_register(cons
|
||||
nvmem->type = config->type;
|
||||
nvmem->reg_read = config->reg_read;
|
||||
nvmem->reg_write = config->reg_write;
|
||||
- nvmem->cell_post_process = config->cell_post_process;
|
||||
nvmem->keepout = config->keepout;
|
||||
nvmem->nkeepout = config->nkeepout;
|
||||
if (config->of_node)
|
||||
@@ -1575,13 +1573,6 @@ static int __nvmem_cell_read(struct nvme
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
-
|
||||
- if (nvmem->cell_post_process) {
|
||||
- rc = nvmem->cell_post_process(nvmem->priv, id, index,
|
||||
- cell->offset, buf, cell->bytes);
|
||||
- if (rc)
|
||||
- return rc;
|
||||
- }
|
||||
|
||||
if (len)
|
||||
*len = cell->bytes;
|
||||
--- a/include/linux/nvmem-provider.h
|
||||
+++ b/include/linux/nvmem-provider.h
|
||||
@@ -85,7 +85,6 @@ struct nvmem_cell_info {
|
||||
* @no_of_node: Device should not use the parent's of_node even if it's !NULL.
|
||||
* @reg_read: Callback to read data.
|
||||
* @reg_write: Callback to write data.
|
||||
- * @cell_post_process: Callback for vendor specific post processing of cell data
|
||||
* @size: Device size.
|
||||
* @word_size: Minimum read/write access granularity.
|
||||
* @stride: Minimum read/write access stride.
|
||||
@@ -118,7 +117,6 @@ struct nvmem_config {
|
||||
bool no_of_node;
|
||||
nvmem_reg_read_t reg_read;
|
||||
nvmem_reg_write_t reg_write;
|
||||
- nvmem_cell_post_process_t cell_post_process;
|
||||
int size;
|
||||
int word_size;
|
||||
int stride;
|
|
@ -0,0 +1,76 @@
|
|||
From 8a134fd9f9323f4c39ec27055b3d3723cfb5c1e9 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Walle <michael@walle.cc>
|
||||
Date: Tue, 4 Apr 2023 18:21:28 +0100
|
||||
Subject: [PATCH] nvmem: core: provide own priv pointer in post process
|
||||
callback
|
||||
|
||||
It doesn't make any more sense to have a opaque pointer set up by the
|
||||
nvmem device. Usually, the layout isn't associated with a particular
|
||||
nvmem device. Instead, let the caller who set the post process callback
|
||||
provide the priv pointer.
|
||||
|
||||
Signed-off-by: Michael Walle <michael@walle.cc>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-21-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/core.c | 4 +++-
|
||||
include/linux/nvmem-provider.h | 5 ++++-
|
||||
2 files changed, 7 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/nvmem/core.c
|
||||
+++ b/drivers/nvmem/core.c
|
||||
@@ -54,6 +54,7 @@ struct nvmem_cell_entry {
|
||||
int bit_offset;
|
||||
int nbits;
|
||||
nvmem_cell_post_process_t read_post_process;
|
||||
+ void *priv;
|
||||
struct device_node *np;
|
||||
struct nvmem_device *nvmem;
|
||||
struct list_head node;
|
||||
@@ -471,6 +472,7 @@ static int nvmem_cell_info_to_nvmem_cell
|
||||
cell->bytes = info->bytes;
|
||||
cell->name = info->name;
|
||||
cell->read_post_process = info->read_post_process;
|
||||
+ cell->priv = info->priv;
|
||||
|
||||
cell->bit_offset = info->bit_offset;
|
||||
cell->nbits = info->nbits;
|
||||
@@ -1568,7 +1570,7 @@ static int __nvmem_cell_read(struct nvme
|
||||
nvmem_shift_read_buffer_in_place(cell, buf);
|
||||
|
||||
if (cell->read_post_process) {
|
||||
- rc = cell->read_post_process(nvmem->priv, id, index,
|
||||
+ rc = cell->read_post_process(cell->priv, id, index,
|
||||
cell->offset, buf, cell->bytes);
|
||||
if (rc)
|
||||
return rc;
|
||||
--- a/include/linux/nvmem-provider.h
|
||||
+++ b/include/linux/nvmem-provider.h
|
||||
@@ -20,7 +20,8 @@ typedef int (*nvmem_reg_write_t)(void *p
|
||||
void *val, size_t bytes);
|
||||
/* used for vendor specific post processing of cell data */
|
||||
typedef int (*nvmem_cell_post_process_t)(void *priv, const char *id, int index,
|
||||
- unsigned int offset, void *buf, size_t bytes);
|
||||
+ unsigned int offset, void *buf,
|
||||
+ size_t bytes);
|
||||
|
||||
enum nvmem_type {
|
||||
NVMEM_TYPE_UNKNOWN = 0,
|
||||
@@ -56,6 +57,7 @@ struct nvmem_keepout {
|
||||
* @np: Optional device_node pointer.
|
||||
* @read_post_process: Callback for optional post processing of cell data
|
||||
* on reads.
|
||||
+ * @priv: Opaque data passed to the read_post_process hook.
|
||||
*/
|
||||
struct nvmem_cell_info {
|
||||
const char *name;
|
||||
@@ -65,6 +67,7 @@ struct nvmem_cell_info {
|
||||
unsigned int nbits;
|
||||
struct device_node *np;
|
||||
nvmem_cell_post_process_t read_post_process;
|
||||
+ void *priv;
|
||||
};
|
||||
|
||||
/**
|
|
@ -0,0 +1,215 @@
|
|||
From d9fae023fe86069750092fc1c2f3a73e2fb18512 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Walle <michael@walle.cc>
|
||||
Date: Tue, 4 Apr 2023 18:21:29 +0100
|
||||
Subject: [PATCH] nvmem: layouts: sl28vpd: Add new layout driver
|
||||
|
||||
This layout applies to the VPD of the Kontron sl28 boards. The VPD only
|
||||
contains a base MAC address. Therefore, we have to add an individual
|
||||
offset to it. This is done by taking the second argument of the nvmem
|
||||
phandle into account. Also this let us checking the VPD version and the
|
||||
checksum.
|
||||
|
||||
Signed-off-by: Michael Walle <michael@walle.cc>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-22-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/layouts/Kconfig | 9 ++
|
||||
drivers/nvmem/layouts/Makefile | 2 +
|
||||
drivers/nvmem/layouts/sl28vpd.c | 165 ++++++++++++++++++++++++++++++++
|
||||
3 files changed, 176 insertions(+)
|
||||
create mode 100644 drivers/nvmem/layouts/sl28vpd.c
|
||||
|
||||
--- a/drivers/nvmem/layouts/Kconfig
|
||||
+++ b/drivers/nvmem/layouts/Kconfig
|
||||
@@ -2,4 +2,13 @@
|
||||
|
||||
menu "Layout Types"
|
||||
|
||||
+config NVMEM_LAYOUT_SL28_VPD
|
||||
+ tristate "Kontron sl28 VPD layout support"
|
||||
+ select CRC8
|
||||
+ help
|
||||
+ Say Y here if you want to support the VPD layout of the Kontron
|
||||
+ SMARC-sAL28 boards.
|
||||
+
|
||||
+ If unsure, say N.
|
||||
+
|
||||
endmenu
|
||||
--- a/drivers/nvmem/layouts/Makefile
|
||||
+++ b/drivers/nvmem/layouts/Makefile
|
||||
@@ -2,3 +2,5 @@
|
||||
#
|
||||
# Makefile for nvmem layouts.
|
||||
#
|
||||
+
|
||||
+obj-$(CONFIG_NVMEM_LAYOUT_SL28_VPD) += sl28vpd.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/nvmem/layouts/sl28vpd.c
|
||||
@@ -0,0 +1,165 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+
|
||||
+#include <linux/crc8.h>
|
||||
+#include <linux/etherdevice.h>
|
||||
+#include <linux/nvmem-consumer.h>
|
||||
+#include <linux/nvmem-provider.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <uapi/linux/if_ether.h>
|
||||
+
|
||||
+#define SL28VPD_MAGIC 'V'
|
||||
+
|
||||
+struct sl28vpd_header {
|
||||
+ u8 magic;
|
||||
+ u8 version;
|
||||
+} __packed;
|
||||
+
|
||||
+struct sl28vpd_v1 {
|
||||
+ struct sl28vpd_header header;
|
||||
+ char serial_number[15];
|
||||
+ u8 base_mac_address[ETH_ALEN];
|
||||
+ u8 crc8;
|
||||
+} __packed;
|
||||
+
|
||||
+static int sl28vpd_mac_address_pp(void *priv, const char *id, int index,
|
||||
+ unsigned int offset, void *buf,
|
||||
+ size_t bytes)
|
||||
+{
|
||||
+ if (bytes != ETH_ALEN)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (index < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (!is_valid_ether_addr(buf))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ eth_addr_add(buf, index);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct nvmem_cell_info sl28vpd_v1_entries[] = {
|
||||
+ {
|
||||
+ .name = "serial-number",
|
||||
+ .offset = offsetof(struct sl28vpd_v1, serial_number),
|
||||
+ .bytes = sizeof_field(struct sl28vpd_v1, serial_number),
|
||||
+ },
|
||||
+ {
|
||||
+ .name = "base-mac-address",
|
||||
+ .offset = offsetof(struct sl28vpd_v1, base_mac_address),
|
||||
+ .bytes = sizeof_field(struct sl28vpd_v1, base_mac_address),
|
||||
+ .read_post_process = sl28vpd_mac_address_pp,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static int sl28vpd_v1_check_crc(struct device *dev, struct nvmem_device *nvmem)
|
||||
+{
|
||||
+ struct sl28vpd_v1 data_v1;
|
||||
+ u8 table[CRC8_TABLE_SIZE];
|
||||
+ int ret;
|
||||
+ u8 crc;
|
||||
+
|
||||
+ crc8_populate_msb(table, 0x07);
|
||||
+
|
||||
+ ret = nvmem_device_read(nvmem, 0, sizeof(data_v1), &data_v1);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ else if (ret != sizeof(data_v1))
|
||||
+ return -EIO;
|
||||
+
|
||||
+ crc = crc8(table, (void *)&data_v1, sizeof(data_v1) - 1, 0);
|
||||
+
|
||||
+ if (crc != data_v1.crc8) {
|
||||
+ dev_err(dev,
|
||||
+ "Checksum is invalid (got %02x, expected %02x).\n",
|
||||
+ crc, data_v1.crc8);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int sl28vpd_add_cells(struct device *dev, struct nvmem_device *nvmem,
|
||||
+ struct nvmem_layout *layout)
|
||||
+{
|
||||
+ const struct nvmem_cell_info *pinfo;
|
||||
+ struct nvmem_cell_info info = {0};
|
||||
+ struct device_node *layout_np;
|
||||
+ struct sl28vpd_header hdr;
|
||||
+ int ret, i;
|
||||
+
|
||||
+ /* check header */
|
||||
+ ret = nvmem_device_read(nvmem, 0, sizeof(hdr), &hdr);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ else if (ret != sizeof(hdr))
|
||||
+ return -EIO;
|
||||
+
|
||||
+ if (hdr.magic != SL28VPD_MAGIC) {
|
||||
+ dev_err(dev, "Invalid magic value (%02x)\n", hdr.magic);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (hdr.version != 1) {
|
||||
+ dev_err(dev, "Version %d is unsupported.\n", hdr.version);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ ret = sl28vpd_v1_check_crc(dev, nvmem);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ layout_np = of_nvmem_layout_get_container(nvmem);
|
||||
+ if (!layout_np)
|
||||
+ return -ENOENT;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(sl28vpd_v1_entries); i++) {
|
||||
+ pinfo = &sl28vpd_v1_entries[i];
|
||||
+
|
||||
+ info.name = pinfo->name;
|
||||
+ info.offset = pinfo->offset;
|
||||
+ info.bytes = pinfo->bytes;
|
||||
+ info.read_post_process = pinfo->read_post_process;
|
||||
+ info.np = of_get_child_by_name(layout_np, pinfo->name);
|
||||
+
|
||||
+ ret = nvmem_add_one_cell(nvmem, &info);
|
||||
+ if (ret) {
|
||||
+ of_node_put(layout_np);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ of_node_put(layout_np);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id sl28vpd_of_match_table[] = {
|
||||
+ { .compatible = "kontron,sl28-vpd" },
|
||||
+ {},
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, sl28vpd_of_match_table);
|
||||
+
|
||||
+struct nvmem_layout sl28vpd_layout = {
|
||||
+ .name = "sl28-vpd",
|
||||
+ .of_match_table = sl28vpd_of_match_table,
|
||||
+ .add_cells = sl28vpd_add_cells,
|
||||
+};
|
||||
+
|
||||
+static int __init sl28vpd_init(void)
|
||||
+{
|
||||
+ return nvmem_layout_register(&sl28vpd_layout);
|
||||
+}
|
||||
+
|
||||
+static void __exit sl28vpd_exit(void)
|
||||
+{
|
||||
+ nvmem_layout_unregister(&sl28vpd_layout);
|
||||
+}
|
||||
+
|
||||
+module_init(sl28vpd_init);
|
||||
+module_exit(sl28vpd_exit);
|
||||
+
|
||||
+MODULE_LICENSE("GPL");
|
||||
+MODULE_AUTHOR("Michael Walle <michael@walle.cc>");
|
||||
+MODULE_DESCRIPTION("NVMEM layout driver for the VPD of Kontron sl28 boards");
|
|
@ -0,0 +1,306 @@
|
|||
From d3c0d12f6474216bf386101e2449cc73e5c5b61d Mon Sep 17 00:00:00 2001
|
||||
From: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:31 +0100
|
||||
Subject: [PATCH] nvmem: layouts: onie-tlv: Add new layout driver
|
||||
|
||||
This layout applies on top of any non volatile storage device containing
|
||||
an ONIE table factory flashed. This table follows the tlv
|
||||
(type-length-value) organization described in the link below. We cannot
|
||||
afford using regular parsers because the content of these tables is
|
||||
manufacturer specific and must be dynamically discovered.
|
||||
|
||||
Link: https://opencomputeproject.github.io/onie/design-spec/hw_requirements.html
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-24-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/layouts/Kconfig | 9 ++
|
||||
drivers/nvmem/layouts/Makefile | 1 +
|
||||
drivers/nvmem/layouts/onie-tlv.c | 257 +++++++++++++++++++++++++++++++
|
||||
3 files changed, 267 insertions(+)
|
||||
create mode 100644 drivers/nvmem/layouts/onie-tlv.c
|
||||
|
||||
--- a/drivers/nvmem/layouts/Kconfig
|
||||
+++ b/drivers/nvmem/layouts/Kconfig
|
||||
@@ -11,4 +11,13 @@ config NVMEM_LAYOUT_SL28_VPD
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
+config NVMEM_LAYOUT_ONIE_TLV
|
||||
+ tristate "ONIE tlv support"
|
||||
+ select CRC32
|
||||
+ help
|
||||
+ Say Y here if you want to support the Open Compute Project ONIE
|
||||
+ Type-Length-Value standard table.
|
||||
+
|
||||
+ If unsure, say N.
|
||||
+
|
||||
endmenu
|
||||
--- a/drivers/nvmem/layouts/Makefile
|
||||
+++ b/drivers/nvmem/layouts/Makefile
|
||||
@@ -4,3 +4,4 @@
|
||||
#
|
||||
|
||||
obj-$(CONFIG_NVMEM_LAYOUT_SL28_VPD) += sl28vpd.o
|
||||
+obj-$(CONFIG_NVMEM_LAYOUT_ONIE_TLV) += onie-tlv.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/nvmem/layouts/onie-tlv.c
|
||||
@@ -0,0 +1,257 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-only
|
||||
+/*
|
||||
+ * ONIE tlv NVMEM cells provider
|
||||
+ *
|
||||
+ * Copyright (C) 2022 Open Compute Group ONIE
|
||||
+ * Author: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
+ * Based on the nvmem driver written by: Vadym Kochan <vadym.kochan@plvision.eu>
|
||||
+ * Inspired by the first layout written by: Rafał Miłecki <rafal@milecki.pl>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/crc32.h>
|
||||
+#include <linux/etherdevice.h>
|
||||
+#include <linux/nvmem-consumer.h>
|
||||
+#include <linux/nvmem-provider.h>
|
||||
+#include <linux/of.h>
|
||||
+
|
||||
+#define ONIE_TLV_MAX_LEN 2048
|
||||
+#define ONIE_TLV_CRC_FIELD_SZ 6
|
||||
+#define ONIE_TLV_CRC_SZ 4
|
||||
+#define ONIE_TLV_HDR_ID "TlvInfo"
|
||||
+
|
||||
+struct onie_tlv_hdr {
|
||||
+ u8 id[8];
|
||||
+ u8 version;
|
||||
+ __be16 data_len;
|
||||
+} __packed;
|
||||
+
|
||||
+struct onie_tlv {
|
||||
+ u8 type;
|
||||
+ u8 len;
|
||||
+} __packed;
|
||||
+
|
||||
+static const char *onie_tlv_cell_name(u8 type)
|
||||
+{
|
||||
+ switch (type) {
|
||||
+ case 0x21:
|
||||
+ return "product-name";
|
||||
+ case 0x22:
|
||||
+ return "part-number";
|
||||
+ case 0x23:
|
||||
+ return "serial-number";
|
||||
+ case 0x24:
|
||||
+ return "mac-address";
|
||||
+ case 0x25:
|
||||
+ return "manufacture-date";
|
||||
+ case 0x26:
|
||||
+ return "device-version";
|
||||
+ case 0x27:
|
||||
+ return "label-revision";
|
||||
+ case 0x28:
|
||||
+ return "platform-name";
|
||||
+ case 0x29:
|
||||
+ return "onie-version";
|
||||
+ case 0x2A:
|
||||
+ return "num-macs";
|
||||
+ case 0x2B:
|
||||
+ return "manufacturer";
|
||||
+ case 0x2C:
|
||||
+ return "country-code";
|
||||
+ case 0x2D:
|
||||
+ return "vendor";
|
||||
+ case 0x2E:
|
||||
+ return "diag-version";
|
||||
+ case 0x2F:
|
||||
+ return "service-tag";
|
||||
+ case 0xFD:
|
||||
+ return "vendor-extension";
|
||||
+ case 0xFE:
|
||||
+ return "crc32";
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static int onie_tlv_mac_read_cb(void *priv, const char *id, int index,
|
||||
+ unsigned int offset, void *buf,
|
||||
+ size_t bytes)
|
||||
+{
|
||||
+ eth_addr_add(buf, index);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static nvmem_cell_post_process_t onie_tlv_read_cb(u8 type, u8 *buf)
|
||||
+{
|
||||
+ switch (type) {
|
||||
+ case 0x24:
|
||||
+ return &onie_tlv_mac_read_cb;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static int onie_tlv_add_cells(struct device *dev, struct nvmem_device *nvmem,
|
||||
+ size_t data_len, u8 *data)
|
||||
+{
|
||||
+ struct nvmem_cell_info cell = {};
|
||||
+ struct device_node *layout;
|
||||
+ struct onie_tlv tlv;
|
||||
+ unsigned int hdr_len = sizeof(struct onie_tlv_hdr);
|
||||
+ unsigned int offset = 0;
|
||||
+ int ret;
|
||||
+
|
||||
+ layout = of_nvmem_layout_get_container(nvmem);
|
||||
+ if (!layout)
|
||||
+ return -ENOENT;
|
||||
+
|
||||
+ while (offset < data_len) {
|
||||
+ memcpy(&tlv, data + offset, sizeof(tlv));
|
||||
+ if (offset + tlv.len >= data_len) {
|
||||
+ dev_err(dev, "Out of bounds field (0x%x bytes at 0x%x)\n",
|
||||
+ tlv.len, hdr_len + offset);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ cell.name = onie_tlv_cell_name(tlv.type);
|
||||
+ if (!cell.name)
|
||||
+ continue;
|
||||
+
|
||||
+ cell.offset = hdr_len + offset + sizeof(tlv.type) + sizeof(tlv.len);
|
||||
+ cell.bytes = tlv.len;
|
||||
+ cell.np = of_get_child_by_name(layout, cell.name);
|
||||
+ cell.read_post_process = onie_tlv_read_cb(tlv.type, data + offset + sizeof(tlv));
|
||||
+
|
||||
+ ret = nvmem_add_one_cell(nvmem, &cell);
|
||||
+ if (ret) {
|
||||
+ of_node_put(layout);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ offset += sizeof(tlv) + tlv.len;
|
||||
+ }
|
||||
+
|
||||
+ of_node_put(layout);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static bool onie_tlv_hdr_is_valid(struct device *dev, struct onie_tlv_hdr *hdr)
|
||||
+{
|
||||
+ if (memcmp(hdr->id, ONIE_TLV_HDR_ID, sizeof(hdr->id))) {
|
||||
+ dev_err(dev, "Invalid header\n");
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (hdr->version != 0x1) {
|
||||
+ dev_err(dev, "Invalid version number\n");
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static bool onie_tlv_crc_is_valid(struct device *dev, size_t table_len, u8 *table)
|
||||
+{
|
||||
+ struct onie_tlv crc_hdr;
|
||||
+ u32 read_crc, calc_crc;
|
||||
+ __be32 crc_be;
|
||||
+
|
||||
+ memcpy(&crc_hdr, table + table_len - ONIE_TLV_CRC_FIELD_SZ, sizeof(crc_hdr));
|
||||
+ if (crc_hdr.type != 0xfe || crc_hdr.len != ONIE_TLV_CRC_SZ) {
|
||||
+ dev_err(dev, "Invalid CRC field\n");
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ /* The table contains a JAMCRC, which is XOR'ed compared to the original
|
||||
+ * CRC32 implementation as known in the Ethernet world.
|
||||
+ */
|
||||
+ memcpy(&crc_be, table + table_len - ONIE_TLV_CRC_SZ, ONIE_TLV_CRC_SZ);
|
||||
+ read_crc = be32_to_cpu(crc_be);
|
||||
+ calc_crc = crc32(~0, table, table_len - ONIE_TLV_CRC_SZ) ^ 0xFFFFFFFF;
|
||||
+ if (read_crc != calc_crc) {
|
||||
+ dev_err(dev, "Invalid CRC read: 0x%08x, expected: 0x%08x\n",
|
||||
+ read_crc, calc_crc);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static int onie_tlv_parse_table(struct device *dev, struct nvmem_device *nvmem,
|
||||
+ struct nvmem_layout *layout)
|
||||
+{
|
||||
+ struct onie_tlv_hdr hdr;
|
||||
+ size_t table_len, data_len, hdr_len;
|
||||
+ u8 *table, *data;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = nvmem_device_read(nvmem, 0, sizeof(hdr), &hdr);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ if (!onie_tlv_hdr_is_valid(dev, &hdr)) {
|
||||
+ dev_err(dev, "Invalid ONIE TLV header\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ hdr_len = sizeof(hdr.id) + sizeof(hdr.version) + sizeof(hdr.data_len);
|
||||
+ data_len = be16_to_cpu(hdr.data_len);
|
||||
+ table_len = hdr_len + data_len;
|
||||
+ if (table_len > ONIE_TLV_MAX_LEN) {
|
||||
+ dev_err(dev, "Invalid ONIE TLV data length\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ table = devm_kmalloc(dev, table_len, GFP_KERNEL);
|
||||
+ if (!table)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ ret = nvmem_device_read(nvmem, 0, table_len, table);
|
||||
+ if (ret != table_len)
|
||||
+ return ret;
|
||||
+
|
||||
+ if (!onie_tlv_crc_is_valid(dev, table_len, table))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ data = table + hdr_len;
|
||||
+ ret = onie_tlv_add_cells(dev, nvmem, data_len, data);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id onie_tlv_of_match_table[] = {
|
||||
+ { .compatible = "onie,tlv-layout", },
|
||||
+ {},
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, onie_tlv_of_match_table);
|
||||
+
|
||||
+static struct nvmem_layout onie_tlv_layout = {
|
||||
+ .name = "ONIE tlv layout",
|
||||
+ .of_match_table = onie_tlv_of_match_table,
|
||||
+ .add_cells = onie_tlv_parse_table,
|
||||
+};
|
||||
+
|
||||
+static int __init onie_tlv_init(void)
|
||||
+{
|
||||
+ return nvmem_layout_register(&onie_tlv_layout);
|
||||
+}
|
||||
+
|
||||
+static void __exit onie_tlv_exit(void)
|
||||
+{
|
||||
+ nvmem_layout_unregister(&onie_tlv_layout);
|
||||
+}
|
||||
+
|
||||
+module_init(onie_tlv_init);
|
||||
+module_exit(onie_tlv_exit);
|
||||
+
|
||||
+MODULE_LICENSE("GPL");
|
||||
+MODULE_AUTHOR("Miquel Raynal <miquel.raynal@bootlin.com>");
|
||||
+MODULE_DESCRIPTION("NVMEM layout driver for Onie TLV table parsing");
|
||||
+MODULE_ALIAS("NVMEM layout driver for Onie TLV table parsing");
|
|
@ -0,0 +1,32 @@
|
|||
From a4fb434ef96ace5af758ca2c52c3a3f8f3abc87c Mon Sep 17 00:00:00 2001
|
||||
From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
Date: Tue, 4 Apr 2023 18:21:34 +0100
|
||||
Subject: [PATCH] nvmem: stm32-romem: mark OF related data as maybe unused
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The driver can be compile tested with !CONFIG_OF making certain data
|
||||
unused:
|
||||
|
||||
drivers/nvmem/stm32-romem.c:271:34: error: ‘stm32_romem_of_match’ defined but not used [-Werror=unused-const-variable=]
|
||||
|
||||
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-27-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/stm32-romem.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/nvmem/stm32-romem.c
|
||||
+++ b/drivers/nvmem/stm32-romem.c
|
||||
@@ -268,7 +268,7 @@ static const struct stm32_romem_cfg stm3
|
||||
.ta = true,
|
||||
};
|
||||
|
||||
-static const struct of_device_id stm32_romem_of_match[] = {
|
||||
+static const struct of_device_id stm32_romem_of_match[] __maybe_unused = {
|
||||
{ .compatible = "st,stm32f4-otp", }, {
|
||||
.compatible = "st,stm32mp15-bsec",
|
||||
.data = (void *)&stm32mp15_bsec_cfg,
|
|
@ -0,0 +1,120 @@
|
|||
From de6e05097f7db066afb0ad4c88b730949f7b7749 Mon Sep 17 00:00:00 2001
|
||||
From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:35 +0100
|
||||
Subject: [PATCH] nvmem: mtk-efuse: Support postprocessing for GPU speed
|
||||
binning data
|
||||
|
||||
On some MediaTek SoCs GPU speed binning data is available for read
|
||||
in the SoC's eFuse array but it has a format that is incompatible
|
||||
with what the OPP API expects, as we read a number from 0 to 7 but
|
||||
opp-supported-hw is expecting a bitmask to enable an OPP entry:
|
||||
being what we read limited to 0-7, it's straightforward to simply
|
||||
convert the value to BIT(value) as a post-processing action.
|
||||
|
||||
So, introduce post-processing support and enable it by evaluating
|
||||
the newly introduced platform data's `uses_post_processing` member,
|
||||
currently enabled only for MT8186.
|
||||
|
||||
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-28-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/mtk-efuse.c | 53 +++++++++++++++++++++++++++++++++++++--
|
||||
1 file changed, 51 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/nvmem/mtk-efuse.c
|
||||
+++ b/drivers/nvmem/mtk-efuse.c
|
||||
@@ -10,6 +10,11 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/nvmem-provider.h>
|
||||
#include <linux/platform_device.h>
|
||||
+#include <linux/property.h>
|
||||
+
|
||||
+struct mtk_efuse_pdata {
|
||||
+ bool uses_post_processing;
|
||||
+};
|
||||
|
||||
struct mtk_efuse_priv {
|
||||
void __iomem *base;
|
||||
@@ -29,6 +34,37 @@ static int mtk_reg_read(void *context,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int mtk_efuse_gpu_speedbin_pp(void *context, const char *id, int index,
|
||||
+ unsigned int offset, void *data, size_t bytes)
|
||||
+{
|
||||
+ u8 *val = data;
|
||||
+
|
||||
+ if (val[0] < 8)
|
||||
+ val[0] = BIT(val[0]);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void mtk_efuse_fixup_cell_info(struct nvmem_device *nvmem,
|
||||
+ struct nvmem_layout *layout,
|
||||
+ struct nvmem_cell_info *cell)
|
||||
+{
|
||||
+ size_t sz = strlen(cell->name);
|
||||
+
|
||||
+ /*
|
||||
+ * On some SoCs, the GPU speedbin is not read as bitmask but as
|
||||
+ * a number with range [0-7] (max 3 bits): post process to use
|
||||
+ * it in OPP tables to describe supported-hw.
|
||||
+ */
|
||||
+ if (cell->nbits <= 3 &&
|
||||
+ strncmp(cell->name, "gpu-speedbin", min(sz, strlen("gpu-speedbin"))) == 0)
|
||||
+ cell->read_post_process = mtk_efuse_gpu_speedbin_pp;
|
||||
+}
|
||||
+
|
||||
+static struct nvmem_layout mtk_efuse_layout = {
|
||||
+ .fixup_cell_info = mtk_efuse_fixup_cell_info,
|
||||
+};
|
||||
+
|
||||
static int mtk_efuse_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
@@ -36,6 +72,7 @@ static int mtk_efuse_probe(struct platfo
|
||||
struct nvmem_device *nvmem;
|
||||
struct nvmem_config econfig = {};
|
||||
struct mtk_efuse_priv *priv;
|
||||
+ const struct mtk_efuse_pdata *pdata;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
@@ -45,20 +82,32 @@ static int mtk_efuse_probe(struct platfo
|
||||
if (IS_ERR(priv->base))
|
||||
return PTR_ERR(priv->base);
|
||||
|
||||
+ pdata = device_get_match_data(dev);
|
||||
econfig.stride = 1;
|
||||
econfig.word_size = 1;
|
||||
econfig.reg_read = mtk_reg_read;
|
||||
econfig.size = resource_size(res);
|
||||
econfig.priv = priv;
|
||||
econfig.dev = dev;
|
||||
+ if (pdata->uses_post_processing)
|
||||
+ econfig.layout = &mtk_efuse_layout;
|
||||
nvmem = devm_nvmem_register(dev, &econfig);
|
||||
|
||||
return PTR_ERR_OR_ZERO(nvmem);
|
||||
}
|
||||
|
||||
+static const struct mtk_efuse_pdata mtk_mt8186_efuse_pdata = {
|
||||
+ .uses_post_processing = true,
|
||||
+};
|
||||
+
|
||||
+static const struct mtk_efuse_pdata mtk_efuse_pdata = {
|
||||
+ .uses_post_processing = false,
|
||||
+};
|
||||
+
|
||||
static const struct of_device_id mtk_efuse_of_match[] = {
|
||||
- { .compatible = "mediatek,mt8173-efuse",},
|
||||
- { .compatible = "mediatek,efuse",},
|
||||
+ { .compatible = "mediatek,mt8173-efuse", .data = &mtk_efuse_pdata },
|
||||
+ { .compatible = "mediatek,mt8186-efuse", .data = &mtk_mt8186_efuse_pdata },
|
||||
+ { .compatible = "mediatek,efuse", .data = &mtk_efuse_pdata },
|
||||
{/* sentinel */},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mtk_efuse_of_match);
|
|
@ -0,0 +1,39 @@
|
|||
From 1dc552fa33cf98af3e784dbc0500da93cae3b24a Mon Sep 17 00:00:00 2001
|
||||
From: Yang Li <yang.lee@linux.alibaba.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:38 +0100
|
||||
Subject: [PATCH] nvmem: bcm-ocotp: Use devm_platform_ioremap_resource()
|
||||
|
||||
According to commit 7945f929f1a7 ("drivers: provide
|
||||
devm_platform_ioremap_resource()"), convert platform_get_resource(),
|
||||
devm_ioremap_resource() to a single call to use
|
||||
devm_platform_ioremap_resource(), as this is exactly what this function
|
||||
does.
|
||||
|
||||
Signed-off-by: Yang Li <yang.lee@linux.alibaba.com>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-31-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/bcm-ocotp.c | 4 +---
|
||||
1 file changed, 1 insertion(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/nvmem/bcm-ocotp.c
|
||||
+++ b/drivers/nvmem/bcm-ocotp.c
|
||||
@@ -254,7 +254,6 @@ MODULE_DEVICE_TABLE(acpi, bcm_otpc_acpi_
|
||||
static int bcm_otpc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
- struct resource *res;
|
||||
struct otpc_priv *priv;
|
||||
struct nvmem_device *nvmem;
|
||||
int err;
|
||||
@@ -269,8 +268,7 @@ static int bcm_otpc_probe(struct platfor
|
||||
return -ENODEV;
|
||||
|
||||
/* Get OTP base address register. */
|
||||
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
- priv->base = devm_ioremap_resource(dev, res);
|
||||
+ priv->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(priv->base)) {
|
||||
dev_err(dev, "unable to map I/O memory\n");
|
||||
return PTR_ERR(priv->base);
|
|
@ -0,0 +1,39 @@
|
|||
From 649409990d2e93fac657be7c6960c28a2c601d65 Mon Sep 17 00:00:00 2001
|
||||
From: Yang Li <yang.lee@linux.alibaba.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:39 +0100
|
||||
Subject: [PATCH] nvmem: nintendo-otp: Use devm_platform_ioremap_resource()
|
||||
|
||||
According to commit 7945f929f1a7 ("drivers: provide
|
||||
devm_platform_ioremap_resource()"), convert platform_get_resource(),
|
||||
devm_ioremap_resource() to a single call to use
|
||||
devm_platform_ioremap_resource(), as this is exactly what this function
|
||||
does.
|
||||
|
||||
Signed-off-by: Yang Li <yang.lee@linux.alibaba.com>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-32-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/nintendo-otp.c | 4 +---
|
||||
1 file changed, 1 insertion(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/nvmem/nintendo-otp.c
|
||||
+++ b/drivers/nvmem/nintendo-otp.c
|
||||
@@ -76,7 +76,6 @@ static int nintendo_otp_probe(struct pla
|
||||
struct device *dev = &pdev->dev;
|
||||
const struct of_device_id *of_id =
|
||||
of_match_device(nintendo_otp_of_table, dev);
|
||||
- struct resource *res;
|
||||
struct nvmem_device *nvmem;
|
||||
struct nintendo_otp_priv *priv;
|
||||
|
||||
@@ -92,8 +91,7 @@ static int nintendo_otp_probe(struct pla
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
- priv->regs = devm_ioremap_resource(dev, res);
|
||||
+ priv->regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(priv->regs))
|
||||
return PTR_ERR(priv->regs);
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
From c2367aa60d5e34d48582362c6de34b4131d92be7 Mon Sep 17 00:00:00 2001
|
||||
From: Yang Li <yang.lee@linux.alibaba.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:40 +0100
|
||||
Subject: [PATCH] nvmem: vf610-ocotp: Use
|
||||
devm_platform_get_and_ioremap_resource()
|
||||
|
||||
According to commit 890cc39a8799 ("drivers: provide
|
||||
devm_platform_get_and_ioremap_resource()"), convert
|
||||
platform_get_resource(), devm_ioremap_resource() to a single
|
||||
call to devm_platform_get_and_ioremap_resource(), as this is exactly
|
||||
what this function does.
|
||||
|
||||
Signed-off-by: Yang Li <yang.lee@linux.alibaba.com>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-33-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/vf610-ocotp.c | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/nvmem/vf610-ocotp.c
|
||||
+++ b/drivers/nvmem/vf610-ocotp.c
|
||||
@@ -219,8 +219,7 @@ static int vf610_ocotp_probe(struct plat
|
||||
if (!ocotp_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
- ocotp_dev->base = devm_ioremap_resource(dev, res);
|
||||
+ ocotp_dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
|
||||
if (IS_ERR(ocotp_dev->base))
|
||||
return PTR_ERR(ocotp_dev->base);
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
From 55d4980ce55b6bb4be66877de4dbec513911b988 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||||
Date: Tue, 4 Apr 2023 18:21:42 +0100
|
||||
Subject: [PATCH] nvmem: core: support specifying both: cell raw data & post
|
||||
read lengths
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Callback .read_post_process() is designed to modify raw cell content
|
||||
before providing it to the consumer. So far we were dealing with
|
||||
modifications that didn't affect cell size (length). In some cases
|
||||
however cell content needs to be reformatted and resized.
|
||||
|
||||
It's required e.g. to provide properly formatted MAC address in case
|
||||
it's stored in a non-binary format (e.g. using ASCII).
|
||||
|
||||
There were few discussions how to optimally handle that. Following
|
||||
possible solutions were considered:
|
||||
1. Allow .read_post_process() to realloc (resize) content buffer
|
||||
2. Allow .read_post_process() to adjust (decrease) just buffer length
|
||||
3. Register NVMEM cells using post-read sizes
|
||||
|
||||
The preferred solution was the last one. The problem is that simply
|
||||
adjusting "bytes" in NVMEM providers would result in core code NOT
|
||||
passing whole raw data to .read_post_process() callbacks. It means
|
||||
callback functions couldn't do their job without somehow manually
|
||||
reading original cell content on their own.
|
||||
|
||||
This patch deals with that by registering NVMEM cells with both lengths:
|
||||
raw content one and post read one. It allows:
|
||||
1. Core code to read whole raw cell content
|
||||
2. Callbacks to return content they want
|
||||
|
||||
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-35-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/core.c | 11 +++++++----
|
||||
include/linux/nvmem-provider.h | 2 ++
|
||||
2 files changed, 9 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/nvmem/core.c
|
||||
+++ b/drivers/nvmem/core.c
|
||||
@@ -50,6 +50,7 @@ struct nvmem_device {
|
||||
struct nvmem_cell_entry {
|
||||
const char *name;
|
||||
int offset;
|
||||
+ size_t raw_len;
|
||||
int bytes;
|
||||
int bit_offset;
|
||||
int nbits;
|
||||
@@ -469,6 +470,7 @@ static int nvmem_cell_info_to_nvmem_cell
|
||||
{
|
||||
cell->nvmem = nvmem;
|
||||
cell->offset = info->offset;
|
||||
+ cell->raw_len = info->raw_len ?: info->bytes;
|
||||
cell->bytes = info->bytes;
|
||||
cell->name = info->name;
|
||||
cell->read_post_process = info->read_post_process;
|
||||
@@ -1560,7 +1562,7 @@ static int __nvmem_cell_read(struct nvme
|
||||
{
|
||||
int rc;
|
||||
|
||||
- rc = nvmem_reg_read(nvmem, cell->offset, buf, cell->bytes);
|
||||
+ rc = nvmem_reg_read(nvmem, cell->offset, buf, cell->raw_len);
|
||||
|
||||
if (rc)
|
||||
return rc;
|
||||
@@ -1571,7 +1573,7 @@ static int __nvmem_cell_read(struct nvme
|
||||
|
||||
if (cell->read_post_process) {
|
||||
rc = cell->read_post_process(cell->priv, id, index,
|
||||
- cell->offset, buf, cell->bytes);
|
||||
+ cell->offset, buf, cell->raw_len);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
@@ -1594,14 +1596,15 @@ static int __nvmem_cell_read(struct nvme
|
||||
*/
|
||||
void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len)
|
||||
{
|
||||
- struct nvmem_device *nvmem = cell->entry->nvmem;
|
||||
+ struct nvmem_cell_entry *entry = cell->entry;
|
||||
+ struct nvmem_device *nvmem = entry->nvmem;
|
||||
u8 *buf;
|
||||
int rc;
|
||||
|
||||
if (!nvmem)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
- buf = kzalloc(cell->entry->bytes, GFP_KERNEL);
|
||||
+ buf = kzalloc(max_t(size_t, entry->raw_len, entry->bytes), GFP_KERNEL);
|
||||
if (!buf)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
--- a/include/linux/nvmem-provider.h
|
||||
+++ b/include/linux/nvmem-provider.h
|
||||
@@ -51,6 +51,7 @@ struct nvmem_keepout {
|
||||
* struct nvmem_cell_info - NVMEM cell description
|
||||
* @name: Name.
|
||||
* @offset: Offset within the NVMEM device.
|
||||
+ * @raw_len: Length of raw data (without post processing).
|
||||
* @bytes: Length of the cell.
|
||||
* @bit_offset: Bit offset if cell is smaller than a byte.
|
||||
* @nbits: Number of bits.
|
||||
@@ -62,6 +63,7 @@ struct nvmem_keepout {
|
||||
struct nvmem_cell_info {
|
||||
const char *name;
|
||||
unsigned int offset;
|
||||
+ size_t raw_len;
|
||||
unsigned int bytes;
|
||||
unsigned int bit_offset;
|
||||
unsigned int nbits;
|
|
@ -0,0 +1,81 @@
|
|||
From c49f1a8af6bcf6d18576bca898f8083ca4b129e1 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||||
Date: Tue, 4 Apr 2023 18:21:43 +0100
|
||||
Subject: [PATCH] nvmem: u-boot-env: post-process "ethaddr" env variable
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
U-Boot environment variables are stored in ASCII format so "ethaddr"
|
||||
requires parsing into binary to make it work with Ethernet interfaces.
|
||||
|
||||
This includes support for indexes to support #nvmem-cell-cells = <1>.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-36-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/Kconfig | 1 +
|
||||
drivers/nvmem/u-boot-env.c | 26 ++++++++++++++++++++++++++
|
||||
2 files changed, 27 insertions(+)
|
||||
|
||||
--- a/drivers/nvmem/Kconfig
|
||||
+++ b/drivers/nvmem/Kconfig
|
||||
@@ -340,6 +340,7 @@ config NVMEM_U_BOOT_ENV
|
||||
tristate "U-Boot environment variables support"
|
||||
depends on OF && MTD
|
||||
select CRC32
|
||||
+ select GENERIC_NET_UTILS
|
||||
help
|
||||
U-Boot stores its setup as environment variables. This driver adds
|
||||
support for verifying & exporting such data. It also exposes variables
|
||||
--- a/drivers/nvmem/u-boot-env.c
|
||||
+++ b/drivers/nvmem/u-boot-env.c
|
||||
@@ -4,6 +4,8 @@
|
||||
*/
|
||||
|
||||
#include <linux/crc32.h>
|
||||
+#include <linux/etherdevice.h>
|
||||
+#include <linux/if_ether.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
@@ -70,6 +72,25 @@ static int u_boot_env_read(void *context
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int u_boot_env_read_post_process_ethaddr(void *context, const char *id, int index,
|
||||
+ unsigned int offset, void *buf, size_t bytes)
|
||||
+{
|
||||
+ u8 mac[ETH_ALEN];
|
||||
+
|
||||
+ if (bytes != 3 * ETH_ALEN - 1)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (!mac_pton(buf, mac))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (index)
|
||||
+ eth_addr_add(mac, index);
|
||||
+
|
||||
+ ether_addr_copy(buf, mac);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int u_boot_env_add_cells(struct u_boot_env *priv, uint8_t *buf,
|
||||
size_t data_offset, size_t data_len)
|
||||
{
|
||||
@@ -101,6 +122,11 @@ static int u_boot_env_add_cells(struct u
|
||||
priv->cells[idx].offset = data_offset + value - data;
|
||||
priv->cells[idx].bytes = strlen(value);
|
||||
priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name);
|
||||
+ if (!strcmp(var, "ethaddr")) {
|
||||
+ priv->cells[idx].raw_len = strlen(value);
|
||||
+ priv->cells[idx].bytes = ETH_ALEN;
|
||||
+ priv->cells[idx].read_post_process = u_boot_env_read_post_process_ethaddr;
|
||||
+ }
|
||||
}
|
||||
|
||||
if (WARN_ON(idx != priv->ncells))
|
|
@ -0,0 +1,42 @@
|
|||
From 814c978f02db17f16e6aa2efa2a929372f06da09 Mon Sep 17 00:00:00 2001
|
||||
From: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:44 +0100
|
||||
Subject: [PATCH] nvmem: Add macro to register nvmem layout drivers
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Provide a module_nvmem_layout_driver() macro at the end of the
|
||||
nvmem-provider.h header to reduce the boilerplate when registering nvmem
|
||||
layout drivers.
|
||||
|
||||
Suggested-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Acked-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-37-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
include/linux/nvmem-provider.h | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
--- a/include/linux/nvmem-provider.h
|
||||
+++ b/include/linux/nvmem-provider.h
|
||||
@@ -9,6 +9,7 @@
|
||||
#ifndef _LINUX_NVMEM_PROVIDER_H
|
||||
#define _LINUX_NVMEM_PROVIDER_H
|
||||
|
||||
+#include <linux/device/driver.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
@@ -242,4 +243,9 @@ nvmem_layout_get_match_data(struct nvmem
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NVMEM */
|
||||
+
|
||||
+#define module_nvmem_layout_driver(__layout_driver) \
|
||||
+ module_driver(__layout_driver, nvmem_layout_register, \
|
||||
+ nvmem_layout_unregister)
|
||||
+
|
||||
#endif /* ifndef _LINUX_NVMEM_PROVIDER_H */
|
|
@ -0,0 +1,39 @@
|
|||
From 0abdf99fe0c86252ba274703425f8d543d7e7f0d Mon Sep 17 00:00:00 2001
|
||||
From: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:45 +0100
|
||||
Subject: [PATCH] nvmem: layouts: sl28vpd: Use module_nvmem_layout_driver()
|
||||
|
||||
Stop open-coding the module init/exit functions. Use the
|
||||
module_nvmem_layout_driver() instead.
|
||||
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-38-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/layouts/sl28vpd.c | 14 +-------------
|
||||
1 file changed, 1 insertion(+), 13 deletions(-)
|
||||
|
||||
--- a/drivers/nvmem/layouts/sl28vpd.c
|
||||
+++ b/drivers/nvmem/layouts/sl28vpd.c
|
||||
@@ -146,19 +146,7 @@ struct nvmem_layout sl28vpd_layout = {
|
||||
.of_match_table = sl28vpd_of_match_table,
|
||||
.add_cells = sl28vpd_add_cells,
|
||||
};
|
||||
-
|
||||
-static int __init sl28vpd_init(void)
|
||||
-{
|
||||
- return nvmem_layout_register(&sl28vpd_layout);
|
||||
-}
|
||||
-
|
||||
-static void __exit sl28vpd_exit(void)
|
||||
-{
|
||||
- nvmem_layout_unregister(&sl28vpd_layout);
|
||||
-}
|
||||
-
|
||||
-module_init(sl28vpd_init);
|
||||
-module_exit(sl28vpd_exit);
|
||||
+module_nvmem_layout_driver(sl28vpd_layout);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Michael Walle <michael@walle.cc>");
|
|
@ -0,0 +1,39 @@
|
|||
From d119eb38faab61125aaa4f63c74eef61585cf34c Mon Sep 17 00:00:00 2001
|
||||
From: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:46 +0100
|
||||
Subject: [PATCH] nvmem: layouts: onie-tlv: Use module_nvmem_layout_driver()
|
||||
|
||||
Stop open-coding the module init/exit functions. Use the
|
||||
module_nvmem_layout_driver() instead.
|
||||
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-39-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/layouts/onie-tlv.c | 14 +-------------
|
||||
1 file changed, 1 insertion(+), 13 deletions(-)
|
||||
|
||||
--- a/drivers/nvmem/layouts/onie-tlv.c
|
||||
+++ b/drivers/nvmem/layouts/onie-tlv.c
|
||||
@@ -237,19 +237,7 @@ static struct nvmem_layout onie_tlv_layo
|
||||
.of_match_table = onie_tlv_of_match_table,
|
||||
.add_cells = onie_tlv_parse_table,
|
||||
};
|
||||
-
|
||||
-static int __init onie_tlv_init(void)
|
||||
-{
|
||||
- return nvmem_layout_register(&onie_tlv_layout);
|
||||
-}
|
||||
-
|
||||
-static void __exit onie_tlv_exit(void)
|
||||
-{
|
||||
- nvmem_layout_unregister(&onie_tlv_layout);
|
||||
-}
|
||||
-
|
||||
-module_init(onie_tlv_init);
|
||||
-module_exit(onie_tlv_exit);
|
||||
+module_nvmem_layout_driver(onie_tlv_layout);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Miquel Raynal <miquel.raynal@bootlin.com>");
|
|
@ -0,0 +1,24 @@
|
|||
From 6b13e4b6a9a45028ac730e550380077df1845912 Mon Sep 17 00:00:00 2001
|
||||
From: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:47 +0100
|
||||
Subject: [PATCH] nvmem: layouts: onie-tlv: Drop wrong module alias
|
||||
|
||||
The MODULE_ALIAS macro is misused here as it carries the
|
||||
description. There is currently no relevant alias to provide so let's
|
||||
just drop it.
|
||||
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-40-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/layouts/onie-tlv.c | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
--- a/drivers/nvmem/layouts/onie-tlv.c
|
||||
+++ b/drivers/nvmem/layouts/onie-tlv.c
|
||||
@@ -242,4 +242,3 @@ module_nvmem_layout_driver(onie_tlv_layo
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Miquel Raynal <miquel.raynal@bootlin.com>");
|
||||
MODULE_DESCRIPTION("NVMEM layout driver for Onie TLV table parsing");
|
||||
-MODULE_ALIAS("NVMEM layout driver for Onie TLV table parsing");
|
|
@ -0,0 +1,31 @@
|
|||
From a8642cd11635a35a5f1dc31857887900d6610778 Mon Sep 17 00:00:00 2001
|
||||
From: Tom Rix <trix@redhat.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:48 +0100
|
||||
Subject: [PATCH] nvmem: layouts: sl28vpd: set varaiable sl28vpd_layout
|
||||
storage-class-specifier to static
|
||||
|
||||
smatch reports
|
||||
drivers/nvmem/layouts/sl28vpd.c:144:21: warning: symbol
|
||||
'sl28vpd_layout' was not declared. Should it be static?
|
||||
|
||||
This variable is only used in one file so it should be static.
|
||||
|
||||
Signed-off-by: Tom Rix <trix@redhat.com>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-41-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/nvmem/layouts/sl28vpd.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/nvmem/layouts/sl28vpd.c
|
||||
+++ b/drivers/nvmem/layouts/sl28vpd.c
|
||||
@@ -141,7 +141,7 @@ static const struct of_device_id sl28vpd
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sl28vpd_of_match_table);
|
||||
|
||||
-struct nvmem_layout sl28vpd_layout = {
|
||||
+static struct nvmem_layout sl28vpd_layout = {
|
||||
.name = "sl28-vpd",
|
||||
.of_match_table = sl28vpd_of_match_table,
|
||||
.add_cells = sl28vpd_add_cells,
|
|
@ -0,0 +1,70 @@
|
|||
From b19a4266c52de78496fe40f0b37580a3b762e67d Mon Sep 17 00:00:00 2001
|
||||
From: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:09 +0100
|
||||
Subject: [PATCH] of: Fix modalias string generation
|
||||
|
||||
The helper generating an OF based modalias (of_device_get_modalias())
|
||||
works fine, but due to the use of snprintf() internally it needs a
|
||||
buffer one byte longer than what should be needed just for the entire
|
||||
string (excluding the '\0'). Most users of this helper are sysfs hooks
|
||||
providing the modalias string to users. They all provide a PAGE_SIZE
|
||||
buffer which is way above the number of bytes required to fit the
|
||||
modalias string and hence do not suffer from this issue.
|
||||
|
||||
There is another user though, of_device_request_module(), which is only
|
||||
called by drivers/usb/common/ulpi.c. This request module function is
|
||||
faulty, but maybe because in most cases there is an alternative, ULPI
|
||||
driver users have not noticed it.
|
||||
|
||||
In this function, of_device_get_modalias() is called twice. The first
|
||||
time without buffer just to get the number of bytes required by the
|
||||
modalias string (excluding the null byte), and a second time, after
|
||||
buffer allocation, to fill the buffer. The allocation asks for an
|
||||
additional byte, in order to store the trailing '\0'. However, the
|
||||
buffer *length* provided to of_device_get_modalias() excludes this extra
|
||||
byte. The internal use of snprintf() with a length that is exactly the
|
||||
number of bytes to be written has the effect of using the last available
|
||||
byte to store a '\0', which then smashes the last character of the
|
||||
modalias string.
|
||||
|
||||
Provide the actual size of the buffer to of_device_get_modalias() to fix
|
||||
this issue.
|
||||
|
||||
Note: the "str[size - 1] = '\0';" line is not really needed as snprintf
|
||||
will anyway end the string with a null byte, but there is a possibility
|
||||
that this function might be called on a struct device_node without
|
||||
compatible, in this case snprintf() would not be executed. So we keep it
|
||||
just to avoid possible unbounded strings.
|
||||
|
||||
Cc: Stephen Boyd <sboyd@kernel.org>
|
||||
Cc: Peter Chen <peter.chen@kernel.org>
|
||||
Fixes: 9c829c097f2f ("of: device: Support loading a module with OF based modalias")
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Reviewed-by: Rob Herring <robh@kernel.org>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-2-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/of/device.c | 7 +++++--
|
||||
1 file changed, 5 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/of/device.c
|
||||
+++ b/drivers/of/device.c
|
||||
@@ -290,12 +290,15 @@ int of_device_request_module(struct devi
|
||||
if (size < 0)
|
||||
return size;
|
||||
|
||||
- str = kmalloc(size + 1, GFP_KERNEL);
|
||||
+ /* Reserve an additional byte for the trailing '\0' */
|
||||
+ size++;
|
||||
+
|
||||
+ str = kmalloc(size, GFP_KERNEL);
|
||||
if (!str)
|
||||
return -ENOMEM;
|
||||
|
||||
of_device_get_modalias(dev, str, size);
|
||||
- str[size] = '\0';
|
||||
+ str[size - 1] = '\0';
|
||||
ret = request_module(str);
|
||||
kfree(str);
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
From 5c3d15e127ebfc0754cd18def7124633b6d46672 Mon Sep 17 00:00:00 2001
|
||||
From: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:15 +0100
|
||||
Subject: [PATCH] of: Update of_device_get_modalias()
|
||||
|
||||
This function only needs a "struct device_node" to work, but for
|
||||
convenience the author (and only user) of this helper did use a "struct
|
||||
device" and put it in device.c.
|
||||
|
||||
Let's convert this helper to take a "struct device node" instead. This
|
||||
change asks for two additional changes: renaming it "of_modalias()"
|
||||
to fit the current naming, and moving it outside of device.c which will
|
||||
be done in a follow-up commit.
|
||||
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Reviewed-by: Rob Herring <robh@kernel.org>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-8-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/of/device.c | 29 +++++++++++++++++------------
|
||||
1 file changed, 17 insertions(+), 12 deletions(-)
|
||||
|
||||
--- a/drivers/of/device.c
|
||||
+++ b/drivers/of/device.c
|
||||
@@ -241,7 +241,7 @@ const void *of_device_get_match_data(con
|
||||
}
|
||||
EXPORT_SYMBOL(of_device_get_match_data);
|
||||
|
||||
-static ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len)
|
||||
+static ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len)
|
||||
{
|
||||
const char *compat;
|
||||
char *c;
|
||||
@@ -249,19 +249,16 @@ static ssize_t of_device_get_modalias(st
|
||||
ssize_t csize;
|
||||
ssize_t tsize;
|
||||
|
||||
- if ((!dev) || (!dev->of_node) || dev->of_node_reused)
|
||||
- return -ENODEV;
|
||||
-
|
||||
/* Name & Type */
|
||||
/* %p eats all alphanum characters, so %c must be used here */
|
||||
- csize = snprintf(str, len, "of:N%pOFn%c%s", dev->of_node, 'T',
|
||||
- of_node_get_device_type(dev->of_node));
|
||||
+ csize = snprintf(str, len, "of:N%pOFn%c%s", np, 'T',
|
||||
+ of_node_get_device_type(np));
|
||||
tsize = csize;
|
||||
len -= csize;
|
||||
if (str)
|
||||
str += csize;
|
||||
|
||||
- of_property_for_each_string(dev->of_node, "compatible", p, compat) {
|
||||
+ of_property_for_each_string(np, "compatible", p, compat) {
|
||||
csize = strlen(compat) + 1;
|
||||
tsize += csize;
|
||||
if (csize > len)
|
||||
@@ -286,7 +283,10 @@ int of_device_request_module(struct devi
|
||||
ssize_t size;
|
||||
int ret;
|
||||
|
||||
- size = of_device_get_modalias(dev, NULL, 0);
|
||||
+ if (!dev || !dev->of_node)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ size = of_modalias(dev->of_node, NULL, 0);
|
||||
if (size < 0)
|
||||
return size;
|
||||
|
||||
@@ -297,7 +297,7 @@ int of_device_request_module(struct devi
|
||||
if (!str)
|
||||
return -ENOMEM;
|
||||
|
||||
- of_device_get_modalias(dev, str, size);
|
||||
+ of_modalias(dev->of_node, str, size);
|
||||
str[size - 1] = '\0';
|
||||
ret = request_module(str);
|
||||
kfree(str);
|
||||
@@ -314,7 +314,12 @@ EXPORT_SYMBOL_GPL(of_device_request_modu
|
||||
*/
|
||||
ssize_t of_device_modalias(struct device *dev, char *str, ssize_t len)
|
||||
{
|
||||
- ssize_t sl = of_device_get_modalias(dev, str, len - 2);
|
||||
+ ssize_t sl;
|
||||
+
|
||||
+ if (!dev || !dev->of_node || dev->of_node_reused)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ sl = of_modalias(dev->of_node, str, len - 2);
|
||||
if (sl < 0)
|
||||
return sl;
|
||||
if (sl > len - 2)
|
||||
@@ -379,8 +384,8 @@ int of_device_uevent_modalias(struct dev
|
||||
if (add_uevent_var(env, "MODALIAS="))
|
||||
return -ENOMEM;
|
||||
|
||||
- sl = of_device_get_modalias(dev, &env->buf[env->buflen-1],
|
||||
- sizeof(env->buf) - env->buflen);
|
||||
+ sl = of_modalias(dev->of_node, &env->buf[env->buflen-1],
|
||||
+ sizeof(env->buf) - env->buflen);
|
||||
if (sl < 0)
|
||||
return sl;
|
||||
if (sl >= (sizeof(env->buf) - env->buflen))
|
|
@ -0,0 +1,173 @@
|
|||
From 673aa1ed1c9b6710bf24e3f0957d85e2f46c77db Mon Sep 17 00:00:00 2001
|
||||
From: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:16 +0100
|
||||
Subject: [PATCH] of: Rename of_modalias_node()
|
||||
|
||||
This helper does not produce a real modalias, but tries to get the
|
||||
"product" compatible part of the "vendor,product" compatibles only. It
|
||||
is far from creating a purely useful modalias string and does not seem
|
||||
to be used like that directly anyway, so let's try to give this helper a
|
||||
more meaningful name before moving there a real modalias helper (already
|
||||
existing under of/device.c).
|
||||
|
||||
Also update the various documentations to refer to the strings as
|
||||
"aliases" rather than "modaliases" which has a real meaning in the Linux
|
||||
kernel.
|
||||
|
||||
There is no functional change.
|
||||
|
||||
Cc: Rafael J. Wysocki <rafael@kernel.org>
|
||||
Cc: Len Brown <lenb@kernel.org>
|
||||
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
|
||||
Cc: Maxime Ripard <mripard@kernel.org>
|
||||
Cc: Thomas Zimmermann <tzimmermann@suse.de>
|
||||
Cc: Sebastian Reichel <sre@kernel.org>
|
||||
Cc: Wolfram Sang <wsa@kernel.org>
|
||||
Cc: Mark Brown <broonie@kernel.org>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Reviewed-by: Rob Herring <robh@kernel.org>
|
||||
Acked-by: Mark Brown <broonie@kernel.org>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Acked-by: Sebastian Reichel <sre@kernel.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-9-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/acpi/bus.c | 7 ++++---
|
||||
drivers/gpu/drm/drm_mipi_dsi.c | 2 +-
|
||||
drivers/hsi/hsi_core.c | 2 +-
|
||||
drivers/i2c/busses/i2c-powermac.c | 2 +-
|
||||
drivers/i2c/i2c-core-of.c | 2 +-
|
||||
drivers/of/base.c | 18 +++++++++++-------
|
||||
drivers/spi/spi.c | 4 ++--
|
||||
include/linux/of.h | 3 ++-
|
||||
8 files changed, 23 insertions(+), 17 deletions(-)
|
||||
|
||||
--- a/drivers/acpi/bus.c
|
||||
+++ b/drivers/acpi/bus.c
|
||||
@@ -785,9 +785,10 @@ static bool acpi_of_modalias(struct acpi
|
||||
* @modalias: Pointer to buffer that modalias value will be copied into
|
||||
* @len: Length of modalias buffer
|
||||
*
|
||||
- * This is a counterpart of of_modalias_node() for struct acpi_device objects.
|
||||
- * If there is a compatible string for @adev, it will be copied to @modalias
|
||||
- * with the vendor prefix stripped; otherwise, @default_id will be used.
|
||||
+ * This is a counterpart of of_alias_from_compatible() for struct acpi_device
|
||||
+ * objects. If there is a compatible string for @adev, it will be copied to
|
||||
+ * @modalias with the vendor prefix stripped; otherwise, @default_id will be
|
||||
+ * used.
|
||||
*/
|
||||
void acpi_set_modalias(struct acpi_device *adev, const char *default_id,
|
||||
char *modalias, size_t len)
|
||||
--- a/drivers/gpu/drm/drm_mipi_dsi.c
|
||||
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
|
||||
@@ -160,7 +160,7 @@ of_mipi_dsi_device_add(struct mipi_dsi_h
|
||||
int ret;
|
||||
u32 reg;
|
||||
|
||||
- if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
|
||||
+ if (of_alias_from_compatible(node, info.type, sizeof(info.type)) < 0) {
|
||||
drm_err(host, "modalias failure on %pOF\n", node);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
--- a/drivers/hsi/hsi_core.c
|
||||
+++ b/drivers/hsi/hsi_core.c
|
||||
@@ -207,7 +207,7 @@ static void hsi_add_client_from_dt(struc
|
||||
if (!cl)
|
||||
return;
|
||||
|
||||
- err = of_modalias_node(client, name, sizeof(name));
|
||||
+ err = of_alias_from_compatible(client, name, sizeof(name));
|
||||
if (err)
|
||||
goto err;
|
||||
|
||||
--- a/drivers/i2c/busses/i2c-powermac.c
|
||||
+++ b/drivers/i2c/busses/i2c-powermac.c
|
||||
@@ -284,7 +284,7 @@ static bool i2c_powermac_get_type(struct
|
||||
*/
|
||||
|
||||
/* First try proper modalias */
|
||||
- if (of_modalias_node(node, tmp, sizeof(tmp)) >= 0) {
|
||||
+ if (of_alias_from_compatible(node, tmp, sizeof(tmp)) >= 0) {
|
||||
snprintf(type, type_size, "MAC,%s", tmp);
|
||||
return true;
|
||||
}
|
||||
--- a/drivers/i2c/i2c-core-of.c
|
||||
+++ b/drivers/i2c/i2c-core-of.c
|
||||
@@ -27,7 +27,7 @@ int of_i2c_get_board_info(struct device
|
||||
|
||||
memset(info, 0, sizeof(*info));
|
||||
|
||||
- if (of_modalias_node(node, info->type, sizeof(info->type)) < 0) {
|
||||
+ if (of_alias_from_compatible(node, info->type, sizeof(info->type)) < 0) {
|
||||
dev_err(dev, "of_i2c: modalias failure on %pOF\n", node);
|
||||
return -EINVAL;
|
||||
}
|
||||
--- a/drivers/of/base.c
|
||||
+++ b/drivers/of/base.c
|
||||
@@ -1159,19 +1159,23 @@ struct device_node *of_find_matching_nod
|
||||
EXPORT_SYMBOL(of_find_matching_node_and_match);
|
||||
|
||||
/**
|
||||
- * of_modalias_node - Lookup appropriate modalias for a device node
|
||||
+ * of_alias_from_compatible - Lookup appropriate alias for a device node
|
||||
+ * depending on compatible
|
||||
* @node: pointer to a device tree node
|
||||
- * @modalias: Pointer to buffer that modalias value will be copied into
|
||||
- * @len: Length of modalias value
|
||||
+ * @alias: Pointer to buffer that alias value will be copied into
|
||||
+ * @len: Length of alias value
|
||||
*
|
||||
* Based on the value of the compatible property, this routine will attempt
|
||||
- * to choose an appropriate modalias value for a particular device tree node.
|
||||
+ * to choose an appropriate alias value for a particular device tree node.
|
||||
* It does this by stripping the manufacturer prefix (as delimited by a ',')
|
||||
* from the first entry in the compatible list property.
|
||||
*
|
||||
+ * Note: The matching on just the "product" side of the compatible is a relic
|
||||
+ * from I2C and SPI. Please do not add any new user.
|
||||
+ *
|
||||
* Return: This routine returns 0 on success, <0 on failure.
|
||||
*/
|
||||
-int of_modalias_node(struct device_node *node, char *modalias, int len)
|
||||
+int of_alias_from_compatible(const struct device_node *node, char *alias, int len)
|
||||
{
|
||||
const char *compatible, *p;
|
||||
int cplen;
|
||||
@@ -1180,10 +1184,10 @@ int of_modalias_node(struct device_node
|
||||
if (!compatible || strlen(compatible) > cplen)
|
||||
return -ENODEV;
|
||||
p = strchr(compatible, ',');
|
||||
- strlcpy(modalias, p ? p + 1 : compatible, len);
|
||||
+ strlcpy(alias, p ? p + 1 : compatible, len);
|
||||
return 0;
|
||||
}
|
||||
-EXPORT_SYMBOL_GPL(of_modalias_node);
|
||||
+EXPORT_SYMBOL_GPL(of_alias_from_compatible);
|
||||
|
||||
/**
|
||||
* of_find_node_by_phandle - Find a node given a phandle
|
||||
--- a/drivers/spi/spi.c
|
||||
+++ b/drivers/spi/spi.c
|
||||
@@ -2128,8 +2128,8 @@ of_register_spi_device(struct spi_contro
|
||||
}
|
||||
|
||||
/* Select device driver */
|
||||
- rc = of_modalias_node(nc, spi->modalias,
|
||||
- sizeof(spi->modalias));
|
||||
+ rc = of_alias_from_compatible(nc, spi->modalias,
|
||||
+ sizeof(spi->modalias));
|
||||
if (rc < 0) {
|
||||
dev_err(&ctlr->dev, "cannot find modalias for %pOF\n", nc);
|
||||
goto err_out;
|
||||
--- a/include/linux/of.h
|
||||
+++ b/include/linux/of.h
|
||||
@@ -361,7 +361,8 @@ extern int of_n_addr_cells(struct device
|
||||
extern int of_n_size_cells(struct device_node *np);
|
||||
extern const struct of_device_id *of_match_node(
|
||||
const struct of_device_id *matches, const struct device_node *node);
|
||||
-extern int of_modalias_node(struct device_node *node, char *modalias, int len);
|
||||
+extern int of_alias_from_compatible(const struct device_node *node, char *alias,
|
||||
+ int len);
|
||||
extern void of_print_phandle_args(const char *msg, const struct of_phandle_args *args);
|
||||
extern int __of_parse_phandle_with_args(const struct device_node *np,
|
||||
const char *list_name, const char *cells_name, int cell_count,
|
|
@ -0,0 +1,160 @@
|
|||
From bd7a7ed774afd1a4174df34227626c95573be517 Mon Sep 17 00:00:00 2001
|
||||
From: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:17 +0100
|
||||
Subject: [PATCH] of: Move of_modalias() to module.c
|
||||
|
||||
Create a specific .c file for OF related module handling.
|
||||
Move of_modalias() inside as a first step.
|
||||
|
||||
The helper is exposed through of.h even though it is only used by core
|
||||
files because the users from device.c will soon be split into an OF-only
|
||||
helper in module.c as well as a device-oriented inline helper in
|
||||
of_device.h. Putting this helper in of_private.h would require to
|
||||
include of_private.h from of_device.h, which is not acceptable.
|
||||
|
||||
Suggested-by: Rob Herring <robh+dt@kernel.org>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Reviewed-by: Rob Herring <robh@kernel.org>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-10-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/of/Makefile | 2 +-
|
||||
drivers/of/device.c | 37 -------------------------------------
|
||||
drivers/of/module.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
|
||||
include/linux/of.h | 9 +++++++++
|
||||
4 files changed, 54 insertions(+), 38 deletions(-)
|
||||
create mode 100644 drivers/of/module.c
|
||||
|
||||
--- a/drivers/of/Makefile
|
||||
+++ b/drivers/of/Makefile
|
||||
@@ -1,5 +1,5 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
-obj-y = base.o device.o platform.o property.o
|
||||
+obj-y = base.o device.o module.o platform.o property.o
|
||||
obj-$(CONFIG_OF_KOBJ) += kobj.o
|
||||
obj-$(CONFIG_OF_DYNAMIC) += dynamic.o
|
||||
obj-$(CONFIG_OF_FLATTREE) += fdt.o
|
||||
--- a/drivers/of/device.c
|
||||
+++ b/drivers/of/device.c
|
||||
@@ -1,5 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
-#include <linux/string.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
@@ -241,42 +240,6 @@ const void *of_device_get_match_data(con
|
||||
}
|
||||
EXPORT_SYMBOL(of_device_get_match_data);
|
||||
|
||||
-static ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len)
|
||||
-{
|
||||
- const char *compat;
|
||||
- char *c;
|
||||
- struct property *p;
|
||||
- ssize_t csize;
|
||||
- ssize_t tsize;
|
||||
-
|
||||
- /* Name & Type */
|
||||
- /* %p eats all alphanum characters, so %c must be used here */
|
||||
- csize = snprintf(str, len, "of:N%pOFn%c%s", np, 'T',
|
||||
- of_node_get_device_type(np));
|
||||
- tsize = csize;
|
||||
- len -= csize;
|
||||
- if (str)
|
||||
- str += csize;
|
||||
-
|
||||
- of_property_for_each_string(np, "compatible", p, compat) {
|
||||
- csize = strlen(compat) + 1;
|
||||
- tsize += csize;
|
||||
- if (csize > len)
|
||||
- continue;
|
||||
-
|
||||
- csize = snprintf(str, len, "C%s", compat);
|
||||
- for (c = str; c; ) {
|
||||
- c = strchr(c, ' ');
|
||||
- if (c)
|
||||
- *c++ = '_';
|
||||
- }
|
||||
- len -= csize;
|
||||
- str += csize;
|
||||
- }
|
||||
-
|
||||
- return tsize;
|
||||
-}
|
||||
-
|
||||
int of_device_request_module(struct device *dev)
|
||||
{
|
||||
char *str;
|
||||
--- /dev/null
|
||||
+++ b/drivers/of/module.c
|
||||
@@ -0,0 +1,44 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/*
|
||||
+ * Linux kernel module helpers.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/string.h>
|
||||
+
|
||||
+ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len)
|
||||
+{
|
||||
+ const char *compat;
|
||||
+ char *c;
|
||||
+ struct property *p;
|
||||
+ ssize_t csize;
|
||||
+ ssize_t tsize;
|
||||
+
|
||||
+ /* Name & Type */
|
||||
+ /* %p eats all alphanum characters, so %c must be used here */
|
||||
+ csize = snprintf(str, len, "of:N%pOFn%c%s", np, 'T',
|
||||
+ of_node_get_device_type(np));
|
||||
+ tsize = csize;
|
||||
+ len -= csize;
|
||||
+ if (str)
|
||||
+ str += csize;
|
||||
+
|
||||
+ of_property_for_each_string(np, "compatible", p, compat) {
|
||||
+ csize = strlen(compat) + 1;
|
||||
+ tsize += csize;
|
||||
+ if (csize > len)
|
||||
+ continue;
|
||||
+
|
||||
+ csize = snprintf(str, len, "C%s", compat);
|
||||
+ for (c = str; c; ) {
|
||||
+ c = strchr(c, ' ');
|
||||
+ if (c)
|
||||
+ *c++ = '_';
|
||||
+ }
|
||||
+ len -= csize;
|
||||
+ str += csize;
|
||||
+ }
|
||||
+
|
||||
+ return tsize;
|
||||
+}
|
||||
--- a/include/linux/of.h
|
||||
+++ b/include/linux/of.h
|
||||
@@ -373,6 +373,9 @@ extern int of_parse_phandle_with_args_ma
|
||||
extern int of_count_phandle_with_args(const struct device_node *np,
|
||||
const char *list_name, const char *cells_name);
|
||||
|
||||
+/* module functions */
|
||||
+extern ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len);
|
||||
+
|
||||
/* phandle iterator functions */
|
||||
extern int of_phandle_iterator_init(struct of_phandle_iterator *it,
|
||||
const struct device_node *np,
|
||||
@@ -885,6 +888,12 @@ static inline int of_count_phandle_with_
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
+static inline ssize_t of_modalias(const struct device_node *np, char *str,
|
||||
+ ssize_t len)
|
||||
+{
|
||||
+ return -ENODEV;
|
||||
+}
|
||||
+
|
||||
static inline int of_phandle_iterator_init(struct of_phandle_iterator *it,
|
||||
const struct device_node *np,
|
||||
const char *list_name,
|
|
@ -0,0 +1,131 @@
|
|||
From e6506f06d5e82765666902ccf9e9162f3e31d518 Mon Sep 17 00:00:00 2001
|
||||
From: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Date: Tue, 4 Apr 2023 18:21:18 +0100
|
||||
Subject: [PATCH] of: Move the request module helper logic to module.c
|
||||
|
||||
Depending on device.c for pure OF handling is considered
|
||||
backwards. Let's extract the content of of_device_request_module() to
|
||||
have the real logic under module.c.
|
||||
|
||||
The next step will be to convert users of of_device_request_module() to
|
||||
use the new helper.
|
||||
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Reviewed-by: Rob Herring <robh@kernel.org>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230404172148.82422-11-srinivas.kandagatla@linaro.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/of/device.c | 25 ++-----------------------
|
||||
drivers/of/module.c | 30 ++++++++++++++++++++++++++++++
|
||||
include/linux/of.h | 6 ++++++
|
||||
3 files changed, 38 insertions(+), 23 deletions(-)
|
||||
|
||||
--- a/drivers/of/device.c
|
||||
+++ b/drivers/of/device.c
|
||||
@@ -8,7 +8,6 @@
|
||||
#include <linux/dma-direct.h> /* for bus_dma_region */
|
||||
#include <linux/dma-map-ops.h>
|
||||
#include <linux/init.h>
|
||||
-#include <linux/module.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/platform_device.h>
|
||||
@@ -242,30 +241,10 @@ EXPORT_SYMBOL(of_device_get_match_data);
|
||||
|
||||
int of_device_request_module(struct device *dev)
|
||||
{
|
||||
- char *str;
|
||||
- ssize_t size;
|
||||
- int ret;
|
||||
-
|
||||
- if (!dev || !dev->of_node)
|
||||
+ if (!dev)
|
||||
return -ENODEV;
|
||||
|
||||
- size = of_modalias(dev->of_node, NULL, 0);
|
||||
- if (size < 0)
|
||||
- return size;
|
||||
-
|
||||
- /* Reserve an additional byte for the trailing '\0' */
|
||||
- size++;
|
||||
-
|
||||
- str = kmalloc(size, GFP_KERNEL);
|
||||
- if (!str)
|
||||
- return -ENOMEM;
|
||||
-
|
||||
- of_modalias(dev->of_node, str, size);
|
||||
- str[size - 1] = '\0';
|
||||
- ret = request_module(str);
|
||||
- kfree(str);
|
||||
-
|
||||
- return ret;
|
||||
+ return of_request_module(dev->of_node);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_device_request_module);
|
||||
|
||||
--- a/drivers/of/module.c
|
||||
+++ b/drivers/of/module.c
|
||||
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/of.h>
|
||||
+#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
@@ -42,3 +43,32 @@ ssize_t of_modalias(const struct device_
|
||||
|
||||
return tsize;
|
||||
}
|
||||
+
|
||||
+int of_request_module(const struct device_node *np)
|
||||
+{
|
||||
+ char *str;
|
||||
+ ssize_t size;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (!np)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ size = of_modalias(np, NULL, 0);
|
||||
+ if (size < 0)
|
||||
+ return size;
|
||||
+
|
||||
+ /* Reserve an additional byte for the trailing '\0' */
|
||||
+ size++;
|
||||
+
|
||||
+ str = kmalloc(size, GFP_KERNEL);
|
||||
+ if (!str)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ of_modalias(np, str, size);
|
||||
+ str[size - 1] = '\0';
|
||||
+ ret = request_module(str);
|
||||
+ kfree(str);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(of_request_module);
|
||||
--- a/include/linux/of.h
|
||||
+++ b/include/linux/of.h
|
||||
@@ -375,6 +375,7 @@ extern int of_count_phandle_with_args(co
|
||||
|
||||
/* module functions */
|
||||
extern ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len);
|
||||
+extern int of_request_module(const struct device_node *np);
|
||||
|
||||
/* phandle iterator functions */
|
||||
extern int of_phandle_iterator_init(struct of_phandle_iterator *it,
|
||||
@@ -893,6 +894,11 @@ static inline ssize_t of_modalias(const
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
+
|
||||
+static inline int of_request_module(const struct device_node *np)
|
||||
+{
|
||||
+ return -ENODEV;
|
||||
+}
|
||||
|
||||
static inline int of_phandle_iterator_init(struct of_phandle_iterator *it,
|
||||
const struct device_node *np,
|
|
@ -4242,6 +4242,8 @@ CONFIG_NMI_LOG_BUF_SHIFT=13
|
|||
# CONFIG_NVMEM is not set
|
||||
# CONFIG_NVMEM_BCM_OCOTP is not set
|
||||
# CONFIG_NVMEM_IMX_OCOTP is not set
|
||||
# CONFIG_NVMEM_LAYOUT_ONIE_TLV is not set
|
||||
# CONFIG_NVMEM_LAYOUT_SL28_VPD is not set
|
||||
# CONFIG_NVMEM_REBOOT_MODE is not set
|
||||
# CONFIG_NVMEM_RMEM is not set
|
||||
# CONFIG_NVMEM_SYSFS is not set
|
||||
|
|
|
@ -4442,6 +4442,8 @@ CONFIG_NMI_LOG_BUF_SHIFT=13
|
|||
# CONFIG_NVMEM is not set
|
||||
# CONFIG_NVMEM_BCM_OCOTP is not set
|
||||
# CONFIG_NVMEM_IMX_OCOTP is not set
|
||||
# CONFIG_NVMEM_LAYOUT_ONIE_TLV is not set
|
||||
# CONFIG_NVMEM_LAYOUT_SL28_VPD is not set
|
||||
# CONFIG_NVMEM_REBOOT_MODE is not set
|
||||
# CONFIG_NVMEM_RMEM is not set
|
||||
# CONFIG_NVMEM_SYSFS is not set
|
||||
|
|
|
@ -77,15 +77,15 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
|
||||
#include "mtdcore.h"
|
||||
|
||||
@@ -1081,6 +1082,8 @@ int mtd_device_parse_register(struct mtd
|
||||
|
||||
ret = mtd_otp_nvmem_add(mtd);
|
||||
@@ -1082,6 +1083,8 @@ int mtd_device_parse_register(struct mtd
|
||||
register_reboot_notifier(&mtd->reboot_notifier);
|
||||
}
|
||||
|
||||
+ register_mtd_blktrans_devs();
|
||||
+
|
||||
out:
|
||||
if (ret && device_is_registered(&mtd->dev))
|
||||
del_mtd_device(mtd);
|
||||
if (ret) {
|
||||
nvmem_unregister(mtd->otp_user_nvmem);
|
||||
--- a/include/linux/mtd/blktrans.h
|
||||
+++ b/include/linux/mtd/blktrans.h
|
||||
@@ -76,6 +76,7 @@ extern int deregister_mtd_blktrans(struc
|
||||
|
|
|
@ -36,7 +36,7 @@ Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
|||
|
||||
--- a/drivers/nvmem/u-boot-env.c
|
||||
+++ b/drivers/nvmem/u-boot-env.c
|
||||
@@ -156,7 +156,7 @@ static int u_boot_env_parse(struct u_boo
|
||||
@@ -182,7 +182,7 @@ static int u_boot_env_parse(struct u_boo
|
||||
crc32_data_len = priv->mtd->size - crc32_data_offset;
|
||||
data_len = priv->mtd->size - data_offset;
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
|||
|
||||
--- a/drivers/nvmem/u-boot-env.c
|
||||
+++ b/drivers/nvmem/u-boot-env.c
|
||||
@@ -156,7 +156,7 @@ static int u_boot_env_parse(struct u_boo
|
||||
@@ -182,7 +182,7 @@ static int u_boot_env_parse(struct u_boo
|
||||
crc32_data_len = priv->mtd->size - crc32_data_offset;
|
||||
data_len = priv->mtd->size - data_offset;
|
||||
|
||||
|
|
|
@ -142,7 +142,7 @@
|
|||
phy-handle = <&qca8081_28>;
|
||||
label = "lan";
|
||||
nvmem-cells = <&macaddr_ubootenv_ethaddr>;
|
||||
nvmem-cell-names = "mac-address-ascii";
|
||||
nvmem-cell-names = "mac-address";
|
||||
};
|
||||
|
||||
&qpic_bam {
|
||||
|
|
|
@ -220,6 +220,7 @@
|
|||
reg = <0x600000 0x10000>;
|
||||
|
||||
macaddr_lan: ethaddr {
|
||||
#nvmem-cell-cells = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -349,49 +350,48 @@
|
|||
status = "okay";
|
||||
phy-handle = <&qca8075_1>;
|
||||
label = "lan1";
|
||||
nvmem-cells = <&macaddr_lan>;
|
||||
nvmem-cell-names = "mac-address-ascii";
|
||||
nvmem-cells = <&macaddr_lan 0>;
|
||||
nvmem-cell-names = "mac-address";
|
||||
};
|
||||
|
||||
&dp2 {
|
||||
status = "okay";
|
||||
phy-handle = <&qca8075_2>;
|
||||
label = "lan2";
|
||||
nvmem-cells = <&macaddr_lan>;
|
||||
nvmem-cell-names = "mac-address-ascii";
|
||||
nvmem-cells = <&macaddr_lan 0>;
|
||||
nvmem-cell-names = "mac-address";
|
||||
};
|
||||
|
||||
&dp3 {
|
||||
status = "okay";
|
||||
phy-handle = <&qca8075_3>;
|
||||
label = "lan3";
|
||||
nvmem-cells = <&macaddr_lan>;
|
||||
nvmem-cell-names = "mac-address-ascii";
|
||||
nvmem-cells = <&macaddr_lan 0>;
|
||||
nvmem-cell-names = "mac-address";
|
||||
};
|
||||
|
||||
&dp4 {
|
||||
status = "okay";
|
||||
phy-handle = <&qca8075_4>;
|
||||
label = "lan4";
|
||||
nvmem-cells = <&macaddr_lan>;
|
||||
nvmem-cell-names = "mac-address-ascii";
|
||||
nvmem-cells = <&macaddr_lan 0>;
|
||||
nvmem-cell-names = "mac-address";
|
||||
};
|
||||
|
||||
&dp5 {
|
||||
status = "okay";
|
||||
phy-handle = <&qca8081>;
|
||||
label = "wan";
|
||||
nvmem-cells = <&macaddr_lan>;
|
||||
nvmem-cell-names = "mac-address-ascii";
|
||||
mac-address-increment = <1>;
|
||||
nvmem-cells = <&macaddr_lan 1>;
|
||||
nvmem-cell-names = "mac-address";
|
||||
};
|
||||
|
||||
&dp6_syn {
|
||||
status = "okay";
|
||||
phy-handle = <&aqr113c>;
|
||||
label = "10g";
|
||||
nvmem-cells = <&macaddr_lan>;
|
||||
nvmem-cell-names = "mac-address-ascii";
|
||||
nvmem-cells = <&macaddr_lan 0>;
|
||||
nvmem-cell-names = "mac-address";
|
||||
};
|
||||
|
||||
&blsp1_i2c2 {
|
||||
|
|
|
@ -320,7 +320,7 @@
|
|||
phy-handle = <&qca8075_2>;
|
||||
label = "lan4";
|
||||
nvmem-cells = <&macaddr_appsblenv_ethaddr>;
|
||||
nvmem-cell-names = "mac-address-ascii";
|
||||
nvmem-cell-names = "mac-address";
|
||||
};
|
||||
|
||||
&dp3 {
|
||||
|
@ -328,7 +328,7 @@
|
|||
phy-handle = <&qca8075_3>;
|
||||
label = "lan3";
|
||||
nvmem-cells = <&macaddr_appsblenv_ethaddr>;
|
||||
nvmem-cell-names = "mac-address-ascii";
|
||||
nvmem-cell-names = "mac-address";
|
||||
};
|
||||
|
||||
&dp4 {
|
||||
|
@ -336,7 +336,7 @@
|
|||
phy-handle = <&qca8075_4>;
|
||||
label = "lan2";
|
||||
nvmem-cells = <&macaddr_appsblenv_ethaddr>;
|
||||
nvmem-cell-names = "mac-address-ascii";
|
||||
nvmem-cell-names = "mac-address";
|
||||
};
|
||||
|
||||
&dp5_syn {
|
||||
|
@ -344,7 +344,7 @@
|
|||
phy-handle = <&aqr113c_1>;
|
||||
label = "wan";
|
||||
nvmem-cells = <&macaddr_appsblenv_ethaddr>;
|
||||
nvmem-cell-names = "mac-address-ascii";
|
||||
nvmem-cell-names = "mac-address";
|
||||
};
|
||||
|
||||
&dp6_syn {
|
||||
|
@ -352,7 +352,7 @@
|
|||
phy-handle = <&aqr113c_2>;
|
||||
label = "lan1";
|
||||
nvmem-cells = <&macaddr_appsblenv_ethaddr>;
|
||||
nvmem-cell-names = "mac-address-ascii";
|
||||
nvmem-cell-names = "mac-address";
|
||||
};
|
||||
|
||||
&ssphy_0 {
|
||||
|
|
|
@ -6,6 +6,11 @@
|
|||
include $(TOPDIR)/rules.mk
|
||||
include $(INCLUDE_DIR)/image.mk
|
||||
|
||||
loadaddr-$(CONFIG_TARGET_mediatek_mt7622) := 0x44000000
|
||||
loadaddr-$(CONFIG_TARGET_mediatek_mt7623) := 0x80008000
|
||||
loadaddr-$(CONFIG_TARGET_mediatek_mt7629) := 0x40008000
|
||||
loadaddr-$(CONFIG_TARGET_mediatek_filogic) := 0x48000000
|
||||
|
||||
# default all platform image(fit) build
|
||||
define Device/Default
|
||||
PROFILES = Default $$(DEVICE_NAME)
|
||||
|
@ -14,6 +19,7 @@ define Device/Default
|
|||
fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb
|
||||
KERNEL_INITRAMFS = kernel-bin | lzma | \
|
||||
fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd
|
||||
KERNEL_LOADADDR = $(loadaddr-y)
|
||||
FILESYSTEMS := squashfs
|
||||
DEVICE_DTS_DIR := $(DTS_DIR)
|
||||
IMAGES := sysupgrade.bin
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
DTS_DIR := $(DTS_DIR)/mediatek
|
||||
|
||||
KERNEL_LOADADDR := 0x44000000
|
||||
|
||||
define Image/Prepare
|
||||
# For UBI we want only one extra block
|
||||
rm -f $(KDIR)/ubi_mark
|
||||
|
@ -46,7 +44,6 @@ define Device/asus_tuf-ax4200
|
|||
DEVICE_DTS_LOADADDR := 0x47000000
|
||||
DEVICE_PACKAGES := kmod-usb3 kmod-mt7986-firmware mt7986-wo-firmware
|
||||
IMAGES := sysupgrade.bin
|
||||
KERNEL_LOADADDR := 0x48000000
|
||||
KERNEL := kernel-bin | lzma | \
|
||||
fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb
|
||||
KERNEL_INITRAMFS := kernel-bin | lzma | \
|
||||
|
@ -65,6 +62,7 @@ define Device/bananapi_bpi-r3
|
|||
DEVICE_DTS_DIR := ../dts
|
||||
DEVICE_PACKAGES := kmod-hwmon-pwmfan kmod-i2c-gpio kmod-mt7986-firmware kmod-sfp kmod-usb3 e2fsprogs f2fsck mkf2fs mt7986-wo-firmware
|
||||
IMAGES := sysupgrade.itb
|
||||
KERNEL_LOADADDR := 0x44000000
|
||||
KERNEL_INITRAMFS_SUFFIX := -recovery.itb
|
||||
ARTIFACTS := \
|
||||
emmc-preloader.bin emmc-bl31-uboot.fip \
|
||||
|
@ -108,7 +106,6 @@ define Device/mediatek_mt7986a-rfb-nand
|
|||
DEVICE_DTS := mt7986a-rfb-spim-nand
|
||||
DEVICE_DTS_DIR := $(DTS_DIR)/
|
||||
DEVICE_PACKAGES := kmod-mt7986-firmware mt7986-wo-firmware
|
||||
KERNEL_LOADADDR := 0x48000000
|
||||
SUPPORTED_DEVICES := mediatek,mt7986a-rfb-snand
|
||||
UBINIZE_OPTS := -E 5
|
||||
BLOCKSIZE := 128k
|
||||
|
@ -132,7 +129,6 @@ define Device/mediatek_mt7986b-rfb
|
|||
DEVICE_DTS := mt7986b-rfb
|
||||
DEVICE_DTS_DIR := $(DTS_DIR)/
|
||||
DEVICE_PACKAGES := kmod-mt7986-firmware mt7986-wo-firmware
|
||||
KERNEL_LOADADDR := 0x48000000
|
||||
SUPPORTED_DEVICES := mediatek,mt7986b-rfb
|
||||
UBINIZE_OPTS := -E 5
|
||||
BLOCKSIZE := 128k
|
||||
|
@ -151,7 +147,6 @@ define Device/xiaomi_redmi-router-ax6000-stock
|
|||
DEVICE_DTS := mt7986a-xiaomi-redmi-router-ax6000-stock
|
||||
DEVICE_DTS_DIR := ../dts
|
||||
DEVICE_PACKAGES := kmod-leds-ws2812b kmod-mt7986-firmware mt7986-wo-firmware
|
||||
KERNEL_LOADADDR := 0x48000000
|
||||
UBINIZE_OPTS := -E 5
|
||||
BLOCKSIZE := 128k
|
||||
PAGESIZE := 2048
|
||||
|
@ -171,7 +166,6 @@ define Device/xiaomi_redmi-router-ax6000-ubootmod
|
|||
DEVICE_PACKAGES := kmod-leds-ws2812b kmod-mt7986-firmware mt7986-wo-firmware
|
||||
KERNEL_INITRAMFS_SUFFIX := -recovery.itb
|
||||
IMAGES := sysupgrade.itb
|
||||
KERNEL_LOADADDR := 0x48000000
|
||||
UBINIZE_OPTS := -E 5
|
||||
BLOCKSIZE := 128k
|
||||
PAGESIZE := 2048
|
||||
|
|
|
@ -1,11 +1,5 @@
|
|||
DTS_DIR := $(DTS_DIR)/mediatek
|
||||
|
||||
ifdef CONFIG_LINUX_5_4
|
||||
KERNEL_LOADADDR := 0x44080000
|
||||
else
|
||||
KERNEL_LOADADDR := 0x44000000
|
||||
endif
|
||||
|
||||
define Image/Prepare
|
||||
# For UBI we want only one extra block
|
||||
rm -f $(KDIR)/ubi_mark
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
KERNEL_LOADADDR := 0x80008000
|
||||
DEVICE_VARS += UBOOT_TARGET UBOOT_OFFSET UBOOT_IMAGE
|
||||
|
||||
# The bootrom of MT7623 expects legacy MediaTek headers present in
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
KERNEL_LOADADDR := 0x40008000
|
||||
|
||||
define Device/mediatek_mt7629-rfb
|
||||
DEVICE_VENDOR := MediaTek
|
||||
DEVICE_MODEL := MT7629 rfb AP
|
||||
|
|
|
@ -81,7 +81,7 @@ define Device/engenius_ews2910p
|
|||
SOC := rtl8380
|
||||
IMAGE_SIZE := 8192k
|
||||
DEVICE_VENDOR := EnGenius
|
||||
DEVICE_MODEL := EWP2910P
|
||||
DEVICE_MODEL := EWS2910P
|
||||
UIMAGE_MAGIC := 0x03802910
|
||||
KERNEL_INITRAMFS := \
|
||||
kernel-bin | \
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=zstd
|
||||
PKG_VERSION:=1.5.4
|
||||
PKG_VERSION:=1.5.5
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://github.com/facebook/zstd/releases/download/v$(PKG_VERSION)
|
||||
PKG_HASH:=0f470992aedad543126d06efab344dc5f3e171893810455787d38347343a4424
|
||||
PKG_HASH:=9c4396cc829cfae319a6e2615202e82aad41372073482fce286fac78646d3ee4
|
||||
|
||||
PKG_LICENSE:=BSD-3-Clause
|
||||
PKG_LICENSE_FILES:=LICENSE
|
||||
|
|
Loading…
Reference in a new issue