Commit 09dc3972 authored by Thomas Richter's avatar Thomas Richter Committed by Heiko Carstens
Browse files

s390/pai_crypto: Consolidate PAI crypto allocation and cleanup paths



Introduce paicrypt_free() to centralize memory release for per-CPU
maps and remove duplicated free logic. Replace paicrypt_busy() with
paicrypt_alloc_cpu() returning int error codes instead of ERR_PTR,
and adjust callers accordingly. System-wide allocation now uses
paicrypt_alloc() with consistent error handling. Memory allocation
and free management is now identical to PMU pai_ext.

Reference counting and root anchor management remain unchanged.
Debug output in the destroy path is dropped.

Signed-off-by: default avatarThomas Richter <tmricht@linux.ibm.com>
Tested-by: default avatarJan Polensky <japo@linux.ibm.com>
Reviewed-by: default avatarJan Polensky <japo@linux.ibm.com>
Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
parent 9daa5a87
Loading
Loading
Loading
Loading
+44 −62
Original line number Diff line number Diff line
@@ -80,6 +80,15 @@ static int paicrypt_root_alloc(void)
/* Release the PMU if event is the last perf event */
static DEFINE_MUTEX(pai_reserve_mutex);

/* Free all memory allocated for event counting/sampling setup */
static void paicrypt_free(struct paicrypt_mapptr *mp)
{
	free_page((unsigned long)mp->mapptr->page);
	kvfree(mp->mapptr->save);
	kfree(mp->mapptr);
	mp->mapptr = NULL;
}

/* Adjust usage counters and remove allocated memory when all users are
 * gone.
 */
@@ -93,15 +102,8 @@ static void paicrypt_event_destroy_cpu(struct perf_event *event, int cpu)
			    "refcnt %u\n", __func__, event->attr.config,
			    event->cpu, cpump->active_events,
			    refcount_read(&cpump->refcnt));
	if (refcount_dec_and_test(&cpump->refcnt)) {
		debug_sprintf_event(cfm_dbg, 4, "%s page %#lx save %p\n",
				    __func__, (unsigned long)cpump->page,
				    cpump->save);
		free_page((unsigned long)cpump->page);
		kvfree(cpump->save);
		kfree(cpump);
		mp->mapptr = NULL;
	}
	if (refcount_dec_and_test(&cpump->refcnt))
		paicrypt_free(mp);
	paicrypt_root_free();
	mutex_unlock(&pai_reserve_mutex);
}
@@ -175,14 +177,13 @@ static u64 paicrypt_getall(struct perf_event *event)
 *
 * Allocate the memory for the event.
 */
static struct paicrypt_map *paicrypt_busy(struct perf_event *event, int cpu)
static int paicrypt_alloc_cpu(struct perf_event *event, int cpu)
{
	struct paicrypt_map *cpump = NULL;
	struct paicrypt_mapptr *mp;
	int rc;

	mutex_lock(&pai_reserve_mutex);

	/* Allocate root node */
	rc = paicrypt_root_alloc();
	if (rc)
@@ -192,58 +193,44 @@ static struct paicrypt_map *paicrypt_busy(struct perf_event *event, int cpu)
	mp = per_cpu_ptr(paicrypt_root.mapptr, cpu);
	cpump = mp->mapptr;
	if (!cpump) {			/* Paicrypt_map allocated? */
		cpump = kzalloc(sizeof(*cpump), GFP_KERNEL);
		if (!cpump) {
		rc = -ENOMEM;
			goto free_root;
		}
		INIT_LIST_HEAD(&cpump->syswide_list);
	}

		cpump = kzalloc(sizeof(*cpump), GFP_KERNEL);
		if (!cpump)
			goto undo;
		/* Allocate memory for counter page and counter extraction.
		 * Only the first counting event has to allocate a page.
		 */
	if (cpump->page) {
		refcount_inc(&cpump->refcnt);
		goto unlock;
	}

	rc = -ENOMEM;
		mp->mapptr = cpump;
		cpump->page = (unsigned long *)get_zeroed_page(GFP_KERNEL);
	if (!cpump->page)
		goto free_paicrypt_map;
		cpump->save = kvmalloc_array(paicrypt_cnt + 1,
				     sizeof(struct pai_userdata), GFP_KERNEL);
	if (!cpump->save) {
		free_page((unsigned long)cpump->page);
		cpump->page = NULL;
		goto free_paicrypt_map;
					     sizeof(struct pai_userdata),
					     GFP_KERNEL);
		if (!cpump->page || !cpump->save) {
			paicrypt_free(mp);
			goto undo;
		}

	/* Set mode and reference count */
	rc = 0;
		INIT_LIST_HEAD(&cpump->syswide_list);
		refcount_set(&cpump->refcnt, 1);
	mp->mapptr = cpump;
	debug_sprintf_event(cfm_dbg, 5, "%s users %d refcnt %u page %#lx "
			    "save %p rc %d\n", __func__, cpump->active_events,
			    refcount_read(&cpump->refcnt),
			    (unsigned long)cpump->page, cpump->save, rc);
	goto unlock;
		rc = 0;
	} else {
		refcount_inc(&cpump->refcnt);
	}

free_paicrypt_map:
	/* Undo memory allocation */
	kfree(cpump);
	mp->mapptr = NULL;
free_root:
undo:
	if (rc) {
		/* Error in allocation of event, decrement anchor. Since
		 * the event in not created, its destroy() function is never
		 * invoked. Adjust the reference counter for the anchor.
		 */
		paicrypt_root_free();
	}
unlock:
	mutex_unlock(&pai_reserve_mutex);
	return rc ? ERR_PTR(rc) : cpump;
	return rc;
}

static int paicrypt_event_init_all(struct perf_event *event)
static int paicrypt_alloc(struct perf_event *event)
{
	struct paicrypt_map *cpump;
	struct cpumask *maskptr;
	int cpu, rc = -ENOMEM;

@@ -252,12 +239,11 @@ static int paicrypt_event_init_all(struct perf_event *event)
		goto out;

	for_each_online_cpu(cpu) {
		cpump = paicrypt_busy(event, cpu);
		if (IS_ERR(cpump)) {
		rc = paicrypt_alloc_cpu(event, cpu);
		if (rc) {
			for_each_cpu(cpu, maskptr)
				paicrypt_event_destroy_cpu(event, cpu);
			kfree(maskptr);
			rc = PTR_ERR(cpump);
			goto out;
		}
		cpumask_set_cpu(cpu, maskptr);
@@ -279,7 +265,6 @@ static int paicrypt_event_init_all(struct perf_event *event)
static int paicrypt_event_init(struct perf_event *event)
{
	struct perf_event_attr *a = &event->attr;
	struct paicrypt_map *cpump;
	int rc = 0;

	/* PAI crypto PMU registered as PERF_TYPE_RAW, check event type */
@@ -301,13 +286,10 @@ static int paicrypt_event_init(struct perf_event *event)
		}
	}

	if (event->cpu >= 0) {
		cpump = paicrypt_busy(event, event->cpu);
		if (IS_ERR(cpump))
			rc = PTR_ERR(cpump);
	} else {
		rc = paicrypt_event_init_all(event);
	}
	if (event->cpu >= 0)
		rc = paicrypt_alloc_cpu(event, event->cpu);
	else
		rc = paicrypt_alloc(event);
	if (rc) {
		free_page(PAI_SAVE_AREA(event));
		goto out;