All CoreSight compliant components have an implementation defined number of 0 to 8 claim tag bits in the claim tag registers.
These are used to claim the CoreSight resources by system agents.
ARM recommends implementions have 4 claim tag registers.
The CoreSight drivers implement a 2 claim tag bit protocol to allow self hosted and external debug agents to manage access to the hardware.
However, if there are less than 2 claim tags available the protocol incorrectly returns an error on device claim, as no checks are made.
If insufficient claim tags are present in a component then the protocol must return success on claim / disclaim to allow components to be used normally.
Changes read the CLAIMSET bits to establish the number of available tags, and adjust the claim returns accordingly.
Cache the claimtag protocol availablity in the coresight_device to reduce reads for the main claim/disclaim api.
changes since v1: 1) Added claim tag availability cache into coresight_device when using the main coresight_claim_device() / coresight_disclaim_device() API.
Applies to coresight/next
Mike Leach (1): coresight: fix issue where coresight component has no claimtags
drivers/hwtracing/coresight/coresight-core.c | 46 ++++++++++++++++++-- drivers/hwtracing/coresight/coresight-priv.h | 10 +++++ include/linux/coresight.h | 15 +++++++ 3 files changed, 68 insertions(+), 3 deletions(-)
Coresight components have 0 to 8 claim tag bits. ARM recommends 4 and the implemented claim tag protocol uses two of these.
If a component has insufficient claim tags then the protocol incorrectly returns an error when attempting to claim a component.
Fix by reading CLAIMSET to establish then actual number of claim tags and return success when attempting to claim a component were there are insufficient tags to implement the protocol.
Signed-off-by: Mike Leach mike.leach@linaro.org --- drivers/hwtracing/coresight/coresight-core.c | 46 ++++++++++++++++++-- drivers/hwtracing/coresight/coresight-priv.h | 10 +++++ include/linux/coresight.h | 15 +++++++ 3 files changed, 68 insertions(+), 3 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index 3267192f0c1c..61b4902b0ead 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -131,6 +131,39 @@ coresight_find_out_connection(struct coresight_device *csdev, return ERR_PTR(-ENODEV); }
+/* + * Reading CLAiMSET returns a bitfield representing the number of claim tags + * implemented from bit 0 to bit nTag-1, valid bits set to 1. + * + * Claim protocol requires 2 bits so test for MS bit required, + * bit 1 - CORESIGHT_CLAIM_BIT_PROTOCOL_HI + * + * return true if sufficient claim tags implemented for protocol + */ +static bool coresight_claim_tags_implemented_unlocked(struct csdev_access *csa) +{ + u32 claim_bits_impl = FIELD_GET(CORESIGHT_CLAIM_BITS_MAX_MASK, + csdev_access_relaxed_read32(csa, CORESIGHT_CLAIMSET)); + return ((claim_bits_impl & CORESIGHT_CLAIM_BIT_PROTOCOL_HI) != 0); +} + +/* + * check if we can use the claim tag protocol. + * + * If currently unknown - read register to determine if sufficient tags and + * save value, otherwise return current value. + */ +static bool coresight_check_use_claim_tag_unlocked(struct coresight_device *csdev) +{ + if (csdev->claim_tag_info == CS_CLAIM_TAG_UNKNOWN) { + if (coresight_claim_tags_implemented_unlocked(&csdev->access)) + csdev->claim_tag_info = CS_CLAIM_TAG_STD_PROTOCOL; + else + csdev->claim_tag_info = CS_CLAIM_TAG_NOT_IMPL; + } + return (csdev->claim_tag_info == CS_CLAIM_TAG_STD_PROTOCOL); +} + static u32 coresight_read_claim_tags_unlocked(struct coresight_device *csdev) { return FIELD_GET(CORESIGHT_CLAIM_MASK, @@ -156,6 +189,9 @@ EXPORT_SYMBOL_GPL(coresight_clear_self_claim_tag);
void coresight_clear_self_claim_tag_unlocked(struct csdev_access *csa) { + if (!coresight_claim_tags_implemented_unlocked(csa)) + return; + csdev_access_relaxed_write32(csa, CORESIGHT_CLAIM_SELF_HOSTED, CORESIGHT_CLAIMCLR); isb(); @@ -175,12 +211,13 @@ EXPORT_SYMBOL_GPL(coresight_clear_self_claim_tag_unlocked); int coresight_claim_device_unlocked(struct coresight_device *csdev) { int tag; - struct csdev_access *csa;
if (WARN_ON(!csdev)) return -EINVAL;
- csa = &csdev->access; + if (!coresight_check_use_claim_tag_unlocked(csdev)) + return 0; + tag = coresight_read_claim_tags_unlocked(csdev);
switch (tag) { @@ -190,7 +227,7 @@ int coresight_claim_device_unlocked(struct coresight_device *csdev) return 0;
/* There was a race setting the tag, clean up and fail */ - coresight_clear_self_claim_tag_unlocked(csa); + coresight_clear_self_claim_tag_unlocked(&csdev->access); dev_dbg(&csdev->dev, "Busy: Couldn't set self claim tag"); return -EBUSY;
@@ -237,6 +274,9 @@ void coresight_disclaim_device_unlocked(struct coresight_device *csdev) if (WARN_ON(!csdev)) return;
+ if (!coresight_check_use_claim_tag_unlocked(csdev)) + return; + if (coresight_read_claim_tags_unlocked(csdev) == CORESIGHT_CLAIM_SELF_HOSTED) coresight_clear_self_claim_tag_unlocked(&csdev->access); else diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h index 33e22b1ba043..270f179c8535 100644 --- a/drivers/hwtracing/coresight/coresight-priv.h +++ b/drivers/hwtracing/coresight/coresight-priv.h @@ -41,6 +41,16 @@ extern const struct device_type coresight_dev_type[]; #define CORESIGHT_CLAIM_SELF_HOSTED 2 #define CORESIGHT_CLAIM_INVALID 3
+/* + * Coresight specification defines a maximum of 8 claim tag bits. + * The precise number is implementation defined, and may be obtained by + * reading the CLAIMSET register. + */ +#define CORESIGHT_CLAIM_BITS_MAX_MASK GENMASK(7, 0) + +/* MS Bit required by the protocol */ +#define CORESIGHT_CLAIM_BIT_PROTOCOL_HI BIT(1) + #define TIMEOUT_US 100 #define BMVAL(val, lsb, msb) ((val & GENMASK(msb, lsb)) >> lsb)
diff --git a/include/linux/coresight.h b/include/linux/coresight.h index 6de59ce8ef8c..fefe4317a793 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -242,6 +242,19 @@ struct coresight_trace_id_map { raw_spinlock_t lock; };
+/* + * Coresight claim tag info: + * CS_CLAIM_TAG_UNKNOWN - not yet checked. + * CS_CLAIM_TAG_STD_PROTOCOL - using standard claim/release protocol. + * CS_CLAIM_TAG_NOT_IMPL - no claim tags available. + */ +enum coresight_claim_tag_info { + CS_CLAIM_TAG_UNKNOWN, + CS_CLAIM_TAG_STD_PROTOCOL, + CS_CLAIM_TAG_NOT_IMPL, +}; + + /** * struct coresight_device - representation of a device as used by the framework * @pdata: Platform data with device connections associated to this device. @@ -265,6 +278,7 @@ struct coresight_trace_id_map { * CS_MODE_SYSFS. Otherwise it must be accessed from inside the * spinlock. * @orphan: true if the component has connections that haven't been linked. + * @claim_tag_info: how the device is using claim tags. * @sysfs_sink_activated: 'true' when a sink has been selected for use via sysfs * by writing a 1 to the 'enable_sink' file. A sink can be * activated but not yet enabled. Enabling for a _sink_ happens @@ -291,6 +305,7 @@ struct coresight_device { local_t mode; int refcnt; bool orphan; + enum coresight_claim_tag_info claim_tag_info; /* sink specific fields */ bool sysfs_sink_activated; struct dev_ext_attribute *ea;