[PATCH] powerpc: Align p_end

2013-12-22 Thread Anton Blanchard

p_end is an 8 byte value embedded in the text section. This means it
is only 4 byte aligned when it should be 8 byte aligned. Fix this
by adding an explicit alignment.

This fixes an issue where POWER7 little endian builds with 
CONFIG_RELOCATABLE=y fail to boot.

Signed-off-by: Anton Blanchard an...@samba.org
---

diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 2ae41ab..fad2abd 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -470,6 +470,7 @@ _STATIC(__after_prom_start)
mtctr   r8
bctr
 
+.balign 8
 p_end: .llong  _end - _stext
 
 4: /* Now copy the rest of the kernel up to _end */
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 4/4] powerpc: Don't return to BE mode when we are already there

2013-12-22 Thread Alexander Graf
Our Little Endian kernels can now live in a world where they are
running with Big Endian interrupts enabled. That is great for kexec,
because now we don't have to switch back to Big Endian mode.

Indicate this in the code. Only try to go into Big Endian mode when
we're not already there yet.

Signed-off-by: Alexander Graf ag...@suse.de
---
 arch/powerpc/platforms/pseries/setup.c | 11 ++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/platforms/pseries/setup.c 
b/arch/powerpc/platforms/pseries/setup.c
index fb5d98c..7db1cf1 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -446,10 +446,15 @@ static void pSeries_machine_kexec(struct kimage *image)
 #endif
 
 #ifdef __LITTLE_ENDIAN__
+static bool ile_enabled;
+
 long pseries_big_endian_exceptions(void)
 {
long rc;
 
+   if (!ile_enabled)
+   return H_SUCCESS;
+
while (1) {
rc = enable_big_endian_exceptions();
if (!H_IS_LONG_BUSY(rc))
@@ -498,8 +503,12 @@ static long pseries_little_endian_exceptions(void)
 
while (1) {
rc = enable_little_endian_exceptions();
-   if (!H_IS_LONG_BUSY(rc))
+
+   if (!H_IS_LONG_BUSY(rc)) {
+   ile_enabled = true;
return rc;
+   }
+
mdelay(get_longbusy_msecs(rc));
}
 }
-- 
1.8.1.4

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 2/4] powerpc: Add relocation code for fixups

2013-12-22 Thread Alexander Graf
We need to patch an instruction that is covered by the fixup
framework. If we don't do anything about it we end up getting
our own patched instruction unpatched by nops by the fixups.

So add an export to the fixup code that allows us to tell it
that an instruction moved location in memory. This works because
we move the instruction into a different location, but still
execute it.

Signed-off-by: Alexander Graf ag...@suse.de
---
 arch/powerpc/include/asm/cputable.h |  2 ++
 arch/powerpc/lib/feature-fixups.c   | 22 ++
 2 files changed, 24 insertions(+)

diff --git a/arch/powerpc/include/asm/cputable.h 
b/arch/powerpc/include/asm/cputable.h
index 0d4939b..c981f99 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -99,6 +99,8 @@ extern unsigned int __start___ftr_fixup, __stop___ftr_fixup;
 extern struct cpu_spec *identify_cpu(unsigned long offset, unsigned int pvr);
 extern void do_feature_fixups(unsigned long value, void *fixup_start,
  void *fixup_end);
+extern void relocate_fixup_entry(void *fixup_start, void *fixup_end,
+void *old_addr, void *new_addr);
 
 extern const char *powerpc_base_platform;
 
diff --git a/arch/powerpc/lib/feature-fixups.c 
b/arch/powerpc/lib/feature-fixups.c
index 7a8a748..33996a4 100644
--- a/arch/powerpc/lib/feature-fixups.c
+++ b/arch/powerpc/lib/feature-fixups.c
@@ -151,6 +151,28 @@ void do_final_fixups(void)
 #endif
 }
 
+/*
+ * This changes the internal fixup location of a code block from
+ * old_addr to new_addr.
+ */
+void relocate_fixup_entry(void *fixup_start, void *fixup_end,
+ void *old_addr, void *new_addr)
+{
+   struct fixup_entry *fcur, *fend;
+
+   fcur = fixup_start;
+   fend = fixup_end;
+
+   for (; fcur  fend; fcur++) {
+   long diff = (long)new_addr -
+   (long)calc_addr(fcur, fcur-start_off);
+   if (calc_addr(fcur, fcur-start_off) == old_addr) {
+   fcur-start_off += diff;
+   fcur-end_off += diff;
+   }
+   }
+}
+
 #ifdef CONFIG_FTR_FIXUP_SELFTEST
 
 #define check(x)   \
