View unanswered posts | View active topics It is currently Wed Dec 13, 2017 1:19 am



Reply to topic  [ 21 posts ]  Go to page 1, 2, 3  Next
 ESXI 5.x Drivers Part 3: Compiling 
Author Message

Joined: Mon Jan 28, 2013 5:09 pm
Posts: 100
Reply with quote
Post ESXI 5.x Drivers Part 3: Compiling
This post is going to walk through the compilation of Linux source code that provides driver functionality for a certain set of Atheros based NIC hardware. It relies upon a build environment as detailed in parts 1 & 2, but the techniques and advice will apply to any build and compile project.

Login to your build host as the build user and move the top level directory where all build attempts will be made.

Code:
build@esx-build:~$ cd ~/vsphere/vmkdrivers-gpl/
build@esx-build:~/vsphere/vmkdrivers-gpl$


In part 1 of the guide we went through setting up a build environment. In part 2 we prepared a build script which would be called to compile our code and produce a suitable kernel module. Here we're going to get straight in to compiling, so we'll call the build script and see what happens:

Code:
build@esx-build:~/vsphere/vmkdrivers-gpl$ ./build-atl1c.sh
In file included from vmkdrivers/src_9/drivers/net/atl1c/atl1c.h:26,
                 from vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:22:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1432: error: conflicting types for 'irq_handler_t'
vmkdrivers/src_9/include/linux/interrupt.h:88: error: previous declaration of 'irq_handler_t' was here
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h: In function '_kc_request_irq':
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1443: warning: passing argument 2 of 'request_irq' from incompatible pointer type
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h: At top level:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1577: error: redefinition of 'struct napi_struct'
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c: In function 'atl1c_shutdown':
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:2755: warning: implicit declaration of function 'atl1c_suspend'
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c: In function 'atl1c_probe':
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:2871: warning: implicit declaration of function 'alloc_etherdev'
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:2871: warning: assignment makes pointer from integer without a cast
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:2957: warning: assignment from incompatible pointer type
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:2957: error: 'struct work_struct' has no member named 'data'
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:2957: error: 'struct work_struct' has no member named 'timer'
In file included from vmkdrivers/src_9/drivers/net/atl1c/at_common.h:4,
                 from vmkdrivers/src_9/drivers/net/atl1c/at_common_main.c:1:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1432: error: conflicting types for 'irq_handler_t'
vmkdrivers/src_9/include/linux/interrupt.h:88: error: previous declaration of 'irq_handler_t' was here
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h: In function '_kc_request_irq':
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1443: warning: passing argument 2 of 'request_irq' from incompatible pointer type
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h: At top level:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1577: error: redefinition of 'struct napi_struct'
vmkdrivers/src_9/drivers/net/atl1c/at_common_main.c: In function 'at_common_suspend':
vmkdrivers/src_9/drivers/net/atl1c/at_common_main.c:32: warning: implicit declaration of function 'atl1e_suspend'
vmkdrivers/src_9/drivers/net/atl1c/at_common_main.c:40: warning: implicit declaration of function 'atl1c_suspend'
In file included from vmkdrivers/src_9/drivers/net/atl1c/atl1c.h:26,
                 from vmkdrivers/src_9/drivers/net/atl1c/atl1c_ethtool.c:26:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1432: error: conflicting types for 'irq_handler_t'
vmkdrivers/src_9/include/linux/interrupt.h:88: error: previous declaration of 'irq_handler_t' was here
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h: In function '_kc_request_irq':
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1443: warning: passing argument 2 of 'request_irq' from incompatible pointer type
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h: At top level:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1577: error: redefinition of 'struct napi_struct'
In file included from vmkdrivers/src_9/drivers/net/atl1c/atl1c.h:26,
                 from vmkdrivers/src_9/drivers/net/atl1c/atl1c_hw.c:26:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1432: error: conflicting types for 'irq_handler_t'
vmkdrivers/src_9/include/linux/interrupt.h:88: error: previous declaration of 'irq_handler_t' was here
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h: In function '_kc_request_irq':
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1443: warning: passing argument 2 of 'request_irq' from incompatible pointer type
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h: At top level:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1577: error: redefinition of 'struct napi_struct'
In file included from vmkdrivers/src_9/drivers/net/atl1c/atl1c.h:26,
                 from vmkdrivers/src_9/drivers/net/atl1c/atl1c_param.c:24:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1432: error: conflicting types for 'irq_handler_t'
vmkdrivers/src_9/include/linux/interrupt.h:88: error: previous declaration of 'irq_handler_t' was here
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h: In function '_kc_request_irq':
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1443: warning: passing argument 2 of 'request_irq' from incompatible pointer type
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h: At top level:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1577: error: redefinition of 'struct napi_struct'
In file included from vmkdrivers/src_9/drivers/net/atl1c/atl1e.h:30,
                 from vmkdrivers/src_9/drivers/net/atl1c/atl1e_ethtool.c:29:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1432: error: conflicting types for 'irq_handler_t'
vmkdrivers/src_9/include/linux/interrupt.h:88: error: previous declaration of 'irq_handler_t' was here
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h: In function '_kc_request_irq':
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1443: warning: passing argument 2 of 'request_irq' from incompatible pointer type
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h: At top level:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1577: error: redefinition of 'struct napi_struct'
In file included from vmkdrivers/src_9/drivers/net/atl1c/atl1e.h:30,
                 from vmkdrivers/src_9/drivers/net/atl1c/atl1e_hw.c:26:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1432: error: conflicting types for 'irq_handler_t'
vmkdrivers/src_9/include/linux/interrupt.h:88: error: previous declaration of 'irq_handler_t' was here
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h: In function '_kc_request_irq':
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1443: warning: passing argument 2 of 'request_irq' from incompatible pointer type
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h: At top level:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1577: error: redefinition of 'struct napi_struct'
In file included from vmkdrivers/src_9/drivers/net/atl1c/at_common.h:4,
                 from vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:23:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1432: error: conflicting types for 'irq_handler_t'
vmkdrivers/src_9/include/linux/interrupt.h:88: error: previous declaration of 'irq_handler_t' was here
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h: In function '_kc_request_irq':
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1443: warning: passing argument 2 of 'request_irq' from incompatible pointer type
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h: At top level:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1577: error: redefinition of 'struct napi_struct'
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c: In function 'atl1e_probe':
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:269: warning: implicit declaration of function 'alloc_etherdev'
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:269: warning: assignment makes pointer from integer without a cast
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:421: warning: assignment from incompatible pointer type
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:421: error: 'struct work_struct' has no member named 'data'
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:421: error: 'struct work_struct' has no member named 'timer'
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:422: warning: assignment from incompatible pointer type
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:422: error: 'struct work_struct' has no member named 'data'
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:422: error: 'struct work_struct' has no member named 'timer'
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c: In function 'atl1e_suspend':
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:592: error: 'retval' undeclared (first use in this function)
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:592: error: (Each undeclared identifier is reported only once
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:592: error: for each function it appears in.)
In file included from vmkdrivers/src_9/drivers/net/atl1c/atl1e.h:30,
                 from vmkdrivers/src_9/drivers/net/atl1c/atl1e_param.c:27:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1432: error: conflicting types for 'irq_handler_t'
