Commit 30be8446 authored by Arnd Bergmann's avatar Arnd Bergmann
Browse files

Merge tag 'qcom-drivers-for-5.13-2' of...

Merge tag 'qcom-drivers-for-5.13-2' of git://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux into arm/drivers

More Qualcomm driver updates for 5.13

This improves the Qualcomm SCM driver logic related to detecting the
calling convention, in particular on SC7180, and fixes a few small
issues in the same.

It introduces additonal sanity checks of the size of loaded segments in
the MDT loader and adds a missing error in the return path of
pdr_register_listener().

It makes it possible to specify the OEM specific firmware path in the
wcn36xx control (and WiFi) driver.

Lastly it adds a missing path specifier in the MAINTAINERS' entry and
fixes a bunch of kerneldoc issues in various drivers.

* tag 'qcom-drivers-for-5.13-2' of git://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux:
  soc: qcom: mdt_loader: Detect truncated read of segments
  soc: qcom: mdt_loader: Validate that p_filesz < p_memsz
  soc: qcom: pdr: Fix error return code in pdr_register_listener
  firmware: qcom_scm: Fix kernel-doc function names to match
  firmware: qcom_scm: Suppress sysfs bind attributes
  firmware: qcom_scm: Workaround lack of "is available" call on SC7180
  firmware: qcom_scm: Reduce locking section for __get_convention()
  firmware: qcom_scm: Make __qcom_scm_is_call_available() return bool
  soc: qcom: wcnss_ctrl: Allow reading firmware-name from DT
  soc: qcom: wcnss_ctrl: Introduce local variable "dev"
  dt-bindings: soc: qcom: wcnss: Add firmware-name property
  soc: qcom: address kernel-doc warnings
  MAINTAINERS: add another entry for ARM/QUALCOMM SUPPORT

Link: https://lore.kernel.org/r/20210409162001.775851-1-bjorn.andersson@linaro.org


Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parents 36841008 0648c55e
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -24,6 +24,13 @@ block and a BT, WiFi and FM radio block, all using SMD as command channels.
		    "qcom,riva",
		    "qcom,pronto"

- firmware-name:
	Usage: optional
	Value type: <string>
	Definition: specifies the relative firmware image path for the WLAN NV
		    blob. Defaults to "wlan/prima/WCNSS_qcom_wlan_nv.bin" if
		    not specified.

= SUBNODES
The subnodes of the wcnss node are optional and describe the individual blocks in
the WCNSS.
+1 −0
Original line number Diff line number Diff line
@@ -2296,6 +2296,7 @@ F: drivers/tty/serial/msm_serial.c
F:	drivers/usb/dwc3/dwc3-qcom.c
F:	include/dt-bindings/*/qcom*
F:	include/linux/*/qcom*
F:	include/linux/soc/qcom/
ARM/RADISYS ENP2611 MACHINE SUPPORT
M:	Lennert Buytenhek <kernel@wantstofly.org>
+2 −2
Original line number Diff line number Diff line
@@ -118,7 +118,7 @@ static void __scm_legacy_do(const struct arm_smccc_args *smc,
}