-- 
1.8.1.4

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 0/4] powerpc: Enable ILE on pSeries without H_MODE_SET

2013-12-22 Thread Alexander Graf
Howdy,

There are a few machines out there that would be pretty ppc64le capable
if only it wasn't for the hypervisor that's running on them.

The problem is that we need to run in ILE (interrupts delivered in little
endian) mode to run our normal interrupt vectors. The hypercall to enable
this mode is not available on PowerVM.

However, we can try to be smart here. Instead of configuring the hypervisor
to run interrupts in little endian mode, we can just bring ourselves back
to little endian on every interrupt.

We do this by patching every interrupt handler with a branch instruction
at the beginning which jumps into a tiny helper that turns on MSR.LE and
resumes the interrupt handler.

This is not the most smart thing to do performance wise, but it does have
a really nice side effect: We do not impact hypervisors that do support
H_SET_MODE. This is important, as we want to be as fast as possible on machines
that are supposed to run Little Endian guests.

As a tiny side effect we also clobber CFAR in every interrupt, rendering
the whole thing pretty useless. So we don't get nice and shiny perf and
debugging helps. Oh well.

Given that the alternatives to all of this would either be

  a) Not run at all or
  b) Incur performance penalties for good systems or
  c) Add significant maintenance burden on us

I'm quite convinced this is the way we want to go.


Enjoy,

Alex

Alexander Graf (4):
  powerpc: Add global exports for all interrupt vectors
  powerpc: Add relocation code for fixups
  powerpc: Add hack to make ppc64le work on hosts without ILE
  powerpc: Don't return to BE mode when we are already there

 arch/powerpc/include/asm/cputable.h|   2 +
 arch/powerpc/kernel/Makefile   |   3 +
 arch/powerpc/kernel/exceptions-64s.S   |   5 ++
 arch/powerpc/kernel/fake_ile.S | 101 +
 arch/powerpc/kernel/vmlinux.lds.S  |  14 +
 arch/powerpc/lib/feature-fixups.c  |  22 +++
 arch/powerpc/platforms/pseries/setup.c |  61 +++-
 7 files changed, 207 insertions(+), 1 deletion(-)
 create mode 100644 arch/powerpc/kernel/fake_ile.S

-- 
1.8.1.4

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 1/4] powerpc: Add global exports for all interrupt vectors

2013-12-22 Thread Alexander Graf
We need to access every interrupt vector we can find soon, so let's
make them all visible through names to outside code.

Signed-off-by: Alexander Graf ag...@suse.de
---
 arch/powerpc/kernel/exceptions-64s.S | 5 +
 1 file changed, 5 insertions(+)

diff --git a/arch/powerpc/kernel/exceptions-64s.S 
b/arch/powerpc/kernel/exceptions-64s.S
index 9f905e4..fcd039f 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -148,6 +148,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
 NOTEST, 0x100)
 
. = 0x200
+   .globl machine_check_pSeries_1
 machine_check_pSeries_1:
/* This is moved out of line as it can be patched by FW, but
 * some code path might still want to branch into the original
@@ -328,24 +329,28 @@ hv_doorbell_trampoline:
 * trickery is thus necessary
 */
. = 0xf00
+   .global performance_monitor_pseries_trampoline
 performance_monitor_pseries_trampoline:
SET_SCRATCH0(r13)
EXCEPTION_PROLOG_0(PACA_EXGEN)
b   performance_monitor_pSeries
 
. = 0xf20
+   .global altivec_unavailable_pseries_trampoline
 altivec_unavailable_pseries_trampoline:
SET_SCRATCH0(r13)
EXCEPTION_PROLOG_0(PACA_EXGEN)
b   altivec_unavailable_pSeries
 
. = 0xf40
+   .global vsx_unavailable_pseries_trampoline
 vsx_unavailable_pseries_trampoline:
SET_SCRATCH0(r13)
EXCEPTION_PROLOG_0(PACA_EXGEN)
b   vsx_unavailable_pSeries
 
. = 0xf60
+   .global facility_unavailable_trampoline
 facility_unavailable_trampoline:
