Skip to contentSkip to conversation

Fix pointer cast for 32 bits arch

PATCH Superseded Peter Senna Tschudin 6 participants 30 messages Apr 12, 2015 – May 19, 2015

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Fix pointer cast for 32 bits arch

Sparse compalins about casting void * to u64 on i386. Change the cast to resource_size_t.

---

Tested by compilation only. Tested for x86 and x86_64.

 drivers/staging/goldfish/goldfish_nand.c | 3 ++-
 include/linux/goldfish.h                 | 2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)
drivers/staging/goldfish/goldfish_nand.c +2 -1
index d68f216..738fdc4 100644
@@ -87,7 +87,8 @@ static u32 goldfish_nand_cmd(struct mtd_info *mtd, enum nand_cmd cmd,
 		writel((u32)(addr >> 32), base + NAND_ADDR_HIGH);
 		writel((u32)addr, base + NAND_ADDR_LOW);
 		writel(len, base + NAND_TRANSFER_SIZE);
-		gf_write64((u64)ptr, base + NAND_DATA, base + NAND_DATA_HIGH);
+		gf_write64((resource_size_t)ptr, base + NAND_DATA,
+			   base + NAND_DATA_HIGH);
 		writel(cmd, base + NAND_COMMAND);
 		rv = readl(base + NAND_RESULT);
 	}
include/linux/goldfish.h +1 -1
index 569236e..494e943 100644
@@ -3,7 +3,7 @@
 
 /* Helpers for Goldfish virtual platform */
 
