+obj-$(CONFIG_ARM_CORESIGHT_PMU_ARCH_SYSTEM_PMU) +=arm_cspmu_impl.o
Not sure what's up with this... I have no complaint with keeping the
impl infrastucture together in its own source file, but it still wants
to end up as part of arm_cspmu_module. Doing otherwise just adds
unnecessary overhead at many levels and invites more problems.
My intention is to separate arm_cspmu_impl, arm_cspmu, and
vendor backend into different modules. Here is the dependency I have in mind:
arm_cspmu_impl
____|____
| |
arm_cspmu nvidia_cspmu
This helps during device probe that the call to request_module can be made
as a blocking call and the backend init_impl_ops will always be ready to use after
request_module returns. The code seems simpler this way. Could you please
elaborate the potential issue that might arise with this approach?
After reading your other comments on built-in kernel, can we use late_initcall
for arm_cspmu module to assume that the main driver will always be init'ed after
backend module ?
-ssize_t arm_cspmu_sysfs_format_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct dev_ext_attribute *eattr =
- container_of(attr, struct dev_ext_attribute, attr);
- return sysfs_emit(buf, "%s\n", (char *)eattr->var);
-}
-EXPORT_SYMBOL_GPL(arm_cspmu_sysfs_format_show);
-
Is there a reason for moving these (other than bodging around issues
caused by the Makefile mishap above)?
The main reason is to remove backend module (nvidia_cspmu)
dependency to main driver.
(also, I'm now wondering why they're exported in the first place, since
a backend module is hardly going to need to override the default
implementations with the default implementations...)
My intention is to make the event and format attribute macro
on the header file to be reusable for the backend module. The event/format
attribute on the other PMUs is pretty generic, so I thought it would be
harmless.
static struct attribute *arm_cspmu_format_attrs[] = {arm_cspmu_cpumask_attr_group = {
ARM_CSPMU_FORMAT_EVENT_ATTR,
ARM_CSPMU_FORMAT_FILTER_ATTR,
@@ -379,27 +355,12 @@ static struct attribute_group
.attrs = arm_cspmu_cpumask_attrs,arm_cspmu *cspmu)
};
-struct impl_match {
- u32 pmiidr;
- u32 mask;
- int (*impl_init_ops)(struct arm_cspmu *cspmu);
-};
-
-static const struct impl_match impl_match[] = {
- {
- .pmiidr = ARM_CSPMU_IMPL_ID_NVIDIA,
- .mask = ARM_CSPMU_PMIIDR_IMPLEMENTER,
- .impl_init_ops = nv_cspmu_init_ops
- },
- {}
-};
-
static int arm_cspmu_init_impl_ops(struct arm_cspmu *cspmu)
{
- int ret;
+ int ret = 0;
struct acpi_apmt_node *apmt_node = cspmu->apmt_node;
struct arm_cspmu_impl_ops *impl_ops = &cspmu->impl.ops;
- const struct impl_match *match = impl_match;
+ const struct arm_cspmu_impl_module *match;
/*
* Get PMU implementer and product id from APMT node.
@@ -411,18 +372,21 @@ static int arm_cspmu_init_impl_ops(struct
readl(cspmu->base0 + PMIIDR);
/* Find implementer specific attribute ops. */
- for (; match->pmiidr; match++) {
- const u32 mask = match->mask;
-
- if ((match->pmiidr & mask) == (cspmu->impl.pmiidr & mask)) {
- ret = match->impl_init_ops(cspmu);
- if (ret)
- return ret;
-
- break;
+ match = arm_cspmu_impl_match_module(cspmu->impl.pmiidr);
+ if (match) {
+ request_module(match->name);
Are we confident this can't deadlock when it's already in the middle of
loading the main module?
The backend module does not depend on the main driver module anymore
(please see my top comment). The blocking call to request_module should be
able to return.
+void arm_cspmu_impl_unregister(const struct arm_cspmu_impl_param*impl_param)
+{
+ struct arm_cspmu_impl_module *module;
+
+ mutex_lock(&arm_cspmu_lock);
+
+ module = arm_cspmu_impl_find_module(impl_param);
+ if (module) {
I think it's reasonable to have a usage model where unregister should
only be called if register succeeded, and thus we can assume this lookup
never fails. That certainly fits if the expectation is that
register/unregister are tied to module_init/module_exit.
Yup, that is the expectation. It is still good to validate the module pointer right ?
Or do you think it will hide a bug, if any ?