SET_SCRATCH0(r13)
EXCEPTION_PROLOG_0(PACA_EXGEN)
-- 
1.8.1.4

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 3/4] powerpc: Add hack to make ppc64le work on hosts without ILE

2013-12-22 Thread Alexander Graf
Some hypervisors don't implement the H_SET_MODE hypercall that we
need to set the ILE bit in LPCR which allows us to execute interrupts
in little endian mode.

However otherwise we would be able to run on those hypervisors just
fine.

So let's be creative. This patch creates a few small helpers that
work without register clobbering that execute in big endian mode.

Every interrupt gets patched with a branch instruction as the first
instruction which jumps into their respective helper. That helper
enables MSR.LE and returns back to the original interrupt.

That way we can keep our interrupt handlers in little endian code
while the hypervisor is unaware that we need them to be in little
endian.

Signed-off-by: Alexander Graf ag...@suse.de
---
 arch/powerpc/kernel/Makefile   |   3 +
 arch/powerpc/kernel/fake_ile.S | 101 +
 arch/powerpc/kernel/vmlinux.lds.S  |  14 +
 arch/powerpc/platforms/pseries/setup.c |  50 
 4 files changed, 168 insertions(+)
 create mode 100644 arch/powerpc/kernel/fake_ile.S

diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 445cb6e..31842e6 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -131,6 +131,9 @@ endif
 
 obj-$(CONFIG_EPAPR_PARAVIRT)   += epapr_paravirt.o epapr_hcalls.o
 obj-$(CONFIG_KVM_GUEST)+= kvm.o kvm_emul.o
+ifeq ($(CONFIG_CPU_LITTLE_ENDIAN),y)
+obj-$(CONFIG_PPC_BOOK3S_64)+= fake_ile.o
+endif
 
 # Disable GCOV in odd or sensitive code
 GCOV_PROFILE_prom_init.o := n
diff --git a/arch/powerpc/kernel/fake_ile.S b/arch/powerpc/kernel/fake_ile.S
new file mode 100644
index 000..21e9bd7
--- /dev/null
+++ b/arch/powerpc/kernel/fake_ile.S
@@ -0,0 +1,101 @@
+/*
+ * PowerPC helpers for hypervisors without ILE implementation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright SUSE Linux Products GmbH 2013
+ *
+ * Authors: Alexander Graf ag...@suse.de
+ */
+
+#include asm/reg.h
+#include asm/ppc_asm.h
+#include asm/asm-offsets.h
+#include asm/exception-64s.h
+
+/* Little Endian fixups for hosts that don't support Little Endian */
+
+#define FAKE_ILE_HANDLER(handler, area) \
+\
+/* This runs in BE mode */  \
+fake_ile_##handler: \
+   .section __be_patch,a ;\
+   .llong fake_ile_##handler   ;\
+   .previous   ;\
+   SET_SCRATCH0(r13)   ;\
+   GET_PACA(r13)   ;\
+   std r9, area + EX_R9(r13)   ;\
+   std r10, area + EX_R10(r13) ;\
+   mfsrr0  r9  ;\
+   mfsrr1  r10 ;\
+   std r9, area + EX_SRR0(r13) ;\
+   std r10, area + EX_R11(r13) ;\
+   mflrr9  ;\
+   bl  1f  ;\
+   1:  ;\
+   mflrr10 ;\
+   mtlrr9  ;\
+   addir9, r10, back_to_interrupt_##handler - 1b   ;\
+   mfmsr   r10 ;\
+   ori r10, r10, MSR_LE;\
+   mtsrr0  r9  ;\
+   mtsrr1  r10 ;\
+   ld  r9, area + EX_SRR0(r13) ;\
+   ld  r10, area + EX_R11(r13) ;\
+   RFI ;\
+   end_fake_ile_##handler: ;\
+   .section __be_patch,a ;\
+   .llong end_fake_ile_##handler   ;\
+   .previous   ;\
+   ;\
+/* This runs 

[PATCH] ibmveth: Fix more little endian issues

2013-12-22 Thread Alexander Graf
The ibmveth driver is memcpy()'ing the mac address between a variable
(register) and memory. This assumes a certain endianness of the
system, so let's make that implicit assumption work again.

This patch adds be64_to_cpu() calls to all places where the mac address
gets memcpy()'ed into a local variable.

Signed-off-by: Alexander Graf ag...@suse.de
---
 drivers/net/ethernet/ibm/ibmveth.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/ibm/ibmveth.c 
b/drivers/net/ethernet/ibm/ibmveth.c
index 952d795..97f4ee96 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -581,7 +581,7 @@ static int ibmveth_open(struct net_device *netdev)
adapter-rx_queue.toggle = 1;
 
memcpy(mac_address, netdev-dev_addr, netdev-addr_len);
-   mac_address = mac_address  16;
+   mac_address = be64_to_cpu(mac_address)  16;
 
rxq_desc.fields.flags_len = IBMVETH_BUF_VALID |
adapter-rx_queue.queue_len;
@@ -1186,6 +1186,7 @@ static void ibmveth_set_multicast_list(struct net_device 
*netdev)
/* add the multicast address to the filter table */
unsigned long mcast_addr = 0;
memcpy(((char *)mcast_addr)+2, ha-addr, ETH_ALEN);
+   mcast_addr = cpu_to_be64(mcast_addr);
lpar_rc = h_multicast_ctrl(adapter-vdev-unit_address,
   IbmVethMcastAddFilter,
   mcast_addr);