/**
 * qcom_scm_call() - Sends a command to the SCM and waits for the command to
 * scm_legacy_call() - Sends a command to the SCM and waits for the command to
 * finish processing.
 *
 * A note on cache maintenance:
@@ -209,7 +209,7 @@ int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc,
				(n & 0xf))

/**
 * qcom_scm_call_atomic() - Send an atomic SCM command with up to 5 arguments
 * scm_legacy_call_atomic() - Send an atomic SCM command with up to 5 arguments
 * and 3 return values
 * @desc: SCM call descriptor containing arguments
 * @res:  SCM call return values
+7 −5
Original line number Diff line number Diff line
@@ -77,7 +77,9 @@ static void __scm_smc_do(const struct arm_smccc_args *smc,
	}  while (res->a0 == QCOM_SCM_V2_EBUSY);
}

int scm_smc_call(struct device *dev, const struct qcom_scm_desc *desc,

int __scm_smc_call(struct device *dev, const struct qcom_scm_desc *desc,
		   enum qcom_scm_convention qcom_convention,
		   struct qcom_scm_res *res, bool atomic)
{
	int arglen = desc->arginfo & 0xf;
@@ -87,8 +89,7 @@ int scm_smc_call(struct device *dev, const struct qcom_scm_desc *desc,
	size_t alloc_len;
	gfp_t flag = atomic ? GFP_ATOMIC : GFP_KERNEL;
	u32 smccc_call_type = atomic ? ARM_SMCCC_FAST_CALL : ARM_SMCCC_STD_CALL;
	u32 qcom_smccc_convention =
			(qcom_scm_convention == SMC_CONVENTION_ARM_32) ?
	u32 qcom_smccc_convention = (qcom_convention == SMC_CONVENTION_ARM_32) ?
				    ARM_SMCCC_SMC_32 : ARM_SMCCC_SMC_64;
	struct arm_smccc_res smc_res;
	struct arm_smccc_args smc = {0};
@@ -148,4 +149,5 @@ int scm_smc_call(struct device *dev, const struct qcom_scm_desc *desc,
	}

	return (long)smc_res.a0 ? qcom_scm_remap_error(smc_res.a0) : 0;

}
+50 −39
Original line number Diff line number Diff line
@@ -113,14 +113,10 @@ static void qcom_scm_clk_disable(void)
	clk_disable_unprepare(__scm->bus_clk);
}

static int __qcom_scm_is_call_available(struct device *dev, u32 svc_id,
					u32 cmd_id);
enum qcom_scm_convention qcom_scm_convention = SMC_CONVENTION_UNKNOWN;
static DEFINE_SPINLOCK(scm_query_lock);

enum qcom_scm_convention qcom_scm_convention;
static bool has_queried __read_mostly;
static DEFINE_SPINLOCK(query_lock);

static void __query_convention(void)
static enum qcom_scm_convention __get_convention(void)
{
	unsigned long flags;
	struct qcom_scm_desc desc = {
@@ -133,36 +129,50 @@ static void __query_convention(void)
		.owner = ARM_SMCCC_OWNER_SIP,
	};
	struct qcom_scm_res res;
	enum qcom_scm_convention probed_convention;
	int ret;
	bool forced = false;

	spin_lock_irqsave(&query_lock, flags);
	if (has_queried)
		goto out;
	if (likely(qcom_scm_convention != SMC_CONVENTION_UNKNOWN))
		return qcom_scm_convention;

	qcom_scm_convention = SMC_CONVENTION_ARM_64;
	// Device isn't required as there is only one argument - no device
	// needed to dma_map_single to secure world
	ret = scm_smc_call(NULL, &desc, &res, true);
	/*
	 * Device isn't required as there is only one argument - no device
	 * needed to dma_map_single to secure world
	 */
	probed_convention = SMC_CONVENTION_ARM_64;
	ret = __scm_smc_call(NULL, &desc, probed_convention, &res, true);
	if (!ret && res.result[0] == 1)
		goto out;
		goto found;

	/*
	 * Some SC7180 firmwares didn't implement the
	 * QCOM_SCM_INFO_IS_CALL_AVAIL call, so we fallback to forcing ARM_64
	 * calling conventions on these firmwares. Luckily we don't make any
	 * early calls into the firmware on these SoCs so the device pointer
	 * will be valid here to check if the compatible matches.
	 */
	if (of_device_is_compatible(__scm ? __scm->dev->of_node : NULL, "qcom,scm-sc7180")) {
		forced = true;
		goto found;
	}

	qcom_scm_convention = SMC_CONVENTION_ARM_32;
	ret = scm_smc_call(NULL, &desc, &res, true);
	probed_convention = SMC_CONVENTION_ARM_32;
	ret = __scm_smc_call(NULL, &desc, probed_convention, &res, true);
	if (!ret && res.result[0] == 1)
		goto out;

	qcom_scm_convention = SMC_CONVENTION_LEGACY;
out:
	has_queried = true;
	spin_unlock_irqrestore(&query_lock, flags);
	pr_info("qcom_scm: convention: %s\n",
		qcom_scm_convention_names[qcom_scm_convention]);
		goto found;

	probed_convention = SMC_CONVENTION_LEGACY;
found:
	spin_lock_irqsave(&scm_query_lock, flags);
	if (probed_convention != qcom_scm_convention) {
		qcom_scm_convention = probed_convention;
		pr_info("qcom_scm: convention: %s%s\n",
			qcom_scm_convention_names[qcom_scm_convention],
			forced ? " (forced)" : "");
	}
	spin_unlock_irqrestore(&scm_query_lock, flags);

static inline enum qcom_scm_convention __get_convention(void)
{
	if (unlikely(!has_queried))
		__query_convention();
	return qcom_scm_convention;
}

@@ -219,7 +229,7 @@ static int qcom_scm_call_atomic(struct device *dev,
	}
}

static int __qcom_scm_is_call_available(struct device *dev, u32 svc_id,
static bool __qcom_scm_is_call_available(struct device *dev, u32 svc_id,
					 u32 cmd_id)
{
	int ret;
@@ -247,7 +257,7 @@ static int __qcom_scm_is_call_available(struct device *dev, u32 svc_id,

	ret = qcom_scm_call(dev, &desc, &res);

	return ret ? : res.result[0];
	return ret ? false : !!res.result[0];
}

/**
@@ -585,9 +595,8 @@ bool qcom_scm_pas_supported(u32 peripheral)
	};
	struct qcom_scm_res res;

	ret = __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_PIL,
					   QCOM_SCM_PIL_PAS_IS_SUPPORTED);
	if (ret <= 0)
	if (!__qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_PIL,
					  QCOM_SCM_PIL_PAS_IS_SUPPORTED))
		return false;

	ret = qcom_scm_call(__scm->dev, &desc, &res);
@@ -1060,17 +1069,18 @@ EXPORT_SYMBOL(qcom_scm_ice_set_key);
 */
bool qcom_scm_hdcp_available(void)
{
	bool avail;
	int ret = qcom_scm_clk_enable();

	if (ret)
		return ret;

	ret = __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_HDCP,
	avail = __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_HDCP,
						QCOM_SCM_HDCP_INVOKE);

	qcom_scm_clk_disable();

	return ret > 0;
	return avail;
}
EXPORT_SYMBOL(qcom_scm_hdcp_available);

@@ -1242,7 +1252,7 @@ static int qcom_scm_probe(struct platform_device *pdev)
	__scm = scm;
	__scm->dev = &pdev->dev;

	__query_convention();
	__get_convention();

	/*
	 * If requested enable "download mode", from this point on warmboot
@@ -1291,6 +1301,7 @@ static struct platform_driver qcom_scm_driver = {
	.driver = {
		.name	= "qcom_scm",
		.of_match_table = qcom_scm_dt_match,
		.suppress_bind_attrs = true,
	},
	.probe = qcom_scm_probe,
	.shutdown = qcom_scm_shutdown,
Loading