162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * s390 crypto adapter related sclp functions.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright IBM Corp. 2020
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci#define KMSG_COMPONENT "sclp_cmd"
862306a36Sopenharmony_ci#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/export.h>
1162306a36Sopenharmony_ci#include <linux/slab.h>
1262306a36Sopenharmony_ci#include <asm/sclp.h>
1362306a36Sopenharmony_ci#include "sclp.h"
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#define SCLP_CMDW_CONFIGURE_AP			0x001f0001
1662306a36Sopenharmony_ci#define SCLP_CMDW_DECONFIGURE_AP		0x001e0001
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_cistruct ap_cfg_sccb {
1962306a36Sopenharmony_ci	struct sccb_header header;
2062306a36Sopenharmony_ci} __packed;
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_cistatic int do_ap_configure(sclp_cmdw_t cmd, u32 apid)
2362306a36Sopenharmony_ci{
2462306a36Sopenharmony_ci	struct ap_cfg_sccb *sccb;
2562306a36Sopenharmony_ci	int rc;
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci	if (!SCLP_HAS_AP_RECONFIG)
2862306a36Sopenharmony_ci		return -EOPNOTSUPP;
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci	sccb = (struct ap_cfg_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
3162306a36Sopenharmony_ci	if (!sccb)
3262306a36Sopenharmony_ci		return -ENOMEM;
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci	sccb->header.length = PAGE_SIZE;
3562306a36Sopenharmony_ci	cmd |= (apid & 0xFF) << 8;
3662306a36Sopenharmony_ci	rc = sclp_sync_request(cmd, sccb);
3762306a36Sopenharmony_ci	if (rc)
3862306a36Sopenharmony_ci		goto out;
3962306a36Sopenharmony_ci	switch (sccb->header.response_code) {
4062306a36Sopenharmony_ci	case 0x0020: case 0x0120: case 0x0440: case 0x0450:
4162306a36Sopenharmony_ci		break;
4262306a36Sopenharmony_ci	default:
4362306a36Sopenharmony_ci		pr_warn("configure AP adapter %u failed: cmd=0x%08x response=0x%04x\n",
4462306a36Sopenharmony_ci			apid, cmd, sccb->header.response_code);
4562306a36Sopenharmony_ci		rc = -EIO;
4662306a36Sopenharmony_ci		break;
4762306a36Sopenharmony_ci	}
4862306a36Sopenharmony_ciout:
4962306a36Sopenharmony_ci	free_page((unsigned long) sccb);
5062306a36Sopenharmony_ci	return rc;
5162306a36Sopenharmony_ci}
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ciint sclp_ap_configure(u32 apid)
5462306a36Sopenharmony_ci{
5562306a36Sopenharmony_ci	return do_ap_configure(SCLP_CMDW_CONFIGURE_AP, apid);
5662306a36Sopenharmony_ci}
5762306a36Sopenharmony_ciEXPORT_SYMBOL(sclp_ap_configure);
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ciint sclp_ap_deconfigure(u32 apid)
6062306a36Sopenharmony_ci{
6162306a36Sopenharmony_ci	return do_ap_configure(SCLP_CMDW_DECONFIGURE_AP, apid);
6262306a36Sopenharmony_ci}
6362306a36Sopenharmony_ciEXPORT_SYMBOL(sclp_ap_deconfigure);
64