-- 
1.8.1.4

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH v2] powernv: eeh: add buffer for P7IOC hub error data

2013-12-22 Thread Gavin Shan
On Fri, Dec 20, 2013 at 01:06:01PM -0600, Brian W Hart wrote:
V2: Replace driver-global 'hub_diag' with a per-PHB hub diag structure.

Prevent ioda_eeh_hub_diag() from clobbering itself when called by supplying
a per-PHB buffer for P7IOC hub diagnostic data.  Take care to inform OPAL of
the correct size for the buffer.

Signed-off-by: Brian W Hart ha...@linux.vnet.ibm.com

Acked-by: Gavin Shan sha...@linux.vnet.ibm.com

We also need backport it to stable kernel 3.11+

---
 arch/powerpc/platforms/powernv/eeh-ioda.c | 15 ++-
 arch/powerpc/platforms/powernv/pci.h  |  4 +++-
 2 files changed, 5 insertions(+), 14 deletions(-)

diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c 
b/arch/powerpc/platforms/powernv/eeh-ioda.c
index 8184ef5..4790275 100644
--- a/arch/powerpc/platforms/powernv/eeh-ioda.c
+++ b/arch/powerpc/platforms/powernv/eeh-ioda.c
@@ -36,7 +36,6 @@
 #include powernv.h
 #include pci.h

-static char *hub_diag = NULL;
 static int ioda_eeh_nb_init = 0;

 static int ioda_eeh_event(struct notifier_block *nb,
@@ -140,15 +139,6 @@ static int ioda_eeh_post_init(struct pci_controller *hose)
   ioda_eeh_nb_init = 1;
   }

