linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [-next] FATAL: drivers/gpu/drm/udl/udl: sizeof(struct usb_device_id)=24 is not a modulo of the size of section __mod_usb_device_table=44.
@ 2012-06-15 17:42 Geert Uytterhoeven
  2012-06-15 20:10 ` Greg Kroah-Hartman
  0 siblings, 1 reply; 17+ messages in thread
From: Geert Uytterhoeven @ 2012-06-15 17:42 UTC (permalink / raw)
  To: Bjørn Mork, Greg Kroah-Hartman
  Cc: USB list, linux-kernel, Linux-Next, linux-kbuild, Linux/m68k

commit 81df2d594340dcb6d1a02191976be88a1ca8120c ("USB: allow match
on bInterfaceNumber") added a byte to the interior of struct usb_device_id,
enabling implicit padding:

--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -115,6 +118,9 @@ struct usb_device_id {
        __u8            bInterfaceSubClass;
        __u8            bInterfaceProtocol;

+       /* Used for vendor-specific interface matches */
+       __u8            bInterfaceNumber;
+
        /* not matched against */
        kernel_ulong_t  driver_info;
 };

On m68k, this causes failures like:

| FATAL: drivers/gpu/drm/udl/udl: sizeof(struct usb_device_id)=24 is
not a modulo of the size of section __mod_usb_device_table=44.
| Fix definition of struct usb_device_id in mod_devicetable.h

M68k is special in that it uses 2 for the alignment of 32-bit entities, hence
sizeof(struct usb_device_id) = 22.

However, when cross-compiling on amd64, sizeof(struct usb_device_id) = 24
in scripts/mod/file2alias.c.

m68k/allmodconfig at http://kisskb.ellerman.id.au/kisskb/buildresult/6518563/

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

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

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [-next] FATAL: drivers/gpu/drm/udl/udl: sizeof(struct usb_device_id)=24 is not a modulo of the size of section __mod_usb_device_table=44.
  2012-06-15 17:42 [-next] FATAL: drivers/gpu/drm/udl/udl: sizeof(struct usb_device_id)=24 is not a modulo of the size of section __mod_usb_device_table=44 Geert Uytterhoeven
@ 2012-06-15 20:10 ` Greg Kroah-Hartman
  2012-06-15 21:02   ` Geert Uytterhoeven
  0 siblings, 1 reply; 17+ messages in thread
From: Greg Kroah-Hartman @ 2012-06-15 20:10 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Bjørn Mork, USB list, linux-kernel, Linux-Next,
	linux-kbuild, Linux/m68k

On Fri, Jun 15, 2012 at 07:42:08PM +0200, Geert Uytterhoeven wrote:
> commit 81df2d594340dcb6d1a02191976be88a1ca8120c ("USB: allow match
> on bInterfaceNumber") added a byte to the interior of struct usb_device_id,
> enabling implicit padding:
> 
> --- a/include/linux/mod_devicetable.h
> +++ b/include/linux/mod_devicetable.h
> @@ -115,6 +118,9 @@ struct usb_device_id {
>         __u8            bInterfaceSubClass;
>         __u8            bInterfaceProtocol;
> 
> +       /* Used for vendor-specific interface matches */
> +       __u8            bInterfaceNumber;
> +
>         /* not matched against */
>         kernel_ulong_t  driver_info;
>  };
> 
> On m68k, this causes failures like:
> 
> | FATAL: drivers/gpu/drm/udl/udl: sizeof(struct usb_device_id)=24 is
> not a modulo of the size of section __mod_usb_device_table=44.
> | Fix definition of struct usb_device_id in mod_devicetable.h
> 
> M68k is special in that it uses 2 for the alignment of 32-bit entities, hence
> sizeof(struct usb_device_id) = 22.
> 
> However, when cross-compiling on amd64, sizeof(struct usb_device_id) = 24
> in scripts/mod/file2alias.c.

I don't really understand, what is the problem here?  The fact that we
added one byte to the structure?  And now something breaks?  How?

What can we do to resolve it?

confused,

greg k-h

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [-next] FATAL: drivers/gpu/drm/udl/udl: sizeof(struct usb_device_id)=24 is not a modulo of the size of section __mod_usb_device_table=44.
  2012-06-15 20:10 ` Greg Kroah-Hartman
@ 2012-06-15 21:02   ` Geert Uytterhoeven
  2012-06-15 23:12     ` Greg Kroah-Hartman
  0 siblings, 1 reply; 17+ messages in thread
From: Geert Uytterhoeven @ 2012-06-15 21:02 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Bjørn Mork, USB list, linux-kernel, Linux-Next,
	linux-kbuild, Linux/m68k

Hi Greg,