vmkdrivers/src_9/include/linux/interrupt.h:88: error: previous declaration of 'irq_handler_t' was here
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h: In function '_kc_request_irq':
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1443: warning: passing argument 2 of 'request_irq' from incompatible pointer type
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h: At top level:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1577: error: redefinition of 'struct napi_struct'
In file included from vmkdrivers/src_9/drivers/net/atl1c/kcompat.c:26:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1432: error: conflicting types for 'irq_handler_t'
vmkdrivers/src_9/include/linux/interrupt.h:88: error: previous declaration of 'irq_handler_t' was here
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h: In function '_kc_request_irq':
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1443: warning: passing argument 2 of 'request_irq' from incompatible pointer type
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h: At top level:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1577: error: redefinition of 'struct napi_struct'
In file included from vmkdrivers/src_9/drivers/net/atl1c/kcompat_ethtool.c:55:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1432: error: conflicting types for 'irq_handler_t'
vmkdrivers/src_9/include/linux/interrupt.h:88: error: previous declaration of 'irq_handler_t' was here
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h: In function '_kc_request_irq':
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1443: warning: passing argument 2 of 'request_irq' from incompatible pointer type
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h: At top level:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1577: error: redefinition of 'struct napi_struct'
GNU ld (Linux/GNU Binutils) 2.17.50.0.15.20070418
/home/build/toolchain/lin32/binutils-2.17.50.0.15-modcall/bin/x86_64-linux-ld: BLD/build/vmkdriver-atl1c-CUR/release/vmkernel64/SUBDIRS/vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.o: No such file: No such file or directory


You should get used to seeing pages of errors like this. In fact, at times it will get worse as you start to remediate the problems highlighted, because as you introduce new headers or code, more and more problems can evolve. The chances are you're reading this to help you through compiling a driver you need; be aware that the problems you see may not look much like what we see with this driver. Every driver is different. I will try to underline the thought process that went in to solving the problems with this driver so that you can take the principles away and bake them in to your own work.

As I work through getting a driver to compile I like to get a sense of whether I'm making progress or not. This is important for morale because this can be a long process. If you're not really experienced with building open source software and at least being able to read and comprehend C code to a basic level, I'm talking about potentially hours if not days of work.

Getting a sense of progress can be hard to do when you have pages of errors, so I like to count the reported errors for each run. Generally speaking there are 2 types of problems reported by the compilation run- warnings and errors. Warnings will flag a message but otherwise let the compilation proceed. Errors will cause the compilation to fail. The initial goal is to reduce the error count to 0. Here's how I count the output:

Code:
build@esx-build:~/vsphere/vmkdrivers-gpl$ ./build-atl1c.sh 2>&1 | wc -l
112


This is basically running the script and redirecting the error output stream to the standard output stream so that all output from the compilation will be pushed in to the pipe toward the wc command, which we call with -l to count lines. You can see that our starting point is 112 warning/error messages with this driver.

You can pick off the errors in any order you like. If you spot an error near the end of the compilation output, and it looks simple enough to resolve, it doesn't really matter if you go after that first. However, many errors can be repeats of errors seen earlier in the compilation, or can be related to problems earlier in the code, so my own experience is that it is easier to pick them off starting at the top.

To that end, let's look at the first few lines of the last run:

Code:
In file included from vmkdrivers/src_9/drivers/net/atl1c/atl1c.h:26,
                 from vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:22:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1432: error: conflicting types for 'irq_handler_t'
vmkdrivers/src_9/include/linux/interrupt.h:88: error: previous declaration of 'irq_handler_t' was here


