summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Gordeev <agordeev@linux.ibm.com>2021-06-18 08:39:12 +0200
committerAlexander Gordeev <agordeev@linux.ibm.com>2022-12-01 10:58:04 +0100
commit5c2e5a0cf5b12c156b0cb07af43b51627c086480 (patch)
treebd5b9271732eff13b5fc28198546086204fdb96a
parent1143f6f55d967ab414a10a559d58a2700f32a54d (diff)
s390/cio: sort out physical vs virtual pointers usage
This does not fix a real bug, since virtual addresses are currently indentical to physical ones. Use virt_to_phys() for intparm interrupt parameter to convert a 64-bit virtual address to the 32-bit physical address, which is expected to be below 2GB. Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com> Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
-rw-r--r--drivers/s390/cio/chsc_sch.c3
-rw-r--r--drivers/s390/cio/cio.c14
-rw-r--r--drivers/s390/cio/device.c2
-rw-r--r--drivers/s390/cio/device_fsm.c13
-rw-r--r--drivers/s390/cio/device_id.c2
-rw-r--r--drivers/s390/cio/device_pgid.c11
-rw-r--r--drivers/s390/cio/device_status.c3
-rw-r--r--drivers/s390/cio/eadm_sch.c9
-rw-r--r--drivers/s390/cio/fcx.c23
-rw-r--r--drivers/s390/cio/itcw.c3
10 files changed, 45 insertions, 38 deletions
diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c
index 962dfa25a310..180ab899289c 100644
--- a/drivers/s390/cio/chsc_sch.c
+++ b/drivers/s390/cio/chsc_sch.c
@@ -11,6 +11,7 @@
#include <linux/slab.h>
#include <linux/compat.h>
#include <linux/device.h>
+#include <linux/io.h>
#include <linux/module.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
@@ -85,7 +86,7 @@ static int chsc_subchannel_probe(struct subchannel *sch)
if (!private)
return -ENOMEM;
dev_set_drvdata(&sch->dev, private);
- ret = cio_enable_subchannel(sch, (u32)(unsigned long)sch);
+ ret = cio_enable_subchannel(sch, (u32)virt_to_phys(sch));
if (ret) {
CHSC_MSG(0, "Failed to enable 0.%x.%04x: %d\n",
sch->schid.ssid, sch->schid.sch_no, ret);
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 923f5ca4f5e6..6127add746d1 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -134,7 +134,7 @@ cio_start_key (struct subchannel *sch, /* subchannel structure */
memset(orb, 0, sizeof(union orb));
/* sch is always under 2G. */
- orb->cmd.intparm = (u32)(addr_t)sch;
+ orb->cmd.intparm = (u32)virt_to_phys(sch);
orb->cmd.fmt = 1;
orb->cmd.pfch = priv->options.prefetch == 0;
@@ -148,7 +148,7 @@ cio_start_key (struct subchannel *sch, /* subchannel structure */
orb->cmd.i2k = 0;
orb->cmd.key = key >> 4;
/* issue "Start Subchannel" */
- orb->cmd.cpa = (__u32) __pa(cpa);
+ orb->cmd.cpa = (u32)virt_to_phys(cpa);
ccode = ssch(sch->schid, orb);
/* process condition code */
@@ -539,13 +539,13 @@ static irqreturn_t do_cio_interrupt(int irq, void *dummy)
tpi_info = &get_irq_regs()->tpi_info;
trace_s390_cio_interrupt(tpi_info);
irb = this_cpu_ptr(&cio_irb);
- sch = (struct subchannel *)(unsigned long) tpi_info->intparm;
- if (!sch) {
+ if (!tpi_info->intparm) {
/* Clear pending interrupt condition. */
inc_irq_stat(IRQIO_CIO);
tsch(tpi_info->schid, irb);
return IRQ_HANDLED;
}
+ sch = phys_to_virt(tpi_info->intparm);
spin_lock(sch->lock);
/* Store interrupt response block to lowcore. */
if (tsch(tpi_info->schid, irb) == 0) {
@@ -666,7 +666,7 @@ struct subchannel *cio_probe_console(void)
lockdep_set_class(sch->lock, &console_sch_key);
isc_register(CONSOLE_ISC);
sch->config.isc = CONSOLE_ISC;
- sch->config.intparm = (u32)(addr_t)sch;
+ sch->config.intparm = (u32)virt_to_phys(sch);
ret = cio_commit_config(sch);
if (ret) {
isc_unregister(CONSOLE_ISC);
@@ -713,11 +713,11 @@ int cio_tm_start_key(struct subchannel *sch, struct tcw *tcw, u8 lpm, u8 key)
union orb *orb = &to_io_private(sch)->orb;
memset(orb, 0, sizeof(union orb));
- orb->tm.intparm = (u32) (addr_t) sch;
+ orb->tm.intparm = (u32)virt_to_phys(sch);
orb->tm.key = key >> 4;
orb->tm.b = 1;
orb->tm.lpm = lpm ? lpm : sch->lpm;
- orb->tm.tcw = (u32) (addr_t) tcw;
+ orb->tm.tcw = (u32)virt_to_phys(tcw);
cc = ssch(sch->schid, orb);
switch (cc) {
case 0:
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 3b1cd0c96a74..9e0cf44ff9d4 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -936,7 +936,7 @@ static int ccw_device_move_to_sch(struct ccw_device *cdev,
if (old_enabled) {
/* Try to reenable the old subchannel. */
spin_lock_irq(old_sch->lock);
- cio_enable_subchannel(old_sch, (u32)(addr_t)old_sch);
+ cio_enable_subchannel(old_sch, (u32)virt_to_phys(old_sch));
spin_unlock_irq(old_sch->lock);
}
/* Release child reference for new parent. */
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 6d63b968309a..2b2058427a2b 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -9,6 +9,7 @@
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/io.h>
#include <linux/jiffies.h>
#include <linux/string.h>
@@ -63,7 +64,7 @@ static void ccw_timeout_log(struct ccw_device *cdev)
printk(KERN_WARNING "cio: orb indicates transport mode\n");
printk(KERN_WARNING "cio: last tcw:\n");
print_hex_dump(KERN_WARNING, "cio: ", DUMP_PREFIX_NONE, 16, 1,
- (void *)(addr_t)orb->tm.tcw,
+ phys_to_virt(orb->tm.tcw),
sizeof(struct tcw), 0);
} else {
printk(KERN_WARNING "cio: orb indicates command mode\n");
@@ -77,7 +78,7 @@ static void ccw_timeout_log(struct ccw_device *cdev)
printk(KERN_WARNING "cio: last channel program:\n");
print_hex_dump(KERN_WARNING, "cio: ", DUMP_PREFIX_NONE, 16, 1,
- (void *)(addr_t)orb->cmd.cpa,
+ phys_to_virt(orb->cmd.cpa),
sizeof(struct ccw1), 0);
}
printk(KERN_WARNING "cio: ccw device state: %d\n",
@@ -397,7 +398,7 @@ void ccw_device_recognition(struct ccw_device *cdev)
*/
cdev->private->flags.recog_done = 0;
cdev->private->state = DEV_STATE_SENSE_ID;
- if (cio_enable_subchannel(sch, (u32) (addr_t) sch)) {
+ if (cio_enable_subchannel(sch, (u32)virt_to_phys(sch))) {
ccw_device_recog_done(cdev, DEV_STATE_NOT_OPER);
return;
}
@@ -548,7 +549,7 @@ ccw_device_online(struct ccw_device *cdev)
(cdev->private->state != DEV_STATE_BOXED))
return -EINVAL;
sch = to_subchannel(cdev->dev.parent);
- ret = cio_enable_subchannel(sch, (u32)(addr_t)sch);
+ ret = cio_enable_subchannel(sch, (u32)virt_to_phys(sch));
if (ret != 0) {
/* Couldn't enable the subchannel for i/o. Sick device. */
if (ret == -ENODEV)
@@ -691,7 +692,7 @@ static void ccw_device_boxed_verify(struct ccw_device *cdev,
struct subchannel *sch = to_subchannel(cdev->dev.parent);
if (cdev->online) {
- if (cio_enable_subchannel(sch, (u32) (addr_t) sch))
+ if (cio_enable_subchannel(sch, (u32)virt_to_phys(sch)))
ccw_device_done(cdev, DEV_STATE_NOT_OPER);
else
ccw_device_online_verify(cdev, dev_event);
@@ -922,7 +923,7 @@ ccw_device_start_id(struct ccw_device *cdev, enum dev_event dev_event)
struct subchannel *sch;
sch = to_subchannel(cdev->dev.parent);
- if (cio_enable_subchannel(sch, (u32)(addr_t)sch) != 0)
+ if (cio_enable_subchannel(sch, (u32)virt_to_phys(sch)) != 0)
/* Couldn't enable the subchannel for i/o. Sick device. */
return;
cdev->private->state = DEV_STATE_DISCONNECTED_SENSE_ID;
diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c
index 7835a87a60b5..ce99ee2457e6 100644
--- a/drivers/s390/cio/device_id.c
+++ b/drivers/s390/cio/device_id.c
@@ -210,7 +210,7 @@ void ccw_device_sense_id_start(struct ccw_device *cdev)
snsid_init(cdev);
/* Channel program setup. */
cp->cmd_code = CCW_CMD_SENSE_ID;
- cp->cda = (u32) (addr_t) &cdev->private->dma_area->senseid;
+ cp->cda = (u32)virt_to_phys(&cdev->private->dma_area->senseid);
cp->count = sizeof(struct senseid);
cp->flags = CCW_FLAG_SLI;
/* Request setup. */
diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c
index 767a85635a0f..3862961697eb 100644
--- a/drivers/s390/cio/device_pgid.c
+++ b/drivers/s390/cio/device_pgid.c
@@ -14,6 +14,7 @@
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/slab.h>
+#include <linux/io.h>
#include <asm/ccwdev.h>
#include <asm/cio.h>
@@ -140,7 +141,7 @@ static void spid_build_cp(struct ccw_device *cdev, u8 fn)
pgid->inf.fc = fn;
cp->cmd_code = CCW_CMD_SET_PGID;
- cp->cda = (u32) (addr_t) pgid;
+ cp->cda = (u32)virt_to_phys(pgid);
cp->count = sizeof(*pgid);
cp->flags = CCW_FLAG_SLI;
req->cp = cp;
@@ -441,7 +442,7 @@ static void snid_build_cp(struct ccw_device *cdev)
/* Channel program setup. */
cp->cmd_code = CCW_CMD_SENSE_PGID;
- cp->cda = (u32) (addr_t) &cdev->private->dma_area->pgid[i];
+ cp->cda = (u32)virt_to_phys(&cdev->private->dma_area->pgid[i]);
cp->count = sizeof(struct pgid);
cp->flags = CCW_FLAG_SLI;
req->cp = cp;
@@ -631,11 +632,11 @@ static void stlck_build_cp(struct ccw_device *cdev, void *buf1, void *buf2)
struct ccw1 *cp = cdev->private->dma_area->iccws;
cp[0].cmd_code = CCW_CMD_STLCK;
- cp[0].cda = (u32) (addr_t) buf1;
+ cp[0].cda = (u32)virt_to_phys(buf1);
cp[0].count = 32;
cp[0].flags = CCW_FLAG_CC;
cp[1].cmd_code = CCW_CMD_RELEASE;
- cp[1].cda = (u32) (addr_t) buf2;
+ cp[1].cda = (u32)virt_to_phys(buf2);
cp[1].count = 32;
cp[1].flags = 0;
req->cp = cp;
@@ -698,7 +699,7 @@ int ccw_device_stlck(struct ccw_device *cdev)
init_completion(&data.done);
data.rc = -EIO;
spin_lock_irq(sch->lock);
- rc = cio_enable_subchannel(sch, (u32) (addr_t) sch);
+ rc = cio_enable_subchannel(sch, (u32)virt_to_phys(sch));
if (rc)
goto out_unlock;
/* Perform operation. */
diff --git a/drivers/s390/cio/device_status.c b/drivers/s390/cio/device_status.c
index 0bd8f2642732..6c2e35065fec 100644
--- a/drivers/s390/cio/device_status.c
+++ b/drivers/s390/cio/device_status.c
@@ -9,6 +9,7 @@
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/io.h>
#include <asm/ccwdev.h>
#include <asm/cio.h>
@@ -331,7 +332,7 @@ ccw_device_do_sense(struct ccw_device *cdev, struct irb *irb)
*/
sense_ccw = &to_io_private(sch)->dma_area->sense_ccw;
sense_ccw->cmd_code = CCW_CMD_BASIC_SENSE;
- sense_ccw->cda = (__u32) __pa(cdev->private->dma_area->irb.ecw);
+ sense_ccw->cda = virt_to_phys(cdev->private->dma_area->irb.ecw);
sense_ccw->count = SENSE_MAX_COUNT;
sense_ccw->flags = CCW_FLAG_SLI;
diff --git a/drivers/s390/cio/eadm_sch.c b/drivers/s390/cio/eadm_sch.c
index ab6a7495180a..826364d2facd 100644
--- a/drivers/s390/cio/eadm_sch.c
+++ b/drivers/s390/cio/eadm_sch.c
@@ -15,6 +15,7 @@
#include <linux/timer.h>
#include <linux/slab.h>
#include <linux/list.h>
+#include <linux/io.h>
#include <asm/css_chars.h>
#include <asm/debug.h>
@@ -62,8 +63,8 @@ static int eadm_subchannel_start(struct subchannel *sch, struct aob *aob)
int cc;
orb_init(orb);
- orb->eadm.aob = (u32)__pa(aob);
- orb->eadm.intparm = (u32)(addr_t)sch;
+ orb->eadm.aob = (u32)virt_to_phys(aob);
+ orb->eadm.intparm = (u32)virt_to_phys(sch);
orb->eadm.key = PAGE_DEFAULT_KEY >> 4;
EADM_LOG(6, "start");
@@ -146,7 +147,7 @@ static void eadm_subchannel_irq(struct subchannel *sch)
css_sched_sch_todo(sch, SCH_TODO_EVAL);
return;
}
- scm_irq_handler((struct aob *)(unsigned long)scsw->aob, error);
+ scm_irq_handler(phys_to_virt(scsw->aob), error);
private->state = EADM_IDLE;
if (private->completion)
@@ -225,7 +226,7 @@ static int eadm_subchannel_probe(struct subchannel *sch)
private->state = EADM_IDLE;
private->sch = sch;
sch->isc = EADM_SCH_ISC;
- ret = cio_enable_subchannel(sch, (u32)(unsigned long)sch);
+ ret = cio_enable_subchannel(sch, (u32)virt_to_phys(sch));
if (ret) {
set_eadm_private(sch, NULL);
spin_unlock_irq(sch->lock);
diff --git a/drivers/s390/cio/fcx.c b/drivers/s390/cio/fcx.c
index 99c900cc3e5b..84f24a2f46e4 100644
--- a/drivers/s390/cio/fcx.c
+++ b/drivers/s390/cio/fcx.c
@@ -9,6 +9,7 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/string.h>
+#include <linux/io.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/module.h>
@@ -24,7 +25,7 @@
*/
struct tcw *tcw_get_intrg(struct tcw *tcw)
{
- return (struct tcw *) ((addr_t) tcw->intrg);
+ return phys_to_virt(tcw->intrg);
}
EXPORT_SYMBOL(tcw_get_intrg);
@@ -39,9 +40,9 @@ EXPORT_SYMBOL(tcw_get_intrg);
void *tcw_get_data(struct tcw *tcw)
{
if (tcw->r)
- return (void *) ((addr_t) tcw->input);
+ return phys_to_virt(tcw->input);
if (tcw->w)
- return (void *) ((addr_t) tcw->output);
+ return phys_to_virt(tcw->output);
return NULL;
}
EXPORT_SYMBOL(tcw_get_data);
@@ -54,7 +55,7 @@ EXPORT_SYMBOL(tcw_get_data);
*/
struct tccb *tcw_get_tccb(struct tcw *tcw)
{
- return (struct tccb *) ((addr_t) tcw->tccb);
+ return phys_to_virt(tcw->tccb);
}
EXPORT_SYMBOL(tcw_get_tccb);
@@ -66,7 +67,7 @@ EXPORT_SYMBOL(tcw_get_tccb);
*/
struct tsb *tcw_get_tsb(struct tcw *tcw)
{
- return (struct tsb *) ((addr_t) tcw->tsb);
+ return phys_to_virt(tcw->tsb);
}
EXPORT_SYMBOL(tcw_get_tsb);
@@ -189,7 +190,7 @@ EXPORT_SYMBOL(tcw_finalize);
*/
void tcw_set_intrg(struct tcw *tcw, struct tcw *intrg_tcw)
{
- tcw->intrg = (u32) ((addr_t) intrg_tcw);
+ tcw->intrg = (u32)virt_to_phys(intrg_tcw);
}
EXPORT_SYMBOL(tcw_set_intrg);
@@ -207,11 +208,11 @@ EXPORT_SYMBOL(tcw_set_intrg);
void tcw_set_data(struct tcw *tcw, void *data, int use_tidal)
{
if (tcw->r) {
- tcw->input = (u64) ((addr_t) data);
+ tcw->input = virt_to_phys(data);
if (use_tidal)
tcw->flags |= TCW_FLAGS_INPUT_TIDA;
} else if (tcw->w) {
- tcw->output = (u64) ((addr_t) data);
+ tcw->output = virt_to_phys(data);
if (use_tidal)
tcw->flags |= TCW_FLAGS_OUTPUT_TIDA;
}
@@ -227,7 +228,7 @@ EXPORT_SYMBOL(tcw_set_data);
*/
void tcw_set_tccb(struct tcw *tcw, struct tccb *tccb)
{
- tcw->tccb = (u64) ((addr_t) tccb);
+ tcw->tccb = virt_to_phys(tccb);
}
EXPORT_SYMBOL(tcw_set_tccb);
@@ -240,7 +241,7 @@ EXPORT_SYMBOL(tcw_set_tccb);
*/
void tcw_set_tsb(struct tcw *tcw, struct tsb *tsb)
{
- tcw->tsb = (u64) ((addr_t) tsb);
+ tcw->tsb = virt_to_phys(tsb);
}
EXPORT_SYMBOL(tcw_set_tsb);
@@ -345,7 +346,7 @@ struct tidaw *tcw_add_tidaw(struct tcw *tcw, int num_tidaws, u8 flags,
memset(tidaw, 0, sizeof(struct tidaw));
tidaw->flags = flags;
tidaw->count = count;
- tidaw->addr = (u64) ((addr_t) addr);
+ tidaw->addr = virt_to_phys(addr);
return tidaw;
}
EXPORT_SYMBOL(tcw_add_tidaw);
diff --git a/drivers/s390/cio/itcw.c b/drivers/s390/cio/itcw.c
index 19e46363348c..dbd3099c520e 100644
--- a/drivers/s390/cio/itcw.c
+++ b/drivers/s390/cio/itcw.c
@@ -9,6 +9,7 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/string.h>
+#include <linux/io.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/module.h>
@@ -187,7 +188,7 @@ struct itcw *itcw_init(void *buffer, size_t size, int op, int intrg,
/* Check for 2G limit. */
start = (addr_t) buffer;
end = start + size;
- if (end > (1 << 31))
+ if ((virt_to_phys(buffer) + size) > (1 << 31))
return ERR_PTR(-EINVAL);
memset(buffer, 0, size);
/* ITCW. */