On Fri, Jun 15, 2012 at 10:10 PM, Greg Kroah-Hartman
<gregkh@linuxfoundation.org> wrote:
> On Fri, Jun 15, 2012 at 07:42:08PM +0200, Geert Uytterhoeven wrote:
>> commit 81df2d594340dcb6d1a02191976be88a1ca8120c ("USB: allow match
>> on bInterfaceNumber") added a byte to the interior of struct usb_device_id,
>> enabling implicit padding:
>>
>> --- a/include/linux/mod_devicetable.h
>> +++ b/include/linux/mod_devicetable.h
>> @@ -115,6 +118,9 @@ struct usb_device_id {
>>         __u8            bInterfaceSubClass;
>>         __u8            bInterfaceProtocol;
>>
>> +       /* Used for vendor-specific interface matches */
>> +       __u8            bInterfaceNumber;
>> +
>>         /* not matched against */
>>         kernel_ulong_t  driver_info;
>>  };
>>
>> On m68k, this causes failures like:
>>
>> | FATAL: drivers/gpu/drm/udl/udl: sizeof(struct usb_device_id)=24 is
>> not a modulo of the size of section __mod_usb_device_table=44.
>> | Fix definition of struct usb_device_id in mod_devicetable.h
>>
>> M68k is special in that it uses 2 for the alignment of 32-bit entities, hence
>> sizeof(struct usb_device_id) = 22.
>>
>> However, when cross-compiling on amd64, sizeof(struct usb_device_id) = 24
>> in scripts/mod/file2alias.c.
>
> I don't really understand, what is the problem here?  The fact that we
> added one byte to the structure?  And now something breaks?  How?
>
> What can we do to resolve it?

As "kernel_ulong_t  driver_info" is no longer naturally aligned, the
compiler will
add implicit padding. But the padding depends on the architecture.

It can be fixed by adding explicit padding. Probably it should be padded by
7 bytes (not 3), as kernel_ulong_t may require 8-byte alignment on some 64-bit
platforms. Or by an explicit alignment attribute.

See also
  * commit 8175fe2dda1c93a9c596921c8ed4a0b4baccdefe ("HID: fix
hid_device_id for cross compiling")
  * commit 7492d4a416d68ab4bd254b36ffcc4e0138daa8ff ("sdio: fix module
device table definition for m68k")
  * commit 9e2d3cd34a159948dc753a14573e16bffc04dba8 ("[PATCH]
mod_devicetable.h fixes")

Still, there's a bug in file2alias (which is compiled by the host
compiler), in that
it may use different padding than the target platform when cross-compiling.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

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

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [-next] FATAL: drivers/gpu/drm/udl/udl: sizeof(struct usb_device_id)=24 is not a modulo of the size of section __mod_usb_device_table=44.
  2012-06-15 21:02   ` Geert Uytterhoeven
@ 2012-06-15 23:12     ` Greg Kroah-Hartman
  2012-06-16 13:23       ` Bjørn Mork
  2012-06-16 18:51       ` Geert Uytterhoeven
  0 siblings, 2 replies; 17+ messages in thread
From: Greg Kroah-Hartman @ 2012-06-15 23:12 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Bjørn Mork, USB list, linux-kernel, Linux-Next,
	linux-kbuild, Linux/m68k

On Fri, Jun 15, 2012 at 11:02:55PM +0200, Geert Uytterhoeven wrote:
> Hi Greg,
> 
> On Fri, Jun 15, 2012 at 10:10 PM, Greg Kroah-Hartman
> <gregkh@linuxfoundation.org> wrote:
> > On Fri, Jun 15, 2012 at 07:42:08PM +0200, Geert Uytterhoeven wrote:
> >> commit 81df2d594340dcb6d1a02191976be88a1ca8120c ("USB: allow match
> >> on bInterfaceNumber") added a byte to the interior of struct usb_device_id,
> >> enabling implicit padding:
> >>
> >> --- a/include/linux/mod_devicetable.h
> >> +++ b/include/linux/mod_devicetable.h
> >> @@ -115,6 +118,9 @@ struct usb_device_id {
> >>         __u8            bInterfaceSubClass;
> >>         __u8            bInterfaceProtocol;
> >>
> >> +       /* Used for vendor-specific interface matches */
> >> +       __u8            bInterfaceNumber;
> >> +
> >>         /* not matched against */
> >>         kernel_ulong_t  driver_info;
> >>  };
> >>
> >> On m68k, this causes failures like:
> >>
> >> | FATAL: drivers/gpu/drm/udl/udl: sizeof(struct usb_device_id)=24 is
> >> not a modulo of the size of section __mod_usb_device_table=44.
> >> | Fix definition of struct usb_device_id in mod_devicetable.h
> >>
> >> M68k is special in that it uses 2 for the alignment of 32-bit entities, hence
> >> sizeof(struct usb_device_id) = 22.
> >>
> >> However, when cross-compiling on amd64, sizeof(struct usb_device_id) = 24
> >> in scripts/mod/file2alias.c.
> >
> > I don't really understand, what is the problem here?  The fact that we
> > added one byte to the structure?  And now something breaks?  How?
> >
> > What can we do to resolve it?
> 
> As "kernel_ulong_t  driver_info" is no longer naturally aligned, the
> compiler will
> add implicit padding. But the padding depends on the architecture.

Ah, so we were "lucky" before, nice.

> It can be fixed by adding explicit padding. Probably it should be padded by
> 7 bytes (not 3), as kernel_ulong_t may require 8-byte alignment on some 64-bit
> platforms. Or by an explicit alignment attribute.
> 
> See also
>   * commit 8175fe2dda1c93a9c596921c8ed4a0b4baccdefe ("HID: fix
> hid_device_id for cross compiling")
>   * commit 7492d4a416d68ab4bd254b36ffcc4e0138daa8ff ("sdio: fix module
> device table definition for m68k")
>   * commit 9e2d3cd34a159948dc753a14573e16bffc04dba8 ("[PATCH]
> mod_devicetable.h fixes")

So would the patch below fix this?  It should force alignment of the
driver_data field, which is all you want here, right?

> Still, there's a bug in file2alias (which is compiled by the host
> compiler), in that
> it may use different padding than the target platform when cross-compiling.

That's not good, but outside of this specific issue, right?  Have we
just been fortunate it hasn't really hit us yet?

thanks,

greg k-h

diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index 7771d45..6955045 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -122,7 +122,8 @@ struct usb_device_id {
 	__u8		bInterfaceNumber;
 
 	/* not matched against */
-	kernel_ulong_t	driver_info;
+	kernel_ulong_t	driver_info
+		__attribute__((aligned(sizeof(kernel_ulong_t))));
 };
 
 /* Some useful macros to use to create struct usb_device_id */

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [-next] FATAL: drivers/gpu/drm/udl/udl: sizeof(struct usb_device_id)=24 is not a modulo of the size of section __mod_usb_device_table=44.
  2012-06-15 23:12     ` Greg Kroah-Hartman
@ 2012-06-16 13:23       ` Bjørn Mork
  2012-06-16 15:43         ` Andreas Schwab
                           ` (2 more replies)
  2012-06-16 18:51       ` Geert Uytterhoeven
  1 sibling, 3 replies; 17+ messages in thread
From: Bjørn Mork @ 2012-06-16 13:23 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Geert Uytterhoeven, USB list, linux-kernel, Linux-Next,
	linux-kbuild, Linux/m68k

Greg Kroah-Hartman <gregkh@linuxfoundation.org> writes:
> On Fri, Jun 15, 2012 at 11:02:55PM +0200, Geert Uytterhoeven wrote:
>
>> As "kernel_ulong_t  driver_info" is no longer naturally aligned, the
>> compiler will
>> add implicit padding. But the padding depends on the architecture.
>
> Ah, so we were "lucky" before, nice.

I don't really believe in luck :-)  I think someone has been really
smart here.  Maybe too smart...


>> It can be fixed by adding explicit padding. Probably it should be padded by
>> 7 bytes (not 3), as kernel_ulong_t may require 8-byte alignment on some 64-bit
>> platforms. Or by an explicit alignment attribute.
>> 
>> See also
>>   * commit 8175fe2dda1c93a9c596921c8ed4a0b4baccdefe ("HID: fix
>> hid_device_id for cross compiling")
>>   * commit 7492d4a416d68ab4bd254b36ffcc4e0138daa8ff ("sdio: fix module
>> device table definition for m68k")
>>   * commit 9e2d3cd34a159948dc753a14573e16bffc04dba8 ("[PATCH]
>> mod_devicetable.h fixes")
>
> So would the patch below fix this?  It should force alignment of the
> driver_data field, which is all you want here, right?
>
>> Still, there's a bug in file2alias (which is compiled by the host
>> compiler), in that
>> it may use different padding than the target platform when cross-compiling.
>
> That's not good, but outside of this specific issue, right?  Have we
> just been fortunate it hasn't really hit us yet?
>
> thanks,
>
> greg k-h
>
> diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
> index 7771d45..6955045 100644
> --- a/include/linux/mod_devicetable.h
> +++ b/include/linux/mod_devicetable.h
> @@ -122,7 +122,8 @@ struct usb_device_id {
>  	__u8		bInterfaceNumber;
>  
>  	/* not matched against */
> -	kernel_ulong_t	driver_info;
> +	kernel_ulong_t	driver_info
> +		__attribute__((aligned(sizeof(kernel_ulong_t))));
>  };


This feels a lot like papering over the real problem.  It will solve
this instance, but the list of such previous "paper work" that Geert
provided should be enough evidence that this will happen again the next
time someone modifies a device id struct for some subsystem.

And adding forced aligment here feels wrong since there is no good
reason why the (target) compiler shouldn't know the proper alignment for
this structure, is there? OK, "feels wrong" is not a good argument. But
it would be better to solve this problem once and for all.

AFAIK (which admittedly is not much wrt cross building) there is no way
we can make the host built file2alias know the proper aligment for the
structure in the target built modules.  That's the background for this
fix: 

commit 4ce6efed48d736e3384c39ff87bda723e1f8e041
Author: Sam Ravnborg <sam@uranus.ravnborg.org>
Date:   Sun Mar 23 21:38:54 2008 +0100

    kbuild: soften modpost checks when doing cross builds
    
    The module alias support in the kernel have a consistency
    check where it is checked that the size of a structure
    in the kernel and on the build host are the same.
    For cross builds this check does not make sense so detect
    when we do cross builds and silently skip the check in these
    situations.
    This fixes a build bug for a wireless driver when cross building
    for arm.



What I'm now wondering is why didn't this kick in?  I believe we should
find and fix that instead of playing around with the in-kernel structure
alignments.  If that's possible.

BTW, thanks for finding and reporting this at such an early stage,
Geert.


Bjørn

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [-next] FATAL: drivers/gpu/drm/udl/udl: sizeof(struct usb_device_id)=24 is not a modulo of the size of section __mod_usb_device_table=44.
  2012-06-16 13:23       ` Bjørn Mork
@ 2012-06-16 15:43         ` Andreas Schwab
  2012-06-17 14:00           ` Bjørn Mork
  2012-06-16 18:33         ` [-next] FATAL: drivers/gpu/drm/udl/udl: sizeof(struct usb_device_id)=24 is not a modulo of the size of section __mod_usb_device_table=44 Philippe De Muyter
  2012-06-16 19:11         ` Greg Kroah-Hartman
  2 siblings, 1 reply; 17+ messages in thread
From: Andreas Schwab @ 2012-06-16 15:43 UTC (permalink / raw)
  To: Bjørn Mork
  Cc: Greg Kroah-Hartman, Geert Uytterhoeven, USB list, linux-kernel,
	Linux-Next, linux-kbuild, Linux/m68k

Bjørn Mork <bjorn@mork.no> writes:

> AFAIK (which admittedly is not much wrt cross building) there is no way
> we can make the host built file2alias know the proper aligment for the
> structure in the target built modules.  That's the background for this
> fix: 
>
> commit 4ce6efed48d736e3384c39ff87bda723e1f8e041
> Author: Sam Ravnborg <sam@uranus.ravnborg.org>
> Date:   Sun Mar 23 21:38:54 2008 +0100
>
>     kbuild: soften modpost checks when doing cross builds

This is not a fix in any sense of the word.  modpost can only work
properly if its view of the device_id structures matches *exactly* that
of the target.

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [-next] FATAL: drivers/gpu/drm/udl/udl: sizeof(struct usb_device_id)=24 is not a modulo of the size of section __mod_usb_device_table=44.
  2012-06-16 13:23       ` Bjørn Mork
  2012-06-16 15:43         ` Andreas Schwab
@ 2012-06-16 18:33         ` Philippe De Muyter
  2012-06-16 19:11         ` Greg Kroah-Hartman
  2 siblings, 0 replies; 17+ messages in thread
From: Philippe De Muyter @ 2012-06-16 18:33 UTC (permalink / raw)
  To: Bjørn Mork
  Cc: Greg Kroah-Hartman, Geert Uytterhoeven, USB list, linux-kernel,
	Linux-Next, linux-kbuild, Linux/m68k

On Sat, Jun 16, 2012 at 03:23:31PM +0200, Bjørn Mork wrote:
> 
> AFAIK (which admittedly is not much wrt cross building) there is no way
> we can make the host built file2alias know the proper aligment for the
> structure in the target built modules.  That's the background for this
> fix: 

autoconf has a lot of nice macros (using the cross-compiler) to solve
that sort  of problems.

Philippe

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [-next] FATAL: drivers/gpu/drm/udl/udl: sizeof(struct usb_device_id)=24 is not a modulo of the size of section __mod_usb_device_table=44.
  2012-06-15 23:12     ` Greg Kroah-Hartman
  2012-06-16 13:23       ` Bjørn Mork
@ 2012-06-16 18:51       ` Geert Uytterhoeven
  1 sibling, 0 replies; 17+ messages in thread
From: Geert Uytterhoeven @ 2012-06-16 18:51 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Bjørn Mork, USB list, linux-kernel, Linux-Next,
	linux-kbuild, Linux/m68k

Hi Greg,

On Sat, Jun 16, 2012 at 1:12 AM, Greg Kroah-Hartman
<gregkh@linuxfoundation.org> wrote:
> On Fri, Jun 15, 2012 at 11:02:55PM +0200, Geert Uytterhoeven wrote:
>> On Fri, Jun 15, 2012 at 10:10 PM, Greg Kroah-Hartman
>> <gregkh@linuxfoundation.org> wrote:
>> > On Fri, Jun 15, 2012 at 07:42:08PM +0200, Geert Uytterhoeven wrote:
>> >> commit 81df2d594340dcb6d1a02191976be88a1ca8120c ("USB: allow match
>> >> on bInterfaceNumber") added a byte to the interior of struct usb_device_id,
>> >> enabling implicit padding:
>> >>
>> >> --- a/include/linux/mod_devicetable.h
>> >> +++ b/include/linux/mod_devicetable.h
>> >> @@ -115,6 +118,9 @@ struct usb_device_id {
>> >>         __u8            bInterfaceSubClass;
>> >>         __u8            bInterfaceProtocol;
>> >>
>> >> +       /* Used for vendor-specific interface matches */
>> >> +       __u8            bInterfaceNumber;
>> >> +
>> >>         /* not matched against */
>> >>         kernel_ulong_t  driver_info;
>> >>  };
>> >>
>> >> On m68k, this causes failures like:
>> >>
>> >> | FATAL: drivers/gpu/drm/udl/udl: sizeof(struct usb_device_id)=24 is
>> >> not a modulo of the size of section __mod_usb_device_table=44.
>> >> | Fix definition of struct usb_device_id in mod_devicetable.h
>> >>
>> >> M68k is special in that it uses 2 for the alignment of 32-bit entities, hence
>> >> sizeof(struct usb_device_id) = 22.
>> >>
>> >> However, when cross-compiling on amd64, sizeof(struct usb_device_id) = 24
>> >> in scripts/mod/file2alias.c.
>> >
>> > I don't really understand, what is the problem here?  The fact that we
>> > added one byte to the structure?  And now something breaks?  How?
>> >
>> > What can we do to resolve it?
>>
>> As "kernel_ulong_t  driver_info" is no longer naturally aligned, the
>> compiler will
>> add implicit padding. But the padding depends on the architecture.
>
> Ah, so we were "lucky" before, nice.
>
>> It can be fixed by adding explicit padding. Probably it should be padded by
>> 7 bytes (not 3), as kernel_ulong_t may require 8-byte alignment on some 64-bit
>> platforms. Or by an explicit alignment attribute.
>>
>> See also
>>   * commit 8175fe2dda1c93a9c596921c8ed4a0b4baccdefe ("HID: fix
>> hid_device_id for cross compiling")
>>   * commit 7492d4a416d68ab4bd254b36ffcc4e0138daa8ff ("sdio: fix module
>> device table definition for m68k")
>>   * commit 9e2d3cd34a159948dc753a14573e16bffc04dba8 ("[PATCH]
>> mod_devicetable.h fixes")
>
> So would the patch below fix this?  It should force alignment of the
> driver_data field, which is all you want here, right?

Yes, it's fixes it, so

Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>

>> Still, there's a bug in file2alias (which is compiled by the host
>> compiler), in that
>> it may use different padding than the target platform when cross-compiling.
>
> That's not good, but outside of this specific issue, right?  Have we
> just been fortunate it hasn't really hit us yet?
>
> thanks,
>
> greg k-h
>
> diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
> index 7771d45..6955045 100644
> --- a/include/linux/mod_devicetable.h
> +++ b/include/linux/mod_devicetable.h
> @@ -122,7 +122,8 @@ struct usb_device_id {
>        __u8            bInterfaceNumber;
>
>        /* not matched against */
> -       kernel_ulong_t  driver_info;
> +       kernel_ulong_t  driver_info
> +               __attribute__((aligned(sizeof(kernel_ulong_t))));
>  };
>
>  /* Some useful macros to use to create struct usb_device_id */

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

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

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [-next] FATAL: drivers/gpu/drm/udl/udl: sizeof(struct usb_device_id)=24 is not a modulo of the size of section __mod_usb_device_table=44.
  2012-06-16 13:23       ` Bjørn Mork
  2012-06-16 15:43         ` Andreas Schwab
  2012-06-16 18:33         ` [-next] FATAL: drivers/gpu/drm/udl/udl: sizeof(struct usb_device_id)=24 is not a modulo of the size of section __mod_usb_device_table=44 Philippe De Muyter
@ 2012-06-16 19:11         ` Greg Kroah-Hartman
  2012-06-16 19:30           ` Geert Uytterhoeven
  2 siblings, 1 reply; 17+ messages in thread
From: Greg Kroah-Hartman @ 2012-06-16 19:11 UTC (permalink / raw)
  To: Bjørn Mork
  Cc: Geert Uytterhoeven, USB list, linux-kernel, Linux-Next,
	linux-kbuild, Linux/m68k

On Sat, Jun 16, 2012 at 03:23:31PM +0200, Bjørn Mork wrote:
> Greg Kroah-Hartman <gregkh@linuxfoundation.org> writes:
> > On Fri, Jun 15, 2012 at 11:02:55PM +0200, Geert Uytterhoeven wrote:
> >
> >> As "kernel_ulong_t  driver_info" is no longer naturally aligned, the
> >> compiler will
> >> add implicit padding. But the padding depends on the architecture.
> >
> > Ah, so we were "lucky" before, nice.
> 
> I don't really believe in luck :-)  I think someone has been really
> smart here.  Maybe too smart...

No, I think the previous structure was just "lucky" in that it just
happened to be the right alignment.  I say this as I think I was the one
who created that structure years ago.  Or maybe not, this was back in
the 2.3 kernel days, I can't remember what patches I wrote last week...

> >> It can be fixed by adding explicit padding. Probably it should be padded by
> >> 7 bytes (not 3), as kernel_ulong_t may require 8-byte alignment on some 64-bit
> >> platforms. Or by an explicit alignment attribute.
> >> 
> >> See also
> >>   * commit 8175fe2dda1c93a9c596921c8ed4a0b4baccdefe ("HID: fix
> >> hid_device_id for cross compiling")
> >>   * commit 7492d4a416d68ab4bd254b36ffcc4e0138daa8ff ("sdio: fix module
> >> device table definition for m68k")
> >>   * commit 9e2d3cd34a159948dc753a14573e16bffc04dba8 ("[PATCH]
> >> mod_devicetable.h fixes")
> >
> > So would the patch below fix this?  It should force alignment of the
> > driver_data field, which is all you want here, right?
> >
> >> Still, there's a bug in file2alias (which is compiled by the host
> >> compiler), in that
> >> it may use different padding than the target platform when cross-compiling.
> >
> > That's not good, but outside of this specific issue, right?  Have we
> > just been fortunate it hasn't really hit us yet?
> >
> > thanks,
> >
> > greg k-h
> >
> > diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
> > index 7771d45..6955045 100644
> > --- a/include/linux/mod_devicetable.h
> > +++ b/include/linux/mod_devicetable.h
> > @@ -122,7 +122,8 @@ struct usb_device_id {
> >  	__u8		bInterfaceNumber;
> >  
> >  	/* not matched against */
> > -	kernel_ulong_t	driver_info;
> > +	kernel_ulong_t	driver_info
> > +		__attribute__((aligned(sizeof(kernel_ulong_t))));
> >  };
> 
> 
> This feels a lot like papering over the real problem.  It will solve
> this instance, but the list of such previous "paper work" that Geert
> provided should be enough evidence that this will happen again the next
> time someone modifies a device id struct for some subsystem.

Hopefully not, if you add another field here, the alignment force will
keep things lined up properly, from what I can tell.  Is that not true?

> And adding forced aligment here feels wrong since there is no good
> reason why the (target) compiler shouldn't know the proper alignment for
> this structure, is there? OK, "feels wrong" is not a good argument. But
> it would be better to solve this problem once and for all.

C doesn't require the structure to be aligned.  Actually the spec says
it doesn't guarantee anything about this, we just "know" that gcc is
going to be semi-sane and try to do the best it can.  Hopefully clang is
also semi-sane as well.

So because of that, we have to give it some guidance, hence the patch.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [-next] FATAL: drivers/gpu/drm/udl/udl: sizeof(struct usb_device_id)=24 is not a modulo of the size of section __mod_usb_device_table=44.
  2012-06-16 19:11         ` Greg Kroah-Hartman
@ 2012-06-16 19:30           ` Geert Uytterhoeven
  0 siblings, 0 replies; 17+ messages in thread
From: Geert Uytterhoeven @ 2012-06-16 19:30 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Bjørn Mork, USB list, linux-kernel, Linux-Next,
	linux-kbuild, Linux/m68k

On Sat, Jun 16, 2012 at 9:11 PM, Greg Kroah-Hartman
<gregkh@linuxfoundation.org> wrote:
> On Sat, Jun 16, 2012 at 03:23:31PM +0200, Bjørn Mork wrote:
>> Greg Kroah-Hartman <gregkh@linuxfoundation.org> writes:
>> > On Fri, Jun 15, 2012 at 11:02:55PM +0200, Geert Uytterhoeven wrote:
>> >
>> >> As "kernel_ulong_t  driver_info" is no longer naturally aligned, the
>> >> compiler will
>> >> add implicit padding. But the padding depends on the architecture.
>> >
>> > Ah, so we were "lucky" before, nice.
>>
>> I don't really believe in luck :-)  I think someone has been really
>> smart here.  Maybe too smart...
>
> No, I think the previous structure was just "lucky" in that it just
> happened to be the right alignment.  I say this as I think I was the one
> who created that structure years ago.  Or maybe not, this was back in
> the 2.3 kernel days, I can't remember what patches I wrote last week...
>
>> >> It can be fixed by adding explicit padding. Probably it should be padded by
>> >> 7 bytes (not 3), as kernel_ulong_t may require 8-byte alignment on some 64-bit
>> >> platforms. Or by an explicit alignment attribute.
>> >>
>> >> See also
>> >>   * commit 8175fe2dda1c93a9c596921c8ed4a0b4baccdefe ("HID: fix
>> >> hid_device_id for cross compiling")
>> >>   * commit 7492d4a416d68ab4bd254b36ffcc4e0138daa8ff ("sdio: fix module
>> >> device table definition for m68k")
>> >>   * commit 9e2d3cd34a159948dc753a14573e16bffc04dba8 ("[PATCH]
>> >> mod_devicetable.h fixes")
>> >
>> > So would the patch below fix this?  It should force alignment of the
>> > driver_data field, which is all you want here, right?
>> >
>> >> Still, there's a bug in file2alias (which is compiled by the host
>> >> compiler), in that
>> >> it may use different padding than the target platform when cross-compiling.
>> >
>> > That's not good, but outside of this specific issue, right?  Have we
>> > just been fortunate it hasn't really hit us yet?
>> >
>> > thanks,
>> >
>> > greg k-h
>> >
>> > diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
>> > index 7771d45..6955045 100644
>> > --- a/include/linux/mod_devicetable.h
>> > +++ b/include/linux/mod_devicetable.h
>> > @@ -122,7 +122,8 @@ struct usb_device_id {
>> >     __u8            bInterfaceNumber;
>> >
>> >     /* not matched against */
>> > -   kernel_ulong_t  driver_info;
>> > +   kernel_ulong_t  driver_info
>> > +           __attribute__((aligned(sizeof(kernel_ulong_t))));
>> >  };
>>
>>
>> This feels a lot like papering over the real problem.  It will solve
>> this instance, but the list of such previous "paper work" that Geert
>> provided should be enough evidence that this will happen again the next
>> time someone modifies a device id struct for some subsystem.
>
> Hopefully not, if you add another field here, the alignment force will
> keep things lined up properly, from what I can tell.  Is that not true?

... for struct usb_device_id.
But not for all other existing and future device ID types.

We have kernel_ulong_t to tell the host compiler what the target's
unsigned long type (actually only its size, not alignment) is.

scripts/mod/file2alias.c handles this with:

#if KERNEL_ELFCLASS == ELFCLASS32
typedef Elf32_Addr      kernel_ulong_t;
#define BITS_PER_LONG 32
#else
typedef Elf64_Addr      kernel_ulong_t;
#define BITS_PER_LONG 64
#endif

To fix the misalignment issue, can't we add
"__attribute__((aligned(2)))" to the typedef when cross-compiling for m68k?

Still, that only solves the problem for "kernel_ulong_t". Not for all other
4 or 8 bytes types (in practice just "u32") that are used in
include/linux/mod_devicetable.h. So we would also need "kernel_u32".
And "kernel_u16" for consistency.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

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

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [-next] FATAL: drivers/gpu/drm/udl/udl: sizeof(struct usb_device_id)=24 is not a modulo of the size of section __mod_usb_device_table=44.
  2012-06-16 15:43         ` Andreas Schwab
@ 2012-06-17 14:00           ` Bjørn Mork
  2012-06-17 15:42             ` Andreas Schwab
  2012-06-25 12:22             ` [PATCH] mod/file2alias: make modalias generation safe for cross compiling Andreas Schwab
  0 siblings, 2 replies; 17+ messages in thread
From: Bjørn Mork @ 2012-06-17 14:00 UTC (permalink / raw)
  To: Andreas Schwab
  Cc: Greg Kroah-Hartman, Geert Uytterhoeven, USB list, linux-kernel,
	Linux-Next, linux-kbuild, Linux/m68k

Andreas Schwab <schwab@linux-m68k.org> writes:
> Bjørn Mork <bjorn@mork.no> writes:
>
>> AFAIK (which admittedly is not much wrt cross building) there is no way
>> we can make the host built file2alias know the proper aligment for the
>> structure in the target built modules.  That's the background for this
>> fix: 
>>
>> commit 4ce6efed48d736e3384c39ff87bda723e1f8e041
>> Author: Sam Ravnborg <sam@uranus.ravnborg.org>
>> Date:   Sun Mar 23 21:38:54 2008 +0100
>>
>>     kbuild: soften modpost checks when doing cross builds
>
> This is not a fix in any sense of the word.  modpost can only work
> properly if its view of the device_id structures matches *exactly* that
> of the target.

You are absolutely correct, of course.  I am starting to believe Greg is
correct.  Cross building works mostly by pure luck :-)

I found that the reason the change I referred to above didn't kick in
was because CONFIG_DEBUG_SECTION_MISMATCH was set, causing modpost to be
called from scripts/Makefile.build without the "-c" option:

 # Do section mismatch analysis for each module/built-in.o
 ifdef CONFIG_DEBUG_SECTION_MISMATCH
   cmd_secanalysis = ; scripts/mod/modpost $@
 endif


But as you point out: The whole "soften modpost check" concept is bogus.
It just cannot work.  And I just verified it doing a m68k allmodconfig
build without CONFIG_DEBUG_SECTION_MISMATCH.  modpost will bail out
unless host and target aligment matches:

  scripts/mod/modpost -m -a -o /usr/local/src/build-tmp/linux/Module.symvers    -S  -c -s
drivers/media/video/gspca/gspca_sunplus: struct usb_device_id is 24 bytes.  The last of 55 is:
0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
FATAL: drivers/media/video/gspca/gspca_sunplus: struct usb_device_id is not terminated with a NULL entry!
make[1]: *** [__modpost] Error 1
make: *** [modules] Error 2


So the prosed fix from Greg is certainly the correct one, until someone
rewrites modpost to be completely cross build safe.


Bjørn

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [-next] FATAL: drivers/gpu/drm/udl/udl: sizeof(struct usb_device_id)=24 is not a modulo of the size of section __mod_usb_device_table=44.
  2012-06-17 14:00           ` Bjørn Mork
@ 2012-06-17 15:42             ` Andreas Schwab
  2012-06-25 12:22             ` [PATCH] mod/file2alias: make modalias generation safe for cross compiling Andreas Schwab
  1 sibling, 0 replies; 17+ messages in thread
From: Andreas Schwab @ 2012-06-17 15:42 UTC (permalink / raw)
  To: Bjørn Mork
  Cc: Greg Kroah-Hartman, Geert Uytterhoeven, USB list, linux-kernel,
	Linux-Next, linux-kbuild, Linux/m68k

Bjørn Mork <bjorn@mork.no> writes:

> So the prosed fix from Greg is certainly the correct one, until someone
> rewrites modpost to be completely cross build safe.

I started working on that.  Then I saw do_input and barfed.

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH] mod/file2alias: make modalias generation safe for cross compiling
  2012-06-17 14:00           ` Bjørn Mork
  2012-06-17 15:42             ` Andreas Schwab
@ 2012-06-25 12:22             ` Andreas Schwab
  2012-06-25 20:32               ` Geert Uytterhoeven
  2012-06-26  5:00               ` Sam Ravnborg
  1 sibling, 2 replies; 17+ messages in thread
From: Andreas Schwab @ 2012-06-25 12:22 UTC (permalink / raw)
  To: Bjørn Mork
  Cc: Greg Kroah-Hartman, Geert Uytterhoeven, USB list, linux-kernel,
	Linux-Next, linux-kbuild, Linux/m68k

Use the target compiler to compute the offsets of the fields of the
device_id structures, so that it won't be broken by different alignments
between the host and target ABIs.

This also fixes missing endian corrections for some modaliases.

Signed-off-by: Andreas Schwab <schwab@linux-m68k.org>
---
This has been tested by cross-compiling a allmodconfig kernel for m68k
and comparing the generated modaliases with the ones generated by a
natively compiled modpost.

 include/linux/mod_devicetable.h   |  59 +---
 scripts/Makefile.modpost          |   3 +-
 scripts/mod/.gitignore            |   1 +
 scripts/mod/Makefile              |  35 ++
 scripts/mod/devicetable-offsets.c | 171 ++++++++++
 scripts/mod/file2alias.c          | 649 +++++++++++++++++++++-----------------
 scripts/mod/modpost.c             |   5 +-
 7 files changed, 571 insertions(+), 352 deletions(-)
 create mode 100644 scripts/mod/devicetable-offsets.c

diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index 501da4c..81c372b 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -33,8 +33,7 @@ struct ieee1394_device_id {
 	__u32 model_id;
 	__u32 specifier_id;
 	__u32 version;
-	kernel_ulong_t driver_data
-		__attribute__((aligned(sizeof(kernel_ulong_t))));
+	kernel_ulong_t driver_data;
 };
 
 
@@ -135,11 +134,9 @@ struct usb_device_id {
 
 struct hid_device_id {
 	__u16 bus;
-	__u16 pad1;
 	__u32 vendor;
 	__u32 product;
-	kernel_ulong_t driver_data
-		__attribute__((aligned(sizeof(kernel_ulong_t))));
+	kernel_ulong_t driver_data;
 };
 
 /* s390 CCW devices */
@@ -163,8 +160,6 @@ struct ccw_device_id {
 struct ap_device_id {
 	__u16 match_flags;	/* which fields to match against */
 	__u8 dev_type;		/* device type */
-	__u8 pad1;
-	__u32 pad2;
 	kernel_ulong_t driver_info;
 };
 
@@ -174,13 +169,10 @@ struct ap_device_id {
 struct css_device_id {
 	__u8 match_flags;
 	__u8 type; /* subchannel type */
-	__u16 pad2;
-	__u32 pad3;
 	kernel_ulong_t driver_data;
 };
 
-#define ACPI_ID_LEN	16 /* only 9 bytes needed here, 16 bytes are used */
-			   /* to workaround crosscompile issues */
+#define ACPI_ID_LEN	9
 
 struct acpi_device_id {
 	__u8 id[ACPI_ID_LEN];
@@ -221,11 +213,7 @@ struct of_device_id
 	char	name[32];
 	char	type[32];
 	char	compatible[128];
-#ifdef __KERNEL__
 	void	*data;
-#else
-	kernel_ulong_t data;
-#endif
 };
 
 /* VIO */
@@ -250,24 +238,14 @@ struct pcmcia_device_id {
 	/* for pseudo multi-function devices */
 	__u8  		device_no;
 
-	__u32 		prod_id_hash[4]
-		__attribute__((aligned(sizeof(__u32))));
+	__u32 		prod_id_hash[4];
 
 	/* not matched against in kernelspace*/
-#ifdef __KERNEL__
 	const char *	prod_id[4];
-#else
-	kernel_ulong_t	prod_id[4]
-		__attribute__((aligned(sizeof(kernel_ulong_t))));
-#endif
 
 	/* not matched against */
 	kernel_ulong_t	driver_info;
-#ifdef __KERNEL__
 	char *		cisfile;
-#else
-	kernel_ulong_t	cisfile;
-#endif
 };
 
 #define PCMCIA_DEV_ID_MATCH_MANF_ID	0x0001
@@ -363,8 +341,7 @@ struct sdio_device_id {
 	__u8	class;			/* Standard interface or SDIO_ANY_ID */
 	__u16	vendor;			/* Vendor or SDIO_ANY_ID */
 	__u16	device;			/* Device ID or SDIO_ANY_ID */
-	kernel_ulong_t driver_data	/* Data private to the driver */
-		__attribute__((aligned(sizeof(kernel_ulong_t))));
+	kernel_ulong_t driver_data;	/* Data private to the driver */
 };
 
 /* SSB core, see drivers/ssb/ */
@@ -410,8 +387,7 @@ struct virtio_device_id {
  */
 struct hv_vmbus_device_id {
 	__u8 guid[16];
-	kernel_ulong_t driver_data	/* Data private to the driver */
-			__attribute__((aligned(sizeof(kernel_ulong_t))));
+	kernel_ulong_t driver_data;	/* Data private to the driver */
 };
 
 /* rpmsg */
@@ -430,8 +406,7 @@ struct rpmsg_device_id {
 
 struct i2c_device_id {
 	char name[I2C_NAME_SIZE];
-	kernel_ulong_t driver_data	/* Data private to the driver */
-			__attribute__((aligned(sizeof(kernel_ulong_t))));
+	kernel_ulong_t driver_data;	/* Data private to the driver */
 };
 
 /* spi */
@@ -441,8 +416,7 @@ struct i2c_device_id {
 
 struct spi_device_id {
 	char name[SPI_NAME_SIZE];
-	kernel_ulong_t driver_data	/* Data private to the driver */
-			__attribute__((aligned(sizeof(kernel_ulong_t))));
+	kernel_ulong_t driver_data;	/* Data private to the driver */
 };
 
 /* dmi */
@@ -474,15 +448,6 @@ struct dmi_strmatch {
 	char substr[79];
 };
 
-#ifndef __KERNEL__
-struct dmi_system_id {
-	kernel_ulong_t callback;
-	kernel_ulong_t ident;
-	struct dmi_strmatch matches[4];
-	kernel_ulong_t driver_data
-			__attribute__((aligned(sizeof(kernel_ulong_t))));
-};
-#else
 struct dmi_system_id {
 	int (*callback)(const struct dmi_system_id *);
 	const char *ident;
@@ -496,7 +461,6 @@ struct dmi_system_id {
  *	error: storage size of '__mod_dmi_device_table' isn't known
  */
 #define dmi_device_id dmi_system_id
-#endif
 
 #define DMI_MATCH(a, b)	{ a, b }
 
@@ -505,8 +469,7 @@ struct dmi_system_id {
 
 struct platform_device_id {
 	char name[PLATFORM_NAME_SIZE];
-	kernel_ulong_t driver_data
-			__attribute__((aligned(sizeof(kernel_ulong_t))));
+	kernel_ulong_t driver_data;
 };
 
 #define MDIO_MODULE_PREFIX	"mdio:"
@@ -562,11 +525,7 @@ struct isapnp_device_id {
 struct amba_id {
 	unsigned int		id;
 	unsigned int		mask;
-#ifndef __KERNEL__
-	kernel_ulong_t		data;
-#else
 	void			*data;
-#endif
 };
 
 /*
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index 08dce14..ff22206 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -80,8 +80,7 @@ modpost = scripts/mod/modpost                    \
  $(if $(KBUILD_EXTRA_SYMBOLS), $(patsubst %, -e %,$(KBUILD_EXTRA_SYMBOLS))) \
  $(if $(KBUILD_EXTMOD),-o $(modulesymfile))      \
  $(if $(CONFIG_DEBUG_SECTION_MISMATCH),,-S)      \
- $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w) \
- $(if $(cross_build),-c)
+ $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w)
 
 quiet_cmd_modpost = MODPOST $(words $(filter-out vmlinux FORCE, $^)) modules
       cmd_modpost = $(modpost) -s
diff --git a/scripts/mod/.gitignore b/scripts/mod/.gitignore
index e9b7abe..33bae0d 100644
--- a/scripts/mod/.gitignore
+++ b/scripts/mod/.gitignore
@@ -1,4 +1,5 @@
 elfconfig.h
 mk_elfconfig
 modpost
+devicetable-offsets.h
 
diff --git a/scripts/mod/Makefile b/scripts/mod/Makefile
index ff954f8..9415b56 100644
--- a/scripts/mod/Makefile
+++ b/scripts/mod/Makefile
@@ -3,9 +3,44 @@ always		:= $(hostprogs-y) empty.o
 
 modpost-objs	:= modpost.o file2alias.o sumversion.o
 
+devicetable-offsets-file := devicetable-offsets.h
+
+define sed-y
+	"/^->/{s:->#\(.*\):/* \1 */:; \
+	s:^->\([^ ]*\) [\$$#]*\([-0-9]*\) \(.*\):#define \1 \2 /* \3 */:; \
+	s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \
+	s:->::; p;}"
+endef
+
+quiet_cmd_offsets = GEN     $@
+define cmd_offsets
+	(set -e; \
+	 echo "#ifndef __DEVICEVTABLE_OFFSETS_H__"; \
+	 echo "#define __DEVICEVTABLE_OFFSETS_H__"; \
+	 echo "/*"; \
+	 echo " * DO NOT MODIFY."; \
+	 echo " *"; \
+	 echo " * This file was generated by Kbuild"; \
+	 echo " *"; \
+	 echo " */"; \
+	 echo ""; \
+	 sed -ne $(sed-y) $<; \
+	 echo ""; \
+	 echo "#endif" ) > $@
+endef
+
+# We use internal kbuild rules to avoid the "is up to date" message from make
+scripts/mod/devicetable-offsets.s: scripts/mod/devicetable-offsets.c FORCE
+	$(Q)mkdir -p $(dir $@)
+	$(call if_changed_dep,cc_s_c)
+
+$(obj)/$(devicetable-offsets-file): scripts/mod/devicetable-offsets.s
+	$(call cmd,offsets)
+
 # dependencies on generated files need to be listed explicitly
 
 $(obj)/modpost.o $(obj)/file2alias.o $(obj)/sumversion.o: $(obj)/elfconfig.h
+$(obj)/file2alias.o: $(obj)/$(devicetable-offsets-file)
 
 quiet_cmd_elfconfig = MKELF   $@
       cmd_elfconfig = $(obj)/mk_elfconfig < $< > $@
diff --git a/scripts/mod/devicetable-offsets.c b/scripts/mod/devicetable-offsets.c
new file mode 100644
index 0000000..ee482c3
--- /dev/null
+++ b/scripts/mod/devicetable-offsets.c
@@ -0,0 +1,171 @@
+#include <linux/kbuild.h>
+#include <linux/mod_devicetable.h>
+
+#define DEVID(devid) DEFINE(SIZE_##devid, sizeof(struct devid))
+#define DEVID_FIELD(devid, field) \
+	DEFINE(OFF_##devid##_##field, offsetof(struct devid, field))
+
+int main(void)
+{
+	DEVID(usb_device_id);
+	DEVID_FIELD(usb_device_id, match_flags);
+	DEVID_FIELD(usb_device_id, idVendor);
+	DEVID_FIELD(usb_device_id, idProduct);
+	DEVID_FIELD(usb_device_id, bcdDevice_lo);
+	DEVID_FIELD(usb_device_id, bcdDevice_hi);
+	DEVID_FIELD(usb_device_id, bDeviceClass);
+	DEVID_FIELD(usb_device_id, bDeviceSubClass);
+	DEVID_FIELD(usb_device_id, bDeviceProtocol);
+	DEVID_FIELD(usb_device_id, bInterfaceClass);
+	DEVID_FIELD(usb_device_id, bInterfaceSubClass);
+	DEVID_FIELD(usb_device_id, bInterfaceProtocol);
+
+	DEVID(hid_device_id);
+	DEVID_FIELD(hid_device_id, bus);
+	DEVID_FIELD(hid_device_id, vendor);
+	DEVID_FIELD(hid_device_id, product);
+
+	DEVID(ieee1394_device_id);
+	DEVID_FIELD(ieee1394_device_id, match_flags);
+	DEVID_FIELD(ieee1394_device_id, vendor_id);
+	DEVID_FIELD(ieee1394_device_id, model_id);
+	DEVID_FIELD(ieee1394_device_id, specifier_id);
+	DEVID_FIELD(ieee1394_device_id, version);
+
+	DEVID(pci_device_id);
+	DEVID_FIELD(pci_device_id, vendor);
+	DEVID_FIELD(pci_device_id, device);
+	DEVID_FIELD(pci_device_id, subvendor);
+	DEVID_FIELD(pci_device_id, subdevice);
+	DEVID_FIELD(pci_device_id, class);
+	DEVID_FIELD(pci_device_id, class_mask);
+
+	DEVID(ccw_device_id);
+	DEVID_FIELD(ccw_device_id, match_flags);
+	DEVID_FIELD(ccw_device_id, cu_type);
+	DEVID_FIELD(ccw_device_id, cu_model);
+	DEVID_FIELD(ccw_device_id, dev_type);
+	DEVID_FIELD(ccw_device_id, dev_model);
+
+	DEVID(ap_device_id);
+	DEVID_FIELD(ap_device_id, dev_type);
+
+	DEVID(css_device_id);
+	DEVID_FIELD(css_device_id, type);
+
+	DEVID(serio_device_id);
+	DEVID_FIELD(serio_device_id, type);
+	DEVID_FIELD(serio_device_id, proto);
+	DEVID_FIELD(serio_device_id, id);
+	DEVID_FIELD(serio_device_id, extra);
+
+	DEVID(acpi_device_id);
+	DEVID_FIELD(acpi_device_id, id);
+
+	DEVID(pnp_device_id);
+	DEVID_FIELD(pnp_device_id, id);
+
+	DEVID(pnp_card_device_id);
+	DEVID_FIELD(pnp_card_device_id, devs);
+
+	DEVID(pcmcia_device_id);
+	DEVID_FIELD(pcmcia_device_id, match_flags);
+	DEVID_FIELD(pcmcia_device_id, manf_id);
+	DEVID_FIELD(pcmcia_device_id, card_id);
+	DEVID_FIELD(pcmcia_device_id, func_id);
+	DEVID_FIELD(pcmcia_device_id, function);
+	DEVID_FIELD(pcmcia_device_id, device_no);
+	DEVID_FIELD(pcmcia_device_id, prod_id_hash);
+
+	DEVID(of_device_id);
+	DEVID_FIELD(of_device_id, name);
+	DEVID_FIELD(of_device_id, type);
+	DEVID_FIELD(of_device_id, compatible);
+
+	DEVID(vio_device_id);
+	DEVID_FIELD(vio_device_id, type);
+	DEVID_FIELD(vio_device_id, compat);
+
+	DEVID(input_device_id);
+	DEVID_FIELD(input_device_id, flags);
+	DEVID_FIELD(input_device_id, bustype);
+	DEVID_FIELD(input_device_id, vendor);
+	DEVID_FIELD(input_device_id, product);
+	DEVID_FIELD(input_device_id, version);
+	DEVID_FIELD(input_device_id, evbit);
+	DEVID_FIELD(input_device_id, keybit);
+	DEVID_FIELD(input_device_id, relbit);
+	DEVID_FIELD(input_device_id, absbit);
+	DEVID_FIELD(input_device_id, mscbit);
+	DEVID_FIELD(input_device_id, ledbit);
+	DEVID_FIELD(input_device_id, sndbit);
+	DEVID_FIELD(input_device_id, ffbit);
+	DEVID_FIELD(input_device_id, swbit);
+
+	DEVID(eisa_device_id);
+	DEVID_FIELD(eisa_device_id, sig);
+
+	DEVID(parisc_device_id);
+	DEVID_FIELD(parisc_device_id, hw_type);
+	DEVID_FIELD(parisc_device_id, hversion);
+	DEVID_FIELD(parisc_device_id, hversion_rev);
+	DEVID_FIELD(parisc_device_id, sversion);
+
+	DEVID(sdio_device_id);
+	DEVID_FIELD(sdio_device_id, class);
+	DEVID_FIELD(sdio_device_id, vendor);
+	DEVID_FIELD(sdio_device_id, device);
+
+	DEVID(ssb_device_id);
+	DEVID_FIELD(ssb_device_id, vendor);
+	DEVID_FIELD(ssb_device_id, coreid);
+	DEVID_FIELD(ssb_device_id, revision);
+
+	DEVID(bcma_device_id);
+	DEVID_FIELD(bcma_device_id, manuf);
+	DEVID_FIELD(bcma_device_id, id);
+	DEVID_FIELD(bcma_device_id, rev);
+	DEVID_FIELD(bcma_device_id, class);
+
+	DEVID(virtio_device_id);
+	DEVID_FIELD(virtio_device_id, device);
+	DEVID_FIELD(virtio_device_id, vendor);
+
+	DEVID(hv_vmbus_device_id);
+	DEVID_FIELD(hv_vmbus_device_id, guid);
+
+	DEVID(i2c_device_id);
+	DEVID_FIELD(i2c_device_id, name);
+
+	DEVID(spi_device_id);
+	DEVID_FIELD(spi_device_id, name);
+
+	DEVID(dmi_system_id);
+	DEVID_FIELD(dmi_system_id, matches);
+
+	DEVID(platform_device_id);
+	DEVID_FIELD(platform_device_id, name);
+
+	DEVID(mdio_device_id);
+	DEVID_FIELD(mdio_device_id, phy_id);
+	DEVID_FIELD(mdio_device_id, phy_id_mask);
+
+	DEVID(zorro_device_id);
+	DEVID_FIELD(zorro_device_id, id);
+
+	DEVID(isapnp_device_id);
+	DEVID_FIELD(isapnp_device_id, vendor);
+	DEVID_FIELD(isapnp_device_id, function);
+
+	DEVID(amba_id);
+	DEVID_FIELD(amba_id, id);
+	DEVID_FIELD(amba_id, mask);
+
+	DEVID(x86_cpu_id);
+	DEVID_FIELD(x86_cpu_id, feature);
+	DEVID_FIELD(x86_cpu_id, family);
+	DEVID_FIELD(x86_cpu_id, model);
+	DEVID_FIELD(x86_cpu_id, vendor);
+
+	return 0;
+}
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 44ddaa5..d23b325 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -11,6 +11,7 @@
  */
 
 #include "modpost.h"
+#include "devicetable-offsets.h"
 
 /* We use the ELF typedefs for kernel_ulong_t but bite the bullet and
  * use either stdint.h or inttypes.h for the rest. */
@@ -84,13 +85,25 @@ extern struct devtable *__start___devtable[], *__stop___devtable[];
 # define __used			__attribute__((__used__))
 #endif
 
+/* Define a variable f that holds the value of field f of struct devid
+ * based at address m.
+ */
+#define DEF_FIELD(m, devid, f) \
+	typeof(((struct devid *)0)->f) f = TO_NATIVE(*(typeof(f) *)((m) + OFF_##devid##_##f))
+/* Define a variable f that holds the address of field f of struct devid
+ * based at address m.  Due to the way typeof works, for a field of type
+ * T[N] the variable has type T(*)[N], _not_ T*.
+ */
+#define DEF_FIELD_ADDR(m, devid, f) \
+	typeof(((struct devid *)0)->f) *f = ((m) + OFF_##devid##_##f)
+
 /* Add a table entry.  We test function type matches while we're here. */
 #define ADD_TO_DEVTABLE(device_id, type, function) \
 	static struct devtable __cat(devtable,__LINE__) = {	\
 		device_id + 0*sizeof((function)((const char *)NULL,	\
-						(type *)NULL,		\
+						(void *)NULL,		\
 						(char *)NULL)),		\
-		sizeof(type), (function) };				\
+		SIZE_##type, (function) };				\
 	static struct devtable *SECTION(__devtable) __used \
 		__cat(devtable_ptr,__LINE__) = &__cat(devtable,__LINE__)
 
@@ -116,7 +129,6 @@ static inline void add_wildcard(char *str)
 		strcat(str + len, "*");
 }
 
-unsigned int cross_build = 0;
 /**
  * Check that sizeof(device_id type) are consistent with size of section
  * in .o file. If in-consistent then userspace and kernel does not agree
@@ -131,8 +143,6 @@ static void device_id_check(const char *modname, const char *device_id,
 	int i;
 
 	if (size % id_size || size < id_size) {
-		if (cross_build != 0)
-			return;
 		fatal("%s: sizeof(struct %s_device_id)=%lu is not a modulo "
 		      "of the size of section __mod_%s_device_table=%lu.\n"
 		      "Fix definition of struct %s_device_id "
@@ -157,17 +167,28 @@ static void device_id_check(const char *modname, const char *device_id,
 
 /* USB is special because the bcdDevice can be matched against a numeric range */
 /* Looks like "usb:vNpNdNdcNdscNdpNicNiscNipN" */
-static void do_usb_entry(struct usb_device_id *id,
+static void do_usb_entry(void *symval,
 			 unsigned int bcdDevice_initial, int bcdDevice_initial_digits,
 			 unsigned char range_lo, unsigned char range_hi,
 			 unsigned char max, struct module *mod)
 {
 	char alias[500];
+	DEF_FIELD(symval, usb_device_id, match_flags);
+	DEF_FIELD(symval, usb_device_id, idVendor);
+	DEF_FIELD(symval, usb_device_id, idProduct);
+	DEF_FIELD(symval, usb_device_id, bcdDevice_lo);
+	DEF_FIELD(symval, usb_device_id, bDeviceClass);
+	DEF_FIELD(symval, usb_device_id, bDeviceSubClass);
+	DEF_FIELD(symval, usb_device_id, bDeviceProtocol);
+	DEF_FIELD(symval, usb_device_id, bInterfaceClass);
+	DEF_FIELD(symval, usb_device_id, bInterfaceSubClass);
+	DEF_FIELD(symval, usb_device_id, bInterfaceProtocol);
+
 	strcpy(alias, "usb:");
-	ADD(alias, "v", id->match_flags&USB_DEVICE_ID_MATCH_VENDOR,
-	    id->idVendor);
-	ADD(alias, "p", id->match_flags&USB_DEVICE_ID_MATCH_PRODUCT,
-	    id->idProduct);
+	ADD(alias, "v", match_flags&USB_DEVICE_ID_MATCH_VENDOR,
+	    idVendor);
+	ADD(alias, "p", match_flags&USB_DEVICE_ID_MATCH_PRODUCT,
+	    idProduct);
 
 	strcat(alias, "d");
 	if (bcdDevice_initial_digits)
@@ -190,26 +211,21 @@ static void do_usb_entry(struct usb_device_id *id,
 				range_lo);
 		}
 	}
-	if (bcdDevice_initial_digits < (sizeof(id->bcdDevice_lo) * 2 - 1))
+	if (bcdDevice_initial_digits < (sizeof(bcdDevice_lo) * 2 - 1))
 		strcat(alias, "*");
 
-	ADD(alias, "dc", id->match_flags&USB_DEVICE_ID_MATCH_DEV_CLASS,
-	    id->bDeviceClass);
-	ADD(alias, "dsc",
-	    id->match_flags&USB_DEVICE_ID_MATCH_DEV_SUBCLASS,
-	    id->bDeviceSubClass);
-	ADD(alias, "dp",
-	    id->match_flags&USB_DEVICE_ID_MATCH_DEV_PROTOCOL,
-	    id->bDeviceProtocol);
-	ADD(alias, "ic",
-	    id->match_flags&USB_DEVICE_ID_MATCH_INT_CLASS,
-	    id->bInterfaceClass);
-	ADD(alias, "isc",
-	    id->match_flags&USB_DEVICE_ID_MATCH_INT_SUBCLASS,
-	    id->bInterfaceSubClass);
-	ADD(alias, "ip",
-	    id->match_flags&USB_DEVICE_ID_MATCH_INT_PROTOCOL,
-	    id->bInterfaceProtocol);
+	ADD(alias, "dc", match_flags&USB_DEVICE_ID_MATCH_DEV_CLASS,
+	    bDeviceClass);
+	ADD(alias, "dsc", match_flags&USB_DEVICE_ID_MATCH_DEV_SUBCLASS,
+	    bDeviceSubClass);
+	ADD(alias, "dp", match_flags&USB_DEVICE_ID_MATCH_DEV_PROTOCOL,
+	    bDeviceProtocol);
+	ADD(alias, "ic", match_flags&USB_DEVICE_ID_MATCH_INT_CLASS,
+	    bInterfaceClass);
+	ADD(alias, "isc", match_flags&USB_DEVICE_ID_MATCH_INT_SUBCLASS,
+	    bInterfaceSubClass);
+	ADD(alias, "ip", match_flags&USB_DEVICE_ID_MATCH_INT_PROTOCOL,
+	    bInterfaceProtocol);
 
 	add_wildcard(alias);
 	buf_printf(&mod->dev_table_buf,
@@ -255,24 +271,28 @@ static unsigned int incbcd(unsigned int *bcd,
 	return init;
 }
 
-static void do_usb_entry_multi(struct usb_device_id *id, struct module *mod)
+static void do_usb_entry_multi(void *symval, struct module *mod)
 {
 	unsigned int devlo, devhi;
 	unsigned char chi, clo, max;
 	int ndigits;
 
-	id->match_flags = TO_NATIVE(id->match_flags);
-	id->idVendor = TO_NATIVE(id->idVendor);
-	id->idProduct = TO_NATIVE(id->idProduct);
+	DEF_FIELD(symval, usb_device_id, match_flags);
+	DEF_FIELD(symval, usb_device_id, idVendor);
+	DEF_FIELD(symval, usb_device_id, idProduct);
+	DEF_FIELD(symval, usb_device_id, bcdDevice_lo);
+	DEF_FIELD(symval, usb_device_id, bcdDevice_hi);
+	DEF_FIELD(symval, usb_device_id, bDeviceClass);
+	DEF_FIELD(symval, usb_device_id, bInterfaceClass);
 
-	devlo = id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO ?
-		TO_NATIVE(id->bcdDevice_lo) : 0x0U;
-	devhi = id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI ?
-		TO_NATIVE(id->bcdDevice_hi) : ~0x0U;
+	devlo = match_flags & USB_DEVICE_ID_MATCH_DEV_LO ?
+		bcdDevice_lo : 0x0U;
+	devhi = match_flags & USB_DEVICE_ID_MATCH_DEV_HI ?
+		bcdDevice_hi : ~0x0U;
 
 	/* Figure out if this entry is in bcd or hex format */
 	max = 0x9; /* Default to decimal format */
-	for (ndigits = 0 ; ndigits < sizeof(id->bcdDevice_lo) * 2 ; ndigits++) {
+	for (ndigits = 0 ; ndigits < sizeof(bcdDevice_lo) * 2 ; ndigits++) {
 		clo = (devlo >> (ndigits << 2)) & 0xf;
 		chi = ((devhi > 0x9999 ? 0x9999 : devhi) >> (ndigits << 2)) & 0xf;
 		if (clo > max || chi > max) {
@@ -285,11 +305,11 @@ static void do_usb_entry_multi(struct usb_device_id *id, struct module *mod)
 	 * Some modules (visor) have empty slots as placeholder for
 	 * run-time specification that results in catch-all alias
 	 */
-	if (!(id->idVendor | id->idProduct | id->bDeviceClass | id->bInterfaceClass))
+	if (!(idVendor | idProduct | bDeviceClass | bInterfaceClass))
 		return;
 
 	/* Convert numeric bcdDevice range into fnmatch-able pattern(s) */
-	for (ndigits = sizeof(id->bcdDevice_lo) * 2 - 1; devlo <= devhi; ndigits--) {
+	for (ndigits = sizeof(bcdDevice_lo) * 2 - 1; devlo <= devhi; ndigits--) {
 		clo = devlo & 0xf;
 		chi = devhi & 0xf;
 		if (chi > max)	/* If we are in bcd mode, truncate if necessary */
@@ -298,20 +318,20 @@ static void do_usb_entry_multi(struct usb_device_id *id, struct module *mod)
 		devhi >>= 4;
 
 		if (devlo == devhi || !ndigits) {
-			do_usb_entry(id, devlo, ndigits, clo, chi, max, mod);
+			do_usb_entry(symval, devlo, ndigits, clo, chi, max, mod);
 			break;
 		}
 
 		if (clo > 0x0)
-			do_usb_entry(id,
+			do_usb_entry(symval,
 				     incbcd(&devlo, 1, max,
-					    sizeof(id->bcdDevice_lo) * 2),
+					    sizeof(bcdDevice_lo) * 2),
 				     ndigits, clo, max, max, mod);
 
 		if (chi < max)
-			do_usb_entry(id,
+			do_usb_entry(symval,
 				     incbcd(&devhi, -1, max,
-					    sizeof(id->bcdDevice_lo) * 2),
+					    sizeof(bcdDevice_lo) * 2),
 				     ndigits, 0x0, chi, max, mod);
 	}
 }
@@ -320,7 +340,7 @@ static void do_usb_table(void *symval, unsigned long size,
 			 struct module *mod)
 {
 	unsigned int i;
-	const unsigned long id_size = sizeof(struct usb_device_id);
+	const unsigned long id_size = SIZE_usb_device_id;
 
 	device_id_check(mod->name, "usb", size, id_size, symval);
 
@@ -333,78 +353,78 @@ static void do_usb_table(void *symval, unsigned long size,
 
 /* Looks like: hid:bNvNpN */
 static int do_hid_entry(const char *filename,
-			     struct hid_device_id *id, char *alias)
+			     void *symval, char *alias)
 {
-	id->bus = TO_NATIVE(id->bus);
-	id->vendor = TO_NATIVE(id->vendor);
-	id->product = TO_NATIVE(id->product);
+	DEF_FIELD(symval, hid_device_id, bus);
+	DEF_FIELD(symval, hid_device_id, vendor);
+	DEF_FIELD(symval, hid_device_id, product);
 
-	sprintf(alias, "hid:b%04X", id->bus);
-	ADD(alias, "v", id->vendor != HID_ANY_ID, id->vendor);
-	ADD(alias, "p", id->product != HID_ANY_ID, id->product);
+	sprintf(alias, "hid:b%04X", bus);
+	ADD(alias, "v", vendor != HID_ANY_ID, vendor);
+	ADD(alias, "p", product != HID_ANY_ID, product);
 
 	return 1;
 }
-ADD_TO_DEVTABLE("hid", struct hid_device_id, do_hid_entry);
+ADD_TO_DEVTABLE("hid", hid_device_id, do_hid_entry);
 
 /* Looks like: ieee1394:venNmoNspNverN */
 static int do_ieee1394_entry(const char *filename,
-			     struct ieee1394_device_id *id, char *alias)
+			     void *symval, char *alias)
 {
-	id->match_flags = TO_NATIVE(id->match_flags);
-	id->vendor_id = TO_NATIVE(id->vendor_id);
-	id->model_id = TO_NATIVE(id->model_id);
-	id->specifier_id = TO_NATIVE(id->specifier_id);
-	id->version = TO_NATIVE(id->version);
+	DEF_FIELD(symval, ieee1394_device_id, match_flags);
+	DEF_FIELD(symval, ieee1394_device_id, vendor_id);
+	DEF_FIELD(symval, ieee1394_device_id, model_id);
+	DEF_FIELD(symval, ieee1394_device_id, specifier_id);
+	DEF_FIELD(symval, ieee1394_device_id, version);
 
 	strcpy(alias, "ieee1394:");
-	ADD(alias, "ven", id->match_flags & IEEE1394_MATCH_VENDOR_ID,
-	    id->vendor_id);
-	ADD(alias, "mo", id->match_flags & IEEE1394_MATCH_MODEL_ID,
-	    id->model_id);
-	ADD(alias, "sp", id->match_flags & IEEE1394_MATCH_SPECIFIER_ID,
-	    id->specifier_id);
-	ADD(alias, "ver", id->match_flags & IEEE1394_MATCH_VERSION,
-	    id->version);
+	ADD(alias, "ven", match_flags & IEEE1394_MATCH_VENDOR_ID,
+	    vendor_id);
+	ADD(alias, "mo", match_flags & IEEE1394_MATCH_MODEL_ID,
+	    model_id);
+	ADD(alias, "sp", match_flags & IEEE1394_MATCH_SPECIFIER_ID,
+	    specifier_id);
+	ADD(alias, "ver", match_flags & IEEE1394_MATCH_VERSION,
+	    version);
 
 	add_wildcard(alias);
 	return 1;
 }
-ADD_TO_DEVTABLE("ieee1394", struct ieee1394_device_id, do_ieee1394_entry);
+ADD_TO_DEVTABLE("ieee1394", ieee1394_device_id, do_ieee1394_entry);
 
 /* Looks like: pci:vNdNsvNsdNbcNscNiN. */
 static int do_pci_entry(const char *filename,
-			struct pci_device_id *id, char *alias)
+			void *symval, char *alias)
 {
 	/* Class field can be divided into these three. */
 	unsigned char baseclass, subclass, interface,
 		baseclass_mask, subclass_mask, interface_mask;
 
-	id->vendor = TO_NATIVE(id->vendor);
-	id->device = TO_NATIVE(id->device);
-	id->subvendor = TO_NATIVE(id->subvendor);
-	id->subdevice = TO_NATIVE(id->subdevice);
-	id->class = TO_NATIVE(id->class);
-	id->class_mask = TO_NATIVE(id->class_mask);
+	DEF_FIELD(symval, pci_device_id, vendor);
+	DEF_FIELD(symval, pci_device_id, device);
+	DEF_FIELD(symval, pci_device_id, subvendor);
+	DEF_FIELD(symval, pci_device_id, subdevice);
+	DEF_FIELD(symval, pci_device_id, class);
+	DEF_FIELD(symval, pci_device_id, class_mask);
 
 	strcpy(alias, "pci:");
-	ADD(alias, "v", id->vendor != PCI_ANY_ID, id->vendor);
-	ADD(alias, "d", id->device != PCI_ANY_ID, id->device);
-	ADD(alias, "sv", id->subvendor != PCI_ANY_ID, id->subvendor);
-	ADD(alias, "sd", id->subdevice != PCI_ANY_ID, id->subdevice);
-
-	baseclass = (id->class) >> 16;
-	baseclass_mask = (id->class_mask) >> 16;
-	subclass = (id->class) >> 8;
-	subclass_mask = (id->class_mask) >> 8;
-	interface = id->class;
-	interface_mask = id->class_mask;
+	ADD(alias, "v", vendor != PCI_ANY_ID, vendor);
+	ADD(alias, "d", device != PCI_ANY_ID, device);
+	ADD(alias, "sv", subvendor != PCI_ANY_ID, subvendor);
+	ADD(alias, "sd", subdevice != PCI_ANY_ID, subdevice);
+
+	baseclass = (class) >> 16;
+	baseclass_mask = (class_mask) >> 16;
+	subclass = (class) >> 8;
+	subclass_mask = (class_mask) >> 8;
+	interface = class;
+	interface_mask = class_mask;
 
 	if ((baseclass_mask != 0 && baseclass_mask != 0xFF)
 	    || (subclass_mask != 0 && subclass_mask != 0xFF)
 	    || (interface_mask != 0 && interface_mask != 0xFF)) {
 		warn("Can't handle masks in %s:%04X\n",
-		     filename, id->class_mask);
+		     filename, class_mask);
 		return 0;
 	}
 
@@ -414,101 +434,105 @@ static int do_pci_entry(const char *filename,
 	add_wildcard(alias);
 	return 1;
 }
-ADD_TO_DEVTABLE("pci", struct pci_device_id, do_pci_entry);
+ADD_TO_DEVTABLE("pci", pci_device_id, do_pci_entry);
 
 /* looks like: "ccw:tNmNdtNdmN" */
 static int do_ccw_entry(const char *filename,
-			struct ccw_device_id *id, char *alias)
+			void *symval, char *alias)
 {
-	id->match_flags = TO_NATIVE(id->match_flags);
-	id->cu_type = TO_NATIVE(id->cu_type);
-	id->cu_model = TO_NATIVE(id->cu_model);
-	id->dev_type = TO_NATIVE(id->dev_type);
-	id->dev_model = TO_NATIVE(id->dev_model);
+	DEF_FIELD(symval, ccw_device_id, match_flags);
+	DEF_FIELD(symval, ccw_device_id, cu_type);
+	DEF_FIELD(symval, ccw_device_id, cu_model);
+	DEF_FIELD(symval, ccw_device_id, dev_type);
+	DEF_FIELD(symval, ccw_device_id, dev_model);
 
 	strcpy(alias, "ccw:");
-	ADD(alias, "t", id->match_flags&CCW_DEVICE_ID_MATCH_CU_TYPE,
-	    id->cu_type);
-	ADD(alias, "m", id->match_flags&CCW_DEVICE_ID_MATCH_CU_MODEL,
-	    id->cu_model);
-	ADD(alias, "dt", id->match_flags&CCW_DEVICE_ID_MATCH_DEVICE_TYPE,
-	    id->dev_type);
-	ADD(alias, "dm", id->match_flags&CCW_DEVICE_ID_MATCH_DEVICE_MODEL,
-	    id->dev_model);
+	ADD(alias, "t", match_flags&CCW_DEVICE_ID_MATCH_CU_TYPE,
+	    cu_type);
+	ADD(alias, "m", match_flags&CCW_DEVICE_ID_MATCH_CU_MODEL,
+	    cu_model);
+	ADD(alias, "dt", match_flags&CCW_DEVICE_ID_MATCH_DEVICE_TYPE,
+	    dev_type);
+	ADD(alias, "dm", match_flags&CCW_DEVICE_ID_MATCH_DEVICE_MODEL,
+	    dev_model);
 	add_wildcard(alias);
 	return 1;
 }
-ADD_TO_DEVTABLE("ccw", struct ccw_device_id, do_ccw_entry);
+ADD_TO_DEVTABLE("ccw", ccw_device_id, do_ccw_entry);
 
 /* looks like: "ap:tN" */
 static int do_ap_entry(const char *filename,
-		       struct ap_device_id *id, char *alias)
+		       void *symval, char *alias)
 {
-	sprintf(alias, "ap:t%02X*", id->dev_type);
+	DEF_FIELD(symval, ap_device_id, dev_type);
+
+	sprintf(alias, "ap:t%02X*", dev_type);
 	return 1;
 }
-ADD_TO_DEVTABLE("ap", struct ap_device_id, do_ap_entry);
+ADD_TO_DEVTABLE("ap", ap_device_id, do_ap_entry);
 
 /* looks like: "css:tN" */
 static int do_css_entry(const char *filename,
-			struct css_device_id *id, char *alias)
+			void *symval, char *alias)
 {
-	sprintf(alias, "css:t%01X", id->type);
+	DEF_FIELD(symval, css_device_id, type);
+
+	sprintf(alias, "css:t%01X", type);
 	return 1;
 }
-ADD_TO_DEVTABLE("css", struct css_device_id, do_css_entry);
+ADD_TO_DEVTABLE("css", css_device_id, do_css_entry);
 
 /* Looks like: "serio:tyNprNidNexN" */
 static int do_serio_entry(const char *filename,
-			  struct serio_device_id *id, char *alias)
+			  void *symval, char *alias)
 {
-	id->type = TO_NATIVE(id->type);
-	id->proto = TO_NATIVE(id->proto);
-	id->id = TO_NATIVE(id->id);
-	id->extra = TO_NATIVE(id->extra);
+	DEF_FIELD(symval, serio_device_id, type);
+	DEF_FIELD(symval, serio_device_id, proto);
+	DEF_FIELD(symval, serio_device_id, id);
+	DEF_FIELD(symval, serio_device_id, extra);
 
 	strcpy(alias, "serio:");
-	ADD(alias, "ty", id->type != SERIO_ANY, id->type);
-	ADD(alias, "pr", id->proto != SERIO_ANY, id->proto);
-	ADD(alias, "id", id->id != SERIO_ANY, id->id);
-	ADD(alias, "ex", id->extra != SERIO_ANY, id->extra);
+	ADD(alias, "ty", type != SERIO_ANY, type);
+	ADD(alias, "pr", proto != SERIO_ANY, proto);
+	ADD(alias, "id", id != SERIO_ANY, id);
+	ADD(alias, "ex", extra != SERIO_ANY, extra);
 
 	add_wildcard(alias);
 	return 1;
 }
-ADD_TO_DEVTABLE("serio", struct serio_device_id, do_serio_entry);
+ADD_TO_DEVTABLE("serio", serio_device_id, do_serio_entry);
 
 /* looks like: "acpi:ACPI0003 or acpi:PNP0C0B" or "acpi:LNXVIDEO" */
 static int do_acpi_entry(const char *filename,
-			struct acpi_device_id *id, char *alias)
+			void *symval, char *alias)
 {
-	sprintf(alias, "acpi*:%s:*", id->id);
+	DEF_FIELD_ADDR(symval, acpi_device_id, id);
+	sprintf(alias, "acpi*:%s:*", *id);
 	return 1;
 }
-ADD_TO_DEVTABLE("acpi", struct acpi_device_id, do_acpi_entry);
+ADD_TO_DEVTABLE("acpi", acpi_device_id, do_acpi_entry);
 
 /* looks like: "pnp:dD" */
 static void do_pnp_device_entry(void *symval, unsigned long size,
 				struct module *mod)
 {
-	const unsigned long id_size = sizeof(struct pnp_device_id);
+	const unsigned long id_size = SIZE_pnp_device_id;
 	const unsigned int count = (size / id_size)-1;
-	const struct pnp_device_id *devs = symval;
 	unsigned int i;
 
 	device_id_check(mod->name, "pnp", size, id_size, symval);
 
 	for (i = 0; i < count; i++) {
-		const char *id = (char *)devs[i].id;
-		char acpi_id[sizeof(devs[0].id)];
+		DEF_FIELD_ADDR(symval + i*id_size, pnp_device_id, id);
+		char acpi_id[sizeof(*id)];
 		int j;
 
 		buf_printf(&mod->dev_table_buf,
-			   "MODULE_ALIAS(\"pnp:d%s*\");\n", id);
+			   "MODULE_ALIAS(\"pnp:d%s*\");\n", *id);
 
 		/* fix broken pnp bus lowercasing */
 		for (j = 0; j < sizeof(acpi_id); j++)
-			acpi_id[j] = toupper(id[j]);
+			acpi_id[j] = toupper((*id)[j]);
 		buf_printf(&mod->dev_table_buf,
 			   "MODULE_ALIAS(\"acpi*:%s:*\");\n", acpi_id);
 	}
@@ -518,19 +542,18 @@ static void do_pnp_device_entry(void *symval, unsigned long size,
 static void do_pnp_card_entries(void *symval, unsigned long size,
 				struct module *mod)
 {
-	const unsigned long id_size = sizeof(struct pnp_card_device_id);
+	const unsigned long id_size = SIZE_pnp_card_device_id;
 	const unsigned int count = (size / id_size)-1;
-	const struct pnp_card_device_id *cards = symval;
 	unsigned int i;
 
 	device_id_check(mod->name, "pnp", size, id_size, symval);
 
 	for (i = 0; i < count; i++) {
 		unsigned int j;
-		const struct pnp_card_device_id *card = &cards[i];
+		DEF_FIELD_ADDR(symval + i*id_size, pnp_card_device_id, devs);
 
 		for (j = 0; j < PNP_MAX_DEVICES; j++) {
-			const char *id = (char *)card->devs[j].id;
+			const char *id = (char *)(*devs)[j].id;
 			int i2, j2;
 			int dup = 0;
 
@@ -539,10 +562,10 @@ static void do_pnp_card_entries(void *symval, unsigned long size,
 
 			/* find duplicate, already added value */
 			for (i2 = 0; i2 < i && !dup; i2++) {
-				const struct pnp_card_device_id *card2 = &cards[i2];
+				DEF_FIELD_ADDR(symval + i2*id_size, pnp_card_device_id, devs);
 
 				for (j2 = 0; j2 < PNP_MAX_DEVICES; j2++) {
-					const char *id2 = (char *)card2->devs[j2].id;
+					const char *id2 = (char *)(*devs)[j2].id;
 
 					if (!id2[0])
 						break;
@@ -556,7 +579,7 @@ static void do_pnp_card_entries(void *symval, unsigned long size,
 
 			/* add an individual alias for every device entry */
 			if (!dup) {
-				char acpi_id[sizeof(card->devs[0].id)];
+				char acpi_id[PNP_ID_LEN];
 				int k;
 
 				buf_printf(&mod->dev_table_buf,
@@ -574,54 +597,58 @@ static void do_pnp_card_entries(void *symval, unsigned long size,
 
 /* Looks like: pcmcia:mNcNfNfnNpfnNvaNvbNvcNvdN. */
 static int do_pcmcia_entry(const char *filename,
-			   struct pcmcia_device_id *id, char *alias)
+			   void *symval, char *alias)
 {
 	unsigned int i;
-
-	id->match_flags = TO_NATIVE(id->match_flags);
-	id->manf_id = TO_NATIVE(id->manf_id);
-	id->card_id = TO_NATIVE(id->card_id);
-	id->func_id = TO_NATIVE(id->func_id);
-	id->function = TO_NATIVE(id->function);
-	id->device_no = TO_NATIVE(id->device_no);
+	DEF_FIELD(symval, pcmcia_device_id, match_flags);
+	DEF_FIELD(symval, pcmcia_device_id, manf_id);
+	DEF_FIELD(symval, pcmcia_device_id, card_id);
+	DEF_FIELD(symval, pcmcia_device_id, func_id);
+	DEF_FIELD(symval, pcmcia_device_id, function);
+	DEF_FIELD(symval, pcmcia_device_id, device_no);
+	DEF_FIELD_ADDR(symval, pcmcia_device_id, prod_id_hash);
 
 	for (i=0; i<4; i++) {
-		id->prod_id_hash[i] = TO_NATIVE(id->prod_id_hash[i]);
-       }
-
-       strcpy(alias, "pcmcia:");
-       ADD(alias, "m", id->match_flags & PCMCIA_DEV_ID_MATCH_MANF_ID,
-	   id->manf_id);
-       ADD(alias, "c", id->match_flags & PCMCIA_DEV_ID_MATCH_CARD_ID,
-	   id->card_id);
-       ADD(alias, "f", id->match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID,
-	   id->func_id);
-       ADD(alias, "fn", id->match_flags & PCMCIA_DEV_ID_MATCH_FUNCTION,
-	   id->function);
-       ADD(alias, "pfn", id->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO,
-	   id->device_no);
-       ADD(alias, "pa", id->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID1, id->prod_id_hash[0]);
-       ADD(alias, "pb", id->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID2, id->prod_id_hash[1]);
-       ADD(alias, "pc", id->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID3, id->prod_id_hash[2]);
-       ADD(alias, "pd", id->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID4, id->prod_id_hash[3]);
+		(*prod_id_hash)[i] = TO_NATIVE((*prod_id_hash)[i]);
+	}
+
+	strcpy(alias, "pcmcia:");
+	ADD(alias, "m", match_flags & PCMCIA_DEV_ID_MATCH_MANF_ID,
+	    manf_id);
+	ADD(alias, "c", match_flags & PCMCIA_DEV_ID_MATCH_CARD_ID,
+	    card_id);
+	ADD(alias, "f", match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID,
+	    func_id);
+	ADD(alias, "fn", match_flags & PCMCIA_DEV_ID_MATCH_FUNCTION,
+	    function);
+	ADD(alias, "pfn", match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO,
+	    device_no);
+	ADD(alias, "pa", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID1, (*prod_id_hash)[0]);
+	ADD(alias, "pb", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID2, (*prod_id_hash)[1]);
+	ADD(alias, "pc", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID3, (*prod_id_hash)[2]);
+	ADD(alias, "pd", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID4, (*prod_id_hash)[3]);
 
 	add_wildcard(alias);
-       return 1;
+	return 1;
 }
-ADD_TO_DEVTABLE("pcmcia", struct pcmcia_device_id, do_pcmcia_entry);
+ADD_TO_DEVTABLE("pcmcia", pcmcia_device_id, do_pcmcia_entry);
 
-static int do_of_entry (const char *filename, struct of_device_id *of, char *alias)
+static int do_of_entry (const char *filename, void *symval, char *alias)
 {
     int len;
     char *tmp;
+    DEF_FIELD_ADDR(symval, of_device_id, name);
+    DEF_FIELD_ADDR(symval, of_device_id, type);
+    DEF_FIELD_ADDR(symval, of_device_id, compatible);
+
     len = sprintf (alias, "of:N%sT%s",
-                    of->name[0] ? of->name : "*",
-                    of->type[0] ? of->type : "*");
+                    (*name)[0] ? *name : "*",
+                    (*type)[0] ? *type : "*");
 
-    if (of->compatible[0])
+    if (compatible[0])
         sprintf (&alias[len], "%sC%s",
-                     of->type[0] ? "*" : "",
-                     of->compatible);
+                     (*type)[0] ? "*" : "",
+                     *compatible);
 
     /* Replace all whitespace with underscores */
     for (tmp = alias; tmp && *tmp; tmp++)
@@ -631,15 +658,17 @@ static int do_of_entry (const char *filename, struct of_device_id *of, char *ali
     add_wildcard(alias);
     return 1;
 }
-ADD_TO_DEVTABLE("of", struct of_device_id, do_of_entry);
+ADD_TO_DEVTABLE("of", of_device_id, do_of_entry);
 
-static int do_vio_entry(const char *filename, struct vio_device_id *vio,
+static int do_vio_entry(const char *filename, void *symval,
 		char *alias)
 {
 	char *tmp;
+	DEF_FIELD_ADDR(symval, vio_device_id, type);
+	DEF_FIELD_ADDR(symval, vio_device_id, compat);
 
-	sprintf(alias, "vio:T%sS%s", vio->type[0] ? vio->type : "*",
-			vio->compat[0] ? vio->compat : "*");
+	sprintf(alias, "vio:T%sS%s", (*type)[0] ? *type : "*",
+			(*compat)[0] ? *compat : "*");
 
 	/* Replace all whitespace with underscores */
 	for (tmp = alias; tmp && *tmp; tmp++)
@@ -649,7 +678,7 @@ static int do_vio_entry(const char *filename, struct vio_device_id *vio,
 	add_wildcard(alias);
 	return 1;
 }
-ADD_TO_DEVTABLE("vio", struct vio_device_id, do_vio_entry);
+ADD_TO_DEVTABLE("vio", vio_device_id, do_vio_entry);
 
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
 
@@ -658,154 +687,172 @@ static void do_input(char *alias,
 {
 	unsigned int i;
 
+	for (i = min / BITS_PER_LONG; i < max / BITS_PER_LONG + 1; i++)
+		arr[i] = TO_NATIVE(arr[i]);
 	for (i = min; i < max; i++)
 		if (arr[i / BITS_PER_LONG] & (1L << (i%BITS_PER_LONG)))
 			sprintf(alias + strlen(alias), "%X,*", i);
 }
 
 /* input:b0v0p0e0-eXkXrXaXmXlXsXfXwX where X is comma-separated %02X. */
-static int do_input_entry(const char *filename, struct input_device_id *id,
+static int do_input_entry(const char *filename, void *symval,
 			  char *alias)
 {
+	DEF_FIELD(symval, input_device_id, flags);
+	DEF_FIELD(symval, input_device_id, bustype);
+	DEF_FIELD(symval, input_device_id, vendor);
+	DEF_FIELD(symval, input_device_id, product);
+	DEF_FIELD(symval, input_device_id, version);
+	DEF_FIELD_ADDR(symval, input_device_id, evbit);
+	DEF_FIELD_ADDR(symval, input_device_id, keybit);
+	DEF_FIELD_ADDR(symval, input_device_id, relbit);
+	DEF_FIELD_ADDR(symval, input_device_id, absbit);
+	DEF_FIELD_ADDR(symval, input_device_id, mscbit);
+	DEF_FIELD_ADDR(symval, input_device_id, ledbit);
+	DEF_FIELD_ADDR(symval, input_device_id, sndbit);
+	DEF_FIELD_ADDR(symval, input_device_id, ffbit);
+	DEF_FIELD_ADDR(symval, input_device_id, swbit);
+
 	sprintf(alias, "input:");
 
-	ADD(alias, "b", id->flags & INPUT_DEVICE_ID_MATCH_BUS, id->bustype);
-	ADD(alias, "v", id->flags & INPUT_DEVICE_ID_MATCH_VENDOR, id->vendor);
-	ADD(alias, "p", id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT, id->product);
-	ADD(alias, "e", id->flags & INPUT_DEVICE_ID_MATCH_VERSION, id->version);
+	ADD(alias, "b", flags & INPUT_DEVICE_ID_MATCH_BUS, bustype);
+	ADD(alias, "v", flags & INPUT_DEVICE_ID_MATCH_VENDOR, vendor);
+	ADD(alias, "p", flags & INPUT_DEVICE_ID_MATCH_PRODUCT, product);
+	ADD(alias, "e", flags & INPUT_DEVICE_ID_MATCH_VERSION, version);
 
 	sprintf(alias + strlen(alias), "-e*");
-	if (id->flags & INPUT_DEVICE_ID_MATCH_EVBIT)
-		do_input(alias, id->evbit, 0, INPUT_DEVICE_ID_EV_MAX);
+	if (flags & INPUT_DEVICE_ID_MATCH_EVBIT)
+		do_input(alias, *evbit, 0, INPUT_DEVICE_ID_EV_MAX);
 	sprintf(alias + strlen(alias), "k*");
-	if (id->flags & INPUT_DEVICE_ID_MATCH_KEYBIT)
-		do_input(alias, id->keybit,
+	if (flags & INPUT_DEVICE_ID_MATCH_KEYBIT)
+		do_input(alias, *keybit,
 			 INPUT_DEVICE_ID_KEY_MIN_INTERESTING,
 			 INPUT_DEVICE_ID_KEY_MAX);
 	sprintf(alias + strlen(alias), "r*");
-	if (id->flags & INPUT_DEVICE_ID_MATCH_RELBIT)
-		do_input(alias, id->relbit, 0, INPUT_DEVICE_ID_REL_MAX);
+	if (flags & INPUT_DEVICE_ID_MATCH_RELBIT)
+		do_input(alias, *relbit, 0, INPUT_DEVICE_ID_REL_MAX);
 	sprintf(alias + strlen(alias), "a*");
-	if (id->flags & INPUT_DEVICE_ID_MATCH_ABSBIT)
-		do_input(alias, id->absbit, 0, INPUT_DEVICE_ID_ABS_MAX);
+	if (flags & INPUT_DEVICE_ID_MATCH_ABSBIT)
+		do_input(alias, *absbit, 0, INPUT_DEVICE_ID_ABS_MAX);
 	sprintf(alias + strlen(alias), "m*");
-	if (id->flags & INPUT_DEVICE_ID_MATCH_MSCIT)
-		do_input(alias, id->mscbit, 0, INPUT_DEVICE_ID_MSC_MAX);
+	if (flags & INPUT_DEVICE_ID_MATCH_MSCIT)
+		do_input(alias, *mscbit, 0, INPUT_DEVICE_ID_MSC_MAX);
 	sprintf(alias + strlen(alias), "l*");
-	if (id->flags & INPUT_DEVICE_ID_MATCH_LEDBIT)
-		do_input(alias, id->ledbit, 0, INPUT_DEVICE_ID_LED_MAX);
+	if (flags & INPUT_DEVICE_ID_MATCH_LEDBIT)
+		do_input(alias, *ledbit, 0, INPUT_DEVICE_ID_LED_MAX);
 	sprintf(alias + strlen(alias), "s*");
-	if (id->flags & INPUT_DEVICE_ID_MATCH_SNDBIT)
-		do_input(alias, id->sndbit, 0, INPUT_DEVICE_ID_SND_MAX);
+	if (flags & INPUT_DEVICE_ID_MATCH_SNDBIT)
+		do_input(alias, *sndbit, 0, INPUT_DEVICE_ID_SND_MAX);
 	sprintf(alias + strlen(alias), "f*");
-	if (id->flags & INPUT_DEVICE_ID_MATCH_FFBIT)
-		do_input(alias, id->ffbit, 0, INPUT_DEVICE_ID_FF_MAX);
+	if (flags & INPUT_DEVICE_ID_MATCH_FFBIT)
+		do_input(alias, *ffbit, 0, INPUT_DEVICE_ID_FF_MAX);
 	sprintf(alias + strlen(alias), "w*");
-	if (id->flags & INPUT_DEVICE_ID_MATCH_SWBIT)
-		do_input(alias, id->swbit, 0, INPUT_DEVICE_ID_SW_MAX);
+	if (flags & INPUT_DEVICE_ID_MATCH_SWBIT)
+		do_input(alias, *swbit, 0, INPUT_DEVICE_ID_SW_MAX);
 	return 1;
 }
-ADD_TO_DEVTABLE("input", struct input_device_id, do_input_entry);
+ADD_TO_DEVTABLE("input", input_device_id, do_input_entry);
 
-static int do_eisa_entry(const char *filename, struct eisa_device_id *eisa,
+static int do_eisa_entry(const char *filename, void *symval,
 		char *alias)
 {
-	if (eisa->sig[0])
-		sprintf(alias, EISA_DEVICE_MODALIAS_FMT "*", eisa->sig);
+	DEF_FIELD_ADDR(symval, eisa_device_id, sig);
+	if (sig[0])
+		sprintf(alias, EISA_DEVICE_MODALIAS_FMT "*", *sig);
 	else
 		strcat(alias, "*");
 	return 1;
 }
-ADD_TO_DEVTABLE("eisa", struct eisa_device_id, do_eisa_entry);
+ADD_TO_DEVTABLE("eisa", eisa_device_id, do_eisa_entry);
 
 /* Looks like: parisc:tNhvNrevNsvN */
-static int do_parisc_entry(const char *filename, struct parisc_device_id *id,
+static int do_parisc_entry(const char *filename, void *symval,
 		char *alias)
 {
-	id->hw_type = TO_NATIVE(id->hw_type);
-	id->hversion = TO_NATIVE(id->hversion);
-	id->hversion_rev = TO_NATIVE(id->hversion_rev);
-	id->sversion = TO_NATIVE(id->sversion);
+	DEF_FIELD(symval, parisc_device_id, hw_type);
+	DEF_FIELD(symval, parisc_device_id, hversion);
+	DEF_FIELD(symval, parisc_device_id, hversion_rev);
+	DEF_FIELD(symval, parisc_device_id, sversion);
 
 	strcpy(alias, "parisc:");
-	ADD(alias, "t", id->hw_type != PA_HWTYPE_ANY_ID, id->hw_type);
-	ADD(alias, "hv", id->hversion != PA_HVERSION_ANY_ID, id->hversion);
-	ADD(alias, "rev", id->hversion_rev != PA_HVERSION_REV_ANY_ID, id->hversion_rev);
-	ADD(alias, "sv", id->sversion != PA_SVERSION_ANY_ID, id->sversion);
+	ADD(alias, "t", hw_type != PA_HWTYPE_ANY_ID, hw_type);
+	ADD(alias, "hv", hversion != PA_HVERSION_ANY_ID, hversion);
+	ADD(alias, "rev", hversion_rev != PA_HVERSION_REV_ANY_ID, hversion_rev);
+	ADD(alias, "sv", sversion != PA_SVERSION_ANY_ID, sversion);
 
 	add_wildcard(alias);
 	return 1;
 }
-ADD_TO_DEVTABLE("parisc", struct parisc_device_id, do_parisc_entry);
+ADD_TO_DEVTABLE("parisc", parisc_device_id, do_parisc_entry);
 
 /* Looks like: sdio:cNvNdN. */
 static int do_sdio_entry(const char *filename,
-			struct sdio_device_id *id, char *alias)
+			void *symval, char *alias)
 {
-	id->class = TO_NATIVE(id->class);
-	id->vendor = TO_NATIVE(id->vendor);
-	id->device = TO_NATIVE(id->device);
+	DEF_FIELD(symval, sdio_device_id, class);
+	DEF_FIELD(symval, sdio_device_id, vendor);
+	DEF_FIELD(symval, sdio_device_id, device);
 
 	strcpy(alias, "sdio:");
-	ADD(alias, "c", id->class != (__u8)SDIO_ANY_ID, id->class);
-	ADD(alias, "v", id->vendor != (__u16)SDIO_ANY_ID, id->vendor);
-	ADD(alias, "d", id->device != (__u16)SDIO_ANY_ID, id->device);
+	ADD(alias, "c", class != (__u8)SDIO_ANY_ID, class);
+	ADD(alias, "v", vendor != (__u16)SDIO_ANY_ID, vendor);
+	ADD(alias, "d", device != (__u16)SDIO_ANY_ID, device);
 	add_wildcard(alias);
 	return 1;
 }
-ADD_TO_DEVTABLE("sdio", struct sdio_device_id, do_sdio_entry);
+ADD_TO_DEVTABLE("sdio", sdio_device_id, do_sdio_entry);
 
 /* Looks like: ssb:vNidNrevN. */
 static int do_ssb_entry(const char *filename,
-			struct ssb_device_id *id, char *alias)
+			void *symval, char *alias)
 {
-	id->vendor = TO_NATIVE(id->vendor);
-	id->coreid = TO_NATIVE(id->coreid);
-	id->revision = TO_NATIVE(id->revision);
+	DEF_FIELD(symval, ssb_device_id, vendor);
+	DEF_FIELD(symval, ssb_device_id, coreid);
+	DEF_FIELD(symval, ssb_device_id, revision);
 
 	strcpy(alias, "ssb:");
-	ADD(alias, "v", id->vendor != SSB_ANY_VENDOR, id->vendor);
-	ADD(alias, "id", id->coreid != SSB_ANY_ID, id->coreid);
-	ADD(alias, "rev", id->revision != SSB_ANY_REV, id->revision);
+	ADD(alias, "v", vendor != SSB_ANY_VENDOR, vendor);
+	ADD(alias, "id", coreid != SSB_ANY_ID, coreid);
+	ADD(alias, "rev", revision != SSB_ANY_REV, revision);
 	add_wildcard(alias);
 	return 1;
 }
-ADD_TO_DEVTABLE("ssb", struct ssb_device_id, do_ssb_entry);
+ADD_TO_DEVTABLE("ssb", ssb_device_id, do_ssb_entry);
 
 /* Looks like: bcma:mNidNrevNclN. */
 static int do_bcma_entry(const char *filename,
-			 struct bcma_device_id *id, char *alias)
+			 void *symval, char *alias)
 {
-	id->manuf = TO_NATIVE(id->manuf);
-	id->id = TO_NATIVE(id->id);
-	id->rev = TO_NATIVE(id->rev);
-	id->class = TO_NATIVE(id->class);
+	DEF_FIELD(symval, bcma_device_id, manuf);
+	DEF_FIELD(symval, bcma_device_id, id);
+	DEF_FIELD(symval, bcma_device_id, rev);
+	DEF_FIELD(symval, bcma_device_id, class);
 
 	strcpy(alias, "bcma:");
-	ADD(alias, "m", id->manuf != BCMA_ANY_MANUF, id->manuf);
-	ADD(alias, "id", id->id != BCMA_ANY_ID, id->id);
-	ADD(alias, "rev", id->rev != BCMA_ANY_REV, id->rev);
-	ADD(alias, "cl", id->class != BCMA_ANY_CLASS, id->class);
+	ADD(alias, "m", manuf != BCMA_ANY_MANUF, manuf);
+	ADD(alias, "id", id != BCMA_ANY_ID, id);
+	ADD(alias, "rev", rev != BCMA_ANY_REV, rev);
+	ADD(alias, "cl", class != BCMA_ANY_CLASS, class);
 	add_wildcard(alias);
 	return 1;
 }
-ADD_TO_DEVTABLE("bcma", struct bcma_device_id, do_bcma_entry);
+ADD_TO_DEVTABLE("bcma", bcma_device_id, do_bcma_entry);
 
 /* Looks like: virtio:dNvN */
-static int do_virtio_entry(const char *filename, struct virtio_device_id *id,
+static int do_virtio_entry(const char *filename, void *symval,
 			   char *alias)
 {
-	id->device = TO_NATIVE(id->device);
-	id->vendor = TO_NATIVE(id->vendor);
+	DEF_FIELD(symval, virtio_device_id, device);
+	DEF_FIELD(symval, virtio_device_id, vendor);
 
 	strcpy(alias, "virtio:");
-	ADD(alias, "d", id->device != VIRTIO_DEV_ANY_ID, id->device);
-	ADD(alias, "v", id->vendor != VIRTIO_DEV_ANY_ID, id->vendor);
+	ADD(alias, "d", device != VIRTIO_DEV_ANY_ID, device);
+	ADD(alias, "v", vendor != VIRTIO_DEV_ANY_ID, vendor);
 
 	add_wildcard(alias);
 	return 1;
 }
-ADD_TO_DEVTABLE("virtio", struct virtio_device_id, do_virtio_entry);
+ADD_TO_DEVTABLE("virtio", virtio_device_id, do_virtio_entry);
 
 /*
  * Looks like: vmbus:guid
@@ -813,41 +860,44 @@ ADD_TO_DEVTABLE("virtio", struct virtio_device_id, do_virtio_entry);
  * in the name.
  */
 
-static int do_vmbus_entry(const char *filename, struct hv_vmbus_device_id *id,
+static int do_vmbus_entry(const char *filename, void *symval,
 			  char *alias)
 {
 	int i;
-	char guid_name[((sizeof(id->guid) + 1)) * 2];
+	DEF_FIELD_ADDR(symval, hv_vmbus_device_id, guid);
+	char guid_name[(sizeof(*guid) + 1) * 2];
 
-	for (i = 0; i < (sizeof(id->guid) * 2); i += 2)
-		sprintf(&guid_name[i], "%02x", id->guid[i/2]);
+	for (i = 0; i < (sizeof(*guid) * 2); i += 2)
+		sprintf(&guid_name[i], "%02x", TO_NATIVE((*guid)[i/2]));
 
 	strcpy(alias, "vmbus:");
 	strcat(alias, guid_name);
 
 	return 1;
 }
-ADD_TO_DEVTABLE("vmbus", struct hv_vmbus_device_id, do_vmbus_entry);
+ADD_TO_DEVTABLE("vmbus", hv_vmbus_device_id, do_vmbus_entry);
 
 /* Looks like: i2c:S */
-static int do_i2c_entry(const char *filename, struct i2c_device_id *id,
+static int do_i2c_entry(const char *filename, void *symval,
 			char *alias)
 {
-	sprintf(alias, I2C_MODULE_PREFIX "%s", id->name);
+	DEF_FIELD_ADDR(symval, i2c_device_id, name);
+	sprintf(alias, I2C_MODULE_PREFIX "%s", *name);
 
 	return 1;
 }
-ADD_TO_DEVTABLE("i2c", struct i2c_device_id, do_i2c_entry);
+ADD_TO_DEVTABLE("i2c", i2c_device_id, do_i2c_entry);
 
 /* Looks like: spi:S */
-static int do_spi_entry(const char *filename, struct spi_device_id *id,
+static int do_spi_entry(const char *filename, void *symval,
 			char *alias)
 {
-	sprintf(alias, SPI_MODULE_PREFIX "%s", id->name);
+	DEF_FIELD_ADDR(symval, spi_device_id, name);
+	sprintf(alias, SPI_MODULE_PREFIX "%s", *name);
 
 	return 1;
 }
-ADD_TO_DEVTABLE("spi", struct spi_device_id, do_spi_entry);
+ADD_TO_DEVTABLE("spi", spi_device_id, do_spi_entry);
 
 static const struct dmifield {
 	const char *prefix;
@@ -879,21 +929,21 @@ static void dmi_ascii_filter(char *d, const char *s)
 }
 
 
-static int do_dmi_entry(const char *filename, struct dmi_system_id *id,
+static int do_dmi_entry(const char *filename, void *symval,
 			char *alias)
 {
 	int i, j;
-
+	DEF_FIELD_ADDR(symval, dmi_system_id, matches);
 	sprintf(alias, "dmi*");
 
 	for (i = 0; i < ARRAY_SIZE(dmi_fields); i++) {
 		for (j = 0; j < 4; j++) {
-			if (id->matches[j].slot &&
-			    id->matches[j].slot == dmi_fields[i].field) {
+			if ((*matches)[j].slot &&
+			    (*matches)[j].slot == dmi_fields[i].field) {
 				sprintf(alias + strlen(alias), ":%s*",
 					dmi_fields[i].prefix);
 				dmi_ascii_filter(alias + strlen(alias),
-						 id->matches[j].substr);
+						 (*matches)[j].substr);
 				strcat(alias, "*");
 			}
 		}
@@ -902,27 +952,30 @@ static int do_dmi_entry(const char *filename, struct dmi_system_id *id,
 	strcat(alias, ":");
 	return 1;
 }
-ADD_TO_DEVTABLE("dmi", struct dmi_system_id, do_dmi_entry);
+ADD_TO_DEVTABLE("dmi", dmi_system_id, do_dmi_entry);
 
 static int do_platform_entry(const char *filename,
-			     struct platform_device_id *id, char *alias)
+			     void *symval, char *alias)
 {
-	sprintf(alias, PLATFORM_MODULE_PREFIX "%s", id->name);
+	DEF_FIELD_ADDR(symval, platform_device_id, name);
+	sprintf(alias, PLATFORM_MODULE_PREFIX "%s", *name);
 	return 1;
 }
-ADD_TO_DEVTABLE("platform", struct platform_device_id, do_platform_entry);
+ADD_TO_DEVTABLE("platform", platform_device_id, do_platform_entry);
 
 static int do_mdio_entry(const char *filename,
-			 struct mdio_device_id *id, char *alias)
+			 void *symval, char *alias)
 {
 	int i;
+	DEF_FIELD(symval, mdio_device_id, phy_id);
+	DEF_FIELD(symval, mdio_device_id, phy_id_mask);
 
 	alias += sprintf(alias, MDIO_MODULE_PREFIX);
 
 	for (i = 0; i < 32; i++) {
-		if (!((id->phy_id_mask >> (31-i)) & 1))
+		if (!((phy_id_mask >> (31-i)) & 1))
 			*(alias++) = '?';
-		else if ((id->phy_id >> (31-i)) & 1)
+		else if ((phy_id >> (31-i)) & 1)
 			*(alias++) = '1';
 		else
 			*(alias++) = '0';
@@ -933,32 +986,34 @@ static int do_mdio_entry(const char *filename,
 
 	return 1;
 }
-ADD_TO_DEVTABLE("mdio", struct mdio_device_id, do_mdio_entry);
+ADD_TO_DEVTABLE("mdio", mdio_device_id, do_mdio_entry);
 
 /* Looks like: zorro:iN. */
-static int do_zorro_entry(const char *filename, struct zorro_device_id *id,
+static int do_zorro_entry(const char *filename, void *symval,
 			  char *alias)
 {
-	id->id = TO_NATIVE(id->id);
+	DEF_FIELD(symval, zorro_device_id, id);
 	strcpy(alias, "zorro:");
-	ADD(alias, "i", id->id != ZORRO_WILDCARD, id->id);
+	ADD(alias, "i", id != ZORRO_WILDCARD, id);
 	return 1;
 }
-ADD_TO_DEVTABLE("zorro", struct zorro_device_id, do_zorro_entry);
+ADD_TO_DEVTABLE("zorro", zorro_device_id, do_zorro_entry);
 
 /* looks like: "pnp:dD" */
 static int do_isapnp_entry(const char *filename,
-			   struct isapnp_device_id *id, char *alias)
+			   void *symval, char *alias)
 {
+	DEF_FIELD(symval, isapnp_device_id, vendor);
+	DEF_FIELD(symval, isapnp_device_id, function);
 	sprintf(alias, "pnp:d%c%c%c%x%x%x%x*",
-		'A' + ((id->vendor >> 2) & 0x3f) - 1,
-		'A' + (((id->vendor & 3) << 3) | ((id->vendor >> 13) & 7)) - 1,
-		'A' + ((id->vendor >> 8) & 0x1f) - 1,
-		(id->function >> 4) & 0x0f, id->function & 0x0f,
-		(id->function >> 12) & 0x0f, (id->function >> 8) & 0x0f);
+		'A' + ((vendor >> 2) & 0x3f) - 1,
+		'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1,
+		'A' + ((vendor >> 8) & 0x1f) - 1,
+		(function >> 4) & 0x0f, function & 0x0f,
+		(function >> 12) & 0x0f, (function >> 8) & 0x0f);
 	return 1;
 }
-ADD_TO_DEVTABLE("isapnp", struct isapnp_device_id, do_isapnp_entry);
+ADD_TO_DEVTABLE("isapnp", isapnp_device_id, do_isapnp_entry);
 
 /*
  * Append a match expression for a single masked hex digit.
@@ -1009,25 +1064,27 @@ static void append_nibble_mask(char **outp,
  *	a ? or [] pattern matching exactly one digit.
  */
 static int do_amba_entry(const char *filename,
-			 struct amba_id *id, char *alias)
+			 void *symval, char *alias)
 {
 	unsigned int digit;
 	char *p = alias;
+	DEF_FIELD(symval, amba_id, id);
+	DEF_FIELD(symval, amba_id, mask);
 
-	if ((id->id & id->mask) != id->id)
+	if ((id & mask) != id)
 		fatal("%s: Masked-off bit(s) of AMBA device ID are non-zero: "
 		      "id=0x%08X, mask=0x%08X.  Please fix this driver.\n",
-		      filename, id->id, id->mask);
+		      filename, id, mask);
 
 	p += sprintf(alias, "amba:d");
 	for (digit = 0; digit < 8; digit++)
 		append_nibble_mask(&p,
-				   (id->id >> (4 * (7 - digit))) & 0xf,
-				   (id->mask >> (4 * (7 - digit))) & 0xf);
+				   (id >> (4 * (7 - digit))) & 0xf,
+				   (mask >> (4 * (7 - digit))) & 0xf);
 
 	return 1;
 }
-ADD_TO_DEVTABLE("amba", struct amba_id, do_amba_entry);
+ADD_TO_DEVTABLE("amba", amba_id, do_amba_entry);
 
 /* LOOKS like x86cpu:vendor:VVVV:family:FFFF:model:MMMM:feature:*,FEAT,*
  * All fields are numbers. It would be nicer to use strings for vendor
@@ -1035,24 +1092,24 @@ ADD_TO_DEVTABLE("amba", struct amba_id, do_amba_entry);
  * complicated.
  */
 
-static int do_x86cpu_entry(const char *filename, struct x86_cpu_id *id,
+static int do_x86cpu_entry(const char *filename, void *symval,
 			   char *alias)
 {
-	id->feature = TO_NATIVE(id->feature);
-	id->family = TO_NATIVE(id->family);
-	id->model = TO_NATIVE(id->model);
-	id->vendor = TO_NATIVE(id->vendor);
+	DEF_FIELD(symval, x86_cpu_id, feature);
+	DEF_FIELD(symval, x86_cpu_id, family);
+	DEF_FIELD(symval, x86_cpu_id, model);
+	DEF_FIELD(symval, x86_cpu_id, vendor);
 
 	strcpy(alias, "x86cpu:");
-	ADD(alias, "vendor:",  id->vendor != X86_VENDOR_ANY, id->vendor);
-	ADD(alias, ":family:", id->family != X86_FAMILY_ANY, id->family);
-	ADD(alias, ":model:",  id->model  != X86_MODEL_ANY,  id->model);
+	ADD(alias, "vendor:",  vendor != X86_VENDOR_ANY, vendor);
+	ADD(alias, ":family:", family != X86_FAMILY_ANY, family);
+	ADD(alias, ":model:",  model  != X86_MODEL_ANY,  model);
 	strcat(alias, ":feature:*");
-	if (id->feature != X86_FEATURE_ANY)
-		sprintf(alias + strlen(alias), "%04X*", id->feature);
+	if (feature != X86_FEATURE_ANY)
+		sprintf(alias + strlen(alias), "%04X*", feature);
 	return 1;
 }
-ADD_TO_DEVTABLE("x86cpu", struct x86_cpu_id, do_x86cpu_entry);
+ADD_TO_DEVTABLE("x86cpu", x86_cpu_id, do_x86cpu_entry);
 
 /* Does namelen bytes of name exactly match the symbol? */
 static bool sym_is(const char *name, unsigned namelen, const char *symbol)
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index c4e7d15..8e7b9fb 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -2113,7 +2113,7 @@ int main(int argc, char **argv)
 	struct ext_sym_list *extsym_iter;
 	struct ext_sym_list *extsym_start = NULL;
 
-	while ((opt = getopt(argc, argv, "i:I:e:cmsSo:awM:K:")) != -1) {
+	while ((opt = getopt(argc, argv, "i:I:e:msSo:awM:K:")) != -1) {
 		switch (opt) {
 		case 'i':
 			kernel_read = optarg;
@@ -2122,9 +2122,6 @@ int main(int argc, char **argv)
 			module_read = optarg;
 			external_module = 1;
 			break;
-		case 'c':
-			cross_build = 1;
-			break;
 		case 'e':
 			external_module = 1;
 			extsym_iter =
-- 
1.7.11.1


Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH] mod/file2alias: make modalias generation safe for cross compiling
  2012-06-25 12:22             ` [PATCH] mod/file2alias: make modalias generation safe for cross compiling Andreas Schwab
@ 2012-06-25 20:32               ` Geert Uytterhoeven
  2012-06-25 21:43                 ` Andreas Schwab
  2012-06-26  5:00               ` Sam Ravnborg
  1 sibling, 1 reply; 17+ messages in thread
From: Geert Uytterhoeven @ 2012-06-25 20:32 UTC (permalink / raw)
  To: Andreas Schwab
  Cc: Bjørn Mork, Greg Kroah-Hartman, USB list, linux-kernel,
	Linux-Next, linux-kbuild, Linux/m68k

	Hi Andreas,

On Mon, 25 Jun 2012, Andreas Schwab wrote:
> Use the target compiler to compute the offsets of the fields of the
> device_id structures, so that it won't be broken by different alignments
> between the host and target ABIs.

Thanks, very nice!

> --- a/include/linux/mod_devicetable.h
> +++ b/include/linux/mod_devicetable.h
> @@ -33,8 +33,7 @@ struct ieee1394_device_id {
>  	__u32 model_id;
>  	__u32 specifier_id;
>  	__u32 version;
> -	kernel_ulong_t driver_data
> -		__attribute__((aligned(sizeof(kernel_ulong_t))));
> +	kernel_ulong_t driver_data;

After this, we can also get rid of kernel_ulong_t, but that's a more intruisive
patch all over the place.

> --- /dev/null
> +++ b/scripts/mod/devicetable-offsets.c
> @@ -0,0 +1,171 @@
> +#include <linux/kbuild.h>
> +#include <linux/mod_devicetable.h>
> +
> +#define DEVID(devid) DEFINE(SIZE_##devid, sizeof(struct devid))
> +#define DEVID_FIELD(devid, field) \
> +	DEFINE(OFF_##devid##_##field, offsetof(struct devid, field))
> +
> +int main(void)
> +{
> +	DEVID(usb_device_id);
> +	DEVID_FIELD(usb_device_id, match_flags);
> +	DEVID_FIELD(usb_device_id, idVendor);
> +	DEVID_FIELD(usb_device_id, idProduct);
> +	DEVID_FIELD(usb_device_id, bcdDevice_lo);
> +	DEVID_FIELD(usb_device_id, bcdDevice_hi);
> +	DEVID_FIELD(usb_device_id, bDeviceClass);
> +	DEVID_FIELD(usb_device_id, bDeviceSubClass);
> +	DEVID_FIELD(usb_device_id, bDeviceProtocol);
> +	DEVID_FIELD(usb_device_id, bInterfaceClass);
> +	DEVID_FIELD(usb_device_id, bInterfaceSubClass);
> +	DEVID_FIELD(usb_device_id, bInterfaceProtocol);

These are all duplicates of the structures in <linux/mod_devicetable.h>.
Can't you get rid of the duplication by putting e.g. the following
in <linux/mod_devicetable.h>:

    DEVID_START(usb_device_id);
    DEVID_FIELD(usb_device_id, __u16, match_flags);
    DEVID_FIELD(usb_device_id, __u16, idVendor);
    DEVID_FIELD(usb_device_id, __u16, idProduct);
    DEVID_FIELD(usb_device_id, __u16, bcdDevice_lo);
    DEVID_FIELD(usb_device_id, __u16, bcdDevice_hi);
    DEVID_FIELD(usb_device_id, __u8, bDeviceClass);
    DEVID_FIELD(usb_device_id, __u8, bDeviceSubClass);
    DEVID_FIELD(usb_device_id, __u8, bDeviceProtocol);
    DEVID_FIELD(usb_device_id, __u8, bInterfaceClass);
    DEVID_FIELD(usb_device_id, __u8, bInterfaceSubClass);
    DEVID_FIELD(usb_device_id, __u8, bInterfaceProtocol);
    DEVID_END();

and redefining the DEVID_*() macros depending on
  1. __KERNEL__, to generate the C struct definitions for kernel builds,
  2. first inclusion by devicetable-offsets.c, also to generate C struct
     definitions,
  3. second inclusion by devicetable-offsets.c, to generate the sizes and
     offset definitions for modalias?

> --- a/scripts/mod/file2alias.c
> +++ b/scripts/mod/file2alias.c
> @@ -116,7 +129,6 @@ static inline void add_wildcard(char *str)
>  		strcat(str + len, "*");
>  }
>  
> -unsigned int cross_build = 0;
>  /**
>   * Check that sizeof(device_id type) are consistent with size of section
>   * in .o file. If in-consistent then userspace and kernel does not agree
> @@ -131,8 +143,6 @@ static void device_id_check(const char *modname, const char *device_id,
>  	int i;
>  
>  	if (size % id_size || size < id_size) {
> -		if (cross_build != 0)
> -			return;
>  		fatal("%s: sizeof(struct %s_device_id)=%lu is not a modulo "
>  		      "of the size of section __mod_%s_device_table=%lu.\n"
>  		      "Fix definition of struct %s_device_id "

Funny, I didn't know there was a check for cross-compiling, supposedly to
ignore the warnings.
And it didn't work, as the problem was noticed originally on the linux-next
build service (which uses cross-compiling), and also showed up for my own
cross-builds.

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

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

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] mod/file2alias: make modalias generation safe for cross compiling
  2012-06-25 20:32               ` Geert Uytterhoeven
@ 2012-06-25 21:43                 ` Andreas Schwab
  0 siblings, 0 replies; 17+ messages in thread
From: Andreas Schwab @ 2012-06-25 21:43 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Bjørn Mork, Greg Kroah-Hartman, USB list, linux-kernel,
	Linux-Next, linux-kbuild, Linux/m68k

Geert Uytterhoeven <geert@linux-m68k.org> writes:

> 	Hi Andreas,
>
> On Mon, 25 Jun 2012, Andreas Schwab wrote:
>> --- /dev/null
>> +++ b/scripts/mod/devicetable-offsets.c
>> @@ -0,0 +1,171 @@
>> +#include <linux/kbuild.h>
>> +#include <linux/mod_devicetable.h>
>> +
>> +#define DEVID(devid) DEFINE(SIZE_##devid, sizeof(struct devid))
>> +#define DEVID_FIELD(devid, field) \
>> +	DEFINE(OFF_##devid##_##field, offsetof(struct devid, field))
>> +
>> +int main(void)
>> +{
>> +	DEVID(usb_device_id);
>> +	DEVID_FIELD(usb_device_id, match_flags);
>> +	DEVID_FIELD(usb_device_id, idVendor);
>> +	DEVID_FIELD(usb_device_id, idProduct);
>> +	DEVID_FIELD(usb_device_id, bcdDevice_lo);
>> +	DEVID_FIELD(usb_device_id, bcdDevice_hi);
>> +	DEVID_FIELD(usb_device_id, bDeviceClass);
>> +	DEVID_FIELD(usb_device_id, bDeviceSubClass);
>> +	DEVID_FIELD(usb_device_id, bDeviceProtocol);
>> +	DEVID_FIELD(usb_device_id, bInterfaceClass);
>> +	DEVID_FIELD(usb_device_id, bInterfaceSubClass);
>> +	DEVID_FIELD(usb_device_id, bInterfaceProtocol);
>
> These are all duplicates of the structures in <linux/mod_devicetable.h>.
> Can't you get rid of the duplication by putting e.g. the following
> in <linux/mod_devicetable.h>:
>
>     DEVID_START(usb_device_id);
>     DEVID_FIELD(usb_device_id, __u16, match_flags);
>     DEVID_FIELD(usb_device_id, __u16, idVendor);
>     DEVID_FIELD(usb_device_id, __u16, idProduct);
>     DEVID_FIELD(usb_device_id, __u16, bcdDevice_lo);
>     DEVID_FIELD(usb_device_id, __u16, bcdDevice_hi);
>     DEVID_FIELD(usb_device_id, __u8, bDeviceClass);
>     DEVID_FIELD(usb_device_id, __u8, bDeviceSubClass);
>     DEVID_FIELD(usb_device_id, __u8, bDeviceProtocol);
>     DEVID_FIELD(usb_device_id, __u8, bInterfaceClass);
>     DEVID_FIELD(usb_device_id, __u8, bInterfaceSubClass);
>     DEVID_FIELD(usb_device_id, __u8, bInterfaceProtocol);
>     DEVID_END();
>
> and redefining the DEVID_*() macros depending on
>   1. __KERNEL__, to generate the C struct definitions for kernel builds,
>   2. first inclusion by devicetable-offsets.c, also to generate C struct
>      definitions,
>   3. second inclusion by devicetable-offsets.c, to generate the sizes and
>      offset definitions for modalias?

That requires some reorganisation of the struct pnp_card_device_id which
has a somewhat complicated structure (which also accounts for the
ugliest part of the patch).

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] mod/file2alias: make modalias generation safe for cross compiling
  2012-06-25 12:22             ` [PATCH] mod/file2alias: make modalias generation safe for cross compiling Andreas Schwab
  2012-06-25 20:32               ` Geert Uytterhoeven
@ 2012-06-26  5:00               ` Sam Ravnborg
  2012-06-26 13:27                 ` [PATCH v2] " Andreas Schwab
  1 sibling, 1 reply; 17+ messages in thread
From: Sam Ravnborg @ 2012-06-26  5:00 UTC (permalink / raw)
  To: Andreas Schwab
  Cc: Bjørn Mork, Greg Kroah-Hartman, Geert Uytterhoeven,
	USB list, linux-kernel, Linux-Next, linux-kbuild, Linux/m68k

Hi Andreas.

On Mon, Jun 25, 2012 at 02:22:34PM +0200, Andreas Schwab wrote:
> Use the target compiler to compute the offsets of the fields of the
> device_id structures, so that it won't be broken by different alignments
> between the host and target ABIs.
Looks good.

> diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
> index 08dce14..ff22206 100644
> --- a/scripts/Makefile.modpost
> +++ b/scripts/Makefile.modpost
> @@ -80,8 +80,7 @@ modpost = scripts/mod/modpost                    \
>   $(if $(KBUILD_EXTRA_SYMBOLS), $(patsubst %, -e %,$(KBUILD_EXTRA_SYMBOLS))) \
>   $(if $(KBUILD_EXTMOD),-o $(modulesymfile))      \
>   $(if $(CONFIG_DEBUG_SECTION_MISMATCH),,-S)      \
> - $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w) \
> - $(if $(cross_build),-c)
> + $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w)

With this change we can kill cross_build, and thus we can
drop KBUILD_BUILDHOST too (from top-level Makefile).

	Sam

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v2] mod/file2alias: make modalias generation safe for cross compiling
  2012-06-26  5:00               ` Sam Ravnborg
@ 2012-06-26 13:27                 ` Andreas Schwab
  0 siblings, 0 replies; 17+ messages in thread
From: Andreas Schwab @ 2012-06-26 13:27 UTC (permalink / raw)
  To: Sam Ravnborg
  Cc: Bjørn Mork, Greg Kroah-Hartman, Geert Uytterhoeven,
	USB list, linux-kernel, Linux-Next, linux-kbuild, Linux/m68k

Use the target compiler to compute the offsets of the fields of the
device_id structures, so that it won't be broken by different alignments
between the host and target ABIs.

This also fixes missing endian corrections for some modaliases.

Signed-off-by: Andreas Schwab <schwab@linux-m68k.org>
---
v2:
 - Remove cross-build and KBUILD_BUILDHOST.
 - Rebase on v3.5-rc4

 Makefile                          |   1 -
 include/linux/mod_devicetable.h   |  58 +---
 scripts/Makefile.modpost          |   7 +-
 scripts/mod/.gitignore            |   1 +
 scripts/mod/Makefile              |  35 ++
 scripts/mod/devicetable-offsets.c | 172 ++++++++++
 scripts/mod/file2alias.c          | 653 +++++++++++++++++++++-----------------
 scripts/mod/modpost.c             |   5 +-
 8 files changed, 574 insertions(+), 358 deletions(-)
 create mode 100644 scripts/mod/devicetable-offsets.c

diff --git a/Makefile b/Makefile
index 3fdfde2..f345298 100644
--- a/Makefile
+++ b/Makefile
@@ -191,7 +191,6 @@ SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
 # "make" in the configured kernel build directory always uses that.
 # Default value for CROSS_COMPILE is not to prefix executables
 # Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile
-export KBUILD_BUILDHOST := $(SUBARCH)
 ARCH		?= $(SUBARCH)
 CROSS_COMPILE	?= $(CONFIG_CROSS_COMPILE:"%"=%)
 
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index 5db9382..bf55000 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -33,8 +33,7 @@ struct ieee1394_device_id {
 	__u32 model_id;
 	__u32 specifier_id;
 	__u32 version;
-	kernel_ulong_t driver_data
-		__attribute__((aligned(sizeof(kernel_ulong_t))));
+	kernel_ulong_t driver_data;
 };
 
 
@@ -140,8 +139,7 @@ struct hid_device_id {
 	__u16 group;
 	__u32 vendor;
 	__u32 product;
-	kernel_ulong_t driver_data
-		__attribute__((aligned(sizeof(kernel_ulong_t))));
+	kernel_ulong_t driver_data;
 };
 
 /* s390 CCW devices */
@@ -165,8 +163,6 @@ struct ccw_device_id {
 struct ap_device_id {
 	__u16 match_flags;	/* which fields to match against */
 	__u8 dev_type;		/* device type */
-	__u8 pad1;
-	__u32 pad2;
 	kernel_ulong_t driver_info;
 };
 
@@ -176,13 +172,10 @@ struct ap_device_id {
 struct css_device_id {
 	__u8 match_flags;
 	__u8 type; /* subchannel type */
-	__u16 pad2;
-	__u32 pad3;
 	kernel_ulong_t driver_data;
 };
 
-#define ACPI_ID_LEN	16 /* only 9 bytes needed here, 16 bytes are used */
-			   /* to workaround crosscompile issues */
+#define ACPI_ID_LEN	9
 
 struct acpi_device_id {
 	__u8 id[ACPI_ID_LEN];
@@ -223,11 +216,7 @@ struct of_device_id
 	char	name[32];
 	char	type[32];
 	char	compatible[128];
-#ifdef __KERNEL__
 	void	*data;
-#else
-	kernel_ulong_t data;
-#endif
 };
 
 /* VIO */
@@ -252,24 +241,14 @@ struct pcmcia_device_id {
 	/* for pseudo multi-function devices */
 	__u8  		device_no;
 
-	__u32 		prod_id_hash[4]
-		__attribute__((aligned(sizeof(__u32))));
+	__u32 		prod_id_hash[4];
 
 	/* not matched against in kernelspace*/
-#ifdef __KERNEL__
 	const char *	prod_id[4];
-#else
-	kernel_ulong_t	prod_id[4]
-		__attribute__((aligned(sizeof(kernel_ulong_t))));
-#endif
 
 	/* not matched against */
 	kernel_ulong_t	driver_info;
-#ifdef __KERNEL__
 	char *		cisfile;
-#else
-	kernel_ulong_t	cisfile;
-#endif
 };
 
 #define PCMCIA_DEV_ID_MATCH_MANF_ID	0x0001
@@ -365,8 +344,7 @@ struct sdio_device_id {
 	__u8	class;			/* Standard interface or SDIO_ANY_ID */
 	__u16	vendor;			/* Vendor or SDIO_ANY_ID */
 	__u16	device;			/* Device ID or SDIO_ANY_ID */
-	kernel_ulong_t driver_data	/* Data private to the driver */
-		__attribute__((aligned(sizeof(kernel_ulong_t))));
+	kernel_ulong_t driver_data;	/* Data private to the driver */
 };
 
 /* SSB core, see drivers/ssb/ */
@@ -412,8 +390,7 @@ struct virtio_device_id {
  */
 struct hv_vmbus_device_id {
 	__u8 guid[16];
-	kernel_ulong_t driver_data	/* Data private to the driver */
-			__attribute__((aligned(sizeof(kernel_ulong_t))));
+	kernel_ulong_t driver_data;	/* Data private to the driver */
 };
 
 /* rpmsg */
@@ -432,8 +409,7 @@ struct rpmsg_device_id {
 
 struct i2c_device_id {
 	char name[I2C_NAME_SIZE];
-	kernel_ulong_t driver_data	/* Data private to the driver */
-			__attribute__((aligned(sizeof(kernel_ulong_t))));
+	kernel_ulong_t driver_data;	/* Data private to the driver */
 };
 
 /* spi */
@@ -443,8 +419,7 @@ struct i2c_device_id {
 
 struct spi_device_id {
 	char name[SPI_NAME_SIZE];
-	kernel_ulong_t driver_data	/* Data private to the driver */
-			__attribute__((aligned(sizeof(kernel_ulong_t))));
+	kernel_ulong_t driver_data;	/* Data private to the driver */
 };
 
 /* dmi */
@@ -476,15 +451,6 @@ struct dmi_strmatch {
 	char substr[79];
 };
 
-#ifndef __KERNEL__
-struct dmi_system_id {
-	kernel_ulong_t callback;
-	kernel_ulong_t ident;
-	struct dmi_strmatch matches[4];
-	kernel_ulong_t driver_data
-			__attribute__((aligned(sizeof(kernel_ulong_t))));
-};
-#else
 struct dmi_system_id {
 	int (*callback)(const struct dmi_system_id *);
 	const char *ident;
@@ -498,7 +464,6 @@ struct dmi_system_id {
  *	error: storage size of '__mod_dmi_device_table' isn't known
  */
 #define dmi_device_id dmi_system_id
-#endif
 
 #define DMI_MATCH(a, b)	{ a, b }
 
@@ -507,8 +472,7 @@ struct dmi_system_id {
 
 struct platform_device_id {
 	char name[PLATFORM_NAME_SIZE];
-	kernel_ulong_t driver_data
-			__attribute__((aligned(sizeof(kernel_ulong_t))));
+	kernel_ulong_t driver_data;
 };
 
 #define MDIO_MODULE_PREFIX	"mdio:"
@@ -564,11 +528,7 @@ struct isapnp_device_id {
 struct amba_id {
 	unsigned int		id;
 	unsigned int		mask;
-#ifndef __KERNEL__
-	kernel_ulong_t		data;
-#else
 	void			*data;
-#endif
 };
 
 /*
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index 08dce14..f26f63d 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -66,10 +66,6 @@ modules   := $(patsubst %.o,%.ko, $(wildcard $(__modules:.ko=.o)))
 # Stop after building .o files if NOFINAL is set. Makes compile tests quicker
 _modpost: $(if $(KBUILD_MODPOST_NOFINAL), $(modules:.ko:.o),$(modules))
 
-ifneq ($(KBUILD_BUILDHOST),$(ARCH))
-        cross_build := 1
-endif
-
 # Step 2), invoke modpost
 #  Includes step 3,4
 modpost = scripts/mod/modpost                    \
@@ -80,8 +76,7 @@ modpost = scripts/mod/modpost                    \
  $(if $(KBUILD_EXTRA_SYMBOLS), $(patsubst %, -e %,$(KBUILD_EXTRA_SYMBOLS))) \
  $(if $(KBUILD_EXTMOD),-o $(modulesymfile))      \
  $(if $(CONFIG_DEBUG_SECTION_MISMATCH),,-S)      \
- $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w) \
- $(if $(cross_build),-c)
+ $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w)
 
 quiet_cmd_modpost = MODPOST $(words $(filter-out vmlinux FORCE, $^)) modules
       cmd_modpost = $(modpost) -s
diff --git a/scripts/mod/.gitignore b/scripts/mod/.gitignore
index e9b7abe..33bae0d 100644
--- a/scripts/mod/.gitignore
+++ b/scripts/mod/.gitignore
@@ -1,4 +1,5 @@
 elfconfig.h
 mk_elfconfig
 modpost
+devicetable-offsets.h
 
diff --git a/scripts/mod/Makefile b/scripts/mod/Makefile
index ff954f8..9415b56 100644
--- a/scripts/mod/Makefile
+++ b/scripts/mod/Makefile
@@ -3,9 +3,44 @@ always		:= $(hostprogs-y) empty.o
 
 modpost-objs	:= modpost.o file2alias.o sumversion.o
 
+devicetable-offsets-file := devicetable-offsets.h
+
+define sed-y
+	"/^->/{s:->#\(.*\):/* \1 */:; \
+	s:^->\([^ ]*\) [\$$#]*\([-0-9]*\) \(.*\):#define \1 \2 /* \3 */:; \
+	s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \
+	s:->::; p;}"
+endef
+
+quiet_cmd_offsets = GEN     $@
+define cmd_offsets
+	(set -e; \
+	 echo "#ifndef __DEVICEVTABLE_OFFSETS_H__"; \
+	 echo "#define __DEVICEVTABLE_OFFSETS_H__"; \
+	 echo "/*"; \
+	 echo " * DO NOT MODIFY."; \
+	 echo " *"; \
+	 echo " * This file was generated by Kbuild"; \
+	 echo " *"; \
+	 echo " */"; \
+	 echo ""; \
+	 sed -ne $(sed-y) $<; \
+	 echo ""; \
+	 echo "#endif" ) > $@
+endef
+
+# We use internal kbuild rules to avoid the "is up to date" message from make
+scripts/mod/devicetable-offsets.s: scripts/mod/devicetable-offsets.c FORCE
+	$(Q)mkdir -p $(dir $@)
+	$(call if_changed_dep,cc_s_c)
+
+$(obj)/$(devicetable-offsets-file): scripts/mod/devicetable-offsets.s
+	$(call cmd,offsets)
+
 # dependencies on generated files need to be listed explicitly
 
 $(obj)/modpost.o $(obj)/file2alias.o $(obj)/sumversion.o: $(obj)/elfconfig.h
+$(obj)/file2alias.o: $(obj)/$(devicetable-offsets-file)
 
 quiet_cmd_elfconfig = MKELF   $@
       cmd_elfconfig = $(obj)/mk_elfconfig < $< > $@
diff --git a/scripts/mod/devicetable-offsets.c b/scripts/mod/devicetable-offsets.c
new file mode 100644
index 0000000..2109b53
--- /dev/null
+++ b/scripts/mod/devicetable-offsets.c
@@ -0,0 +1,172 @@
+#include <linux/kbuild.h>
+#include <linux/mod_devicetable.h>
+
+#define DEVID(devid) DEFINE(SIZE_##devid, sizeof(struct devid))
+#define DEVID_FIELD(devid, field) \
+	DEFINE(OFF_##devid##_##field, offsetof(struct devid, field))
+
+int main(void)
+{
+	DEVID(usb_device_id);
+	DEVID_FIELD(usb_device_id, match_flags);
+	DEVID_FIELD(usb_device_id, idVendor);
+	DEVID_FIELD(usb_device_id, idProduct);
+	DEVID_FIELD(usb_device_id, bcdDevice_lo);
+	DEVID_FIELD(usb_device_id, bcdDevice_hi);
+	DEVID_FIELD(usb_device_id, bDeviceClass);
+	DEVID_FIELD(usb_device_id, bDeviceSubClass);
+	DEVID_FIELD(usb_device_id, bDeviceProtocol);
+	DEVID_FIELD(usb_device_id, bInterfaceClass);
+	DEVID_FIELD(usb_device_id, bInterfaceSubClass);
+	DEVID_FIELD(usb_device_id, bInterfaceProtocol);
+
+	DEVID(hid_device_id);
+	DEVID_FIELD(hid_device_id, bus);
+	DEVID_FIELD(hid_device_id, group);
+	DEVID_FIELD(hid_device_id, vendor);
+	DEVID_FIELD(hid_device_id, product);
+
+	DEVID(ieee1394_device_id);
+	DEVID_FIELD(ieee1394_device_id, match_flags);
+	DEVID_FIELD(ieee1394_device_id, vendor_id);
+	DEVID_FIELD(ieee1394_device_id, model_id);
+	DEVID_FIELD(ieee1394_device_id, specifier_id);
+	DEVID_FIELD(ieee1394_device_id, version);
+
+	DEVID(pci_device_id);
+	DEVID_FIELD(pci_device_id, vendor);
+	DEVID_FIELD(pci_device_id, device);
+	DEVID_FIELD(pci_device_id, subvendor);
+	DEVID_FIELD(pci_device_id, subdevice);
+	DEVID_FIELD(pci_device_id, class);
+	DEVID_FIELD(pci_device_id, class_mask);
+
+	DEVID(ccw_device_id);
+	DEVID_FIELD(ccw_device_id, match_flags);
+	DEVID_FIELD(ccw_device_id, cu_type);
+	DEVID_FIELD(ccw_device_id, cu_model);
+	DEVID_FIELD(ccw_device_id, dev_type);
+	DEVID_FIELD(ccw_device_id, dev_model);
+
+	DEVID(ap_device_id);
+	DEVID_FIELD(ap_device_id, dev_type);
+
+	DEVID(css_device_id);
+	DEVID_FIELD(css_device_id, type);
+
+	DEVID(serio_device_id);
+	DEVID_FIELD(serio_device_id, type);
+	DEVID_FIELD(serio_device_id, proto);
+	DEVID_FIELD(serio_device_id, id);
+	DEVID_FIELD(serio_device_id, extra);
+
+	DEVID(acpi_device_id);
+	DEVID_FIELD(acpi_device_id, id);
+
+	DEVID(pnp_device_id);
+	DEVID_FIELD(pnp_device_id, id);
+
+	DEVID(pnp_card_device_id);
+	DEVID_FIELD(pnp_card_device_id, devs);
+
+	DEVID(pcmcia_device_id);
+	DEVID_FIELD(pcmcia_device_id, match_flags);
+	DEVID_FIELD(pcmcia_device_id, manf_id);
+	DEVID_FIELD(pcmcia_device_id, card_id);
+	DEVID_FIELD(pcmcia_device_id, func_id);
+	DEVID_FIELD(pcmcia_device_id, function);
+	DEVID_FIELD(pcmcia_device_id, device_no);
+	DEVID_FIELD(pcmcia_device_id, prod_id_hash);
+
+	DEVID(of_device_id);
+	DEVID_FIELD(of_device_id, name);
+	DEVID_FIELD(of_device_id, type);
+	DEVID_FIELD(of_device_id, compatible);
+
+	DEVID(vio_device_id);
+	DEVID_FIELD(vio_device_id, type);
+	DEVID_FIELD(vio_device_id, compat);
+
+	DEVID(input_device_id);
+	DEVID_FIELD(input_device_id, flags);
+	DEVID_FIELD(input_device_id, bustype);
+	DEVID_FIELD(input_device_id, vendor);
+	DEVID_FIELD(input_device_id, product);
+	DEVID_FIELD(input_device_id, version);
+	DEVID_FIELD(input_device_id, evbit);
+	DEVID_FIELD(input_device_id, keybit);
+	DEVID_FIELD(input_device_id, relbit);
+	DEVID_FIELD(input_device_id, absbit);
+	DEVID_FIELD(input_device_id, mscbit);
+	DEVID_FIELD(input_device_id, ledbit);
+	DEVID_FIELD(input_device_id, sndbit);
+	DEVID_FIELD(input_device_id, ffbit);
+	DEVID_FIELD(input_device_id, swbit);
+
+	DEVID(eisa_device_id);
+	DEVID_FIELD(eisa_device_id, sig);
+
+	DEVID(parisc_device_id);
+	DEVID_FIELD(parisc_device_id, hw_type);
+	DEVID_FIELD(parisc_device_id, hversion);
+	DEVID_FIELD(parisc_device_id, hversion_rev);
+	DEVID_FIELD(parisc_device_id, sversion);
+
+	DEVID(sdio_device_id);
+	DEVID_FIELD(sdio_device_id, class);
+	DEVID_FIELD(sdio_device_id, vendor);
+	DEVID_FIELD(sdio_device_id, device);
+
+	DEVID(ssb_device_id);
+	DEVID_FIELD(ssb_device_id, vendor);
+	DEVID_FIELD(ssb_device_id, coreid);
+	DEVID_FIELD(ssb_device_id, revision);
+
+	DEVID(bcma_device_id);
+	DEVID_FIELD(bcma_device_id, manuf);
+	DEVID_FIELD(bcma_device_id, id);
+	DEVID_FIELD(bcma_device_id, rev);
+	DEVID_FIELD(bcma_device_id, class);
+
+	DEVID(virtio_device_id);
+	DEVID_FIELD(virtio_device_id, device);
+	DEVID_FIELD(virtio_device_id, vendor);
+
+	DEVID(hv_vmbus_device_id);
+	DEVID_FIELD(hv_vmbus_device_id, guid);
+
+	DEVID(i2c_device_id);
+	DEVID_FIELD(i2c_device_id, name);
+
+	DEVID(spi_device_id);
+	DEVID_FIELD(spi_device_id, name);
+
+	DEVID(dmi_system_id);
+	DEVID_FIELD(dmi_system_id, matches);
+
+	DEVID(platform_device_id);
+	DEVID_FIELD(platform_device_id, name);
+
+	DEVID(mdio_device_id);
+	DEVID_FIELD(mdio_device_id, phy_id);
+	DEVID_FIELD(mdio_device_id, phy_id_mask);
+
+	DEVID(zorro_device_id);
+	DEVID_FIELD(zorro_device_id, id);
+
+	DEVID(isapnp_device_id);
+	DEVID_FIELD(isapnp_device_id, vendor);
+	DEVID_FIELD(isapnp_device_id, function);
+
+	DEVID(amba_id);
+	DEVID_FIELD(amba_id, id);
+	DEVID_FIELD(amba_id, mask);
+
+	DEVID(x86_cpu_id);
+	DEVID_FIELD(x86_cpu_id, feature);
+	DEVID_FIELD(x86_cpu_id, family);
+	DEVID_FIELD(x86_cpu_id, model);
+	DEVID_FIELD(x86_cpu_id, vendor);
+
+	return 0;
+}
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 5759751..646af49 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -11,6 +11,7 @@
  */
 
 #include "modpost.h"
+#include "devicetable-offsets.h"
 
 /* We use the ELF typedefs for kernel_ulong_t but bite the bullet and
  * use either stdint.h or inttypes.h for the rest. */
@@ -84,13 +85,25 @@ extern struct devtable *__start___devtable[], *__stop___devtable[];
 # define __used			__attribute__((__used__))
 #endif
 
+/* Define a variable f that holds the value of field f of struct devid
+ * based at address m.
+ */
+#define DEF_FIELD(m, devid, f) \
+	typeof(((struct devid *)0)->f) f = TO_NATIVE(*(typeof(f) *)((m) + OFF_##devid##_##f))
+/* Define a variable f that holds the address of field f of struct devid
+ * based at address m.  Due to the way typeof works, for a field of type
+ * T[N] the variable has type T(*)[N], _not_ T*.
+ */
+#define DEF_FIELD_ADDR(m, devid, f) \
+	typeof(((struct devid *)0)->f) *f = ((m) + OFF_##devid##_##f)
+
 /* Add a table entry.  We test function type matches while we're here. */
 #define ADD_TO_DEVTABLE(device_id, type, function) \
 	static struct devtable __cat(devtable,__LINE__) = {	\
 		device_id + 0*sizeof((function)((const char *)NULL,	\
-						(type *)NULL,		\
+						(void *)NULL,		\
 						(char *)NULL)),		\
-		sizeof(type), (function) };				\
+		SIZE_##type, (function) };				\
 	static struct devtable *SECTION(__devtable) __used \
 		__cat(devtable_ptr,__LINE__) = &__cat(devtable,__LINE__)
 
@@ -116,7 +129,6 @@ static inline void add_wildcard(char *str)
 		strcat(str + len, "*");
 }
 
-unsigned int cross_build = 0;
 /**
  * Check that sizeof(device_id type) are consistent with size of section
  * in .o file. If in-consistent then userspace and kernel does not agree
@@ -131,8 +143,6 @@ static void device_id_check(const char *modname, const char *device_id,
 	int i;
 
 	if (size % id_size || size < id_size) {
-		if (cross_build != 0)
-			return;
 		fatal("%s: sizeof(struct %s_device_id)=%lu is not a modulo "
 		      "of the size of section __mod_%s_device_table=%lu.\n"
 		      "Fix definition of struct %s_device_id "
@@ -157,17 +167,28 @@ static void device_id_check(const char *modname, const char *device_id,
 
 /* USB is special because the bcdDevice can be matched against a numeric range */
 /* Looks like "usb:vNpNdNdcNdscNdpNicNiscNipN" */
-static void do_usb_entry(struct usb_device_id *id,
+static void do_usb_entry(void *symval,
 			 unsigned int bcdDevice_initial, int bcdDevice_initial_digits,
 			 unsigned char range_lo, unsigned char range_hi,
 			 unsigned char max, struct module *mod)
 {
 	char alias[500];
+	DEF_FIELD(symval, usb_device_id, match_flags);
+	DEF_FIELD(symval, usb_device_id, idVendor);
+	DEF_FIELD(symval, usb_device_id, idProduct);
+	DEF_FIELD(symval, usb_device_id, bcdDevice_lo);
+	DEF_FIELD(symval, usb_device_id, bDeviceClass);
+	DEF_FIELD(symval, usb_device_id, bDeviceSubClass);
+	DEF_FIELD(symval, usb_device_id, bDeviceProtocol);
+	DEF_FIELD(symval, usb_device_id, bInterfaceClass);
+	DEF_FIELD(symval, usb_device_id, bInterfaceSubClass);
+	DEF_FIELD(symval, usb_device_id, bInterfaceProtocol);
+
 	strcpy(alias, "usb:");
-	ADD(alias, "v", id->match_flags&USB_DEVICE_ID_MATCH_VENDOR,
-	    id->idVendor);
-	ADD(alias, "p", id->match_flags&USB_DEVICE_ID_MATCH_PRODUCT,
-	    id->idProduct);
+	ADD(alias, "v", match_flags&USB_DEVICE_ID_MATCH_VENDOR,
+	    idVendor);
+	ADD(alias, "p", match_flags&USB_DEVICE_ID_MATCH_PRODUCT,
+	    idProduct);
 
 	strcat(alias, "d");
 	if (bcdDevice_initial_digits)
@@ -190,26 +211,21 @@ static void do_usb_entry(struct usb_device_id *id,
 				range_lo);
 		}
 	}
-	if (bcdDevice_initial_digits < (sizeof(id->bcdDevice_lo) * 2 - 1))
+	if (bcdDevice_initial_digits < (sizeof(bcdDevice_lo) * 2 - 1))
 		strcat(alias, "*");
 
-	ADD(alias, "dc", id->match_flags&USB_DEVICE_ID_MATCH_DEV_CLASS,
-	    id->bDeviceClass);
-	ADD(alias, "dsc",
-	    id->match_flags&USB_DEVICE_ID_MATCH_DEV_SUBCLASS,
-	    id->bDeviceSubClass);
-	ADD(alias, "dp",
-	    id->match_flags&USB_DEVICE_ID_MATCH_DEV_PROTOCOL,
-	    id->bDeviceProtocol);
-	ADD(alias, "ic",
-	    id->match_flags&USB_DEVICE_ID_MATCH_INT_CLASS,
-	    id->bInterfaceClass);
-	ADD(alias, "isc",
-	    id->match_flags&USB_DEVICE_ID_MATCH_INT_SUBCLASS,
-	    id->bInterfaceSubClass);
-	ADD(alias, "ip",
-	    id->match_flags&USB_DEVICE_ID_MATCH_INT_PROTOCOL,
-	    id->bInterfaceProtocol);
+	ADD(alias, "dc", match_flags&USB_DEVICE_ID_MATCH_DEV_CLASS,
+	    bDeviceClass);
+	ADD(alias, "dsc", match_flags&USB_DEVICE_ID_MATCH_DEV_SUBCLASS,
+	    bDeviceSubClass);
+	ADD(alias, "dp", match_flags&USB_DEVICE_ID_MATCH_DEV_PROTOCOL,
+	    bDeviceProtocol);
+	ADD(alias, "ic", match_flags&USB_DEVICE_ID_MATCH_INT_CLASS,
+	    bInterfaceClass);
+	ADD(alias, "isc", match_flags&USB_DEVICE_ID_MATCH_INT_SUBCLASS,
+	    bInterfaceSubClass);
+	ADD(alias, "ip", match_flags&USB_DEVICE_ID_MATCH_INT_PROTOCOL,
+	    bInterfaceProtocol);
 
 	add_wildcard(alias);
 	buf_printf(&mod->dev_table_buf,
@@ -255,24 +271,28 @@ static unsigned int incbcd(unsigned int *bcd,
 	return init;
 }
 
-static void do_usb_entry_multi(struct usb_device_id *id, struct module *mod)
+static void do_usb_entry_multi(void *symval, struct module *mod)
 {
 	unsigned int devlo, devhi;
 	unsigned char chi, clo, max;
 	int ndigits;
 
-	id->match_flags = TO_NATIVE(id->match_flags);
-	id->idVendor = TO_NATIVE(id->idVendor);
-	id->idProduct = TO_NATIVE(id->idProduct);
+	DEF_FIELD(symval, usb_device_id, match_flags);
+	DEF_FIELD(symval, usb_device_id, idVendor);
+	DEF_FIELD(symval, usb_device_id, idProduct);
+	DEF_FIELD(symval, usb_device_id, bcdDevice_lo);
+	DEF_FIELD(symval, usb_device_id, bcdDevice_hi);
+	DEF_FIELD(symval, usb_device_id, bDeviceClass);
+	DEF_FIELD(symval, usb_device_id, bInterfaceClass);
 
-	devlo = id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO ?
-		TO_NATIVE(id->bcdDevice_lo) : 0x0U;
-	devhi = id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI ?
-		TO_NATIVE(id->bcdDevice_hi) : ~0x0U;
+	devlo = match_flags & USB_DEVICE_ID_MATCH_DEV_LO ?
+		bcdDevice_lo : 0x0U;
+	devhi = match_flags & USB_DEVICE_ID_MATCH_DEV_HI ?
+		bcdDevice_hi : ~0x0U;
 
 	/* Figure out if this entry is in bcd or hex format */
 	max = 0x9; /* Default to decimal format */
-	for (ndigits = 0 ; ndigits < sizeof(id->bcdDevice_lo) * 2 ; ndigits++) {
+	for (ndigits = 0 ; ndigits < sizeof(bcdDevice_lo) * 2 ; ndigits++) {
 		clo = (devlo >> (ndigits << 2)) & 0xf;
 		chi = ((devhi > 0x9999 ? 0x9999 : devhi) >> (ndigits << 2)) & 0xf;
 		if (clo > max || chi > max) {
@@ -285,11 +305,11 @@ static void do_usb_entry_multi(struct usb_device_id *id, struct module *mod)
 	 * Some modules (visor) have empty slots as placeholder for
 	 * run-time specification that results in catch-all alias
 	 */
-	if (!(id->idVendor | id->idProduct | id->bDeviceClass | id->bInterfaceClass))
+	if (!(idVendor | idProduct | bDeviceClass | bInterfaceClass))
 		return;
 
 	/* Convert numeric bcdDevice range into fnmatch-able pattern(s) */
-	for (ndigits = sizeof(id->bcdDevice_lo) * 2 - 1; devlo <= devhi; ndigits--) {
+	for (ndigits = sizeof(bcdDevice_lo) * 2 - 1; devlo <= devhi; ndigits--) {
 		clo = devlo & 0xf;
 		chi = devhi & 0xf;
 		if (chi > max)	/* If we are in bcd mode, truncate if necessary */
@@ -298,20 +318,20 @@ static void do_usb_entry_multi(struct usb_device_id *id, struct module *mod)
 		devhi >>= 4;
 
 		if (devlo == devhi || !ndigits) {
-			do_usb_entry(id, devlo, ndigits, clo, chi, max, mod);
+			do_usb_entry(symval, devlo, ndigits, clo, chi, max, mod);
 			break;
 		}
 
 		if (clo > 0x0)
-			do_usb_entry(id,
+			do_usb_entry(symval,
 				     incbcd(&devlo, 1, max,
-					    sizeof(id->bcdDevice_lo) * 2),
+					    sizeof(bcdDevice_lo) * 2),
 				     ndigits, clo, max, max, mod);
 
 		if (chi < max)
-			do_usb_entry(id,
+			do_usb_entry(symval,
 				     incbcd(&devhi, -1, max,
-					    sizeof(id->bcdDevice_lo) * 2),
+					    sizeof(bcdDevice_lo) * 2),
 				     ndigits, 0x0, chi, max, mod);
 	}
 }
@@ -320,7 +340,7 @@ static void do_usb_table(void *symval, unsigned long size,
 			 struct module *mod)
 {
 	unsigned int i;
-	const unsigned long id_size = sizeof(struct usb_device_id);
+	const unsigned long id_size = SIZE_usb_device_id;
 
 	device_id_check(mod->name, "usb", size, id_size, symval);
 
@@ -333,81 +353,81 @@ static void do_usb_table(void *symval, unsigned long size,
 
 /* Looks like: hid:bNvNpN */
 static int do_hid_entry(const char *filename,
-			     struct hid_device_id *id, char *alias)
+			     void *symval, char *alias)
 {
-	id->bus = TO_NATIVE(id->bus);
-	id->group = TO_NATIVE(id->group);
-	id->vendor = TO_NATIVE(id->vendor);
-	id->product = TO_NATIVE(id->product);
+	DEF_FIELD(symval, hid_device_id, bus);
+	DEF_FIELD(symval, hid_device_id, group);
+	DEF_FIELD(symval, hid_device_id, vendor);
+	DEF_FIELD(symval, hid_device_id, product);
 
 	sprintf(alias, "hid:");
-	ADD(alias, "b", id->bus != HID_BUS_ANY, id->bus);
-	ADD(alias, "g", id->group != HID_GROUP_ANY, id->group);
-	ADD(alias, "v", id->vendor != HID_ANY_ID, id->vendor);
-	ADD(alias, "p", id->product != HID_ANY_ID, id->product);
+	ADD(alias, "b", bus != HID_BUS_ANY, bus);
+	ADD(alias, "g", group != HID_GROUP_ANY, group);
+	ADD(alias, "v", vendor != HID_ANY_ID, vendor);
+	ADD(alias, "p", product != HID_ANY_ID, product);
 
 	return 1;
 }
-ADD_TO_DEVTABLE("hid", struct hid_device_id, do_hid_entry);
+ADD_TO_DEVTABLE("hid", hid_device_id, do_hid_entry);
 
 /* Looks like: ieee1394:venNmoNspNverN */
 static int do_ieee1394_entry(const char *filename,
-			     struct ieee1394_device_id *id, char *alias)
+			     void *symval, char *alias)
 {
-	id->match_flags = TO_NATIVE(id->match_flags);
-	id->vendor_id = TO_NATIVE(id->vendor_id);
-	id->model_id = TO_NATIVE(id->model_id);
-	id->specifier_id = TO_NATIVE(id->specifier_id);
-	id->version = TO_NATIVE(id->version);
+	DEF_FIELD(symval, ieee1394_device_id, match_flags);
+	DEF_FIELD(symval, ieee1394_device_id, vendor_id);
+	DEF_FIELD(symval, ieee1394_device_id, model_id);
+	DEF_FIELD(symval, ieee1394_device_id, specifier_id);
+	DEF_FIELD(symval, ieee1394_device_id, version);
 
 	strcpy(alias, "ieee1394:");
-	ADD(alias, "ven", id->match_flags & IEEE1394_MATCH_VENDOR_ID,
-	    id->vendor_id);
-	ADD(alias, "mo", id->match_flags & IEEE1394_MATCH_MODEL_ID,
-	    id->model_id);
-	ADD(alias, "sp", id->match_flags & IEEE1394_MATCH_SPECIFIER_ID,
-	    id->specifier_id);
-	ADD(alias, "ver", id->match_flags & IEEE1394_MATCH_VERSION,
-	    id->version);
+	ADD(alias, "ven", match_flags & IEEE1394_MATCH_VENDOR_ID,
+	    vendor_id);
+	ADD(alias, "mo", match_flags & IEEE1394_MATCH_MODEL_ID,
+	    model_id);
+	ADD(alias, "sp", match_flags & IEEE1394_MATCH_SPECIFIER_ID,
+	    specifier_id);
+	ADD(alias, "ver", match_flags & IEEE1394_MATCH_VERSION,
+	    version);
 
 	add_wildcard(alias);
 	return 1;
 }
-ADD_TO_DEVTABLE("ieee1394", struct ieee1394_device_id, do_ieee1394_entry);
+ADD_TO_DEVTABLE("ieee1394", ieee1394_device_id, do_ieee1394_entry);
 
 /* Looks like: pci:vNdNsvNsdNbcNscNiN. */
 static int do_pci_entry(const char *filename,
-			struct pci_device_id *id, char *alias)
+			void *symval, char *alias)
 {
 	/* Class field can be divided into these three. */
 	unsigned char baseclass, subclass, interface,
 		baseclass_mask, subclass_mask, interface_mask;
 
-	id->vendor = TO_NATIVE(id->vendor);
-	id->device = TO_NATIVE(id->device);
-	id->subvendor = TO_NATIVE(id->subvendor);
-	id->subdevice = TO_NATIVE(id->subdevice);
-	id->class = TO_NATIVE(id->class);
-	id->class_mask = TO_NATIVE(id->class_mask);
+	DEF_FIELD(symval, pci_device_id, vendor);
+	DEF_FIELD(symval, pci_device_id, device);
+	DEF_FIELD(symval, pci_device_id, subvendor);
+	DEF_FIELD(symval, pci_device_id, subdevice);
+	DEF_FIELD(symval, pci_device_id, class);
+	DEF_FIELD(symval, pci_device_id, class_mask);
 
 	strcpy(alias, "pci:");
-	ADD(alias, "v", id->vendor != PCI_ANY_ID, id->vendor);
-	ADD(alias, "d", id->device != PCI_ANY_ID, id->device);
-	ADD(alias, "sv", id->subvendor != PCI_ANY_ID, id->subvendor);
-	ADD(alias, "sd", id->subdevice != PCI_ANY_ID, id->subdevice);
-
-	baseclass = (id->class) >> 16;
-	baseclass_mask = (id->class_mask) >> 16;
-	subclass = (id->class) >> 8;
-	subclass_mask = (id->class_mask) >> 8;
-	interface = id->class;
-	interface_mask = id->class_mask;
+	ADD(alias, "v", vendor != PCI_ANY_ID, vendor);
+	ADD(alias, "d", device != PCI_ANY_ID, device);
+	ADD(alias, "sv", subvendor != PCI_ANY_ID, subvendor);
+	ADD(alias, "sd", subdevice != PCI_ANY_ID, subdevice);
+
+	baseclass = (class) >> 16;
+	baseclass_mask = (class_mask) >> 16;
+	subclass = (class) >> 8;
+	subclass_mask = (class_mask) >> 8;
+	interface = class;
+	interface_mask = class_mask;
 
 	if ((baseclass_mask != 0 && baseclass_mask != 0xFF)
 	    || (subclass_mask != 0 && subclass_mask != 0xFF)
 	    || (interface_mask != 0 && interface_mask != 0xFF)) {
 		warn("Can't handle masks in %s:%04X\n",
-		     filename, id->class_mask);
+		     filename, class_mask);
 		return 0;
 	}
 
@@ -417,101 +437,105 @@ static int do_pci_entry(const char *filename,
 	add_wildcard(alias);
 	return 1;
 }
-ADD_TO_DEVTABLE("pci", struct pci_device_id, do_pci_entry);
+ADD_TO_DEVTABLE("pci", pci_device_id, do_pci_entry);
 
 /* looks like: "ccw:tNmNdtNdmN" */
 static int do_ccw_entry(const char *filename,
-			struct ccw_device_id *id, char *alias)
+			void *symval, char *alias)
 {
-	id->match_flags = TO_NATIVE(id->match_flags);
-	id->cu_type = TO_NATIVE(id->cu_type);
-	id->cu_model = TO_NATIVE(id->cu_model);
-	id->dev_type = TO_NATIVE(id->dev_type);
-	id->dev_model = TO_NATIVE(id->dev_model);
+	DEF_FIELD(symval, ccw_device_id, match_flags);
+	DEF_FIELD(symval, ccw_device_id, cu_type);
+	DEF_FIELD(symval, ccw_device_id, cu_model);
+	DEF_FIELD(symval, ccw_device_id, dev_type);
+	DEF_FIELD(symval, ccw_device_id, dev_model);
 
 	strcpy(alias, "ccw:");
-	ADD(alias, "t", id->match_flags&CCW_DEVICE_ID_MATCH_CU_TYPE,
-	    id->cu_type);
-	ADD(alias, "m", id->match_flags&CCW_DEVICE_ID_MATCH_CU_MODEL,
-	    id->cu_model);
-	ADD(alias, "dt", id->match_flags&CCW_DEVICE_ID_MATCH_DEVICE_TYPE,
-	    id->dev_type);
-	ADD(alias, "dm", id->match_flags&CCW_DEVICE_ID_MATCH_DEVICE_MODEL,
-	    id->dev_model);
+	ADD(alias, "t", match_flags&CCW_DEVICE_ID_MATCH_CU_TYPE,
+	    cu_type);
+	ADD(alias, "m", match_flags&CCW_DEVICE_ID_MATCH_CU_MODEL,
+	    cu_model);
+	ADD(alias, "dt", match_flags&CCW_DEVICE_ID_MATCH_DEVICE_TYPE,
+	    dev_type);
+	ADD(alias, "dm", match_flags&CCW_DEVICE_ID_MATCH_DEVICE_MODEL,
+	    dev_model);
 	add_wildcard(alias);
 	return 1;
 }
-ADD_TO_DEVTABLE("ccw", struct ccw_device_id, do_ccw_entry);
+ADD_TO_DEVTABLE("ccw", ccw_device_id, do_ccw_entry);
 
 /* looks like: "ap:tN" */
 static int do_ap_entry(const char *filename,
-		       struct ap_device_id *id, char *alias)
+		       void *symval, char *alias)
 {
-	sprintf(alias, "ap:t%02X*", id->dev_type);
+	DEF_FIELD(symval, ap_device_id, dev_type);
+
+	sprintf(alias, "ap:t%02X*", dev_type);
 	return 1;
 }
-ADD_TO_DEVTABLE("ap", struct ap_device_id, do_ap_entry);
+ADD_TO_DEVTABLE("ap", ap_device_id, do_ap_entry);
 
 /* looks like: "css:tN" */
 static int do_css_entry(const char *filename,
-			struct css_device_id *id, char *alias)
+			void *symval, char *alias)
 {
-	sprintf(alias, "css:t%01X", id->type);
+	DEF_FIELD(symval, css_device_id, type);
+
+	sprintf(alias, "css:t%01X", type);
 	return 1;
 }
-ADD_TO_DEVTABLE("css", struct css_device_id, do_css_entry);
+ADD_TO_DEVTABLE("css", css_device_id, do_css_entry);
 
 /* Looks like: "serio:tyNprNidNexN" */
 static int do_serio_entry(const char *filename,
-			  struct serio_device_id *id, char *alias)
+			  void *symval, char *alias)
 {
-	id->type = TO_NATIVE(id->type);
-	id->proto = TO_NATIVE(id->proto);
-	id->id = TO_NATIVE(id->id);
-	id->extra = TO_NATIVE(id->extra);
+	DEF_FIELD(symval, serio_device_id, type);
+	DEF_FIELD(symval, serio_device_id, proto);
+	DEF_FIELD(symval, serio_device_id, id);
+	DEF_FIELD(symval, serio_device_id, extra);
 
 	strcpy(alias, "serio:");
-	ADD(alias, "ty", id->type != SERIO_ANY, id->type);
-	ADD(alias, "pr", id->proto != SERIO_ANY, id->proto);
-	ADD(alias, "id", id->id != SERIO_ANY, id->id);
-	ADD(alias, "ex", id->extra != SERIO_ANY, id->extra);
+	ADD(alias, "ty", type != SERIO_ANY, type);
+	ADD(alias, "pr", proto != SERIO_ANY, proto);
+	ADD(alias, "id", id != SERIO_ANY, id);
+	ADD(alias, "ex", extra != SERIO_ANY, extra);
 
 	add_wildcard(alias);
 	return 1;
 }
-ADD_TO_DEVTABLE("serio", struct serio_device_id, do_serio_entry);
+ADD_TO_DEVTABLE("serio", serio_device_id, do_serio_entry);
 
 /* looks like: "acpi:ACPI0003 or acpi:PNP0C0B" or "acpi:LNXVIDEO" */
 static int do_acpi_entry(const char *filename,
-			struct acpi_device_id *id, char *alias)
+			void *symval, char *alias)
 {
-	sprintf(alias, "acpi*:%s:*", id->id);
+	DEF_FIELD_ADDR(symval, acpi_device_id, id);
+	sprintf(alias, "acpi*:%s:*", *id);
 	return 1;
 }
-ADD_TO_DEVTABLE("acpi", struct acpi_device_id, do_acpi_entry);
+ADD_TO_DEVTABLE("acpi", acpi_device_id, do_acpi_entry);
 
 /* looks like: "pnp:dD" */
 static void do_pnp_device_entry(void *symval, unsigned long size,
 				struct module *mod)
 {
-	const unsigned long id_size = sizeof(struct pnp_device_id);
+	const unsigned long id_size = SIZE_pnp_device_id;
 	const unsigned int count = (size / id_size)-1;
-	const struct pnp_device_id *devs = symval;
 	unsigned int i;
 
 	device_id_check(mod->name, "pnp", size, id_size, symval);
 
 	for (i = 0; i < count; i++) {
-		const char *id = (char *)devs[i].id;
-		char acpi_id[sizeof(devs[0].id)];
+		DEF_FIELD_ADDR(symval + i*id_size, pnp_device_id, id);
+		char acpi_id[sizeof(*id)];
 		int j;
 
 		buf_printf(&mod->dev_table_buf,
-			   "MODULE_ALIAS(\"pnp:d%s*\");\n", id);
+			   "MODULE_ALIAS(\"pnp:d%s*\");\n", *id);
 
 		/* fix broken pnp bus lowercasing */
 		for (j = 0; j < sizeof(acpi_id); j++)
-			acpi_id[j] = toupper(id[j]);
+			acpi_id[j] = toupper((*id)[j]);
 		buf_printf(&mod->dev_table_buf,
 			   "MODULE_ALIAS(\"acpi*:%s:*\");\n", acpi_id);
 	}
@@ -521,19 +545,18 @@ static void do_pnp_device_entry(void *symval, unsigned long size,
 static void do_pnp_card_entries(void *symval, unsigned long size,
 				struct module *mod)
 {
-	const unsigned long id_size = sizeof(struct pnp_card_device_id);
+	const unsigned long id_size = SIZE_pnp_card_device_id;
 	const unsigned int count = (size / id_size)-1;
-	const struct pnp_card_device_id *cards = symval;
 	unsigned int i;
 
 	device_id_check(mod->name, "pnp", size, id_size, symval);
 
 	for (i = 0; i < count; i++) {
 		unsigned int j;
-		const struct pnp_card_device_id *card = &cards[i];
+		DEF_FIELD_ADDR(symval + i*id_size, pnp_card_device_id, devs);
 
 		for (j = 0; j < PNP_MAX_DEVICES; j++) {
-			const char *id = (char *)card->devs[j].id;
+			const char *id = (char *)(*devs)[j].id;
 			int i2, j2;
 			int dup = 0;
 
@@ -542,10 +565,10 @@ static void do_pnp_card_entries(void *symval, unsigned long size,
 
 			/* find duplicate, already added value */
 			for (i2 = 0; i2 < i && !dup; i2++) {
-				const struct pnp_card_device_id *card2 = &cards[i2];
+				DEF_FIELD_ADDR(symval + i2*id_size, pnp_card_device_id, devs);
 
 				for (j2 = 0; j2 < PNP_MAX_DEVICES; j2++) {
-					const char *id2 = (char *)card2->devs[j2].id;
+					const char *id2 = (char *)(*devs)[j2].id;
 
 					if (!id2[0])
 						break;
@@ -559,7 +582,7 @@ static void do_pnp_card_entries(void *symval, unsigned long size,
 
 			/* add an individual alias for every device entry */
 			if (!dup) {
-				char acpi_id[sizeof(card->devs[0].id)];
+				char acpi_id[PNP_ID_LEN];
 				int k;
 
 				buf_printf(&mod->dev_table_buf,
@@ -577,54 +600,58 @@ static void do_pnp_card_entries(void *symval, unsigned long size,
 
 /* Looks like: pcmcia:mNcNfNfnNpfnNvaNvbNvcNvdN. */
 static int do_pcmcia_entry(const char *filename,
-			   struct pcmcia_device_id *id, char *alias)
+			   void *symval, char *alias)
 {
 	unsigned int i;
-
-	id->match_flags = TO_NATIVE(id->match_flags);
-	id->manf_id = TO_NATIVE(id->manf_id);
-	id->card_id = TO_NATIVE(id->card_id);
-	id->func_id = TO_NATIVE(id->func_id);
-	id->function = TO_NATIVE(id->function);
-	id->device_no = TO_NATIVE(id->device_no);
+	DEF_FIELD(symval, pcmcia_device_id, match_flags);
+	DEF_FIELD(symval, pcmcia_device_id, manf_id);
+	DEF_FIELD(symval, pcmcia_device_id, card_id);
+	DEF_FIELD(symval, pcmcia_device_id, func_id);
+	DEF_FIELD(symval, pcmcia_device_id, function);
+	DEF_FIELD(symval, pcmcia_device_id, device_no);
+	DEF_FIELD_ADDR(symval, pcmcia_device_id, prod_id_hash);
 
 	for (i=0; i<4; i++) {
-		id->prod_id_hash[i] = TO_NATIVE(id->prod_id_hash[i]);
-       }
-
-       strcpy(alias, "pcmcia:");
-       ADD(alias, "m", id->match_flags & PCMCIA_DEV_ID_MATCH_MANF_ID,
-	   id->manf_id);
-       ADD(alias, "c", id->match_flags & PCMCIA_DEV_ID_MATCH_CARD_ID,
-	   id->card_id);
-       ADD(alias, "f", id->match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID,
-	   id->func_id);
-       ADD(alias, "fn", id->match_flags & PCMCIA_DEV_ID_MATCH_FUNCTION,
-	   id->function);
-       ADD(alias, "pfn", id->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO,
-	   id->device_no);
-       ADD(alias, "pa", id->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID1, id->prod_id_hash[0]);
-       ADD(alias, "pb", id->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID2, id->prod_id_hash[1]);
-       ADD(alias, "pc", id->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID3, id->prod_id_hash[2]);
-       ADD(alias, "pd", id->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID4, id->prod_id_hash[3]);
+		(*prod_id_hash)[i] = TO_NATIVE((*prod_id_hash)[i]);
+	}
+
+	strcpy(alias, "pcmcia:");
+	ADD(alias, "m", match_flags & PCMCIA_DEV_ID_MATCH_MANF_ID,
+	    manf_id);
+	ADD(alias, "c", match_flags & PCMCIA_DEV_ID_MATCH_CARD_ID,
+	    card_id);
+	ADD(alias, "f", match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID,
+	    func_id);
+	ADD(alias, "fn", match_flags & PCMCIA_DEV_ID_MATCH_FUNCTION,
+	    function);
+	ADD(alias, "pfn", match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO,
+	    device_no);
+	ADD(alias, "pa", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID1, (*prod_id_hash)[0]);
+	ADD(alias, "pb", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID2, (*prod_id_hash)[1]);
+	ADD(alias, "pc", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID3, (*prod_id_hash)[2]);
+	ADD(alias, "pd", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID4, (*prod_id_hash)[3]);
 
 	add_wildcard(alias);
-       return 1;
+	return 1;
 }
-ADD_TO_DEVTABLE("pcmcia", struct pcmcia_device_id, do_pcmcia_entry);
+ADD_TO_DEVTABLE("pcmcia", pcmcia_device_id, do_pcmcia_entry);
 
-static int do_of_entry (const char *filename, struct of_device_id *of, char *alias)
+static int do_of_entry (const char *filename, void *symval, char *alias)
 {
     int len;
     char *tmp;
+    DEF_FIELD_ADDR(symval, of_device_id, name);
+    DEF_FIELD_ADDR(symval, of_device_id, type);
+    DEF_FIELD_ADDR(symval, of_device_id, compatible);
+
     len = sprintf (alias, "of:N%sT%s",
-                    of->name[0] ? of->name : "*",
-                    of->type[0] ? of->type : "*");
+                    (*name)[0] ? *name : "*",
+                    (*type)[0] ? *type : "*");
 
-    if (of->compatible[0])
+    if (compatible[0])
         sprintf (&alias[len], "%sC%s",
-                     of->type[0] ? "*" : "",
-                     of->compatible);
+                     (*type)[0] ? "*" : "",
+                     *compatible);
 
     /* Replace all whitespace with underscores */
     for (tmp = alias; tmp && *tmp; tmp++)
@@ -634,15 +661,17 @@ static int do_of_entry (const char *filename, struct of_device_id *of, char *ali
     add_wildcard(alias);
     return 1;
 }
-ADD_TO_DEVTABLE("of", struct of_device_id, do_of_entry);
+ADD_TO_DEVTABLE("of", of_device_id, do_of_entry);
 
-static int do_vio_entry(const char *filename, struct vio_device_id *vio,
+static int do_vio_entry(const char *filename, void *symval,
 		char *alias)
 {
 	char *tmp;
+	DEF_FIELD_ADDR(symval, vio_device_id, type);
+	DEF_FIELD_ADDR(symval, vio_device_id, compat);
 
-	sprintf(alias, "vio:T%sS%s", vio->type[0] ? vio->type : "*",
-			vio->compat[0] ? vio->compat : "*");
+	sprintf(alias, "vio:T%sS%s", (*type)[0] ? *type : "*",
+			(*compat)[0] ? *compat : "*");
 
 	/* Replace all whitespace with underscores */
 	for (tmp = alias; tmp && *tmp; tmp++)
@@ -652,7 +681,7 @@ static int do_vio_entry(const char *filename, struct vio_device_id *vio,
 	add_wildcard(alias);
 	return 1;
 }
-ADD_TO_DEVTABLE("vio", struct vio_device_id, do_vio_entry);
+ADD_TO_DEVTABLE("vio", vio_device_id, do_vio_entry);
 
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
 
@@ -661,154 +690,172 @@ static void do_input(char *alias,
 {
 	unsigned int i;
 
+	for (i = min / BITS_PER_LONG; i < max / BITS_PER_LONG + 1; i++)
+		arr[i] = TO_NATIVE(arr[i]);
 	for (i = min; i < max; i++)
 		if (arr[i / BITS_PER_LONG] & (1L << (i%BITS_PER_LONG)))
 			sprintf(alias + strlen(alias), "%X,*", i);
 }
 
 /* input:b0v0p0e0-eXkXrXaXmXlXsXfXwX where X is comma-separated %02X. */
-static int do_input_entry(const char *filename, struct input_device_id *id,
+static int do_input_entry(const char *filename, void *symval,
 			  char *alias)
 {
+	DEF_FIELD(symval, input_device_id, flags);
+	DEF_FIELD(symval, input_device_id, bustype);
+	DEF_FIELD(symval, input_device_id, vendor);
+	DEF_FIELD(symval, input_device_id, product);
+	DEF_FIELD(symval, input_device_id, version);
+	DEF_FIELD_ADDR(symval, input_device_id, evbit);
+	DEF_FIELD_ADDR(symval, input_device_id, keybit);
+	DEF_FIELD_ADDR(symval, input_device_id, relbit);
+	DEF_FIELD_ADDR(symval, input_device_id, absbit);
+	DEF_FIELD_ADDR(symval, input_device_id, mscbit);
+	DEF_FIELD_ADDR(symval, input_device_id, ledbit);
+	DEF_FIELD_ADDR(symval, input_device_id, sndbit);
+	DEF_FIELD_ADDR(symval, input_device_id, ffbit);
+	DEF_FIELD_ADDR(symval, input_device_id, swbit);
+
 	sprintf(alias, "input:");
 
-	ADD(alias, "b", id->flags & INPUT_DEVICE_ID_MATCH_BUS, id->bustype);
-	ADD(alias, "v", id->flags & INPUT_DEVICE_ID_MATCH_VENDOR, id->vendor);
-	ADD(alias, "p", id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT, id->product);
-	ADD(alias, "e", id->flags & INPUT_DEVICE_ID_MATCH_VERSION, id->version);
+	ADD(alias, "b", flags & INPUT_DEVICE_ID_MATCH_BUS, bustype);
+	ADD(alias, "v", flags & INPUT_DEVICE_ID_MATCH_VENDOR, vendor);
+	ADD(alias, "p", flags & INPUT_DEVICE_ID_MATCH_PRODUCT, product);
+	ADD(alias, "e", flags & INPUT_DEVICE_ID_MATCH_VERSION, version);
 
 	sprintf(alias + strlen(alias), "-e*");
-	if (id->flags & INPUT_DEVICE_ID_MATCH_EVBIT)
-		do_input(alias, id->evbit, 0, INPUT_DEVICE_ID_EV_MAX);
+	if (flags & INPUT_DEVICE_ID_MATCH_EVBIT)
+		do_input(alias, *evbit, 0, INPUT_DEVICE_ID_EV_MAX);
 	sprintf(alias + strlen(alias), "k*");
-	if (id->flags & INPUT_DEVICE_ID_MATCH_KEYBIT)
-		do_input(alias, id->keybit,
+	if (flags & INPUT_DEVICE_ID_MATCH_KEYBIT)
+		do_input(alias, *keybit,
 			 INPUT_DEVICE_ID_KEY_MIN_INTERESTING,
 			 INPUT_DEVICE_ID_KEY_MAX);
 	sprintf(alias + strlen(alias), "r*");
-	if (id->flags & INPUT_DEVICE_ID_MATCH_RELBIT)
-		do_input(alias, id->relbit, 0, INPUT_DEVICE_ID_REL_MAX);
+	if (flags & INPUT_DEVICE_ID_MATCH_RELBIT)
+		do_input(alias, *relbit, 0, INPUT_DEVICE_ID_REL_MAX);
 	sprintf(alias + strlen(alias), "a*");
-	if (id->flags & INPUT_DEVICE_ID_MATCH_ABSBIT)
-		do_input(alias, id->absbit, 0, INPUT_DEVICE_ID_ABS_MAX);
+	if (flags & INPUT_DEVICE_ID_MATCH_ABSBIT)
+		do_input(alias, *absbit, 0, INPUT_DEVICE_ID_ABS_MAX);
 	sprintf(alias + strlen(alias), "m*");
-	if (id->flags & INPUT_DEVICE_ID_MATCH_MSCIT)
-		do_input(alias, id->mscbit, 0, INPUT_DEVICE_ID_MSC_MAX);
+	if (flags & INPUT_DEVICE_ID_MATCH_MSCIT)
+		do_input(alias, *mscbit, 0, INPUT_DEVICE_ID_MSC_MAX);
 	sprintf(alias + strlen(alias), "l*");
-	if (id->flags & INPUT_DEVICE_ID_MATCH_LEDBIT)
-		do_input(alias, id->ledbit, 0, INPUT_DEVICE_ID_LED_MAX);
+	if (flags & INPUT_DEVICE_ID_MATCH_LEDBIT)
+		do_input(alias, *ledbit, 0, INPUT_DEVICE_ID_LED_MAX);
 	sprintf(alias + strlen(alias), "s*");
-	if (id->flags & INPUT_DEVICE_ID_MATCH_SNDBIT)
-		do_input(alias, id->sndbit, 0, INPUT_DEVICE_ID_SND_MAX);
+	if (flags & INPUT_DEVICE_ID_MATCH_SNDBIT)
+		do_input(alias, *sndbit, 0, INPUT_DEVICE_ID_SND_MAX);
 	sprintf(alias + strlen(alias), "f*");
-	if (id->flags & INPUT_DEVICE_ID_MATCH_FFBIT)
-		do_input(alias, id->ffbit, 0, INPUT_DEVICE_ID_FF_MAX);
+	if (flags & INPUT_DEVICE_ID_MATCH_FFBIT)
+		do_input(alias, *ffbit, 0, INPUT_DEVICE_ID_FF_MAX);
 	sprintf(alias + strlen(alias), "w*");
-	if (id->flags & INPUT_DEVICE_ID_MATCH_SWBIT)
-		do_input(alias, id->swbit, 0, INPUT_DEVICE_ID_SW_MAX);
+	if (flags & INPUT_DEVICE_ID_MATCH_SWBIT)
+		do_input(alias, *swbit, 0, INPUT_DEVICE_ID_SW_MAX);
 	return 1;
 }
-ADD_TO_DEVTABLE("input", struct input_device_id, do_input_entry);
+ADD_TO_DEVTABLE("input", input_device_id, do_input_entry);
 
-static int do_eisa_entry(const char *filename, struct eisa_device_id *eisa,
+static int do_eisa_entry(const char *filename, void *symval,
 		char *alias)
 {
-	if (eisa->sig[0])
-		sprintf(alias, EISA_DEVICE_MODALIAS_FMT "*", eisa->sig);
+	DEF_FIELD_ADDR(symval, eisa_device_id, sig);
+	if (sig[0])
+		sprintf(alias, EISA_DEVICE_MODALIAS_FMT "*", *sig);
 	else
 		strcat(alias, "*");
 	return 1;
 }
-ADD_TO_DEVTABLE("eisa", struct eisa_device_id, do_eisa_entry);
+ADD_TO_DEVTABLE("eisa", eisa_device_id, do_eisa_entry);
 
 /* Looks like: parisc:tNhvNrevNsvN */
-static int do_parisc_entry(const char *filename, struct parisc_device_id *id,
+static int do_parisc_entry(const char *filename, void *symval,
 		char *alias)
 {
-	id->hw_type = TO_NATIVE(id->hw_type);
-	id->hversion = TO_NATIVE(id->hversion);
-	id->hversion_rev = TO_NATIVE(id->hversion_rev);
-	id->sversion = TO_NATIVE(id->sversion);
+	DEF_FIELD(symval, parisc_device_id, hw_type);
+	DEF_FIELD(symval, parisc_device_id, hversion);
+	DEF_FIELD(symval, parisc_device_id, hversion_rev);
+	DEF_FIELD(symval, parisc_device_id, sversion);
 
 	strcpy(alias, "parisc:");
-	ADD(alias, "t", id->hw_type != PA_HWTYPE_ANY_ID, id->hw_type);
-	ADD(alias, "hv", id->hversion != PA_HVERSION_ANY_ID, id->hversion);
-	ADD(alias, "rev", id->hversion_rev != PA_HVERSION_REV_ANY_ID, id->hversion_rev);
-	ADD(alias, "sv", id->sversion != PA_SVERSION_ANY_ID, id->sversion);
+	ADD(alias, "t", hw_type != PA_HWTYPE_ANY_ID, hw_type);
+	ADD(alias, "hv", hversion != PA_HVERSION_ANY_ID, hversion);
+	ADD(alias, "rev", hversion_rev != PA_HVERSION_REV_ANY_ID, hversion_rev);
+	ADD(alias, "sv", sversion != PA_SVERSION_ANY_ID, sversion);
 
 	add_wildcard(alias);
 	return 1;
 }
-ADD_TO_DEVTABLE("parisc", struct parisc_device_id, do_parisc_entry);
+ADD_TO_DEVTABLE("parisc", parisc_device_id, do_parisc_entry);
 
 /* Looks like: sdio:cNvNdN. */
 static int do_sdio_entry(const char *filename,
-			struct sdio_device_id *id, char *alias)
+			void *symval, char *alias)
 {
-	id->class = TO_NATIVE(id->class);
-	id->vendor = TO_NATIVE(id->vendor);
-	id->device = TO_NATIVE(id->device);
+	DEF_FIELD(symval, sdio_device_id, class);
+	DEF_FIELD(symval, sdio_device_id, vendor);
+	DEF_FIELD(symval, sdio_device_id, device);
 
 	strcpy(alias, "sdio:");
-	ADD(alias, "c", id->class != (__u8)SDIO_ANY_ID, id->class);
-	ADD(alias, "v", id->vendor != (__u16)SDIO_ANY_ID, id->vendor);
-	ADD(alias, "d", id->device != (__u16)SDIO_ANY_ID, id->device);
+	ADD(alias, "c", class != (__u8)SDIO_ANY_ID, class);
+	ADD(alias, "v", vendor != (__u16)SDIO_ANY_ID, vendor);
+	ADD(alias, "d", device != (__u16)SDIO_ANY_ID, device);
 	add_wildcard(alias);
 	return 1;
 }
-ADD_TO_DEVTABLE("sdio", struct sdio_device_id, do_sdio_entry);
+ADD_TO_DEVTABLE("sdio", sdio_device_id, do_sdio_entry);
 
 /* Looks like: ssb:vNidNrevN. */
 static int do_ssb_entry(const char *filename,
-			struct ssb_device_id *id, char *alias)
+			void *symval, char *alias)
 {
-	id->vendor = TO_NATIVE(id->vendor);
-	id->coreid = TO_NATIVE(id->coreid);
-	id->revision = TO_NATIVE(id->revision);
+	DEF_FIELD(symval, ssb_device_id, vendor);
+	DEF_FIELD(symval, ssb_device_id, coreid);
+	DEF_FIELD(symval, ssb_device_id, revision);
 
 	strcpy(alias, "ssb:");
-	ADD(alias, "v", id->vendor != SSB_ANY_VENDOR, id->vendor);
-	ADD(alias, "id", id->coreid != SSB_ANY_ID, id->coreid);
-	ADD(alias, "rev", id->revision != SSB_ANY_REV, id->revision);
+	ADD(alias, "v", vendor != SSB_ANY_VENDOR, vendor);
+	ADD(alias, "id", coreid != SSB_ANY_ID, coreid);
+	ADD(alias, "rev", revision != SSB_ANY_REV, revision);
 	add_wildcard(alias);
 	return 1;
 }
-ADD_TO_DEVTABLE("ssb", struct ssb_device_id, do_ssb_entry);
+ADD_TO_DEVTABLE("ssb", ssb_device_id, do_ssb_entry);
 
 /* Looks like: bcma:mNidNrevNclN. */
 static int do_bcma_entry(const char *filename,
-			 struct bcma_device_id *id, char *alias)
+			 void *symval, char *alias)
 {
-	id->manuf = TO_NATIVE(id->manuf);
-	id->id = TO_NATIVE(id->id);
-	id->rev = TO_NATIVE(id->rev);
-	id->class = TO_NATIVE(id->class);
+	DEF_FIELD(symval, bcma_device_id, manuf);
+	DEF_FIELD(symval, bcma_device_id, id);
+	DEF_FIELD(symval, bcma_device_id, rev);
+	DEF_FIELD(symval, bcma_device_id, class);
 
 	strcpy(alias, "bcma:");
-	ADD(alias, "m", id->manuf != BCMA_ANY_MANUF, id->manuf);
-	ADD(alias, "id", id->id != BCMA_ANY_ID, id->id);
-	ADD(alias, "rev", id->rev != BCMA_ANY_REV, id->rev);
-	ADD(alias, "cl", id->class != BCMA_ANY_CLASS, id->class);
+	ADD(alias, "m", manuf != BCMA_ANY_MANUF, manuf);
+	ADD(alias, "id", id != BCMA_ANY_ID, id);
+	ADD(alias, "rev", rev != BCMA_ANY_REV, rev);
+	ADD(alias, "cl", class != BCMA_ANY_CLASS, class);
 	add_wildcard(alias);
 	return 1;
 }
-ADD_TO_DEVTABLE("bcma", struct bcma_device_id, do_bcma_entry);
+ADD_TO_DEVTABLE("bcma", bcma_device_id, do_bcma_entry);
 
 /* Looks like: virtio:dNvN */
-static int do_virtio_entry(const char *filename, struct virtio_device_id *id,
+static int do_virtio_entry(const char *filename, void *symval,
 			   char *alias)
 {
-	id->device = TO_NATIVE(id->device);
-	id->vendor = TO_NATIVE(id->vendor);
+	DEF_FIELD(symval, virtio_device_id, device);
+	DEF_FIELD(symval, virtio_device_id, vendor);
 
 	strcpy(alias, "virtio:");
-	ADD(alias, "d", id->device != VIRTIO_DEV_ANY_ID, id->device);
-	ADD(alias, "v", id->vendor != VIRTIO_DEV_ANY_ID, id->vendor);
+	ADD(alias, "d", device != VIRTIO_DEV_ANY_ID, device);
+	ADD(alias, "v", vendor != VIRTIO_DEV_ANY_ID, vendor);
 
 	add_wildcard(alias);
 	return 1;
 }
-ADD_TO_DEVTABLE("virtio", struct virtio_device_id, do_virtio_entry);
+ADD_TO_DEVTABLE("virtio", virtio_device_id, do_virtio_entry);
 
 /*
  * Looks like: vmbus:guid
@@ -816,41 +863,44 @@ ADD_TO_DEVTABLE("virtio", struct virtio_device_id, do_virtio_entry);
  * in the name.
  */
 
-static int do_vmbus_entry(const char *filename, struct hv_vmbus_device_id *id,
+static int do_vmbus_entry(const char *filename, void *symval,
 			  char *alias)
 {
 	int i;
-	char guid_name[((sizeof(id->guid) + 1)) * 2];
+	DEF_FIELD_ADDR(symval, hv_vmbus_device_id, guid);
+	char guid_name[(sizeof(*guid) + 1) * 2];
 
-	for (i = 0; i < (sizeof(id->guid) * 2); i += 2)
-		sprintf(&guid_name[i], "%02x", id->guid[i/2]);
+	for (i = 0; i < (sizeof(*guid) * 2); i += 2)
+		sprintf(&guid_name[i], "%02x", TO_NATIVE((*guid)[i/2]));
 
 	strcpy(alias, "vmbus:");
 	strcat(alias, guid_name);
 
 	return 1;
 }
-ADD_TO_DEVTABLE("vmbus", struct hv_vmbus_device_id, do_vmbus_entry);
+ADD_TO_DEVTABLE("vmbus", hv_vmbus_device_id, do_vmbus_entry);
 
 /* Looks like: i2c:S */
-static int do_i2c_entry(const char *filename, struct i2c_device_id *id,
+static int do_i2c_entry(const char *filename, void *symval,
 			char *alias)
 {
-	sprintf(alias, I2C_MODULE_PREFIX "%s", id->name);
+	DEF_FIELD_ADDR(symval, i2c_device_id, name);
+	sprintf(alias, I2C_MODULE_PREFIX "%s", *name);
 
 	return 1;
 }
-ADD_TO_DEVTABLE("i2c", struct i2c_device_id, do_i2c_entry);
+ADD_TO_DEVTABLE("i2c", i2c_device_id, do_i2c_entry);
 
 /* Looks like: spi:S */
-static int do_spi_entry(const char *filename, struct spi_device_id *id,
+static int do_spi_entry(const char *filename, void *symval,
 			char *alias)
 {
-	sprintf(alias, SPI_MODULE_PREFIX "%s", id->name);
+	DEF_FIELD_ADDR(symval, spi_device_id, name);
+	sprintf(alias, SPI_MODULE_PREFIX "%s", *name);
 
 	return 1;
 }
-ADD_TO_DEVTABLE("spi", struct spi_device_id, do_spi_entry);
+ADD_TO_DEVTABLE("spi", spi_device_id, do_spi_entry);
 
 static const struct dmifield {
 	const char *prefix;
@@ -882,21 +932,21 @@ static void dmi_ascii_filter(char *d, const char *s)
 }
 
 
-static int do_dmi_entry(const char *filename, struct dmi_system_id *id,
+static int do_dmi_entry(const char *filename, void *symval,
 			char *alias)
 {
 	int i, j;
-
+	DEF_FIELD_ADDR(symval, dmi_system_id, matches);
 	sprintf(alias, "dmi*");
 
 	for (i = 0; i < ARRAY_SIZE(dmi_fields); i++) {
 		for (j = 0; j < 4; j++) {
-			if (id->matches[j].slot &&
-			    id->matches[j].slot == dmi_fields[i].field) {
+			if ((*matches)[j].slot &&
+			    (*matches)[j].slot == dmi_fields[i].field) {
 				sprintf(alias + strlen(alias), ":%s*",
 					dmi_fields[i].prefix);
 				dmi_ascii_filter(alias + strlen(alias),
-						 id->matches[j].substr);
+						 (*matches)[j].substr);
 				strcat(alias, "*");
 			}
 		}
@@ -905,27 +955,30 @@ static int do_dmi_entry(const char *filename, struct dmi_system_id *id,
 	strcat(alias, ":");
 	return 1;
 }
-ADD_TO_DEVTABLE("dmi", struct dmi_system_id, do_dmi_entry);
+ADD_TO_DEVTABLE("dmi", dmi_system_id, do_dmi_entry);
 
 static int do_platform_entry(const char *filename,
-			     struct platform_device_id *id, char *alias)
+			     void *symval, char *alias)
 {
-	sprintf(alias, PLATFORM_MODULE_PREFIX "%s", id->name);
+	DEF_FIELD_ADDR(symval, platform_device_id, name);
+	sprintf(alias, PLATFORM_MODULE_PREFIX "%s", *name);
 	return 1;
 }
-ADD_TO_DEVTABLE("platform", struct platform_device_id, do_platform_entry);
+ADD_TO_DEVTABLE("platform", platform_device_id, do_platform_entry);
 
 static int do_mdio_entry(const char *filename,
-			 struct mdio_device_id *id, char *alias)
+			 void *symval, char *alias)
 {
 	int i;
+	DEF_FIELD(symval, mdio_device_id, phy_id);
+	DEF_FIELD(symval, mdio_device_id, phy_id_mask);
 
 	alias += sprintf(alias, MDIO_MODULE_PREFIX);
 
 	for (i = 0; i < 32; i++) {
-		if (!((id->phy_id_mask >> (31-i)) & 1))
+		if (!((phy_id_mask >> (31-i)) & 1))
 			*(alias++) = '?';
-		else if ((id->phy_id >> (31-i)) & 1)
+		else if ((phy_id >> (31-i)) & 1)
 			*(alias++) = '1';
 		else
 			*(alias++) = '0';
@@ -936,32 +989,34 @@ static int do_mdio_entry(const char *filename,
 
 	return 1;
 }
-ADD_TO_DEVTABLE("mdio", struct mdio_device_id, do_mdio_entry);
+ADD_TO_DEVTABLE("mdio", mdio_device_id, do_mdio_entry);
 
 /* Looks like: zorro:iN. */
-static int do_zorro_entry(const char *filename, struct zorro_device_id *id,
+static int do_zorro_entry(const char *filename, void *symval,
 			  char *alias)
 {
-	id->id = TO_NATIVE(id->id);
+	DEF_FIELD(symval, zorro_device_id, id);
 	strcpy(alias, "zorro:");
-	ADD(alias, "i", id->id != ZORRO_WILDCARD, id->id);
+	ADD(alias, "i", id != ZORRO_WILDCARD, id);
 	return 1;
 }
-ADD_TO_DEVTABLE("zorro", struct zorro_device_id, do_zorro_entry);
+ADD_TO_DEVTABLE("zorro", zorro_device_id, do_zorro_entry);
 
 /* looks like: "pnp:dD" */
 static int do_isapnp_entry(const char *filename,
-			   struct isapnp_device_id *id, char *alias)
+			   void *symval, char *alias)
 {
+	DEF_FIELD(symval, isapnp_device_id, vendor);
+	DEF_FIELD(symval, isapnp_device_id, function);
 	sprintf(alias, "pnp:d%c%c%c%x%x%x%x*",
-		'A' + ((id->vendor >> 2) & 0x3f) - 1,
-		'A' + (((id->vendor & 3) << 3) | ((id->vendor >> 13) & 7)) - 1,
-		'A' + ((id->vendor >> 8) & 0x1f) - 1,
-		(id->function >> 4) & 0x0f, id->function & 0x0f,
-		(id->function >> 12) & 0x0f, (id->function >> 8) & 0x0f);
+		'A' + ((vendor >> 2) & 0x3f) - 1,
+		'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1,
+		'A' + ((vendor >> 8) & 0x1f) - 1,
+		(function >> 4) & 0x0f, function & 0x0f,
+		(function >> 12) & 0x0f, (function >> 8) & 0x0f);
 	return 1;
 }
-ADD_TO_DEVTABLE("isapnp", struct isapnp_device_id, do_isapnp_entry);
+ADD_TO_DEVTABLE("isapnp", isapnp_device_id, do_isapnp_entry);
 
 /*
  * Append a match expression for a single masked hex digit.
@@ -1012,25 +1067,27 @@ static void append_nibble_mask(char **outp,
  *	a ? or [] pattern matching exactly one digit.
  */
 static int do_amba_entry(const char *filename,
-			 struct amba_id *id, char *alias)
+			 void *symval, char *alias)
 {
 	unsigned int digit;
 	char *p = alias;
+	DEF_FIELD(symval, amba_id, id);
+	DEF_FIELD(symval, amba_id, mask);
 
-	if ((id->id & id->mask) != id->id)
+	if ((id & mask) != id)
 		fatal("%s: Masked-off bit(s) of AMBA device ID are non-zero: "
 		      "id=0x%08X, mask=0x%08X.  Please fix this driver.\n",
-		      filename, id->id, id->mask);
+		      filename, id, mask);
 
 	p += sprintf(alias, "amba:d");
 	for (digit = 0; digit < 8; digit++)
 		append_nibble_mask(&p,
-				   (id->id >> (4 * (7 - digit))) & 0xf,
-				   (id->mask >> (4 * (7 - digit))) & 0xf);
+				   (id >> (4 * (7 - digit))) & 0xf,
+				   (mask >> (4 * (7 - digit))) & 0xf);
 
 	return 1;
 }
-ADD_TO_DEVTABLE("amba", struct amba_id, do_amba_entry);
+ADD_TO_DEVTABLE("amba", amba_id, do_amba_entry);
 
 /* LOOKS like x86cpu:vendor:VVVV:family:FFFF:model:MMMM:feature:*,FEAT,*
  * All fields are numbers. It would be nicer to use strings for vendor
@@ -1038,24 +1095,24 @@ ADD_TO_DEVTABLE("amba", struct amba_id, do_amba_entry);
  * complicated.
  */
 
-static int do_x86cpu_entry(const char *filename, struct x86_cpu_id *id,
+static int do_x86cpu_entry(const char *filename, void *symval,
 			   char *alias)
 {
-	id->feature = TO_NATIVE(id->feature);
-	id->family = TO_NATIVE(id->family);
-	id->model = TO_NATIVE(id->model);
-	id->vendor = TO_NATIVE(id->vendor);
+	DEF_FIELD(symval, x86_cpu_id, feature);
+	DEF_FIELD(symval, x86_cpu_id, family);
+	DEF_FIELD(symval, x86_cpu_id, model);
+	DEF_FIELD(symval, x86_cpu_id, vendor);
 
 	strcpy(alias, "x86cpu:");
-	ADD(alias, "vendor:",  id->vendor != X86_VENDOR_ANY, id->vendor);
-	ADD(alias, ":family:", id->family != X86_FAMILY_ANY, id->family);
-	ADD(alias, ":model:",  id->model  != X86_MODEL_ANY,  id->model);
+	ADD(alias, "vendor:",  vendor != X86_VENDOR_ANY, vendor);
+	ADD(alias, ":family:", family != X86_FAMILY_ANY, family);
+	ADD(alias, ":model:",  model  != X86_MODEL_ANY,  model);
 	strcat(alias, ":feature:*");
-	if (id->feature != X86_FEATURE_ANY)
-		sprintf(alias + strlen(alias), "%04X*", id->feature);
+	if (feature != X86_FEATURE_ANY)
+		sprintf(alias + strlen(alias), "%04X*", feature);
 	return 1;
 }
-ADD_TO_DEVTABLE("x86cpu", struct x86_cpu_id, do_x86cpu_entry);
+ADD_TO_DEVTABLE("x86cpu", x86_cpu_id, do_x86cpu_entry);
 
 /* Does namelen bytes of name exactly match the symbol? */
 static bool sym_is(const char *name, unsigned namelen, const char *symbol)
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 0f84bb3..21d4b89 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -2116,7 +2116,7 @@ int main(int argc, char **argv)
 	struct ext_sym_list *extsym_iter;
 	struct ext_sym_list *extsym_start = NULL;
 
-	while ((opt = getopt(argc, argv, "i:I:e:cmsSo:awM:K:")) != -1) {
+	while ((opt = getopt(argc, argv, "i:I:e:msSo:awM:K:")) != -1) {
 		switch (opt) {
 		case 'i':
 			kernel_read = optarg;
@@ -2125,9 +2125,6 @@ int main(int argc, char **argv)
 			module_read = optarg;
 			external_module = 1;
 			break;
-		case 'c':
-			cross_build = 1;
-			break;
 		case 'e':
 			external_module = 1;
 			extsym_iter =
-- 
1.7.11.1


-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply related	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2012-06-26 13:28 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-06-15 17:42 [-next] FATAL: drivers/gpu/drm/udl/udl: sizeof(struct usb_device_id)=24 is not a modulo of the size of section __mod_usb_device_table=44 Geert Uytterhoeven
2012-06-15 20:10 ` Greg Kroah-Hartman
2012-06-15 21:02   ` Geert Uytterhoeven
2012-06-15 23:12     ` Greg Kroah-Hartman
2012-06-16 13:23       ` Bjørn Mork
2012-06-16 15:43         ` Andreas Schwab
2012-06-17 14:00           ` Bjørn Mork
2012-06-17 15:42             ` Andreas Schwab
2012-06-25 12:22             ` [PATCH] mod/file2alias: make modalias generation safe for cross compiling Andreas Schwab
2012-06-25 20:32               ` Geert Uytterhoeven
2012-06-25 21:43                 ` Andreas Schwab
2012-06-26  5:00               ` Sam Ravnborg
2012-06-26 13:27                 ` [PATCH v2] " Andreas Schwab
2012-06-16 18:33         ` [-next] FATAL: drivers/gpu/drm/udl/udl: sizeof(struct usb_device_id)=24 is not a modulo of the size of section __mod_usb_device_table=44 Philippe De Muyter
2012-06-16 19:11         ` Greg Kroah-Hartman
2012-06-16 19:30           ` Geert Uytterhoeven
2012-06-16 18:51       ` Geert Uytterhoeven

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).