-  /* We needn't HUB diag-data on PHB3 */
-  if (phb-type == PNV_PHB_IODA1  !hub_diag) {
-  hub_diag = (char *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
-  if (!hub_diag) {
-  pr_err(%s: Out of memory !\n, __func__);
-  return -ENOMEM;
-  }
-  }
-
 #ifdef CONFIG_DEBUG_FS
   if (phb-dbgfs) {
   debugfs_create_file(err_injct_outbound, 0600,
@@ -633,11 +623,10 @@ static void ioda_eeh_hub_diag_common(struct 
OpalIoP7IOCErrorData *data)
 static void ioda_eeh_hub_diag(struct pci_controller *hose)
 {
   struct pnv_phb *phb = hose-private_data;
-  struct OpalIoP7IOCErrorData *data;
+  struct OpalIoP7IOCErrorData *data = phb-diag.hub_diag;
   long rc;

-  data = (struct OpalIoP7IOCErrorData *)ioda_eeh_hub_diag;
-  rc = opal_pci_get_hub_diag_data(phb-hub_id, data, PAGE_SIZE);
+  rc = opal_pci_get_hub_diag_data(phb-hub_id, data, sizeof *data);
   if (rc != OPAL_SUCCESS) {
   pr_warning(%s: Failed to get HUB#%llx diag-data (%ld)\n,
  __func__, phb-hub_id, rc);
diff --git a/arch/powerpc/platforms/powernv/pci.h 
b/arch/powerpc/platforms/powernv/pci.h
index 911c24e..1ed8d5f 100644
--- a/arch/powerpc/platforms/powernv/pci.h
+++ b/arch/powerpc/platforms/powernv/pci.h
@@ -172,11 +172,13 @@ struct pnv_phb {
   } ioda;
   };

-  /* PHB status structure */
+  /* PHB and hub status structure */
   union {
   unsigned char   blob[PNV_PCI_DIAG_BUF_SIZE];
   struct OpalIoP7IOCPhbErrorData  p7ioc;
+  struct OpalIoP7IOCErrorData hub_diag;
   } diag;
+
 };

 extern struct pci_ops pnv_pci_ops;

Thanks,
Gavin

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH] powerpc/mpic_timer: fix the time calculation is not accurate

2013-12-22 Thread Dongsheng Wang
From: Wang Dongsheng dongsheng.w...@freescale.com

When the timer GTCCR toggle bit is inverted, we calculated the rest
of the time is not accurate. So we need to ignore this bit.

Signed-off-by: Wang Dongsheng dongsheng.w...@freescale.com

diff --git a/arch/powerpc/sysdev/mpic_timer.c b/arch/powerpc/sysdev/mpic_timer.c
index 22d7d57..0fb70c9 100644
--- a/arch/powerpc/sysdev/mpic_timer.c
+++ b/arch/powerpc/sysdev/mpic_timer.c
@@ -41,6 +41,7 @@
 #define MPIC_TIMER_TCR_ROVR_OFFSET 24
 
 #define TIMER_STOP 0x8000
+#define GTCCR_TOG  0x8000
 #define TIMERS_PER_GROUP   4
 #define MAX_TICKS  (~0U  1)
 #define MAX_TICKS_CASCADE  (~0U)
@@ -96,8 +97,15 @@ static void convert_ticks_to_time(struct timer_group_priv 
*priv,
time-tv_sec = (__kernel_time_t)div_u64(ticks, priv-timerfreq);
tmp_sec = (u64)time-tv_sec * (u64)priv-timerfreq;
 
-   time-tv_usec = (__kernel_suseconds_t)
-   div_u64((ticks - tmp_sec) * 100, priv-timerfreq);
+   time-tv_usec = 0;
+
+   /*
+* In some cases tmp_sec may be greater than ticks, because in the
+* process of calculation ticks and tmp_sec will be rounded.
+*/
+   if (tmp_sec = ticks)
+   time-tv_usec = (__kernel_suseconds_t)
+   div_u64((ticks - tmp_sec) * 100, priv-timerfreq);
 
return;
 }
@@ -327,11 +335,13 @@ void mpic_get_remain_time(struct mpic_timer *handle, 
struct timeval *time)
casc_priv = priv-timer[handle-num].cascade_handle;
if (casc_priv) {
tmp_ticks = in_be32(priv-regs[handle-num].gtccr);
+   tmp_ticks = ~GTCCR_TOG;
ticks = ((u64)tmp_ticks  UINT_MAX) * (u64)MAX_TICKS_CASCADE;
tmp_ticks = in_be32(priv-regs[handle-num - 1].gtccr);
ticks += tmp_ticks;
} else {
ticks = in_be32(priv-regs[handle-num].gtccr);
+   ticks = ~GTCCR_TOG;
}
 
convert_ticks_to_time(priv, ticks, time);
-- 
1.8.5


___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 02/21] net: freescale: slight optimization of addr compare

2013-12-22 Thread Ding Tianhong
Use the recently added and possibly more efficient
ether_addr_equal_unaligned to instead of memcmp.

Cc: Li Yang le...@freescale.com
Cc: net...@vger.kernel.org
Cc: linuxppc-dev@lists.ozlabs.org
Cc: linux-ker...@vger.kernel.org
Signed-off-by: Ding Tianhong dingtianh...@huawei.com
---
 drivers/net/ethernet/freescale/ucc_geth.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/ucc_geth.c 
b/drivers/net/ethernet/freescale/ucc_geth.c
index 5548b6d..88a1525 100644
--- a/drivers/net/ethernet/freescale/ucc_geth.c
+++ b/drivers/net/ethernet/freescale/ucc_geth.c
@@ -437,7 +437,7 @@ static void hw_add_addr_in_hash(struct ucc_geth_private 
*ugeth,
 
 static inline int compare_addr(u8 **addr1, u8 **addr2)
 {
-   return memcmp(addr1, addr2, ETH_ALEN);
+   return !ether_addr_equal_unaligned(addr1, addr2);
 }
 
 #ifdef DEBUG
-- 
1.8.0


___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH] ibmveth: Fix more little endian issues

2013-12-22 Thread Anton Blanchard

Hi Alex,

 The ibmveth driver is memcpy()'ing the mac address between a variable
 (register) and memory. This assumes a certain endianness of the
 system, so let's make that implicit assumption work again.

Nice catch! I don't like how the driver has two different methods
for creating these MAC addresses, both without comments. How does
this look?

Anton
--

The hypervisor expects MAC addresses passed in registers to be big
endian u64. Create a helper function called ibmveth_encode_mac_addr
which does the right thing in both big and little endian.

We were storing the MAC address in a long in struct ibmveth_adapter.
It's never used so remove it - we don't need another place in the
driver where we create endian issues with MAC addresses.

Reported-by: Alexander Graf ag...@suse.de
Signed-off-by: Anton Blanchard an...@samba.org
---

diff --git a/drivers/net/ethernet/ibm/ibmveth.c 
b/drivers/net/ethernet/ibm/ibmveth.c
index 952d795..044178b 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -523,6 +523,17 @@ retry:
return rc;
 }
 
+/*
+ * The hypervisor expects MAC addresses passed in registers to be
+ * big endian u64.
+ */
+static unsigned long ibmveth_encode_mac_addr(char *mac)
+{
+   unsigned long encoded = 0;
+   memcpy(((char *)encoded) + 2, mac, ETH_ALEN);
+   return cpu_to_be64(encoded);
+}
+
 static int ibmveth_open(struct net_device *netdev)
 {
struct ibmveth_adapter *adapter = netdev_priv(netdev);
@@ -580,8 +591,7 @@ static int ibmveth_open(struct net_device *netdev)
adapter-rx_queue.num_slots = rxq_entries;
adapter-rx_queue.toggle = 1;
 
-   memcpy(mac_address, netdev-dev_addr, netdev-addr_len);
-   mac_address = mac_address  16;
+   mac_address = ibmveth_encode_mac_addr(netdev-dev_addr);
 
rxq_desc.fields.flags_len = IBMVETH_BUF_VALID |
adapter-rx_queue.queue_len;
@@ -1184,8 +1194,8 @@ static void ibmveth_set_multicast_list(struct net_device 
*netdev)
/* add the addresses to the filter table */
netdev_for_each_mc_addr(ha, netdev) {
/* add the multicast address to the filter table */
-   unsigned long mcast_addr = 0;
-   memcpy(((char *)mcast_addr)+2, ha-addr, ETH_ALEN);
+   unsigned long mcast_addr;
+   mcast_addr = ibmveth_encode_mac_addr(ha-addr);
lpar_rc = h_multicast_ctrl(adapter-vdev-unit_address,
   IbmVethMcastAddFilter,
   mcast_addr);
@@ -1369,9 +1379,6 @@ static int ibmveth_probe(struct vio_dev *dev, const 
struct vio_device_id *id)
 
netif_napi_add(netdev, adapter-napi, ibmveth_poll, 16);
 
-   adapter-mac_addr = 0;
-   memcpy(adapter-mac_addr, mac_addr_p, ETH_ALEN);
-
netdev-irq = dev-irq;
netdev-netdev_ops = ibmveth_netdev_ops;
netdev-ethtool_ops = netdev_ethtool_ops;
@@ -1380,7 +1387,7 @@ static int ibmveth_probe(struct vio_dev *dev, const 
struct vio_device_id *id)
NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
netdev-features |= netdev-hw_features;
 
-   memcpy(netdev-dev_addr, adapter-mac_addr, netdev-addr_len);
+   memcpy(netdev-dev_addr, mac_addr_p, ETH_ALEN);
 
for (i = 0; i  IBMVETH_NUM_BUFF_POOLS; i++) {
struct kobject *kobj = adapter-rx_buff_pool[i].kobj;
diff --git a/drivers/net/ethernet/ibm/ibmveth.h 
b/drivers/net/ethernet/ibm/ibmveth.h
index 84066ba..2c636cb 100644
--- a/drivers/net/ethernet/ibm/ibmveth.h
+++ b/drivers/net/ethernet/ibm/ibmveth.h
@@ -139,7 +139,6 @@ struct ibmveth_adapter {
 struct napi_struct napi;
 struct net_device_stats stats;
 unsigned int mcastFilterSize;
-unsigned long mac_addr;
 void * buffer_list_addr;
 void * filter_list_addr;
 dma_addr_t buffer_list_dma;
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev