* [PATCH] ibmveth: Fix more little endian issues @ 2013-12-23 1:29 Alexander Graf 2013-12-23 6:38 ` Anton Blanchard 0 siblings, 1 reply; 9+ messages in thread From: Alexander Graf @ 2013-12-23 1:29 UTC (permalink / raw) To: linuxppc-dev; +Cc: Santiago Leon, Dinar Valeev, Anton Blanchard, netdev 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 <agraf@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 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH] ibmveth: Fix more little endian issues 2013-12-23 1:29 [PATCH] ibmveth: Fix more little endian issues Alexander Graf @ 2013-12-23 6:38 ` Anton Blanchard 2013-12-23 10:17 ` Alexander Graf 2013-12-23 14:52 ` Joe Perches 0 siblings, 2 replies; 9+ messages in thread From: Anton Blanchard @ 2013-12-23 6:38 UTC (permalink / raw) To: Alexander Graf; +Cc: Dinar Valeev, Santiago Leon, linuxppc-dev, netdev 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 <agraf@suse.de> Signed-off-by: Anton Blanchard <anton@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; ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH] ibmveth: Fix more little endian issues 2013-12-23 6:38 ` Anton Blanchard @ 2013-12-23 10:17 ` Alexander Graf 2013-12-23 14:52 ` Joe Perches 1 sibling, 0 replies; 9+ messages in thread From: Alexander Graf @ 2013-12-23 10:17 UTC (permalink / raw) To: Anton Blanchard; +Cc: Dinar Valeev, Santiago Leon, linuxppc-dev, netdev On 23.12.2013, at 07:38, Anton Blanchard <anton@samba.org> wrote: >=20 > Hi Alex, >=20 >> 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. >=20 > 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? Heh - I didn't even realize those two places were doing the same thing. Obviously your patch is by far nicer. Reviewed-by: Alexander Graf <agraf@suse.de> Alex >=20 > Anton > -- >=20 > 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. >=20 > 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. >=20 > Reported-by: Alexander Graf <agraf@suse.de> > Signed-off-by: Anton Blanchard <anton@samba.org> > --- >=20 > 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; > } >=20 > +/* > + * 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 =3D 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 =3D netdev_priv(netdev); > @@ -580,8 +591,7 @@ static int ibmveth_open(struct net_device *netdev) > adapter->rx_queue.num_slots =3D rxq_entries; > adapter->rx_queue.toggle =3D 1; >=20 > - memcpy(&mac_address, netdev->dev_addr, netdev->addr_len); > - mac_address =3D mac_address >> 16; > + mac_address =3D ibmveth_encode_mac_addr(netdev->dev_addr); >=20 > rxq_desc.fields.flags_len =3D 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 =3D 0; > - memcpy(((char *)&mcast_addr)+2, ha->addr, = ETH_ALEN); > + unsigned long mcast_addr; > + mcast_addr =3D = ibmveth_encode_mac_addr(ha->addr); > lpar_rc =3D = 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) >=20 > netif_napi_add(netdev, &adapter->napi, ibmveth_poll, 16); >=20 > - adapter->mac_addr =3D 0; > - memcpy(&adapter->mac_addr, mac_addr_p, ETH_ALEN); > - > netdev->irq =3D dev->irq; > netdev->netdev_ops =3D &ibmveth_netdev_ops; > netdev->ethtool_ops =3D &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 |=3D netdev->hw_features; >=20 > - memcpy(netdev->dev_addr, &adapter->mac_addr, netdev->addr_len); > + memcpy(netdev->dev_addr, mac_addr_p, ETH_ALEN); >=20 > for (i =3D 0; i < IBMVETH_NUM_BUFF_POOLS; i++) { > struct kobject *kobj =3D &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; ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] ibmveth: Fix more little endian issues 2013-12-23 6:38 ` Anton Blanchard 2013-12-23 10:17 ` Alexander Graf @ 2013-12-23 14:52 ` Joe Perches 2013-12-24 1:55 ` Anton Blanchard 2013-12-24 4:37 ` [PATCH] ibmveth: Fix more little endian issues Benjamin Herrenschmidt 1 sibling, 2 replies; 9+ messages in thread From: Joe Perches @ 2013-12-23 14:52 UTC (permalink / raw) To: Anton Blanchard Cc: Dinar Valeev, linuxppc-dev, Alexander Graf, netdev, Santiago Leon On Mon, 2013-12-23 at 17:38 +1100, Anton Blanchard wrote: > The hypervisor expects MAC addresses passed in registers to be big > endian u64. So maybe use __be64 declarations? > +static unsigned long ibmveth_encode_mac_addr(char *mac) static __be64 ibmveth_encode_mac_addr(const char *mac) ? etc... ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH] ibmveth: Fix more little endian issues 2013-12-23 14:52 ` Joe Perches @ 2013-12-24 1:55 ` Anton Blanchard 2013-12-25 10:38 ` Ben Hutchings 2014-03-05 3:51 ` ibmveth: Fix endian issues with MAC addresses Anton Blanchard 2013-12-24 4:37 ` [PATCH] ibmveth: Fix more little endian issues Benjamin Herrenschmidt 1 sibling, 2 replies; 9+ messages in thread From: Anton Blanchard @ 2013-12-24 1:55 UTC (permalink / raw) To: Joe Perches Cc: Dinar Valeev, linuxppc-dev, Alexander Graf, netdev, Santiago Leon 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. Signed-off-by: Anton Blanchard <anton@samba.org> Reviewed-by: Alexander Graf <agraf@suse.de> --- v2: annotate with __be64 as suggested by Joe diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c index 952d795..bb9a631 100644 --- a/drivers/net/ethernet/ibm/ibmveth.c +++ b/drivers/net/ethernet/ibm/ibmveth.c @@ -497,7 +497,7 @@ static void ibmveth_cleanup(struct ibmveth_adapter *adapter) } static int ibmveth_register_logical_lan(struct ibmveth_adapter *adapter, - union ibmveth_buf_desc rxq_desc, u64 mac_address) + union ibmveth_buf_desc rxq_desc, __be64 mac_address) { int rc, try_again = 1; @@ -523,10 +523,20 @@ retry: return rc; } +/* The hypervisor expects MAC addresses passed in registers to be + * big endian u64. + */ +static __be64 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); - u64 mac_address = 0; + __be64 mac_address = 0; int rxq_entries = 1; unsigned long lpar_rc; int rc; @@ -580,8 +590,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 +1193,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); + __be64 mcast_addr; + mcast_addr = ibmveth_encode_mac_addr(ha->addr); lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address, IbmVethMcastAddFilter, mcast_addr); @@ -1369,9 +1378,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 +1386,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; ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH] ibmveth: Fix more little endian issues 2013-12-24 1:55 ` Anton Blanchard @ 2013-12-25 10:38 ` Ben Hutchings 2014-03-05 3:51 ` ibmveth: Fix endian issues with MAC addresses Anton Blanchard 1 sibling, 0 replies; 9+ messages in thread From: Ben Hutchings @ 2013-12-25 10:38 UTC (permalink / raw) To: Anton Blanchard Cc: Dinar Valeev, linuxppc-dev, Alexander Graf, netdev, Joe Perches, Santiago Leon On Tue, 2013-12-24 at 12:55 +1100, Anton Blanchard wrote: > 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. [...] > @@ -523,10 +523,20 @@ retry: > return rc; > } > > +/* The hypervisor expects MAC addresses passed in registers to be > + * big endian u64. > + */ > +static __be64 ibmveth_encode_mac_addr(char *mac) > +{ > + unsigned long encoded = 0; u64 > + memcpy(((char *)&encoded) + 2, mac, ETH_ALEN); > + return cpu_to_be64(encoded); > +} [...] So on big-endian systems the byte order of the result will be: 0 0 mac0 mac1 mac2 mac3 mac4 mac5 and on little-endian systems it's: mac5 mac4 mac3 mac2 mac1 mac0 0 0 It seems to me that 'encoded' is actually in big-endian order and this function returns the address in CPU order. So are you sure your explanation isn't backwards, because it looks to me like the driver was already holding the MAC address in big-endian order and perhaps the hypercall mechanism does a byte-swap when the guest is little-endian. Ben. -- Ben Hutchings, Staff Engineer, Solarflare Not speaking for my employer; that's the marketing department's job. They asked us to note that Solarflare product names are trademarked. ^ permalink raw reply [flat|nested] 9+ messages in thread
* ibmveth: Fix endian issues with MAC addresses 2013-12-24 1:55 ` Anton Blanchard 2013-12-25 10:38 ` Ben Hutchings @ 2014-03-05 3:51 ` Anton Blanchard 2014-03-06 21:27 ` David Miller 1 sibling, 1 reply; 9+ messages in thread From: Anton Blanchard @ 2014-03-05 3:51 UTC (permalink / raw) To: Joe Perches, Alexander Graf, Ben Herrenschmidt, Dinar Valeev, Santiago Leon, tony Cc: netdev, linuxppc-dev The code to load a MAC address into a u64 for passing to the hypervisor via a register is broken on little endian. 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. Signed-off-by: Anton Blanchard <anton@samba.org> Cc: stable@vger.kernel.org --- Index: b/drivers/net/ethernet/ibm/ibmveth.c =================================================================== --- a/drivers/net/ethernet/ibm/ibmveth.c +++ b/drivers/net/ethernet/ibm/ibmveth.c @@ -522,10 +522,21 @@ retry: return rc; } +static u64 ibmveth_encode_mac_addr(u8 *mac) +{ + int i; + u64 encoded = 0; + + for (i = 0; i < ETH_ALEN; i++) + encoded = (encoded << 8) | mac[i]; + + return encoded; +} + static int ibmveth_open(struct net_device *netdev) { struct ibmveth_adapter *adapter = netdev_priv(netdev); - u64 mac_address = 0; + u64 mac_address; int rxq_entries = 1; unsigned long lpar_rc; int rc; @@ -579,8 +590,7 @@ static int ibmveth_open(struct net_devic 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; @@ -1183,8 +1193,8 @@ static void ibmveth_set_multicast_list(s /* 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); + u64 mcast_addr; + mcast_addr = ibmveth_encode_mac_addr(ha->addr); lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address, IbmVethMcastAddFilter, mcast_addr); @@ -1372,9 +1382,6 @@ static int ibmveth_probe(struct vio_dev 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; @@ -1383,7 +1390,7 @@ static int ibmveth_probe(struct vio_dev 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; Index: b/drivers/net/ethernet/ibm/ibmveth.h =================================================================== --- a/drivers/net/ethernet/ibm/ibmveth.h +++ b/drivers/net/ethernet/ibm/ibmveth.h @@ -138,7 +138,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; ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: ibmveth: Fix endian issues with MAC addresses 2014-03-05 3:51 ` ibmveth: Fix endian issues with MAC addresses Anton Blanchard @ 2014-03-06 21:27 ` David Miller 0 siblings, 0 replies; 9+ messages in thread From: David Miller @ 2014-03-06 21:27 UTC (permalink / raw) To: anton; +Cc: linuxppc-dev, dvaleev, agraf, netdev, joe, santil From: Anton Blanchard <anton@samba.org> Date: Wed, 5 Mar 2014 14:51:37 +1100 > The code to load a MAC address into a u64 for passing to the > hypervisor via a register is broken on little endian. > > 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. > > Signed-off-by: Anton Blanchard <anton@samba.org> > Cc: stable@vger.kernel.org Applied, thanks Anton. > - memcpy(&adapter->mac_addr, mac_addr_p, ETH_ALEN); ... > - unsigned long mac_addr; That's some scary stuff right there. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] ibmveth: Fix more little endian issues 2013-12-23 14:52 ` Joe Perches 2013-12-24 1:55 ` Anton Blanchard @ 2013-12-24 4:37 ` Benjamin Herrenschmidt 1 sibling, 0 replies; 9+ messages in thread From: Benjamin Herrenschmidt @ 2013-12-24 4:37 UTC (permalink / raw) To: Joe Perches Cc: netdev, Dinar Valeev, linuxppc-dev, Alexander Graf, Anton Blanchard, Santiago Leon On Mon, 2013-12-23 at 06:52 -0800, Joe Perches wrote: > On Mon, 2013-12-23 at 17:38 +1100, Anton Blanchard wrote: > > The hypervisor expects MAC addresses passed in registers to be big > > endian u64. > > So maybe use __be64 declarations? > > > +static unsigned long ibmveth_encode_mac_addr(char *mac) > > static __be64 ibmveth_encode_mac_addr(const char *mac) A register value has no endianness. Only memory content does. Especially talking of a MAC address which is really a byte stream.... (Yes, our __beXX types used without a * are borderline, but we've got used to it). In fact I find the use of memcpy(((char *)&encoded) + 2, mac, ETH_ALEN); Really gross :-) Yes it works with the added cpu_to_be64() but in that specific case, I think it would be nicer to simply load & shift into position the 6 bytes and avoid the endianness issue completely. Cheers, Ben. ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2014-03-06 21:27 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2013-12-23 1:29 [PATCH] ibmveth: Fix more little endian issues Alexander Graf 2013-12-23 6:38 ` Anton Blanchard 2013-12-23 10:17 ` Alexander Graf 2013-12-23 14:52 ` Joe Perches 2013-12-24 1:55 ` Anton Blanchard 2013-12-25 10:38 ` Ben Hutchings 2014-03-05 3:51 ` ibmveth: Fix endian issues with MAC addresses Anton Blanchard 2014-03-06 21:27 ` David Miller 2013-12-24 4:37 ` [PATCH] ibmveth: Fix more little endian issues Benjamin Herrenschmidt
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).