a52832164b
This fixes #12927. SVN-Revision: 35507
94 lines
3 KiB
Diff
94 lines
3 KiB
Diff
commit fa0879e37b59e8e3f130a30a9e6fa515717c5bdd
|
|
Author: Stefan Hajnoczi <stefanha@gmail.com>
|
|
Date: Mon Jan 21 01:17:22 2013 +0000
|
|
|
|
net: split eth_mac_addr for better error handling
|
|
|
|
When we set mac address, software mac address in system and hardware mac
|
|
address all need to be updated. Current eth_mac_addr() doesn't allow
|
|
callers to implement error handling nicely.
|
|
|
|
This patch split eth_mac_addr() to prepare part and real commit part,
|
|
then we can prepare first, and try to change hardware address, then do
|
|
the real commit if hardware address is set successfully.
|
|
|
|
Signed-off-by: Stefan Hajnoczi <stefanha@gmail.com>
|
|
Signed-off-by: Amos Kong <akong@redhat.com>
|
|
Signed-off-by: David S. Miller <davem@davemloft.net>
|
|
|
|
--- a/include/linux/etherdevice.h
|
|
+++ b/include/linux/etherdevice.h
|
|
@@ -40,6 +40,8 @@ extern int eth_header_cache(const struct
|
|
extern void eth_header_cache_update(struct hh_cache *hh,
|
|
const struct net_device *dev,
|
|
const unsigned char *haddr);
|
|
+extern int eth_prepare_mac_addr_change(struct net_device *dev, void *p);
|
|
+extern void eth_commit_mac_addr_change(struct net_device *dev, void *p);
|
|
extern int eth_mac_addr(struct net_device *dev, void *p);
|
|
extern int eth_change_mtu(struct net_device *dev, int new_mtu);
|
|
extern int eth_validate_addr(struct net_device *dev);
|
|
--- a/net/ethernet/eth.c
|
|
+++ b/net/ethernet/eth.c
|
|
@@ -278,16 +278,11 @@ void eth_header_cache_update(struct hh_c
|
|
EXPORT_SYMBOL(eth_header_cache_update);
|
|
|
|
/**
|
|
- * eth_mac_addr - set new Ethernet hardware address
|
|
+ * eth_prepare_mac_addr_change - prepare for mac change
|
|
* @dev: network device
|
|
* @p: socket address
|
|
- *
|
|
- * Change hardware address of device.
|
|
- *
|
|
- * This doesn't change hardware matching, so needs to be overridden
|
|
- * for most real devices.
|
|
*/
|
|
-int eth_mac_addr(struct net_device *dev, void *p)
|
|
+int eth_prepare_mac_addr_change(struct net_device *dev, void *p)
|
|
{
|
|
struct sockaddr *addr = p;
|
|
|
|
@@ -295,9 +290,43 @@ int eth_mac_addr(struct net_device *dev,
|
|
return -EBUSY;
|
|
if (!is_valid_ether_addr(addr->sa_data))
|
|
return -EADDRNOTAVAIL;
|
|
+ return 0;
|
|
+}
|
|
+EXPORT_SYMBOL(eth_prepare_mac_addr_change);
|
|
+
|
|
+/**
|
|
+ * eth_commit_mac_addr_change - commit mac change
|
|
+ * @dev: network device
|
|
+ * @p: socket address
|
|
+ */
|
|
+void eth_commit_mac_addr_change(struct net_device *dev, void *p)
|
|
+{
|
|
+ struct sockaddr *addr = p;
|
|
+
|
|
memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
|
|
/* if device marked as NET_ADDR_RANDOM, reset it */
|
|
dev->addr_assign_type &= ~NET_ADDR_RANDOM;
|
|
+}
|
|
+EXPORT_SYMBOL(eth_commit_mac_addr_change);
|
|
+
|
|
+/**
|
|
+ * eth_mac_addr - set new Ethernet hardware address
|
|
+ * @dev: network device
|
|
+ * @p: socket address
|
|
+ *
|
|
+ * Change hardware address of device.
|
|
+ *
|
|
+ * This doesn't change hardware matching, so needs to be overridden
|
|
+ * for most real devices.
|
|
+ */
|
|
+int eth_mac_addr(struct net_device *dev, void *p)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ ret = eth_prepare_mac_addr_change(dev, p);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+ eth_commit_mac_addr_change(dev, p);
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(eth_mac_addr);
|