* Re: [PATCH] powerpc: add compile-time support for lbarx, lwarx
From: Gabriel Paubert @ 2020-11-08 20:01 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: linuxppc-dev, Nicholas Piggin
In-Reply-To: <0810564117125.202011.20201107114257.GG2672@gate.crashing.org>
On Sat, Nov 07, 2020 at 05:42:57AM -0600, Segher Boessenkool wrote:
> On Sat, Nov 07, 2020 at 08:12:13AM +0100, Gabriel Paubert wrote:
> > On Sat, Nov 07, 2020 at 01:23:28PM +1000, Nicholas Piggin wrote:
> > > ISA v2.06 (POWER7 and up) as well as e6500 support lbarx and lwarx.
> >
> > Hmm, lwarx exists since original Power AFAIR,
>
> Almost: it was new on PowerPC.
I stand corrected. Does this mean that Power1 (and 2 I believe) had
no SMP support?
Gabriel
^ permalink raw reply
* [RFC][PATCH 1/2] libnvdimm: Introduce ND_CMD_GET_STAT to retrieve nvdimm statistics
From: Vaibhav Jain @ 2020-11-08 21:15 UTC (permalink / raw)
To: linuxppc-dev, linux-nvdimm
Cc: Santosh Sivaraj, Aneesh Kumar K . V, Vaibhav Jain, Dan Williams,
Ira Weiny
Implement support for exposing generic nvdimm statistics via newly
introduced dimm-command ND_CMD_GET_STAT that can be handled by nvdimm
command handler function and provide values for these statistics back
to libnvdimm. Following generic nvdimm statistics are defined as an
enumeration in 'uapi/ndctl.h':
* "media_reads" : Number of media reads that have occurred since reboot.
* "media_writes" : Number of media writes that have occurred since reboot.
* "read_requests" : Number of read requests that have occurred since reboot.
* "write_requests" : Number of write requests that have occurred since reboot.
* "total_media_reads" : Total number of media reads that have occurred.
* "total_media_writes" : Total number of media writes that have occurred.
* "total_read_requests" : Total number of read requests that have occurred.
* "total_write_requests" : Total number of write requests that have occurred.
Apart from ND_CMD_GET_STAT ioctl these nvdimm statistics are also
exposed via sysfs '<nvdimm-device>/stats' directory for easy user-space
access like below:
/sys/class/nd/ndctl0/device/nmem0/stats # tail -n +1 *
==> media_reads <==
252197707602
==> media_writes <==
20684685172
==> read_requests <==
658810924962
==> write_requests <==
404464081574
In case a specific nvdimm-statistic is not supported than nvdimm
command handler function can simply return an error (e.g -ENOENT) for
request to read that nvdimm-statistic.
The value for a specific nvdimm-stat is exchanged via newly introduced
'struct nd_cmd_get_dimm_stat' that hold a single statistics and a
union of possible values types. Presently only '__s64' type of generic
attributes are supported. These attributes are defined in
'ndvimm/dimm_devs.c' via a helper macro 'NVDIMM_STAT_ATTR'.
Signed-off-by: Vaibhav Jain <vaibhav@linux.ibm.com>
---
drivers/nvdimm/bus.c | 6 ++
drivers/nvdimm/dimm_devs.c | 109 +++++++++++++++++++++++++++++++++++++
drivers/nvdimm/nd.h | 5 ++
include/uapi/linux/ndctl.h | 27 +++++++++
4 files changed, 147 insertions(+)
diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
index 2304c6183822..d53564477437 100644
--- a/drivers/nvdimm/bus.c
+++ b/drivers/nvdimm/bus.c
@@ -794,6 +794,12 @@ static const struct nd_cmd_desc __nd_cmd_dimm_descs[] = {
.out_num = 1,
.out_sizes = { UINT_MAX, },
},
+ [ND_CMD_GET_STAT] = {
+ .in_num = 1,
+ .in_sizes = { sizeof(struct nd_cmd_get_dimm_stat), },
+ .out_num = 1,
+ .out_sizes = { sizeof(struct nd_cmd_get_dimm_stat), },
+ },
};
const struct nd_cmd_desc *nd_cmd_dimm_desc(int cmd)
diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c
index b59032e0859b..68aaa294def7 100644
--- a/drivers/nvdimm/dimm_devs.c
+++ b/drivers/nvdimm/dimm_devs.c
@@ -555,6 +555,114 @@ static umode_t nvdimm_firmware_visible(struct kobject *kobj, struct attribute *a
return a->mode;
}
+/* Request a dimm stat from the bus driver */
+static int __request_dimm_stat(struct nvdimm_bus *nvdimm_bus,
+ struct nvdimm *dimm, u64 stat_id,
+ s64 *stat_val)
+{
+ struct nvdimm_bus_descriptor *nd_desc = nvdimm_bus->nd_desc;
+ struct nd_cmd_get_dimm_stat stat = { .stat_id = stat_id };
+ int rc, cmd_rc;
+
+ if (!test_bit(ND_CMD_GET_STAT, &dimm->cmd_mask)) {
+ pr_debug("CMD_GET_STAT not set for bus driver 0x%lx\n",
+ nd_desc->cmd_mask);
+ return -ENOENT;
+ }
+
+ /* Is stat requested is known & bus driver supports fetching stats */
+ if (stat_id <= ND_DIMM_STAT_INVALID || stat_id > ND_DIMM_STAT_MAX) {
+ WARN(1, "Unknown stat-id(%llu) requested", stat_id);
+ return -ENOENT;
+ }
+
+ /* Ask bus driver for its stat value */
+ rc = nd_desc->ndctl(nd_desc, dimm, ND_CMD_GET_STAT,
+ &stat, sizeof(stat), &cmd_rc);
+ if (rc || cmd_rc) {
+ pr_debug("Unable to request stat %lld. Error (%d,%d)\n",
+ stat_id, rc, cmd_rc);
+ return rc ? rc : cmd_rc;
+ }
+
+ /* Indicate error in case returned struct doesn't have the stat_id set */
+ if (stat.stat_id != stat_id) {
+ pr_debug("Invalid statid %llu returned\n", stat.stat_id);
+ return -ENOENT;
+ }
+
+ *stat_val = stat.int_val;
+ return 0;
+}
+
+static ssize_t nvdimm_stat_attr_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct nvdimm_stat_attr *nattr = container_of(attr, typeof(*nattr), attr);
+ struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev);
+ struct nvdimm *nvdimm = to_nvdimm(dev);
+ s64 stat_val;
+ int rc;
+
+ rc = __request_dimm_stat(nvdimm_bus, nvdimm, nattr->stat_id, &stat_val);
+
+ if (rc)
+ return rc;
+
+ return snprintf(buf, PAGE_SIZE, "%lld", stat_val);
+}
+
+static umode_t nvdimm_stats_visible(struct kobject *kobj, struct attribute *a, int n)
+{
+ struct nvdimm_stat_attr *nattr = container_of(a, typeof(*nattr), attr.attr);
+ struct device *dev = container_of(kobj, typeof(*dev), kobj);
+ struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev);
+ struct nvdimm *nvdimm = to_nvdimm(dev);
+ u64 stat_val;
+ int rc;
+
+ /* request dimm stat from bus driver and is success mark attribute as visible */
+ rc = __request_dimm_stat(nvdimm_bus, nvdimm, nattr->stat_id, &stat_val);
+ if (rc)
+ pr_info("Unable to query stat %llu . Error(%d)\n", nattr->stat_id, rc);
+
+ return rc ? 0 : a->mode;
+}
+
+#define NVDIMM_STAT_ATTR(_name, _stat_id) \
+ struct nvdimm_stat_attr nvdimm_stat_attr_##_name = { \
+ .attr = __ATTR(_name, 0400, nvdimm_stat_attr_show, NULL), \
+ .stat_id = _stat_id, \
+ }
+
+static NVDIMM_STAT_ATTR(media_reads, ND_DIMM_STAT_MEDIA_READS);
+static NVDIMM_STAT_ATTR(media_writes, ND_DIMM_STAT_MEDIA_WRITES);
+static NVDIMM_STAT_ATTR(read_requests, ND_DIMM_STAT_READ_REQUESTS);
+static NVDIMM_STAT_ATTR(write_requests, ND_DIMM_STAT_WRITE_REQUESTS);
+static NVDIMM_STAT_ATTR(total_media_reads, ND_DIMM_STAT_TOTAL_MEDIA_READS);
+static NVDIMM_STAT_ATTR(total_media_writes, ND_DIMM_STAT_TOTAL_MEDIA_WRITES);
+static NVDIMM_STAT_ATTR(total_read_requests, ND_DIMM_STAT_TOTAL_READ_REQUESTS);
+static NVDIMM_STAT_ATTR(total_write_requests, ND_DIMM_STAT_TOTAL_WRITE_REQUESTS);
+
+static struct attribute *nvdimm_stats_attributes[] = {
+ &nvdimm_stat_attr_media_reads.attr.attr,
+ &nvdimm_stat_attr_media_writes.attr.attr,
+ &nvdimm_stat_attr_read_requests.attr.attr,
+ &nvdimm_stat_attr_write_requests.attr.attr,
+ &nvdimm_stat_attr_total_media_reads.attr.attr,
+ &nvdimm_stat_attr_total_media_writes.attr.attr,
+ &nvdimm_stat_attr_total_read_requests.attr.attr,
+ &nvdimm_stat_attr_total_write_requests.attr.attr,
+ NULL,
+};
+
+static const struct attribute_group nvdimm_stats_group = {
+ .name = "stats",
+ .attrs = nvdimm_stats_attributes,
+ .is_visible = nvdimm_stats_visible,
+};
+
static const struct attribute_group nvdimm_firmware_attribute_group = {
.name = "firmware",
.attrs = nvdimm_firmware_attributes,
@@ -565,6 +673,7 @@ static const struct attribute_group *nvdimm_attribute_groups[] = {
&nd_device_attribute_group,
&nvdimm_attribute_group,
&nvdimm_firmware_attribute_group,
+ &nvdimm_stats_group,
NULL,
};
diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
index 696b55556d4d..ea9e846ae245 100644
--- a/drivers/nvdimm/nd.h
+++ b/drivers/nvdimm/nd.h
@@ -223,6 +223,11 @@ enum nd_async_mode {
ND_ASYNC,
};
+struct nvdimm_stat_attr {
+ struct device_attribute attr;
+ u64 stat_id;
+};
+
int nd_integrity_init(struct gendisk *disk, unsigned long meta_size);
void wait_nvdimm_bus_probe_idle(struct device *dev);
void nd_device_register(struct device *dev);
diff --git a/include/uapi/linux/ndctl.h b/include/uapi/linux/ndctl.h
index 8cf1e4884fd5..81b76986b423 100644
--- a/include/uapi/linux/ndctl.h
+++ b/include/uapi/linux/ndctl.h
@@ -97,6 +97,31 @@ struct nd_cmd_clear_error {
__u64 cleared;
} __packed;
+/* Various generic dimm stats that can be reported */
+enum {
+ ND_DIMM_STAT_INVALID = 0,
+ ND_DIMM_STAT_MEDIA_READS = 1, /* Media reads after power cycle */
+ ND_DIMM_STAT_MEDIA_WRITES = 2, /* Media writes after power cycle */
+ ND_DIMM_STAT_READ_REQUESTS = 3, /* Read requests after power cycle */
+ ND_DIMM_STAT_WRITE_REQUESTS = 4, /* Write requests after power cycle */
+ ND_DIMM_STAT_TOTAL_MEDIA_READS = 5, /* Total Media Reads */
+ ND_DIMM_STAT_TOTAL_MEDIA_WRITES = 6, /* Total Media Writes */
+ ND_DIMM_STAT_TOTAL_READ_REQUESTS = 7, /* Total Read Requests */
+ ND_DIMM_STAT_TOTAL_WRITE_REQUESTS = 8, /* Total Write Requests */
+ ND_DIMM_STAT_MAX = 8,
+};
+
+struct nd_cmd_get_dimm_stat {
+ /* See enum above for valid values */
+ __u64 stat_id;
+
+ /* Holds a single dimm stat value */
+ union {
+ __s64 int_val;
+ char str_val[120];
+ };
+} __packed;
+
enum {
ND_CMD_IMPLEMENTED = 0,
@@ -117,6 +142,7 @@ enum {
ND_CMD_VENDOR_EFFECT_LOG = 8,
ND_CMD_VENDOR = 9,
ND_CMD_CALL = 10,
+ ND_CMD_GET_STAT = 11,
};
enum {
@@ -151,6 +177,7 @@ static inline const char *nvdimm_cmd_name(unsigned cmd)
case ND_CMD_VENDOR_EFFECT_LOG: return "effect_log";
case ND_CMD_VENDOR: return "vendor";
case ND_CMD_CALL: return "cmd_call";
+ case ND_CMD_GET_STAT: return "get_stat";
default: return "unknown";
}
}
--
2.28.0
^ permalink raw reply related
* [RFC][PATCH 2/2] powerpc/papr_scm: Implement support for reporting generic nvdimm stats
From: Vaibhav Jain @ 2020-11-08 21:15 UTC (permalink / raw)
To: linuxppc-dev, linux-nvdimm
Cc: Santosh Sivaraj, Aneesh Kumar K . V, Vaibhav Jain, Dan Williams,
Ira Weiny
In-Reply-To: <20201108211549.122018-1-vaibhav@linux.ibm.com>
Add support for reporting papr-scm supported generic nvdimm stats by
implementing support for handling ND_CMD_GET_STAT in
'papr_scm_ndctl().
The mapping between libnvdimm generic nvdimm-stats and papr-scm
specific performance-stats is embedded inside 'dimm_stats_map[]'. This
array is queried by newly introduced 'papr_scm_get_stat()' that
verifies if the requested nvdimm-stat is supported and if yes does an
hcall via 'drc_pmem_query_stat()' to request the performance-stat and
return it back to libnvdimm.
Signed-off-by: Vaibhav Jain <vaibhav@linux.ibm.com>
---
arch/powerpc/platforms/pseries/papr_scm.c | 66 ++++++++++++++++++++++-
1 file changed, 65 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
index 835163f54244..51eeab3376fd 100644
--- a/arch/powerpc/platforms/pseries/papr_scm.c
+++ b/arch/powerpc/platforms/pseries/papr_scm.c
@@ -25,7 +25,8 @@
((1ul << ND_CMD_GET_CONFIG_SIZE) | \
(1ul << ND_CMD_GET_CONFIG_DATA) | \
(1ul << ND_CMD_SET_CONFIG_DATA) | \
- (1ul << ND_CMD_CALL))
+ (1ul << ND_CMD_CALL) | \
+ (1ul << ND_CMD_GET_STAT))
/* DIMM health bitmap bitmap indicators */
/* SCM device is unable to persist memory contents */
@@ -120,6 +121,16 @@ struct papr_scm_priv {
static LIST_HEAD(papr_nd_regions);
static DEFINE_MUTEX(papr_ndr_lock);
+/* Map generic nvdimm stats to papr-scm stats */
+static const char * const dimm_stat_map[] = {
+ [ND_DIMM_STAT_INVALID] = NULL,
+ [ND_DIMM_STAT_MEDIA_READS] = "MedRCnt ",
+ [ND_DIMM_STAT_MEDIA_WRITES] = "MedWCnt ",
+ [ND_DIMM_STAT_READ_REQUESTS] = "HostLCnt",
+ [ND_DIMM_STAT_WRITE_REQUESTS] = "HostSCnt",
+ [ND_DIMM_STAT_MAX] = NULL,
+};
+
static int drc_pmem_bind(struct papr_scm_priv *p)
{
unsigned long ret[PLPAR_HCALL_BUFSIZE];
@@ -728,6 +739,54 @@ static int papr_scm_service_pdsm(struct papr_scm_priv *p,
return pdsm_pkg->cmd_status;
}
+/*
+ * For a given pdsm request call an appropriate service function.
+ * Returns errors if any while handling the pdsm command package.
+ */
+static int papr_scm_get_stat(struct papr_scm_priv *p,
+ struct nd_cmd_get_dimm_stat *dimm_stat)
+
+{
+ int rc;
+ ssize_t size;
+ struct papr_scm_perf_stat *stat;
+ struct papr_scm_perf_stats *stats;
+
+ /* Check if the requested stat-id is supported */
+ if (dimm_stat->stat_id >= ARRAY_SIZE(dimm_stat_map) ||
+ !dimm_stat_map[dimm_stat->stat_id]) {
+ dev_dbg(&p->pdev->dev, "Invalid stat-id %lld\n", dimm_stat->stat_id);
+ return -ENOSPC;
+ }
+
+ /* Allocate request buffer enough to hold single performance stat */
+ size = sizeof(struct papr_scm_perf_stats) +
+ sizeof(struct papr_scm_perf_stat);
+
+ stats = kzalloc(size, GFP_KERNEL);
+ if (!stats)
+ return -ENOMEM;
+
+ stat = &stats->scm_statistic[0];
+ memcpy(&stat->stat_id, dimm_stat_map[dimm_stat->stat_id],
+ sizeof(stat->stat_id));
+ stat->stat_val = 0;
+
+ /* Fetch the statistic from PHYP and copy it to provided payload */
+ rc = drc_pmem_query_stats(p, stats, 1);
+ if (rc < 0) {
+ dev_dbg(&p->pdev->dev, "Err(%d) fetching stat '%.8s'\n",
+ rc, stat->stat_id);
+ kfree(stats);
+ return rc;
+ }
+
+ dimm_stat->int_val = be64_to_cpu(stat->stat_val);
+
+ kfree(stats);
+ return 0;
+}
+
static int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc,
struct nvdimm *nvdimm, unsigned int cmd, void *buf,
unsigned int buf_len, int *cmd_rc)
@@ -772,6 +831,11 @@ static int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc,
*cmd_rc = papr_scm_service_pdsm(p, call_pkg);
break;
+ case ND_CMD_GET_STAT:
+ *cmd_rc = papr_scm_get_stat(p,
+ (struct nd_cmd_get_dimm_stat *)buf);
+ break;
+
default:
dev_dbg(&p->pdev->dev, "Unknown command = %d\n", cmd);
return -EINVAL;
--
2.28.0
^ permalink raw reply related
* Re: [PATCH v2 20/39] docs: ABI: testing: make the files compatible with ReST output
From: Jonathan Cameron @ 2020-11-08 16:56 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: Gautham R. Shenoy, Jason A. Donenfeld, Heikki Krogerus,
Peter Meerwald-Stadler, Petr Mladek, Linux Doc Mailing List,
Alexander Shishkin, Nayna Jain, Jonathan Cameron,
Alexandre Belloni, Mimi Zohar, Sebastian Reichel, linux-mm,
Bruno Meneguele, Vishal Verma, Pavel Machek, Hanjun Guo,
Guenter Roeck, netdev, Oleh Kravchenko, Dan Williams,
Andrew Donnellan, Javier González, Fabrice Gasnier,
Mark Gross, linux-acpi, Jonathan Corbet, Chunyan Zhang,
Mario Limonciello, linux-stm32, Lakshmi Ramasubramanian,
Ludovic Desroches, Pawan Gupta, linux-arm-kernel, Tom Rix,
Frederic Barrat, Niklas Cassel, Len Brown, Juergen Gross,
linuxppc-dev, Mika Westerberg, Alexandre Torgue, linux-pm,
linux-kernel, Richard Cochran, Oded Gabbay, Baolin Wang,
Lars-Peter Clausen, Dan Murphy, Orson Zhai, Philippe Bergheaud,
xen-devel, Boris Ostrovsky, Andy Shevchenko, Benson Leung,
Konstantin Khlebnikov, Jens Axboe, Felipe Balbi, Kranthi Kuntala,
Martin K. Petersen, Greg Kroah-Hartman, linux-usb,
Rafael J. Wysocki, Nicolas Ferre, linux-iio, Thinh Nguyen,
Sergey Senozhatsky, Stefano Stabellini, Thomas Gleixner,
Leonid Maksymchuk, Maxime Coquelin, Johannes Thumshirn,
Enric Balletbo i Serra, Vaibhav Jain, Vineela Tummalapalli,
Peter Rosin, Mike Kravetz
In-Reply-To: <20201102154250.45bee17f@coco.lan>
On Mon, 2 Nov 2020 15:42:50 +0100
Mauro Carvalho Chehab <mchehab+huawei@kernel.org> wrote:
> Em Mon, 2 Nov 2020 13:46:41 +0100
> Greg Kroah-Hartman <gregkh@linuxfoundation.org> escreveu:
>
> > On Mon, Nov 02, 2020 at 12:04:36PM +0100, Fabrice Gasnier wrote:
> > > On 10/30/20 11:09 AM, Mauro Carvalho Chehab wrote:
> > > > Em Fri, 30 Oct 2020 10:19:12 +0100
> > > > Fabrice Gasnier <fabrice.gasnier@st.com> escreveu:
> > > >
> > > >> Hi Mauro,
> > > >>
> > > >> [...]
> > > >>
> > > >>>
> > > >>> +What: /sys/bus/iio/devices/iio:deviceX/in_count_quadrature_mode_available
> > > >>> +KernelVersion: 4.12
> > > >>> +Contact: benjamin.gaignard@st.com
> > > >>> +Description:
> > > >>> + Reading returns the list possible quadrature modes.
> > > >>> +
> > > >>> +What: /sys/bus/iio/devices/iio:deviceX/in_count0_quadrature_mode
> > > >>> +KernelVersion: 4.12
> > > >>> +Contact: benjamin.gaignard@st.com
> > > >>> +Description:
> > > >>> + Configure the device counter quadrature modes:
> > > >>> +
> > > >>> + channel_A:
> > > >>> + Encoder A input servers as the count input and B as
> > > >>> + the UP/DOWN direction control input.
> > > >>> +
> > > >>> + channel_B:
> > > >>> + Encoder B input serves as the count input and A as
> > > >>> + the UP/DOWN direction control input.
> > > >>> +
> > > >>> + quadrature:
> > > >>> + Encoder A and B inputs are mixed to get direction
> > > >>> + and count with a scale of 0.25.
> > > >>> +
> > > >>
> > > >
> > > > Hi Fabrice,
> > > >
> > > >> I just noticed that since Jonathan question in v1.
> > > >>
> > > >> Above ABI has been moved in the past as discussed in [1]. You can take a
> > > >> look at:
> > > >> b299d00 IIO: stm32: Remove quadrature related functions from trigger driver
> > > >>
> > > >> Could you please remove the above chunk ?
> > > >>
> > > >> With that, for the stm32 part:
> > > >> Acked-by: Fabrice Gasnier <fabrice.gasnier@st.com>
> > > >
> > > >
> > > > Hmm... probably those were re-introduced due to a rebase. This
> > > > series were originally written about 1,5 years ago.
> > > >
> > > > I'll drop those hunks.
> > >
> > > Hi Mauro, Greg,
> > >
> > > I just figured out this patch has been applied with above hunk.
> > >
> > > This should be dropped: is there a fix on its way already ?
> > > (I may have missed it)
> >
> > Can you send a fix for just this hunk?
>
> Hmm...
>
> $ git grep /sys/bus/iio/devices/iio:deviceX/in_count_quadrature_mode_available
> Documentation/ABI/testing/sysfs-bus-iio-counter-104-quad-8:What: /sys/bus/iio/devices/iio:deviceX/in_count_quadrature_mode_available
> Documentation/ABI/testing/sysfs-bus-iio-lptimer-stm32:What: /sys/bus/iio/devices/iio:deviceX/in_count_quadrature_mode_available
> Documentation/ABI/testing/sysfs-bus-iio-timer-stm32:What: /sys/bus/iio/devices/iio:deviceX/in_count_quadrature_mode_available
>
> Even re-doing the changes from
> changeset b299d00420e2 ("IIO: stm32: Remove quadrature related functions from trigger driver")
> at Documentation/ABI/testing/sysfs-bus-iio-timer-stm32, there's still
> a third duplicate of some of those, as reported by the script:
>
> $ ./scripts/get_abi.pl validate 2>&1|grep quadra
> Warning: /sys/bus/iio/devices/iio:deviceX/in_count0_quadrature_mode is defined 2 times: Documentation/ABI/testing/sysfs-bus-iio-timer-stm32:117 Documentation/ABI/testing/sysfs-bus-iio-lptimer-stm32:14
> Warning: /sys/bus/iio/devices/iio:deviceX/in_count_quadrature_mode_available is defined 3 times: Documentation/ABI/testing/sysfs-bus-iio-counter-104-quad-8:2 Documentation/ABI/testing/sysfs-bus-iio-timer-stm32:111 Documentation/ABI/testing/sysfs-bus-iio-lptimer-stm32:8
>
> As in_count_quadrature_mode_available is also defined at:
> Documentation/ABI/testing/sysfs-bus-iio-counter-104-quad-8:2
>
> The best here seems to have a patch that will also drop the other
> duplication of this, probably moving in_count_quadrature_mode_available
> to a generic node probably placing it inside
> Documentation/ABI/testing/sysfs-bus-iio.
In this particular case it may be valid to do that, but it's not in
general without loosing information - see below.
>
> Comments?
>
> Thanks,
> Mauro
>
> PS.: the IIO subsystem is the one that currently has more duplicated
> ABI entries:
That was intentional. Often these provide more information on the
ABI for a particular device than is present in the base ABI doc.
A bit like when we have additional description for dt binding properties
for a particular device, even though they are standard properties.
Often a standard property allows for more values than the specific
one for a particular device. There can also be obscuring coupling
between sysfs attributes due to hardware restrictions that we would
like to provide some explanatory info on.
I suppose we could add all this information to the parent doc but
that is pretty ugly and will make that doc very nasty to read.
Jonathan
>
> $ ./scripts/get_abi.pl validate 2>&1|grep iio
> Warning: /sys/bus/iio/devices/iio:deviceX/in_accel_x_calibbias is defined 2 times: Documentation/ABI/testing/sysfs-bus-iio-icm42600:0 Documentation/ABI/testing/sysfs-bus-iio:394
> Warning: /sys/bus/iio/devices/iio:deviceX/in_accel_y_calibbias is defined 2 times: Documentation/ABI/testing/sysfs-bus-iio-icm42600:1 Documentation/ABI/testing/sysfs-bus-iio:395
> Warning: /sys/bus/iio/devices/iio:deviceX/in_accel_z_calibbias is defined 2 times: Documentation/ABI/testing/sysfs-bus-iio-icm42600:2 Documentation/ABI/testing/sysfs-bus-iio:396
> Warning: /sys/bus/iio/devices/iio:deviceX/in_anglvel_x_calibbias is defined 2 times: Documentation/ABI/testing/sysfs-bus-iio-icm42600:3 Documentation/ABI/testing/sysfs-bus-iio:397
> Warning: /sys/bus/iio/devices/iio:deviceX/in_anglvel_y_calibbias is defined 2 times: Documentation/ABI/testing/sysfs-bus-iio-icm42600:4 Documentation/ABI/testing/sysfs-bus-iio:398
> Warning: /sys/bus/iio/devices/iio:deviceX/in_anglvel_z_calibbias is defined 2 times: Documentation/ABI/testing/sysfs-bus-iio-icm42600:5 Documentation/ABI/testing/sysfs-bus-iio:399
> Warning: /sys/bus/iio/devices/iio:deviceX/in_count0_preset is defined 2 times: Documentation/ABI/testing/sysfs-bus-iio-timer-stm32:100 Documentation/ABI/testing/sysfs-bus-iio-lptimer-stm32:0
> Warning: /sys/bus/iio/devices/iio:deviceX/in_count0_quadrature_mode is defined 2 times: Documentation/ABI/testing/sysfs-bus-iio-timer-stm32:117 Documentation/ABI/testing/sysfs-bus-iio-lptimer-stm32:14
> Warning: /sys/bus/iio/devices/iio:deviceX/in_count_quadrature_mode_available is defined 3 times: Documentation/ABI/testing/sysfs-bus-iio-counter-104-quad-8:2 Documentation/ABI/testing/sysfs-bus-iio-timer-stm32:111 Documentation/ABI/testing/sysfs-bus-iio-lptimer-stm32:8
> Warning: /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_frequency is defined 2 times: Documentation/ABI/testing/sysfs-bus-iio-frequency-adf4371:0 Documentation/ABI/testing/sysfs-bus-iio:599
> Warning: /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_powerdown is defined 2 times: Documentation/ABI/testing/sysfs-bus-iio-frequency-adf4371:36 Documentation/ABI/testing/sysfs-bus-iio:588
> Warning: /sys/bus/iio/devices/iio:deviceX/out_currentY_raw is defined 2 times: Documentation/ABI/testing/sysfs-bus-iio-light-lm3533-als:43 Documentation/ABI/testing/sysfs-bus-iio-health-afe440x:38
> Warning: /sys/bus/iio/devices/iio:deviceX/out_current_heater_raw is defined 2 times: Documentation/ABI/testing/sysfs-bus-iio-humidity-hdc2010:0 Documentation/ABI/testing/sysfs-bus-iio-humidity-hdc100x:0
> Warning: /sys/bus/iio/devices/iio:deviceX/out_current_heater_raw_available is defined 2 times: Documentation/ABI/testing/sysfs-bus-iio-humidity-hdc2010:1 Documentation/ABI/testing/sysfs-bus-iio-humidity-hdc100x:1
> Warning: /sys/bus/iio/devices/iio:deviceX/sensor_sensitivity is defined 2 times: Documentation/ABI/testing/sysfs-bus-iio-distance-srf08:0 Documentation/ABI/testing/sysfs-bus-iio-proximity-as3935:8
> Warning: /sys/bus/iio/devices/triggerX/sampling_frequency is defined 2 times: Documentation/ABI/testing/sysfs-bus-iio-timer-stm32:92 Documentation/ABI/testing/sysfs-bus-iio:45
^ permalink raw reply
* Re: [PATCH kernel v2] irq: Add reference counting to IRQ mappings
From: Thomas Gleixner @ 2020-11-08 23:07 UTC (permalink / raw)
To: Alexey Kardashevskiy, linuxppc-dev
Cc: Rob Herring, Marc Zyngier, linux-kernel, Qian Cai,
Cédric Le Goater, Frederic Barrat, Michal Suchánek,
David Gibson
In-Reply-To: <4ed56f8d-3fe4-2d5d-6ec4-139efc742cb2@ozlabs.ru>
On Fri, Nov 06 2020 at 14:06, Alexey Kardashevskiy wrote:
> Hi,
>
> This one seems to be broken in the domain associating part so please
> ignore it, I'll post v3 soon. Thanks,
When you do that please use a proper subject line:
[ PATCH vN ] $subsystem: Shortlog
and to find the subsystem string just run git log kernel/irq/irqdomain.c
for hints.
Thanks,
tglx
^ permalink raw reply
* [powerpc:fixes-test] BUILD SUCCESS 33fe43cfd9b1c20f6f9899b44bf04e91823ff1c9
From: kernel test robot @ 2020-11-09 0:45 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git fixes-test
branch HEAD: 33fe43cfd9b1c20f6f9899b44bf04e91823ff1c9 powerpc/8xx: Manage _PAGE_ACCESSED through APG bits in L1 entry
elapsed time: 4486m
configs tested: 152
configs skipped: 87
The following configs have been built successfully.
More configs may be tested in the coming days.
gcc tested configs:
arm defconfig
arm64 allyesconfig
arm64 defconfig
arm allyesconfig
arm allmodconfig
powerpc tqm8xx_defconfig
sh rsk7269_defconfig
sh sh7763rdp_defconfig
powerpc cm5200_defconfig
mips maltaup_defconfig
arm viper_defconfig
arm colibri_pxa300_defconfig
arm lpc18xx_defconfig
arm tct_hammer_defconfig
powerpc ebony_defconfig
powerpc mpc8313_rdb_defconfig
nios2 3c120_defconfig
sh r7780mp_defconfig
sparc defconfig
powerpc ep8248e_defconfig
powerpc lite5200b_defconfig
powerpc mpc834x_itx_defconfig
c6x defconfig
mips bmips_be_defconfig
sparc sparc32_defconfig
arm zeus_defconfig
arm pleb_defconfig
arm am200epdkit_defconfig
powerpc stx_gp3_defconfig
s390 debug_defconfig
arm mini2440_defconfig
arm versatile_defconfig
sh shmin_defconfig
powerpc mpc834x_mds_defconfig
c6x evmc6457_defconfig
arm tegra_defconfig
mips rt305x_defconfig
powerpc powernv_defconfig
powerpc taishan_defconfig
powerpc mpc7448_hpc2_defconfig
arm multi_v4t_defconfig
powerpc mpc836x_rdk_defconfig
mips malta_kvm_guest_defconfig
sh rsk7264_defconfig
arm lpd270_defconfig
powerpc allnoconfig
powerpc mpc837x_rdb_defconfig
arm hackkit_defconfig
arc haps_hs_smp_defconfig
riscv alldefconfig
arm s3c2410_defconfig
sh se7724_defconfig
ia64 generic_defconfig
mips capcella_defconfig
openrisc simple_smp_defconfig
mips ip27_defconfig
powerpc sequoia_defconfig
mips bcm47xx_defconfig
sh ecovec24_defconfig
arm moxart_defconfig
arm footbridge_defconfig
arm colibri_pxa270_defconfig
powerpc kmeter1_defconfig
sh se7722_defconfig
mips malta_kvm_defconfig
mips lemote2f_defconfig
powerpc ppc44x_defconfig
ia64 allmodconfig
ia64 defconfig
ia64 allyesconfig
m68k defconfig
m68k allmodconfig
m68k allyesconfig
nios2 defconfig
arc allyesconfig
nds32 allnoconfig
c6x allyesconfig
nds32 defconfig
nios2 allyesconfig
csky defconfig
alpha defconfig
alpha allyesconfig
xtensa allyesconfig
h8300 allyesconfig
arc defconfig
sh allmodconfig
parisc defconfig
s390 allyesconfig
parisc allyesconfig
s390 defconfig
i386 allyesconfig
sparc allyesconfig
i386 defconfig
mips allyesconfig
mips allmodconfig
powerpc allyesconfig
powerpc allmodconfig
i386 randconfig-a004-20201104
i386 randconfig-a006-20201104
i386 randconfig-a005-20201104
i386 randconfig-a001-20201104
i386 randconfig-a002-20201104
i386 randconfig-a003-20201104
i386 randconfig-a004-20201105
i386 randconfig-a006-20201105
i386 randconfig-a005-20201105
i386 randconfig-a001-20201105
i386 randconfig-a002-20201105
i386 randconfig-a003-20201105
x86_64 randconfig-a012-20201104
x86_64 randconfig-a015-20201104
x86_64 randconfig-a013-20201104
x86_64 randconfig-a011-20201104
x86_64 randconfig-a014-20201104
x86_64 randconfig-a016-20201104
i386 randconfig-a015-20201105
i386 randconfig-a013-20201105
i386 randconfig-a014-20201105
i386 randconfig-a016-20201105
i386 randconfig-a011-20201105
i386 randconfig-a012-20201105
i386 randconfig-a015-20201104
i386 randconfig-a013-20201104
i386 randconfig-a014-20201104
i386 randconfig-a016-20201104
i386 randconfig-a011-20201104
i386 randconfig-a012-20201104
x86_64 randconfig-a004-20201105
x86_64 randconfig-a003-20201105
x86_64 randconfig-a005-20201105
x86_64 randconfig-a002-20201105
x86_64 randconfig-a006-20201105
x86_64 randconfig-a001-20201105
riscv nommu_k210_defconfig
riscv allyesconfig
riscv nommu_virt_defconfig
riscv allnoconfig
riscv defconfig
riscv rv32_defconfig
riscv allmodconfig
x86_64 rhel
x86_64 allyesconfig
x86_64 rhel-7.6-kselftests
x86_64 defconfig
x86_64 rhel-8.3
x86_64 kexec
clang tested configs:
x86_64 randconfig-a004-20201104
x86_64 randconfig-a003-20201104
x86_64 randconfig-a005-20201104
x86_64 randconfig-a002-20201104
x86_64 randconfig-a006-20201104
x86_64 randconfig-a001-20201104
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
^ permalink raw reply
* [powerpc:next-test] BUILD SUCCESS fea97f268bc201789c3da74db7eb0c6313d17917
From: kernel test robot @ 2020-11-09 0:46 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next-test
branch HEAD: fea97f268bc201789c3da74db7eb0c6313d17917 powerpc: Use the common INIT_DATA_SECTION macro in vmlinux.lds.S
elapsed time: 4487m
configs tested: 163
configs skipped: 3
The following configs have been built successfully.
More configs may be tested in the coming days.
gcc tested configs:
arm defconfig
arm64 allyesconfig
arm64 defconfig
arm allyesconfig
arm allmodconfig
powerpc tqm8xx_defconfig
sh rsk7269_defconfig
sh sh7763rdp_defconfig
powerpc cm5200_defconfig
mips maltaup_defconfig
arm viper_defconfig
arm colibri_pxa300_defconfig
arm lpc18xx_defconfig
arm tct_hammer_defconfig
powerpc ebony_defconfig
powerpc mpc8313_rdb_defconfig
nios2 3c120_defconfig
sh r7780mp_defconfig
sparc defconfig
powerpc ep8248e_defconfig
powerpc lite5200b_defconfig
powerpc mpc834x_itx_defconfig
c6x defconfig
mips bmips_be_defconfig
sparc sparc32_defconfig
arm zeus_defconfig
arm pleb_defconfig
arm am200epdkit_defconfig
powerpc stx_gp3_defconfig
sh se7724_defconfig
mips nlm_xlr_defconfig
arm colibri_pxa270_defconfig
mips lemote2f_defconfig
s390 allyesconfig
s390 debug_defconfig
arm mini2440_defconfig
arm versatile_defconfig
sh shmin_defconfig
powerpc mpc834x_mds_defconfig
c6x evmc6457_defconfig
arm tegra_defconfig
mips rt305x_defconfig
powerpc powernv_defconfig
powerpc taishan_defconfig
powerpc mpc7448_hpc2_defconfig
arm multi_v4t_defconfig
powerpc mpc836x_rdk_defconfig
mips malta_kvm_guest_defconfig
sh rsk7264_defconfig
arm lpd270_defconfig
powerpc allnoconfig
powerpc mpc837x_rdb_defconfig
arm hackkit_defconfig
arc haps_hs_smp_defconfig
riscv alldefconfig
arm s3c2410_defconfig
ia64 generic_defconfig
mips capcella_defconfig
openrisc simple_smp_defconfig
nds32 alldefconfig
sh ap325rxa_defconfig
arm gemini_defconfig
arm xcep_defconfig
mips ath79_defconfig
mips ip27_defconfig
powerpc sequoia_defconfig
mips bcm47xx_defconfig
sh ecovec24_defconfig
arm moxart_defconfig
arm footbridge_defconfig
powerpc kmeter1_defconfig
sh se7722_defconfig
mips malta_kvm_defconfig
powerpc ppc44x_defconfig
ia64 allmodconfig
ia64 defconfig
ia64 allyesconfig
m68k allmodconfig
m68k defconfig
m68k allyesconfig
nios2 defconfig
arc allyesconfig
nds32 allnoconfig
c6x allyesconfig
nds32 defconfig
nios2 allyesconfig
csky defconfig
alpha defconfig
alpha allyesconfig
xtensa allyesconfig
h8300 allyesconfig
arc defconfig
sh allmodconfig
parisc defconfig
parisc allyesconfig
s390 defconfig
i386 allyesconfig
sparc allyesconfig
i386 defconfig
mips allyesconfig
mips allmodconfig
powerpc allyesconfig
powerpc allmodconfig
i386 randconfig-a004-20201104
i386 randconfig-a006-20201104
i386 randconfig-a005-20201104
i386 randconfig-a001-20201104
i386 randconfig-a002-20201104
i386 randconfig-a003-20201104
i386 randconfig-a004-20201105
i386 randconfig-a006-20201105
i386 randconfig-a005-20201105
i386 randconfig-a001-20201105
i386 randconfig-a002-20201105
i386 randconfig-a003-20201105
x86_64 randconfig-a012-20201104
x86_64 randconfig-a015-20201104
x86_64 randconfig-a013-20201104
x86_64 randconfig-a011-20201104
x86_64 randconfig-a014-20201104
x86_64 randconfig-a016-20201104
x86_64 randconfig-a012-20201106
x86_64 randconfig-a011-20201106
x86_64 randconfig-a013-20201106
x86_64 randconfig-a014-20201106
x86_64 randconfig-a016-20201106
i386 randconfig-a015-20201104
i386 randconfig-a013-20201104
i386 randconfig-a014-20201104
i386 randconfig-a016-20201104
i386 randconfig-a011-20201104
i386 randconfig-a012-20201104
i386 randconfig-a015-20201105
i386 randconfig-a013-20201105
i386 randconfig-a014-20201105
i386 randconfig-a016-20201105
i386 randconfig-a011-20201105
i386 randconfig-a012-20201105
x86_64 randconfig-a004-20201105
x86_64 randconfig-a003-20201105
x86_64 randconfig-a005-20201105
x86_64 randconfig-a002-20201105
x86_64 randconfig-a006-20201105
x86_64 randconfig-a001-20201105
riscv nommu_k210_defconfig
riscv allyesconfig
riscv allnoconfig
riscv defconfig
riscv allmodconfig
riscv nommu_virt_defconfig
riscv rv32_defconfig
x86_64 rhel
x86_64 allyesconfig
x86_64 rhel-7.6-kselftests
x86_64 defconfig
x86_64 rhel-8.3
x86_64 kexec
clang tested configs:
x86_64 randconfig-a004-20201104
x86_64 randconfig-a003-20201104
x86_64 randconfig-a005-20201104
x86_64 randconfig-a002-20201104
x86_64 randconfig-a006-20201104
x86_64 randconfig-a001-20201104
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
^ permalink raw reply
* Re: [PATCH v2 09/16] PCI: dwc: Rework MSI initialization
From: Jisheng Zhang @ 2020-11-09 2:53 UTC (permalink / raw)
To: Rob Herring
Cc: Roy Zang, Lorenzo Pieralisi, linux-pci, Minghuan Lian,
Murali Karicheri, linux-arm-kernel, Jingoo Han, Bjorn Helgaas,
Gustavo Pimentel, linuxppc-dev, Mingkai Hu
In-Reply-To: <20201105211159.1814485-10-robh@kernel.org>
On Thu, 5 Nov 2020 15:11:52 -0600
Rob Herring <robh@kernel.org> wrote:
> CAUTION: Email originated externally, do not click links or open attachments unless you recognize the sender and know the content is safe.
>
>
> There are 3 possible MSI implementations for the DWC host. The first is
> using the built-in DWC MSI controller. The 2nd is a custom MSI
> controller as part of the PCI host (keystone only). The 3rd is an
> external MSI controller (typically GICv3 ITS). Currently, the last 2
> are distinguished with a .msi_host_init() hook with the 3rd option using
> an empty function. However we can detect the 3rd case with the presence
> of 'msi-parent' or 'msi-map' properties, so let's do that instead and
> remove the empty functions.
>
> Cc: Murali Karicheri <m-karicheri2@ti.com>
> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Cc: Bjorn Helgaas <bhelgaas@google.com>
> Cc: Minghuan Lian <minghuan.Lian@nxp.com>
> Cc: Mingkai Hu <mingkai.hu@nxp.com>
> Cc: Roy Zang <roy.zang@nxp.com>
> Cc: Gustavo Pimentel <gustavo.pimentel@synopsys.com>
> Cc: linuxppc-dev@lists.ozlabs.org
> Acked-by: Jingoo Han <jingoohan1@gmail.com>
> Signed-off-by: Rob Herring <robh@kernel.org>
> ---
> drivers/pci/controller/dwc/pci-keystone.c | 9 -------
> drivers/pci/controller/dwc/pci-layerscape.c | 25 -------------------
> .../pci/controller/dwc/pcie-designware-host.c | 20 +++++++++------
> drivers/pci/controller/dwc/pcie-designware.h | 1 +
> drivers/pci/controller/dwc/pcie-intel-gw.c | 9 -------
> 5 files changed, 13 insertions(+), 51 deletions(-)
>
> diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
> index 9cf14f13798b..784385ae6074 100644
> --- a/drivers/pci/controller/dwc/pci-keystone.c
> +++ b/drivers/pci/controller/dwc/pci-keystone.c
> @@ -272,14 +272,6 @@ static void ks_pcie_handle_legacy_irq(struct keystone_pcie *ks_pcie,
> ks_pcie_app_writel(ks_pcie, IRQ_EOI, offset);
> }
>
> -/*
> - * Dummy function so that DW core doesn't configure MSI
> - */
> -static int ks_pcie_am654_msi_host_init(struct pcie_port *pp)
> -{
> - return 0;
> -}
> -
> static void ks_pcie_enable_error_irq(struct keystone_pcie *ks_pcie)
> {
> ks_pcie_app_writel(ks_pcie, ERR_IRQ_ENABLE_SET, ERR_IRQ_ALL);
> @@ -854,7 +846,6 @@ static const struct dw_pcie_host_ops ks_pcie_host_ops = {
>
> static const struct dw_pcie_host_ops ks_pcie_am654_host_ops = {
> .host_init = ks_pcie_host_init,
> - .msi_host_init = ks_pcie_am654_msi_host_init,
> };
>
> static irqreturn_t ks_pcie_err_irq_handler(int irq, void *priv)
> diff --git a/drivers/pci/controller/dwc/pci-layerscape.c b/drivers/pci/controller/dwc/pci-layerscape.c
> index 53e56d54c482..0d84986c4c16 100644
> --- a/drivers/pci/controller/dwc/pci-layerscape.c
> +++ b/drivers/pci/controller/dwc/pci-layerscape.c
> @@ -168,37 +168,12 @@ static int ls1021_pcie_host_init(struct pcie_port *pp)
> return ls_pcie_host_init(pp);
> }
>
> -static int ls_pcie_msi_host_init(struct pcie_port *pp)
> -{
> - struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> - struct device *dev = pci->dev;
> - struct device_node *np = dev->of_node;
> - struct device_node *msi_node;
> -
> - /*
> - * The MSI domain is set by the generic of_msi_configure(). This
> - * .msi_host_init() function keeps us from doing the default MSI
> - * domain setup in dw_pcie_host_init() and also enforces the
> - * requirement that "msi-parent" exists.
> - */
> - msi_node = of_parse_phandle(np, "msi-parent", 0);
> - if (!msi_node) {
> - dev_err(dev, "failed to find msi-parent\n");
> - return -EINVAL;
> - }
> -
> - of_node_put(msi_node);
> - return 0;
> -}
> -
> static const struct dw_pcie_host_ops ls1021_pcie_host_ops = {
> .host_init = ls1021_pcie_host_init,
> - .msi_host_init = ls_pcie_msi_host_init,
> };
>
> static const struct dw_pcie_host_ops ls_pcie_host_ops = {
> .host_init = ls_pcie_host_init,
> - .msi_host_init = ls_pcie_msi_host_init,
> };
>
> static const struct dw_pcie_ops dw_ls1021_pcie_ops = {
> diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
> index 95deef0eaadf..9b952639d020 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-host.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
> @@ -365,6 +365,10 @@ int dw_pcie_host_init(struct pcie_port *pp)
> pci->link_gen = of_pci_get_max_link_speed(np);
>
> if (pci_msi_enabled()) {
> + pp->has_msi_ctrl = !(pp->ops->msi_host_init ||
> + of_property_read_bool(np, "msi-parent") ||
> + of_property_read_bool(np, "msi-map"));
> +
> if (!pp->num_vectors) {
> pp->num_vectors = MSI_DEF_NUM_VECTORS;
> } else if (pp->num_vectors > MAX_MSI_IRQS) {
> @@ -372,7 +376,11 @@ int dw_pcie_host_init(struct pcie_port *pp)
> return -EINVAL;
> }
>
> - if (!pp->ops->msi_host_init) {
> + if (pp->ops->msi_host_init) {
> + ret = pp->ops->msi_host_init(pp);
> + if (ret < 0)
> + return ret;
> + } else if (pp->has_msi_ctrl) {
> if (!pp->msi_irq) {
> pp->msi_irq = platform_get_irq_byname_optional(pdev, "msi");
> if (pp->msi_irq < 0) {
> @@ -402,10 +410,6 @@ int dw_pcie_host_init(struct pcie_port *pp)
> pp->msi_data = 0;
> goto err_free_msi;
> }
> - } else {
> - ret = pp->ops->msi_host_init(pp);
> - if (ret < 0)
> - return ret;
> }
> }
>
> @@ -426,7 +430,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
> return 0;
>
> err_free_msi:
> - if (pci_msi_enabled() && !pp->ops->msi_host_init)
> + if (pp->has_msi_ctrl)
> dw_pcie_free_msi(pp);
> return ret;
> }
> @@ -436,7 +440,7 @@ void dw_pcie_host_deinit(struct pcie_port *pp)
> {
> pci_stop_root_bus(pp->bridge->bus);
> pci_remove_root_bus(pp->bridge->bus);
> - if (pci_msi_enabled() && !pp->ops->msi_host_init)
> + if (pp->has_msi_ctrl)
> dw_pcie_free_msi(pp);
> }
> EXPORT_SYMBOL_GPL(dw_pcie_host_deinit);
> @@ -544,7 +548,7 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
>
> dw_pcie_setup(pci);
>
> - if (pci_msi_enabled() && !pp->ops->msi_host_init) {
> + if (pp->has_msi_ctrl) {
> num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL;
>
> /* Initialize IRQ Status array */
> diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
> index 96382dcb2859..5d374bab10d1 100644
> --- a/drivers/pci/controller/dwc/pcie-designware.h
> +++ b/drivers/pci/controller/dwc/pcie-designware.h
> @@ -175,6 +175,7 @@ struct dw_pcie_host_ops {
> };
>
> struct pcie_port {
> + bool has_msi_ctrl:1;
Can we relocate has_msi_ctrl? e.g put it at the end of the pcie_port structure.
Thanks
> u64 cfg0_base;
> void __iomem *va_cfg0_base;
> u32 cfg0_size;
> diff --git a/drivers/pci/controller/dwc/pcie-intel-gw.c b/drivers/pci/controller/dwc/pcie-intel-gw.c
> index c562eb7454b1..292b9de86532 100644
> --- a/drivers/pci/controller/dwc/pcie-intel-gw.c
> +++ b/drivers/pci/controller/dwc/pcie-intel-gw.c
> @@ -385,14 +385,6 @@ static int intel_pcie_rc_init(struct pcie_port *pp)
> return intel_pcie_host_setup(lpp);
> }
>
> -/*
> - * Dummy function so that DW core doesn't configure MSI
> - */
> -static int intel_pcie_msi_init(struct pcie_port *pp)
> -{
> - return 0;
> -}
> -
> static u64 intel_pcie_cpu_addr(struct dw_pcie *pcie, u64 cpu_addr)
> {
> return cpu_addr + BUS_IATU_OFFSET;
> @@ -404,7 +396,6 @@ static const struct dw_pcie_ops intel_pcie_ops = {
>
> static const struct dw_pcie_host_ops intel_pcie_dw_ops = {
> .host_init = intel_pcie_rc_init,
> - .msi_host_init = intel_pcie_msi_init,
> };
>
> static const struct intel_pcie_soc pcie_data = {
> --
> 2.25.1
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
>
^ permalink raw reply
* [PATCH] sched/rt, powerpc: Prepare for PREEMPT_RT
From: Wang Qing @ 2020-11-09 3:40 UTC (permalink / raw)
To: Michael Ellerman, Benjamin Herrenschmidt, Paul Mackerras,
Nicholas Piggin, Christophe Leroy, Alistair Popple, Jordan Niethe,
Aneesh Kumar K.V, Wang Qing, Greg Kroah-Hartman, Peter Zijlstra,
linuxppc-dev, linux-kernel
Cc: tglx
Add PREEMPT_RT output to die().
Signed-off-by: Wang Qing <wangqing@vivo.com>
---
arch/powerpc/kernel/traps.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 5006dcb..6dfe567
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -258,6 +258,14 @@ static char *get_mmu_str(void)
return "";
}
+#ifdef CONFIG_PREEMPT
+#define S_PREEMPT " PREEMPT"
+#elif defined(CONFIG_PREEMPT_RT)
+#define S_PREEMPT " PREEMPT_RT"
+#else
+#define S_PREEMPT ""
+#endif
+
static int __die(const char *str, struct pt_regs *regs, long err)
{
printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter);
@@ -265,7 +273,7 @@ static int __die(const char *str, struct pt_regs *regs, long err)
printk("%s PAGE_SIZE=%luK%s%s%s%s%s%s %s\n",
IS_ENABLED(CONFIG_CPU_LITTLE_ENDIAN) ? "LE" : "BE",
PAGE_SIZE / 1024, get_mmu_str(),
- IS_ENABLED(CONFIG_PREEMPT) ? " PREEMPT" : "",
+ S_PREEMPT,
IS_ENABLED(CONFIG_SMP) ? " SMP" : "",
IS_ENABLED(CONFIG_SMP) ? (" NR_CPUS=" __stringify(NR_CPUS)) : "",
debug_pagealloc_enabled() ? " DEBUG_PAGEALLOC" : "",
--
2.7.4
^ permalink raw reply related
* Re: [PATCH] sched/rt, powerpc: Prepare for PREEMPT_RT
From: Greg Kroah-Hartman @ 2020-11-09 6:24 UTC (permalink / raw)
To: Wang Qing
Cc: Aneesh Kumar K.V, Peter Zijlstra, linuxppc-dev, linux-kernel,
Paul Mackerras, Nicholas Piggin, Alistair Popple, tglx,
Jordan Niethe
In-Reply-To: <1604893209-18762-1-git-send-email-wangqing@vivo.com>
On Mon, Nov 09, 2020 at 11:40:08AM +0800, Wang Qing wrote:
> Add PREEMPT_RT output to die().
That says what you did, but not why you are doing this.
Why are you doing this? That needs to go into the changelog text.
greg k-h
^ permalink raw reply
* Re: [PATCH v2 00/23] Rid W=1 warnings in MTD
From: Miquel Raynal @ 2020-11-09 8:28 UTC (permalink / raw)
To: Lee Jones
Cc: Boris BREZILLON, Vignesh Raghavendra, Sergey Lapin, dri-devel,
linux-mtd, Frieder Schrempf, Choudary Kalluri, Robert Jarzmik,
Sumit Semwal, Paul Mackerras, Dan Brown, linux-samsung-soc,
Adrian Hunter, Kamal Dasu, Krzysztof Kozlowski, Thomas Gleixner,
Chen-Yu Tsai, Kukjin Kim, bcm-kernel-feedback-list, linux-media,
Tudor Ambarus, Maxime Ripard, linaro-mm-sig, Dmitriy B,
Thomas Gleixner, Jochen Schäuble, Naga Sureshkumar Relli,
Yoshio Furuyama, Nicolas Pitre, linuxppc-dev, linux-kernel,
Ben Dooks, Kyungmin Park, Boris Brezillon, Qiang Yu,
Philipp Zabel, Richard Weinberger, Jian Zhang, Brian Norris,
David Woodhouse, Christian König
In-Reply-To: <20201106213655.1838861-1-lee.jones@linaro.org>
Hi Lee,
Lee Jones <lee.jones@linaro.org> wrote on Fri, 6 Nov 2020 21:36:32
+0000:
> This set is part of a larger effort attempting to clean-up W=1
> kernel builds, which are currently overwhelmingly riddled with
> niggly little warnings.
>
> v1 => v2:
> - Added tags
> - Satisfied Miquel's review comments
>
You probably missed my request to update the titles. That's why I
wanted the entire series to be resent. Anyway, as I forgot a few,
please find below the prefixes that should be used:
> Lee Jones (23):
> mtd: mtdpart: Fix misdocumented function parameter 'mtd'
> mtd: devices: phram: File headers are not good candidates for
> kernel-doc
> mtd: nand: onenand: onenand_base: Fix expected kernel-doc formatting
mtd: onenand: Fix...
> mtd: devices: docg3: Fix kernel-doc 'bad line' and 'excessive doc'
> issues
> mtd: mtdcore: Fix misspelled function parameter 'section'
mtd: Fix...
> mtd: nand: onenand: onenand_bbt: Fix expected kernel-doc formatting
mtd: onenand: Fix...
> mtd: spi-nor: controllers: hisi-sfc: Demote non-conformant kernel-doc
mtd: spi-nor: hisi-sfc: Demote...
> mtd: ubi: build: Document 'ubi_num' in struct mtd_dev_param
> mtd: nand: spi: toshiba: Demote non-conformant kernel-doc header
mtd: spinand: toshiba: Demote...
> mtd: ubi: kapi: Correct documentation for 'ubi_leb_read_sg's 'sgl'
> parameter
> mtd: ubi: eba: Fix a couple of misdocumentation issues
> mtd: ubi: wl: Fix a couple of kernel-doc issues
> mtd: nand: raw: brcmnand: brcmnand: Demote non-conformant kernel-doc
> headers
mtd: rawnand: brcmnand: Demote...
> mtd: ubi: gluebi: Fix misnamed function parameter documentation
> mtd: nand: raw: diskonchip: Marking unused variables as
> __always_unused
mtd: rawnand: diskonchip: Marking...
> mtd: nand: raw: cafe_nand: Remove superfluous param doc and add
> another
mtd: rawnand: cafe: Remove
> mtd: nand: raw: s3c2410: Add documentation for 2 missing struct
> members
mtd: rawnand: s3c2410: Add...
> mtd: nand: raw: omap_elm: Finish half populated function header,
> demote empty ones
mtd: rawnand: omap_elm: Finish
> mtd: nand: raw: omap2: Fix a bunch of kernel-doc misdemeanours
mtd:r rawnand: omap2: Fix
> mtd: nand: raw: sunxi_nand: Document 'sunxi_nfc's 'caps' member
mtd: rawnand: sunxi: Document
> mtd: nand: raw: arasan-nand-controller: Document 'anfc_op's 'buf'
> member
mtd: rawnand: arasan: Document
> mtd: nand: onenand: onenand_base: Fix some kernel-doc misdemeanours
mtd: onenand: Fix
> mtd: devices: powernv_flash: Add function names to headers and fix
> 'dev'
Otherwise the content of the series looks good to me.
Thanks,
Miquèl
^ permalink raw reply
* [PATCH v2 1/2] dt-bindings: misc: convert fsl, dpaa2-console from txt to YAML
From: Laurentiu Tudor @ 2020-11-09 10:46 UTC (permalink / raw)
To: robh+dt, leoyang.li, corbet, linux-arm-kernel, devicetree,
linux-kernel, netdev, linux-doc
Cc: ioana.ciornei, Ionut-robert Aron, kuba, linuxppc-dev, davem,
Laurentiu Tudor
From: Ionut-robert Aron <ionut-robert.aron@nxp.com>
Convert fsl,dpaa2-console to YAML in order to automate the
verification process of dts files.
Signed-off-by: Ionut-robert Aron <ionut-robert.aron@nxp.com>
Signed-off-by: Laurentiu Tudor <laurentiu.tudor@nxp.com>
---
Changes in v2:
- add missing additionalProperties
.../bindings/misc/fsl,dpaa2-console.txt | 11 --------
.../bindings/misc/fsl,dpaa2-console.yaml | 25 +++++++++++++++++++
2 files changed, 25 insertions(+), 11 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/misc/fsl,dpaa2-console.txt
create mode 100644 Documentation/devicetree/bindings/misc/fsl,dpaa2-console.yaml
diff --git a/Documentation/devicetree/bindings/misc/fsl,dpaa2-console.txt b/Documentation/devicetree/bindings/misc/fsl,dpaa2-console.txt
deleted file mode 100644
index 1442ba5d2d98..000000000000
--- a/Documentation/devicetree/bindings/misc/fsl,dpaa2-console.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-DPAA2 console support
-
-Required properties:
-
- - compatible
- Value type: <string>
- Definition: Must be "fsl,dpaa2-console".
- - reg
- Value type: <prop-encoded-array>
- Definition: A standard property. Specifies the region where the MCFBA
- (MC firmware base address) register can be found.
diff --git a/Documentation/devicetree/bindings/misc/fsl,dpaa2-console.yaml b/Documentation/devicetree/bindings/misc/fsl,dpaa2-console.yaml
new file mode 100644
index 000000000000..271a3eafc054
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/fsl,dpaa2-console.yaml
@@ -0,0 +1,25 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+# Copyright 2020 NXP
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/misc/fsl,dpaa2-console.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: DPAA2 console support
+
+maintainers:
+ - Laurentiu Tudor <laurentiu.tudor@nxp.com>
+
+properties:
+ compatible:
+ const: "fsl,dpaa2-console"
+
+ reg:
+ description: A standard property. Specifies the region where the MCFBA
+ (MC firmware base address) register can be found.
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
--
2.17.1
^ permalink raw reply related
* [PATCH v2 2/2] dt-bindings: misc: convert fsl, qoriq-mc from txt to YAML
From: Laurentiu Tudor @ 2020-11-09 10:46 UTC (permalink / raw)
To: robh+dt, leoyang.li, corbet, linux-arm-kernel, devicetree,
linux-kernel, netdev, linux-doc
Cc: ioana.ciornei, Ionut-robert Aron, kuba, linuxppc-dev, davem,
Laurentiu Tudor
In-Reply-To: <20201109104635.21116-1-laurentiu.tudor@nxp.com>
From: Ionut-robert Aron <ionut-robert.aron@nxp.com>
Convert fsl,qoriq-mc to YAML in order to automate the verification
process of dts files. In addition, update MAINTAINERS accordingly
and, while at it, add some missing files.
Signed-off-by: Ionut-robert Aron <ionut-robert.aron@nxp.com>
[laurentiu.tudor@nxp.com: update MINTAINERS, updates & fixes in schema]
Signed-off-by: Laurentiu Tudor <laurentiu.tudor@nxp.com>
---
Changes in v2:
- fixed errors reported by yamllint
- dropped multiple unnecessary quotes
- used schema instead of text in description
- added constraints on dpmac reg property
.../devicetree/bindings/misc/fsl,qoriq-mc.txt | 196 ----------------
.../bindings/misc/fsl,qoriq-mc.yaml | 210 ++++++++++++++++++
.../ethernet/freescale/dpaa2/overview.rst | 5 +-
MAINTAINERS | 4 +-
4 files changed, 217 insertions(+), 198 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt
create mode 100644 Documentation/devicetree/bindings/misc/fsl,qoriq-mc.yaml
diff --git a/Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt b/Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt
deleted file mode 100644
index 7b486d4985dc..000000000000
--- a/Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt
+++ /dev/null
@@ -1,196 +0,0 @@
-* Freescale Management Complex
-
-The Freescale Management Complex (fsl-mc) is a hardware resource
-manager that manages specialized hardware objects used in
-network-oriented packet processing applications. After the fsl-mc
-block is enabled, pools of hardware resources are available, such as
-queues, buffer pools, I/O interfaces. These resources are building
-blocks that can be used to create functional hardware objects/devices
-such as network interfaces, crypto accelerator instances, L2 switches,
-etc.
-
-For an overview of the DPAA2 architecture and fsl-mc bus see:
-Documentation/networking/device_drivers/ethernet/freescale/dpaa2/overview.rst
-
-As described in the above overview, all DPAA2 objects in a DPRC share the
-same hardware "isolation context" and a 10-bit value called an ICID
-(isolation context id) is expressed by the hardware to identify
-the requester.
-
-The generic 'iommus' property is insufficient to describe the relationship
-between ICIDs and IOMMUs, so an iommu-map property is used to define
-the set of possible ICIDs under a root DPRC and how they map to
-an IOMMU.
-
-For generic IOMMU bindings, see
-Documentation/devicetree/bindings/iommu/iommu.txt.
-
-For arm-smmu binding, see:
-Documentation/devicetree/bindings/iommu/arm,smmu.yaml.
-
-The MSI writes are accompanied by sideband data which is derived from the ICID.
-The msi-map property is used to associate the devices with both the ITS
-controller and the sideband data which accompanies the writes.
-
-For generic MSI bindings, see
-Documentation/devicetree/bindings/interrupt-controller/msi.txt.
-
-For GICv3 and GIC ITS bindings, see:
-Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml.
-
-Required properties:
-
- - compatible
- Value type: <string>
- Definition: Must be "fsl,qoriq-mc". A Freescale Management Complex
- compatible with this binding must have Block Revision
- Registers BRR1 and BRR2 at offset 0x0BF8 and 0x0BFC in
- the MC control register region.
-
- - reg
- Value type: <prop-encoded-array>
- Definition: A standard property. Specifies one or two regions
- defining the MC's registers:
-
- -the first region is the command portal for the
- this machine and must always be present
-
- -the second region is the MC control registers. This
- region may not be present in some scenarios, such
- as in the device tree presented to a virtual machine.
-
- - ranges
- Value type: <prop-encoded-array>
- Definition: A standard property. Defines the mapping between the child
- MC address space and the parent system address space.
-
- The MC address space is defined by 3 components:
- <region type> <offset hi> <offset lo>
-
- Valid values for region type are
- 0x0 - MC portals
- 0x1 - QBMAN portals
-
- - #address-cells
- Value type: <u32>
- Definition: Must be 3. (see definition in 'ranges' property)
-
- - #size-cells
- Value type: <u32>
- Definition: Must be 1.
-
-Sub-nodes:
-
- The fsl-mc node may optionally have dpmac sub-nodes that describe
- the relationship between the Ethernet MACs which belong to the MC
- and the Ethernet PHYs on the system board.
-
- The dpmac nodes must be under a node named "dpmacs" which contains
- the following properties:
-
- - #address-cells
- Value type: <u32>
- Definition: Must be present if dpmac sub-nodes are defined and must
- have a value of 1.
-
- - #size-cells
- Value type: <u32>
- Definition: Must be present if dpmac sub-nodes are defined and must
- have a value of 0.
-
- These nodes must have the following properties:
-
- - compatible
- Value type: <string>
- Definition: Must be "fsl,qoriq-mc-dpmac".
-
- - reg
- Value type: <prop-encoded-array>
- Definition: Specifies the id of the dpmac.
-
- - phy-handle
- Value type: <phandle>
- Definition: Specifies the phandle to the PHY device node associated
- with the this dpmac.
-Optional properties:
-
-- iommu-map: Maps an ICID to an IOMMU and associated iommu-specifier
- data.
-
- The property is an arbitrary number of tuples of
- (icid-base,iommu,iommu-base,length).
-
- Any ICID i in the interval [icid-base, icid-base + length) is
- associated with the listed IOMMU, with the iommu-specifier
- (i - icid-base + iommu-base).
-
-- msi-map: Maps an ICID to a GIC ITS and associated msi-specifier
- data.
-
- The property is an arbitrary number of tuples of
- (icid-base,gic-its,msi-base,length).
-
- Any ICID in the interval [icid-base, icid-base + length) is
- associated with the listed GIC ITS, with the msi-specifier
- (i - icid-base + msi-base).
-
-Deprecated properties:
-
- - msi-parent
- Value type: <phandle>
- Definition: Describes the MSI controller node handling message
- interrupts for the MC. When there is no translation
- between the ICID and deviceID this property can be used
- to describe the MSI controller used by the devices on the
- mc-bus.
- The use of this property for mc-bus is deprecated. Please
- use msi-map.
-
-Example:
-
- smmu: iommu@5000000 {
- compatible = "arm,mmu-500";
- #iommu-cells = <1>;
- stream-match-mask = <0x7C00>;
- ...
- };
-
- gic: interrupt-controller@6000000 {
- compatible = "arm,gic-v3";
- ...
- }
- its: gic-its@6020000 {
- compatible = "arm,gic-v3-its";
- msi-controller;
- ...
- };
-
- fsl_mc: fsl-mc@80c000000 {
- compatible = "fsl,qoriq-mc";
- reg = <0x00000008 0x0c000000 0 0x40>, /* MC portal base */
- <0x00000000 0x08340000 0 0x40000>; /* MC control reg */
- /* define map for ICIDs 23-64 */
- iommu-map = <23 &smmu 23 41>;
- /* define msi map for ICIDs 23-64 */
- msi-map = <23 &its 23 41>;
- #address-cells = <3>;
- #size-cells = <1>;
-
- /*
- * Region type 0x0 - MC portals
- * Region type 0x1 - QBMAN portals
- */
- ranges = <0x0 0x0 0x0 0x8 0x0c000000 0x4000000
- 0x1 0x0 0x0 0x8 0x18000000 0x8000000>;
-
- dpmacs {
- #address-cells = <1>;
- #size-cells = <0>;
-
- dpmac@1 {
- compatible = "fsl,qoriq-mc-dpmac";
- reg = <1>;
- phy-handle = <&mdio0_phy0>;
- }
- }
- };
diff --git a/Documentation/devicetree/bindings/misc/fsl,qoriq-mc.yaml b/Documentation/devicetree/bindings/misc/fsl,qoriq-mc.yaml
new file mode 100644
index 000000000000..5b69057eeda8
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/fsl,qoriq-mc.yaml
@@ -0,0 +1,210 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+# Copyright 2020 NXP
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/misc/fsl,qoriq-mc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+maintainers:
+ - Laurentiu Tudor <laurentiu.tudor@nxp.com>
+
+title: Freescale Management Complex
+
+description: |
+ The Freescale Management Complex (fsl-mc) is a hardware resource
+ manager that manages specialized hardware objects used in
+ network-oriented packet processing applications. After the fsl-mc
+ block is enabled, pools of hardware resources are available, such as
+ queues, buffer pools, I/O interfaces. These resources are building
+ blocks that can be used to create functional hardware objects/devices
+ such as network interfaces, crypto accelerator instances, L2 switches,
+ etc.
+
+ For an overview of the DPAA2 architecture and fsl-mc bus see:
+ Documentation/networking/device_drivers/freescale/dpaa2/overview.rst
+
+ As described in the above overview, all DPAA2 objects in a DPRC share the
+ same hardware "isolation context" and a 10-bit value called an ICID
+ (isolation context id) is expressed by the hardware to identify
+ the requester.
+
+ The generic 'iommus' property is insufficient to describe the relationship
+ between ICIDs and IOMMUs, so an iommu-map property is used to define
+ the set of possible ICIDs under a root DPRC and how they map to
+ an IOMMU.
+
+ For generic IOMMU bindings, see:
+ Documentation/devicetree/bindings/iommu/iommu.txt.
+
+ For arm-smmu binding, see:
+ Documentation/devicetree/bindings/iommu/arm,smmu.yaml.
+
+ MC firmware binary images can be found here:
+ https://github.com/NXP/qoriq-mc-binary
+
+properties:
+ compatible:
+ const: fsl,qoriq-mc
+ description:
+ A Freescale Management Complex compatible with this binding must have
+ Block Revision Registers BRR1 and BRR2 at offset 0x0BF8 and 0x0BFC in
+ the MC control register region.
+
+ reg:
+ minItems: 1
+ items:
+ - description: the command portal for this machine
+ - description:
+ MC control registers. This region may not be present in some
+ scenarios, such as in the device tree presented to a virtual
+ machine.
+
+ ranges:
+ description: |
+ A standard property. Defines the mapping between the child MC address
+ space and the parent system address space.
+
+ The MC address space is defined by 3 components:
+ <region type> <offset hi> <offset lo>
+
+ Valid values for region type are:
+ 0x0 - MC portals
+ 0x1 - QBMAN portals
+
+ '#address-cells':
+ const: 3
+
+ '#size-cells':
+ const: 1
+
+ dpmacs:
+ type: object
+ description:
+ The fsl-mc node may optionally have dpmac sub-nodes that describe the
+ relationship between the Ethernet MACs which belong to the MC and the
+ Ethernet PHYs on the system board.
+
+ properties:
+ '#address-cells':
+ const: 1
+
+ '#size-cells':
+ const: 0
+
+ patternProperties:
+ "^dpmac@[0-9a-f]+$":
+ type: object
+
+ description:
+ dpmac sub-node that describes the relationship between the
+ Ethernet MACs which belong to the MC and the Ethernet PHYs
+ on the system board.
+
+ properties:
+ compatible:
+ const: "fsl,qoriq-mc-dpmac"
+
+ reg:
+ description: Specifies the id of the dpmac
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 1
+ maximum: 31
+
+ phy-handle:
+ $ref: /schemas/types.yaml#definitions/phandle
+ description:
+ Specifies the phandle to the PHY device node associated with
+ this dpmac.
+
+ required:
+ - compatible
+ - reg
+ - phy-handle
+
+ iommu-map:
+ description: |
+ Maps an ICID to an IOMMU and associated iommu-specifier data.
+
+ The property is an arbitrary number of tuples of
+ (icid-base, iommu, iommu-base, length).
+
+ Any ICID i in the interval [icid-base, icid-base + length) is
+ associated with the listed IOMMU, with the iommu-specifier
+ (i - icid-base + iommu-base).
+
+ msi-map:
+ description: |
+ Maps an ICID to a GIC ITS and associated msi-specifier data.
+
+ The property is an arbitrary number of tuples of
+ (icid-base, gic-its, msi-base, length).
+
+ Any ICID in the interval [icid-base, icid-base + length) is
+ associated with the listed GIC ITS, with the msi-specifier
+ (i - icid-base + msi-base).
+
+ msi-parent:
+ deprecated: true
+ description:
+ Points to the MSI controller node handling message interrupts for the MC.
+
+required:
+ - compatible
+ - reg
+ - iommu-map
+ - msi-map
+ - ranges
+ - '#address-cells'
+ - '#size-cells'
+
+additionalProperties: false
+
+examples:
+ - |
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ smmu: iommu@5000000 {
+ compatible = "arm,mmu-500";
+ #global-interrupts = <1>;
+ #iommu-cells = <1>;
+ reg = <0 0x5000000 0 0x800000>;
+ stream-match-mask = <0x7c00>;
+ interrupts = <0 13 4>,
+ <0 146 4>, <0 147 4>,
+ <0 148 4>, <0 149 4>,
+ <0 150 4>, <0 151 4>,
+ <0 152 4>, <0 153 4>;
+ };
+
+ fsl_mc: fsl-mc@80c000000 {
+ compatible = "fsl,qoriq-mc";
+ reg = <0x00000008 0x0c000000 0 0x40>, /* MC portal base */
+ <0x00000000 0x08340000 0 0x40000>; /* MC control reg */
+ /* define map for ICIDs 23-64 */
+ iommu-map = <23 &smmu 23 41>;
+ /* define msi map for ICIDs 23-64 */
+ msi-map = <23 &its 23 41>;
+ #address-cells = <3>;
+ #size-cells = <1>;
+
+ /*
+ * Region type 0x0 - MC portals
+ * Region type 0x1 - QBMAN portals
+ */
+ ranges = <0x0 0x0 0x0 0x8 0x0c000000 0x4000000
+ 0x1 0x0 0x0 0x8 0x18000000 0x8000000>;
+
+ dpmacs {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dpmac@1 {
+ compatible = "fsl,qoriq-mc-dpmac";
+ reg = <1>;
+ phy-handle = <&mdio0_phy0>;
+ };
+ };
+ };
+ };
diff --git a/Documentation/networking/device_drivers/ethernet/freescale/dpaa2/overview.rst b/Documentation/networking/device_drivers/ethernet/freescale/dpaa2/overview.rst
index d638b5a8aadd..b3261c5871cc 100644
--- a/Documentation/networking/device_drivers/ethernet/freescale/dpaa2/overview.rst
+++ b/Documentation/networking/device_drivers/ethernet/freescale/dpaa2/overview.rst
@@ -28,6 +28,9 @@ interfaces, an L2 switch, or accelerator instances.
The MC provides memory-mapped I/O command interfaces (MC portals)
which DPAA2 software drivers use to operate on DPAA2 objects.
+MC firmware binary images can be found here:
+https://github.com/NXP/qoriq-mc-binary
+
The diagram below shows an overview of the DPAA2 resource management
architecture::
@@ -338,7 +341,7 @@ Key functions include:
a bind of the root DPRC to the DPRC driver
The binding for the MC-bus device-tree node can be consulted at
-*Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt*.
+*Documentation/devicetree/bindings/misc/fsl,qoriq-mc.yaml*.
The sysfs bind/unbind interfaces for the MC-bus can be consulted at
*Documentation/ABI/testing/sysfs-bus-fsl-mc*.
diff --git a/MAINTAINERS b/MAINTAINERS
index b43b59542d15..400a17c90edb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14409,9 +14409,11 @@ M: Stuart Yoder <stuyoder@gmail.com>
M: Laurentiu Tudor <laurentiu.tudor@nxp.com>
L: linux-kernel@vger.kernel.org
S: Maintained
-F: Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt
+F: Documentation/devicetree/bindings/misc/fsl,dpaa2-console.yaml
+F: Documentation/devicetree/bindings/misc/fsl,qoriq-mc.yaml
F: Documentation/networking/device_drivers/ethernet/freescale/dpaa2/overview.rst
F: drivers/bus/fsl-mc/
+F: include/linux/fsl/mc.h
QT1010 MEDIA DRIVER
M: Antti Palosaari <crope@iki.fi>
--
2.17.1
^ permalink raw reply related
* [PATCH] xsysace: Remove SYSACE driver
From: Michal Simek @ 2020-11-09 10:59 UTC (permalink / raw)
To: linux-kernel, monstr, michal.simek, git
Cc: Jens Axboe, devicetree, YueHaibing, Rob Herring, linux-block,
Chris Packham, Paul Mackerras, linuxppc-dev
Sysace IP is no longer used on Xilinx PowerPC 405/440 and Microblaze
systems. The driver is not regularly tested and very likely not working for
quite a long time that's why remove it.
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
---
Based on discussion
https://lore.kernel.org/linux-arm-kernel/5ab9a2a1-20e3-c7b2-f666-2034df436e74@kernel.dk/
I have grepped the kernel and found any old ppc platform. I have included
it in this patch to have a discussion about it.
---
MAINTAINERS | 1 -
arch/microblaze/boot/dts/system.dts | 8 -
arch/powerpc/boot/dts/icon.dts | 7 -
arch/powerpc/configs/44x/icon_defconfig | 1 -
drivers/block/Kconfig | 6 -
drivers/block/Makefile | 1 -
drivers/block/xsysace.c | 1273 -----------------------
7 files changed, 1297 deletions(-)
delete mode 100644 drivers/block/xsysace.c
diff --git a/MAINTAINERS b/MAINTAINERS
index cba8ddf87a08..38556c009758 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2741,7 +2741,6 @@ T: git https://github.com/Xilinx/linux-xlnx.git
F: Documentation/devicetree/bindings/i2c/cdns,i2c-r1p10.yaml
F: Documentation/devicetree/bindings/i2c/xlnx,xps-iic-2.00.a.yaml
F: arch/arm/mach-zynq/
-F: drivers/block/xsysace.c
F: drivers/clocksource/timer-cadence-ttc.c
F: drivers/cpuidle/cpuidle-zynq.c
F: drivers/edac/synopsys_edac.c
diff --git a/arch/microblaze/boot/dts/system.dts b/arch/microblaze/boot/dts/system.dts
index 5b236527176e..b7ee1056779e 100644
--- a/arch/microblaze/boot/dts/system.dts
+++ b/arch/microblaze/boot/dts/system.dts
@@ -310,14 +310,6 @@ RS232_Uart_1: serial@84000000 {
xlnx,odd-parity = <0x0>;
xlnx,use-parity = <0x0>;
} ;
- SysACE_CompactFlash: sysace@83600000 {
- compatible = "xlnx,xps-sysace-1.00.a";
- interrupt-parent = <&xps_intc_0>;
- interrupts = < 4 2 >;
- reg = < 0x83600000 0x10000 >;
- xlnx,family = "virtex5";
- xlnx,mem-width = <0x10>;
- } ;
debug_module: debug@84400000 {
compatible = "xlnx,mdm-1.00.d";
reg = < 0x84400000 0x10000 >;
diff --git a/arch/powerpc/boot/dts/icon.dts b/arch/powerpc/boot/dts/icon.dts
index fbaa60b8f87a..4fd7a4fbb4fb 100644
--- a/arch/powerpc/boot/dts/icon.dts
+++ b/arch/powerpc/boot/dts/icon.dts
@@ -197,13 +197,6 @@ partition@fa0000 {
reg = <0x00fa0000 0x00060000>;
};
};
-
- SysACE_CompactFlash: sysace@1,0 {
- compatible = "xlnx,sysace";
- interrupt-parent = <&UIC2>;
- interrupts = <24 0x4>;
- reg = <0x00000001 0x00000000 0x10000>;
- };
};
UART0: serial@f0000200 {
diff --git a/arch/powerpc/configs/44x/icon_defconfig b/arch/powerpc/configs/44x/icon_defconfig
index 930948a1da76..fb9a15573546 100644
--- a/arch/powerpc/configs/44x/icon_defconfig
+++ b/arch/powerpc/configs/44x/icon_defconfig
@@ -28,7 +28,6 @@ CONFIG_MTD_CFI_AMDSTD=y
CONFIG_MTD_PHYSMAP_OF=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=35000
-CONFIG_XILINX_SYSACE=y
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_SCSI_CONSTANTS=y
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index ecceaaa1a66f..9cb02861298d 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -388,12 +388,6 @@ config SUNVDC
source "drivers/s390/block/Kconfig"
-config XILINX_SYSACE
- tristate "Xilinx SystemACE support"
- depends on 4xx || MICROBLAZE
- help
- Include support for the Xilinx SystemACE CompactFlash interface
-
config XEN_BLKDEV_FRONTEND
tristate "Xen virtual block device support"
depends on XEN
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index e1f63117ee94..5ddd9370972a 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -19,7 +19,6 @@ obj-$(CONFIG_ATARI_FLOPPY) += ataflop.o
obj-$(CONFIG_AMIGA_Z2RAM) += z2ram.o
obj-$(CONFIG_BLK_DEV_RAM) += brd.o
obj-$(CONFIG_BLK_DEV_LOOP) += loop.o
-obj-$(CONFIG_XILINX_SYSACE) += xsysace.o
obj-$(CONFIG_CDROM_PKTCDVD) += pktcdvd.o
obj-$(CONFIG_SUNVDC) += sunvdc.o
obj-$(CONFIG_BLK_DEV_SKD) += skd.o
diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c
deleted file mode 100644
index eb8ef65778c3..000000000000
--- a/drivers/block/xsysace.c
+++ /dev/null
@@ -1,1273 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Xilinx SystemACE device driver
- *
- * Copyright 2007 Secret Lab Technologies Ltd.
- */
-
-/*
- * The SystemACE chip is designed to configure FPGAs by loading an FPGA
- * bitstream from a file on a CF card and squirting it into FPGAs connected
- * to the SystemACE JTAG chain. It also has the advantage of providing an
- * MPU interface which can be used to control the FPGA configuration process
- * and to use the attached CF card for general purpose storage.
- *
- * This driver is a block device driver for the SystemACE.
- *
- * Initialization:
- * The driver registers itself as a platform_device driver at module
- * load time. The platform bus will take care of calling the
- * ace_probe() method for all SystemACE instances in the system. Any
- * number of SystemACE instances are supported. ace_probe() calls
- * ace_setup() which initialized all data structures, reads the CF
- * id structure and registers the device.
- *
- * Processing:
- * Just about all of the heavy lifting in this driver is performed by
- * a Finite State Machine (FSM). The driver needs to wait on a number
- * of events; some raised by interrupts, some which need to be polled
- * for. Describing all of the behaviour in a FSM seems to be the
- * easiest way to keep the complexity low and make it easy to
- * understand what the driver is doing. If the block ops or the
- * request function need to interact with the hardware, then they
- * simply need to flag the request and kick of FSM processing.
- *
- * The FSM itself is atomic-safe code which can be run from any
- * context. The general process flow is:
- * 1. obtain the ace->lock spinlock.
- * 2. loop on ace_fsm_dostate() until the ace->fsm_continue flag is
- * cleared.
- * 3. release the lock.
- *
- * Individual states do not sleep in any way. If a condition needs to
- * be waited for then the state much clear the fsm_continue flag and
- * either schedule the FSM to be run again at a later time, or expect
- * an interrupt to call the FSM when the desired condition is met.
- *
- * In normal operation, the FSM is processed at interrupt context
- * either when the driver's tasklet is scheduled, or when an irq is
- * raised by the hardware. The tasklet can be scheduled at any time.
- * The request method in particular schedules the tasklet when a new
- * request has been indicated by the block layer. Once started, the
- * FSM proceeds as far as it can processing the request until it
- * needs on a hardware event. At this point, it must yield execution.
- *
- * A state has two options when yielding execution:
- * 1. ace_fsm_yield()
- * - Call if need to poll for event.
- * - clears the fsm_continue flag to exit the processing loop
- * - reschedules the tasklet to run again as soon as possible
- * 2. ace_fsm_yieldirq()
- * - Call if an irq is expected from the HW
- * - clears the fsm_continue flag to exit the processing loop
- * - does not reschedule the tasklet so the FSM will not be processed
- * again until an irq is received.
- * After calling a yield function, the state must return control back
- * to the FSM main loop.
- *
- * Additionally, the driver maintains a kernel timer which can process
- * the FSM. If the FSM gets stalled, typically due to a missed
- * interrupt, then the kernel timer will expire and the driver can
- * continue where it left off.
- *
- * To Do:
- * - Add FPGA configuration control interface.
- * - Request major number from lanana
- */
-
-#undef DEBUG
-
-#include <linux/module.h>
-#include <linux/ctype.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/blk-mq.h>
-#include <linux/mutex.h>
-#include <linux/ata.h>
-#include <linux/hdreg.h>
-#include <linux/platform_device.h>
-#if defined(CONFIG_OF)
-#include <linux/of_address.h>
-#include <linux/of_device.h>
-#include <linux/of_platform.h>
-#endif
-
-MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
-MODULE_DESCRIPTION("Xilinx SystemACE device driver");
-MODULE_LICENSE("GPL");
-
-/* SystemACE register definitions */
-#define ACE_BUSMODE (0x00)
-
-#define ACE_STATUS (0x04)
-#define ACE_STATUS_CFGLOCK (0x00000001)
-#define ACE_STATUS_MPULOCK (0x00000002)
-#define ACE_STATUS_CFGERROR (0x00000004) /* config controller error */
-#define ACE_STATUS_CFCERROR (0x00000008) /* CF controller error */
-#define ACE_STATUS_CFDETECT (0x00000010)
-#define ACE_STATUS_DATABUFRDY (0x00000020)
-#define ACE_STATUS_DATABUFMODE (0x00000040)
-#define ACE_STATUS_CFGDONE (0x00000080)
-#define ACE_STATUS_RDYFORCFCMD (0x00000100)
-#define ACE_STATUS_CFGMODEPIN (0x00000200)
-#define ACE_STATUS_CFGADDR_MASK (0x0000e000)
-#define ACE_STATUS_CFBSY (0x00020000)
-#define ACE_STATUS_CFRDY (0x00040000)
-#define ACE_STATUS_CFDWF (0x00080000)
-#define ACE_STATUS_CFDSC (0x00100000)
-#define ACE_STATUS_CFDRQ (0x00200000)
-#define ACE_STATUS_CFCORR (0x00400000)
-#define ACE_STATUS_CFERR (0x00800000)
-
-#define ACE_ERROR (0x08)
-#define ACE_CFGLBA (0x0c)
-#define ACE_MPULBA (0x10)
-
-#define ACE_SECCNTCMD (0x14)
-#define ACE_SECCNTCMD_RESET (0x0100)
-#define ACE_SECCNTCMD_IDENTIFY (0x0200)
-#define ACE_SECCNTCMD_READ_DATA (0x0300)
-#define ACE_SECCNTCMD_WRITE_DATA (0x0400)
-#define ACE_SECCNTCMD_ABORT (0x0600)
-
-#define ACE_VERSION (0x16)
-#define ACE_VERSION_REVISION_MASK (0x00FF)
-#define ACE_VERSION_MINOR_MASK (0x0F00)
-#define ACE_VERSION_MAJOR_MASK (0xF000)
-
-#define ACE_CTRL (0x18)
-#define ACE_CTRL_FORCELOCKREQ (0x0001)
-#define ACE_CTRL_LOCKREQ (0x0002)
-#define ACE_CTRL_FORCECFGADDR (0x0004)
-#define ACE_CTRL_FORCECFGMODE (0x0008)
-#define ACE_CTRL_CFGMODE (0x0010)
-#define ACE_CTRL_CFGSTART (0x0020)
-#define ACE_CTRL_CFGSEL (0x0040)
-#define ACE_CTRL_CFGRESET (0x0080)
-#define ACE_CTRL_DATABUFRDYIRQ (0x0100)
-#define ACE_CTRL_ERRORIRQ (0x0200)
-#define ACE_CTRL_CFGDONEIRQ (0x0400)
-#define ACE_CTRL_RESETIRQ (0x0800)
-#define ACE_CTRL_CFGPROG (0x1000)
-#define ACE_CTRL_CFGADDR_MASK (0xe000)
-
-#define ACE_FATSTAT (0x1c)
-
-#define ACE_NUM_MINORS 16
-#define ACE_SECTOR_SIZE (512)
-#define ACE_FIFO_SIZE (32)
-#define ACE_BUF_PER_SECTOR (ACE_SECTOR_SIZE / ACE_FIFO_SIZE)
-
-#define ACE_BUS_WIDTH_8 0
-#define ACE_BUS_WIDTH_16 1
-
-struct ace_reg_ops;
-
-struct ace_device {
- /* driver state data */
- int id;
- int media_change;
- int users;
- struct list_head list;
-
- /* finite state machine data */
- struct tasklet_struct fsm_tasklet;
- uint fsm_task; /* Current activity (ACE_TASK_*) */
- uint fsm_state; /* Current state (ACE_FSM_STATE_*) */
- uint fsm_continue_flag; /* cleared to exit FSM mainloop */
- uint fsm_iter_num;
- struct timer_list stall_timer;
-
- /* Transfer state/result, use for both id and block request */
- struct request *req; /* request being processed */
- void *data_ptr; /* pointer to I/O buffer */
- int data_count; /* number of buffers remaining */
- int data_result; /* Result of transfer; 0 := success */
-
- int id_req_count; /* count of id requests */
- int id_result;
- struct completion id_completion; /* used when id req finishes */
- int in_irq;
-
- /* Details of hardware device */
- resource_size_t physaddr;
- void __iomem *baseaddr;
- int irq;
- int bus_width; /* 0 := 8 bit; 1 := 16 bit */
- struct ace_reg_ops *reg_ops;
- int lock_count;
-
- /* Block device data structures */
- spinlock_t lock;
- struct device *dev;
- struct request_queue *queue;
- struct gendisk *gd;
- struct blk_mq_tag_set tag_set;
- struct list_head rq_list;
-
- /* Inserted CF card parameters */
- u16 cf_id[ATA_ID_WORDS];
-};
-
-static DEFINE_MUTEX(xsysace_mutex);
-static int ace_major;
-
-/* ---------------------------------------------------------------------
- * Low level register access
- */
-
-struct ace_reg_ops {
- u16(*in) (struct ace_device * ace, int reg);
- void (*out) (struct ace_device * ace, int reg, u16 val);
- void (*datain) (struct ace_device * ace);
- void (*dataout) (struct ace_device * ace);
-};
-
-/* 8 Bit bus width */
-static u16 ace_in_8(struct ace_device *ace, int reg)
-{
- void __iomem *r = ace->baseaddr + reg;
- return in_8(r) | (in_8(r + 1) << 8);
-}
-
-static void ace_out_8(struct ace_device *ace, int reg, u16 val)
-{
- void __iomem *r = ace->baseaddr + reg;
- out_8(r, val);
- out_8(r + 1, val >> 8);
-}
-
-static void ace_datain_8(struct ace_device *ace)
-{
- void __iomem *r = ace->baseaddr + 0x40;
- u8 *dst = ace->data_ptr;
- int i = ACE_FIFO_SIZE;
- while (i--)
- *dst++ = in_8(r++);
- ace->data_ptr = dst;
-}
-
-static void ace_dataout_8(struct ace_device *ace)
-{
- void __iomem *r = ace->baseaddr + 0x40;
- u8 *src = ace->data_ptr;
- int i = ACE_FIFO_SIZE;
- while (i--)
- out_8(r++, *src++);
- ace->data_ptr = src;
-}
-
-static struct ace_reg_ops ace_reg_8_ops = {
- .in = ace_in_8,
- .out = ace_out_8,
- .datain = ace_datain_8,
- .dataout = ace_dataout_8,
-};
-
-/* 16 bit big endian bus attachment */
-static u16 ace_in_be16(struct ace_device *ace, int reg)
-{
- return in_be16(ace->baseaddr + reg);
-}
-
-static void ace_out_be16(struct ace_device *ace, int reg, u16 val)
-{
- out_be16(ace->baseaddr + reg, val);
-}
-
-static void ace_datain_be16(struct ace_device *ace)
-{
- int i = ACE_FIFO_SIZE / 2;
- u16 *dst = ace->data_ptr;
- while (i--)
- *dst++ = in_le16(ace->baseaddr + 0x40);
- ace->data_ptr = dst;
-}
-
-static void ace_dataout_be16(struct ace_device *ace)
-{
- int i = ACE_FIFO_SIZE / 2;
- u16 *src = ace->data_ptr;
- while (i--)
- out_le16(ace->baseaddr + 0x40, *src++);
- ace->data_ptr = src;
-}
-
-/* 16 bit little endian bus attachment */
-static u16 ace_in_le16(struct ace_device *ace, int reg)
-{
- return in_le16(ace->baseaddr + reg);
-}
-
-static void ace_out_le16(struct ace_device *ace, int reg, u16 val)
-{
- out_le16(ace->baseaddr + reg, val);
-}
-
-static void ace_datain_le16(struct ace_device *ace)
-{
- int i = ACE_FIFO_SIZE / 2;
- u16 *dst = ace->data_ptr;
- while (i--)
- *dst++ = in_be16(ace->baseaddr + 0x40);
- ace->data_ptr = dst;
-}
-
-static void ace_dataout_le16(struct ace_device *ace)
-{
- int i = ACE_FIFO_SIZE / 2;
- u16 *src = ace->data_ptr;
- while (i--)
- out_be16(ace->baseaddr + 0x40, *src++);
- ace->data_ptr = src;
-}
-
-static struct ace_reg_ops ace_reg_be16_ops = {
- .in = ace_in_be16,
- .out = ace_out_be16,
- .datain = ace_datain_be16,
- .dataout = ace_dataout_be16,
-};
-
-static struct ace_reg_ops ace_reg_le16_ops = {
- .in = ace_in_le16,
- .out = ace_out_le16,
- .datain = ace_datain_le16,
- .dataout = ace_dataout_le16,
-};
-
-static inline u16 ace_in(struct ace_device *ace, int reg)
-{
- return ace->reg_ops->in(ace, reg);
-}
-
-static inline u32 ace_in32(struct ace_device *ace, int reg)
-{
- return ace_in(ace, reg) | (ace_in(ace, reg + 2) << 16);
-}
-
-static inline void ace_out(struct ace_device *ace, int reg, u16 val)
-{
- ace->reg_ops->out(ace, reg, val);
-}
-
-static inline void ace_out32(struct ace_device *ace, int reg, u32 val)
-{
- ace_out(ace, reg, val);
- ace_out(ace, reg + 2, val >> 16);
-}
-
-/* ---------------------------------------------------------------------
- * Debug support functions
- */
-
-#if defined(DEBUG)
-static void ace_dump_mem(void *base, int len)
-{
- const char *ptr = base;
- int i, j;
-
- for (i = 0; i < len; i += 16) {
- printk(KERN_INFO "%.8x:", i);
- for (j = 0; j < 16; j++) {
- if (!(j % 4))
- printk(" ");
- printk("%.2x", ptr[i + j]);
- }
- printk(" ");
- for (j = 0; j < 16; j++)
- printk("%c", isprint(ptr[i + j]) ? ptr[i + j] : '.');
- printk("\n");
- }
-}
-#else
-static inline void ace_dump_mem(void *base, int len)
-{
-}
-#endif
-
-static void ace_dump_regs(struct ace_device *ace)
-{
- dev_info(ace->dev,
- " ctrl: %.8x seccnt/cmd: %.4x ver:%.4x\n"
- " status:%.8x mpu_lba:%.8x busmode:%4x\n"
- " error: %.8x cfg_lba:%.8x fatstat:%.4x\n",
- ace_in32(ace, ACE_CTRL),
- ace_in(ace, ACE_SECCNTCMD),
- ace_in(ace, ACE_VERSION),
- ace_in32(ace, ACE_STATUS),
- ace_in32(ace, ACE_MPULBA),
- ace_in(ace, ACE_BUSMODE),
- ace_in32(ace, ACE_ERROR),
- ace_in32(ace, ACE_CFGLBA), ace_in(ace, ACE_FATSTAT));
-}
-
-static void ace_fix_driveid(u16 *id)
-{
-#if defined(__BIG_ENDIAN)
- int i;
-
- /* All half words have wrong byte order; swap the bytes */
- for (i = 0; i < ATA_ID_WORDS; i++, id++)
- *id = le16_to_cpu(*id);
-#endif
-}
-
-/* ---------------------------------------------------------------------
- * Finite State Machine (FSM) implementation
- */
-
-/* FSM tasks; used to direct state transitions */
-#define ACE_TASK_IDLE 0
-#define ACE_TASK_IDENTIFY 1
-#define ACE_TASK_READ 2
-#define ACE_TASK_WRITE 3
-#define ACE_FSM_NUM_TASKS 4
-
-/* FSM state definitions */
-#define ACE_FSM_STATE_IDLE 0
-#define ACE_FSM_STATE_REQ_LOCK 1
-#define ACE_FSM_STATE_WAIT_LOCK 2
-#define ACE_FSM_STATE_WAIT_CFREADY 3
-#define ACE_FSM_STATE_IDENTIFY_PREPARE 4
-#define ACE_FSM_STATE_IDENTIFY_TRANSFER 5
-#define ACE_FSM_STATE_IDENTIFY_COMPLETE 6
-#define ACE_FSM_STATE_REQ_PREPARE 7
-#define ACE_FSM_STATE_REQ_TRANSFER 8
-#define ACE_FSM_STATE_REQ_COMPLETE 9
-#define ACE_FSM_STATE_ERROR 10
-#define ACE_FSM_NUM_STATES 11
-
-/* Set flag to exit FSM loop and reschedule tasklet */
-static inline void ace_fsm_yieldpoll(struct ace_device *ace)
-{
- tasklet_schedule(&ace->fsm_tasklet);
- ace->fsm_continue_flag = 0;
-}
-
-static inline void ace_fsm_yield(struct ace_device *ace)
-{
- dev_dbg(ace->dev, "%s()\n", __func__);
- ace_fsm_yieldpoll(ace);
-}
-
-/* Set flag to exit FSM loop and wait for IRQ to reschedule tasklet */
-static inline void ace_fsm_yieldirq(struct ace_device *ace)
-{
- dev_dbg(ace->dev, "ace_fsm_yieldirq()\n");
-
- if (ace->irq > 0)
- ace->fsm_continue_flag = 0;
- else
- ace_fsm_yieldpoll(ace);
-}
-
-static bool ace_has_next_request(struct request_queue *q)
-{
- struct ace_device *ace = q->queuedata;
-
- return !list_empty(&ace->rq_list);
-}
-
-/* Get the next read/write request; ending requests that we don't handle */
-static struct request *ace_get_next_request(struct request_queue *q)
-{
- struct ace_device *ace = q->queuedata;
- struct request *rq;
-
- rq = list_first_entry_or_null(&ace->rq_list, struct request, queuelist);
- if (rq) {
- list_del_init(&rq->queuelist);
- blk_mq_start_request(rq);
- }
-
- return NULL;
-}
-
-static void ace_fsm_dostate(struct ace_device *ace)
-{
- struct request *req;
- u32 status;
- u16 val;
- int count;
-
-#if defined(DEBUG)
- dev_dbg(ace->dev, "fsm_state=%i, id_req_count=%i\n",
- ace->fsm_state, ace->id_req_count);
-#endif
-
- /* Verify that there is actually a CF in the slot. If not, then
- * bail out back to the idle state and wake up all the waiters */
- status = ace_in32(ace, ACE_STATUS);
- if ((status & ACE_STATUS_CFDETECT) == 0) {
- ace->fsm_state = ACE_FSM_STATE_IDLE;
- ace->media_change = 1;
- set_capacity(ace->gd, 0);
- dev_info(ace->dev, "No CF in slot\n");
-
- /* Drop all in-flight and pending requests */
- if (ace->req) {
- blk_mq_end_request(ace->req, BLK_STS_IOERR);
- ace->req = NULL;
- }
- while ((req = ace_get_next_request(ace->queue)) != NULL)
- blk_mq_end_request(req, BLK_STS_IOERR);
-
- /* Drop back to IDLE state and notify waiters */
- ace->fsm_state = ACE_FSM_STATE_IDLE;
- ace->id_result = -EIO;
- while (ace->id_req_count) {
- complete(&ace->id_completion);
- ace->id_req_count--;
- }
- }
-
- switch (ace->fsm_state) {
- case ACE_FSM_STATE_IDLE:
- /* See if there is anything to do */
- if (ace->id_req_count || ace_has_next_request(ace->queue)) {
- ace->fsm_iter_num++;
- ace->fsm_state = ACE_FSM_STATE_REQ_LOCK;
- mod_timer(&ace->stall_timer, jiffies + HZ);
- if (!timer_pending(&ace->stall_timer))
- add_timer(&ace->stall_timer);
- break;
- }
- del_timer(&ace->stall_timer);
- ace->fsm_continue_flag = 0;
- break;
-
- case ACE_FSM_STATE_REQ_LOCK:
- if (ace_in(ace, ACE_STATUS) & ACE_STATUS_MPULOCK) {
- /* Already have the lock, jump to next state */
- ace->fsm_state = ACE_FSM_STATE_WAIT_CFREADY;
- break;
- }
-
- /* Request the lock */
- val = ace_in(ace, ACE_CTRL);
- ace_out(ace, ACE_CTRL, val | ACE_CTRL_LOCKREQ);
- ace->fsm_state = ACE_FSM_STATE_WAIT_LOCK;
- break;
-
- case ACE_FSM_STATE_WAIT_LOCK:
- if (ace_in(ace, ACE_STATUS) & ACE_STATUS_MPULOCK) {
- /* got the lock; move to next state */
- ace->fsm_state = ACE_FSM_STATE_WAIT_CFREADY;
- break;
- }
-
- /* wait a bit for the lock */
- ace_fsm_yield(ace);
- break;
-
- case ACE_FSM_STATE_WAIT_CFREADY:
- status = ace_in32(ace, ACE_STATUS);
- if (!(status & ACE_STATUS_RDYFORCFCMD) ||
- (status & ACE_STATUS_CFBSY)) {
- /* CF card isn't ready; it needs to be polled */
- ace_fsm_yield(ace);
- break;
- }
-
- /* Device is ready for command; determine what to do next */
- if (ace->id_req_count)
- ace->fsm_state = ACE_FSM_STATE_IDENTIFY_PREPARE;
- else
- ace->fsm_state = ACE_FSM_STATE_REQ_PREPARE;
- break;
-
- case ACE_FSM_STATE_IDENTIFY_PREPARE:
- /* Send identify command */
- ace->fsm_task = ACE_TASK_IDENTIFY;
- ace->data_ptr = ace->cf_id;
- ace->data_count = ACE_BUF_PER_SECTOR;
- ace_out(ace, ACE_SECCNTCMD, ACE_SECCNTCMD_IDENTIFY);
-
- /* As per datasheet, put config controller in reset */
- val = ace_in(ace, ACE_CTRL);
- ace_out(ace, ACE_CTRL, val | ACE_CTRL_CFGRESET);
-
- /* irq handler takes over from this point; wait for the
- * transfer to complete */
- ace->fsm_state = ACE_FSM_STATE_IDENTIFY_TRANSFER;
- ace_fsm_yieldirq(ace);
- break;
-
- case ACE_FSM_STATE_IDENTIFY_TRANSFER:
- /* Check that the sysace is ready to receive data */
- status = ace_in32(ace, ACE_STATUS);
- if (status & ACE_STATUS_CFBSY) {
- dev_dbg(ace->dev, "CFBSY set; t=%i iter=%i dc=%i\n",
- ace->fsm_task, ace->fsm_iter_num,
- ace->data_count);
- ace_fsm_yield(ace);
- break;
- }
- if (!(status & ACE_STATUS_DATABUFRDY)) {
- ace_fsm_yield(ace);
- break;
- }
-
- /* Transfer the next buffer */
- ace->reg_ops->datain(ace);
- ace->data_count--;
-
- /* If there are still buffers to be transfers; jump out here */
- if (ace->data_count != 0) {
- ace_fsm_yieldirq(ace);
- break;
- }
-
- /* transfer finished; kick state machine */
- dev_dbg(ace->dev, "identify finished\n");
- ace->fsm_state = ACE_FSM_STATE_IDENTIFY_COMPLETE;
- break;
-
- case ACE_FSM_STATE_IDENTIFY_COMPLETE:
- ace_fix_driveid(ace->cf_id);
- ace_dump_mem(ace->cf_id, 512); /* Debug: Dump out disk ID */
-
- if (ace->data_result) {
- /* Error occurred, disable the disk */
- ace->media_change = 1;
- set_capacity(ace->gd, 0);
- dev_err(ace->dev, "error fetching CF id (%i)\n",
- ace->data_result);
- } else {
- ace->media_change = 0;
-
- /* Record disk parameters */
- set_capacity(ace->gd,
- ata_id_u32(ace->cf_id, ATA_ID_LBA_CAPACITY));
- dev_info(ace->dev, "capacity: %i sectors\n",
- ata_id_u32(ace->cf_id, ATA_ID_LBA_CAPACITY));
- }
-
- /* We're done, drop to IDLE state and notify waiters */
- ace->fsm_state = ACE_FSM_STATE_IDLE;
- ace->id_result = ace->data_result;
- while (ace->id_req_count) {
- complete(&ace->id_completion);
- ace->id_req_count--;
- }
- break;
-
- case ACE_FSM_STATE_REQ_PREPARE:
- req = ace_get_next_request(ace->queue);
- if (!req) {
- ace->fsm_state = ACE_FSM_STATE_IDLE;
- break;
- }
-
- /* Okay, it's a data request, set it up for transfer */
- dev_dbg(ace->dev,
- "request: sec=%llx hcnt=%x, ccnt=%x, dir=%i\n",
- (unsigned long long)blk_rq_pos(req),
- blk_rq_sectors(req), blk_rq_cur_sectors(req),
- rq_data_dir(req));
-
- ace->req = req;
- ace->data_ptr = bio_data(req->bio);
- ace->data_count = blk_rq_cur_sectors(req) * ACE_BUF_PER_SECTOR;
- ace_out32(ace, ACE_MPULBA, blk_rq_pos(req) & 0x0FFFFFFF);
-
- count = blk_rq_sectors(req);
- if (rq_data_dir(req)) {
- /* Kick off write request */
- dev_dbg(ace->dev, "write data\n");
- ace->fsm_task = ACE_TASK_WRITE;
- ace_out(ace, ACE_SECCNTCMD,
- count | ACE_SECCNTCMD_WRITE_DATA);
- } else {
- /* Kick off read request */
- dev_dbg(ace->dev, "read data\n");
- ace->fsm_task = ACE_TASK_READ;
- ace_out(ace, ACE_SECCNTCMD,
- count | ACE_SECCNTCMD_READ_DATA);
- }
-
- /* As per datasheet, put config controller in reset */
- val = ace_in(ace, ACE_CTRL);
- ace_out(ace, ACE_CTRL, val | ACE_CTRL_CFGRESET);
-
- /* Move to the transfer state. The systemace will raise
- * an interrupt once there is something to do
- */
- ace->fsm_state = ACE_FSM_STATE_REQ_TRANSFER;
- if (ace->fsm_task == ACE_TASK_READ)
- ace_fsm_yieldirq(ace); /* wait for data ready */
- break;
-
- case ACE_FSM_STATE_REQ_TRANSFER:
- /* Check that the sysace is ready to receive data */
- status = ace_in32(ace, ACE_STATUS);
- if (status & ACE_STATUS_CFBSY) {
- dev_dbg(ace->dev,
- "CFBSY set; t=%i iter=%i c=%i dc=%i irq=%i\n",
- ace->fsm_task, ace->fsm_iter_num,
- blk_rq_cur_sectors(ace->req) * 16,
- ace->data_count, ace->in_irq);
- ace_fsm_yield(ace); /* need to poll CFBSY bit */
- break;
- }
- if (!(status & ACE_STATUS_DATABUFRDY)) {
- dev_dbg(ace->dev,
- "DATABUF not set; t=%i iter=%i c=%i dc=%i irq=%i\n",
- ace->fsm_task, ace->fsm_iter_num,
- blk_rq_cur_sectors(ace->req) * 16,
- ace->data_count, ace->in_irq);
- ace_fsm_yieldirq(ace);
- break;
- }
-
- /* Transfer the next buffer */
- if (ace->fsm_task == ACE_TASK_WRITE)
- ace->reg_ops->dataout(ace);
- else
- ace->reg_ops->datain(ace);
- ace->data_count--;
-
- /* If there are still buffers to be transfers; jump out here */
- if (ace->data_count != 0) {
- ace_fsm_yieldirq(ace);
- break;
- }
-
- /* bio finished; is there another one? */
- if (blk_update_request(ace->req, BLK_STS_OK,
- blk_rq_cur_bytes(ace->req))) {
- /* dev_dbg(ace->dev, "next block; h=%u c=%u\n",
- * blk_rq_sectors(ace->req),
- * blk_rq_cur_sectors(ace->req));
- */
- ace->data_ptr = bio_data(ace->req->bio);
- ace->data_count = blk_rq_cur_sectors(ace->req) * 16;
- ace_fsm_yieldirq(ace);
- break;
- }
-
- ace->fsm_state = ACE_FSM_STATE_REQ_COMPLETE;
- break;
-
- case ACE_FSM_STATE_REQ_COMPLETE:
- ace->req = NULL;
-
- /* Finished request; go to idle state */
- ace->fsm_state = ACE_FSM_STATE_IDLE;
- break;
-
- default:
- ace->fsm_state = ACE_FSM_STATE_IDLE;
- break;
- }
-}
-
-static void ace_fsm_tasklet(unsigned long data)
-{
- struct ace_device *ace = (void *)data;
- unsigned long flags;
-
- spin_lock_irqsave(&ace->lock, flags);
-
- /* Loop over state machine until told to stop */
- ace->fsm_continue_flag = 1;
- while (ace->fsm_continue_flag)
- ace_fsm_dostate(ace);
-
- spin_unlock_irqrestore(&ace->lock, flags);
-}
-
-static void ace_stall_timer(struct timer_list *t)
-{
- struct ace_device *ace = from_timer(ace, t, stall_timer);
- unsigned long flags;
-
- dev_warn(ace->dev,
- "kicking stalled fsm; state=%i task=%i iter=%i dc=%i\n",
- ace->fsm_state, ace->fsm_task, ace->fsm_iter_num,
- ace->data_count);
- spin_lock_irqsave(&ace->lock, flags);
-
- /* Rearm the stall timer *before* entering FSM (which may then
- * delete the timer) */
- mod_timer(&ace->stall_timer, jiffies + HZ);
-
- /* Loop over state machine until told to stop */
- ace->fsm_continue_flag = 1;
- while (ace->fsm_continue_flag)
- ace_fsm_dostate(ace);
-
- spin_unlock_irqrestore(&ace->lock, flags);
-}
-
-/* ---------------------------------------------------------------------
- * Interrupt handling routines
- */
-static int ace_interrupt_checkstate(struct ace_device *ace)
-{
- u32 sreg = ace_in32(ace, ACE_STATUS);
- u16 creg = ace_in(ace, ACE_CTRL);
-
- /* Check for error occurrence */
- if ((sreg & (ACE_STATUS_CFGERROR | ACE_STATUS_CFCERROR)) &&
- (creg & ACE_CTRL_ERRORIRQ)) {
- dev_err(ace->dev, "transfer failure\n");
- ace_dump_regs(ace);
- return -EIO;
- }
-
- return 0;
-}
-
-static irqreturn_t ace_interrupt(int irq, void *dev_id)
-{
- u16 creg;
- struct ace_device *ace = dev_id;
-
- /* be safe and get the lock */
- spin_lock(&ace->lock);
- ace->in_irq = 1;
-
- /* clear the interrupt */
- creg = ace_in(ace, ACE_CTRL);
- ace_out(ace, ACE_CTRL, creg | ACE_CTRL_RESETIRQ);
- ace_out(ace, ACE_CTRL, creg);
-
- /* check for IO failures */
- if (ace_interrupt_checkstate(ace))
- ace->data_result = -EIO;
-
- if (ace->fsm_task == 0) {
- dev_err(ace->dev,
- "spurious irq; stat=%.8x ctrl=%.8x cmd=%.4x\n",
- ace_in32(ace, ACE_STATUS), ace_in32(ace, ACE_CTRL),
- ace_in(ace, ACE_SECCNTCMD));
- dev_err(ace->dev, "fsm_task=%i fsm_state=%i data_count=%i\n",
- ace->fsm_task, ace->fsm_state, ace->data_count);
- }
-
- /* Loop over state machine until told to stop */
- ace->fsm_continue_flag = 1;
- while (ace->fsm_continue_flag)
- ace_fsm_dostate(ace);
-
- /* done with interrupt; drop the lock */
- ace->in_irq = 0;
- spin_unlock(&ace->lock);
-
- return IRQ_HANDLED;
-}
-
-/* ---------------------------------------------------------------------
- * Block ops
- */
-static blk_status_t ace_queue_rq(struct blk_mq_hw_ctx *hctx,
- const struct blk_mq_queue_data *bd)
-{
- struct ace_device *ace = hctx->queue->queuedata;
- struct request *req = bd->rq;
-
- if (blk_rq_is_passthrough(req)) {
- blk_mq_start_request(req);
- return BLK_STS_IOERR;
- }
-
- spin_lock_irq(&ace->lock);
- list_add_tail(&req->queuelist, &ace->rq_list);
- spin_unlock_irq(&ace->lock);
-
- tasklet_schedule(&ace->fsm_tasklet);
- return BLK_STS_OK;
-}
-
-static unsigned int ace_check_events(struct gendisk *gd, unsigned int clearing)
-{
- struct ace_device *ace = gd->private_data;
- dev_dbg(ace->dev, "ace_check_events(): %i\n", ace->media_change);
-
- return ace->media_change ? DISK_EVENT_MEDIA_CHANGE : 0;
-}
-
-static void ace_media_changed(struct ace_device *ace)
-{
- unsigned long flags;
-
- dev_dbg(ace->dev, "requesting cf id and scheduling tasklet\n");
-
- spin_lock_irqsave(&ace->lock, flags);
- ace->id_req_count++;
- spin_unlock_irqrestore(&ace->lock, flags);
-
- tasklet_schedule(&ace->fsm_tasklet);
- wait_for_completion(&ace->id_completion);
-
- dev_dbg(ace->dev, "revalidate complete\n");
-}
-
-static int ace_open(struct block_device *bdev, fmode_t mode)
-{
- struct ace_device *ace = bdev->bd_disk->private_data;
- unsigned long flags;
-
- dev_dbg(ace->dev, "ace_open() users=%i\n", ace->users + 1);
-
- mutex_lock(&xsysace_mutex);
- spin_lock_irqsave(&ace->lock, flags);
- ace->users++;
- spin_unlock_irqrestore(&ace->lock, flags);
-
- if (bdev_check_media_change(bdev) && ace->media_change)
- ace_media_changed(ace);
- mutex_unlock(&xsysace_mutex);
-
- return 0;
-}
-
-static void ace_release(struct gendisk *disk, fmode_t mode)
-{
- struct ace_device *ace = disk->private_data;
- unsigned long flags;
- u16 val;
-
- dev_dbg(ace->dev, "ace_release() users=%i\n", ace->users - 1);
-
- mutex_lock(&xsysace_mutex);
- spin_lock_irqsave(&ace->lock, flags);
- ace->users--;
- if (ace->users == 0) {
- val = ace_in(ace, ACE_CTRL);
- ace_out(ace, ACE_CTRL, val & ~ACE_CTRL_LOCKREQ);
- }
- spin_unlock_irqrestore(&ace->lock, flags);
- mutex_unlock(&xsysace_mutex);
-}
-
-static int ace_getgeo(struct block_device *bdev, struct hd_geometry *geo)
-{
- struct ace_device *ace = bdev->bd_disk->private_data;
- u16 *cf_id = ace->cf_id;
-
- dev_dbg(ace->dev, "ace_getgeo()\n");
-
- geo->heads = cf_id[ATA_ID_HEADS];
- geo->sectors = cf_id[ATA_ID_SECTORS];
- geo->cylinders = cf_id[ATA_ID_CYLS];
-
- return 0;
-}
-
-static const struct block_device_operations ace_fops = {
- .owner = THIS_MODULE,
- .open = ace_open,
- .release = ace_release,
- .check_events = ace_check_events,
- .getgeo = ace_getgeo,
-};
-
-static const struct blk_mq_ops ace_mq_ops = {
- .queue_rq = ace_queue_rq,
-};
-
-/* --------------------------------------------------------------------
- * SystemACE device setup/teardown code
- */
-static int ace_setup(struct ace_device *ace)
-{
- u16 version;
- u16 val;
- int rc;
-
- dev_dbg(ace->dev, "ace_setup(ace=0x%p)\n", ace);
- dev_dbg(ace->dev, "physaddr=0x%llx irq=%i\n",
- (unsigned long long)ace->physaddr, ace->irq);
-
- spin_lock_init(&ace->lock);
- init_completion(&ace->id_completion);
- INIT_LIST_HEAD(&ace->rq_list);
-
- /*
- * Map the device
- */
- ace->baseaddr = ioremap(ace->physaddr, 0x80);
- if (!ace->baseaddr)
- goto err_ioremap;
-
- /*
- * Initialize the state machine tasklet and stall timer
- */
- tasklet_init(&ace->fsm_tasklet, ace_fsm_tasklet, (unsigned long)ace);
- timer_setup(&ace->stall_timer, ace_stall_timer, 0);
-
- /*
- * Initialize the request queue
- */
- ace->queue = blk_mq_init_sq_queue(&ace->tag_set, &ace_mq_ops, 2,
- BLK_MQ_F_SHOULD_MERGE);
- if (IS_ERR(ace->queue)) {
- rc = PTR_ERR(ace->queue);
- ace->queue = NULL;
- goto err_blk_initq;
- }
- ace->queue->queuedata = ace;
-
- blk_queue_logical_block_size(ace->queue, 512);
- blk_queue_bounce_limit(ace->queue, BLK_BOUNCE_HIGH);
-
- /*
- * Allocate and initialize GD structure
- */
- ace->gd = alloc_disk(ACE_NUM_MINORS);
- if (!ace->gd)
- goto err_alloc_disk;
-
- ace->gd->major = ace_major;
- ace->gd->first_minor = ace->id * ACE_NUM_MINORS;
- ace->gd->fops = &ace_fops;
- ace->gd->events = DISK_EVENT_MEDIA_CHANGE;
- ace->gd->queue = ace->queue;
- ace->gd->private_data = ace;
- snprintf(ace->gd->disk_name, 32, "xs%c", ace->id + 'a');
-
- /* set bus width */
- if (ace->bus_width == ACE_BUS_WIDTH_16) {
- /* 0x0101 should work regardless of endianess */
- ace_out_le16(ace, ACE_BUSMODE, 0x0101);
-
- /* read it back to determine endianess */
- if (ace_in_le16(ace, ACE_BUSMODE) == 0x0001)
- ace->reg_ops = &ace_reg_le16_ops;
- else
- ace->reg_ops = &ace_reg_be16_ops;
- } else {
- ace_out_8(ace, ACE_BUSMODE, 0x00);
- ace->reg_ops = &ace_reg_8_ops;
- }
-
- /* Make sure version register is sane */
- version = ace_in(ace, ACE_VERSION);
- if ((version == 0) || (version == 0xFFFF))
- goto err_read;
-
- /* Put sysace in a sane state by clearing most control reg bits */
- ace_out(ace, ACE_CTRL, ACE_CTRL_FORCECFGMODE |
- ACE_CTRL_DATABUFRDYIRQ | ACE_CTRL_ERRORIRQ);
-
- /* Now we can hook up the irq handler */
- if (ace->irq > 0) {
- rc = request_irq(ace->irq, ace_interrupt, 0, "systemace", ace);
- if (rc) {
- /* Failure - fall back to polled mode */
- dev_err(ace->dev, "request_irq failed\n");
- ace->irq = rc;
- }
- }
-
- /* Enable interrupts */
- val = ace_in(ace, ACE_CTRL);
- val |= ACE_CTRL_DATABUFRDYIRQ | ACE_CTRL_ERRORIRQ;
- ace_out(ace, ACE_CTRL, val);
-
- /* Print the identification */
- dev_info(ace->dev, "Xilinx SystemACE revision %i.%i.%i\n",
- (version >> 12) & 0xf, (version >> 8) & 0x0f, version & 0xff);
- dev_dbg(ace->dev, "physaddr 0x%llx, mapped to 0x%p, irq=%i\n",
- (unsigned long long) ace->physaddr, ace->baseaddr, ace->irq);
-
- ace->media_change = 1;
- ace_media_changed(ace);
-
- /* Make the sysace device 'live' */
- add_disk(ace->gd);
-
- return 0;
-
-err_read:
- /* prevent double queue cleanup */
- ace->gd->queue = NULL;
- put_disk(ace->gd);
-err_alloc_disk:
- blk_cleanup_queue(ace->queue);
- blk_mq_free_tag_set(&ace->tag_set);
-err_blk_initq:
- iounmap(ace->baseaddr);
-err_ioremap:
- dev_info(ace->dev, "xsysace: error initializing device at 0x%llx\n",
- (unsigned long long) ace->physaddr);
- return -ENOMEM;
-}
-
-static void ace_teardown(struct ace_device *ace)
-{
- if (ace->gd) {
- del_gendisk(ace->gd);
- put_disk(ace->gd);
- }
-
- if (ace->queue) {
- blk_cleanup_queue(ace->queue);
- blk_mq_free_tag_set(&ace->tag_set);
- }
-
- tasklet_kill(&ace->fsm_tasklet);
-
- if (ace->irq > 0)
- free_irq(ace->irq, ace);
-
- iounmap(ace->baseaddr);
-}
-
-static int ace_alloc(struct device *dev, int id, resource_size_t physaddr,
- int irq, int bus_width)
-{
- struct ace_device *ace;
- int rc;
- dev_dbg(dev, "ace_alloc(%p)\n", dev);
-
- /* Allocate and initialize the ace device structure */
- ace = kzalloc(sizeof(struct ace_device), GFP_KERNEL);
- if (!ace) {
- rc = -ENOMEM;
- goto err_alloc;
- }
-
- ace->dev = dev;
- ace->id = id;
- ace->physaddr = physaddr;
- ace->irq = irq;
- ace->bus_width = bus_width;
-
- /* Call the setup code */
- rc = ace_setup(ace);
- if (rc)
- goto err_setup;
-
- dev_set_drvdata(dev, ace);
- return 0;
-
-err_setup:
- dev_set_drvdata(dev, NULL);
- kfree(ace);
-err_alloc:
- dev_err(dev, "could not initialize device, err=%i\n", rc);
- return rc;
-}
-
-static void ace_free(struct device *dev)
-{
- struct ace_device *ace = dev_get_drvdata(dev);
- dev_dbg(dev, "ace_free(%p)\n", dev);
-
- if (ace) {
- ace_teardown(ace);
- dev_set_drvdata(dev, NULL);
- kfree(ace);
- }
-}
-
-/* ---------------------------------------------------------------------
- * Platform Bus Support
- */
-
-static int ace_probe(struct platform_device *dev)
-{
- int bus_width = ACE_BUS_WIDTH_16; /* FIXME: should not be hard coded */
- resource_size_t physaddr;
- struct resource *res;
- u32 id = dev->id;
- int irq;
- int i;
-
- dev_dbg(&dev->dev, "ace_probe(%p)\n", dev);
-
- /* device id and bus width */
- if (of_property_read_u32(dev->dev.of_node, "port-number", &id))
- id = 0;
- if (of_find_property(dev->dev.of_node, "8-bit", NULL))
- bus_width = ACE_BUS_WIDTH_8;
-
- res = platform_get_resource(dev, IORESOURCE_MEM, 0);
- if (!res)
- return -EINVAL;
-
- physaddr = res->start;
- if (!physaddr)
- return -ENODEV;
-
- irq = platform_get_irq_optional(dev, 0);
-
- /* Call the bus-independent setup code */
- return ace_alloc(&dev->dev, id, physaddr, irq, bus_width);
-}
-
-/*
- * Platform bus remove() method
- */
-static int ace_remove(struct platform_device *dev)
-{
- ace_free(&dev->dev);
- return 0;
-}
-
-#if defined(CONFIG_OF)
-/* Match table for of_platform binding */
-static const struct of_device_id ace_of_match[] = {
- { .compatible = "xlnx,opb-sysace-1.00.b", },
- { .compatible = "xlnx,opb-sysace-1.00.c", },
- { .compatible = "xlnx,xps-sysace-1.00.a", },
- { .compatible = "xlnx,sysace", },
- {},
-};
-MODULE_DEVICE_TABLE(of, ace_of_match);
-#else /* CONFIG_OF */
-#define ace_of_match NULL
-#endif /* CONFIG_OF */
-
-static struct platform_driver ace_platform_driver = {
- .probe = ace_probe,
- .remove = ace_remove,
- .driver = {
- .name = "xsysace",
- .of_match_table = ace_of_match,
- },
-};
-
-/* ---------------------------------------------------------------------
- * Module init/exit routines
- */
-static int __init ace_init(void)
-{
- int rc;
-
- ace_major = register_blkdev(ace_major, "xsysace");
- if (ace_major <= 0) {
- rc = -ENOMEM;
- goto err_blk;
- }
-
- rc = platform_driver_register(&ace_platform_driver);
- if (rc)
- goto err_plat;
-
- pr_info("Xilinx SystemACE device driver, major=%i\n", ace_major);
- return 0;
-
-err_plat:
- unregister_blkdev(ace_major, "xsysace");
-err_blk:
- printk(KERN_ERR "xsysace: registration failed; err=%i\n", rc);
- return rc;
-}
-module_init(ace_init);
-
-static void __exit ace_exit(void)
-{
- pr_debug("Unregistering Xilinx SystemACE driver\n");
- platform_driver_unregister(&ace_platform_driver);
- unregister_blkdev(ace_major, "xsysace");
-}
-module_exit(ace_exit);
--
2.29.2
^ permalink raw reply related
* Re: [PATCH v5 1/5] mm: introduce debug_pagealloc_{map, unmap}_pages() helpers
From: Vlastimil Babka @ 2020-11-09 11:33 UTC (permalink / raw)
To: Mike Rapoport, Andrew Morton
Cc: David Hildenbrand, Peter Zijlstra, Dave Hansen, linux-mm,
Paul Mackerras, Pavel Machek, H. Peter Anvin, sparclinux,
Christoph Lameter, Will Deacon, linux-riscv, linux-s390, x86,
Mike Rapoport, Christian Borntraeger, Ingo Molnar,
Catalin Marinas, Len Brown, Albert Ou, Vasily Gorbik, linux-pm,
Heiko Carstens, David Rientjes, Borislav Petkov, Andy Lutomirski,
Paul Walmsley, Kirill A. Shutemov, Thomas Gleixner,
linux-arm-kernel, Rafael J. Wysocki, linux-kernel, Pekka Enberg,
Palmer Dabbelt, Joonsoo Kim, Edgecombe, Rick P, linuxppc-dev,
David S. Miller, Kirill A . Shutemov
In-Reply-To: <20201108065758.1815-2-rppt@kernel.org>
On 11/8/20 7:57 AM, Mike Rapoport wrote:
> --- a/mm/slab.c
> +++ b/mm/slab.c
> @@ -1428,21 +1428,19 @@ static bool is_debug_pagealloc_cache(struct kmem_cache *cachep)
> return false;
> }
>
> -#ifdef CONFIG_DEBUG_PAGEALLOC
> static void slab_kernel_map(struct kmem_cache *cachep, void *objp, int map)
> {
> if (!is_debug_pagealloc_cache(cachep))
> return;
Hmm, I didn't notice earlier, sorry.
The is_debug_pagealloc_cache() above includes a debug_pagealloc_enabled_static()
check, so it should be fine to use
__kernel_map_pages() directly below. Otherwise we generate two static key checks
for the same key needlessly.
>
> - kernel_map_pages(virt_to_page(objp), cachep->size / PAGE_SIZE, map);
> + if (map)
> + debug_pagealloc_map_pages(virt_to_page(objp),
> + cachep->size / PAGE_SIZE);
> + else
> + debug_pagealloc_unmap_pages(virt_to_page(objp),
> + cachep->size / PAGE_SIZE);
> }
>
> -#else
> -static inline void slab_kernel_map(struct kmem_cache *cachep, void *objp,
> - int map) {}
> -
> -#endif
> -
> static void poison_obj(struct kmem_cache *cachep, void *addr, unsigned char val)
> {
> int size = cachep->object_size;
> @@ -2062,7 +2060,7 @@ int __kmem_cache_create(struct kmem_cache *cachep, slab_flags_t flags)
>
> #if DEBUG
> /*
> - * If we're going to use the generic kernel_map_pages()
> + * If we're going to use the generic debug_pagealloc_map_pages()
> * poisoning, then it's going to smash the contents of
> * the redzone and userword anyhow, so switch them off.
> */
>
^ permalink raw reply
* Re: [PATCH] powerpc: add compile-time support for lbarx, lwarx
From: Segher Boessenkool @ 2020-11-09 12:34 UTC (permalink / raw)
To: Gabriel Paubert; +Cc: linuxppc-dev, Nicholas Piggin
In-Reply-To: <20201108200152.GA16446@lt-gp.iram.es>
On Sun, Nov 08, 2020 at 09:01:52PM +0100, Gabriel Paubert wrote:
> On Sat, Nov 07, 2020 at 05:42:57AM -0600, Segher Boessenkool wrote:
> > On Sat, Nov 07, 2020 at 08:12:13AM +0100, Gabriel Paubert wrote:
> > > On Sat, Nov 07, 2020 at 01:23:28PM +1000, Nicholas Piggin wrote:
> > > > ISA v2.06 (POWER7 and up) as well as e6500 support lbarx and lwarx.
> > >
> > > Hmm, lwarx exists since original Power AFAIR,
> >
> > Almost: it was new on PowerPC.
>
> I stand corrected. Does this mean that Power1 (and 2 I believe) had
> no SMP support?
As I understand it, that's correct. Of course you always can do SMP "by
hand" -- you can do all synchronisation via software (perhaps using some
knowledge of the specific hardware you're running on), it's just slow
(and usually not portable). Compare to SMP on 603 for example.
Segher
^ permalink raw reply
* Re: [PATCH v5 1/5] mm: introduce debug_pagealloc_{map, unmap}_pages() helpers
From: Mike Rapoport @ 2020-11-09 14:41 UTC (permalink / raw)
To: Vlastimil Babka
Cc: David Hildenbrand, Peter Zijlstra, Dave Hansen, linux-mm,
Paul Mackerras, Pavel Machek, H. Peter Anvin, sparclinux,
Christoph Lameter, Will Deacon, linux-riscv, linux-s390, x86,
Mike Rapoport, Christian Borntraeger, Ingo Molnar,
Catalin Marinas, Len Brown, Albert Ou, Vasily Gorbik, linux-pm,
Heiko Carstens, David Rientjes, Borislav Petkov, Andy Lutomirski,
Paul Walmsley, Kirill A. Shutemov, Thomas Gleixner, Joonsoo Kim,
linux-arm-kernel, Rafael J. Wysocki, linux-kernel, Pekka Enberg,
Palmer Dabbelt, Andrew Morton, Edgecombe, Rick P, linuxppc-dev,
David S. Miller, Kirill A . Shutemov
In-Reply-To: <4bd5ae2b-4fc6-73dc-b83b-e71826990946@suse.cz>
On Mon, Nov 09, 2020 at 12:33:46PM +0100, Vlastimil Babka wrote:
> On 11/8/20 7:57 AM, Mike Rapoport wrote:
> > --- a/mm/slab.c
> > +++ b/mm/slab.c
> > @@ -1428,21 +1428,19 @@ static bool is_debug_pagealloc_cache(struct kmem_cache *cachep)
> > return false;
> > }
> > -#ifdef CONFIG_DEBUG_PAGEALLOC
> > static void slab_kernel_map(struct kmem_cache *cachep, void *objp, int map)
> > {
> > if (!is_debug_pagealloc_cache(cachep))
> > return;
>
> Hmm, I didn't notice earlier, sorry.
> The is_debug_pagealloc_cache() above includes a
> debug_pagealloc_enabled_static() check, so it should be fine to use
> __kernel_map_pages() directly below. Otherwise we generate two static key
> checks for the same key needlessly.
Ok, I'll revert slab changes.
> > - kernel_map_pages(virt_to_page(objp), cachep->size / PAGE_SIZE, map);
> > + if (map)
> > + debug_pagealloc_map_pages(virt_to_page(objp),
> > + cachep->size / PAGE_SIZE);
> > + else
> > + debug_pagealloc_unmap_pages(virt_to_page(objp),
> > + cachep->size / PAGE_SIZE);
> > }
> > -#else
> > -static inline void slab_kernel_map(struct kmem_cache *cachep, void *objp,
> > - int map) {}
> > -
> > -#endif
> > -
> > static void poison_obj(struct kmem_cache *cachep, void *addr, unsigned char val)
> > {
> > int size = cachep->object_size;
> > @@ -2062,7 +2060,7 @@ int __kmem_cache_create(struct kmem_cache *cachep, slab_flags_t flags)
> > #if DEBUG
> > /*
> > - * If we're going to use the generic kernel_map_pages()
> > + * If we're going to use the generic debug_pagealloc_map_pages()
> > * poisoning, then it's going to smash the contents of
> > * the redzone and userword anyhow, so switch them off.
> > */
> >
>
--
Sincerely yours,
Mike.
^ permalink raw reply
* [PATCH v6 0/4] arch, mm: improve robustness of direct map manipulation
From: Mike Rapoport @ 2020-11-09 16:24 UTC (permalink / raw)
To: Andrew Morton
Cc: David Hildenbrand, Peter Zijlstra, Dave Hansen, linux-mm,
Paul Mackerras, Pavel Machek, H. Peter Anvin, sparclinux,
Christoph Lameter, Will Deacon, linux-riscv, linux-s390, x86,
Mike Rapoport, Christian Borntraeger, Ingo Molnar,
linux-arm-kernel, Catalin Marinas, Len Brown, Albert Ou,
Vasily Gorbik, linux-pm, Heiko Carstens, David Rientjes,
Borislav Petkov, Andy Lutomirski, Paul Walmsley,
Kirill A. Shutemov, Thomas Gleixner, Vlastimil Babka,
Rafael J. Wysocki, linux-kernel, Pekka Enberg, Palmer Dabbelt,
Kirill A . Shutemov, Joonsoo Kim, Edgecombe, Rick P, linuxppc-dev,
David S. Miller, Mike Rapoport
From: Mike Rapoport <rppt@linux.ibm.com>
Hi,
During recent discussion about KVM protected memory, David raised a concern
about usage of __kernel_map_pages() outside of DEBUG_PAGEALLOC scope [1].
Indeed, for architectures that define CONFIG_ARCH_HAS_SET_DIRECT_MAP it is
possible that __kernel_map_pages() would fail, but since this function is
void, the failure will go unnoticed.
Moreover, there's lack of consistency of __kernel_map_pages() semantics
across architectures as some guard this function with
#ifdef DEBUG_PAGEALLOC, some refuse to update the direct map if page
allocation debugging is disabled at run time and some allow modifying the
direct map regardless of DEBUG_PAGEALLOC settings.
This set straightens this out by restoring dependency of
__kernel_map_pages() on DEBUG_PAGEALLOC and updating the call sites
accordingly.
Since currently the only user of __kernel_map_pages() outside
DEBUG_PAGEALLOC is hibernation, it is updated to make direct map accesses
there more explicit.
[1] https://lore.kernel.org/lkml/2759b4bf-e1e3-d006-7d86-78a40348269d@redhat.com
v6 changes:
* revert slab changes to avoid redundant check of static key
v5 changes:
* use pairs of _map()/_unmap() functions instead of _map(..., int enable) as
Vlastimil suggested
https://lore.kernel.org/lkml/20201108065758.1815-1-rppt@kernel.org
v4 changes:
* s/WARN_ON/pr_warn_once/ per David and Kirill
* rebase on v5.10-rc2
* add Acked/Reviewed tags
https://lore.kernel.org/lkml/20201103162057.22916-1-rppt@kernel.org
v3 changes:
* update arm64 changes to avoid regression, per Rick's comments
* fix bisectability
https://lore.kernel.org/lkml/20201101170815.9795-1-rppt@kernel.org
v2 changes:
* Rephrase patch 2 changelog to better describe the change intentions and
implications
* Move removal of kernel_map_pages() from patch 1 to patch 2, per David
https://lore.kernel.org/lkml/20201029161902.19272-1-rppt@kernel.org
v1:
https://lore.kernel.org/lkml/20201025101555.3057-1-rppt@kernel.org
Mike Rapoport (4):
mm: introduce debug_pagealloc_{map,unmap}_pages() helpers
PM: hibernate: make direct map manipulations more explicit
arch, mm: restore dependency of __kernel_map_pages() on DEBUG_PAGEALLOC
arch, mm: make kernel_page_present() always available
arch/Kconfig | 3 +++
arch/arm64/Kconfig | 4 +--
arch/arm64/include/asm/cacheflush.h | 1 +
arch/arm64/mm/pageattr.c | 6 +++--
arch/powerpc/Kconfig | 5 +---
arch/riscv/Kconfig | 4 +--
arch/riscv/include/asm/pgtable.h | 2 --
arch/riscv/include/asm/set_memory.h | 1 +
arch/riscv/mm/pageattr.c | 31 ++++++++++++++++++++++
arch/s390/Kconfig | 4 +--
arch/sparc/Kconfig | 4 +--
arch/x86/Kconfig | 4 +--
arch/x86/include/asm/set_memory.h | 1 +
arch/x86/mm/pat/set_memory.c | 4 +--
include/linux/mm.h | 40 ++++++++++++++---------------
include/linux/set_memory.h | 5 ++++
kernel/power/snapshot.c | 38 +++++++++++++++++++++++++--
mm/memory_hotplug.c | 3 +--
mm/page_alloc.c | 6 ++---
19 files changed, 113 insertions(+), 53 deletions(-)
--
2.28.0
^ permalink raw reply
* [PATCH v6 1/4] mm: introduce debug_pagealloc_{map, unmap}_pages() helpers
From: Mike Rapoport @ 2020-11-09 16:24 UTC (permalink / raw)
To: Andrew Morton
Cc: David Hildenbrand, Peter Zijlstra, Dave Hansen, linux-mm,
Paul Mackerras, Pavel Machek, H. Peter Anvin, sparclinux,
Christoph Lameter, Will Deacon, linux-riscv, linux-s390, x86,
Mike Rapoport, Christian Borntraeger, Ingo Molnar,
linux-arm-kernel, Catalin Marinas, Len Brown, Albert Ou,
Vasily Gorbik, linux-pm, Heiko Carstens, David Rientjes,
Borislav Petkov, Andy Lutomirski, Paul Walmsley,
Kirill A. Shutemov, Thomas Gleixner, Vlastimil Babka,
Rafael J. Wysocki, linux-kernel, Pekka Enberg, Palmer Dabbelt,
Kirill A . Shutemov, Joonsoo Kim, Edgecombe, Rick P, linuxppc-dev,
David S. Miller, Mike Rapoport
In-Reply-To: <20201109162415.13764-1-rppt@kernel.org>
From: Mike Rapoport <rppt@linux.ibm.com>
When CONFIG_DEBUG_PAGEALLOC is enabled, it unmaps pages from the kernel
direct mapping after free_pages(). The pages than need to be mapped back
before they could be used. Theese mapping operations use
__kernel_map_pages() guarded with with debug_pagealloc_enabled().
The only place that calls __kernel_map_pages() without checking whether
DEBUG_PAGEALLOC is enabled is the hibernation code that presumes
availability of this function when ARCH_HAS_SET_DIRECT_MAP is set.
Still, on arm64, __kernel_map_pages() will bail out when DEBUG_PAGEALLOC is
not enabled but set_direct_map_invalid_noflush() may render some pages not
present in the direct map and hibernation code won't be able to save such
pages.
To make page allocation debugging and hibernation interaction more robust,
the dependency on DEBUG_PAGEALLOC or ARCH_HAS_SET_DIRECT_MAP has to be made
more explicit.
Start with combining the guard condition and the call to
__kernel_map_pages() into debug_pagealloc_map_pages() and
debug_pagealloc_unmap_pages() functions to emphasize that
__kernel_map_pages() should not be called without DEBUG_PAGEALLOC and use
these new functions to map/unmap pages when page allocation debugging is
enabled.
Signed-off-by: Mike Rapoport <rppt@linux.ibm.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Acked-by: Vlastimil Babka <vbabka@suse.cz>
---
include/linux/mm.h | 15 +++++++++++++++
mm/memory_hotplug.c | 3 +--
mm/page_alloc.c | 6 ++----
3 files changed, 18 insertions(+), 6 deletions(-)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index ef360fe70aaf..bb8c70178f4e 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2936,12 +2936,27 @@ kernel_map_pages(struct page *page, int numpages, int enable)
{
__kernel_map_pages(page, numpages, enable);
}
+
+static inline void debug_pagealloc_map_pages(struct page *page, int numpages)
+{
+ if (debug_pagealloc_enabled_static())
+ __kernel_map_pages(page, numpages, 1);
+}
+
+static inline void debug_pagealloc_unmap_pages(struct page *page, int numpages)
+{
+ if (debug_pagealloc_enabled_static())
+ __kernel_map_pages(page, numpages, 0);
+}
+
#ifdef CONFIG_HIBERNATION
extern bool kernel_page_present(struct page *page);
#endif /* CONFIG_HIBERNATION */
#else /* CONFIG_DEBUG_PAGEALLOC || CONFIG_ARCH_HAS_SET_DIRECT_MAP */
static inline void
kernel_map_pages(struct page *page, int numpages, int enable) {}
+static inline void debug_pagealloc_map_pages(struct page *page, int numpages) {}
+static inline void debug_pagealloc_unmap_pages(struct page *page, int numpages) {}
#ifdef CONFIG_HIBERNATION
static inline bool kernel_page_present(struct page *page) { return true; }
#endif /* CONFIG_HIBERNATION */
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index b44d4c7ba73b..f18f86ba2a68 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -614,8 +614,7 @@ void generic_online_page(struct page *page, unsigned int order)
* so we should map it first. This is better than introducing a special
* case in page freeing fast path.
*/
- if (debug_pagealloc_enabled_static())
- kernel_map_pages(page, 1 << order, 1);
+ debug_pagealloc_map_pages(page, 1 << order);
__free_pages_core(page, order);
totalram_pages_add(1UL << order);
#ifdef CONFIG_HIGHMEM
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 23f5066bd4a5..db1bf70458d0 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1272,8 +1272,7 @@ static __always_inline bool free_pages_prepare(struct page *page,
*/
arch_free_page(page, order);
- if (debug_pagealloc_enabled_static())
- kernel_map_pages(page, 1 << order, 0);
+ debug_pagealloc_unmap_pages(page, 1 << order);
kasan_free_nondeferred_pages(page, order);
@@ -2270,8 +2269,7 @@ inline void post_alloc_hook(struct page *page, unsigned int order,
set_page_refcounted(page);
arch_alloc_page(page, order);
- if (debug_pagealloc_enabled_static())
- kernel_map_pages(page, 1 << order, 1);
+ debug_pagealloc_map_pages(page, 1 << order);
kasan_alloc_pages(page, order);
kernel_poison_pages(page, 1 << order, 1);
set_page_owner(page, order, gfp_flags);
--
2.28.0
^ permalink raw reply related
* [PATCH v6 2/4] PM: hibernate: make direct map manipulations more explicit
From: Mike Rapoport @ 2020-11-09 16:24 UTC (permalink / raw)
To: Andrew Morton
Cc: Rafael J . Wysocki, David Hildenbrand, Peter Zijlstra,
Dave Hansen, linux-mm, Paul Mackerras, Pavel Machek,
H. Peter Anvin, sparclinux, Christoph Lameter, Will Deacon,
linux-riscv, linux-s390, x86, Mike Rapoport,
Christian Borntraeger, Ingo Molnar, linux-arm-kernel,
Catalin Marinas, Len Brown, Albert Ou, Vasily Gorbik, linux-pm,
Heiko Carstens, David Rientjes, Borislav Petkov, Andy Lutomirski,
Paul Walmsley, Kirill A. Shutemov, Thomas Gleixner,
Vlastimil Babka, Rafael J. Wysocki, linux-kernel, Pekka Enberg,
Palmer Dabbelt, Kirill A . Shutemov, Joonsoo Kim,
Edgecombe, Rick P, linuxppc-dev, David S. Miller, Mike Rapoport
In-Reply-To: <20201109162415.13764-1-rppt@kernel.org>
From: Mike Rapoport <rppt@linux.ibm.com>
When DEBUG_PAGEALLOC or ARCH_HAS_SET_DIRECT_MAP is enabled a page may be
not present in the direct map and has to be explicitly mapped before it
could be copied.
Introduce hibernate_map_page() and hibernation_unmap_page() that will
explicitly use set_direct_map_{default,invalid}_noflush() for
ARCH_HAS_SET_DIRECT_MAP case and debug_pagealloc_{map,unmap}_pages() for
DEBUG_PAGEALLOC case.
The remapping of the pages in safe_copy_page() presumes that it only
changes protection bits in an existing PTE and so it is safe to ignore
return value of set_direct_map_{default,invalid}_noflush().
Still, add a pr_warn() so that future changes in set_memory APIs will not
silently break hibernation.
Signed-off-by: Mike Rapoport <rppt@linux.ibm.com>
Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Acked-by: Vlastimil Babka <vbabka@suse.cz>
---
include/linux/mm.h | 12 ------------
kernel/power/snapshot.c | 38 ++++++++++++++++++++++++++++++++++++--
2 files changed, 36 insertions(+), 14 deletions(-)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index bb8c70178f4e..e198b938f5c5 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2927,16 +2927,6 @@ static inline bool debug_pagealloc_enabled_static(void)
#if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_ARCH_HAS_SET_DIRECT_MAP)
extern void __kernel_map_pages(struct page *page, int numpages, int enable);
-/*
- * When called in DEBUG_PAGEALLOC context, the call should most likely be
- * guarded by debug_pagealloc_enabled() or debug_pagealloc_enabled_static()
- */
-static inline void
-kernel_map_pages(struct page *page, int numpages, int enable)
-{
- __kernel_map_pages(page, numpages, enable);
-}
-
static inline void debug_pagealloc_map_pages(struct page *page, int numpages)
{
if (debug_pagealloc_enabled_static())
@@ -2953,8 +2943,6 @@ static inline void debug_pagealloc_unmap_pages(struct page *page, int numpages)
extern bool kernel_page_present(struct page *page);
#endif /* CONFIG_HIBERNATION */
#else /* CONFIG_DEBUG_PAGEALLOC || CONFIG_ARCH_HAS_SET_DIRECT_MAP */
-static inline void
-kernel_map_pages(struct page *page, int numpages, int enable) {}
static inline void debug_pagealloc_map_pages(struct page *page, int numpages) {}
static inline void debug_pagealloc_unmap_pages(struct page *page, int numpages) {}
#ifdef CONFIG_HIBERNATION
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index 46b1804c1ddf..d848377dd8dc 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -76,6 +76,40 @@ static inline void hibernate_restore_protect_page(void *page_address) {}
static inline void hibernate_restore_unprotect_page(void *page_address) {}
#endif /* CONFIG_STRICT_KERNEL_RWX && CONFIG_ARCH_HAS_SET_MEMORY */
+
+/*
+ * The calls to set_direct_map_*() should not fail because remapping a page
+ * here means that we only update protection bits in an existing PTE.
+ * It is still worth to have a warning here if something changes and this
+ * will no longer be the case.
+ */
+static inline void hibernate_map_page(struct page *page)
+{
+ if (IS_ENABLED(CONFIG_ARCH_HAS_SET_DIRECT_MAP)) {
+ int ret = set_direct_map_default_noflush(page);
+
+ if (ret)
+ pr_warn_once("Failed to remap page\n");
+ } else {
+ debug_pagealloc_map_pages(page, 1);
+ }
+}
+
+static inline void hibernate_unmap_page(struct page *page)
+{
+ if (IS_ENABLED(CONFIG_ARCH_HAS_SET_DIRECT_MAP)) {
+ unsigned long addr = (unsigned long)page_address(page);
+ int ret = set_direct_map_invalid_noflush(page);
+
+ if (ret)
+ pr_warn_once("Failed to remap page\n");
+
+ flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
+ } else {
+ debug_pagealloc_unmap_pages(page, 1);
+ }
+}
+
static int swsusp_page_is_free(struct page *);
static void swsusp_set_page_forbidden(struct page *);
static void swsusp_unset_page_forbidden(struct page *);
@@ -1355,9 +1389,9 @@ static void safe_copy_page(void *dst, struct page *s_page)
if (kernel_page_present(s_page)) {
do_copy_page(dst, page_address(s_page));
} else {
- kernel_map_pages(s_page, 1, 1);
+ hibernate_map_page(s_page);
do_copy_page(dst, page_address(s_page));
- kernel_map_pages(s_page, 1, 0);
+ hibernate_unmap_page(s_page);
}
}
--
2.28.0
^ permalink raw reply related
* [PATCH v6 3/4] arch, mm: restore dependency of __kernel_map_pages() on DEBUG_PAGEALLOC
From: Mike Rapoport @ 2020-11-09 16:24 UTC (permalink / raw)
To: Andrew Morton
Cc: David Hildenbrand, Peter Zijlstra, Dave Hansen, linux-mm,
Paul Mackerras, Pavel Machek, H. Peter Anvin, sparclinux,
Christoph Lameter, Will Deacon, linux-riscv, linux-s390, x86,
Mike Rapoport, Christian Borntraeger, Ingo Molnar,
linux-arm-kernel, Catalin Marinas, Len Brown, Albert Ou,
Vasily Gorbik, linux-pm, Heiko Carstens, David Rientjes,
Borislav Petkov, Andy Lutomirski, Paul Walmsley,
Kirill A. Shutemov, Thomas Gleixner, Vlastimil Babka,
Rafael J. Wysocki, linux-kernel, Pekka Enberg, Palmer Dabbelt,
Kirill A . Shutemov, Joonsoo Kim, Edgecombe, Rick P, linuxppc-dev,
David S. Miller, Mike Rapoport
In-Reply-To: <20201109162415.13764-1-rppt@kernel.org>
From: Mike Rapoport <rppt@linux.ibm.com>
The design of DEBUG_PAGEALLOC presumes that __kernel_map_pages() must never
fail. With this assumption is wouldn't be safe to allow general usage of
this function.
Moreover, some architectures that implement __kernel_map_pages() have this
function guarded by #ifdef DEBUG_PAGEALLOC and some refuse to map/unmap
pages when page allocation debugging is disabled at runtime.
As all the users of __kernel_map_pages() were converted to use
debug_pagealloc_map_pages() it is safe to make it available only when
DEBUG_PAGEALLOC is set.
Signed-off-by: Mike Rapoport <rppt@linux.ibm.com>
Acked-by: David Hildenbrand <david@redhat.com>
Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
---
arch/Kconfig | 3 +++
arch/arm64/Kconfig | 4 +---
arch/arm64/mm/pageattr.c | 8 ++++++--
arch/powerpc/Kconfig | 5 +----
arch/riscv/Kconfig | 4 +---
arch/riscv/include/asm/pgtable.h | 2 --
arch/riscv/mm/pageattr.c | 2 ++
arch/s390/Kconfig | 4 +---
arch/sparc/Kconfig | 4 +---
arch/x86/Kconfig | 4 +---
arch/x86/mm/pat/set_memory.c | 2 ++
include/linux/mm.h | 10 +++++++---
12 files changed, 26 insertions(+), 26 deletions(-)
diff --git a/arch/Kconfig b/arch/Kconfig
index 56b6ccc0e32d..56d4752b6db6 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -1028,6 +1028,9 @@ config HAVE_STATIC_CALL_INLINE
bool
depends on HAVE_STATIC_CALL
+config ARCH_SUPPORTS_DEBUG_PAGEALLOC
+ bool
+
source "kernel/gcov/Kconfig"
source "scripts/gcc-plugins/Kconfig"
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 1d466addb078..a932810cfd90 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -71,6 +71,7 @@ config ARM64
select ARCH_USE_QUEUED_RWLOCKS
select ARCH_USE_QUEUED_SPINLOCKS
select ARCH_USE_SYM_ANNOTATIONS
+ select ARCH_SUPPORTS_DEBUG_PAGEALLOC
select ARCH_SUPPORTS_MEMORY_FAILURE
select ARCH_SUPPORTS_SHADOW_CALL_STACK if CC_HAVE_SHADOW_CALL_STACK
select ARCH_SUPPORTS_ATOMIC_RMW
@@ -1025,9 +1026,6 @@ config HOLES_IN_ZONE
source "kernel/Kconfig.hz"
-config ARCH_SUPPORTS_DEBUG_PAGEALLOC
- def_bool y
-
config ARCH_SPARSEMEM_ENABLE
def_bool y
select SPARSEMEM_VMEMMAP_ENABLE
diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c
index 1b94f5b82654..439325532be1 100644
--- a/arch/arm64/mm/pageattr.c
+++ b/arch/arm64/mm/pageattr.c
@@ -155,7 +155,7 @@ int set_direct_map_invalid_noflush(struct page *page)
.clear_mask = __pgprot(PTE_VALID),
};
- if (!rodata_full)
+ if (!debug_pagealloc_enabled() && !rodata_full)
return 0;
return apply_to_page_range(&init_mm,
@@ -170,7 +170,7 @@ int set_direct_map_default_noflush(struct page *page)
.clear_mask = __pgprot(PTE_RDONLY),
};
- if (!rodata_full)
+ if (!debug_pagealloc_enabled() && !rodata_full)
return 0;
return apply_to_page_range(&init_mm,
@@ -178,6 +178,7 @@ int set_direct_map_default_noflush(struct page *page)
PAGE_SIZE, change_page_range, &data);
}
+#ifdef CONFIG_DEBUG_PAGEALLOC
void __kernel_map_pages(struct page *page, int numpages, int enable)
{
if (!debug_pagealloc_enabled() && !rodata_full)
@@ -186,6 +187,7 @@ void __kernel_map_pages(struct page *page, int numpages, int enable)
set_memory_valid((unsigned long)page_address(page), numpages, enable);
}
+#ifdef CONFIG_HIBERNATION
/*
* This function is used to determine if a linear map page has been marked as
* not-valid. Walk the page table and check the PTE_VALID bit. This is based
@@ -232,3 +234,5 @@ bool kernel_page_present(struct page *page)
ptep = pte_offset_kernel(pmdp, addr);
return pte_valid(READ_ONCE(*ptep));
}
+#endif /* CONFIG_HIBERNATION */
+#endif /* CONFIG_DEBUG_PAGEALLOC */
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index e9f13fe08492..ad8a83f3ddca 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -146,6 +146,7 @@ config PPC
select ARCH_MIGHT_HAVE_PC_SERIO
select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
select ARCH_SUPPORTS_ATOMIC_RMW
+ select ARCH_SUPPORTS_DEBUG_PAGEALLOC if PPC32 || PPC_BOOK3S_64
select ARCH_USE_BUILTIN_BSWAP
select ARCH_USE_CMPXCHG_LOCKREF if PPC64
select ARCH_USE_QUEUED_RWLOCKS if PPC_QUEUED_SPINLOCKS
@@ -355,10 +356,6 @@ config PPC_OF_PLATFORM_PCI
depends on PCI
depends on PPC64 # not supported on 32 bits yet
-config ARCH_SUPPORTS_DEBUG_PAGEALLOC
- depends on PPC32 || PPC_BOOK3S_64
- def_bool y
-
config ARCH_SUPPORTS_UPROBES
def_bool y
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 44377fd7860e..9283c6f9ae2a 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -14,6 +14,7 @@ config RISCV
def_bool y
select ARCH_CLOCKSOURCE_INIT
select ARCH_SUPPORTS_ATOMIC_RMW
+ select ARCH_SUPPORTS_DEBUG_PAGEALLOC if MMU
select ARCH_HAS_BINFMT_FLAT
select ARCH_HAS_DEBUG_VM_PGTABLE
select ARCH_HAS_DEBUG_VIRTUAL if MMU
@@ -153,9 +154,6 @@ config ARCH_SELECT_MEMORY_MODEL
config ARCH_WANT_GENERAL_HUGETLB
def_bool y
-config ARCH_SUPPORTS_DEBUG_PAGEALLOC
- def_bool y
-
config SYS_SUPPORTS_HUGETLBFS
depends on MMU
def_bool y
diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
index 183f1f4b2ae6..41a72861987c 100644
--- a/arch/riscv/include/asm/pgtable.h
+++ b/arch/riscv/include/asm/pgtable.h
@@ -461,8 +461,6 @@ static inline int ptep_clear_flush_young(struct vm_area_struct *vma,
#define VMALLOC_START 0
#define VMALLOC_END TASK_SIZE
-static inline void __kernel_map_pages(struct page *page, int numpages, int enable) {}
-
#endif /* !CONFIG_MMU */
#define kern_addr_valid(addr) (1) /* FIXME */
diff --git a/arch/riscv/mm/pageattr.c b/arch/riscv/mm/pageattr.c
index 19fecb362d81..321b09d2e2ea 100644
--- a/arch/riscv/mm/pageattr.c
+++ b/arch/riscv/mm/pageattr.c
@@ -184,6 +184,7 @@ int set_direct_map_default_noflush(struct page *page)
return ret;
}
+#ifdef CONFIG_DEBUG_PAGEALLOC
void __kernel_map_pages(struct page *page, int numpages, int enable)
{
if (!debug_pagealloc_enabled())
@@ -196,3 +197,4 @@ void __kernel_map_pages(struct page *page, int numpages, int enable)
__set_memory((unsigned long)page_address(page), numpages,
__pgprot(0), __pgprot(_PAGE_PRESENT));
}
+#endif
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 4a2a12be04c9..991a850a6c0b 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -35,9 +35,6 @@ config GENERIC_LOCKBREAK
config PGSTE
def_bool y if KVM
-config ARCH_SUPPORTS_DEBUG_PAGEALLOC
- def_bool y
-
config AUDIT_ARCH
def_bool y
@@ -106,6 +103,7 @@ config S390
select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE
select ARCH_STACKWALK
select ARCH_SUPPORTS_ATOMIC_RMW
+ select ARCH_SUPPORTS_DEBUG_PAGEALLOC
select ARCH_SUPPORTS_NUMA_BALANCING
select ARCH_USE_BUILTIN_BSWAP
select ARCH_USE_CMPXCHG_LOCKREF
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index a6ca135442f9..2c729b8d097a 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -88,6 +88,7 @@ config SPARC64
select HAVE_C_RECORDMCOUNT
select HAVE_ARCH_AUDITSYSCALL
select ARCH_SUPPORTS_ATOMIC_RMW
+ select ARCH_SUPPORTS_DEBUG_PAGEALLOC
select HAVE_NMI
select HAVE_REGS_AND_STACK_ACCESS_API
select ARCH_USE_QUEUED_RWLOCKS
@@ -148,9 +149,6 @@ config GENERIC_ISA_DMA
bool
default y if SPARC32
-config ARCH_SUPPORTS_DEBUG_PAGEALLOC
- def_bool y if SPARC64
-
config PGTABLE_LEVELS
default 4 if 64BIT
default 3
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index f6946b81f74a..0db3fb1da70c 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -91,6 +91,7 @@ config X86
select ARCH_STACKWALK
select ARCH_SUPPORTS_ACPI
select ARCH_SUPPORTS_ATOMIC_RMW
+ select ARCH_SUPPORTS_DEBUG_PAGEALLOC
select ARCH_SUPPORTS_NUMA_BALANCING if X86_64
select ARCH_USE_BUILTIN_BSWAP
select ARCH_USE_QUEUED_RWLOCKS
@@ -329,9 +330,6 @@ config ZONE_DMA32
config AUDIT_ARCH
def_bool y if X86_64
-config ARCH_SUPPORTS_DEBUG_PAGEALLOC
- def_bool y
-
config KASAN_SHADOW_OFFSET
hex
depends on KASAN
diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
index 40baa90e74f4..bc9be96b777f 100644
--- a/arch/x86/mm/pat/set_memory.c
+++ b/arch/x86/mm/pat/set_memory.c
@@ -2194,6 +2194,7 @@ int set_direct_map_default_noflush(struct page *page)
return __set_pages_p(page, 1);
}
+#ifdef CONFIG_DEBUG_PAGEALLOC
void __kernel_map_pages(struct page *page, int numpages, int enable)
{
if (PageHighMem(page))
@@ -2239,6 +2240,7 @@ bool kernel_page_present(struct page *page)
return (pte_val(*pte) & _PAGE_PRESENT);
}
#endif /* CONFIG_HIBERNATION */
+#endif /* CONFIG_DEBUG_PAGEALLOC */
int __init kernel_map_pages_in_pgd(pgd_t *pgd, u64 pfn, unsigned long address,
unsigned numpages, unsigned long page_flags)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index e198b938f5c5..260113ba660a 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2924,7 +2924,11 @@ static inline bool debug_pagealloc_enabled_static(void)
return static_branch_unlikely(&_debug_pagealloc_enabled);
}
-#if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_ARCH_HAS_SET_DIRECT_MAP)
+#ifdef CONFIG_DEBUG_PAGEALLOC
+/*
+ * To support DEBUG_PAGEALLOC architecture must ensure that
+ * __kernel_map_pages() never fails
+ */
extern void __kernel_map_pages(struct page *page, int numpages, int enable);
static inline void debug_pagealloc_map_pages(struct page *page, int numpages)
@@ -2942,13 +2946,13 @@ static inline void debug_pagealloc_unmap_pages(struct page *page, int numpages)
#ifdef CONFIG_HIBERNATION
extern bool kernel_page_present(struct page *page);
#endif /* CONFIG_HIBERNATION */
-#else /* CONFIG_DEBUG_PAGEALLOC || CONFIG_ARCH_HAS_SET_DIRECT_MAP */
+#else /* CONFIG_DEBUG_PAGEALLOC */
static inline void debug_pagealloc_map_pages(struct page *page, int numpages) {}
static inline void debug_pagealloc_unmap_pages(struct page *page, int numpages) {}
#ifdef CONFIG_HIBERNATION
static inline bool kernel_page_present(struct page *page) { return true; }
#endif /* CONFIG_HIBERNATION */
-#endif /* CONFIG_DEBUG_PAGEALLOC || CONFIG_ARCH_HAS_SET_DIRECT_MAP */
+#endif /* CONFIG_DEBUG_PAGEALLOC */
#ifdef __HAVE_ARCH_GATE_AREA
extern struct vm_area_struct *get_gate_vma(struct mm_struct *mm);
--
2.28.0
^ permalink raw reply related
* [PATCH v6 4/4] arch, mm: make kernel_page_present() always available
From: Mike Rapoport @ 2020-11-09 16:24 UTC (permalink / raw)
To: Andrew Morton
Cc: David Hildenbrand, Peter Zijlstra, Dave Hansen, linux-mm,
Paul Mackerras, Pavel Machek, H. Peter Anvin, sparclinux,
Christoph Lameter, Will Deacon, linux-riscv, linux-s390, x86,
Mike Rapoport, Christian Borntraeger, Ingo Molnar,
linux-arm-kernel, Catalin Marinas, Len Brown, Albert Ou,
Vasily Gorbik, linux-pm, Heiko Carstens, David Rientjes,
Borislav Petkov, Andy Lutomirski, Paul Walmsley,
Kirill A. Shutemov, Thomas Gleixner, Vlastimil Babka,
Rafael J. Wysocki, linux-kernel, Pekka Enberg, Palmer Dabbelt,
Kirill A . Shutemov, Joonsoo Kim, Edgecombe, Rick P, linuxppc-dev,
David S. Miller, Mike Rapoport
In-Reply-To: <20201109162415.13764-1-rppt@kernel.org>
From: Mike Rapoport <rppt@linux.ibm.com>
For architectures that enable ARCH_HAS_SET_MEMORY having the ability to
verify that a page is mapped in the kernel direct map can be useful
regardless of hibernation.
Add RISC-V implementation of kernel_page_present(), update its forward
declarations and stubs to be a part of set_memory API and remove ugly
ifdefery in inlcude/linux/mm.h around current declarations of
kernel_page_present().
Signed-off-by: Mike Rapoport <rppt@linux.ibm.com>
Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
---
arch/arm64/include/asm/cacheflush.h | 1 +
arch/arm64/mm/pageattr.c | 4 +---
arch/riscv/include/asm/set_memory.h | 1 +
arch/riscv/mm/pageattr.c | 29 +++++++++++++++++++++++++++++
arch/x86/include/asm/set_memory.h | 1 +
arch/x86/mm/pat/set_memory.c | 4 +---
include/linux/mm.h | 7 -------
include/linux/set_memory.h | 5 +++++
8 files changed, 39 insertions(+), 13 deletions(-)
diff --git a/arch/arm64/include/asm/cacheflush.h b/arch/arm64/include/asm/cacheflush.h
index 9384fd8fc13c..45217f21f1fe 100644
--- a/arch/arm64/include/asm/cacheflush.h
+++ b/arch/arm64/include/asm/cacheflush.h
@@ -140,6 +140,7 @@ int set_memory_valid(unsigned long addr, int numpages, int enable);
int set_direct_map_invalid_noflush(struct page *page);
int set_direct_map_default_noflush(struct page *page);
+bool kernel_page_present(struct page *page);
#include <asm-generic/cacheflush.h>
diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c
index 439325532be1..92eccaf595c8 100644
--- a/arch/arm64/mm/pageattr.c
+++ b/arch/arm64/mm/pageattr.c
@@ -186,8 +186,8 @@ void __kernel_map_pages(struct page *page, int numpages, int enable)
set_memory_valid((unsigned long)page_address(page), numpages, enable);
}
+#endif /* CONFIG_DEBUG_PAGEALLOC */
-#ifdef CONFIG_HIBERNATION
/*
* This function is used to determine if a linear map page has been marked as
* not-valid. Walk the page table and check the PTE_VALID bit. This is based
@@ -234,5 +234,3 @@ bool kernel_page_present(struct page *page)
ptep = pte_offset_kernel(pmdp, addr);
return pte_valid(READ_ONCE(*ptep));
}
-#endif /* CONFIG_HIBERNATION */
-#endif /* CONFIG_DEBUG_PAGEALLOC */
diff --git a/arch/riscv/include/asm/set_memory.h b/arch/riscv/include/asm/set_memory.h
index 4c5bae7ca01c..d690b08dff2a 100644
--- a/arch/riscv/include/asm/set_memory.h
+++ b/arch/riscv/include/asm/set_memory.h
@@ -24,6 +24,7 @@ static inline int set_memory_nx(unsigned long addr, int numpages) { return 0; }
int set_direct_map_invalid_noflush(struct page *page);
int set_direct_map_default_noflush(struct page *page);
+bool kernel_page_present(struct page *page);
#endif /* __ASSEMBLY__ */
diff --git a/arch/riscv/mm/pageattr.c b/arch/riscv/mm/pageattr.c
index 321b09d2e2ea..87ba5a68bbb8 100644
--- a/arch/riscv/mm/pageattr.c
+++ b/arch/riscv/mm/pageattr.c
@@ -198,3 +198,32 @@ void __kernel_map_pages(struct page *page, int numpages, int enable)
__pgprot(0), __pgprot(_PAGE_PRESENT));
}
#endif
+
+bool kernel_page_present(struct page *page)
+{
+ unsigned long addr = (unsigned long)page_address(page);
+ pgd_t *pgd;
+ pud_t *pud;
+ p4d_t *p4d;
+ pmd_t *pmd;
+ pte_t *pte;
+
+ pgd = pgd_offset_k(addr);
+ if (!pgd_present(*pgd))
+ return false;
+
+ p4d = p4d_offset(pgd, addr);
+ if (!p4d_present(*p4d))
+ return false;
+
+ pud = pud_offset(p4d, addr);
+ if (!pud_present(*pud))
+ return false;
+
+ pmd = pmd_offset(pud, addr);
+ if (!pmd_present(*pmd))
+ return false;
+
+ pte = pte_offset_kernel(pmd, addr);
+ return pte_present(*pte);
+}
diff --git a/arch/x86/include/asm/set_memory.h b/arch/x86/include/asm/set_memory.h
index 5948218f35c5..4352f08bfbb5 100644
--- a/arch/x86/include/asm/set_memory.h
+++ b/arch/x86/include/asm/set_memory.h
@@ -82,6 +82,7 @@ int set_pages_rw(struct page *page, int numpages);
int set_direct_map_invalid_noflush(struct page *page);
int set_direct_map_default_noflush(struct page *page);
+bool kernel_page_present(struct page *page);
extern int kernel_set_to_readonly;
diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
index bc9be96b777f..16f878c26667 100644
--- a/arch/x86/mm/pat/set_memory.c
+++ b/arch/x86/mm/pat/set_memory.c
@@ -2226,8 +2226,8 @@ void __kernel_map_pages(struct page *page, int numpages, int enable)
arch_flush_lazy_mmu_mode();
}
+#endif /* CONFIG_DEBUG_PAGEALLOC */
-#ifdef CONFIG_HIBERNATION
bool kernel_page_present(struct page *page)
{
unsigned int level;
@@ -2239,8 +2239,6 @@ bool kernel_page_present(struct page *page)
pte = lookup_address((unsigned long)page_address(page), &level);
return (pte_val(*pte) & _PAGE_PRESENT);
}
-#endif /* CONFIG_HIBERNATION */
-#endif /* CONFIG_DEBUG_PAGEALLOC */
int __init kernel_map_pages_in_pgd(pgd_t *pgd, u64 pfn, unsigned long address,
unsigned numpages, unsigned long page_flags)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 260113ba660a..fe9a8d35a6eb 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2942,16 +2942,9 @@ static inline void debug_pagealloc_unmap_pages(struct page *page, int numpages)
if (debug_pagealloc_enabled_static())
__kernel_map_pages(page, numpages, 0);
}
-
-#ifdef CONFIG_HIBERNATION
-extern bool kernel_page_present(struct page *page);
-#endif /* CONFIG_HIBERNATION */
#else /* CONFIG_DEBUG_PAGEALLOC */
static inline void debug_pagealloc_map_pages(struct page *page, int numpages) {}
static inline void debug_pagealloc_unmap_pages(struct page *page, int numpages) {}
-#ifdef CONFIG_HIBERNATION
-static inline bool kernel_page_present(struct page *page) { return true; }
-#endif /* CONFIG_HIBERNATION */
#endif /* CONFIG_DEBUG_PAGEALLOC */
#ifdef __HAVE_ARCH_GATE_AREA
diff --git a/include/linux/set_memory.h b/include/linux/set_memory.h
index 860e0f843c12..fe1aa4e54680 100644
--- a/include/linux/set_memory.h
+++ b/include/linux/set_memory.h
@@ -23,6 +23,11 @@ static inline int set_direct_map_default_noflush(struct page *page)
{
return 0;
}
+
+static inline bool kernel_page_present(struct page *page)
+{
+ return true;
+}
#endif
#ifndef set_mce_nospec
--
2.28.0
^ permalink raw reply related
* Re: [PATCH v6 0/4] arch, mm: improve robustness of direct map manipulation
From: Mike Rapoport @ 2020-11-09 16:47 UTC (permalink / raw)
To: Andrew Morton
Cc: David Hildenbrand, Peter Zijlstra, Dave Hansen, linux-mm,
Paul Mackerras, Pavel Machek, H. Peter Anvin, sparclinux,
Christoph Lameter, Will Deacon, linux-riscv, linux-s390, x86,
Mike Rapoport, Christian Borntraeger, Ingo Molnar,
linux-arm-kernel, Catalin Marinas, Len Brown, Albert Ou,
Vasily Gorbik, linux-pm, Heiko Carstens, David Rientjes,
Borislav Petkov, Andy Lutomirski, Paul Walmsley,
Kirill A. Shutemov, Thomas Gleixner, Vlastimil Babka,
Rafael J. Wysocki, linux-kernel, Pekka Enberg, Palmer Dabbelt,
Joonsoo Kim, Edgecombe, Rick P, linuxppc-dev, David S. Miller,
Kirill A . Shutemov
In-Reply-To: <20201109162415.13764-1-rppt@kernel.org>
Oops, this one has some rebase errors, I'll send v7 soon.
Sorry for the noise.
On Mon, Nov 09, 2020 at 06:24:11PM +0200, Mike Rapoport wrote:
> From: Mike Rapoport <rppt@linux.ibm.com>
>
> Hi,
>
> During recent discussion about KVM protected memory, David raised a concern
> about usage of __kernel_map_pages() outside of DEBUG_PAGEALLOC scope [1].
>
> Indeed, for architectures that define CONFIG_ARCH_HAS_SET_DIRECT_MAP it is
> possible that __kernel_map_pages() would fail, but since this function is
> void, the failure will go unnoticed.
>
> Moreover, there's lack of consistency of __kernel_map_pages() semantics
> across architectures as some guard this function with
> #ifdef DEBUG_PAGEALLOC, some refuse to update the direct map if page
> allocation debugging is disabled at run time and some allow modifying the
> direct map regardless of DEBUG_PAGEALLOC settings.
>
> This set straightens this out by restoring dependency of
> __kernel_map_pages() on DEBUG_PAGEALLOC and updating the call sites
> accordingly.
>
> Since currently the only user of __kernel_map_pages() outside
> DEBUG_PAGEALLOC is hibernation, it is updated to make direct map accesses
> there more explicit.
>
> [1] https://lore.kernel.org/lkml/2759b4bf-e1e3-d006-7d86-78a40348269d@redhat.com
>
> v6 changes:
> * revert slab changes to avoid redundant check of static key
>
> v5 changes:
> * use pairs of _map()/_unmap() functions instead of _map(..., int enable) as
> Vlastimil suggested
> https://lore.kernel.org/lkml/20201108065758.1815-1-rppt@kernel.org
>
> v4 changes:
> * s/WARN_ON/pr_warn_once/ per David and Kirill
> * rebase on v5.10-rc2
> * add Acked/Reviewed tags
> https://lore.kernel.org/lkml/20201103162057.22916-1-rppt@kernel.org
>
> v3 changes:
> * update arm64 changes to avoid regression, per Rick's comments
> * fix bisectability
> https://lore.kernel.org/lkml/20201101170815.9795-1-rppt@kernel.org
>
> v2 changes:
> * Rephrase patch 2 changelog to better describe the change intentions and
> implications
> * Move removal of kernel_map_pages() from patch 1 to patch 2, per David
> https://lore.kernel.org/lkml/20201029161902.19272-1-rppt@kernel.org
>
> v1:
> https://lore.kernel.org/lkml/20201025101555.3057-1-rppt@kernel.org
>
> Mike Rapoport (4):
> mm: introduce debug_pagealloc_{map,unmap}_pages() helpers
> PM: hibernate: make direct map manipulations more explicit
> arch, mm: restore dependency of __kernel_map_pages() on DEBUG_PAGEALLOC
> arch, mm: make kernel_page_present() always available
>
> arch/Kconfig | 3 +++
> arch/arm64/Kconfig | 4 +--
> arch/arm64/include/asm/cacheflush.h | 1 +
> arch/arm64/mm/pageattr.c | 6 +++--
> arch/powerpc/Kconfig | 5 +---
> arch/riscv/Kconfig | 4 +--
> arch/riscv/include/asm/pgtable.h | 2 --
> arch/riscv/include/asm/set_memory.h | 1 +
> arch/riscv/mm/pageattr.c | 31 ++++++++++++++++++++++
> arch/s390/Kconfig | 4 +--
> arch/sparc/Kconfig | 4 +--
> arch/x86/Kconfig | 4 +--
> arch/x86/include/asm/set_memory.h | 1 +
> arch/x86/mm/pat/set_memory.c | 4 +--
> include/linux/mm.h | 40 ++++++++++++++---------------
> include/linux/set_memory.h | 5 ++++
> kernel/power/snapshot.c | 38 +++++++++++++++++++++++++--
> mm/memory_hotplug.c | 3 +--
> mm/page_alloc.c | 6 ++---
> 19 files changed, 113 insertions(+), 53 deletions(-)
>
> --
> 2.28.0
>
--
Sincerely yours,
Mike.
^ permalink raw reply
* [PATCH for 5.4] powerpc/603: Always fault when _PAGE_ACCESSED is not set
From: Christophe Leroy @ 2020-11-09 17:40 UTC (permalink / raw)
To: gregkh, stable; +Cc: linuxppc-dev, linux-kernel
[That is backport of 11522448e641e8f1690c9db06e01985e8e19b401 to linux 5.4]
The kernel expects pte_young() to work regardless of CONFIG_SWAP.
Make sure a minor fault is taken to set _PAGE_ACCESSED when it
is not already set, regardless of the selection of CONFIG_SWAP.
Fixes: 84de6ab0e904 ("powerpc/603: don't handle PAGE_ACCESSED in TLB miss handlers.")
Cc: stable@vger.kernel.org
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/a44367744de54e2315b2f1a8cbbd7f88488072e0.1602342806.git.christophe.leroy@csgroup.eu
---
arch/powerpc/kernel/head_32.S | 12 ------------
1 file changed, 12 deletions(-)
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S
index 5e2f2fd78b94..126ba5438430 100644
--- a/arch/powerpc/kernel/head_32.S
+++ b/arch/powerpc/kernel/head_32.S
@@ -418,11 +418,7 @@ InstructionTLBMiss:
cmplw 0,r1,r3
#endif
mfspr r2, SPRN_SPRG_PGDIR
-#ifdef CONFIG_SWAP
li r1,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC
-#else
- li r1,_PAGE_PRESENT | _PAGE_EXEC
-#endif
#if defined(CONFIG_MODULES) || defined(CONFIG_DEBUG_PAGEALLOC)
bge- 112f
lis r2, (swapper_pg_dir - PAGE_OFFSET)@ha /* if kernel address, use */
@@ -484,11 +480,7 @@ DataLoadTLBMiss:
lis r1,PAGE_OFFSET@h /* check if kernel address */
cmplw 0,r1,r3
mfspr r2, SPRN_SPRG_PGDIR
-#ifdef CONFIG_SWAP
li r1, _PAGE_PRESENT | _PAGE_ACCESSED
-#else
- li r1, _PAGE_PRESENT
-#endif
bge- 112f
lis r2, (swapper_pg_dir - PAGE_OFFSET)@ha /* if kernel address, use */
addi r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l /* kernel page table */
@@ -564,11 +556,7 @@ DataStoreTLBMiss:
lis r1,PAGE_OFFSET@h /* check if kernel address */
cmplw 0,r1,r3
mfspr r2, SPRN_SPRG_PGDIR
-#ifdef CONFIG_SWAP
li r1, _PAGE_RW | _PAGE_DIRTY | _PAGE_PRESENT | _PAGE_ACCESSED
-#else
- li r1, _PAGE_RW | _PAGE_DIRTY | _PAGE_PRESENT
-#endif
bge- 112f
lis r2, (swapper_pg_dir - PAGE_OFFSET)@ha /* if kernel address, use */
addi r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l /* kernel page table */
--
2.25.0
^ permalink raw reply related
* [PATCH] powerpc/603: Always fault when _PAGE_ACCESSED is not set
From: Christophe Leroy @ 2020-11-09 17:46 UTC (permalink / raw)
To: gregkh, stable; +Cc: linuxppc-dev, linux-kernel
[That is backport of 11522448e641e8f1690c9db06e01985e8e19b401 to linux 5.9]
The kernel expects pte_young() to work regardless of CONFIG_SWAP.
Make sure a minor fault is taken to set _PAGE_ACCESSED when it
is not already set, regardless of the selection of CONFIG_SWAP.
Fixes: 84de6ab0e904 ("powerpc/603: don't handle PAGE_ACCESSED in TLB miss handlers.")
Cc: stable@vger.kernel.org
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/a44367744de54e2315b2f1a8cbbd7f88488072e0.1602342806.git.christophe.leroy@csgroup.eu
---
arch/powerpc/kernel/head_32.S | 12 ------------
1 file changed, 12 deletions(-)
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S
index a5a612deef66..898c2fe4ac67 100644
--- a/arch/powerpc/kernel/head_32.S
+++ b/arch/powerpc/kernel/head_32.S
@@ -472,11 +472,7 @@ InstructionTLBMiss:
cmplw 0,r1,r3
#endif
mfspr r2, SPRN_SPRG_PGDIR
-#ifdef CONFIG_SWAP
li r1,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC
-#else
- li r1,_PAGE_PRESENT | _PAGE_EXEC
-#endif
#if defined(CONFIG_MODULES) || defined(CONFIG_DEBUG_PAGEALLOC)
bgt- 112f
lis r2, (swapper_pg_dir - PAGE_OFFSET)@ha /* if kernel address, use */
@@ -538,11 +534,7 @@ DataLoadTLBMiss:
lis r1, TASK_SIZE@h /* check if kernel address */
cmplw 0,r1,r3
mfspr r2, SPRN_SPRG_PGDIR
-#ifdef CONFIG_SWAP
li r1, _PAGE_PRESENT | _PAGE_ACCESSED
-#else
- li r1, _PAGE_PRESENT
-#endif
bgt- 112f
lis r2, (swapper_pg_dir - PAGE_OFFSET)@ha /* if kernel address, use */
addi r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l /* kernel page table */
@@ -618,11 +610,7 @@ DataStoreTLBMiss:
lis r1, TASK_SIZE@h /* check if kernel address */
cmplw 0,r1,r3
mfspr r2, SPRN_SPRG_PGDIR
-#ifdef CONFIG_SWAP
li r1, _PAGE_RW | _PAGE_DIRTY | _PAGE_PRESENT | _PAGE_ACCESSED
-#else
- li r1, _PAGE_RW | _PAGE_DIRTY | _PAGE_PRESENT
-#endif
bgt- 112f
lis r2, (swapper_pg_dir - PAGE_OFFSET)@ha /* if kernel address, use */
addi r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l /* kernel page table */
--
2.25.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox