printk and dma_addr_t
Subsystems (5)
PATCH 1/1 printk and dma_addr_t
A number of drivers like to print out the values of variables
which have type dma_addr_t. But there's no sane safe way
of doing this, because the size of the dma_addr_t type depends upon platform and config.
This code:
dma_addr_t a;
char *s;
printk("stuff: %lx %s", a, s);will crash the kernel if dma_addr_t is 64-bit, because printk will get the string's address wrong.
The patch introduces a DMA_ADDR_T_FMT macro which is the appropriate printf conversion string for the selecteddma_addr_t type. So the above usage will become
printk("stuff: " DMA_ADDR_T_FMT " %s", a, s);A patch which fixes all the drivers which I could find follows.
Ralf, could you please double-check the mips implementation?
include/asm-i386/types.h +2 -0
@@ -47,8 +47,10 @@ typedef unsigned long long u64;#ifdef CONFIG_HIGHMEM typedef u64 dma_addr_t ; +#define DMA_ADDR_T_FMT "%Lx"#else typedef u32 dma_addr_t ; +#define DMA_ADDR_T_FMT "%lx"#endif typedef u64 dma64_addr_t ;
include/asm-alpha/types.h +2 -0
@@ -50,5 +50,7 @@ typedef unsigned long u64;typedef u64 dma_addr_t ;typedef u64 dma64_addr_t ; +#define DMA_ADDR_T_FMT "%Lx" +#endif /* __KERNEL__ */ #endif /* _ALPHA_TYPES_H */
include/asm-arm/types.h +1 -0
@@ -44,6 +44,7 @@ typedef unsigned long long u64;/* Dma addresses are 32-bits wide. */ typedef u32 dma_addr_t ; +#define DMA_ADDR_T_FMT "%lx"#endif /* __KERNEL__ */
include/asm-cris/types.h +1 -0
@@ -44,6 +44,7 @@ typedef unsigned long long u64;/* Dma addresses are 32-bits wide, just like our other addresses. */ typedef u32 dma_addr_t ; +#define DMA_ADDR_T_FMT "%lx"#endif /* __KERNEL__ */
include/asm-ia64/types.h +1 -0
@@ -63,6 +63,7 @@ typedef __u64 u64;/* DMA addresses are 64-bits wide, in general. */ typedef u64 dma_addr_t ; +#define DMA_ADDR_T_FMT "%Lx"# endif /* __KERNEL__ */ #endif /* !__ASSEMBLY__ */
include/asm-m68k/types.h +1 -0
@@ -52,6 +52,7 @@ typedef unsigned long long u64;/* DMA addresses are 32-bits wide */ typedef u32 dma_addr_t ; +#define DMA_ADDR_T_FMT "%lx"#endif /* __KERNEL__ */
include/asm-mips64/types.h +1 -0
@@ -70,6 +70,7 @@ typedef unsigned long long u64;#define BITS_PER_LONG _MIPS_SZLONGtypedef unsigned long dma_addr_t ; +#define DMA_ADDR_T_FMT "%lx"#endif /* __KERNEL__ */
include/asm-mips/types.h +1 -0
@@ -71,6 +71,7 @@ typedef unsigned long long u64;#define BITS_PER_LONG _MIPS_SZLONGtypedef unsigned long dma_addr_t ; +#define DMA_ADDR_T_FMT "%lx"#endif /* __KERNEL__ */
include/asm-parisc/types.h +1 -0
@@ -48,6 +48,7 @@ typedef unsigned long long u64;/* Dma addresses are 32-bits wide. */ typedef u32 dma_addr_t ; +#define DMA_ADDR_T_FMT "%lx"#endif /* __KERNEL__ */
include/asm-ppc/types.h +2 -0
@@ -46,6 +46,8 @@ typedef __vector128 vector128;/* DMA addresses are 32-bits wide */ typedef u32 dma_addr_t ; +#define DMA_ADDR_T_FMT "%lx" +typedef u64 dma64_addr_t ;#endif /* __KERNEL__ */
include/asm-s390/types.h +1 -0
@@ -54,6 +54,7 @@ typedef unsigned long long u64;#define BITS_PER_LONG 32typedef u32 dma_addr_t ; +#define DMA_ADDR_T_FMT "%lx" typedef union { unsigned long long pair;
include/asm-s390x/types.h +1 -0
@@ -56,6 +56,7 @@ typedef unsigned long u64;#define BITS_PER_LONG 64typedef u32 dma_addr_t ; +#define DMA_ADDR_T_FMT "%lx"#endif /* __KERNEL__ */ #endif
include/asm-sh/types.h +1 -0
@@ -44,6 +44,7 @@ typedef unsigned long long u64;/* Dma addresses are 32-bits wide. */ typedef u32 dma_addr_t ; +#define DMA_ADDR_T_FMT "%lx"#endif /* __KERNEL__ */
include/asm-sparc64/types.h +2 -0
@@ -48,6 +48,8 @@ typedef unsigned long u64;/* Dma addresses come in generic and 64-bit flavours. */ typedef u32 dma_addr_t ; +#define DMA_ADDR_T_FMT "%lx" +typedef u64 dma64_addr_t ;#endif /* __KERNEL__ */
-
Quoted 3 lines
dma_addr_ttype. So the above usage will becomeprintk("stuff: " DMA_ADDR_T_FMT " %s", a, s);
Vomit. How about adding a dma_addr_t %code to the printk function ?
Quoted 6 lines · Alan Cox
Quoted 4 lines
dma_addr_ttype. So the above usage will becomeprintk("stuff: " DMA_ADDR_T_FMT " %s", a, s);Vomit. How about adding a
dma_addr_t%code to the printk function ?
heh, my comment on the patch was, "about as good as you can do without teaching printk and gcc about the type"
Can we hack gcc warnings, too?
Signature · 3 lines
Jeff Garzik | "I went through my candy like hot oatmeal Building 1024 | through an internally-buttered weasel." MandrakeSoft | - goats.com
From: Alan Cox <[email protected]>
Date: Wed, 13 Feb 2002 09:40:44 +0000 (GMT)
Vomit. How about adding a dma_addr_t %code to the printk function ?
And gcc will discover this via what? Osmosis perhaps? :-)
Quoted 6 lines
From: Alan Cox <[email protected]>
Date: Wed, 13 Feb 2002 09:40:44 +0000 (GMT)Vomit. How about adding a
dma_addr_t%code to the printk function ?And gcc will discover this via what? Osmosis perhaps? :-)
Yeah, seems gcc is a bit lacking in its overclever printf handlers. It lacks the ability to declare additional non standard % code - despite the fact glibc itself expands on the standard
glibc 2.0 adds conversion characters C and S.
glibc 2.1 adds length modifiers hh,j,t,z and conversion characters a,A.
glibc 2.2 adds the conversion character F with C99 seman- tics, and the flag character I.
So how do they modify the printf format rules in gcc ?
From: Alan Cox <[email protected]>
Date: Wed, 13 Feb 2002 10:23:50 +0000 (GMT)
So how do they modify the printf format rules in gcc ?
Because they can claim that they are part of the C environment, and for the most part they are right so their extensions go into gcc's magic list.
In fact I'd claim their case to be plugging holes in the standards specified set of printf format strings. :-)
Hey... we could "borrow" one of these printf format strings we don't have any need for in the kernel and pretend that is for "dma_addr_t". :-)
Quoted 9 lines · David S. Miller
From: Alan Cox <[email protected]>
Date: Wed, 13 Feb 2002 10:23:50 +0000 (GMT)So how do they modify the printf format rules in gcc ?
Because they can claim that they are part of the C environment, and for the most part they are right so their extensions go into gcc's magic list.
Quoted 6 lines
In fact I'd claim their case to be plugging holes in the standards specified set of printf format strings. :-)
Hey... we could "borrow" one of these printf format strings we don't have any need for in the kernel and pretend that is for "
dma_addr_t". :-)
Eeeep! I know you put a smiley there, but don't even think that!
Regards, Richard.... Permanent: [email protected] Current: [email protected]
Quoted 2 lines · Alan Cox
So how do they modify the printf format rules in gcc ?
Good question. It'd be nice for NIPQUAD and such.
Here's an alternative fix. Less vomitous?
Sorry about sticking a prototype in types.h. It needs to be somewhere where all dma_addr_t users will see it, and where dma_addr_t is already in scope. Maybe there's a better place?
include/linux/types.h +4 -0
@@ -127,4 +127,8 @@ struct ustat { char f_fpack[6]; }; +#ifdef __KERNEL__ +char *form_dma_addr_t (char *buf,dma_addr_t a); +#endif +#endif /* _LINUX_TYPES_H */
lib/vsprintf.c +17 -0
@@ -709,3 +709,20 @@ int sscanf(const char * buf, const charva_end (args);return i; } + +/* +* dma_addr_t's have different sizes on different platforms, +* so we use this helper when we want to pass one to printk. +*/ +char *form_dma_addr_t (char *buf,dma_addr_t a) +{ +char *fmt;/* Funny code to prevent a printf warning */ + +if (sizeof (dma_addr_t) ==sizeof (long )) + fmt ="%lx" ; +else + fmt ="%Lx" ; + +sprintf (buf, fmt, a); +return buf; +}
kernel/ksyms.c +1 -0
@@ -458,6 +458,7 @@ EXPORT_SYMBOL(sscanf);EXPORT_SYMBOL (vsprintf);EXPORT_SYMBOL (vsnprintf);EXPORT_SYMBOL (vsscanf); +EXPORT_SYMBOL (form_dma_addr_t);EXPORT_SYMBOL (kdevname);EXPORT_SYMBOL (bdevname);EXPORT_SYMBOL (cdevname);
drivers/atm/idt77252.c +4 -2
@@ -641,6 +641,7 @@ static struct scq_info * alloc_scq(struct idt77252_dev *card, int class) {struct scq_info *scq; +char da_buf[33 ]; scq = (struct scq_info *)kmalloc (sizeof (struct scq_info ),GFP_KERNEL );if (!scq)
@@ -665,8 +666,9 @@ alloc_scq(struct idt77252_dev *card, intskb_queue_head_init (&scq->transmit);skb_queue_head_init (&scq->pending); -TXPRINTK ("idt77252: SCQ: base 0x%p, next 0x%p, last 0x%p, paddr %08x\n" , - scq->base, scq->next, scq->last, scq->paddr); +TXPRINTK ("idt77252: SCQ: base 0x%p, next 0x%p, last 0x%p, paddr %s\n" , + scq->base, scq->next, scq->last, +form_dma_addr_t (da_buf, scq->paddr));return scq; }
drivers/message/fusion/mptbase.c +7 -4
@@ -3186,6 +3186,7 @@ mpt_print_ioc_facts(MPT_ADAPTER *ioc, ch {char expVer[32 ];char iocName[16 ]; +char da_buf[33 ];int sz;int y;int p;
@@ -3217,8 +3218,9 @@ mpt_print_ioc_facts(MPT_ADAPTER *ioc, ch y +=sprintf (buffer+len+y," MaxChainDepth = 0x%02x frames\n" , ioc->facts.MaxChainDepth); y +=sprintf (buffer+len+y," MinBlockSize = 0x%02x bytes\n" ,4 *ioc->facts.BlockSize); - y +=sprintf (buffer+len+y," RequestFrames @ 0x%p (Dma @ 0x%08x)\n" , - ioc->req_alloc, ioc->req_alloc_dma); + y +=sprintf (buffer+len+y," RequestFrames @ 0x%p (Dma @ 0x%s)\n" , + ioc->req_alloc, +form_dma_addr_t (da_buf, ioc->req_alloc_dma));/* * Rounding UP to nearest 4-kB boundary here... */
@@ -3230,8 +3232,9 @@ mpt_print_ioc_facts(MPT_ADAPTER *ioc, ch4 *ioc->facts.RequestFrameSize, ioc->facts.GlobalCredits); - y +=sprintf (buffer+len+y," ReplyFrames @ 0x%p (Dma @ 0x%08x)\n" , - ioc->reply_alloc, ioc->reply_alloc_dma); + y +=sprintf (buffer+len+y," ReplyFrames @ 0x%p (Dma @ 0x%s)\n" , + ioc->reply_alloc, +form_dma_addr_t (da_buf, ioc->reply_alloc_dma)); sz = (ioc->reply_sz * ioc->reply_depth) +128 ; y +=sprintf (buffer+len+y," {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n" , ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz);
drivers/net/tokenring/tms380tr.c +3 -1
@@ -1428,6 +1428,7 @@ static int tms380tr_bringup_diags(structstatic int tms380tr_init_adapter (struct net_device *dev) {struct net_local *tp = (struct net_local *)dev->priv; +char da_buf[33 ];const unsigned char SCB_Test[6 ] = {0x00 ,0x00 ,0xC1 ,0xE2 ,0xD4 ,0x8B };const unsigned char SSB_Test[8 ] = {0xFF ,0xFF ,0xD1 ,0xD7 ,
@@ -1446,7 +1447,8 @@ static int tms380tr_init_adapter(structif (tms380tr_debug >3 ) {printk (KERN_INFO "%s: buffer (real): %lx\n" , dev->name, (long ) &tp->scb); -printk (KERN_INFO "%s: buffer (virt): %lx\n" , dev->name, (long ) ((char *)&tp->scb - (char *)tp) + tp->dmabuffer); +printk (KERN_INFO "%s: buffer (virt): %s\n" , dev->name, +form_dma_addr_t (da_buf, (long ) ((char *)&tp->scb - (char *)tp) + tp->dmabuffer));printk (KERN_INFO "%s: buffer (DMA) : %lx\n" , dev->name, (long ) tp->dmabuffer);printk (KERN_INFO "%s: buffer (tp) : %lx\n" , dev->name, (long ) tp); }
drivers/net/pcnet32.c +3 -1
@@ -529,6 +529,7 @@ pcnet32_probe1(unsigned long ioaddr, unschar *chipname;struct net_device *dev;struct pcnet32_access *a =NULL ; +char da_buf[33 ];/* reset the chip */ pcnet32_dwio_reset (ioaddr);
@@ -711,7 +712,8 @@ pcnet32_probe1(unsigned long ioaddr, unsmemset (lp,0 ,sizeof (*lp)); lp->dma_addr = lp_dma_addr; lp->pci_dev = pdev; -printk ("\n" KERN_INFO "pcnet32: pcnet32_private lp=%p lp_dma_addr=%#08x" , lp, lp_dma_addr); +printk ("\n" KERN_INFO "pcnet32: pcnet32_private lp=%p lp_dma_addr=%s" , + lp,form_dma_addr_t (da_buf, lp_dma_addr));spin_lock_init (&lp->lock);
drivers/net/yellowfin.c +6 -2
@@ -1273,7 +1273,10 @@ static int yellowfin_close(struct net_de#if defined(__i386__)if (yellowfin_debug >2 ) { -printk ("\n" KERN_DEBUG " Tx ring at %8.8x:\n" , yp->tx_ring_dma); +char da_buf[33 ]; + +printk ("\n" KERN_DEBUG " Tx ring at %s:\n" , +form_dma_addr_t (da_buf, yp->tx_ring_dma));for (i =0 ; i <TX_RING_SIZE *2 ; i++) printk(" %c #%d desc. %8.8x %8.8x %8.8x %8.8x.\n", inl(ioaddr + TxPtr) == (long)&yp->tx_ring[i] ? '>' : ' ',
@@ -1285,7 +1288,8 @@ static int yellowfin_close(struct net_de i, yp->tx_status[i].tx_cnt, yp->tx_status[i].tx_errs, yp->tx_status[i].total_tx_cnt, yp->tx_status[i].paused); -printk ("\n" KERN_DEBUG " Rx ring %8.8x:\n" , yp->rx_ring_dma); +printk ("\n" KERN_DEBUG " Rx ring %s:\n" , +form_dma_addr_t (da_buf, yp->rx_ring_dma));for (i =0 ; i <RX_RING_SIZE ; i++) { printk(KERN_DEBUG " %c #%d desc. %8.8x %8.8x %8.8x\n", inl(ioaddr + RxPtr) == (long)&yp->rx_ring[i] ? '>' : ' ',
drivers/net/starfire.c +6 -4
@@ -1911,15 +1911,17 @@ static int netdev_close(struct net_devic#ifdef __i386__if (debug >2 ) { -printk ("\n" KERN_DEBUG " Tx ring at %8.8x:\n" , - np->tx_ring_dma); +char da_buf[33 ]; + +printk ("\n" KERN_DEBUG " Tx ring at %s:\n" , +form_dma_addr_t (da_buf, np->tx_ring_dma));for (i =0 ; i <8 /* TX_RING_SIZE is huge! */ ; i++)printk (KERN_DEBUG " #%d desc. %8.8x %8.8x -> %8.8x.\n" , i,le32_to_cpu (np->tx_ring[i].status),le32_to_cpu (np->tx_ring[i].first_addr),le32_to_cpu (np->tx_done_q[i].status)); -printk (KERN_DEBUG " Rx ring at %8.8x -> %p:\n" , - np->rx_ring_dma, np->rx_done_q); +printk (KERN_DEBUG " Rx ring at %s -> %p:\n" , +form_dma_addr_t (da_buf, np->rx_ring_dma), np->rx_done_q);if (np->rx_done_q)for (i =0 ; i <8 /* RX_RING_SIZE */ ; i++) { printk(KERN_DEBUG " #%d desc. %8.8x -> %8.8x\n",
-
Quoted 11 lines · Andrew Morton
Quoted 2 lines · Alan Cox
So how do they modify the printf format rules in gcc ?
Good question. It'd be nice for NIPQUAD and such.
Here's an alternative fix. Less vomitous?
Sorry about sticking a prototype in
types.h. It needs to be somewhere where alldma_addr_tusers will see it, and wheredma_addr_tis already in scope. Maybe there's a better place?
Personally, I like this less.. I don't think the previous #define DMA_ADDR_T_FMT (or whatever it was) is that bad, considering the options.
Once we set the precedent of having little 'char
* form_some_random_type()' functions, they will show up all over the place.
I need something like this for the MTD patch I've got that supports 64 bit buswidths on 32 bit machines and needs to printk the data on error.
I found that #define CFI_FMT '%lx' or whatever to be more straightforward, and easier to understand.
Quoted 13 lines
+ */
(quoted diff) +12
-0+char *form_dma_addr_t(char *buf, dma_addr_t a) +{ + char *fmt; /* Funny code to prevent a printf warning */ + + if (sizeof(dma_addr_t) == sizeof(long)) + fmt = "%lx"; + else + fmt = "%Lx"; + + sprintf(buf, fmt, a); + return buf; +}
Signature · 5 lines
Troy Benjegerdes | master of mispeeling | 'da hozer' | [email protected] -----"If this message isn't misspelled, I didn't write it" -- Me ----- "Why do musicians compose symphonies and poets write poems? They do it because life wouldn't have any meaning for them if they didn't. That's why I draw cartoons. It's my life." -- Charles Schulz
Quoted 6 lines · [email protected] said:
I need something like this for the MTD patch I've got that supports
64 bit buswidths on 32 bit machines and needs to printk the data on error.I found that #define
CFI_FMT'%lx' or whatever to be more straightforward, and easier to understand.
I got annoyed with the original implementation that turned up in CVS, with a completely separate printk line #ifdef CFI_WORD_64, and I changed it to always cast to (long long) before printing. Although I half suspect I'll end up redoing it again before actually sending it to Linus.
--
dwmw2
Quoted 11 lines · Jeff Garzik
Quoted 6 lines · Alan Cox
Quoted 4 lines
dma_addr_ttype. So the above usage will becomeprintk("stuff: " DMA_ADDR_T_FMT " %s", a, s);Vomit. How about adding a
dma_addr_t%code to the printk function ?heh, my comment on the patch was, "about as good as you can do without teaching printk and gcc about the type"
we could do:
char *format_dma_addr_t(char *buf, dma_addr_t a);
-
Quoted 6 lines · Alan Cox
Quoted 4 lines
dma_addr_ttype. So the above usage will becomeprintk("stuff: " DMA_ADDR_T_FMT " %s", a, s);Vomit.
See, I said I should have used [email protected] for this one.
Quoted 1 line
How about adding a
dma_addr_t%code to the printk function ?
The compiler's printf arg checking will choke on that.
-