Received: by 2002:ac0:bc90:0:0:0:0:0 with SMTP id a16csp4970898img; Tue, 26 Mar 2019 22:33:43 -0700 (PDT) X-Google-Smtp-Source: APXvYqwDtkBuo6/mmnMFoKGIKa4gqj3SSHSl5PeB3nB7v15IGXbsTDEK12TcUmJ2FrVTicVIKBIP X-Received: by 2002:a62:14d7:: with SMTP id 206mr5352655pfu.162.1553664823663; Tue, 26 Mar 2019 22:33:43 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1553664823; cv=none; d=google.com; s=arc-20160816; b=ZAMhDjjn2Ri+Q3ZnPnSOYb6VBIfSzq7jc+tmUrGT6g7YUVGpliEbC2oGJUT3n0uv2e hb/Z+Y0DXm+4zjBqbUO969QN4pP8CLQjp3I03my7nYwMa3eevJnXyLkXIfz31fp0RjtS BBpGhBesoJ0YABpglJhBO8vxoUZIou6RdoupcEGmR8REjSAXWNK0dBdJdlKfa2EEcFGx aJ1B0gE0WLxth+NxK3l51jKhPrBWFtdRhgdyIAh7xYQBp2SH+RhD1eWCK5klKpS3Jjfm vi0XMnn9deO+JlXRLK66fswAdgUZNH4nrWsbWrku//2rpTwixMyvR6x8WyrWKL7LW5Gh vuRQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:content-transfer-encoding :mime-version:references:in-reply-to:date:subject:cc:to:from; bh=Fm4+sPbduuH/QxcCYu2wvokggI0FRfLeUnjb6BYY1Vs=; b=WlkwtUvepdVqesk4vfM+dq1hueEYiaKyKkhIMkjzwtYmWo1xKaTIhdpehmtphekzuf XrBT0302D8gHTmx2yylsyTUhwBl6QJ7hB0u7DJTMofHRzI9+rAbcsocoFY18ZJpBLgjz HPeu2b4NOFxjQauLv7/dLZxptu+Rgmcez0t9BmsF8xiQEhnP6Bk0xPAmdwg/jR0vkCQP dXPmyhi1A7BH/u56M+R5VwbbL5vjWbVApidnKpHJhiUWNtHqtP/eDKoNOnz39GXcF8x/ dPXCV36zIhbZhjV1WxBPhknzi1J2i9I/zz7puRj1S/AS+ovgo0uivvUNw6iXl0B6GHGe zTDQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=ibm.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id y9si1914848pgg.15.2019.03.26.22.33.28; Tue, 26 Mar 2019 22:33:43 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=ibm.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732836AbfC0Fcj (ORCPT + 99 others); Wed, 27 Mar 2019 01:32:39 -0400 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:46064 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732789AbfC0Fci (ORCPT ); Wed, 27 Mar 2019 01:32:38 -0400 Received: from pps.filterd (m0098399.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x2R5TSk6140462 for ; Wed, 27 Mar 2019 01:32:38 -0400 Received: from e06smtp07.uk.ibm.com (e06smtp07.uk.ibm.com [195.75.94.103]) by mx0a-001b2d01.pphosted.com with ESMTP id 2rg0vevfvq-1 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=NOT) for ; Wed, 27 Mar 2019 01:32:38 -0400 Received: from localhost by e06smtp07.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 27 Mar 2019 05:32:35 -0000 Received: from b06cxnps4074.portsmouth.uk.ibm.com (9.149.109.196) by e06smtp07.uk.ibm.com (192.168.101.137) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; (version=TLSv1/SSLv3 cipher=AES256-GCM-SHA384 bits=256/256) Wed, 27 Mar 2019 05:32:31 -0000 Received: from d06av24.portsmouth.uk.ibm.com (mk.ibm.com [9.149.105.60]) by b06cxnps4074.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id x2R5WUwS19660974 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 27 Mar 2019 05:32:30 GMT Received: from d06av24.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id B399E42047; Wed, 27 Mar 2019 05:32:30 +0000 (GMT) Received: from d06av24.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 1AE5B4205C; Wed, 27 Mar 2019 05:32:30 +0000 (GMT) Received: from ozlabs.au.ibm.com (unknown [9.192.253.14]) by d06av24.portsmouth.uk.ibm.com (Postfix) with ESMTP; Wed, 27 Mar 2019 05:32:30 +0000 (GMT) Received: from adsilva.ozlabs.ibm.com (haven.au.ibm.com [9.192.254.114]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.au.ibm.com (Postfix) with ESMTPSA id 0DD47A00BD; Wed, 27 Mar 2019 16:32:29 +1100 (AEDT) From: "Alastair D'Silva" To: alastair@d-silva.org Cc: Greg Kurz , Frederic Barrat , Andrew Donnellan , Arnd Bergmann , Greg Kroah-Hartman , linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org Subject: [PATCH v4 7/7] ocxl: Provide global MMIO accessors for external drivers Date: Wed, 27 Mar 2019 16:31:36 +1100 X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190327053137.15173-1-alastair@au1.ibm.com> References: <20190327053137.15173-1-alastair@au1.ibm.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-TM-AS-GCONF: 00 x-cbid: 19032705-0028-0000-0000-00000358B777 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 19032705-0029-0000-0000-0000241771B6 Message-Id: <20190327053137.15173-8-alastair@au1.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:,, definitions=2019-03-27_03:,, signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=1 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 mlxscore=0 impostorscore=0 mlxlogscore=753 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1810050000 definitions=main-1903270038 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Alastair D'Silva External drivers that communicate via OpenCAPI will need to make MMIO calls to interact with the devices. Signed-off-by: Alastair D'Silva Reviewed-by: Greg Kurz --- drivers/misc/ocxl/Makefile | 2 +- drivers/misc/ocxl/mmio.c | 234 +++++++++++++++++++++++++++++++++++++ include/misc/ocxl.h | 110 +++++++++++++++++ 3 files changed, 345 insertions(+), 1 deletion(-) create mode 100644 drivers/misc/ocxl/mmio.c diff --git a/drivers/misc/ocxl/Makefile b/drivers/misc/ocxl/Makefile index bc4e39bfda7b..d07d1bb8e8d4 100644 --- a/drivers/misc/ocxl/Makefile +++ b/drivers/misc/ocxl/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0+ ccflags-$(CONFIG_PPC_WERROR) += -Werror -ocxl-y += main.o pci.o config.o file.o pasid.o +ocxl-y += main.o pci.o config.o file.o pasid.o mmio.o ocxl-y += link.o context.o afu_irq.o sysfs.o trace.o ocxl-y += core.o obj-$(CONFIG_OCXL) += ocxl.o diff --git a/drivers/misc/ocxl/mmio.c b/drivers/misc/ocxl/mmio.c new file mode 100644 index 000000000000..aae713db4ebe --- /dev/null +++ b/drivers/misc/ocxl/mmio.c @@ -0,0 +1,234 @@ +// SPDX-License-Identifier: GPL-2.0+ +// Copyright 2019 IBM Corp. +#include +#include "trace.h" +#include "ocxl_internal.h" + +int ocxl_global_mmio_read32(struct ocxl_afu *afu, size_t offset, + enum ocxl_endian endian, u32 *val) +{ + if (offset > afu->config.global_mmio_size - 4) + return -EINVAL; + +#ifdef __BIG_ENDIAN__ + if (endian == OCXL_HOST_ENDIAN) + endian = OCXL_BIG_ENDIAN; +#endif + + switch (endian) { + case OCXL_BIG_ENDIAN: + *val = readl_be((char *)afu->global_mmio_ptr + offset); + break; + + default: + *val = readl((char *)afu->global_mmio_ptr + offset); + break; + } + + return 0; +} +EXPORT_SYMBOL_GPL(ocxl_global_mmio_read32); + +int ocxl_global_mmio_read64(struct ocxl_afu *afu, size_t offset, + enum ocxl_endian endian, u64 *val) +{ + if (offset > afu->config.global_mmio_size - 8) + return -EINVAL; + +#ifdef __BIG_ENDIAN__ + if (endian == OCXL_HOST_ENDIAN) + endian = OCXL_BIG_ENDIAN; +#endif + + switch (endian) { + case OCXL_BIG_ENDIAN: + *val = readq_be((char *)afu->global_mmio_ptr + offset); + break; + + default: + *val = readq((char *)afu->global_mmio_ptr + offset); + break; + } + + return 0; +} +EXPORT_SYMBOL_GPL(ocxl_global_mmio_read64); + +int ocxl_global_mmio_write32(struct ocxl_afu *afu, size_t offset, + enum ocxl_endian endian, u32 val) +{ + if (offset > afu->config.global_mmio_size - 4) + return -EINVAL; + +#ifdef __BIG_ENDIAN__ + if (endian == OCXL_HOST_ENDIAN) + endian = OCXL_BIG_ENDIAN; +#endif + + switch (endian) { + case OCXL_BIG_ENDIAN: + writel_be(val, (char *)afu->global_mmio_ptr + offset); + break; + + default: + writel(val, (char *)afu->global_mmio_ptr + offset); + break; + } + + + return 0; +} +EXPORT_SYMBOL_GPL(ocxl_global_mmio_write32); + +int ocxl_global_mmio_write64(struct ocxl_afu *afu, size_t offset, + enum ocxl_endian endian, u64 val) +{ + if (offset > afu->config.global_mmio_size - 8) + return -EINVAL; + +#ifdef __BIG_ENDIAN__ + if (endian == OCXL_HOST_ENDIAN) + endian = OCXL_BIG_ENDIAN; +#endif + + switch (endian) { + case OCXL_BIG_ENDIAN: + writeq_be(val, (char *)afu->global_mmio_ptr + offset); + break; + + default: + writeq(val, (char *)afu->global_mmio_ptr + offset); + break; + } + + + return 0; +} +EXPORT_SYMBOL_GPL(ocxl_global_mmio_write64); + +int ocxl_global_mmio_set32(struct ocxl_afu *afu, size_t offset, + enum ocxl_endian endian, u32 mask) +{ + u32 tmp; + + if (offset > afu->config.global_mmio_size - 4) + return -EINVAL; + +#ifdef __BIG_ENDIAN__ + if (endian == OCXL_HOST_ENDIAN) + endian = OCXL_BIG_ENDIAN; +#endif + + switch (endian) { + case OCXL_BIG_ENDIAN: + tmp = readl_be((char *)afu->global_mmio_ptr + offset); + tmp |= mask; + writel_be(tmp, (char *)afu->global_mmio_ptr + offset); + break; + + default: + tmp = readl((char *)afu->global_mmio_ptr + offset); + tmp |= mask; + writel(tmp, (char *)afu->global_mmio_ptr + offset); + break; + } + + return 0; +} +EXPORT_SYMBOL_GPL(ocxl_global_mmio_set32); + +int ocxl_global_mmio_set64(struct ocxl_afu *afu, size_t offset, + enum ocxl_endian endian, u64 mask) +{ + u64 tmp; + + if (offset > afu->config.global_mmio_size - 8) + return -EINVAL; + +#ifdef __BIG_ENDIAN__ + if (endian == OCXL_HOST_ENDIAN) + endian = OCXL_BIG_ENDIAN; +#endif + + switch (endian) { + case OCXL_BIG_ENDIAN: + tmp = readq_be((char *)afu->global_mmio_ptr + offset); + tmp |= mask; + writeq_be(tmp, (char *)afu->global_mmio_ptr + offset); + break; + + default: + tmp = readq((char *)afu->global_mmio_ptr + offset); + tmp |= mask; + writeq(tmp, (char *)afu->global_mmio_ptr + offset); + break; + } + + return 0; +} +EXPORT_SYMBOL_GPL(ocxl_global_mmio_set64); + +int ocxl_global_mmio_clear32(struct ocxl_afu *afu, size_t offset, + enum ocxl_endian endian, u32 mask) +{ + u32 tmp; + + if (offset > afu->config.global_mmio_size - 4) + return -EINVAL; + +#ifdef __BIG_ENDIAN__ + if (endian == OCXL_HOST_ENDIAN) + endian = OCXL_BIG_ENDIAN; +#endif + + switch (endian) { + case OCXL_BIG_ENDIAN: + tmp = readl_be((char *)afu->global_mmio_ptr + offset); + tmp &= ~mask; + writel_be(tmp, (char *)afu->global_mmio_ptr + offset); + break; + + default: + tmp = readl((char *)afu->global_mmio_ptr + offset); + tmp &= ~mask; + writel(tmp, (char *)afu->global_mmio_ptr + offset); + break; + } + + + return 0; +} +EXPORT_SYMBOL_GPL(ocxl_global_mmio_clear32); + +int ocxl_global_mmio_clear64(struct ocxl_afu *afu, size_t offset, + enum ocxl_endian endian, u64 mask) +{ + u64 tmp; + + if (offset > afu->config.global_mmio_size - 8) + return -EINVAL; + +#ifdef __BIG_ENDIAN__ + if (endian == OCXL_HOST_ENDIAN) + endian = OCXL_BIG_ENDIAN; +#endif + + switch (endian) { + case OCXL_BIG_ENDIAN: + tmp = readq_be((char *)afu->global_mmio_ptr + offset); + tmp &= ~mask; + writeq_be(tmp, (char *)afu->global_mmio_ptr + offset); + break; + + default: + tmp = readq((char *)afu->global_mmio_ptr + offset); + tmp &= ~mask; + writeq(tmp, (char *)afu->global_mmio_ptr + offset); + break; + } + + writeq(tmp, (char *)afu->global_mmio_ptr + offset); + + return 0; +} +EXPORT_SYMBOL_GPL(ocxl_global_mmio_clear64); diff --git a/include/misc/ocxl.h b/include/misc/ocxl.h index dea93885a839..5c4b4916e6be 100644 --- a/include/misc/ocxl.h +++ b/include/misc/ocxl.h @@ -45,6 +45,12 @@ struct ocxl_fn_config { s8 max_afu_index; }; +enum ocxl_endian { + OCXL_BIG_ENDIAN = 0, /**< AFU data is big-endian */ + OCXL_LITTLE_ENDIAN = 1, /**< AFU data is little-endian */ + OCXL_HOST_ENDIAN = 2, /**< AFU data is the same endianness as the host */ +}; + // These are opaque outside the ocxl driver struct ocxl_afu; struct ocxl_fn; @@ -230,6 +236,110 @@ void ocxl_afu_set_private(struct ocxl_afu *afu, void *private); */ void *ocxl_afu_get_private(struct ocxl_afu *dev); +// Global MMIO +/** + * Read a 32 bit value from global MMIO + * + * @afu: The AFU + * @offset: The Offset from the start of MMIO + * @endian: the endianness that the MMIO data is in + * @val: returns the value + * + * Returns 0 for success, negative on error + */ +int ocxl_global_mmio_read32(struct ocxl_afu *afu, size_t offset, + enum ocxl_endian endian, u32 *val); + +/** + * Read a 64 bit value from global MMIO + * + * @afu: The AFU + * @offset: The Offset from the start of MMIO + * @endian: the endianness that the MMIO data is in + * @val: returns the value + * + * Returns 0 for success, negative on error + */ +int ocxl_global_mmio_read64(struct ocxl_afu *afu, size_t offset, + enum ocxl_endian endian, u64 *val); + +/** + * Write a 32 bit value to global MMIO + * + * @afu: The AFU + * @offset: The Offset from the start of MMIO + * @endian: the endianness that the MMIO data is in + * @val: The value to write + * + * Returns 0 for success, negative on error + */ +int ocxl_global_mmio_write32(struct ocxl_afu *afu, size_t offset, + enum ocxl_endian endian, u32 val); + +/** + * Write a 64 bit value to global MMIO + * + * @afu: The AFU + * @offset: The Offset from the start of MMIO + * @endian: the endianness that the MMIO data is in + * @val: The value to write + * + * Returns 0 for success, negative on error + */ +int ocxl_global_mmio_write64(struct ocxl_afu *afu, size_t offset, + enum ocxl_endian endian, u64 val); + +/** + * Set bits in a 32 bit global MMIO register + * + * @afu: The AFU + * @offset: The Offset from the start of MMIO + * @endian: the endianness that the MMIO data is in + * @mask: a mask of the bits to set + * + * Returns 0 for success, negative on error + */ +int ocxl_global_mmio_set32(struct ocxl_afu *afu, size_t offset, + enum ocxl_endian endian, u32 mask); + +/** + * Set bits in a 64 bit global MMIO register + * + * @afu: The AFU + * @offset: The Offset from the start of MMIO + * @endian: the endianness that the MMIO data is in + * @mask: a mask of the bits to set + * + * Returns 0 for success, negative on error + */ +int ocxl_global_mmio_set64(struct ocxl_afu *afu, size_t offset, + enum ocxl_endian endian, u64 mask); + +/** + * Set bits in a 32 bit global MMIO register + * + * @afu: The AFU + * @offset: The Offset from the start of MMIO + * @endian: the endianness that the MMIO data is in + * @mask: a mask of the bits to set + * + * Returns 0 for success, negative on error + */ +int ocxl_global_mmio_clear32(struct ocxl_afu *afu, size_t offset, + enum ocxl_endian endian, u32 mask); + +/** + * Set bits in a 64 bit global MMIO register + * + * @afu: The AFU + * @offset: The Offset from the start of MMIO + * @endian: the endianness that the MMIO data is in + * @mask: a mask of the bits to set + * + * Returns 0 for success, negative on error + */ +int ocxl_global_mmio_clear64(struct ocxl_afu *afu, size_t offset, + enum ocxl_endian endian, u64 mask); // Functions left here are for compatibility with the cxlflash driver -- 2.20.1