So this is telling us that in kcompat.h, a file that is part of our driver source, at line 1432, there is a typedef irq_handler_t which conflicts with one of the same name in file vmkdrivers/src_9/include/linux/interrupt.h at line 88. The file with the conflicting definition is one provided by VMware (it's in the tree we unpacked).

If we look at the line in our file:

Code:
typedef irqreturn_t (*irq_handler_t)(int, void*, struct pt_regs *);


And then the one VMWare provide:

Code:
typedef irqreturn_t (*irq_handler_t)(int, void *);


It's quite possible these could of been identical, in which case you'd simply comment out either one of them (but not both) However, they're not identical so which one gets to stay and which gets to go? In all such conflicts I think that the VMWare code should probably take precedence. After all, our module will be a tiny integrated part of the bigger kernel VMware provide so it's almost certainly going to dictate the way things should work. To further increase confidence in this approach you can look around the code block where that typedef is; notice that it's part of an #if compiler directive block. It looks like this:

Code:
#if !defined(__VMKLNX__)
[code 1 here]
#else
[code 2 here]
#endif


Our conflicting typedef is in the code 2 section. So VMWare made a conscious edit to the standard linux interrupt.h header file checking to see whether VMKLNX is set, and if so, it provides the irqreturn_t typedef. It it wasn't important I'm sure they wouldn't have gone to that trouble. So, we edit vmkdrivers/src_9/drivers/net/atl1c/kcompat.h and change line 1432 to look like this:

Code:
//typedef irqreturn_t (*irq_handler_t)(int, void*, struct pt_regs *);


The line is now commented out and the conflict should be gone.

Code:
build@esx-build:~/vsphere/vmkdrivers-gpl$ ./build-atl1c.sh
In file included from vmkdrivers/src_9/drivers/net/atl1c/atl1c.h:26,
                 from vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:22:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1577: error: redefinition of 'struct napi_struct'
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c: In function 'atl1c_shutdown':
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:2755: warning: implicit declaration of function 'atl1c_suspend'
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c: In function 'atl1c_probe':
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:2871: warning: implicit declaration of function 'alloc_etherdev'
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:2871: warning: assignment makes pointer from integer without a cast
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:2957: warning: assignment from incompatible pointer type
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:2957: error: 'struct work_struct' has no member named 'data'
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:2957: error: 'struct work_struct' has no member named 'timer'
In file included from vmkdrivers/src_9/drivers/net/atl1c/at_common.h:4,
                 from vmkdrivers/src_9/drivers/net/atl1c/at_common_main.c:1:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1577: error: redefinition of 'struct napi_struct'
vmkdrivers/src_9/drivers/net/atl1c/at_common_main.c: In function 'at_common_suspend':
vmkdrivers/src_9/drivers/net/atl1c/at_common_main.c:32: warning: implicit declaration of function 'atl1e_suspend'
vmkdrivers/src_9/drivers/net/atl1c/at_common_main.c:40: warning: implicit declaration of function 'atl1c_suspend'
In file included from vmkdrivers/src_9/drivers/net/atl1c/atl1c.h:26,
                 from vmkdrivers/src_9/drivers/net/atl1c/atl1c_ethtool.c:26:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1577: error: redefinition of 'struct napi_struct'
In file included from vmkdrivers/src_9/drivers/net/atl1c/atl1c.h:26,
                 from vmkdrivers/src_9/drivers/net/atl1c/atl1c_hw.c:26:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1577: error: redefinition of 'struct napi_struct'
In file included from vmkdrivers/src_9/drivers/net/atl1c/atl1c.h:26,
                 from vmkdrivers/src_9/drivers/net/atl1c/atl1c_param.c:24:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1577: error: redefinition of 'struct napi_struct'
In file included from vmkdrivers/src_9/drivers/net/atl1c/atl1e.h:30,
                 from vmkdrivers/src_9/drivers/net/atl1c/atl1e_ethtool.c:29:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1577: error: redefinition of 'struct napi_struct'
In file included from vmkdrivers/src_9/drivers/net/atl1c/atl1e.h:30,
                 from vmkdrivers/src_9/drivers/net/atl1c/atl1e_hw.c:26:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1577: error: redefinition of 'struct napi_struct'
In file included from vmkdrivers/src_9/drivers/net/atl1c/at_common.h:4,
                 from vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:23:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1577: error: redefinition of 'struct napi_struct'
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c: In function 'atl1e_probe':
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:269: warning: implicit declaration of function 'alloc_etherdev'
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:269: warning: assignment makes pointer from integer without a cast
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:421: warning: assignment from incompatible pointer type
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:421: error: 'struct work_struct' has no member named 'data'
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:421: error: 'struct work_struct' has no member named 'timer'
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:422: warning: assignment from incompatible pointer type
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:422: error: 'struct work_struct' has no member named 'data'
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:422: error: 'struct work_struct' has no member named 'timer'
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c: In function 'atl1e_suspend':
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:592: error: 'retval' undeclared (first use in this function)
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:592: error: (Each undeclared identifier is reported only once
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:592: error: for each function it appears in.)
In file included from vmkdrivers/src_9/drivers/net/atl1c/atl1e.h:30,
                 from vmkdrivers/src_9/drivers/net/atl1c/atl1e_param.c:27:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1577: error: redefinition of 'struct napi_struct'
In file included from vmkdrivers/src_9/drivers/net/atl1c/kcompat.c:26:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1577: error: redefinition of 'struct napi_struct'
In file included from vmkdrivers/src_9/drivers/net/atl1c/kcompat_ethtool.c:55:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1577: error: redefinition of 'struct napi_struct'
GNU ld (Linux/GNU Binutils) 2.17.50.0.15.20070418
/home/build/toolchain/lin32/binutils-2.17.50.0.15-modcall/bin/x86_64-linux-ld: BLD/build/vmkdriver-atl1c-CUR/release/vmkernel64/SUBDIRS/vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.o: No such file: No such file or directory



Indeed it has. It looks like our error count has probably gone down a bit too, but by how much?

Code:
build@esx-build:~/vsphere/vmkdrivers-gpl$ ./build-atl1c.sh 2>&1 | wc -l
57


We're down from 112 to 57. Encouraging. Let's take the next one:

Code:
In file included from vmkdrivers/src_9/drivers/net/atl1c/atl1c.h:26,
                 from vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:22:
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:1577: error: redefinition of 'struct napi_struct'


This is saying the struct 'napi_struct" is being defined in our file "vmkdrivers/src_9/drivers/net/atl1c/kcompat.h" on line 1577 but it's already defined elsewhere. Unfortunately it's not giving us a hint as to where it's already defined, so we'll have to look for it. First I'm going to look for any files in the entire source tree with references to napi_struct and I'm also going to filter out any results from binary files (we have a lot of unstripped binary modules hanging around that will cloud the results)

Code:
build@esx-build:~/vsphere/vmkdrivers-gpl$ grep -Ilr napi_struct *
vmkdrivers/src_9/vmklinux_9/vmware/linux_net.c
vmkdrivers/src_9/vmklinux_9/vmware/linux_cna.c
vmkdrivers/src_9/drivers/net/nx_nic/nx_nic_vmk.c
vmkdrivers/src_9/drivers/net/nx_nic/unm_nic_main.c
vmkdrivers/src_9/drivers/net/nx_nic/unm_nic.h
vmkdrivers/src_9/drivers/net/r8168/r8168.h
vmkdrivers/src_9/drivers/net/enic/enic_main.c
vmkdrivers/src_9/drivers/net/enic/enic.h
vmkdrivers/src_9/drivers/net/enic/kcompat.h
vmkdrivers/src_9/drivers/net/r8169/r8169.h
vmkdrivers/src_9/drivers/net/bnx2x/bnx2x.h
vmkdrivers/src_9/drivers/net/bnx2x/bnx2x_esx.c
vmkdrivers/src_9/drivers/net/bnx2x/bnx2x_common.c
vmkdrivers/src_9/drivers/net/bnx2x/bnx2x_common.h
vmkdrivers/src_9/drivers/net/ixgbe/ixgbe.h
vmkdrivers/src_9/drivers/net/ixgbe/ixgbe_main.c
vmkdrivers/src_9/drivers/net/ixgbe/ixgbe_vmdq.c
vmkdrivers/src_9/drivers/net/forcedeth/forcedeth.c
vmkdrivers/src_9/drivers/net/e1000e/netdev.c
vmkdrivers/src_9/drivers/net/e1000e/e1000.h
vmkdrivers/src_9/drivers/net/e1000e/kcompat.h
vmkdrivers/src_9/drivers/net/e1000e/kcompat.c
vmkdrivers/src_9/drivers/net/bnx2/bnx2.h
vmkdrivers/src_9/drivers/net/bnx2/bnx2.c
vmkdrivers/src_9/drivers/net/s2io/s2io.h
vmkdrivers/src_9/drivers/net/s2io/s2io.c
vmkdrivers/src_9/drivers/net/igb/igb.h
vmkdrivers/src_9/drivers/net/igb/igb_main.c
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h
vmkdrivers/src_9/drivers/net/atl1c/atl1c.h
vmkdrivers/src_9/drivers/net/sky2/sky2.c
vmkdrivers/src_9/drivers/net/sky2/sky2.h
vmkdrivers/src_9/drivers/net/e1000/e1000.h
vmkdrivers/src_9/drivers/net/e1000/e1000_main.c
vmkdrivers/src_9/drivers/net/e1000/kcompat.h
vmkdrivers/src_9/drivers/net/e1000/kcompat.c
vmkdrivers/src_9/drivers/net/tg3/tg3_vmware.c
vmkdrivers/src_9/drivers/net/tg3/tg3.h
vmkdrivers/src_9/drivers/net/tg3/tg3.c
vmkdrivers/src_9/include/vmklinux_9/vmknetddinetq.h
vmkdrivers/src_9/include/linux/netdevice.h
vmkdrivers/src_9/include/linux/skbuff.h


A definition is normally in a header file and not a .c file so I'm going to narrow it down to those:

Code:
build@esx-build:~/vsphere/vmkdrivers-gpl$ grep -Ilr napi_struct *  | grep -v .c$
vmkdrivers/src_9/drivers/net/nx_nic/unm_nic.h
vmkdrivers/src_9/drivers/net/r8168/r8168.h
vmkdrivers/src_9/drivers/net/enic/enic.h
vmkdrivers/src_9/drivers/net/enic/kcompat.h
vmkdrivers/src_9/drivers/net/r8169/r8169.h
vmkdrivers/src_9/drivers/net/bnx2x/bnx2x.h
vmkdrivers/src_9/drivers/net/bnx2x/bnx2x_common.h
vmkdrivers/src_9/drivers/net/ixgbe/ixgbe.h
vmkdrivers/src_9/drivers/net/e1000e/e1000.h
vmkdrivers/src_9/drivers/net/e1000e/kcompat.h
vmkdrivers/src_9/drivers/net/bnx2/bnx2.h
vmkdrivers/src_9/drivers/net/s2io/s2io.h
vmkdrivers/src_9/drivers/net/igb/igb.h
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h
vmkdrivers/src_9/drivers/net/atl1c/atl1c.h
vmkdrivers/src_9/drivers/net/sky2/sky2.h
vmkdrivers/src_9/drivers/net/e1000/e1000.h
vmkdrivers/src_9/drivers/net/e1000/kcompat.h
vmkdrivers/src_9/drivers/net/tg3/tg3.h
vmkdrivers/src_9/include/vmklinux_9/vmknetddinetq.h
vmkdrivers/src_9/include/linux/netdevice.h
vmkdrivers/src_9/include/linux/skbuff.h



We basically need to do the same thing we just did with the conflicting typedef- see what the two pieces of code look like and choose which one stays. Most of the hits for references to napi_struct are in other supplied drivers, so the definition we are interested in is probably in one of the last 3 files on that output. What you're looking for is a line that starts "struct napi_struct {" and it's in netdevice.h. The struct in vmkdrivers/src_9/include/linux/netdevice.h looks like this:

Code:
struct napi_struct {
        unsigned long           state;
        int                     weight;
        int                     (*poll)(struct napi_struct *, int);
        unsigned int            napi_id;
        struct net_device       *dev;
        struct list_head        dev_list;
        vmk_Bool                dev_poll;
        void *                  net_poll;
        vmklnx_poll_type        net_poll_type;
        struct napi_wdt_priv    napi_wdt_priv;
        vmk_uint32              vector;
        struct net_lro_mgr      lro_mgr;
        struct net_lro_desc     lro_desc[LRO_DEFAULT_MAX_DESC];
};


The struct at line 1577 of our kcompat.h file looks like this:

Code:
struct napi_struct {
        /* used to look up the real NAPI polling routine */
        int (*poll)(struct napi_struct *, int);
        int weight;
};


So they look quite different. Using the same logic applied earlier, namely that VMWare's provided definitions should probably take precedence, I commented out lines 1577 to through 1581. Again, the definition in netdevice.h is in a compiler directive "if defined(__VMKLNX__)" block so that further backs up the decision.

Next, another compilation attempt:

Code:
build@esx-build:~/vsphere/vmkdrivers-gpl$ ./build-atl1c.sh
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c: In function 'atl1c_shutdown':
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:2755: warning: implicit declaration of function 'atl1c_suspend'
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c: In function 'atl1c_probe':
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:2871: warning: implicit declaration of function 'alloc_etherdev'
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:2871: warning: assignment makes pointer from integer without a cast
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:2957: warning: assignment from incompatible pointer type
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:2957: error: 'struct work_struct' has no member named 'data'
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:2957: error: 'struct work_struct' has no member named 'timer'
vmkdrivers/src_9/drivers/net/atl1c/at_common_main.c: In function 'at_common_suspend':
vmkdrivers/src_9/drivers/net/atl1c/at_common_main.c:32: warning: implicit declaration of function 'atl1e_suspend'
vmkdrivers/src_9/drivers/net/atl1c/at_common_main.c:40: warning: implicit declaration of function 'atl1c_suspend'
vmkdrivers/src_9/drivers/net/atl1c/at_common_main.c: At top level:
vmkdrivers/src_9/drivers/net/atl1c/at_common_main.c:27: warning: 'at_common_suspend' defined but not used
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c: In function 'atl1e_probe':
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:269: warning: implicit declaration of function 'alloc_etherdev'
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:269: warning: assignment makes pointer from integer without a cast
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:421: warning: assignment from incompatible pointer type
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:421: error: 'struct work_struct' has no member named 'data'
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:421: error: 'struct work_struct' has no member named 'timer'
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:422: warning: assignment from incompatible pointer type
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:422: error: 'struct work_struct' has no member named 'data'
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:422: error: 'struct work_struct' has no member named 'timer'
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c: In function 'atl1e_suspend':
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:592: error: 'retval' undeclared (first use in this function)
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:592: error: (Each undeclared identifier is reported only once
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:592: error: for each function it appears in.)
GNU ld (Linux/GNU Binutils) 2.17.50.0.15.20070418
/home/build/toolchain/lin32/binutils-2.17.50.0.15-modcall/bin/x86_64-linux-ld: BLD/build/vmkdriver-atl1c-CUR/release/vmkernel64/SUBDIRS/vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.o: No such file: No such file or directory


That is looking much better. Only 28 lines of output. As mentioned earlier, the initial goal is to focus on moving the error count down to 0 so we end up with a module we can try to load in. I say "try to load" because the chances are when you come to insert the module it probably won't be accepted by the kernel on the first pass. Moving down to the next error:

Code:
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:2957: error: 'struct work_struct' has no member named 'data'
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:2957: error: 'struct work_struct' has no member named 'timer'


If you open up atl1c_main.c and look at line 2957 you will see this:

Code:
INIT_WORK(&adapter->common_task, atl1c_common_task);


Huh? there is no mention of struct work_struct there? INIT_WORK is a macro. Basically where ever the identifier INIT_WORK appears, it gets substituted with a piece of code that is defined elsewhere. Let's search our code base for references to INIT_WORK:

Code:
build@esx-build:~/vsphere/vmkdrivers-gpl$ grep -r INIT_WORK vmkdrivers/src_9/drivers/net/atl1c/
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:    INIT_WORK(&adapter->reset_task, atl1e_reset_task);
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:    INIT_WORK(&adapter->link_chg_task, atl1e_link_chg_task);
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:   INIT_WORK(&adapter->common_task, atl1c_common_task);
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:#undef INIT_WORK
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:#define INIT_WORK(a,b) INIT_TQUEUE(a,(void (*)(void *))b,a)
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:#undef INIT_WORK
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:#define INIT_WORK(_work, _func) \


So it looks like the INIT_WORK macro is called 3 times by our code, and it appears a few times in our kcompat.h file. If we open up the kcompat.h file and look for INIT_WORK, we can see it looks like this in our code at line 1505:

Code:
#undef INIT_WORK
#define INIT_WORK(_work, _func) \
do { \
        INIT_LIST_HEAD(&(_work)->entry); \
        (_work)->pending = 0; \
        (_work)->func = (void (*)(void *))_func; \
        (_work)->data = _work; \
        init_timer(&(_work)->timer); \
} while (0)



Bonus points if you noticed that there is a similar undef/define for INIT_WORK at line 1072 also. The version at line 1072 applies if the LINUX_VERSION_CODE is less than 2.5.38. Our LINUX_VERSION_CODE is 2.6.18 so it's the code at line 1505 that is coming in to play. How do we know our target environment is linux 2.6.18? If you look at the file vmkdrivers/src_9/include/linux/version.h it has the line #define LINUX_VERSION_CODE 132626. That translates to 2.6.18. You can figure that out with X*65536 + Y*256 + Z.

So you can see that our driver is calling #undef INIT_WORK to undefine whatever was previously defined, and then is defining it again in the way it wants.

Was INIT_WORK already defined in the VMware environment, though? We can search the VMWare provided include path to see:

Code:
build@esx-build:~/vsphere/vmkdrivers-gpl$ grep -Ir INIT_WORK vmkdrivers/src_9/include/
vmkdrivers/src_9/include/linux/workqueue.h: *  INIT_WORK - Initialize all of a work_struct
vmkdrivers/src_9/include/linux/workqueue.h: *  #define INIT_WORK(_work, _func)
vmkdrivers/src_9/include/linux/workqueue.h:/* _VMKLNX_CODECHECK_: INIT_WORK */
vmkdrivers/src_9/include/linux/workqueue.h:#define INIT_WORK(_work, _func)                        \
vmkdrivers/src_9/include/linux/workqueue.h:/* _VMKLNX_CODECHECK_: INIT_WORK */
vmkdrivers/src_9/include/linux/workqueue.h:                INIT_WORK(&(_dwork)->work, (_func));            \
vmkdrivers/src_9/include/linux/workqueue.h:#define INIT_WORK(_work, _func, _data)      


So yes, in fact, INIT_WORK was already setup and available. This is what the VMware version looks like from the workqueue.h file:

Code:
#define INIT_WORK(_work, _func)                                 \
        do {                                                    \
                INIT_LIST_HEAD(&(_work)->entry);                \
                (_work)->pending = 0;                           \
                PREPARE_WORK((_work), (_func));                 \
                (_work)->module_id = VMK_INVALID_MODULE_ID;     \
        } while (0)



So our error message said that struct work_struct has no member named data and timer. One of the problem lines generating the error then is (_work)->data = _work; from line 1511 in kcompat.h. What this line really translates to is adapter->common_task->data does not exist. adapter->common_task is what is passed to the macro and is referred to by _work. So we need to find the definition of common_task in our code:

Code:
build@esx-build:~/vsphere/vmkdrivers-gpl$ grep -r common_task vmkdrivers/src_9/drivers/net/atl1c
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:static void atl1c_common_task(struct work_struct *work)
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:   adapter = container_of(work, struct atl1c_adapter, common_task);
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:   schedule_work(&adapter->common_task);
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:   schedule_work(&adapter->common_task);
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:         schedule_work(&adapter->common_task);
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:   INIT_WORK(&adapter->common_task, atl1c_common_task);
vmkdrivers/src_9/drivers/net/atl1c/atl1c.h:   struct work_struct common_task;


From our atl1c.h file here is the definition:

Code:
struct work_struct common_task;


So common_task is a struct of type work_struct. Perhaps work_struct is redefined? Let's look:

Code:
build@esx-build:~/vsphere/vmkdrivers-gpl$ grep -r work_struct vmkdrivers/src_9/drivers/net/atl1c
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:static void atl1e_reset_task(struct work_struct *work);
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:static void atl1e_link_chg_task(struct work_struct *work);
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:atl1e_reset_task(struct work_struct *work)
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:atl1e_link_chg_task(struct work_struct *work)
vmkdrivers/src_9/drivers/net/atl1c/atl1e.h:    struct work_struct reset_task;//
vmkdrivers/src_9/drivers/net/atl1c/atl1e.h:    struct work_struct link_chg_task;//
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:static void atl1c_common_task(struct work_struct *work)
vmkdrivers/src_9/drivers/net/atl1c/kcompat.h:#define work_struct tq_struct
vmkdrivers/src_9/drivers/net/atl1c/atl1c.h:   struct work_struct common_task;


It looks like there is a kcompat.h #define for work_struct, and here it is from line 1071 in our kcompat.h file:

Code:
#define work_struct tq_struct


This is saying that work_struct is basically an alias to tg_struct. But, this definition isn't a factor in our problem, because if you look at the context of the definition it's in a compiler directive again saying that it only applies if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,28), and we know our version is higher.

