summaryrefslogtreecommitdiff
path: root/drivers/net
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-05-09 17:00:51 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2019-05-09 17:00:51 -0700
commit601e6bcc4ef02bda2831d5ac8133947b5edf597b (patch)
treef08e159e7b48e2e906c97faddd37b6f08d8c775a /drivers/net
parent9b6c9e96f941c5ab13dad7278a3622f58e5672fc (diff)
parent6c9f05441477e29783e8391d06c067e4a3b23d47 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking fixes from David Miller: "Several bug fixes, many are quick merge-window regression cures: - When NLM_F_EXCL is not set, allow same fib rule insertion. From Hangbin Liu. - Several cures in sja1105 DSA driver (while loop exit condition fix, return of negative u8, etc.) from Vladimir Oltean. - Handle tx/rx delays in realtek PHY driver properly, from Serge Semin. - Double free in cls_matchall, from Pieter Jansen van Vuuren. - Disable SIOCSHWTSTAMP in macvlan/vlan containers, from Hangbin Liu. - Endainness fixes in aqc111, from Oliver Neukum. - Handle errors in packet_init properly, from Haibing Yue. - Various W=1 warning fixes in kTLS, from Jakub Kicinski" * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (34 commits) nfp: add missing kdoc net/tls: handle errors from padding_length() net/tls: remove set but not used variables docs/btf: fix the missing section marks nfp: bpf: fix static check error through tightening shift amount adjustment selftests: bpf: initialize bpf_object pointers where needed packet: Fix error path in packet_init net/tcp: use deferred jump label for TCP acked data hook net: aquantia: fix undefined devm_hwmon_device_register_with_info reference aqc111: fix double endianness swap on BE aqc111: fix writing to the phy on BE aqc111: fix endianness issue in aqc111_change_mtu vlan: disable SIOCSHWTSTAMP in container macvlan: disable SIOCSHWTSTAMP in container tipc: fix hanging clients using poll with EPOLLOUT flag tuntap: synchronize through tfiles array instead of tun->numqueues tuntap: fix dividing by zero in ebpf queue selection dwmac4_prog_mtl_tx_algorithms() missing write operation ptp_qoriq: fix NULL access if ptp dt node missing net/sched: avoid double free on matchall reoffload ...
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/dsa/lantiq_gswip.c8
-rw-r--r--drivers/net/dsa/sja1105/sja1105_main.c6
-rw-r--r--drivers/net/dsa/sja1105/sja1105_spi.c11
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/aq_drvinfo.c5
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3_enet.c2
-rw-r--r--drivers/net/ethernet/netronome/nfp/bpf/jit.c13
-rw-r--r--drivers/net/ethernet/netronome/nfp/ccm.h2
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_repr.c1
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_port.c16
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c2
-rw-r--r--drivers/net/macvlan.c2
-rw-r--r--drivers/net/phy/realtek.c70
-rw-r--r--drivers/net/tun.c14
-rw-r--r--drivers/net/usb/aqc111.c31
14 files changed, 157 insertions, 26 deletions
diff --git a/drivers/net/dsa/lantiq_gswip.c b/drivers/net/dsa/lantiq_gswip.c
index 553831df58fe..4e64835deac2 100644
--- a/drivers/net/dsa/lantiq_gswip.c
+++ b/drivers/net/dsa/lantiq_gswip.c
@@ -1235,7 +1235,7 @@ static void gswip_port_fast_age(struct dsa_switch *ds, int port)
err = gswip_pce_table_entry_read(priv, &mac_bridge);
if (err) {
- dev_err(priv->dev, "failed to read mac brigde: %d\n",
+ dev_err(priv->dev, "failed to read mac bridge: %d\n",
err);
return;
}
@@ -1252,7 +1252,7 @@ static void gswip_port_fast_age(struct dsa_switch *ds, int port)
mac_bridge.valid = false;
err = gswip_pce_table_entry_write(priv, &mac_bridge);
if (err) {
- dev_err(priv->dev, "failed to write mac brigde: %d\n",
+ dev_err(priv->dev, "failed to write mac bridge: %d\n",
err);
return;
}
@@ -1328,7 +1328,7 @@ static int gswip_port_fdb(struct dsa_switch *ds, int port,
err = gswip_pce_table_entry_write(priv, &mac_bridge);
if (err)
- dev_err(priv->dev, "failed to write mac brigde: %d\n", err);
+ dev_err(priv->dev, "failed to write mac bridge: %d\n", err);
return err;
}
@@ -1360,7 +1360,7 @@ static int gswip_port_fdb_dump(struct dsa_switch *ds, int port,
err = gswip_pce_table_entry_read(priv, &mac_bridge);
if (err) {
- dev_err(priv->dev, "failed to write mac brigde: %d\n",
+ dev_err(priv->dev, "failed to write mac bridge: %d\n",
err);
return err;
}
diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c
index 50ff625c85d6..0663b78a2f6c 100644
--- a/drivers/net/dsa/sja1105/sja1105_main.c
+++ b/drivers/net/dsa/sja1105/sja1105_main.c
@@ -1070,7 +1070,11 @@ static u8 sja1105_stp_state_get(struct sja1105_private *priv, int port)
return BR_STATE_LEARNING;
if (mac[port].ingress && mac[port].egress && mac[port].dyn_learn)
return BR_STATE_FORWARDING;
- return -EINVAL;
+ /* This is really an error condition if the MAC was in none of the STP
+ * states above. But treating the port as disabled does nothing, which
+ * is adequate, and it also resets the MAC to a known state later on.
+ */
+ return BR_STATE_DISABLED;
}
/* For situations where we need to change a setting at runtime that is only
diff --git a/drivers/net/dsa/sja1105/sja1105_spi.c b/drivers/net/dsa/sja1105/sja1105_spi.c
index 244a94ccfc18..2eb70b8acfc3 100644
--- a/drivers/net/dsa/sja1105/sja1105_spi.c
+++ b/drivers/net/dsa/sja1105/sja1105_spi.c
@@ -466,14 +466,15 @@ int sja1105_static_config_upload(struct sja1105_private *priv)
"invalid, retrying...\n");
continue;
}
- } while (--retries && (status.crcchkl == 1 || status.crcchkg == 1 ||
- status.configs == 0 || status.ids == 1));
+ /* Success! */
+ break;
+ } while (--retries);
if (!retries) {
rc = -EIO;
dev_err(dev, "Failed to upload config to device, giving up\n");
goto out;
- } else if (retries != RETRIES - 1) {
+ } else if (retries != RETRIES) {
dev_info(dev, "Succeeded after %d tried\n", RETRIES - retries);
}
@@ -483,7 +484,7 @@ out:
return rc;
}
-struct sja1105_regs sja1105et_regs = {
+static struct sja1105_regs sja1105et_regs = {
.device_id = 0x0,
.prod_id = 0x100BC3,
.status = 0x1,
@@ -508,7 +509,7 @@ struct sja1105_regs sja1105et_regs = {
.rmii_ext_tx_clk = {0x100018, 0x10001F, 0x100026, 0x10002D, 0x100034},
};
-struct sja1105_regs sja1105pqrs_regs = {
+static struct sja1105_regs sja1105pqrs_regs = {
.device_id = 0x0,
.prod_id = 0x100BC3,
.status = 0x1,
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_drvinfo.c b/drivers/net/ethernet/aquantia/atlantic/aq_drvinfo.c
index f5a92b2a5cd6..adad6a7acabe 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_drvinfo.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_drvinfo.c
@@ -13,6 +13,7 @@
#include "aq_drvinfo.h"
+#if IS_REACHABLE(CONFIG_HWMON)
static int aq_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, long *value)
{
@@ -123,3 +124,7 @@ int aq_drvinfo_init(struct net_device *ndev)
return err;
}
+
+#else
+int aq_drvinfo_init(struct net_device *ndev) { return 0; }
+#endif
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
index 18711e0f9bdf..196a3d780dcf 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
@@ -810,7 +810,7 @@ static int hns3_set_l2l3l4(struct sk_buff *skb, u8 ol4_proto,
u8 il4_proto, u32 *type_cs_vlan_tso,
u32 *ol_type_vlan_len_msec)
{
- unsigned char *l2_hdr = l2_hdr = skb->data;
+ unsigned char *l2_hdr = skb->data;
u32 l4_proto = ol4_proto;
union l4_hdr_info l4;
union l3_hdr_info l3;
diff --git a/drivers/net/ethernet/netronome/nfp/bpf/jit.c b/drivers/net/ethernet/netronome/nfp/bpf/jit.c
index f272247d1708..d4bf0e694541 100644
--- a/drivers/net/ethernet/netronome/nfp/bpf/jit.c
+++ b/drivers/net/ethernet/netronome/nfp/bpf/jit.c
@@ -328,7 +328,18 @@ __emit_shf(struct nfp_prog *nfp_prog, u16 dst, enum alu_dst_ab dst_ab,
return;
}
- if (sc == SHF_SC_L_SHF)
+ /* NFP shift instruction has something special. If shift direction is
+ * left then shift amount of 1 to 31 is specified as 32 minus the amount
+ * to shift.
+ *
+ * But no need to do this for indirect shift which has shift amount be
+ * 0. Even after we do this subtraction, shift amount 0 will be turned
+ * into 32 which will eventually be encoded the same as 0 because only
+ * low 5 bits are encoded, but shift amount be 32 will fail the
+ * FIELD_PREP check done later on shift mask (0x1f), due to 32 is out of
+ * mask range.
+ */
+ if (sc == SHF_SC_L_SHF && shift)
shift = 32 - shift;
insn = OP_SHF_BASE |
diff --git a/drivers/net/ethernet/netronome/nfp/ccm.h b/drivers/net/ethernet/netronome/nfp/ccm.h
index e2fe4b867958..ac963b128203 100644
--- a/drivers/net/ethernet/netronome/nfp/ccm.h
+++ b/drivers/net/ethernet/netronome/nfp/ccm.h
@@ -54,6 +54,8 @@ static inline unsigned int nfp_ccm_get_tag(struct sk_buff *skb)
/**
* struct nfp_ccm - common control message handling
+ * @app: APP handle
+ *
* @tag_allocator: bitmap of control message tags in use
* @tag_alloc_next: next tag bit to allocate
* @tag_alloc_last: next tag bit to be freed
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
index 036edcc1fa18..1eef446036d6 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
@@ -273,6 +273,7 @@ const struct net_device_ops nfp_repr_netdev_ops = {
.ndo_fix_features = nfp_repr_fix_features,
.ndo_set_features = nfp_port_set_features,
.ndo_set_mac_address = eth_mac_addr,
+ .ndo_get_port_parent_id = nfp_port_get_port_parent_id,
.ndo_get_devlink_port = nfp_devlink_get_devlink_port,
};
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_port.c b/drivers/net/ethernet/netronome/nfp/nfp_port.c
index fcd16877e6e0..93c5bfc0510b 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_port.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_port.c
@@ -30,6 +30,22 @@ struct nfp_port *nfp_port_from_netdev(struct net_device *netdev)
return NULL;
}
+int nfp_port_get_port_parent_id(struct net_device *netdev,
+ struct netdev_phys_item_id *ppid)
+{
+ struct nfp_port *port;
+ const u8 *serial;
+
+ port = nfp_port_from_netdev(netdev);
+ if (!port)
+ return -EOPNOTSUPP;
+
+ ppid->id_len = nfp_cpp_serial(port->app->cpp, &serial);
+ memcpy(&ppid->id, serial, ppid->id_len);
+
+ return 0;
+}
+
int nfp_port_setup_tc(struct net_device *netdev, enum tc_setup_type type,
void *type_data)
{
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
index 7e5d5db0d516..b4bb5629de38 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
@@ -192,6 +192,8 @@ static void dwmac4_prog_mtl_tx_algorithms(struct mac_device_info *hw,
default:
break;
}
+
+ writel(value, ioaddr + MTL_OPERATION_MODE);
}
static void dwmac4_set_mtl_tx_queue_weight(struct mac_device_info *hw,
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index b395423b19bc..92efa93649f0 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -836,6 +836,8 @@ static int macvlan_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
switch (cmd) {
case SIOCSHWTSTAMP:
+ if (!net_eq(dev_net(dev), &init_net))
+ break;
case SIOCGHWTSTAMP:
if (netif_device_present(real_dev) && ops->ndo_do_ioctl)
err = ops->ndo_do_ioctl(real_dev, &ifrr, cmd);
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index d6a10f323117..761ce3b1e7bd 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -23,11 +23,15 @@
#define RTL821x_INSR 0x13
+#define RTL821x_EXT_PAGE_SELECT 0x1e
#define RTL821x_PAGE_SELECT 0x1f
#define RTL8211F_INSR 0x1d
#define RTL8211F_TX_DELAY BIT(8)
+#define RTL8211E_TX_DELAY BIT(1)
+#define RTL8211E_RX_DELAY BIT(2)
+#define RTL8211E_MODE_MII_GMII BIT(3)
#define RTL8201F_ISR 0x1e
#define RTL8201F_IER 0x13
@@ -157,16 +161,73 @@ static int rtl8211c_config_init(struct phy_device *phydev)
static int rtl8211f_config_init(struct phy_device *phydev)
{
- u16 val = 0;
+ u16 val;
- /* enable TX-delay for rgmii-id and rgmii-txid, otherwise disable it */
- if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
- phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
+ /* enable TX-delay for rgmii-{id,txid}, and disable it for rgmii and
+ * rgmii-rxid. The RX-delay can be enabled by the external RXDLY pin.
+ */
+ switch (phydev->interface) {
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ val = 0;
+ break;
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ case PHY_INTERFACE_MODE_RGMII_TXID:
val = RTL8211F_TX_DELAY;
+ break;
+ default: /* the rest of the modes imply leaving delay as is. */
+ return 0;
+ }
return phy_modify_paged(phydev, 0xd08, 0x11, RTL8211F_TX_DELAY, val);
}
+static int rtl8211e_config_init(struct phy_device *phydev)
+{
+ int ret = 0, oldpage;
+ u16 val;
+
+ /* enable TX/RX delay for rgmii-* modes, and disable them for rgmii. */
+ switch (phydev->interface) {
+ case PHY_INTERFACE_MODE_RGMII:
+ val = 0;
+ break;
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ val = RTL8211E_TX_DELAY | RTL8211E_RX_DELAY;
+ break;
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ val = RTL8211E_RX_DELAY;
+ break;
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ val = RTL8211E_TX_DELAY;
+ break;
+ default: /* the rest of the modes imply leaving delays as is. */
+ return 0;
+ }
+
+ /* According to a sample driver there is a 0x1c config register on the
+ * 0xa4 extension page (0x7) layout. It can be used to disable/enable
+ * the RX/TX delays otherwise controlled by RXDLY/TXDLY pins. It can
+ * also be used to customize the whole configuration register:
+ * 8:6 = PHY Address, 5:4 = Auto-Negotiation, 3 = Interface Mode Select,
+ * 2 = RX Delay, 1 = TX Delay, 0 = SELRGV (see original PHY datasheet
+ * for details).
+ */
+ oldpage = phy_select_page(phydev, 0x7);
+ if (oldpage < 0)
+ goto err_restore_page;
+
+ ret = phy_write(phydev, RTL821x_EXT_PAGE_SELECT, 0xa4);
+ if (ret)
+ goto err_restore_page;
+
+ ret = phy_modify(phydev, 0x1c, RTL8211E_TX_DELAY | RTL8211E_RX_DELAY,
+ val);
+
+err_restore_page:
+ return phy_restore_page(phydev, oldpage, ret);
+}
+
static int rtl8211b_suspend(struct phy_device *phydev)
{
phy_write(phydev, MII_MMD_DATA, BIT(9));
@@ -239,6 +300,7 @@ static struct phy_driver realtek_drvs[] = {
}, {
PHY_ID_MATCH_EXACT(0x001cc915),
.name = "RTL8211E Gigabit Ethernet",
+ .config_init = &rtl8211e_config_init,
.ack_interrupt = &rtl821x_ack_interrupt,
.config_intr = &rtl8211e_config_intr,
.suspend = genphy_suspend,
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 9d72f8c76c15..abae165dcca5 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -596,13 +596,18 @@ static u16 tun_automq_select_queue(struct tun_struct *tun, struct sk_buff *skb)
static u16 tun_ebpf_select_queue(struct tun_struct *tun, struct sk_buff *skb)
{
struct tun_prog *prog;
+ u32 numqueues;
u16 ret = 0;
+ numqueues = READ_ONCE(tun->numqueues);
+ if (!numqueues)
+ return 0;
+
prog = rcu_dereference(tun->steering_prog);
if (prog)
ret = bpf_prog_run_clear_cb(prog->prog, skb);
- return ret % tun->numqueues;
+ return ret % numqueues;
}
static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb,
@@ -699,6 +704,8 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
tun->tfiles[tun->numqueues - 1]);
ntfile = rtnl_dereference(tun->tfiles[index]);
ntfile->queue_index = index;
+ rcu_assign_pointer(tun->tfiles[tun->numqueues - 1],
+ NULL);
--tun->numqueues;
if (clean) {
@@ -1081,7 +1088,7 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
tfile = rcu_dereference(tun->tfiles[txq]);
/* Drop packet if interface is not attached */
- if (txq >= tun->numqueues)
+ if (!tfile)
goto drop;
if (!rcu_dereference(tun->steering_prog))
@@ -1304,6 +1311,7 @@ static int tun_xdp_xmit(struct net_device *dev, int n,
rcu_read_lock();
+resample:
numqueues = READ_ONCE(tun->numqueues);
if (!numqueues) {
rcu_read_unlock();
@@ -1312,6 +1320,8 @@ static int tun_xdp_xmit(struct net_device *dev, int n,
tfile = rcu_dereference(tun->tfiles[smp_processor_id() %
numqueues]);
+ if (unlikely(!tfile))
+ goto resample;
spin_lock(&tfile->tx_ring.producer_lock);
for (i = 0; i < n; i++) {
diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index aff995be2a31..b86c5ce9a92a 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -320,6 +320,7 @@ static int aqc111_get_link_ksettings(struct net_device *net,
static void aqc111_set_phy_speed(struct usbnet *dev, u8 autoneg, u16 speed)
{
struct aqc111_data *aqc111_data = dev->driver_priv;
+ u32 phy_on_the_wire;
aqc111_data->phy_cfg &= ~AQ_ADV_MASK;
aqc111_data->phy_cfg |= AQ_PAUSE;
@@ -361,7 +362,8 @@ static void aqc111_set_phy_speed(struct usbnet *dev, u8 autoneg, u16 speed)
}
}
- aqc111_write32_cmd(dev, AQ_PHY_OPS, 0, 0, &aqc111_data->phy_cfg);
+ phy_on_the_wire = aqc111_data->phy_cfg;
+ aqc111_write32_cmd(dev, AQ_PHY_OPS, 0, 0, &phy_on_the_wire);
}
static int aqc111_set_link_ksettings(struct net_device *net,
@@ -453,6 +455,8 @@ static int aqc111_change_mtu(struct net_device *net, int new_mtu)
reg16 = 0x1420;
else if (dev->net->mtu <= 16334)
reg16 = 0x1A20;
+ else
+ return 0;
aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_PAUSE_WATERLVL_LOW,
2, &reg16);
@@ -753,6 +757,7 @@ static void aqc111_unbind(struct usbnet *dev, struct usb_interface *intf)
{
struct aqc111_data *aqc111_data = dev->driver_priv;
u16 reg16;
+ u32 phy_on_the_wire;
/* Force bz */
reg16 = SFR_PHYPWR_RSTCTL_BZ;
@@ -766,8 +771,9 @@ static void aqc111_unbind(struct usbnet *dev, struct usb_interface *intf)
aqc111_data->phy_cfg &= ~AQ_ADV_MASK;
aqc111_data->phy_cfg |= AQ_LOW_POWER;
aqc111_data->phy_cfg &= ~AQ_PHY_POWER_EN;
+ phy_on_the_wire = aqc111_data->phy_cfg;
aqc111_write32_cmd_nopm(dev, AQ_PHY_OPS, 0, 0,
- &aqc111_data->phy_cfg);
+ &phy_on_the_wire);
kfree(aqc111_data);
}
@@ -990,6 +996,7 @@ static int aqc111_reset(struct usbnet *dev)
{
struct aqc111_data *aqc111_data = dev->driver_priv;
u8 reg8 = 0;
+ u32 phy_on_the_wire;
dev->rx_urb_size = URB_SIZE;
@@ -1002,8 +1009,9 @@ static int aqc111_reset(struct usbnet *dev)
/* Power up ethernet PHY */
aqc111_data->phy_cfg = AQ_PHY_POWER_EN;
+ phy_on_the_wire = aqc111_data->phy_cfg;
aqc111_write32_cmd(dev, AQ_PHY_OPS, 0, 0,
- &aqc111_data->phy_cfg);
+ &phy_on_the_wire);
/* Set the MAC address */
aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_NODE_ID, ETH_ALEN,
@@ -1034,6 +1042,7 @@ static int aqc111_stop(struct usbnet *dev)
{
struct aqc111_data *aqc111_data = dev->driver_priv;
u16 reg16 = 0;
+ u32 phy_on_the_wire;
aqc111_read16_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
2, &reg16);
@@ -1045,8 +1054,9 @@ static int aqc111_stop(struct usbnet *dev)
/* Put PHY to low power*/
aqc111_data->phy_cfg |= AQ_LOW_POWER;
+ phy_on_the_wire = aqc111_data->phy_cfg;
aqc111_write32_cmd(dev, AQ_PHY_OPS, 0, 0,
- &aqc111_data->phy_cfg);
+ &phy_on_the_wire);
netif_carrier_off(dev->net);
@@ -1322,6 +1332,7 @@ static int aqc111_suspend(struct usb_interface *intf, pm_message_t message)
u16 temp_rx_ctrl = 0x00;
u16 reg16;
u8 reg8;
+ u32 phy_on_the_wire;
usbnet_suspend(intf, message);
@@ -1393,12 +1404,14 @@ static int aqc111_suspend(struct usb_interface *intf, pm_message_t message)
aqc111_write_cmd(dev, AQ_WOL_CFG, 0, 0,
WOL_CFG_SIZE, &wol_cfg);
+ phy_on_the_wire = aqc111_data->phy_cfg;
aqc111_write32_cmd(dev, AQ_PHY_OPS, 0, 0,
- &aqc111_data->phy_cfg);
+ &phy_on_the_wire);
} else {
aqc111_data->phy_cfg |= AQ_LOW_POWER;
+ phy_on_the_wire = aqc111_data->phy_cfg;
aqc111_write32_cmd(dev, AQ_PHY_OPS, 0, 0,
- &aqc111_data->phy_cfg);
+ &phy_on_the_wire);
/* Disable RX path */
aqc111_read16_cmd_nopm(dev, AQ_ACCESS_MAC,
@@ -1415,7 +1428,7 @@ static int aqc111_resume(struct usb_interface *intf)
{
struct usbnet *dev = usb_get_intfdata(intf);
struct aqc111_data *aqc111_data = dev->driver_priv;
- u16 reg16;
+ u16 reg16, oldreg16;
u8 reg8;
netif_carrier_off(dev->net);
@@ -1431,9 +1444,11 @@ static int aqc111_resume(struct usb_interface *intf)
/* Configure RX control register => start operation */
reg16 = aqc111_data->rxctl;
reg16 &= ~SFR_RX_CTL_START;
+ /* needs to be saved in case endianness is swapped */
+ oldreg16 = reg16;
aqc111_write16_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, &reg16);
- reg16 |= SFR_RX_CTL_START;
+ reg16 = oldreg16 | SFR_RX_CTL_START;
aqc111_write16_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, &reg16);
aqc111_set_phy_speed(dev, aqc111_data->autoneg,