IB/mthca: Work around gcc bug on sparc64
authorDavid Howells <dhowells@redhat.com>
Tue, 6 Feb 2007 00:21:08 +0000 (16:21 -0800)
committerRoland Dreier <rolandd@cisco.com>
Sat, 10 Feb 2007 16:00:49 +0000 (08:00 -0800)
For some reason gcc-3.4.5 on sparc64 does:

 WARNING: "____ilog2_NaN" [drivers/infiniband/hw/mthca/ib_mthca.ko] undefined!

Points to note:

 (1) The asm volatile flush/flushw are just markers for viewing what comes out
     in the assembly; removing them has no effect on the result.

 (2) Changing almost anything else in dwh__mthca_arbel_init_srq_context() or
     dwh__mthca_alloc_srq() causes the problem to go away.

The compiler command line issued by the kernel build is:

/opt/crosstool/gcc-3.4.5-glibc-2.3.6/sparc64-unknown-linux-gnu/bin/sparc64-unknown-linux-gnu-gcc -fno-strict-aliasing -fno-common -Os -m64 -mno-fpu -mcpu=ultrasparc -mcmodel=medlow -ffixed-g4 -ffixed-g5 -fcall-used-g7 -Wa,--undeclared-regs -pg -fno-omit-frame-pointer -fno-optimize-sibling-calls -fasynchronous-unwind-tables -g  -c -o drivers/infiniband/hw/mthca/.tmp_mthca_srq.o drivers/infiniband/hw/mthca/mthca_srq.c

This can be reduced to this whilst still retaining the problem:

/opt/crosstool/gcc-3.4.5-glibc-2.3.6/sparc64-unknown-linux-gnu/bin/sparc64-unknown-linux-gnu-gcc -m64 -c -o drivers/infiniband/hw/mthca/mthca_srq.o drivers/infiniband/hw/mthca/mthca_srq.c -Os

Removing -Os or changing it to -O or -O0 thru -O6 gets rid of the problem.

This patch to the kernel code fixes the problem:

Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
drivers/infiniband/hw/mthca/mthca_srq.c

index 10684da33d5853e18e0cea25d9b219fbcd2b3b54..61974b0296ca132e26feacb70d10e556f2d706b4 100644 (file)
@@ -116,11 +116,16 @@ static void mthca_arbel_init_srq_context(struct mthca_dev *dev,
                                         struct mthca_srq *srq,
                                         struct mthca_arbel_srq_context *context)
 {
-       int logsize;
+       int logsize, max;
 
        memset(context, 0, sizeof *context);
 
-       logsize = ilog2(srq->max);
+       /*
+        * Put max in a temporary variable to work around gcc bug
+        * triggered by ilog2() on sparc64.
+        */
+       max = srq->max;
+       logsize = ilog2(max);
        context->state_logsize_srqn = cpu_to_be32(logsize << 24 | srq->srqn);
        context->lkey = cpu_to_be32(srq->mr.ibmr.lkey);
        context->db_index = cpu_to_be32(srq->db_index);