So work_struct must be defined elsewhere. Here we'll check for it in the VMWare include path:

Code:
build@esx-build:~/vsphere/vmkdrivers-gpl$ grep -r work_struct vmkdrivers/src_9/include/linux
vmkdrivers/src_9/include/linux/libata.h:   struct work_struct   scsi_rescan_task;
vmkdrivers/src_9/include/linux/relay.h:   struct work_struct wake_readers; /* reader wake-up work struct */
vmkdrivers/src_9/include/linux/blkdev.h:   struct work_struct   unplug_work;
vmkdrivers/src_9/include/linux/blkdev.h:struct work_struct;
vmkdrivers/src_9/include/linux/blkdev.h:int kblockd_schedule_work(struct work_struct *work);
vmkdrivers/src_9/include/linux/workqueue.h:struct work_struct;
vmkdrivers/src_9/include/linux/workqueue.h:typedef void (*work_func_t)(struct work_struct *work);
vmkdrivers/src_9/include/linux/workqueue.h:struct work_struct {
vmkdrivers/src_9/include/linux/workqueue.h:   struct work_struct work;
vmkdrivers/src_9/include/linux/workqueue.h:struct work_struct {
vmkdrivers/src_9/include/linux/workqueue.h:   struct work_struct work;
vmkdrivers/src_9/include/linux/workqueue.h: *  DECLARE_WORK - Declare and initialize a work_struct
vmkdrivers/src_9/include/linux/workqueue.h: *  @n: name of the work_struct to declare
vmkdrivers/src_9/include/linux/workqueue.h: *  Declares and initializes a work_struct with the given name, using the
vmkdrivers/src_9/include/linux/workqueue.h:   struct work_struct n = __WORK_INITIALIZER(n, f)
vmkdrivers/src_9/include/linux/workqueue.h:   struct work_struct n = __WORK_INITIALIZER(n, f, d)
vmkdrivers/src_9/include/linux/workqueue.h: *  PREPARE_WORK - Initialize a work_struct
vmkdrivers/src_9/include/linux/workqueue.h: *  @_work: name of the work_struct to prepare
vmkdrivers/src_9/include/linux/workqueue.h: *  Initializes the given work_struct (@_work), using the
vmkdrivers/src_9/include/linux/workqueue.h: *  INIT_WORK - Initialize all of a work_struct
vmkdrivers/src_9/include/linux/workqueue.h: *  @_work: name of the work_struct to prepare
vmkdrivers/src_9/include/linux/workqueue.h: *  Initializes the given work_struct (@_work)
vmkdrivers/src_9/include/linux/workqueue.h:extern int FASTCALL(queue_work(struct workqueue_struct *wq, struct work_struct *work));
vmkdrivers/src_9/include/linux/workqueue.h:   struct work_struct *work, unsigned long delay);
vmkdrivers/src_9/include/linux/workqueue.h:extern int FASTCALL(schedule_work(struct work_struct *work));
vmkdrivers/src_9/include/linux/workqueue.h:void cancel_rearming_delayed_work(struct work_struct *work);
vmkdrivers/src_9/include/linux/workqueue.h:                   struct work_struct *);
vmkdrivers/src_9/include/linux/workqueue.h:extern int vmklnx_cancel_work_sync(struct work_struct *work, struct timer_list *timer);
vmkdrivers/src_9/include/linux/workqueue.h: *  cancel_work_sync - block until a work_struct's callback has terminated
vmkdrivers/src_9/include/linux/workqueue.h:static inline int cancel_work_sync(struct work_struct *work)
vmkdrivers/src_9/include/linux/workqueue.h: *  cancel_delayed_work_sync - block until a work_struct's callback has terminated
vmkdrivers/src_9/include/linux/aio.h:   struct work_struct   wq;
vmkdrivers/src_9/include/linux/usb.h:   struct work_struct reset_ws;   /* for resets in atomic context */