-static inline void gf_write64(unsigned long data,
+static inline void gf_write64(resource_size_t data,
 		void __iomem *portl, void __iomem *porth)
 {
 	writel((u32)data, portl);
Signature · 1 line
2.1.0
#1 lore raw
Quoted 17 lines · Peter Senna Tschudin

Sparse compalins about casting void * to u64 on i386. Change the cast to resource_size_t.

---

Tested by compilation only. Tested for x86 and x86_64.

 drivers/staging/goldfish/goldfish_nand.c | 3 ++-
 include/linux/goldfish.h                 | 2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)
drivers/staging/goldfish/goldfish_nand.c +0 -0
index d68f216..738fdc4 100644

drivers/staging/goldfish/goldfish_nand.c static u32 goldfish_nand_cmd(struct mtd_info *mtd, enum nand_cmd cmd, · line 91

Quoted 6 lines
drivers/staging/goldfish/goldfish_nand.c +2 -1
@@ -87,7 +87,8 @@ static u32 goldfish_nand_cmd(struct mtd_info *mtd, enum nand_cmd cmd,
                writel((u32)(addr >> 32), base + NAND_ADDR_HIGH);
                writel((u32)addr, base + NAND_ADDR_LOW);
                writel(len, base + NAND_TRANSFER_SIZE);
-               gf_write64((u64)ptr, base + NAND_DATA, base + NAND_DATA_HIGH);
+               gf_write64((resource_size_t)ptr, base + NAND_DATA,
+                          base + NAND_DATA_HIGH);

I guess sparse still complains if CONFIG_X86_PAE=y, which makes resource_size_t u64?

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds

#2 lore raw
Quoted 14 lines · Geert Uytterhoeven
Quoted 12 lines · Peter Senna Tschudin

Sparse compalins about casting void * to u64 on i386. Change the cast to resource_size_t.

---

Tested by compilation only. Tested for x86 and x86_64.

 drivers/staging/goldfish/goldfish_nand.c | 3 ++-
 include/linux/goldfish.h                 | 2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)
Quoted 14 lines

drivers/staging/goldfish/goldfish_nand.c static u32 goldfish_nand_cmd(struct mtd_info *mtd, enum nand_cmd cmd, · line 91

Quoted 11 lines
drivers/staging/goldfish/goldfish_nand.c +2 -1
index d68f216..738fdc4 100644
@@ -87,7 +87,8 @@ static u32 goldfish_nand_cmd(struct mtd_info *mtd, enum nand_cmd cmd,
                writel((u32)(addr >> 32), base + NAND_ADDR_HIGH);
                writel((u32)addr, base + NAND_ADDR_LOW);
                writel(len, base + NAND_TRANSFER_SIZE);
-               gf_write64((u64)ptr, base + NAND_DATA, base + NAND_DATA_HIGH);
+               gf_write64((resource_size_t)ptr, base + NAND_DATA,
+                          base + NAND_DATA_HIGH);

I guess sparse still complains if CONFIG_X86_PAE=y, which makes resource_size_t u64?

Yes, when CONFIG_X86_PAE=y the patch doesn't fix the warning(gcc warning). What is the correct/portable way of fixing this?

Quoted 11 lines

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds

Signature · 1 line
Peter
#3 lore raw
Quoted 31 lines · Peter Senna Tschudin
Quoted 14 lines · Geert Uytterhoeven
Quoted 12 lines · Peter Senna Tschudin

Sparse compalins about casting void * to u64 on i386. Change the cast to resource_size_t.

---

Tested by compilation only. Tested for x86 and x86_64.

 drivers/staging/goldfish/goldfish_nand.c | 3 ++-
 include/linux/goldfish.h                 | 2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)
Quoted 14 lines

drivers/staging/goldfish/goldfish_nand.c static u32 goldfish_nand_cmd(struct mtd_info *mtd, enum nand_cmd cmd, · line 91

Quoted 11 lines
drivers/staging/goldfish/goldfish_nand.c +2 -1
index d68f216..738fdc4 100644
@@ -87,7 +87,8 @@ static u32 goldfish_nand_cmd(struct mtd_info *mtd, enum nand_cmd cmd,
                writel((u32)(addr >> 32), base + NAND_ADDR_HIGH);
                writel((u32)addr, base + NAND_ADDR_LOW);
                writel(len, base + NAND_TRANSFER_SIZE);
-               gf_write64((u64)ptr, base + NAND_DATA, base + NAND_DATA_HIGH);
+               gf_write64((resource_size_t)ptr, base + NAND_DATA,
+                          base + NAND_DATA_HIGH);

I guess sparse still complains if CONFIG_X86_PAE=y, which makes resource_size_t u64?

Quoted 2 lines

Yes, when CONFIG_X86_PAE=y the patch doesn't fix the warning(gcc warning). What is the correct/portable way of fixing this?

As gf_write64() takes "unsigned long data" for its first argument, why not simply cast ptr to "unsigned long"? "void *" and "unsigned long" have the same size on all Linux platforms.

Seems like there a several silly casting tricks being done in the goldfish drivers:

$ git grep -w gf_write64drivers/platform/goldfish/goldfish_pipe.c:
 gf_write64((u64)(unsigned long)p
drivers/platform/goldfish/goldfish_pipe.c:      gf_write64((u64)(unsigned long)p
drivers/platform/goldfish/goldfish_pipe.c:                      gf_write64((u64)
drivers/platform/goldfish/goldfish_pipe.c:                      gf_write64(addre
drivers/staging/goldfish/goldfish_audio.c:      (gf_write64((u64)(x), data->reg_
drivers/staging/goldfish/goldfish_nand.c:               gf_write64((u64)ptr, bas
drivers/tty/goldfish.c: gf_write64((u64)buf, base + GOLDFISH_TTY_DATA_PTR,
drivers/tty/goldfish.c: gf_write64((u64)buf, base + GOLDFISH_TTY_DATA_PTR,
include/linux/goldfish.h:static inline void gf_write64(unsigned long data,

with interesting history showing one wrong cast being "fixed" using another wrong cast:

commit f4e131dc38d34469b9fee1840ad237324831bce3

Author: Octavian Purdila <[email protected]>
Date:   Fri May 16 08:24:59 2014 +0300

goldfish: pipe: fix warnings for 32bit builds

- gf_write64((u64)pipe, dev->base + PIPE_REG_CHANNEL,
+ gf_write64((u64)(unsigned long)pipe, dev->base + PIPE_REG_CHANNEL,

As in general casts don't belong in drivers[*], what about creating an inline helper gf_set_pipe() that converts the pointer to unsigned long and calls gf_write64()?

Perhaps checkpatch should complain about casts outside header files?

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds

#4 lore raw
Quoted 1 line · Geert Uytterhoeven

Perhaps checkpatch should complain about casts outside header files?

I think that's not feasible/desirable.

type casting is pretty common and necessary.
There are 50k+ casts in drivers/ alone.

#5 lore raw
Quoted 7 lines · Joe Perches
Quoted 1 line · Geert Uytterhoeven

Perhaps checkpatch should complain about casts outside header files?

I think that's not feasible/desirable.

type casting is pretty common and necessary.
There are 50k+ casts in drivers/ alone.

What a pity.... How many of those are wrong? ;-)

If there's one thing I like about C++, it's the new-style casts, and how easy they are to grep for, unlike their C counterparts.

It would help if gcc offered -Wcast, so we could at least identify all newly introduced casts by comparing build logs, and audit them manually (like with other warnings).

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds

#6 lore raw
In reply to Geert Uytterhoeven
Quoted 66 lines · Geert Uytterhoeven
Quoted 31 lines · Peter Senna Tschudin
Quoted 14 lines · Geert Uytterhoeven
Quoted 12 lines · Peter Senna Tschudin

Sparse compalins about casting void * to u64 on i386. Change the cast to resource_size_t.

---

Tested by compilation only. Tested for x86 and x86_64.

 drivers/staging/goldfish/goldfish_nand.c | 3 ++-
 include/linux/goldfish.h                 | 2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)
Quoted 14 lines

drivers/staging/goldfish/goldfish_nand.c static u32 goldfish_nand_cmd(struct mtd_info *mtd, enum nand_cmd cmd, · line 91

Quoted 11 lines
drivers/staging/goldfish/goldfish_nand.c +2 -1
index d68f216..738fdc4 100644
@@ -87,7 +87,8 @@ static u32 goldfish_nand_cmd(struct mtd_info *mtd, enum nand_cmd cmd,
                writel((u32)(addr >> 32), base + NAND_ADDR_HIGH);
                writel((u32)addr, base + NAND_ADDR_LOW);
                writel(len, base + NAND_TRANSFER_SIZE);
-               gf_write64((u64)ptr, base + NAND_DATA, base + NAND_DATA_HIGH);
+               gf_write64((resource_size_t)ptr, base + NAND_DATA,
+                          base + NAND_DATA_HIGH);

I guess sparse still complains if CONFIG_X86_PAE=y, which makes resource_size_t u64?

Quoted 2 lines

Yes, when CONFIG_X86_PAE=y the patch doesn't fix the warning(gcc warning). What is the correct/portable way of fixing this?

As gf_write64() takes "unsigned long data" for its first argument, why not simply cast ptr to "unsigned long"? "void *" and "unsigned long" have the same size on all Linux platforms.

Seems like there a several silly casting tricks being done in the goldfish drivers:

$ git grep -w gf_write64drivers/platform/goldfish/goldfish_pipe.c:
 gf_write64((u64)(unsigned long)p
drivers/platform/goldfish/goldfish_pipe.c:      gf_write64((u64)(unsigned long)p
drivers/platform/goldfish/goldfish_pipe.c:                      gf_write64((u64)
drivers/platform/goldfish/goldfish_pipe.c:                      gf_write64(addre
drivers/staging/goldfish/goldfish_audio.c:      (gf_write64((u64)(x), data->reg_
drivers/staging/goldfish/goldfish_nand.c:               gf_write64((u64)ptr, bas
drivers/tty/goldfish.c: gf_write64((u64)buf, base + GOLDFISH_TTY_DATA_PTR,
drivers/tty/goldfish.c: gf_write64((u64)buf, base + GOLDFISH_TTY_DATA_PTR,
include/linux/goldfish.h:static inline void gf_write64(unsigned long data,

with interesting history showing one wrong cast being "fixed" using another wrong cast:

commit f4e131dc38d34469b9fee1840ad237324831bce3

Author: Octavian Purdila <[email protected]>
Date:   Fri May 16 08:24:59 2014 +0300

goldfish: pipe: fix warnings for 32bit builds

(quoted diff) +1 -1
-       gf_write64((u64)pipe, dev->base + PIPE_REG_CHANNEL,
+       gf_write64((u64)(unsigned long)pipe, dev->base + PIPE_REG_CHANNEL,
Quoted 5 lines

As in general casts don't belong in drivers[*], what about creating an inline helper gf_set_pipe() that converts the pointer to unsigned long and calls gf_write64()?

Perhaps checkpatch should complain about casts outside header files?

Cocinelle found 664 double casts:
http://pastebin.com/2bi9Dg7k

and 9 triple casts:
http://pastebin.com/RkJhPTTV

Those are 'not' patches, just the output of Coccinelle for analysis. The .cocci for triple cast:
@@
expression e1, e2;
type t1, t2, t3;
@@
e1 =
- (t1)(t2)(t3)
e2

So if there are cast patterns known to be wrong, it is easy to find and probably fix them with Coccinelle.

Quoted 11 lines

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds

Signature · 1 line
Peter
#7 lore raw

Hi Peter,

Quoted 6 lines · Peter Senna Tschudin
Quoted 1 line

Perhaps checkpatch should complain about casts outside header files?

Cocinelle found 664 double casts:
http://pastebin.com/2bi9Dg7k

and 9 triple casts:
http://pastebin.com/RkJhPTTV

I think double casts are only needed when casting between integers and pointers of different sizes:
1. One cast to make the sizes match,
2. One cast to convert between pointer and integer.

I think triple casts can always be simplified.
Or am I missing some use cases?

Quoted 10 lines

Those are 'not' patches, just the output of Coccinelle for analysis. The .cocci for triple cast:
@@
expression e1, e2;
type t1, t2, t3;
@@
e1 =
- (t1)(t2)(t3)
e2

Quoted 2 lines

So if there are cast patterns known to be wrong, it is easy to find and probably fix them with Coccinelle.

It depends on the original type and on the destination type.

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds

#8 lore raw

Line 4677 of http://pastebin.com/2bi9Dg7k looks like a bug

diff -u -p a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
- regs->nip = (unsigned long) (unsigned long)ksig->ka.sa.sa_handler;

Quoted 44 lines · Geert Uytterhoeven

Hi Peter,

Quoted 6 lines · Peter Senna Tschudin
Quoted 1 line

Perhaps checkpatch should complain about casts outside header files?

Cocinelle found 664 double casts:
http://pastebin.com/2bi9Dg7k

and 9 triple casts:
http://pastebin.com/RkJhPTTV

I think double casts are only needed when casting between integers and pointers of different sizes:
1. One cast to make the sizes match,
2. One cast to convert between pointer and integer.

I think triple casts can always be simplified.
Or am I missing some use cases?

Quoted 10 lines

Those are 'not' patches, just the output of Coccinelle for analysis. The .cocci for triple cast:
@@
expression e1, e2;
type t1, t2, t3;
@@
e1 =
- (t1)(t2)(t3)
e2

Quoted 2 lines

So if there are cast patterns known to be wrong, it is easy to find and probably fix them with Coccinelle.

It depends on the original type and on the destination type.

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds

Signature · 1 line
Peter
#9 lore raw
Quoted 4 lines · Peter Senna Tschudin

Line 4677 of http://pastebin.com/2bi9Dg7k looks like a bug

diff -u -p a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
- regs->nip = (unsigned long) (unsigned long)ksig->ka.sa.sa_handler;

I don't know about "bug" but it does look uninentional, yes.

Double casting is probably a good thing to print a static checker warning about.

Other static checkers complain about:

1) ~(char)foo;

(char)foo is type promoted to an int before the bitwise NOT.

2) (long *)&some_int

3) some_function((struct foo *)ptr);

Casting function arguments is almost always wrong. I check this with Smatch. I don't remember the details.

4) (long long)(x + y)

Probably it should be (long long)x + y

regards,
dan carpenter

#10 lore raw

PATCH v4 1/1 Fix pointer cast for 32 bits arch

As the first argument of gf_write64() was of type unsigned long, and as some calls to gf_write64() were casting the first argument from void * to u64 the compiler and/or sparse were printing warnings for casts of wrong sizes when compiling for i386.

This patch changes the type of the first argument of gf_write64() to void *, and update all calls to the function. This change fixed the warings and allowed to remove casts from 3 calls to gf_write64().

In addition gf_write64() was renamed to gf_write_ptr() as the name was misleading because it only writes 32 bits on 32 bit systems.

---
Tested by compilation only for x86, x86 with CONFIG_X86_PAE=y, and for x86_64.

Changes from V3:
- Changed type of first argument of gf_write64
- Renamed from gf_write64 to gf_write_ptr
- Updated all calls to gf_write_ptr

Changes from V2:
- Fixed spelling of complains
- Updated commit message

Changes from V1:
- Updated commit message

 drivers/platform/goldfish/goldfish_pipe.c | 18 +++++++++---------
 drivers/staging/goldfish/goldfish_audio.c |  2 +-
 drivers/staging/goldfish/goldfish_nand.c  |  2 +-
 drivers/tty/goldfish.c                    |  8 ++++----
 include/linux/goldfish.h                  |  8 ++++----
 5 files changed, 19 insertions(+), 19 deletions(-)
drivers/platform/goldfish/goldfish_pipe.c +9 -9
index d9a09d9..aad16bc 100644
@@ -158,8 +158,8 @@ static u32 goldfish_cmd_status(struct goldfish_pipe *pipe, u32 cmd)
 	struct goldfish_pipe_dev *dev = pipe->dev;
 
 	spin_lock_irqsave(&dev->lock, flags);
-	gf_write64((u64)(unsigned long)pipe, dev->base + PIPE_REG_CHANNEL,
-				dev->base + PIPE_REG_CHANNEL_HIGH);
+	gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL,
+		     dev->base + PIPE_REG_CHANNEL_HIGH);
 	writel(cmd, dev->base + PIPE_REG_COMMAND);
 	status = readl(dev->base + PIPE_REG_STATUS);
 	spin_unlock_irqrestore(&dev->lock, flags);
@@ -172,8 +172,8 @@ static void goldfish_cmd(struct goldfish_pipe *pipe, u32 cmd)
 	struct goldfish_pipe_dev *dev = pipe->dev;
 
 	spin_lock_irqsave(&dev->lock, flags);
-	gf_write64((u64)(unsigned long)pipe, dev->base + PIPE_REG_CHANNEL,
-				dev->base + PIPE_REG_CHANNEL_HIGH);
+	gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL,
+		     dev->base + PIPE_REG_CHANNEL_HIGH);
 	writel(cmd, dev->base + PIPE_REG_COMMAND);
 	spin_unlock_irqrestore(&dev->lock, flags);
 }
@@ -327,12 +327,12 @@ static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer,
 		spin_lock_irqsave(&dev->lock, irq_flags);
 		if (access_with_param(dev, CMD_WRITE_BUFFER + cmd_offset,
 				address, avail, pipe, &status)) {
-			gf_write64((u64)(unsigned long)pipe,
-				   dev->base + PIPE_REG_CHANNEL,
-				   dev->base + PIPE_REG_CHANNEL_HIGH);
+			gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL,
+				     dev->base + PIPE_REG_CHANNEL_HIGH);
 			writel(avail, dev->base + PIPE_REG_SIZE);
-			gf_write64(address, dev->base + PIPE_REG_ADDRESS,
-				dev->base + PIPE_REG_ADDRESS_HIGH);
+			gf_write_ptr((void *)address,
+				     dev->base + PIPE_REG_ADDRESS,
+				     dev->base + PIPE_REG_ADDRESS_HIGH);
 			writel(CMD_WRITE_BUFFER + cmd_offset,
 					dev->base + PIPE_REG_COMMAND);
 			status = readl(dev->base + PIPE_REG_STATUS);
drivers/staging/goldfish/goldfish_audio.c +1 -1
index 702ae04..ffb3f44 100644
@@ -63,7 +63,7 @@ struct goldfish_audio {
 #define AUDIO_READ(data, addr)		(readl(data->reg_base + addr))
 #define AUDIO_WRITE(data, addr, x)	(writel(x, data->reg_base + addr))
 #define AUDIO_WRITE64(data, addr, addr2, x)	\
-	(gf_write64((u64)(x), data->reg_base + addr, data->reg_base+addr2))
+	(gf_write_ptr((void *)(x), data->reg_base + addr, data->reg_base+addr2))
 
 /*
  *  temporary variable used between goldfish_audio_probe() and
drivers/staging/goldfish/goldfish_nand.c +1 -1
index 213877a..66ae48f 100644
@@ -87,7 +87,7 @@ static u32 goldfish_nand_cmd(struct mtd_info *mtd, enum nand_cmd cmd,
 		writel((u32)(addr >> 32), base + NAND_ADDR_HIGH);
 		writel((u32)addr, base + NAND_ADDR_LOW);
 		writel(len, base + NAND_TRANSFER_SIZE);
-		gf_write64((u64)ptr, base + NAND_DATA, base + NAND_DATA_HIGH);
+		gf_write_ptr(ptr, base + NAND_DATA, base + NAND_DATA_HIGH);
 		writel(cmd, base + NAND_COMMAND);
 		rv = readl(base + NAND_RESULT);
 	}
drivers/tty/goldfish.c +4 -4
index 0655fec..8cbfa02 100644
@@ -59,8 +59,8 @@ static void goldfish_tty_do_write(int line, const char *buf, unsigned count)
 	struct goldfish_tty *qtty = &goldfish_ttys[line];
 	void __iomem *base = qtty->base;
 	spin_lock_irqsave(&qtty->lock, irq_flags);
-	gf_write64((u64)buf, base + GOLDFISH_TTY_DATA_PTR,
-				base + GOLDFISH_TTY_DATA_PTR_HIGH);
+	gf_write_ptr((void *)buf, base + GOLDFISH_TTY_DATA_PTR,
+		     base + GOLDFISH_TTY_DATA_PTR_HIGH);
 	writel(count, base + GOLDFISH_TTY_DATA_LEN);
 	writel(GOLDFISH_TTY_CMD_WRITE_BUFFER, base + GOLDFISH_TTY_CMD);
 	spin_unlock_irqrestore(&qtty->lock, irq_flags);
@@ -81,8 +81,8 @@ static irqreturn_t goldfish_tty_interrupt(int irq, void *dev_id)
 
 	count = tty_prepare_flip_string(&qtty->port, &buf, count);
 	spin_lock_irqsave(&qtty->lock, irq_flags);
-	gf_write64((u64)buf, base + GOLDFISH_TTY_DATA_PTR,
-				base + GOLDFISH_TTY_DATA_PTR_HIGH);
+	gf_write_ptr((void *)buf, base + GOLDFISH_TTY_DATA_PTR,
+		     base + GOLDFISH_TTY_DATA_PTR_HIGH);
 	writel(count, base + GOLDFISH_TTY_DATA_LEN);
 	writel(GOLDFISH_TTY_CMD_READ_BUFFER, base + GOLDFISH_TTY_CMD);
 	spin_unlock_irqrestore(&qtty->lock, irq_flags);
include/linux/goldfish.h +4 -4
index 569236e..8621042 100644
@@ -3,12 +3,12 @@
 
 /* Helpers for Goldfish virtual platform */
 
-static inline void gf_write64(unsigned long data,
-		void __iomem *portl, void __iomem *porth)
+static inline void gf_write_ptr(void *data, void __iomem *portl,
+				void __iomem *porth)
 {
-	writel((u32)data, portl);
+	writel((u32)(unsigned long)data, portl);
 #ifdef CONFIG_64BIT
-	writel(data>>32, porth);
+	writel((unsigned long)data >> 32, porth);
 #endif
 }
 
Signature · 1 line
2.1.0
#11 lore raw

drivers/staging/goldfish/goldfish_audio.c struct goldfish_audio { · line 66

Quoted 8 lines · Peter Senna Tschudin
drivers/staging/goldfish/goldfish_audio.c +1 -1
@@ -63,7 +63,7 @@ struct goldfish_audio {
 #define AUDIO_READ(data, addr)         (readl(data->reg_base + addr))
 #define AUDIO_WRITE(data, addr, x)     (writel(x, data->reg_base + addr))
 #define AUDIO_WRITE64(data, addr, addr2, x)    \
-       (gf_write64((u64)(x), data->reg_base + addr, data->reg_base+addr2))
+       (gf_write_ptr((void *)(x), data->reg_base + addr, data->reg_base+addr2))

This one should not be converted, as all callers pass a dma_addr_t, which may be 64-bit on 32-bit systems, i.e. larger than void *.

drivers/tty/goldfish.c static void goldfish_tty_do_write(int line, const char *buf, unsigned count) · line 62

Quoted 11 lines
drivers/tty/goldfish.c +1 -2
index 0655fec..8cbfa02 100644
@@ -59,8 +59,8 @@ static void goldfish_tty_do_write(int line, const char *buf, unsigned count)
        struct goldfish_tty *qtty = &goldfish_ttys[line];
        void __iomem *base = qtty->base;
        spin_lock_irqsave(&qtty->lock, irq_flags);
-       gf_write64((u64)buf, base + GOLDFISH_TTY_DATA_PTR,
-                               base + GOLDFISH_TTY_DATA_PTR_HIGH);
+       gf_write_ptr((void *)buf, base + GOLDFISH_TTY_DATA_PTR,

Please drop the unneeded "void *" cast, as it will hide warnings if a type is changed some future time.

drivers/tty/goldfish.c static irqreturn_t goldfish_tty_interrupt(int irq, void *dev_id) · line 84

Quoted 11 lines
drivers/tty/goldfish.c +2 -2
+                    base + GOLDFISH_TTY_DATA_PTR_HIGH);
        writel(count, base + GOLDFISH_TTY_DATA_LEN);
        writel(GOLDFISH_TTY_CMD_WRITE_BUFFER, base + GOLDFISH_TTY_CMD);
        spin_unlock_irqrestore(&qtty->lock, irq_flags);
@@ -81,8 +81,8 @@ static irqreturn_t goldfish_tty_interrupt(int irq, void *dev_id)
 
        count = tty_prepare_flip_string(&qtty->port, &buf, count);
        spin_lock_irqsave(&qtty->lock, irq_flags);
-       gf_write64((u64)buf, base + GOLDFISH_TTY_DATA_PTR,
-                               base + GOLDFISH_TTY_DATA_PTR_HIGH);
+       gf_write_ptr((void *)buf, base + GOLDFISH_TTY_DATA_PTR,

Idem.

drivers/tty/goldfish.c static irqreturn_t goldfish_tty_interrupt(int irq, void *dev_id) · line 88

Quoted 4 lines
drivers/tty/goldfish.c +1 -0
+                    base + GOLDFISH_TTY_DATA_PTR_HIGH);
        writel(count, base + GOLDFISH_TTY_DATA_LEN);
        writel(GOLDFISH_TTY_CMD_READ_BUFFER, base + GOLDFISH_TTY_CMD);
        spin_unlock_irqrestore(&qtty->lock, irq_flags);

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds

#12 lore raw
Quoted 13 lines · Geert Uytterhoeven

drivers/staging/goldfish/goldfish_audio.c struct goldfish_audio { · line 66

Quoted 8 lines · Peter Senna Tschudin
drivers/staging/goldfish/goldfish_audio.c +1 -1
@@ -63,7 +63,7 @@ struct goldfish_audio {
 #define AUDIO_READ(data, addr)         (readl(data->reg_base + addr))
 #define AUDIO_WRITE(data, addr, x)     (writel(x, data->reg_base + addr))
 #define AUDIO_WRITE64(data, addr, addr2, x)    \
-       (gf_write64((u64)(x), data->reg_base + addr, data->reg_base+addr2))
+       (gf_write_ptr((void *)(x), data->reg_base + addr, data->reg_base+addr2))

This one should not be converted, as all callers pass a dma_addr_t, which may be 64-bit on 32-bit systems, i.e. larger than void *.

Ugh... You're right.

I've been avoiding asking this but I can't any longer. What is gf_write64() actually doing? We are writing dma addresses, user space pointers and kernel space pointers to this hardware?

This stuff doesn't seem to make any kind of sense and I can easily imagine a situation where it wrote a 64 bit pointer. Then we partially write over it with a 32 bit userspace pointer. Then it writes somewhere totally unintended.

This thing doesn't make any sort of sense to me.

regards,
dan carpenter

#13 lore raw
Quoted 21 lines · Dan Carpenter
Quoted 13 lines · Geert Uytterhoeven

drivers/staging/goldfish/goldfish_audio.c struct goldfish_audio { · line 66

Quoted 8 lines · Peter Senna Tschudin
drivers/staging/goldfish/goldfish_audio.c +1 -1
@@ -63,7 +63,7 @@ struct goldfish_audio {
 #define AUDIO_READ(data, addr)         (readl(data->reg_base + addr))
 #define AUDIO_WRITE(data, addr, x)     (writel(x, data->reg_base + addr))
 #define AUDIO_WRITE64(data, addr, addr2, x)    \
-       (gf_write64((u64)(x), data->reg_base + addr, data->reg_base+addr2))
+       (gf_write_ptr((void *)(x), data->reg_base + addr, data->reg_base+addr2))

This one should not be converted, as all callers pass a dma_addr_t, which may be 64-bit on 32-bit systems, i.e. larger than void *.

Ugh... You're right.

I've been avoiding asking this but I can't any longer. What is gf_write64() actually doing? We are writing dma addresses, user space pointers and kernel space pointers to this hardware?

Quoted 6 lines

This stuff doesn't seem to make any kind of sense and I can easily imagine a situation where it wrote a 64 bit pointer. Then we partially write over it with a 32 bit userspace pointer. Then it writes somewhere totally unintended.

This thing doesn't make any sort of sense to me.

Its a 64 on 64 or 32 on 32 virtual machine. Goldfish is used for Android emulation for all the system level phone emulation tools. On the emulation side it provides an interface for the emulated OS but makes no effort to emulate it as if it was a real hardware. If you think of it as a funky emulator interface all is good. If you think about it as "hardware" you've got the wrong model and chunks of Goldfish make less sense.

Alan

#14 lore raw
Quoted 29 lines · Alan Cox
Quoted 21 lines · Dan Carpenter
Quoted 13 lines · Geert Uytterhoeven

drivers/staging/goldfish/goldfish_audio.c struct goldfish_audio { · line 66

Quoted 8 lines · Peter Senna Tschudin
drivers/staging/goldfish/goldfish_audio.c +1 -1
@@ -63,7 +63,7 @@ struct goldfish_audio {
 #define AUDIO_READ(data, addr)         (readl(data->reg_base + addr))
 #define AUDIO_WRITE(data, addr, x)     (writel(x, data->reg_base + addr))
 #define AUDIO_WRITE64(data, addr, addr2, x)    \
-       (gf_write64((u64)(x), data->reg_base + addr, data->reg_base+addr2))
+       (gf_write_ptr((void *)(x), data->reg_base + addr, data->reg_base+addr2))

This one should not be converted, as all callers pass a dma_addr_t, which may be 64-bit on 32-bit systems, i.e. larger than void *.

Ugh... You're right.

I've been avoiding asking this but I can't any longer. What is gf_write64() actually doing? We are writing dma addresses, user space pointers and kernel space pointers to this hardware?

Quoted 6 lines

This stuff doesn't seem to make any kind of sense and I can easily imagine a situation where it wrote a 64 bit pointer. Then we partially write over it with a 32 bit userspace pointer. Then it writes somewhere totally unintended.

This thing doesn't make any sort of sense to me.

Quoted 7 lines

Its a 64 on 64 or 32 on 32 virtual machine. Goldfish is used for Android emulation for all the system level phone emulation tools. On the emulation side it provides an interface for the emulated OS but makes no effort to emulate it as if it was a real hardware. If you think of it as a funky emulator interface all is good. If you think about it as "hardware" you've got the wrong model and chunks of Goldfish make less sense.

Is is better to leave the code as is, and ignore the compiler / sparse warnings for i386? Or is the proposal welcome if done correctly? And if so what would be correctly?

Signature · 1 line
Peter
#15 lore raw
Quoted 38 lines · Peter Senna Tschudin
Quoted 29 lines · Alan Cox
Quoted 21 lines · Dan Carpenter
Quoted 13 lines · Geert Uytterhoeven

drivers/staging/goldfish/goldfish_audio.c struct goldfish_audio { · line 66

Quoted 8 lines · Peter Senna Tschudin
drivers/staging/goldfish/goldfish_audio.c +1 -1
@@ -63,7 +63,7 @@ struct goldfish_audio {
 #define AUDIO_READ(data, addr)         (readl(data->reg_base + addr))
 #define AUDIO_WRITE(data, addr, x)     (writel(x, data->reg_base + addr))
 #define AUDIO_WRITE64(data, addr, addr2, x)    \
-       (gf_write64((u64)(x), data->reg_base + addr, data->reg_base+addr2))
+       (gf_write_ptr((void *)(x), data->reg_base + addr, data->reg_base+addr2))

This one should not be converted, as all callers pass a dma_addr_t, which may be 64-bit on 32-bit systems, i.e. larger than void *.

Ugh... You're right.

I've been avoiding asking this but I can't any longer. What is gf_write64() actually doing? We are writing dma addresses, user space pointers and kernel space pointers to this hardware?

Quoted 6 lines

This stuff doesn't seem to make any kind of sense and I can easily imagine a situation where it wrote a 64 bit pointer. Then we partially write over it with a 32 bit userspace pointer. Then it writes somewhere totally unintended.

This thing doesn't make any sort of sense to me.

Quoted 7 lines

Its a 64 on 64 or 32 on 32 virtual machine. Goldfish is used for Android emulation for all the system level phone emulation tools. On the emulation side it provides an interface for the emulated OS but makes no effort to emulate it as if it was a real hardware. If you think of it as a funky emulator interface all is good. If you think about it as "hardware" you've got the wrong model and chunks of Goldfish make less sense.

Quoted 3 lines

Is is better to leave the code as is, and ignore the compiler / sparse warnings for i386? Or is the proposal welcome if done correctly? And if so what would be correctly?

What's the status with this mess?

Oh, and please, put a "staging: goldfish:" at the front of your subject line in the future so I know to look at it, otherwise it gets lost at times...

thanks,

greg k-h

#16 lore raw

PATCH v5 1/1 staging: goldfish: Fix pointer cast for 32 bits

As the first argument of gf_write64() was of type unsigned long, and as some calls to gf_write64() were casting the first argument from void * to u64 the compiler and/or sparse were printing warnings for casts of wrong sizes when compiling for i386.

This patch changes the type of the first argument of gf_write64() to void *, and update calls to the function. This change fixed the warnings and allowed to remove casts from 6 calls to gf_write64().

In addition gf_write64() was renamed to gf_write_ptr() as the name was misleading because it only writes 32 bits on 32 bit systems.

gf_write_dma_addr() was added to handle dma_addr_t values which is used at drivers/staging/goldfish/goldfish_audio.c.

---
Tested by compilation only for x86 and for x86_64.

Changes from V4:
- Added the function gf_write_dma_addr()
- Changed the subject line

Changes from V3:
- Changed type of first argument of gf_write64
- Renamed from gf_write64 to gf_write_ptr
- Updated all calls to gf_write_ptr

Changes from V2:
- Fixed spelling of complains
- Updated commit message

Changes from V1:
- Updated commit message

 drivers/platform/goldfish/goldfish_pipe.c | 18 +++++++++---------
 drivers/staging/goldfish/goldfish_audio.c |  2 +-
 drivers/staging/goldfish/goldfish_nand.c  |  2 +-
 drivers/tty/goldfish.c                    |  4 ++--
 include/linux/goldfish.h                  | 18 ++++++++++++++----
 5 files changed, 27 insertions(+), 17 deletions(-)
drivers/platform/goldfish/goldfish_pipe.c +9 -9
index d9a09d9..aad16bc 100644
@@ -158,8 +158,8 @@ static u32 goldfish_cmd_status(struct goldfish_pipe *pipe, u32 cmd)
 	struct goldfish_pipe_dev *dev = pipe->dev;
 
 	spin_lock_irqsave(&dev->lock, flags);
-	gf_write64((u64)(unsigned long)pipe, dev->base + PIPE_REG_CHANNEL,
-				dev->base + PIPE_REG_CHANNEL_HIGH);
+	gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL,
+		     dev->base + PIPE_REG_CHANNEL_HIGH);
 	writel(cmd, dev->base + PIPE_REG_COMMAND);
 	status = readl(dev->base + PIPE_REG_STATUS);
 	spin_unlock_irqrestore(&dev->lock, flags);
@@ -172,8 +172,8 @@ static void goldfish_cmd(struct goldfish_pipe *pipe, u32 cmd)
 	struct goldfish_pipe_dev *dev = pipe->dev;
 
 	spin_lock_irqsave(&dev->lock, flags);
-	gf_write64((u64)(unsigned long)pipe, dev->base + PIPE_REG_CHANNEL,
-				dev->base + PIPE_REG_CHANNEL_HIGH);
+	gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL,
+		     dev->base + PIPE_REG_CHANNEL_HIGH);
 	writel(cmd, dev->base + PIPE_REG_COMMAND);
 	spin_unlock_irqrestore(&dev->lock, flags);
 }
@@ -327,12 +327,12 @@ static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer,
 		spin_lock_irqsave(&dev->lock, irq_flags);
 		if (access_with_param(dev, CMD_WRITE_BUFFER + cmd_offset,
 				address, avail, pipe, &status)) {
-			gf_write64((u64)(unsigned long)pipe,
-				   dev->base + PIPE_REG_CHANNEL,
-				   dev->base + PIPE_REG_CHANNEL_HIGH);
+			gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL,
+				     dev->base + PIPE_REG_CHANNEL_HIGH);
 			writel(avail, dev->base + PIPE_REG_SIZE);
-			gf_write64(address, dev->base + PIPE_REG_ADDRESS,
-				dev->base + PIPE_REG_ADDRESS_HIGH);
+			gf_write_ptr((void *)address,
+				     dev->base + PIPE_REG_ADDRESS,
+				     dev->base + PIPE_REG_ADDRESS_HIGH);
 			writel(CMD_WRITE_BUFFER + cmd_offset,
 					dev->base + PIPE_REG_COMMAND);
 			status = readl(dev->base + PIPE_REG_STATUS);
drivers/staging/goldfish/goldfish_audio.c +1 -1
index 702ae04..b0927e4 100644
@@ -63,7 +63,7 @@ struct goldfish_audio {
 #define AUDIO_READ(data, addr)		(readl(data->reg_base + addr))
 #define AUDIO_WRITE(data, addr, x)	(writel(x, data->reg_base + addr))
 #define AUDIO_WRITE64(data, addr, addr2, x)	\
-	(gf_write64((u64)(x), data->reg_base + addr, data->reg_base+addr2))
+	(gf_write_dma_addr((x), data->reg_base + addr, data->reg_base+addr2))
 
 /*
  *  temporary variable used between goldfish_audio_probe() and
drivers/staging/goldfish/goldfish_nand.c +1 -1
index 213877a..66ae48f 100644
@@ -87,7 +87,7 @@ static u32 goldfish_nand_cmd(struct mtd_info *mtd, enum nand_cmd cmd,
 		writel((u32)(addr >> 32), base + NAND_ADDR_HIGH);
 		writel((u32)addr, base + NAND_ADDR_LOW);
 		writel(len, base + NAND_TRANSFER_SIZE);
-		gf_write64((u64)ptr, base + NAND_DATA, base + NAND_DATA_HIGH);
+		gf_write_ptr(ptr, base + NAND_DATA, base + NAND_DATA_HIGH);
 		writel(cmd, base + NAND_COMMAND);
 		rv = readl(base + NAND_RESULT);
 	}
drivers/tty/goldfish.c +2 -2
index 0655fec..0f82c0b 100644
@@ -59,7 +59,7 @@ static void goldfish_tty_do_write(int line, const char *buf, unsigned count)
 	struct goldfish_tty *qtty = &goldfish_ttys[line];
 	void __iomem *base = qtty->base;
 	spin_lock_irqsave(&qtty->lock, irq_flags);
-	gf_write64((u64)buf, base + GOLDFISH_TTY_DATA_PTR,
+	gf_write_ptr(buf, base + GOLDFISH_TTY_DATA_PTR,
 				base + GOLDFISH_TTY_DATA_PTR_HIGH);
 	writel(count, base + GOLDFISH_TTY_DATA_LEN);
 	writel(GOLDFISH_TTY_CMD_WRITE_BUFFER, base + GOLDFISH_TTY_CMD);
@@ -81,7 +81,7 @@ static irqreturn_t goldfish_tty_interrupt(int irq, void *dev_id)
 
 	count = tty_prepare_flip_string(&qtty->port, &buf, count);
 	spin_lock_irqsave(&qtty->lock, irq_flags);
-	gf_write64((u64)buf, base + GOLDFISH_TTY_DATA_PTR,
+	gf_write_ptr(buf, base + GOLDFISH_TTY_DATA_PTR,
 				base + GOLDFISH_TTY_DATA_PTR_HIGH);
 	writel(count, base + GOLDFISH_TTY_DATA_LEN);
 	writel(GOLDFISH_TTY_CMD_READ_BUFFER, base + GOLDFISH_TTY_CMD);
include/linux/goldfish.h +14 -4
index 569236e..37a5e2f 100644
@@ -3,13 +3,23 @@
 
 /* Helpers for Goldfish virtual platform */
 
-static inline void gf_write64(unsigned long data,
-		void __iomem *portl, void __iomem *porth)
+static inline void gf_write_ptr(void *ptr, void __iomem *portl,
+				void __iomem *porth)
 {
-	writel((u32)data, portl);
+	writel((u32)(unsigned long)ptr, portl);
 #ifdef CONFIG_64BIT
-	writel(data>>32, porth);
+	writel((unsigned long)ptr >> 32, porth);
 #endif
 }
 
+static inline void gf_write_dma_addr(dma_addr_t addr, void __iomem *portl,
+				     void __iomem *porth)
+{
+	writel((u32)addr, portl);
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+	writel(addr >> 32, porth);
+#endif
+}
+
+
 #endif /* __LINUX_GOLDFISH_H */
Signature · 1 line
2.1.0
#17 lore raw

Re: [PATCH V5] staging: goldfish: Fix pointer cast for 32 bits

Looks good.

regards,
dan carpenter

maintainer
#18 lore raw

Re: [PATCH V5] staging: goldfish: Fix pointer cast for 32 bits

In reply to Peter Senna Tschudin
Quoted 12 lines · Peter Senna Tschudin

As the first argument of gf_write64() was of type unsigned long, and as some calls to gf_write64() were casting the first argument from void * to u64 the compiler and/or sparse were printing warnings for casts of wrong sizes when compiling for i386.

This patch changes the type of the first argument of gf_write64() to void *, and update calls to the function. This change fixed the warnings and allowed to remove casts from 6 calls to gf_write64().

In addition gf_write64() was renamed to gf_write_ptr() as the name was misleading because it only writes 32 bits on 32 bit systems.

Quoted 7 lines

gf_write_dma_addr() was added to handle dma_addr_t values which is used at drivers/staging/goldfish/goldfish_audio.c.

---
Tested by compilation only for x86 and for x86_64.

This adds two build warnings:

drivers/tty/goldfish.c: In function ‘goldfish_tty_do_write’:
drivers/tty/goldfish.c:62:15: warning: passing argument 1 of ‘gf_write_ptr’ discards ‘const’ qualifier from pointer target type
gf_write_ptr(buf, base + GOLDFISH_TTY_DATA_PTR,

               ^
In file included from drivers/tty/goldfish.c:24:0:
include/linux/goldfish.h:6:20: note: expected ‘void *’ but argument is of type ‘const char *’
 static inline void gf_write_ptr(void *ptr, void __iomem *portl,
                    ^

So I can't take this. Please fix up and resend, and always test build your patches...

thanks,

greg k-h

#19 lore raw

PATCH v6 1/1 staging: goldfish: Fix pointer cast for 32 bits

As the first argument of gf_write64() was of type unsigned long, and as some calls to gf_write64() were casting the first argument from void * to u64 the compiler and/or sparse were printing warnings for casts of wrong sizes when compiling for i386.

This patch changes the type of the first argument of gf_write64() to const void *, and update calls to the function. This change fixed the warnings and allowed to remove casts from 3 calls to gf_write64().

In addition gf_write64() was renamed to gf_write_ptr() as the name was misleading because it only writes 32 bits on 32 bit systems.

gf_write_dma_addr() was added to handle dma_addr_t values which is used at drivers/staging/goldfish/goldfish_audio.c.

---
When submiting V5, I havent tested the patch properly. It was my fault. Tested by compilation only for i386 and for x86_64.

Changes from v5:
- Added const to first argument of both gf_write_ptr() and gf_write_dma_addr()

Changes from V4:
- Added the function gf_write_dma_addr()
- Changed the subject line

Changes from V3:
- Changed type of first argument of gf_write64
- Renamed from gf_write64 to gf_write_ptr
- Updated all calls to gf_write_ptr

Changes from V2:
- Fixed spelling of complains
- Updated commit message

Changes from V1:
- Updated commit message

 drivers/platform/goldfish/goldfish_pipe.c | 18 +++++++++---------
 drivers/staging/goldfish/goldfish_audio.c |  2 +-
 drivers/staging/goldfish/goldfish_nand.c  |  2 +-
 drivers/tty/goldfish.c                    |  4 ++--
 include/linux/goldfish.h                  | 19 +++++++++++++++----
 5 files changed, 28 insertions(+), 17 deletions(-)
drivers/platform/goldfish/goldfish_pipe.c +9 -9
index d9a09d9..aad16bc 100644
@@ -158,8 +158,8 @@ static u32 goldfish_cmd_status(struct goldfish_pipe *pipe, u32 cmd)
 	struct goldfish_pipe_dev *dev = pipe->dev;
 
 	spin_lock_irqsave(&dev->lock, flags);
-	gf_write64((u64)(unsigned long)pipe, dev->base + PIPE_REG_CHANNEL,
-				dev->base + PIPE_REG_CHANNEL_HIGH);
+	gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL,
+		     dev->base + PIPE_REG_CHANNEL_HIGH);
 	writel(cmd, dev->base + PIPE_REG_COMMAND);
 	status = readl(dev->base + PIPE_REG_STATUS);
 	spin_unlock_irqrestore(&dev->lock, flags);
@@ -172,8 +172,8 @@ static void goldfish_cmd(struct goldfish_pipe *pipe, u32 cmd)
 	struct goldfish_pipe_dev *dev = pipe->dev;
 
 	spin_lock_irqsave(&dev->lock, flags);
-	gf_write64((u64)(unsigned long)pipe, dev->base + PIPE_REG_CHANNEL,
-				dev->base + PIPE_REG_CHANNEL_HIGH);
+	gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL,
+		     dev->base + PIPE_REG_CHANNEL_HIGH);
 	writel(cmd, dev->base + PIPE_REG_COMMAND);
 	spin_unlock_irqrestore(&dev->lock, flags);
 }
@@ -327,12 +327,12 @@ static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer,
 		spin_lock_irqsave(&dev->lock, irq_flags);
 		if (access_with_param(dev, CMD_WRITE_BUFFER + cmd_offset,
 				address, avail, pipe, &status)) {
-			gf_write64((u64)(unsigned long)pipe,
-				   dev->base + PIPE_REG_CHANNEL,
-				   dev->base + PIPE_REG_CHANNEL_HIGH);
+			gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL,
+				     dev->base + PIPE_REG_CHANNEL_HIGH);
 			writel(avail, dev->base + PIPE_REG_SIZE);
-			gf_write64(address, dev->base + PIPE_REG_ADDRESS,
-				dev->base + PIPE_REG_ADDRESS_HIGH);
+			gf_write_ptr((void *)address,
+				     dev->base + PIPE_REG_ADDRESS,
+				     dev->base + PIPE_REG_ADDRESS_HIGH);
 			writel(CMD_WRITE_BUFFER + cmd_offset,
 					dev->base + PIPE_REG_COMMAND);
 			status = readl(dev->base + PIPE_REG_STATUS);
drivers/staging/goldfish/goldfish_audio.c +1 -1
index 702ae04..b0927e4 100644
@@ -63,7 +63,7 @@ struct goldfish_audio {
 #define AUDIO_READ(data, addr)		(readl(data->reg_base + addr))
 #define AUDIO_WRITE(data, addr, x)	(writel(x, data->reg_base + addr))
 #define AUDIO_WRITE64(data, addr, addr2, x)	\
-	(gf_write64((u64)(x), data->reg_base + addr, data->reg_base+addr2))
+	(gf_write_dma_addr((x), data->reg_base + addr, data->reg_base+addr2))
 
 /*
  *  temporary variable used between goldfish_audio_probe() and
drivers/staging/goldfish/goldfish_nand.c +1 -1
index 213877a..66ae48f 100644
@@ -87,7 +87,7 @@ static u32 goldfish_nand_cmd(struct mtd_info *mtd, enum nand_cmd cmd,
 		writel((u32)(addr >> 32), base + NAND_ADDR_HIGH);
 		writel((u32)addr, base + NAND_ADDR_LOW);
 		writel(len, base + NAND_TRANSFER_SIZE);
-		gf_write64((u64)ptr, base + NAND_DATA, base + NAND_DATA_HIGH);
+		gf_write_ptr(ptr, base + NAND_DATA, base + NAND_DATA_HIGH);
 		writel(cmd, base + NAND_COMMAND);
 		rv = readl(base + NAND_RESULT);
 	}
drivers/tty/goldfish.c +2 -2
index 0655fec..0f82c0b 100644
@@ -59,7 +59,7 @@ static void goldfish_tty_do_write(int line, const char *buf, unsigned count)
 	struct goldfish_tty *qtty = &goldfish_ttys[line];
 	void __iomem *base = qtty->base;
 	spin_lock_irqsave(&qtty->lock, irq_flags);
-	gf_write64((u64)buf, base + GOLDFISH_TTY_DATA_PTR,
+	gf_write_ptr(buf, base + GOLDFISH_TTY_DATA_PTR,
 				base + GOLDFISH_TTY_DATA_PTR_HIGH);
 	writel(count, base + GOLDFISH_TTY_DATA_LEN);
 	writel(GOLDFISH_TTY_CMD_WRITE_BUFFER, base + GOLDFISH_TTY_CMD);
@@ -81,7 +81,7 @@ static irqreturn_t goldfish_tty_interrupt(int irq, void *dev_id)
 
 	count = tty_prepare_flip_string(&qtty->port, &buf, count);
 	spin_lock_irqsave(&qtty->lock, irq_flags);
-	gf_write64((u64)buf, base + GOLDFISH_TTY_DATA_PTR,
+	gf_write_ptr(buf, base + GOLDFISH_TTY_DATA_PTR,
 				base + GOLDFISH_TTY_DATA_PTR_HIGH);
 	writel(count, base + GOLDFISH_TTY_DATA_LEN);
 	writel(GOLDFISH_TTY_CMD_READ_BUFFER, base + GOLDFISH_TTY_CMD);
include/linux/goldfish.h +15 -4
index 569236e..93e080b 100644
@@ -3,13 +3,24 @@
 
 /* Helpers for Goldfish virtual platform */
 
-static inline void gf_write64(unsigned long data,
-		void __iomem *portl, void __iomem *porth)
+static inline void gf_write_ptr(const void *ptr, void __iomem *portl,
+				void __iomem *porth)
 {
-	writel((u32)data, portl);
+	writel((u32)(unsigned long)ptr, portl);
 #ifdef CONFIG_64BIT
-	writel(data>>32, porth);
+	writel((unsigned long)ptr >> 32, porth);
 #endif
 }
 
+static inline void gf_write_dma_addr(const dma_addr_t addr,
+				     void __iomem *portl,
+				     void __iomem *porth)
+{
+	writel((u32)addr, portl);
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+	writel(addr >> 32, porth);
+#endif
+}
+
+
 #endif /* __LINUX_GOLDFISH_H */
Signature · 1 line
2.1.0
#20 lore raw
In reply to Alan Cox
Quoted 8 lines · Alan Cox

Its a 64 on 64 or 32 on 32 virtual machine. Goldfish is used for Android emulation for all the system level phone emulation tools. On the emulation side it provides an interface for the emulated OS but makes no effort to emulate it as if it was a real hardware. If you think of it as a funky emulator interface all is good. If you think about it as "hardware" you've got the wrong model and chunks of Goldfish make less sense.

Ah. Ok. That makes sense.

Peter maybe the fix is to make a different function:

static inline void gf_write_dma_addr(dma_addr_t addr, void __iomem *portl,
void __iomem *porth)

{
        writel((u32)data, portl);
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
        writel(data >> 32, porth);

#endif
}

Something like that.

The gf_write_ptr() function patch you wrote preserves the current behavior, but the current behavior is buggy, (I think) so we need both gf_write_dma_addr() and gf_write_ptr().

regards,
dan carpenter

#21 lore raw

Actually, my patch seems like a good idea to me but it's one of those things that someone should probably test. Unless someone can test goldfish on a 32 bit system with 64 bit dma addresses then maybe the thing to is to write the new function but preserve the current behavior.

static inline void gf_write_dma_addr(dma_addr_t addr, void __iomem *portl,
void __iomem *porth)

{
	writel((u32)data, portl);
	/*
	 * This should be CONFIG_ARCH_DMA_ADDR_T_64BIT but someone needs to
	 * test it.
	 */
#ifdef CONFIG_64BIT
	writel(data >> 32, porth);

#endif
}

regards,
dan carpenter

#22 lore raw
Quoted 3 lines · Dan Carpenter

Actually, my patch seems like a good idea to me but it's one of those things that someone should probably test. Unless someone can test goldfish on a 32 bit system with 64 bit dma addresses

No such "system" exists.

Alan

#23 lore raw
Quoted 6 lines · Alan Cox
Quoted 3 lines · Dan Carpenter

Actually, my patch seems like a good idea to me but it's one of those things that someone should probably test. Unless someone can test goldfish on a 32 bit system with 64 bit dma addresses

No such "system" exists.

I don't understand. We definitely can have 64bit dma addresses on x86_32.

regards,
dan carpenter

#24 lore raw
Quoted 10 lines · Dan Carpenter
Quoted 6 lines · Alan Cox
Quoted 3 lines · Dan Carpenter

Actually, my patch seems like a good idea to me but it's one of those things that someone should probably test. Unless someone can test goldfish on a 32 bit system with 64 bit dma addresses

No such "system" exists.

I don't understand. We definitely can have 64bit dma addresses on x86_32.

Yes but no actual Goldfish environment is built that way

#25 lore raw
Quoted 7 lines · Alan Cox
Quoted 6 lines · Dan Carpenter
Quoted 5 lines · Alan Cox
Quoted 3 lines · Dan Carpenter

Actually, my patch seems like a good idea to me but it's one of those things that someone should probably test. Unless someone can test goldfish on a 32 bit system with 64 bit dma addresses

Quoted 7 lines
Quoted 4 lines
Quoted 1 line

No such "system" exists.

I don't understand. We definitely can have 64bit dma addresses on x86_32.

Yes but no actual Goldfish environment is built that way

Isn't this a simpler fix?

drivers/staging/goldfish/goldfish_nand.c +1 -1
index 213877a..053ac11 100644
@@ -87,7 +87,7 @@ static u32 goldfish_nand_cmd(struct mtd_info *mtd, enum nand_cmd cmd,
 		writel((u32)(addr >> 32), base + NAND_ADDR_HIGH);
 		writel((u32)addr, base + NAND_ADDR_LOW);
 		writel(len, base + NAND_TRANSFER_SIZE);
-		gf_write64((u64)ptr, base + NAND_DATA, base + NAND_DATA_HIGH);
+		gf_write64((unsigned long)ptr, base + NAND_DATA, base + NAND_DATA_HIGH);
 		writel(cmd, base + NAND_COMMAND);
 		rv = readl(base + NAND_RESULT);
 	}
Signature · 1 line
Peter
#26 lore raw
Quoted 10 lines · Peter Senna Tschudin
Quoted 7 lines · Alan Cox
Quoted 6 lines · Dan Carpenter
Quoted 5 lines · Alan Cox
Quoted 3 lines · Dan Carpenter

Actually, my patch seems like a good idea to me but it's one of those things that someone should probably test. Unless someone can test goldfish on a 32 bit system with 64 bit dma addresses

Quoted 8 lines
Quoted 7 lines
Quoted 4 lines
Quoted 1 line

No such "system" exists.

I don't understand. We definitely can have 64bit dma addresses on x86_32.

Yes but no actual Goldfish environment is built that way

Isn't this a simpler fix?

I still think my fix is cleanest even though dma_addr_t and size_t are always the same. It just means that we can commit it without worrying about testing.

regards,
dan carpenter

#27 lore raw
In reply to Peter Senna Tschudin
Quoted 17 lines · Peter Senna Tschudin

Sparse compalins about casting void * to u64 on i386. Change the cast to resource_size_t.

---

Tested by compilation only. Tested for x86 and x86_64.

 drivers/staging/goldfish/goldfish_nand.c | 3 ++-
 include/linux/goldfish.h                 | 2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)
drivers/staging/goldfish/goldfish_nand.c +0 -0
index d68f216..738fdc4 100644

drivers/staging/goldfish/goldfish_nand.c static u32 goldfish_nand_cmd(struct mtd_info *mtd, enum nand_cmd cmd, · line 91

Quoted 6 lines
drivers/staging/goldfish/goldfish_nand.c +2 -1
@@ -87,7 +87,8 @@ static u32 goldfish_nand_cmd(struct mtd_info *mtd, enum nand_cmd cmd,
 		writel((u32)(addr >> 32), base + NAND_ADDR_HIGH);
 		writel((u32)addr, base + NAND_ADDR_LOW);
 		writel(len, base + NAND_TRANSFER_SIZE);
-		gf_write64((u64)ptr, base + NAND_DATA, base + NAND_DATA_HIGH);
+		gf_write64((resource_size_t)ptr, base + NAND_DATA,
+			   base + NAND_DATA_HIGH);

write64 is a misleading name because it only writes 32 bits on 32 bit systems.

Are you sure it's a resource_size_t? If that's really true then this code needs a lot more work. The ifdef in gf_write64() should be CONFIG_PHYS_ADDR_T_64BIT and ops->datbuf needs to updated. It would be a lot of changes...

I *think* but I'm not positive that gf_write64 should just take a void pointer like this:

drivers/staging/goldfish/goldfish_nand.c +1 -1
index 213877a..92d6479 100644
@@ -87,7 +87,7 @@ static u32 goldfish_nand_cmd(struct mtd_info *mtd, enum nand_cmd cmd,
 		writel((u32)(addr >> 32), base + NAND_ADDR_HIGH);
 		writel((u32)addr, base + NAND_ADDR_LOW);
 		writel(len, base + NAND_TRANSFER_SIZE);
-		gf_write64((u64)ptr, base + NAND_DATA, base + NAND_DATA_HIGH);
+		gf_write64(ptr, base + NAND_DATA, base + NAND_DATA_HIGH);
 		writel(cmd, base + NAND_COMMAND);
 		rv = readl(base + NAND_RESULT);
 	}
include/linux/goldfish.h +3 -3
index 569236e..4cdb913 100644
@@ -3,12 +3,12 @@
 
 /* Helpers for Goldfish virtual platform */
 
-static inline void gf_write64(unsigned long data,
+static inline void gf_write64(void *data,
 		void __iomem *portl, void __iomem *porth)
 {
-	writel((u32)data, portl);
+	writel((u32)(unsigned long)data, portl);
 #ifdef CONFIG_64BIT
-	writel(data>>32, porth);
+	writel((unsigned long)data >> 32, porth);
 #endif
 }
 
#28 lore raw
Quoted 59 lines · Dan Carpenter
Quoted 17 lines · Peter Senna Tschudin

Sparse compalins about casting void * to u64 on i386. Change the cast to resource_size_t.

---

Tested by compilation only. Tested for x86 and x86_64.

 drivers/staging/goldfish/goldfish_nand.c | 3 ++-
 include/linux/goldfish.h                 | 2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)
drivers/staging/goldfish/goldfish_nand.c +0 -0
index d68f216..738fdc4 100644

drivers/staging/goldfish/goldfish_nand.c static u32 goldfish_nand_cmd(struct mtd_info *mtd, enum nand_cmd cmd, · line 91

Quoted 6 lines
drivers/staging/goldfish/goldfish_nand.c +2 -1
@@ -87,7 +87,8 @@ static u32 goldfish_nand_cmd(struct mtd_info *mtd, enum nand_cmd cmd,
              writel((u32)(addr >> 32), base + NAND_ADDR_HIGH);
              writel((u32)addr, base + NAND_ADDR_LOW);
              writel(len, base + NAND_TRANSFER_SIZE);
-             gf_write64((u64)ptr, base + NAND_DATA, base + NAND_DATA_HIGH);
+             gf_write64((resource_size_t)ptr, base + NAND_DATA,
+                        base + NAND_DATA_HIGH);

write64 is a misleading name because it only writes 32 bits on 32 bit systems.

Are you sure it's a resource_size_t? If that's really true then this code needs a lot more work. The ifdef in gf_write64() should be CONFIG_PHYS_ADDR_T_64BIT and ops->datbuf needs to updated. It would be a lot of changes...

I *think* but I'm not positive that gf_write64 should just take a void pointer like this:

drivers/staging/goldfish/goldfish_nand.c +1 -1
index 213877a..92d6479 100644
@@ -87,7 +87,7 @@ static u32 goldfish_nand_cmd(struct mtd_info *mtd, enum nand_cmd cmd,
                writel((u32)(addr >> 32), base + NAND_ADDR_HIGH);
                writel((u32)addr, base + NAND_ADDR_LOW);
                writel(len, base + NAND_TRANSFER_SIZE);
-               gf_write64((u64)ptr, base + NAND_DATA, base + NAND_DATA_HIGH);
+               gf_write64(ptr, base + NAND_DATA, base + NAND_DATA_HIGH);
                writel(cmd, base + NAND_COMMAND);
                rv = readl(base + NAND_RESULT);
        }
include/linux/goldfish.h +1 -1
index 569236e..4cdb913 100644
@@ -3,12 +3,12 @@
 
 /* Helpers for Goldfish virtual platform */
 
-static inline void gf_write64(unsigned long data,
+static inline void gf_write64(void *data,

include/linux/goldfish.h line 14

Quoted 10 lines
include/linux/goldfish.h +2 -2
                void __iomem *portl, void __iomem *porth)
 {
-       writel((u32)data, portl);
+       writel((u32)(unsigned long)data, portl);
 #ifdef CONFIG_64BIT
-       writel(data>>32, porth);
+       writel((unsigned long)data >> 32, porth);
 #endif
 }
 

I like this solution. Should I send a single patch changing gf_write64() and removing all casts when calling the gf_write64(), or if to split, how to split the patch?

Signature · 1 line
Peter
#29 lore raw
Quoted 59 lines · Peter Senna Tschudin
Quoted 57 lines · Dan Carpenter
Quoted 17 lines · Peter Senna Tschudin

Sparse compalins about casting void * to u64 on i386. Change the cast to resource_size_t.

---

Tested by compilation only. Tested for x86 and x86_64.

 drivers/staging/goldfish/goldfish_nand.c | 3 ++-
 include/linux/goldfish.h                 | 2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)
drivers/staging/goldfish/goldfish_nand.c +0 -0
index d68f216..738fdc4 100644

drivers/staging/goldfish/goldfish_nand.c static u32 goldfish_nand_cmd(struct mtd_info *mtd, enum nand_cmd cmd, · line 91

Quoted 6 lines
drivers/staging/goldfish/goldfish_nand.c +2 -1
@@ -87,7 +87,8 @@ static u32 goldfish_nand_cmd(struct mtd_info *mtd, enum nand_cmd cmd,
              writel((u32)(addr >> 32), base + NAND_ADDR_HIGH);
              writel((u32)addr, base + NAND_ADDR_LOW);
              writel(len, base + NAND_TRANSFER_SIZE);
-             gf_write64((u64)ptr, base + NAND_DATA, base + NAND_DATA_HIGH);
+             gf_write64((resource_size_t)ptr, base + NAND_DATA,
+                        base + NAND_DATA_HIGH);

write64 is a misleading name because it only writes 32 bits on 32 bit systems.

Are you sure it's a resource_size_t? If that's really true then this code needs a lot more work. The ifdef in gf_write64() should be CONFIG_PHYS_ADDR_T_64BIT and ops->datbuf needs to updated. It would be a lot of changes...

I *think* but I'm not positive that gf_write64 should just take a void pointer like this:

drivers/staging/goldfish/goldfish_nand.c +1 -1
index 213877a..92d6479 100644
@@ -87,7 +87,7 @@ static u32 goldfish_nand_cmd(struct mtd_info *mtd, enum nand_cmd cmd,
                writel((u32)(addr >> 32), base + NAND_ADDR_HIGH);
                writel((u32)addr, base + NAND_ADDR_LOW);
                writel(len, base + NAND_TRANSFER_SIZE);
-               gf_write64((u64)ptr, base + NAND_DATA, base + NAND_DATA_HIGH);
+               gf_write64(ptr, base + NAND_DATA, base + NAND_DATA_HIGH);
                writel(cmd, base + NAND_COMMAND);
                rv = readl(base + NAND_RESULT);
        }
include/linux/goldfish.h +0 -0
index 569236e..4cdb913 100644
@@ -3,12 +3,12 @@
 
 /* Helpers for Goldfish virtual platform */
 
Quoted 16 lines

include/linux/goldfish.h line 14

Quoted 12 lines
include/linux/goldfish.h +3 -3
-static inline void gf_write64(unsigned long data,
+static inline void gf_write64(void *data,
                void __iomem *portl, void __iomem *porth)
 {
-       writel((u32)data, portl);
+       writel((u32)(unsigned long)data, portl);
 #ifdef CONFIG_64BIT
-       writel(data>>32, porth);
+       writel((unsigned long)data >> 32, porth);
 #endif
 }
 

I like this solution. Should I send a single patch changing gf_write64() and removing all casts when calling the gf_write64(), or if to split, how to split the patch?

Single patch, please. Maybe rename the function to gf_write_ptr() or something similar.

regards,
dan carpenter