What you're looking for is the text struct work_struct { and it's in the workqueue.h file. Here is the structure definition:

Code:
struct work_struct {
        unsigned long pending;
        struct list_head entry;
        work_func_t func;
        volatile void *wq_data;
        vmk_ModuleID module_id;
};


There IS another work_struct definition later in the file:

Code:
struct work_struct {
        unsigned long pending;
        struct list_head entry;
        void (*func)(void *);
        void *data;
        volatile void *wq_data;
        struct timer_list timer;
};


The first work_struct definition is applied if __VMKLNX__ is set (we've seen that before, it is set in our build script as a compile option) and the second definition is applied if isn't set.

So at this point we have enough information to understand the problem. The VMware environment has a modified workqueue.h with a different work_struct format applied. Because it has a modified work_struct struct, is also has a modified INIT_WORK macro. Our driver code comes along and drops the carefully modified INIT_WORK macro, and provides one which it likes but which is oblivious to our non-standard work_struct.

So the short answer to this problem is that the redefined INIT_WORK macro is getting us in trouble. What to do? As before, we'll let the VMWare code take precedence and comment out the redefinition of INIT_WORK in our kcompat.h file at line 1505:

Code:
/* #undef INIT_WORK
#define INIT_WORK(_work, _func) \
do { \
        INIT_LIST_HEAD(&(_work)->entry); \
        (_work)->pending = 0; \
        (_work)->func = (void (*)(void *))_func; \
        (_work)->data = _work; \
        init_timer(&(_work)->timer); \
} while (0)
*/


Let's do another compilation run and see what's changed:

Code:
build@esx-build:~/vsphere/vmkdrivers-gpl$ ./build-atl1c.sh 2>&1
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c: In function 'atl1c_shutdown':
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:2755: warning: implicit declaration of function 'atl1c_suspend'
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c: In function 'atl1c_probe':
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:2871: warning: implicit declaration of function 'alloc_etherdev'
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:2871: warning: assignment makes pointer from integer without a cast
vmkdrivers/src_9/drivers/net/atl1c/at_common_main.c: In function 'at_common_suspend':
vmkdrivers/src_9/drivers/net/atl1c/at_common_main.c:32: warning: implicit declaration of function 'atl1e_suspend'
vmkdrivers/src_9/drivers/net/atl1c/at_common_main.c:40: warning: implicit declaration of function 'atl1c_suspend'
vmkdrivers/src_9/drivers/net/atl1c/at_common_main.c: At top level:
vmkdrivers/src_9/drivers/net/atl1c/at_common_main.c:27: warning: 'at_common_suspend' defined but not used
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c: In function 'atl1e_probe':
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:269: warning: implicit declaration of function 'alloc_etherdev'
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:269: warning: assignment makes pointer from integer without a cast
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c: In function 'atl1e_suspend':
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:592: error: 'retval' undeclared (first use in this function)
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:592: error: (Each undeclared identifier is reported only once
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:592: error: for each function it appears in.)
GNU ld (Linux/GNU Binutils) 2.17.50.0.15.20070418
/home/build/toolchain/lin32/binutils-2.17.50.0.15-modcall/bin/x86_64-linux-ld: BLD/build/vmkdriver-atl1c-CUR/release/vmkernel64/SUBDIRS/vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.o: No such file: No such file or directory


Yes, we're making good progress here. If you scan down that output, it seems like there's really only 1 error left to deal with, because those 3 error messages all refer to the same problem on line 592.

If you open vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c and move to line 592 you'll find:

Code:
retval = atl1e_power_ctrl_suspend_init(hw);


The error message says that "retval" is undeclared in function atl1e_suspend. This seems like a fairly simple error message. Local variable declarations are typically at the start of a function so that is the first place to look. Here are the first 25 or so lines:

Code:
atl1e_suspend(struct pci_dev *pdev, pm_message_t state)
{
#define AT_SUSPEND_LINK_TIMEOUT 50
    struct net_device *netdev = pci_get_drvdata(pdev);
    struct atl1e_adapter *adapter = netdev_priv(netdev);
    struct atl1e_hw * hw = &adapter->hw;
    //u16 speed, duplex;
    u32 ctrl = 0;
    u32 mac_ctrl_data = 0;
    u32 wol_ctrl_data = 0;
    u16 mii_advertise_data = 0;
    u16 mii_bmsr_data = 0;
    u16 mii_intr_status_data = 0;
    u32 wufc = adapter->wol;
    u32 i;
#ifdef CONFIG_PM
    int retval = 0;
#endif

    DEBUGFUNC("atl1e_suspend !");

    if (netif_running(netdev)) {
        WARN_ON(test_bit(__AT_RESETTING, &adapter->flags));
        atl1e_down(adapter);
    }




The declaration is present but it's between a compiler directive to only include it if CONFIG_PM is set as a define. So we can infer that CONFIG_PM is probably not set when we compile and that's why retval isn't declared later.

As a quick and dirty solution to this, you can simply comment out the compiler directive to make the declaration occur in all circumstances.

Code:
//#ifdef CONFIG_PM
    int retval = 0;
//#endif



We may end up revisiting that later. Let's try again with a compilation run:

Code:
build@esx-build:~/vsphere/vmkdrivers-gpl$ ./build-atl1c.sh
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c: In function 'atl1c_shutdown':
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:2755: warning: implicit declaration of function 'atl1c_suspend'
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c: In function 'atl1c_probe':
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:2871: warning: implicit declaration of function 'alloc_etherdev'
vmkdrivers/src_9/drivers/net/atl1c/atl1c_main.c:2871: warning: assignment makes pointer from integer without a cast
vmkdrivers/src_9/drivers/net/atl1c/at_common_main.c: In function 'at_common_suspend':
vmkdrivers/src_9/drivers/net/atl1c/at_common_main.c:32: warning: implicit declaration of function 'atl1e_suspend'
vmkdrivers/src_9/drivers/net/atl1c/at_common_main.c:40: warning: implicit declaration of function 'atl1c_suspend'
vmkdrivers/src_9/drivers/net/atl1c/at_common_main.c: At top level:
vmkdrivers/src_9/drivers/net/atl1c/at_common_main.c:27: warning: 'at_common_suspend' defined but not used
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c: In function 'atl1e_probe':
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:269: warning: implicit declaration of function 'alloc_etherdev'
vmkdrivers/src_9/drivers/net/atl1c/atl1e_main.c:269: warning: assignment makes pointer from integer without a cast
GNU ld (Linux/GNU Binutils) 2.17.50.0.15.20070418


See that? No errors. Let's double check that the output directory really contains a module:

Code:
build@esx-build:~/vsphere/vmkdrivers-gpl$ ls -l BLD/build/vmkdriver-atl1c-CUR/release/vmkernel64/atl1c
-rw-rw-r-- 1 build build 8025712 Mar 24 19:27 BLD/build/vmkdriver-atl1c-CUR/release/vmkernel64/atl1c



Looking good. As in part 1 of this guide, if you have an operating target ESXI server, you can simply scp the file over, otherwise if you're working with a system that you can't even get installed because of the lack of the driver you are trying to make, you'll need to copy the module over to the system using the USB flash drive technique I describe in another post. For the sake of simplicity I will assume you have a running system you can simply scp the module to:

Code:
build@esx-build:~/vsphere/vmkdrivers-gpl$ scp BLD/build/vmkdriver-atl1c-CUR/release/vmkernel64/atl1c root@YOUTHOST:/tmp


Next ssh in to your ESXI host and try to insert the new module you just copied over:

Code:
~ # vmkload_mod /tmp/atl1c
vmkload_mod: Can not load module /tmp/atl1c: Unresolved symbol
~ #


Uh oh. Unlike Part 2 of the guide where I left you on a happy note, in this part of the guide I'm going to leave you with your bubble burst. The journey isn't over yet!


Sun Mar 24, 2013 5:47 pm
Profile

Joined: Sun Mar 24, 2013 10:36 am
Posts: 20
Reply with quote
Post Re: ESXI 5.x Drivers Part 3: Compiling
THANK YOU!!!!! I owe you a beer my friend.

I followed your instructions for the sunhme net drivers. I was much more lucky than you :)

Code:
[root@localhost vmkdrivers-gpl]# ./build-sunhme.sh 
vmkdrivers/src_9/drivers/net/sunhme/sunhme.c: In function 'get_hme_mac_nonsparc':
vmkdrivers/src_9/drivers/net/sunhme/sunhme.c:2961: warning: unused variable 'size'
vmkdrivers/src_9/drivers/net/sunhme/sunhme.c: In function 'happy_meal_pci_probe':
vmkdrivers/src_9/drivers/net/sunhme/sunhme.c:3159: warning: assignment discards qualifiers from pointer target type


Code:
/tmp # vmkload_mod sunhme
Module sunhme loaded successfully


Code:
/tmp # esxcfg-nics -l
Name    PCI           Driver      Link Speed     Duplex MAC Address       MTU    Description                   
vmnic1  0000:07:00.00 r8168       Up   100Mbps   Full   8c:89:a5:6c:e7:32 1500   Realtek Realtek 8168 Gigabit Ethernet
vmnic32 0000:05:00.01 sunhme      Down 0Mbps     Half   08:00:20:c0:e3:6f 1500   Sun Microsystems Computer Corp. Happy Meal 10/100 Ethernet [hme]
vmnic33 0000:05:01.01 sunhme      Down 0Mbps     Half   08:00:20:c5:62:b5 1500   Sun Microsystems Computer Corp. Happy Meal 10/100 Ethernet [hme]
vmnic34 0000:05:02.01 sunhme      Down 0Mbps     Half   08:00:20:ac:be:d2 1500   Sun Microsystems Computer Corp. Happy Meal 10/100 Ethernet [hme]
vmnic35 0000:05:03.01 sunhme      Down 0Mbps     Half   08:00:20:74:3c:4c 1500   Sun Microsystems Computer Corp. Happy Meal 10/100 Ethernet [hme]


luckily, there was only one .c and .o file with these drivers. Much less complex than your drivers. Here was my whole script:

Code:
[root@localhost vmkdrivers-gpl]# cat build-sunhme.sh
#!/bin/sh

rm -rf BLD/build/vmkdriver-sunhme-CUR/

# Use gcc version 4.1.2-9
# Below is the internal VMWare location.  Please change as required for your
# installed location.
CC=/home/build/toolchain/lin32/gcc-4.1.2-9/bin/x86_64-linux-gcc

# Use ld from binutils-2.17.50.0.15-modcall
# Below is the internal VMWare location.  Please change as required for your
# installed location.
LD=/home/build/toolchain/lin32/binutils-2.17.50.0.15-modcall/bin/x86_64-linux-ld

# Use GNU grep 2.5.1
GREP=grep
# Use GNU sed 4.5.1
SED=sed
# Use GNU xargs 4.2.27
XARGS=xargs
# Use mkdir from GNU coreutils 5.97
MKDIR=mkdir

# Create output directories
$GREP -v -e "SED" build-sunhme.sh \
| $GREP -o -e "-o [^ ]*\."            \
| $SED -e 's?-o \(.*\)/[^/]*\.?\1?'   \
| $GREP -v -e "\*"                    \
| $XARGS $MKDIR -p

$CC -fwrapv -fno-working-directory -g -ggdb3 -O2 -fno-strict-aliasing -Wall -Werror -Wstrict-prototypes -fPIE -falign-functions=4 -falign-jumps=4 -falign-loops=4 -ffreestanding -fno-common -fno-omit-frame-pointer -fno-strength-reduce -march=x86-64 -mcmodel=small -minline-all-stringops -mno-red-zone -nostartfiles -nostdlib --sysroot=/nowhere -Wno-error -Wdeclaration-after-statement -Wno-unused-value -Wno-pointer-sign -Wno-strict-prototypes -Wno-declaration-after-statement -Wno-declaration-after-statement -DCONFIG_COMPAT -DCONFIG_PROC_FS -DCPU=x86-64 -DDEBUG_STUB -DESX3_NETWORKING_NOT_DONE_YET -DGPLED_CODE -DKBUILD_MODNAME=\"sunhme\" -DLINUX_MODULE_AUX_HEAP_NAME=vmklnx_sunhme -DLINUX_MODULE_HEAP_INITIAL=1024*100 -DLINUX_MODULE_HEAP_MAX=1024*4096 -DLINUX_MODULE_HEAP_NAME=vmklnx_sunhme -DLINUX_MODULE_SKB_HEAP -DLINUX_MODULE_SKB_HEAP_INITIAL=512*1024 -DLINUX_MODULE_SKB_HEAP_MAX=22*1024*1024 -DLINUX_MODULE_VERSION=\"1.20\" -DMODULE -DNET_DRIVER -DVMKERNEL_MODULE -DVMK_DEVKIT_HAS_API_VMKAPI_BASE -DVMK_DEVKIT_HAS_API_VMKAPI_DEVICE -DVMK_DEVKIT_HAS_API_VMKAPI_ISCSI -DVMK_DEVKIT_HAS_API_VMKAPI_NET -DVMK_DEVKIT_HAS_API_VMKAPI_SCSI -DVMK_DEVKIT_IS_DDK -DVMK_DEVKIT_USES_BINARY_COMPATIBLE_APIS -DVMK_DEVKIT_USES_PUBLIC_APIS -DVMNIX -DVMX86_RELEASE -DVMX86_SERVER -DVMX86_VPROBES -D_LINUX -D__KERNEL__ -D__VMKERNEL_MODULE__ -D__VMKERNEL__ -D__VMKLNX__ -D__VMK_GCC_BUG_ALIGNMENT_PADDING__ -D__VMWARE__ -Ivmkdrivers/src_9/drivers/net/sunhme -IBLD/build/version -IBLD/build/HEADERS/vmkdrivers-vmkernel/vmkernel64/release -Ivmkdrivers/src_9/include -Ivmkdrivers/src_9/include/vmklinux_9 -IBLD/build/HEADERS/CUR-9-vmkdrivers-asm-x64/vmkernel64/release -Ivmkdrivers/src_9/drivers/net -IBLD/build/HEADERS/vmkapi-current-all-public-bincomp/vmkernel64/release -include bora/vmkernel/distribute/push-hidden.h -include vmkdrivers/src_9/include/linux/autoconf.h -c -o BLD/build/vmkdriver-sunhme-CUR/release/vmkernel64/SUBDIRS/vmkdrivers/src_9/drivers/net/sunhme/sunhme.o vmkdrivers/src_9/drivers/net/sunhme/sunhme.c
$CC -fwrapv -fno-working-directory -g -ggdb3 -O2 -fno-strict-aliasing -Wall -Werror -Wstrict-prototypes -fPIE -falign-functions=4 -falign-jumps=4 -falign-loops=4 -ffreestanding -fno-common -fno-omit-frame-pointer -fno-strength-reduce -march=x86-64 -mcmodel=small -minline-all-stringops -mno-red-zone -nostartfiles -nostdlib --sysroot=/nowhere -Wno-error -Wdeclaration-after-statement -Wno-unused-value -Wno-pointer-sign -Wno-strict-prototypes -Wno-declaration-after-statement -Wno-declaration-after-statement -DCONFIG_COMPAT -DCONFIG_PROC_FS -DCPU=x86-64 -DDEBUG_STUB -DESX3_NETWORKING_NOT_DONE_YET -DGPLED_CODE -DKBUILD_MODNAME=\"sunhme\" -DLINUX_MODULE_AUX_HEAP_NAME=vmklnx_sunhme -DLINUX_MODULE_HEAP_INITIAL=1024*100 -DLINUX_MODULE_HEAP_MAX=1024*4096 -DLINUX_MODULE_HEAP_NAME=vmklnx_sunhme -DLINUX_MODULE_SKB_HEAP -DLINUX_MODULE_SKB_HEAP_INITIAL=512*1024 -DLINUX_MODULE_SKB_HEAP_MAX=22*1024*1024 -DLINUX_MODULE_VERSION=\"1.20\" -DMODULE -DNET_DRIVER -DVMKERNEL_MODULE -DVMK_DEVKIT_HAS_API_VMKAPI_BASE -DVMK_DEVKIT_HAS_API_VMKAPI_DEVICE -DVMK_DEVKIT_HAS_API_VMKAPI_ISCSI -DVMK_DEVKIT_HAS_API_VMKAPI_NET -DVMK_DEVKIT_HAS_API_VMKAPI_SCSI -DVMK_DEVKIT_IS_DDK -DVMK_DEVKIT_USES_BINARY_COMPATIBLE_APIS -DVMK_DEVKIT_USES_PUBLIC_APIS -DVMNIX -DVMX86_RELEASE -DVMX86_SERVER -DVMX86_VPROBES -D_LINUX -D__KERNEL__ -D__VMKERNEL_MODULE__ -D__VMKERNEL__ -D__VMKLNX__ -D__VMK_GCC_BUG_ALIGNMENT_PADDING__ -D__VMWARE__ -Ivmkdrivers/src_9/drivers/net/sunhme -IBLD/build/version -IBLD/build/HEADERS/vmkdrivers-vmkernel/vmkernel64/release -Ivmkdrivers/src_9/include -Ivmkdrivers/src_9/include/vmklinux_9 -IBLD/build/HEADERS/CUR-9-vmkdrivers-asm-x64/vmkernel64/release -Ivmkdrivers/src_9/drivers/net -IBLD/build/HEADERS/vmkapi-current-all-public-bincomp/vmkernel64/release -include bora/vmkernel/distribute/push-hidden.h -include vmkdrivers/src_9/include/linux/autoconf.h -c -o BLD/build/vmkdriver-sunhme-CUR/release/vmkernel64/SUBDIRS/vmkdrivers/src_9/common/vmklinux_module.o vmkdrivers/src_9/common/vmklinux_module.c
$LD -v -r -o BLD/build/vmkdriver-sunhme-CUR/release/vmkernel64/sunhme --whole-archive BLD/build/vmkdriver-sunhme-CUR/release/vmkernel64/SUBDIRS/vmkdrivers/src_9/drivers/net/sunhme/sunhme.o BLD/build/vmkdriver-sunhme-CUR/release/vmkernel64/SUBDIRS/vmkdrivers/src_9/common/vmklinux_module.o

[root@localhost vmkdrivers-gpl]#


I am testing now... I will let you know.


Mon Mar 25, 2013 5:31 pm
Profile

Joined: Sun Mar 24, 2013 10:36 am
Posts: 20
Reply with quote
Post Re: ESXI 5.x Drivers Part 3: Compiling
One note, when rebooting ESXi the module does not load automatically. I have to run 'vmkload_mod sunhme' when I reboot.


Mon Mar 25, 2013 7:58 pm
Profile

Joined: Mon Jan 28, 2013 5:09 pm
Posts: 100
Reply with quote
Post ESXI 5.x Drivers Part 3: Compiling
Oh that is great news. To load automatically it will need packaging properly as a .vib I think


Mon Mar 25, 2013 8:02 pm
Profile

Joined: Sun Mar 24, 2013 10:36 am
Posts: 20
Reply with quote
Post Re: ESXI 5.x Drivers Part 3: Compiling
found this on another post, going to give it a try

Code:
[root@node02 ~]# cat /etc/rc.local
#!/bin/sh
#
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don’t
# want to do the full Sys V style init stuff.
vmkload_mod sunhme
touch /var/lock/subsys/local


Mon Mar 25, 2013 8:18 pm
Profile

Joined: Sun Mar 24, 2013 10:36 am
Posts: 20
Reply with quote
Post Re: ESXI 5.x Drivers Part 3: Compiling
This did not work :P still trying.


Mon Mar 25, 2013 9:19 pm
Profile

Joined: Mon Jan 28, 2013 5:09 pm
Posts: 100
Reply with quote
Post ESXI 5.x Drivers Part 3: Compiling
Did you pack it as a vib with the right pci.ids etc?


Tue Mar 26, 2013 6:31 am
Profile

Joined: Sun Mar 24, 2013 10:36 am
Posts: 20
Reply with quote
Post Re: ESXI 5.x Drivers Part 3: Compiling
Have not tried that yet... I wonder if the sig.pkcs7 is required, as I am feeling lazy and hoping I can just package it up without the cert.

I pulled a random network VIB from vmware and found 3 files: descriptor.xml, net-igb (the driver), sig.pkcs7

descriptor.xml gives me some clues

Code:
<vib version="5.0"><type>bootbank</type><name>net-igb</name><version>3.4.7.3-1OEM.500.0.0.472560</version><vendor>Intel</vendor><summary>igb: net driver for VMware ESX</summary><description>Intel(R) Gigabit Ethernet Network Driver</description><release-date>2012-07-23T20:49:21.561844+00:00</release-date><urls/><relationships><depends><constraint name="vmkapi_2_0_0_0"/><constraint name="com.vmware.driverAPI-9.2.0.0"/></depends><conflicts/><replaces/><provides/><compatibleWith/></relationships><software-tags><tag>driver</tag><tag>module</tag></software-tags><system-requires><maintenance-mode>true</maintenance-mode></system-requires><file-list><file>etc/vmware/driver.map.d/igb.map</file><file>usr/lib/vmware/vmkmod/igb</file><file>usr/share/hwdata/driver.pciids.d/igb.ids</file></file-list><acceptance-level>certified</acceptance-level><live-install-allowed>false</live-install-allowed><live-remove-allowed>false</live-remove-allowed><cimom-restart>false</cimom-restart><stateless-ready>false</stateless-ready><overlay>false</overlay><payloads><payload name="net-igb" type="vgz" size="83200"><checksum checksum-type="sha-256">0f12f38354574e5f9d5a08a5b2cf529015961b2ad08d8aa524e3e94dea0e7e0b</checksum><checksum checksum-type="sha-1" verify-process="gunzip">06535da85407c2c300a9baecf7dd4c4d1324165e</checksum></payload></payloads></vib>


this looks like a start:
Code:
<file-list><file>etc/vmware/driver.map.d/igb.map</file><file>usr/lib/vmware/vmkmod/igb</file><file>usr/share/hwdata/driver.pciids.d/igb.ids</file></file-list>


and maybe tweaking this will remove the cert check
Code:
<acceptance-level>certified</acceptance-level>


Once I have a little time to sit and go though the xml and do some trial-and-error i will post back my results.

google-fu brought me this little gem: http://www.yellow-bricks.com/2011/11/29 ... vib-files/

I am feeling very good right now.


Tue Mar 26, 2013 7:47 am
Profile

Joined: Sun Mar 24, 2013 10:36 am
Posts: 20
Reply with quote
Post Re: ESXI 5.x Drivers Part 3: Compiling
It turns out I may have been quite lucky. I found my sunhme driver files here: http://www.kernelcrash.com/blog/using-a ... 009/08/22/

Someone there had already run the original .c file through some script that added some ESXi stuff to it. I found the original source (http://www.cs.fsu.edu/~baker/devices/lx ... v=2.6.25.8) and am seeing what the diffs are. Had I not found that esxi4 sunhme driver, my adventure might not have been this easy.


Tue Mar 26, 2013 9:05 am
Profile

Joined: Sun Mar 24, 2013 10:36 am
Posts: 20
Reply with quote
Post Re: ESXI 5.x Drivers Part 3: Compiling
for shits and gigs, here is the diff between the 2 files:

New code added:
Code:
63 // Stuff for ESX compile
63 #define csum_offset csum
64


Diffs
old
Code:
        save_and_cli(flags);
        tlp = &tx_log[txlog_cur_entry];
        tlp->tstamp = (unsigned int)jiffies;
        tlp->tx_new = hp->tx_new;
        tlp->tx_old = hp->tx_old;
        tlp->action = a;
        tlp->status = s;
        txlog_cur_entry = (txlog_cur_entry + 1) & (TX_LOG_LEN - 1);
        restore_flags(flags);

Code:

 static void get_hme_mac_nonsparc(struct pci_dev *pdev, unsigned char *dev_addr)
 {
         size_t size;
         void __iomem *p = pci_map_rom(pdev, &size);

 
         if (p) {


                 int index = 0;
                 int found;
 
                 if (is_quattro_p(pdev))
                         index = PCI_SLOT(pdev->devfn);
 
                 found = readb(p) == 0x55 &&
                         readb(p + 1) == 0xaa &&
                         find_eth_addr_in_vpd(p, (64 * 1024), index, dev_addr);
                 pci_unmap_rom(pdev, p);
                 if (found)
                         return;
         }
 

         /* Sun MAC prefix then 3 random bytes. */
         dev_addr[0] = 0x08;
         dev_addr[1] = 0x00;
         dev_addr[2] = 0x20;
         get_random_bytes(&dev_addr[3], 3);
         return;
 }


new
Code:
   local_irq_save(flags);
   tlp = &tx_log[txlog_cur_entry];
   tlp->tstamp = (unsigned int)jiffies;
   tlp->tx_new = hp->tx_new;
   tlp->tx_old = hp->tx_old;
   tlp->action = a;
   tlp->status = s;
   txlog_cur_entry = (txlog_cur_entry + 1) & (TX_LOG_LEN - 1);
   local_irq_restore(flags);

Code:
// Warning cheap hack below, because ESX does not have the pci_map_rom or pci_unmap_rom
// routines
static void get_hme_mac_nonsparc(struct pci_dev *pdev, unsigned char *dev_addr)
{
   size_t size;
   //void __iomem *p = pci_map_rom(pdev, &size);
   void __iomem *p = NULL;

//   if (p) {
// Never execute this bit
   if (0) {
      int index = 0;
      int found;

      if (is_quattro_p(pdev))
         index = PCI_SLOT(pdev->devfn);

      found = readb(p) == 0x55 &&
         readb(p + 1) == 0xaa &&
         find_eth_addr_in_vpd(p, (64 * 1024), index, dev_addr);
      //pci_unmap_rom(pdev, p);
      if (found)
         return;
   }

// Here we just always returned random MAC addresses which I agree is a bad solution. To be fixed later.
   /* Sun MAC prefix then 3 random bytes. */
   dev_addr[0] = 0x08;
   dev_addr[1] = 0x00;
   dev_addr[2] = 0x20;
   get_random_bytes(&dev_addr[3], 3);
   return;
}


I am going to try to compile the esx driver using the original source and see how it goes. I will let you know :) I will probably try creating the VIB first. Should have something tonight.


Last edited by ch0psu3y on Tue Mar 26, 2013 12:12 pm, edited 1 time in total.



Tue Mar 26, 2013 10:09 am
Profile
Display posts from previous:  Sort by  
Reply to topic   [ 21 posts ]  Go to page 1, 2, 3  Next

Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by STSoftware for PTF.