summaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/dsa/mv88e6060.c16
-rw-r--r--drivers/net/dsa/mv88e6171.c2
-rw-r--r--drivers/net/dsa/mv88e6xxx.c14
-rw-r--r--drivers/net/ethernet/apm/xgene/Makefile3
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c37
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_hw.c45
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_hw.h34
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_main.c96
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_main.h36
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c389
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h41
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c332
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h53
-rw-r--r--drivers/net/ethernet/broadcom/bcmsysport.c3
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmgenet.c9
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c4
-rw-r--r--drivers/net/ethernet/broadcom/tg3.c10
-rw-r--r--drivers/net/ethernet/brocade/bna/bnad.c2
-rw-r--r--drivers/net/ethernet/chelsio/Kconfig2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4.h4
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c35
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/sge.c5
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_hw.c23
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_msg.h1
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_regs.h5
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c12
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4vf/sge.c5
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h6
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c10
-rw-r--r--drivers/net/ethernet/freescale/fec.h60
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c69
-rw-r--r--drivers/net/ethernet/freescale/fec_ptp.c277
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/mac-fcc.c2
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/mac-scc.c2
-rw-r--r--drivers/net/ethernet/freescale/fsl_pq_mdio.c56
-rw-r--r--drivers/net/ethernet/freescale/gianfar.c70
-rw-r--r--drivers/net/ethernet/freescale/gianfar.h31
-rw-r--r--drivers/net/ethernet/intel/Kconfig12
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_main.c72
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_netdev.c13
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_pci.c1
-rw-r--r--drivers/net/ethernet/intel/igb/igb_main.c7
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c8
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c3
-rw-r--r--drivers/net/ethernet/marvell/Kconfig3
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_rx.c6
-rw-r--r--drivers/net/ethernet/micrel/ks8842.c6
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c6
-rw-r--r--drivers/net/ethernet/sfc/nic.h29
-rw-r--r--drivers/net/ethernet/sfc/tx.c43
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c374
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c4
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac.h3
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c20
-rw-r--r--drivers/net/ethernet/sun/sunvnet.c4
-rw-r--r--drivers/net/ethernet/ti/cpsw.c10
-rw-r--r--drivers/net/ethernet/ti/davinci_cpdma.c5
-rw-r--r--drivers/net/ethernet/tile/tilegx.c22
-rw-r--r--drivers/net/ethernet/tile/tilepro.c8
-rw-r--r--drivers/net/hyperv/netvsc_drv.c26
-rw-r--r--drivers/net/macvlan.c21
-rw-r--r--drivers/net/macvtap.c2
-rw-r--r--drivers/net/phy/micrel.c35
-rw-r--r--drivers/net/ppp/ppp_generic.c2
-rw-r--r--drivers/net/tun.c4
-rw-r--r--drivers/net/usb/r8152.c118
-rw-r--r--drivers/net/virtio_net.c48
-rw-r--r--drivers/net/vmxnet3/vmxnet3_int.h1
-rw-r--r--drivers/net/vxlan.c15
-rw-r--r--drivers/net/wimax/Makefile4
-rw-r--r--drivers/net/wireless/ath/ath.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h4
-rw-r--r--drivers/net/wireless/ath/ath9k/beacon.c12
-rw-r--r--drivers/net/wireless/ath/ath9k/common.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_init.c1
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c55
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/tx99.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c44
-rw-r--r--drivers/net/wireless/ath/main.c8
-rw-r--r--drivers/net/wireless/ath/regd.c14
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c25
-rw-r--r--drivers/net/wireless/hostap/hostap_proc.c5
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2100.c22
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2200.c270
-rw-r--r--drivers/net/wireless/ipw2x00/libipw_rx.c65
-rw-r--r--drivers/net/wireless/ipw2x00/libipw_wx.c16
-rw-r--r--drivers/net/wireless/libertas/cfg.c8
-rw-r--r--drivers/net/wireless/libertas/mesh.c7
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180/dev.c36
-rw-r--r--drivers/net/wireless/rtlwifi/base.c2
-rw-r--r--drivers/net/wireless/rtlwifi/pci.c3
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c8
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h4
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/hw.c2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/hw.c17
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/hw.h1
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/sw.c7
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ee/hw.c8
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8821ae/phy.c15
-rw-r--r--drivers/net/wireless/rtlwifi/usb.c11
-rw-r--r--drivers/net/wireless/rtlwifi/wifi.h2
-rw-r--r--drivers/net/xen-netback/xenbus.c10
-rw-r--r--drivers/net/xen-netfront.c18
104 files changed, 2442 insertions, 1016 deletions
diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c
index 776e965dc9f4..05b0ca3bf71d 100644
--- a/drivers/net/dsa/mv88e6060.c
+++ b/drivers/net/dsa/mv88e6060.c
@@ -21,8 +21,12 @@
static int reg_read(struct dsa_switch *ds, int addr, int reg)
{
- return mdiobus_read(to_mii_bus(ds->master_dev),
- ds->pd->sw_addr + addr, reg);
+ struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev);
+
+ if (bus == NULL)
+ return -EINVAL;
+
+ return mdiobus_read(bus, ds->pd->sw_addr + addr, reg);
}
#define REG_READ(addr, reg) \
@@ -38,8 +42,12 @@ static int reg_read(struct dsa_switch *ds, int addr, int reg)
static int reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
{
- return mdiobus_write(to_mii_bus(ds->master_dev),
- ds->pd->sw_addr + addr, reg, val);
+ struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev);
+
+ if (bus == NULL)
+ return -EINVAL;
+
+ return mdiobus_write(bus, ds->pd->sw_addr + addr, reg, val);
}
#define REG_WRITE(addr, reg, val) \
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index 6365e30138af..1020a7af67cf 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -206,7 +206,7 @@ static int mv88e6171_setup_port(struct dsa_switch *ds, int p)
*/
val = 0x0433;
if (dsa_is_cpu_port(ds, p)) {
- if (ds->dst->tag_protocol == htons(ETH_P_EDSA))
+ if (ds->dst->tag_protocol == DSA_TAG_PROTO_EDSA)
val |= 0x3300;
else
val |= 0x0100;
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index d6f6428b27dc..a6c90cf5634d 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -75,11 +75,14 @@ int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, int reg)
int mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+ struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev);
int ret;
+ if (bus == NULL)
+ return -EINVAL;
+
mutex_lock(&ps->smi_mutex);
- ret = __mv88e6xxx_reg_read(to_mii_bus(ds->master_dev),
- ds->pd->sw_addr, addr, reg);
+ ret = __mv88e6xxx_reg_read(bus, ds->pd->sw_addr, addr, reg);
mutex_unlock(&ps->smi_mutex);
return ret;
@@ -119,11 +122,14 @@ int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr,
int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+ struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev);
int ret;
+ if (bus == NULL)
+ return -EINVAL;
+
mutex_lock(&ps->smi_mutex);
- ret = __mv88e6xxx_reg_write(to_mii_bus(ds->master_dev),
- ds->pd->sw_addr, addr, reg, val);
+ ret = __mv88e6xxx_reg_write(bus, ds->pd->sw_addr, addr, reg, val);
mutex_unlock(&ps->smi_mutex);
return ret;
diff --git a/drivers/net/ethernet/apm/xgene/Makefile b/drivers/net/ethernet/apm/xgene/Makefile
index c643e8a0a0dc..68be565548c0 100644
--- a/drivers/net/ethernet/apm/xgene/Makefile
+++ b/drivers/net/ethernet/apm/xgene/Makefile
@@ -2,5 +2,6 @@
# Makefile for APM X-Gene Ethernet Driver.
#
-xgene-enet-objs := xgene_enet_hw.o xgene_enet_main.o xgene_enet_ethtool.o
+xgene-enet-objs := xgene_enet_hw.o xgene_enet_sgmac.o xgene_enet_xgmac.o \
+ xgene_enet_main.o xgene_enet_ethtool.o
obj-$(CONFIG_NET_XGENE) += xgene-enet.o
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
index 63f2aa54a594..416d6ebfc2ce 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
@@ -59,10 +59,31 @@ static int xgene_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
struct xgene_enet_pdata *pdata = netdev_priv(ndev);
struct phy_device *phydev = pdata->phy_dev;
- if (phydev == NULL)
- return -ENODEV;
+ if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) {
+ if (phydev == NULL)
+ return -ENODEV;
+
+ return phy_ethtool_gset(phydev, cmd);
+ } else if (pdata->phy_mode == PHY_INTERFACE_MODE_SGMII) {
+ cmd->supported = SUPPORTED_1000baseT_Full |
+ SUPPORTED_Autoneg | SUPPORTED_MII;
+ cmd->advertising = cmd->supported;
+ ethtool_cmd_speed_set(cmd, SPEED_1000);
+ cmd->duplex = DUPLEX_FULL;
+ cmd->port = PORT_MII;
+ cmd->transceiver = XCVR_INTERNAL;
+ cmd->autoneg = AUTONEG_ENABLE;
+ } else {
+ cmd->supported = SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE;
+ cmd->advertising = cmd->supported;
+ ethtool_cmd_speed_set(cmd, SPEED_10000);
+ cmd->duplex = DUPLEX_FULL;
+ cmd->port = PORT_FIBRE;
+ cmd->transceiver = XCVR_INTERNAL;
+ cmd->autoneg = AUTONEG_DISABLE;
+ }
- return phy_ethtool_gset(phydev, cmd);
+ return 0;
}
static int xgene_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
@@ -70,10 +91,14 @@ static int xgene_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
struct xgene_enet_pdata *pdata = netdev_priv(ndev);
struct phy_device *phydev = pdata->phy_dev;
- if (phydev == NULL)
- return -ENODEV;
+ if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) {
+ if (phydev == NULL)
+ return -ENODEV;
+
+ return phy_ethtool_sset(phydev, cmd);
+ }
- return phy_ethtool_sset(phydev, cmd);
+ return -EINVAL;
}
static void xgene_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index 812d8d65159b..63ea1941e973 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -402,7 +402,7 @@ static int xgene_mii_phy_read(struct xgene_enet_pdata *pdata,
return data;
}
-void xgene_gmac_set_mac_addr(struct xgene_enet_pdata *pdata)
+static void xgene_gmac_set_mac_addr(struct xgene_enet_pdata *pdata)
{
u32 addr0, addr1;
u8 *dev_addr = pdata->ndev->dev_addr;
@@ -410,7 +410,6 @@ void xgene_gmac_set_mac_addr(struct xgene_enet_pdata *pdata)
addr0 = (dev_addr[3] << 24) | (dev_addr[2] << 16) |
(dev_addr[1] << 8) | dev_addr[0];
addr1 = (dev_addr[5] << 24) | (dev_addr[4] << 16);
- addr1 |= pdata->phy_addr & 0xFFFF;
xgene_enet_wr_mcx_mac(pdata, STATION_ADDR0_ADDR, addr0);
xgene_enet_wr_mcx_mac(pdata, STATION_ADDR1_ADDR, addr1);
@@ -436,13 +435,13 @@ static int xgene_enet_ecc_init(struct xgene_enet_pdata *pdata)
return 0;
}
-void xgene_gmac_reset(struct xgene_enet_pdata *pdata)
+static void xgene_gmac_reset(struct xgene_enet_pdata *pdata)
{
xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, SOFT_RESET1);
xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, 0);
}
-void xgene_gmac_init(struct xgene_enet_pdata *pdata, int speed)
+static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
{
u32 value, mc2;
u32 intf_ctl, rgmii;
@@ -456,7 +455,7 @@ void xgene_gmac_init(struct xgene_enet_pdata *pdata, int speed)
xgene_enet_rd_mcx_mac(pdata, INTERFACE_CONTROL_ADDR, &intf_ctl);
xgene_enet_rd_csr(pdata, RGMII_REG_0_ADDR, &rgmii);
- switch (speed) {
+ switch (pdata->phy_speed) {
case SPEED_10:
ENET_INTERFACE_MODE2_SET(&mc2, 1);
CFG_MACMODE_SET(&icm0, 0);
@@ -525,8 +524,8 @@ static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *pdata)
xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIQMLITEFPQASSOC_ADDR, val);
}
-void xgene_enet_cle_bypass(struct xgene_enet_pdata *pdata,
- u32 dst_ring_num, u16 bufpool_id)
+static void xgene_enet_cle_bypass(struct xgene_enet_pdata *pdata,
+ u32 dst_ring_num, u16 bufpool_id)
{
u32 cb;
u32 fpsel;
@@ -544,7 +543,7 @@ void xgene_enet_cle_bypass(struct xgene_enet_pdata *pdata,
xgene_enet_wr_csr(pdata, CLE_BYPASS_REG1_0_ADDR, cb);
}
-void xgene_gmac_rx_enable(struct xgene_enet_pdata *pdata)
+static void xgene_gmac_rx_enable(struct xgene_enet_pdata *pdata)
{
u32 data;
@@ -552,7 +551,7 @@ void xgene_gmac_rx_enable(struct xgene_enet_pdata *pdata)
xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data | RX_EN);
}
-void xgene_gmac_tx_enable(struct xgene_enet_pdata *pdata)
+static void xgene_gmac_tx_enable(struct xgene_enet_pdata *pdata)
{
u32 data;
@@ -560,7 +559,7 @@ void xgene_gmac_tx_enable(struct xgene_enet_pdata *pdata)
xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data | TX_EN);
}
-void xgene_gmac_rx_disable(struct xgene_enet_pdata *pdata)
+static void xgene_gmac_rx_disable(struct xgene_enet_pdata *pdata)
{
u32 data;
@@ -568,7 +567,7 @@ void xgene_gmac_rx_disable(struct xgene_enet_pdata *pdata)
xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data & ~RX_EN);
}
-void xgene_gmac_tx_disable(struct xgene_enet_pdata *pdata)
+static void xgene_gmac_tx_disable(struct xgene_enet_pdata *pdata)
{
u32 data;
@@ -576,7 +575,7 @@ void xgene_gmac_tx_disable(struct xgene_enet_pdata *pdata)
xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data & ~TX_EN);
}
-void xgene_enet_reset(struct xgene_enet_pdata *pdata)
+static void xgene_enet_reset(struct xgene_enet_pdata *pdata)
{
u32 val;
@@ -593,7 +592,7 @@ void xgene_enet_reset(struct xgene_enet_pdata *pdata)
xgene_enet_wr_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, val);
}
-void xgene_gport_shutdown(struct xgene_enet_pdata *pdata)
+static void xgene_gport_shutdown(struct xgene_enet_pdata *pdata)
{
clk_disable_unprepare(pdata->clk);
}
@@ -627,10 +626,10 @@ static void xgene_enet_adjust_link(struct net_device *ndev)
if (phydev->link) {
if (pdata->phy_speed != phydev->speed) {
- xgene_gmac_init(pdata, phydev->speed);
+ pdata->phy_speed = phydev->speed;
+ xgene_gmac_init(pdata);
xgene_gmac_rx_enable(pdata);
xgene_gmac_tx_enable(pdata);
- pdata->phy_speed = phydev->speed;
phy_print_status(phydev);
}
} else {
@@ -726,3 +725,19 @@ void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata)
mdiobus_free(pdata->mdio_bus);
pdata->mdio_bus = NULL;
}
+
+struct xgene_mac_ops xgene_gmac_ops = {
+ .init = xgene_gmac_init,
+ .reset = xgene_gmac_reset,
+ .rx_enable = xgene_gmac_rx_enable,
+ .tx_enable = xgene_gmac_tx_enable,
+ .rx_disable = xgene_gmac_rx_disable,
+ .tx_disable = xgene_gmac_tx_disable,
+ .set_mac_addr = xgene_gmac_set_mac_addr,
+};
+
+struct xgene_port_ops xgene_gport_ops = {
+ .reset = xgene_enet_reset,
+ .cle_bypass = xgene_enet_cle_bypass,
+ .shutdown = xgene_gport_shutdown,
+};
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
index 371e7a5b2507..38558584080e 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
@@ -42,6 +42,12 @@ static inline u32 xgene_get_bits(u32 val, u32 start, u32 end)
return (val & GENMASK(end, start)) >> start;
}
+enum xgene_enet_rm {
+ RM0,
+ RM1,
+ RM3 = 3
+};
+
#define CSR_RING_ID 0x0008
#define OVERWRITE BIT(31)
#define IS_BUFFER_POOL BIT(20)
@@ -52,7 +58,6 @@ static inline u32 xgene_get_bits(u32 val, u32 start, u32 end)
#define CSR_RING_WR_BASE 0x0070
#define NUM_RING_CONFIG 5
#define BUFPOOL_MODE 3
-#define RM3 3
#define INC_DEC_CMD_ADDR 0x002c
#define UDP_HDR_SIZE 2
#define BUF_LEN_CODE_2K 0x5000
@@ -94,11 +99,9 @@ static inline u32 xgene_get_bits(u32 val, u32 start, u32 end)
#define BLOCK_ETH_CSR_OFFSET 0x2000
#define BLOCK_ETH_RING_IF_OFFSET 0x9000
-#define BLOCK_ETH_CLKRST_CSR_OFFSET 0xC000
#define BLOCK_ETH_DIAG_CSR_OFFSET 0xD000
#define BLOCK_ETH_MAC_OFFSET 0x0000
-#define BLOCK_ETH_STATS_OFFSET 0x0014
#define BLOCK_ETH_MAC_CSR_OFFSET 0x2800
#define MAC_ADDR_REG_OFFSET 0x00
@@ -107,12 +110,6 @@ static inline u32 xgene_get_bits(u32 val, u32 start, u32 end)
#define MAC_READ_REG_OFFSET 0x0c
#define MAC_COMMAND_DONE_REG_OFFSET 0x10
-#define STAT_ADDR_REG_OFFSET 0x00
-#define STAT_COMMAND_REG_OFFSET 0x04
-#define STAT_WRITE_REG_OFFSET 0x08
-#define STAT_READ_REG_OFFSET 0x0c
-#define STAT_COMMAND_DONE_REG_OFFSET 0x10
-
#define MII_MGMT_CONFIG_ADDR 0x20
#define MII_MGMT_COMMAND_ADDR 0x24
#define MII_MGMT_ADDRESS_ADDR 0x28
@@ -147,6 +144,8 @@ static inline u32 xgene_get_bits(u32 val, u32 start, u32 end)
#define CFG_CLE_FPSEL0_SET(dst, val) xgene_set_bits(dst, val, 16, 4)
#define CFG_MACMODE_SET(dst, val) xgene_set_bits(dst, val, 18, 2)
#define CFG_WAITASYNCRD_SET(dst, val) xgene_set_bits(dst, val, 0, 16)
+#define CFG_CLE_DSTQID0(val) (val & GENMASK(11, 0))
+#define CFG_CLE_FPSEL0(val) ((val << 16) & GENMASK(19, 16))
#define ICM_CONFIG0_REG_0_ADDR 0x0400
#define ICM_CONFIG2_REG_0_ADDR 0x0410
#define RX_DV_GATE_REG_0_ADDR 0x05fc
@@ -183,7 +182,6 @@ static inline u32 xgene_get_bits(u32 val, u32 start, u32 end)
#define TUND_ADDR 0x4a
#define TSO_IPPROTO_TCP 1
-#define FULL_DUPLEX 2
#define USERINFO_POS 0
#define USERINFO_LEN 32
@@ -318,20 +316,10 @@ void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
struct xgene_enet_pdata *pdata,
enum xgene_enet_err_code status);
-void xgene_enet_reset(struct xgene_enet_pdata *priv);
-void xgene_gmac_reset(struct xgene_enet_pdata *priv);
-void xgene_gmac_init(struct xgene_enet_pdata *priv, int speed);
-void xgene_gmac_tx_enable(struct xgene_enet_pdata *priv);
-void xgene_gmac_rx_enable(struct xgene_enet_pdata *priv);
-void xgene_gmac_tx_disable(struct xgene_enet_pdata *priv);
-void xgene_gmac_rx_disable(struct xgene_enet_pdata *priv);
-void xgene_gmac_set_mac_addr(struct xgene_enet_pdata *pdata);
-void xgene_enet_cle_bypass(struct xgene_enet_pdata *pdata,
- u32 dst_ring_num, u16 bufpool_id);
-void xgene_gport_shutdown(struct xgene_enet_pdata *priv);
-void xgene_gmac_get_tx_stats(struct xgene_enet_pdata *pdata);
-
int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata);
void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata);
+extern struct xgene_mac_ops xgene_gmac_ops;
+extern struct xgene_port_ops xgene_gport_ops;
+
#endif /* __XGENE_ENET_HW_H__ */
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index e4222af2baa6..3c208cc6f6bb 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -21,6 +21,8 @@
#include "xgene_enet_main.h"
#include "xgene_enet_hw.h"
+#include "xgene_enet_sgmac.h"
+#include "xgene_enet_xgmac.h"
static void xgene_enet_init_bufpool(struct xgene_enet_desc_ring *buf_pool)
{
@@ -390,7 +392,7 @@ static int xgene_enet_process_ring(struct xgene_enet_desc_ring *ring,
}
}
- return budget;
+ return count;
}
static int xgene_enet_napi(struct napi_struct *napi, const int budget)
@@ -413,7 +415,7 @@ static void xgene_enet_timeout(struct net_device *ndev)
{
struct xgene_enet_pdata *pdata = netdev_priv(ndev);
- xgene_gmac_reset(pdata);
+ pdata->mac_ops->reset(pdata);
}
static int xgene_enet_register_irq(struct net_device *ndev)
@@ -445,18 +447,21 @@ static void xgene_enet_free_irq(struct net_device *ndev)
static int xgene_enet_open(struct net_device *ndev)
{
struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ struct xgene_mac_ops *mac_ops = pdata->mac_ops;
int ret;
- xgene_gmac_tx_enable(pdata);
- xgene_gmac_rx_enable(pdata);
+ mac_ops->tx_enable(pdata);
+ mac_ops->rx_enable(pdata);
ret = xgene_enet_register_irq(ndev);
if (ret)
return ret;
napi_enable(&pdata->rx_ring->napi);
- if (pdata->phy_dev)
+ if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII)
phy_start(pdata->phy_dev);
+ else
+ schedule_delayed_work(&pdata->link_work, PHY_POLL_LINK_OFF);
netif_start_queue(ndev);
@@ -466,18 +471,21 @@ static int xgene_enet_open(struct net_device *ndev)
static int xgene_enet_close(struct net_device *ndev)
{
struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ struct xgene_mac_ops *mac_ops = pdata->mac_ops;
netif_stop_queue(ndev);
- if (pdata->phy_dev)
+ if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII)
phy_stop(pdata->phy_dev);
+ else
+ cancel_delayed_work_sync(&pdata->link_work);
napi_disable(&pdata->rx_ring->napi);
xgene_enet_free_irq(ndev);
xgene_enet_process_ring(pdata->rx_ring, -1);
- xgene_gmac_tx_disable(pdata);
- xgene_gmac_rx_disable(pdata);
+ mac_ops->tx_disable(pdata);
+ mac_ops->rx_disable(pdata);
return 0;
}
@@ -613,7 +621,6 @@ static struct xgene_enet_desc_ring *xgene_enet_create_desc_ring(
ring->cmd_base = pdata->ring_cmd_addr + (ring->num << 6);
ring->cmd = ring->cmd_base + INC_DEC_CMD_ADDR;
- pdata->rm = RM3;
ring = xgene_enet_setup_ring(ring);
netdev_dbg(ndev, "ring info: num=%d size=%d id=%d slots=%d\n",
ring->num, ring->size, ring->id, ring->slots);
@@ -724,7 +731,7 @@ static int xgene_enet_set_mac_address(struct net_device *ndev, void *addr)
ret = eth_mac_addr(ndev, addr);
if (ret)
return ret;
- xgene_gmac_set_mac_addr(pdata);
+ pdata->mac_ops->set_mac_addr(pdata);
return ret;
}
@@ -803,8 +810,14 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
pdata->phy_mode = of_get_phy_mode(pdev->dev.of_node);
if (pdata->phy_mode < 0) {
- dev_err(dev, "Incorrect phy-connection-type in DTS\n");
- return -EINVAL;
+ dev_err(dev, "Unable to get phy-connection-type\n");
+ return pdata->phy_mode;
+ }
+ if (pdata->phy_mode != PHY_INTERFACE_MODE_RGMII &&
+ pdata->phy_mode != PHY_INTERFACE_MODE_SGMII &&
+ pdata->phy_mode != PHY_INTERFACE_MODE_XGMII) {
+ dev_err(dev, "Incorrect phy-connection-type specified\n");
+ return -ENODEV;
}
pdata->clk = devm_clk_get(&pdev->dev, NULL);
@@ -819,12 +832,17 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
pdata->eth_csr_addr = base_addr + BLOCK_ETH_CSR_OFFSET;
pdata->eth_ring_if_addr = base_addr + BLOCK_ETH_RING_IF_OFFSET;
pdata->eth_diag_csr_addr = base_addr + BLOCK_ETH_DIAG_CSR_OFFSET;
- pdata->mcx_mac_addr = base_addr + BLOCK_ETH_MAC_OFFSET;
- pdata->mcx_stats_addr = base_addr + BLOCK_ETH_STATS_OFFSET;
- pdata->mcx_mac_csr_addr = base_addr + BLOCK_ETH_MAC_CSR_OFFSET;
+ if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII ||
+ pdata->phy_mode == PHY_INTERFACE_MODE_SGMII) {
+ pdata->mcx_mac_addr = base_addr + BLOCK_ETH_MAC_OFFSET;
+ pdata->mcx_mac_csr_addr = base_addr + BLOCK_ETH_MAC_CSR_OFFSET;
+ } else {
+ pdata->mcx_mac_addr = base_addr + BLOCK_AXG_MAC_OFFSET;
+ pdata->mcx_mac_csr_addr = base_addr + BLOCK_AXG_MAC_CSR_OFFSET;
+ }
pdata->rx_buff_cnt = NUM_PKT_BUF;
- return ret;
+ return 0;
}
static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
@@ -834,8 +852,7 @@ static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
u16 dst_ring_num;
int ret;
- xgene_gmac_tx_disable(pdata);
- xgene_gmac_rx_disable(pdata);
+ pdata->port_ops->reset(pdata);
ret = xgene_enet_create_desc_rings(ndev);
if (ret) {
@@ -853,17 +870,40 @@ static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
}
dst_ring_num = xgene_enet_dst_ring_num(pdata->rx_ring);
- xgene_enet_cle_bypass(pdata, dst_ring_num, buf_pool->id);
+ pdata->port_ops->cle_bypass(pdata, dst_ring_num, buf_pool->id);
+ pdata->mac_ops->init(pdata);
return ret;
}
+static void xgene_enet_setup_ops(struct xgene_enet_pdata *pdata)
+{
+ switch (pdata->phy_mode) {
+ case PHY_INTERFACE_MODE_RGMII:
+ pdata->mac_ops = &xgene_gmac_ops;
+ pdata->port_ops = &xgene_gport_ops;
+ pdata->rm = RM3;
+ break;
+ case PHY_INTERFACE_MODE_SGMII:
+ pdata->mac_ops = &xgene_sgmac_ops;
+ pdata->port_ops = &xgene_sgport_ops;
+ pdata->rm = RM1;
+ break;
+ default:
+ pdata->mac_ops = &xgene_xgmac_ops;
+ pdata->port_ops = &xgene_xgport_ops;
+ pdata->rm = RM0;
+ break;
+ }
+}
+
static int xgene_enet_probe(struct platform_device *pdev)
{
struct net_device *ndev;
struct xgene_enet_pdata *pdata;
struct device *dev = &pdev->dev;
struct napi_struct *napi;
+ struct xgene_mac_ops *mac_ops;
int ret;
ndev = alloc_etherdev(sizeof(struct xgene_enet_pdata));
@@ -886,8 +926,7 @@ static int xgene_enet_probe(struct platform_device *pdev)
if (ret)
goto err;
- xgene_enet_reset(pdata);
- xgene_gmac_init(pdata, SPEED_1000);
+ xgene_enet_setup_ops(pdata);
ret = register_netdev(ndev);
if (ret) {
@@ -907,7 +946,11 @@ static int xgene_enet_probe(struct platform_device *pdev)
napi = &pdata->rx_ring->napi;
netif_napi_add(ndev, napi, xgene_enet_napi, NAPI_POLL_WEIGHT);
- ret = xgene_enet_mdio_config(pdata);
+ mac_ops = pdata->mac_ops;
+ if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII)
+ ret = xgene_enet_mdio_config(pdata);
+ else
+ INIT_DELAYED_WORK(&pdata->link_work, mac_ops->link_state);
return ret;
err:
@@ -918,19 +961,21 @@ err:
static int xgene_enet_remove(struct platform_device *pdev)
{
struct xgene_enet_pdata *pdata;
+ struct xgene_mac_ops *mac_ops;
struct net_device *ndev;
pdata = platform_get_drvdata(pdev);
+ mac_ops = pdata->mac_ops;
ndev = pdata->ndev;
- xgene_gmac_rx_disable(pdata);
- xgene_gmac_tx_disable(pdata);
+ mac_ops->rx_disable(pdata);
+ mac_ops->tx_disable(pdata);
netif_napi_del(&pdata->rx_ring->napi);
xgene_enet_mdio_remove(pdata);
xgene_enet_delete_desc_rings(pdata);
unregister_netdev(ndev);
- xgene_gport_shutdown(pdata);
+ pdata->port_ops->shutdown(pdata);
free_netdev(ndev);
return 0;
@@ -956,5 +1001,6 @@ module_platform_driver(xgene_enet_driver);
MODULE_DESCRIPTION("APM X-Gene SoC Ethernet driver");
MODULE_VERSION(XGENE_DRV_VERSION);
+MODULE_AUTHOR("Iyappan Subramanian <isubramanian@apm.com>");
MODULE_AUTHOR("Keyur Chudgar <kchudgar@apm.com>");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
index 0815866986b0..874e5a01161f 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
@@ -39,6 +39,9 @@
#define NUM_PKT_BUF 64
#define NUM_BUFPOOL 32
+#define PHY_POLL_LINK_ON (10 * HZ)
+#define PHY_POLL_LINK_OFF (PHY_POLL_LINK_ON / 5)
+
/* software context of a descriptor ring */
struct xgene_enet_desc_ring {
struct net_device *ndev;
@@ -68,6 +71,24 @@ struct xgene_enet_desc_ring {
};
};
+struct xgene_mac_ops {
+ void (*init)(struct xgene_enet_pdata *pdata);
+ void (*reset)(struct xgene_enet_pdata *pdata);
+ void (*tx_enable)(struct xgene_enet_pdata *pdata);
+ void (*rx_enable)(struct xgene_enet_pdata *pdata);
+ void (*tx_disable)(struct xgene_enet_pdata *pdata);
+ void (*rx_disable)(struct xgene_enet_pdata *pdata);
+ void (*set_mac_addr)(struct xgene_enet_pdata *pdata);
+ void (*link_state)(struct work_struct *work);
+};
+
+struct xgene_port_ops {
+ void (*reset)(struct xgene_enet_pdata *pdata);
+ void (*cle_bypass)(struct xgene_enet_pdata *pdata,
+ u32 dst_ring_num, u16 bufpool_id);
+ void (*shutdown)(struct xgene_enet_pdata *pdata);
+};
+
/* ethernet private data */
struct xgene_enet_pdata {
struct net_device *ndev;
@@ -88,16 +109,23 @@ struct xgene_enet_pdata {
void __iomem *eth_ring_if_addr;
void __iomem *eth_diag_csr_addr;
void __iomem *mcx_mac_addr;
- void __iomem *mcx_stats_addr;
void __iomem *mcx_mac_csr_addr;
void __iomem *base_addr;
void __iomem *ring_csr_addr;
void __iomem *ring_cmd_addr;
- u32 phy_addr;
int phy_mode;
- u32 speed;
- u16 rm;
+ enum xgene_enet_rm rm;
struct rtnl_link_stats64 stats;
+ struct xgene_mac_ops *mac_ops;
+ struct xgene_port_ops *port_ops;
+ struct delayed_work link_work;
+};
+
+struct xgene_indirect_ctl {
+ void __iomem *addr;
+ void __iomem *ctl;
+ void __iomem *cmd;
+ void __iomem *cmd_done;
};
/* Set the specified value into a bit-field defined by its starting position
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
new file mode 100644
index 000000000000..e6d24c210198
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
@@ -0,0 +1,389 @@
+/* Applied Micro X-Gene SoC Ethernet Driver
+ *
+ * Copyright (c) 2014, Applied Micro Circuits Corporation
+ * Authors: Iyappan Subramanian <isubramanian@apm.com>
+ * Keyur Chudgar <kchudgar@apm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "xgene_enet_main.h"
+#include "xgene_enet_hw.h"
+#include "xgene_enet_sgmac.h"
+
+static void xgene_enet_wr_csr(struct xgene_enet_pdata *p, u32 offset, u32 val)
+{
+ iowrite32(val, p->eth_csr_addr + offset);
+}
+
+static void xgene_enet_wr_ring_if(struct xgene_enet_pdata *p,
+ u32 offset, u32 val)
+{
+ iowrite32(val, p->eth_ring_if_addr + offset);
+}
+
+static void xgene_enet_wr_diag_csr(struct xgene_enet_pdata *p,
+ u32 offset, u32 val)
+{
+ iowrite32(val, p->eth_diag_csr_addr + offset);
+}
+
+static bool xgene_enet_wr_indirect(struct xgene_indirect_ctl *ctl,
+ u32 wr_addr, u32 wr_data)
+{
+ int i;
+
+ iowrite32(wr_addr, ctl->addr);
+ iowrite32(wr_data, ctl->ctl);
+ iowrite32(XGENE_ENET_WR_CMD, ctl->cmd);
+
+ /* wait for write command to complete */
+ for (i = 0; i < 10; i++) {
+ if (ioread32(ctl->cmd_done)) {
+ iowrite32(0, ctl->cmd);
+ return true;
+ }
+ udelay(1);
+ }
+
+ return false;
+}
+
+static void xgene_enet_wr_mac(struct xgene_enet_pdata *p,
+ u32 wr_addr, u32 wr_data)
+{
+ struct xgene_indirect_ctl ctl = {
+ .addr = p->mcx_mac_addr + MAC_ADDR_REG_OFFSET,
+ .ctl = p->mcx_mac_addr + MAC_WRITE_REG_OFFSET,
+ .cmd = p->mcx_mac_addr + MAC_COMMAND_REG_OFFSET,
+ .cmd_done = p->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET
+ };
+
+ if (!xgene_enet_wr_indirect(&ctl, wr_addr, wr_data))
+ netdev_err(p->ndev, "mac write failed, addr: %04x\n", wr_addr);
+}
+
+static u32 xgene_enet_rd_csr(struct xgene_enet_pdata *p, u32 offset)
+{
+ return ioread32(p->eth_csr_addr + offset);
+}
+
+static u32 xgene_enet_rd_diag_csr(struct xgene_enet_pdata *p, u32 offset)
+{
+ return ioread32(p->eth_diag_csr_addr + offset);
+}
+
+static u32 xgene_enet_rd_indirect(struct xgene_indirect_ctl *ctl, u32 rd_addr)
+{
+ u32 rd_data;
+ int i;
+
+ iowrite32(rd_addr, ctl->addr);
+ iowrite32(XGENE_ENET_RD_CMD, ctl->cmd);
+
+ /* wait for read command to complete */
+ for (i = 0; i < 10; i++) {
+ if (ioread32(ctl->cmd_done)) {
+ rd_data = ioread32(ctl->ctl);
+ iowrite32(0, ctl->cmd);
+
+ return rd_data;
+ }
+ udelay(1);
+ }
+
+ pr_err("%s: mac read failed, addr: %04x\n", __func__, rd_addr);
+
+ return 0;
+}
+
+static u32 xgene_enet_rd_mac(struct xgene_enet_pdata *p, u32 rd_addr)
+{
+ struct xgene_indirect_ctl ctl = {
+ .addr = p->mcx_mac_addr + MAC_ADDR_REG_OFFSET,
+ .ctl = p->mcx_mac_addr + MAC_READ_REG_OFFSET,
+ .cmd = p->mcx_mac_addr + MAC_COMMAND_REG_OFFSET,
+ .cmd_done = p->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET
+ };
+
+ return xgene_enet_rd_indirect(&ctl, rd_addr);
+}
+
+static int xgene_enet_ecc_init(struct xgene_enet_pdata *p)
+{
+ struct net_device *ndev = p->ndev;
+ u32 data;
+ int i;
+
+ xgene_enet_wr_diag_csr(p, ENET_CFG_MEM_RAM_SHUTDOWN_ADDR, 0);
+ for (i = 0; i < 10 && data != ~0U ; i++) {
+ usleep_range(100, 110);
+ data = xgene_enet_rd_diag_csr(p, ENET_BLOCK_MEM_RDY_ADDR);
+ }
+
+ if (data != ~0U) {
+ netdev_err(ndev, "Failed to release memory from shutdown\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *p)
+{
+ u32 val = 0xffffffff;
+
+ xgene_enet_wr_ring_if(p, ENET_CFGSSQMIWQASSOC_ADDR, val);
+ xgene_enet_wr_ring_if(p, ENET_CFGSSQMIFPQASSOC_ADDR, val);
+}
+
+static void xgene_mii_phy_write(struct xgene_enet_pdata *p, u8 phy_id,
+ u32 reg, u16 data)
+{
+ u32 addr, wr_data, done;
+ int i;
+
+ addr = PHY_ADDR(phy_id) | REG_ADDR(reg);
+ xgene_enet_wr_mac(p, MII_MGMT_ADDRESS_ADDR, addr);
+
+ wr_data = PHY_CONTROL(data);
+ xgene_enet_wr_mac(p, MII_MGMT_CONTROL_ADDR, wr_data);
+
+ for (i = 0; i < 10; i++) {
+ done = xgene_enet_rd_mac(p, MII_MGMT_INDICATORS_ADDR);
+ if (!(done & BUSY_MASK))
+ return;
+ usleep_range(10, 20);
+ }
+
+ netdev_err(p->ndev, "MII_MGMT write failed\n");
+}
+
+static u32 xgene_mii_phy_read(struct xgene_enet_pdata *p, u8 phy_id, u32 reg)
+{
+ u32 addr, data, done;
+ int i;
+
+ addr = PHY_ADDR(phy_id) | REG_ADDR(reg);
+ xgene_enet_wr_mac(p, MII_MGMT_ADDRESS_ADDR, addr);
+ xgene_enet_wr_mac(p, MII_MGMT_COMMAND_ADDR, READ_CYCLE_MASK);
+
+ for (i = 0; i < 10; i++) {
+ done = xgene_enet_rd_mac(p, MII_MGMT_INDICATORS_ADDR);
+ if (!(done & BUSY_MASK)) {
+ data = xgene_enet_rd_mac(p, MII_MGMT_STATUS_ADDR);
+ xgene_enet_wr_mac(p, MII_MGMT_COMMAND_ADDR, 0);
+
+ return data;
+ }
+ usleep_range(10, 20);
+ }
+
+ netdev_err(p->ndev, "MII_MGMT read failed\n");
+
+ return 0;
+}
+
+static void xgene_sgmac_reset(struct xgene_enet_pdata *p)
+{
+ xgene_enet_wr_mac(p, MAC_CONFIG_1_ADDR, SOFT_RESET1);
+ xgene_enet_wr_mac(p, MAC_CONFIG_1_ADDR, 0);
+}
+
+static void xgene_sgmac_set_mac_addr(struct xgene_enet_pdata *p)
+{
+ u32 addr0, addr1;
+ u8 *dev_addr = p->ndev->dev_addr;
+
+ addr0 = (dev_addr[3] << 24) | (dev_addr[2] << 16) |
+ (dev_addr[1] << 8) | dev_addr[0];
+ xgene_enet_wr_mac(p, STATION_ADDR0_ADDR, addr0);
+
+ addr1 = xgene_enet_rd_mac(p, STATION_ADDR1_ADDR);
+ addr1 |= (dev_addr[5] << 24) | (dev_addr[4] << 16);
+ xgene_enet_wr_mac(p, STATION_ADDR1_ADDR, addr1);
+}
+
+static u32 xgene_enet_link_status(struct xgene_enet_pdata *p)
+{
+ u32 data;
+
+ data = xgene_mii_phy_read(p, INT_PHY_ADDR,
+ SGMII_BASE_PAGE_ABILITY_ADDR >> 2);
+
+ return data & LINK_UP;
+}
+
+static void xgene_sgmac_init(struct xgene_enet_pdata *p)
+{
+ u32 data, loop = 10;
+
+ xgene_sgmac_reset(p);
+
+ /* Enable auto-negotiation */
+ xgene_mii_phy_write(p, INT_PHY_ADDR, SGMII_CONTROL_ADDR >> 2, 0x1000);
+ xgene_mii_phy_write(p, INT_PHY_ADDR, SGMII_TBI_CONTROL_ADDR >> 2, 0);
+
+ while (loop--) {
+ data = xgene_mii_phy_read(p, INT_PHY_ADDR,
+ SGMII_STATUS_ADDR >> 2);
+ if ((data & AUTO_NEG_COMPLETE) && (data & LINK_STATUS))
+ break;
+ usleep_range(10, 20);
+ }
+ if (!(data & AUTO_NEG_COMPLETE) || !(data & LINK_STATUS))
+ netdev_err(p->ndev, "Auto-negotiation failed\n");
+
+ data = xgene_enet_rd_mac(p, MAC_CONFIG_2_ADDR);
+ ENET_INTERFACE_MODE2_SET(&data, 2);
+ xgene_enet_wr_mac(p, MAC_CONFIG_2_ADDR, data | FULL_DUPLEX2);
+ xgene_enet_wr_mac(p, INTERFACE_CONTROL_ADDR, ENET_GHD_MODE);
+
+ data = xgene_enet_rd_csr(p, ENET_SPARE_CFG_REG_ADDR);
+ data |= MPA_IDLE_WITH_QMI_EMPTY;
+ xgene_enet_wr_csr(p, ENET_SPARE_CFG_REG_ADDR, data);
+
+ xgene_sgmac_set_mac_addr(p);
+
+ data = xgene_enet_rd_csr(p, DEBUG_REG_ADDR);
+ data |= CFG_BYPASS_UNISEC_TX | CFG_BYPASS_UNISEC_RX;
+ xgene_enet_wr_csr(p, DEBUG_REG_ADDR, data);
+
+ /* Adjust MDC clock frequency */
+ data = xgene_enet_rd_mac(p, MII_MGMT_CONFIG_ADDR);
+ MGMT_CLOCK_SEL_SET(&data, 7);
+ xgene_enet_wr_mac(p, MII_MGMT_CONFIG_ADDR, data);
+
+ /* Enable drop if bufpool not available */
+ data = xgene_enet_rd_csr(p, RSIF_CONFIG_REG_ADDR);
+ data |= CFG_RSIF_FPBUFF_TIMEOUT_EN;
+ xgene_enet_wr_csr(p, RSIF_CONFIG_REG_ADDR, data);
+
+ /* Rtype should be copied from FP */
+ xgene_enet_wr_csr(p, RSIF_RAM_DBG_REG0_ADDR, 0);
+
+ /* Bypass traffic gating */
+ xgene_enet_wr_csr(p, CFG_LINK_AGGR_RESUME_0_ADDR, TX_PORT0);
+ xgene_enet_wr_csr(p, CFG_BYPASS_ADDR, RESUME_TX);
+ xgene_enet_wr_csr(p, SG_RX_DV_GATE_REG_0_ADDR, RESUME_RX0);
+}
+
+static void xgene_sgmac_rxtx(struct xgene_enet_pdata *p, u32 bits, bool set)
+{
+ u32 data;
+
+ data = xgene_enet_rd_mac(p, MAC_CONFIG_1_ADDR);
+
+ if (set)
+ data |= bits;
+ else
+ data &= ~bits;
+
+ xgene_enet_wr_mac(p, MAC_CONFIG_1_ADDR, data);
+}
+
+static void xgene_sgmac_rx_enable(struct xgene_enet_pdata *p)
+{
+ xgene_sgmac_rxtx(p, RX_EN, true);
+}
+
+static void xgene_sgmac_tx_enable(struct xgene_enet_pdata *p)
+{
+ xgene_sgmac_rxtx(p, TX_EN, true);
+}
+
+static void xgene_sgmac_rx_disable(struct xgene_enet_pdata *p)
+{
+ xgene_sgmac_rxtx(p, RX_EN, false);
+}
+
+static void xgene_sgmac_tx_disable(struct xgene_enet_pdata *p)
+{
+ xgene_sgmac_rxtx(p, TX_EN, false);
+}
+
+static void xgene_enet_reset(struct xgene_enet_pdata *p)
+{
+ clk_prepare_enable(p->clk);
+ clk_disable_unprepare(p->clk);
+ clk_prepare_enable(p->clk);
+
+ xgene_enet_ecc_init(p);
+ xgene_enet_config_ring_if_assoc(p);
+}
+
+static void xgene_enet_cle_bypass(struct xgene_enet_pdata *p,
+ u32 dst_ring_num, u16 bufpool_id)
+{
+ u32 data, fpsel;
+
+ data = CFG_CLE_BYPASS_EN0;
+ xgene_enet_wr_csr(p, CLE_BYPASS_REG0_0_ADDR, data);
+
+ fpsel = xgene_enet_ring_bufnum(bufpool_id) - 0x20;
+ data = CFG_CLE_DSTQID0(dst_ring_num) | CFG_CLE_FPSEL0(fpsel);
+ xgene_enet_wr_csr(p, CLE_BYPASS_REG1_0_ADDR, data);
+}
+
+static void xgene_enet_shutdown(struct xgene_enet_pdata *p)
+{
+ clk_disable_unprepare(p->clk);
+}
+
+static void xgene_enet_link_state(struct work_struct *work)
+{
+ struct xgene_enet_pdata *p = container_of(to_delayed_work(work),
+ struct xgene_enet_pdata, link_work);
+ struct net_device *ndev = p->ndev;
+ u32 link, poll_interval;
+
+ link = xgene_enet_link_status(p);
+ if (link) {
+ if (!netif_carrier_ok(ndev)) {
+ netif_carrier_on(ndev);
+ xgene_sgmac_init(p);
+ xgene_sgmac_rx_enable(p);
+ xgene_sgmac_tx_enable(p);
+ netdev_info(ndev, "Link is Up - 1Gbps\n");
+ }
+ poll_interval = PHY_POLL_LINK_ON;
+ } else {
+ if (netif_carrier_ok(ndev)) {
+ xgene_sgmac_rx_disable(p);
+ xgene_sgmac_tx_disable(p);
+ netif_carrier_off(ndev);
+ netdev_info(ndev, "Link is Down\n");
+ }
+ poll_interval = PHY_POLL_LINK_OFF;
+ }
+
+ schedule_delayed_work(&p->link_work, poll_interval);
+}
+
+struct xgene_mac_ops xgene_sgmac_ops = {
+ .init = xgene_sgmac_init,
+ .reset = xgene_sgmac_reset,
+ .rx_enable = xgene_sgmac_rx_enable,
+ .tx_enable = xgene_sgmac_tx_enable,
+ .rx_disable = xgene_sgmac_rx_disable,
+ .tx_disable = xgene_sgmac_tx_disable,
+ .set_mac_addr = xgene_sgmac_set_mac_addr,
+ .link_state = xgene_enet_link_state
+};
+
+struct xgene_port_ops xgene_sgport_ops = {
+ .reset = xgene_enet_reset,
+ .cle_bypass = xgene_enet_cle_bypass,
+ .shutdown = xgene_enet_shutdown
+};
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h
new file mode 100644
index 000000000000..de432465009c
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h
@@ -0,0 +1,41 @@
+/* Applied Micro X-Gene SoC Ethernet Driver
+ *
+ * Copyright (c) 2014, Applied Micro Circuits Corporation
+ * Authors: Iyappan Subramanian <isubramanian@apm.com>
+ * Keyur Chudgar <kchudgar@apm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __XGENE_ENET_SGMAC_H__
+#define __XGENE_ENET_SGMAC_H__
+
+#define PHY_ADDR(src) (((src)<<8) & GENMASK(12, 8))
+#define REG_ADDR(src) ((src) & GENMASK(4, 0))
+#define PHY_CONTROL(src) ((src) & GENMASK(15, 0))
+#define INT_PHY_ADDR 0x1e
+#define SGMII_TBI_CONTROL_ADDR 0x44
+#define SGMII_CONTROL_ADDR 0x00
+#define SGMII_STATUS_ADDR 0x04
+#define SGMII_BASE_PAGE_ABILITY_ADDR 0x14
+#define AUTO_NEG_COMPLETE BIT(5)
+#define LINK_STATUS BIT(2)
+#define LINK_UP BIT(15)
+#define MPA_IDLE_WITH_QMI_EMPTY BIT(12)
+#define SG_RX_DV_GATE_REG_0_ADDR 0x0dfc
+
+extern struct xgene_mac_ops xgene_sgmac_ops;
+extern struct xgene_port_ops xgene_sgport_ops;
+
+#endif /* __XGENE_ENET_SGMAC_H__ */
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
new file mode 100644
index 000000000000..67d07206b3c7
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
@@ -0,0 +1,332 @@
+/* Applied Micro X-Gene SoC Ethernet Driver
+ *
+ * Copyright (c) 2014, Applied Micro Circuits Corporation
+ * Authors: Iyappan Subramanian <isubramanian@apm.com>
+ * Keyur Chudgar <kchudgar@apm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "xgene_enet_main.h"
+#include "xgene_enet_hw.h"
+#include "xgene_enet_xgmac.h"
+
+static void xgene_enet_wr_csr(struct xgene_enet_pdata *pdata,
+ u32 offset, u32 val)
+{
+ void __iomem *addr = pdata->eth_csr_addr + offset;
+
+ iowrite32(val, addr);
+}
+
+static void xgene_enet_wr_ring_if(struct xgene_enet_pdata *pdata,
+ u32 offset, u32 val)
+{
+ void __iomem *addr = pdata->eth_ring_if_addr + offset;
+
+ iowrite32(val, addr);
+}
+
+static void xgene_enet_wr_diag_csr(struct xgene_enet_pdata *pdata,
+ u32 offset, u32 val)
+{
+ void __iomem *addr = pdata->eth_diag_csr_addr + offset;
+
+ iowrite32(val, addr);
+}
+
+static bool xgene_enet_wr_indirect(void __iomem *addr, void __iomem *wr,
+ void __iomem *cmd, void __iomem *cmd_done,
+ u32 wr_addr, u32 wr_data)
+{
+ u32 done;
+ u8 wait = 10;
+
+ iowrite32(wr_addr, addr);
+ iowrite32(wr_data, wr);
+ iowrite32(XGENE_ENET_WR_CMD, cmd);
+
+ /* wait for write command to complete */
+ while (!(done = ioread32(cmd_done)) && wait--)
+ udelay(1);
+
+ if (!done)
+ return false;
+
+ iowrite32(0, cmd);
+
+ return true;
+}
+
+static void xgene_enet_wr_mac(struct xgene_enet_pdata *pdata,
+ u32 wr_addr, u32 wr_data)
+{
+ void __iomem *addr, *wr, *cmd, *cmd_done;
+
+ addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET;
+ wr = pdata->mcx_mac_addr + MAC_WRITE_REG_OFFSET;
+ cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET;
+ cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET;
+
+ if (!xgene_enet_wr_indirect(addr, wr, cmd, cmd_done, wr_addr, wr_data))
+ netdev_err(pdata->ndev, "MCX mac write failed, addr: %04x\n",
+ wr_addr);
+}
+
+static void xgene_enet_rd_csr(struct xgene_enet_pdata *pdata,
+ u32 offset, u32 *val)
+{
+ void __iomem *addr = pdata->eth_csr_addr + offset;
+
+ *val = ioread32(addr);
+}
+
+static void xgene_enet_rd_diag_csr(struct xgene_enet_pdata *pdata,
+ u32 offset, u32 *val)
+{
+ void __iomem *addr = pdata->eth_diag_csr_addr + offset;
+
+ *val = ioread32(addr);
+}
+
+static bool xgene_enet_rd_indirect(void __iomem *addr, void __iomem *rd,
+ void __iomem *cmd, void __iomem *cmd_done,
+ u32 rd_addr, u32 *rd_data)
+{
+ u32 done;
+ u8 wait = 10;
+
+ iowrite32(rd_addr, addr);
+ iowrite32(XGENE_ENET_RD_CMD, cmd);
+
+ /* wait for read command to complete */
+ while (!(done = ioread32(cmd_done)) && wait--)
+ udelay(1);
+
+ if (!done)
+ return false;
+
+ *rd_data = ioread32(rd);
+ iowrite32(0, cmd);
+
+ return true;
+}
+
+static void xgene_enet_rd_mac(struct xgene_enet_pdata *pdata,
+ u32 rd_addr, u32 *rd_data)
+{
+ void __iomem *addr, *rd, *cmd, *cmd_done;
+
+ addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET;
+ rd = pdata->mcx_mac_addr + MAC_READ_REG_OFFSET;
+ cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET;
+ cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET;
+
+ if (!xgene_enet_rd_indirect(addr, rd, cmd, cmd_done, rd_addr, rd_data))
+ netdev_err(pdata->ndev, "MCX mac read failed, addr: %04x\n",
+ rd_addr);
+}
+
+static int xgene_enet_ecc_init(struct xgene_enet_pdata *pdata)
+{
+ struct net_device *ndev = pdata->ndev;
+ u32 data;
+ u8 wait = 10;
+
+ xgene_enet_wr_diag_csr(pdata, ENET_CFG_MEM_RAM_SHUTDOWN_ADDR, 0x0);
+ do {
+ usleep_range(100, 110);
+ xgene_enet_rd_diag_csr(pdata, ENET_BLOCK_MEM_RDY_ADDR, &data);
+ } while ((data != 0xffffffff) && wait--);
+
+ if (data != 0xffffffff) {
+ netdev_err(ndev, "Failed to release memory from shutdown\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *pdata)
+{
+ xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIWQASSOC_ADDR, 0);
+ xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIFPQASSOC_ADDR, 0);
+ xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIQMLITEWQASSOC_ADDR, 0);
+ xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIQMLITEFPQASSOC_ADDR, 0);
+}
+
+static void xgene_xgmac_reset(struct xgene_enet_pdata *pdata)
+{
+ xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_0, HSTMACRST);
+ xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_0, 0);
+}
+
+static void xgene_xgmac_set_mac_addr(struct xgene_enet_pdata *pdata)
+{
+ u32 addr0, addr1;
+ u8 *dev_addr = pdata->ndev->dev_addr;
+
+ addr0 = (dev_addr[3] << 24) | (dev_addr[2] << 16) |
+ (dev_addr[1] << 8) | dev_addr[0];
+ addr1 = (dev_addr[5] << 24) | (dev_addr[4] << 16);
+
+ xgene_enet_wr_mac(pdata, HSTMACADR_LSW_ADDR, addr0);
+ xgene_enet_wr_mac(pdata, HSTMACADR_MSW_ADDR, addr1);
+}
+
+static u32 xgene_enet_link_status(struct xgene_enet_pdata *pdata)
+{
+ u32 data;
+
+ xgene_enet_rd_csr(pdata, XG_LINK_STATUS_ADDR, &data);
+
+ return data;
+}
+
+static void xgene_xgmac_init(struct xgene_enet_pdata *pdata)
+{
+ u32 data;
+
+ xgene_xgmac_reset(pdata);
+
+ xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data);
+ data |= HSTPPEN;
+ data &= ~HSTLENCHK;
+ xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data);
+
+ xgene_enet_wr_mac(pdata, HSTMAXFRAME_LENGTH_ADDR, 0x06000600);
+ xgene_xgmac_set_mac_addr(pdata);
+
+ xgene_enet_rd_csr(pdata, XG_RSIF_CONFIG_REG_ADDR, &data);
+ data |= CFG_RSIF_FPBUFF_TIMEOUT_EN;
+ xgene_enet_wr_csr(pdata, XG_RSIF_CONFIG_REG_ADDR, data);
+
+ xgene_enet_wr_csr(pdata, XG_CFG_BYPASS_ADDR, RESUME_TX);
+ xgene_enet_wr_csr(pdata, XGENET_RX_DV_GATE_REG_0_ADDR, 0);
+ xgene_enet_rd_csr(pdata, XG_ENET_SPARE_CFG_REG_ADDR, &data);
+ data |= BIT(12);
+ xgene_enet_wr_csr(pdata, XG_ENET_SPARE_CFG_REG_ADDR, data);
+ xgene_enet_wr_csr(pdata, XG_ENET_SPARE_CFG_REG_1_ADDR, 0x82);
+}
+
+static void xgene_xgmac_rx_enable(struct xgene_enet_pdata *pdata)
+{
+ u32 data;
+
+ xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data);
+ xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data | HSTRFEN);
+}
+
+static void xgene_xgmac_tx_enable(struct xgene_enet_pdata *pdata)
+{
+ u32 data;
+
+ xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data);
+ xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data | HSTTFEN);
+}
+
+static void xgene_xgmac_rx_disable(struct xgene_enet_pdata *pdata)
+{
+ u32 data;
+
+ xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data);
+ xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data & ~HSTRFEN);
+}
+
+static void xgene_xgmac_tx_disable(struct xgene_enet_pdata *pdata)
+{
+ u32 data;
+
+ xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data);
+ xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data & ~HSTTFEN);
+}
+
+static void xgene_enet_reset(struct xgene_enet_pdata *pdata)
+{
+ clk_prepare_enable(pdata->clk);
+ clk_disable_unprepare(pdata->clk);
+ clk_prepare_enable(pdata->clk);
+
+ xgene_enet_ecc_init(pdata);
+ xgene_enet_config_ring_if_assoc(pdata);
+}
+
+static void xgene_enet_xgcle_bypass(struct xgene_enet_pdata *pdata,
+ u32 dst_ring_num, u16 bufpool_id)
+{
+ u32 cb, fpsel;
+
+ xgene_enet_rd_csr(pdata, XCLE_BYPASS_REG0_ADDR, &cb);
+ cb |= CFG_CLE_BYPASS_EN0;
+ CFG_CLE_IP_PROTOCOL0_SET(&cb, 3);
+ xgene_enet_wr_csr(pdata, XCLE_BYPASS_REG0_ADDR, cb);
+
+ fpsel = xgene_enet_ring_bufnum(bufpool_id) - 0x20;
+ xgene_enet_rd_csr(pdata, XCLE_BYPASS_REG1_ADDR, &cb);
+ CFG_CLE_DSTQID0_SET(&cb, dst_ring_num);
+ CFG_CLE_FPSEL0_SET(&cb, fpsel);
+ xgene_enet_wr_csr(pdata, XCLE_BYPASS_REG1_ADDR, cb);
+}
+
+static void xgene_enet_shutdown(struct xgene_enet_pdata *pdata)
+{
+ clk_disable_unprepare(pdata->clk);
+}
+
+static void xgene_enet_link_state(struct work_struct *work)
+{
+ struct xgene_enet_pdata *pdata = container_of(to_delayed_work(work),
+ struct xgene_enet_pdata, link_work);
+ struct net_device *ndev = pdata->ndev;
+ u32 link_status, poll_interval;
+
+ link_status = xgene_enet_link_status(pdata);
+ if (link_status) {
+ if (!netif_carrier_ok(ndev)) {
+ netif_carrier_on(ndev);
+ xgene_xgmac_init(pdata);
+ xgene_xgmac_rx_enable(pdata);
+ xgene_xgmac_tx_enable(pdata);
+ netdev_info(ndev, "Link is Up - 10Gbps\n");
+ }
+ poll_interval = PHY_POLL_LINK_ON;
+ } else {
+ if (netif_carrier_ok(ndev)) {
+ xgene_xgmac_rx_disable(pdata);
+ xgene_xgmac_tx_disable(pdata);
+ netif_carrier_off(ndev);
+ netdev_info(ndev, "Link is Down\n");
+ }
+ poll_interval = PHY_POLL_LINK_OFF;
+ }
+
+ schedule_delayed_work(&pdata->link_work, poll_interval);
+}
+
+struct xgene_mac_ops xgene_xgmac_ops = {
+ .init = xgene_xgmac_init,
+ .reset = xgene_xgmac_reset,
+ .rx_enable = xgene_xgmac_rx_enable,
+ .tx_enable = xgene_xgmac_tx_enable,
+ .rx_disable = xgene_xgmac_rx_disable,
+ .tx_disable = xgene_xgmac_tx_disable,
+ .set_mac_addr = xgene_xgmac_set_mac_addr,
+ .link_state = xgene_enet_link_state
+};
+
+struct xgene_port_ops xgene_xgport_ops = {
+ .reset = xgene_enet_reset,
+ .cle_bypass = xgene_enet_xgcle_bypass,
+ .shutdown = xgene_enet_shutdown,
+};
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h
new file mode 100644
index 000000000000..5a5296a6d1df
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h
@@ -0,0 +1,53 @@
+/* Applied Micro X-Gene SoC Ethernet Driver
+ *
+ * Copyright (c) 2014, Applied Micro Circuits Corporation
+ * Authors: Iyappan Subramanian <isubramanian@apm.com>
+ * Keyur Chudgar <kchudgar@apm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __XGENE_ENET_XGMAC_H__
+#define __XGENE_ENET_XGMAC_H__
+
+#define BLOCK_AXG_MAC_OFFSET 0x0800
+#define BLOCK_AXG_MAC_CSR_OFFSET 0x2000
+
+#define AXGMAC_CONFIG_0 0x0000
+#define AXGMAC_CONFIG_1 0x0004
+#define HSTMACRST BIT(31)
+#define HSTTCTLEN BIT(31)
+#define HSTTFEN BIT(30)
+#define HSTRCTLEN BIT(29)
+#define HSTRFEN BIT(28)
+#define HSTPPEN BIT(7)
+#define HSTDRPLT64 BIT(5)
+#define HSTLENCHK BIT(3)
+#define HSTMACADR_LSW_ADDR 0x0010
+#define HSTMACADR_MSW_ADDR 0x0014
+#define HSTMAXFRAME_LENGTH_ADDR 0x0020
+
+#define XG_RSIF_CONFIG_REG_ADDR 0x00a0
+#define XCLE_BYPASS_REG0_ADDR 0x0160
+#define XCLE_BYPASS_REG1_ADDR 0x0164
+#define XG_CFG_BYPASS_ADDR 0x0204
+#define XG_LINK_STATUS_ADDR 0x0228
+#define XG_ENET_SPARE_CFG_REG_ADDR 0x040c
+#define XG_ENET_SPARE_CFG_REG_1_ADDR 0x0410
+#define XGENET_RX_DV_GATE_REG_0_ADDR 0x0804
+
+extern struct xgene_mac_ops xgene_xgmac_ops;
+extern struct xgene_port_ops xgene_xgport_ops;
+
+#endif /* __XGENE_ENET_XGMAC_H__ */
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
index 075688188644..9ae36979bdee 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
@@ -436,7 +436,8 @@ static int bcm_sysport_set_wol(struct net_device *dev,
/* Flag the device and relevant IRQ as wakeup capable */
if (wol->wolopts) {
device_set_wakeup_enable(kdev, 1);
- enable_irq_wake(priv->wol_irq);
+ if (priv->wol_irq_disabled)
+ enable_irq_wake(priv->wol_irq);
priv->wol_irq_disabled = 0;
} else {
device_set_wakeup_enable(kdev, 0);
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
index fff2634b6f34..fdc9ec09e453 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -1285,11 +1285,6 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_priv *priv,
cb = &priv->rx_cbs[priv->rx_read_ptr];
skb = cb->skb;
- rxpktprocessed++;
-
- priv->rx_read_ptr++;
- priv->rx_read_ptr &= (priv->num_rx_bds - 1);
-
/* We do not have a backing SKB, so we do not have a
* corresponding DMA mapping for this incoming packet since
* bcmgenet_rx_refill always either has both skb and mapping or
@@ -1404,6 +1399,10 @@ refill:
err = bcmgenet_rx_refill(priv, cb);
if (err)
netif_err(priv, rx_err, dev, "Rx refill failed\n");
+
+ rxpktprocessed++;
+ priv->rx_read_ptr++;
+ priv->rx_read_ptr &= (priv->num_rx_bds - 1);
}
return rxpktprocessed;
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c b/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
index b82b7e4e06b2..149a0d70c108 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
@@ -86,7 +86,9 @@ int bcmgenet_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
/* Flag the device and relevant IRQ as wakeup capable */
if (wol->wolopts) {
device_set_wakeup_enable(kdev, 1);
- enable_irq_wake(priv->wol_irq);
+ /* Avoid unbalanced enable_irq_wake calls */
+ if (priv->wol_irq_disabled)
+ enable_irq_wake(priv->wol_irq);
priv->wol_irq_disabled = false;
} else {
device_set_wakeup_enable(kdev, 0);
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index ba499489969a..dbb41c1923e6 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -8099,9 +8099,6 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* Sync BD data before updating mailbox */
wmb();
- /* Packets are ready, update Tx producer idx local and on card. */
- tw32_tx_mbox(tnapi->prodmbox, entry);
-
tnapi->tx_prod = entry;
if (unlikely(tg3_tx_avail(tnapi) <= (MAX_SKB_FRAGS + 1))) {
netif_tx_stop_queue(txq);
@@ -8116,7 +8113,12 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
netif_tx_wake_queue(txq);
}
- mmiowb();
+ if (!skb->xmit_more || netif_xmit_stopped(txq)) {
+ /* Packets are ready, update Tx producer idx on card. */
+ tw32_tx_mbox(tnapi->prodmbox, entry);
+ mmiowb();
+ }
+
return NETDEV_TX_OK;
dma_error:
diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c
index 153cafac323c..c3861de9dc81 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.c
+++ b/drivers/net/ethernet/brocade/bna/bnad.c
@@ -552,6 +552,7 @@ bnad_cq_setup_skb_frags(struct bna_rcb *rcb, struct sk_buff *skb,
len = (vec == nvecs) ?
last_fraglen : unmap->vector.len;
+ skb->truesize += unmap->vector.len;
totlen += len;
skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags,
@@ -563,7 +564,6 @@ bnad_cq_setup_skb_frags(struct bna_rcb *rcb, struct sk_buff *skb,
skb->len += totlen;
skb->data_len += totlen;
- skb->truesize += totlen;
}
static inline void
diff --git a/drivers/net/ethernet/chelsio/Kconfig b/drivers/net/ethernet/chelsio/Kconfig
index c3ce9df0041a..ac6473f75eb9 100644
--- a/drivers/net/ethernet/chelsio/Kconfig
+++ b/drivers/net/ethernet/chelsio/Kconfig
@@ -68,7 +68,7 @@ config CHELSIO_T3
config CHELSIO_T4
tristate "Chelsio Communications T4/T5 Ethernet support"
- depends on PCI
+ depends on PCI && (IPV6 || IPV6=n)
select FW_LOADER
select MDIO
---help---
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index 9b2c669b6522..3c481b260745 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -968,7 +968,7 @@ void t4_intr_enable(struct adapter *adapter);
void t4_intr_disable(struct adapter *adapter);
int t4_slow_intr_handler(struct adapter *adapter);
-int t4_wait_dev_ready(struct adapter *adap);
+int t4_wait_dev_ready(void __iomem *regs);
int t4_link_start(struct adapter *adap, unsigned int mbox, unsigned int port,
struct link_config *lc);
int t4_restart_aneg(struct adapter *adap, unsigned int mbox, unsigned int port);
@@ -986,6 +986,8 @@ static inline int t4_memory_write(struct adapter *adap, int mtype, u32 addr,
int t4_seeprom_wp(struct adapter *adapter, bool enable);
int get_vpd_params(struct adapter *adapter, struct vpd_params *p);
int t4_load_fw(struct adapter *adapter, const u8 *fw_data, unsigned int size);
+int t4_fw_upgrade(struct adapter *adap, unsigned int mbox,
+ const u8 *fw_data, unsigned int size, int force);
unsigned int t4_flash_cfg_addr(struct adapter *adapter);
int t4_get_fw_version(struct adapter *adapter, u32 *vers);
int t4_get_tp_version(struct adapter *adapter, u32 *vers);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 321f3d9385c9..3f60070f2519 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -2929,16 +2929,26 @@ static int set_flash(struct net_device *netdev, struct ethtool_flash *ef)
int ret;
const struct firmware *fw;
struct adapter *adap = netdev2adap(netdev);
+ unsigned int mbox = FW_PCIE_FW_MASTER_MASK + 1;
ef->data[sizeof(ef->data) - 1] = '\0';
ret = request_firmware(&fw, ef->data, adap->pdev_dev);
if (ret < 0)
return ret;
- ret = t4_load_fw(adap, fw->data, fw->size);
+ /* If the adapter has been fully initialized then we'll go ahead and
+ * try to get the firmware's cooperation in upgrading to the new
+ * firmware image otherwise we'll try to do the entire job from the
+ * host ... and we always "force" the operation in this path.
+ */
+ if (adap->flags & FULL_INIT_DONE)
+ mbox = adap->mbox;
+
+ ret = t4_fw_upgrade(adap, mbox, fw->data, fw->size, 1);
release_firmware(fw);
if (!ret)
- dev_info(adap->pdev_dev, "loaded firmware %s\n", ef->data);
+ dev_info(adap->pdev_dev, "loaded firmware %s,"
+ " reload cxgb4 driver\n", ef->data);
return ret;
}
@@ -4359,6 +4369,7 @@ EXPORT_SYMBOL(cxgb4_unregister_uld);
* success (true) if it belongs otherwise failure (false).
* Called with rcu_read_lock() held.
*/
+#if IS_ENABLED(CONFIG_IPV6)
static bool cxgb4_netdev(const struct net_device *netdev)
{
struct adapter *adap;
@@ -4480,6 +4491,13 @@ static int update_root_dev_clip(struct net_device *dev)
return ret;
/* Parse all bond and vlan devices layered on top of the physical dev */
+ root_dev = netdev_master_upper_dev_get_rcu(dev);
+ if (root_dev) {
+ ret = update_dev_clip(root_dev, dev);
+ if (ret)
+ return ret;
+ }
+
for (i = 0; i < VLAN_N_VID; i++) {
root_dev = __vlan_find_dev_deep_rcu(dev, htons(ETH_P_8021Q), i);
if (!root_dev)
@@ -4512,6 +4530,7 @@ static void update_clip(const struct adapter *adap)
}
rcu_read_unlock();
}
+#endif /* IS_ENABLED(CONFIG_IPV6) */
/**
* cxgb_up - enable the adapter
@@ -4558,7 +4577,9 @@ static int cxgb_up(struct adapter *adap)
t4_intr_enable(adap);
adap->flags |= FULL_INIT_DONE;
notify_ulds(adap, CXGB4_STATE_UP);
+#if IS_ENABLED(CONFIG_IPV6)
update_clip(adap);
+#endif
out:
return err;
irq_err:
@@ -6137,7 +6158,7 @@ static pci_ers_result_t eeh_slot_reset(struct pci_dev *pdev)
pci_save_state(pdev);
pci_cleanup_aer_uncorrect_error_status(pdev);
- if (t4_wait_dev_ready(adap) < 0)
+ if (t4_wait_dev_ready(adap->regs) < 0)
return PCI_ERS_RESULT_DISCONNECT;
if (t4_fw_hello(adap, adap->fn, adap->fn, MASTER_MUST, NULL) < 0)
return PCI_ERS_RESULT_DISCONNECT;
@@ -6530,6 +6551,10 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
goto out_disable_device;
}
+ err = t4_wait_dev_ready(regs);
+ if (err < 0)
+ goto out_unmap_bar0;
+
/* We control everything through one PF */
func = SOURCEPF_GET(readl(regs + PL_WHOAMI));
if (func != ent->driver_data) {
@@ -6848,14 +6873,18 @@ static int __init cxgb4_init_module(void)
if (ret < 0)
debugfs_remove(cxgb4_debugfs_root);
+#if IS_ENABLED(CONFIG_IPV6)
register_inet6addr_notifier(&cxgb4_inet6addr_notifier);
+#endif
return ret;
}
static void __exit cxgb4_cleanup_module(void)
{
+#if IS_ENABLED(CONFIG_IPV6)
unregister_inet6addr_notifier(&cxgb4_inet6addr_notifier);
+#endif
pci_unregister_driver(&cxgb4_driver);
debugfs_remove(cxgb4_debugfs_root); /* NULL ok */
}
diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c
index fab4c84a1da4..5e1b314e11af 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
@@ -1123,7 +1123,10 @@ out_free: dev_kfree_skb_any(skb);
lso->c.ipid_ofst = htons(0);
lso->c.mss = htons(ssi->gso_size);
lso->c.seqno_offset = htonl(0);
- lso->c.len = htonl(skb->len);
+ if (is_t4(adap->params.chip))
+ lso->c.len = htonl(skb->len);
+ else
+ lso->c.len = htonl(LSO_T5_XFER_SIZE(skb->len));
cpl = (void *)(lso + 1);
cntrl = TXPKT_CSUM_TYPE(v6 ? TX_CSUM_TCPIP6 : TX_CSUM_TCPIP) |
TXPKT_IPHDR_LEN(l3hdr_len) |
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
index 22d7581341a9..a9d9d74e4f09 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
@@ -37,8 +37,6 @@
#include "t4_regs.h"
#include "t4fw_api.h"
-static int t4_fw_upgrade(struct adapter *adap, unsigned int mbox,
- const u8 *fw_data, unsigned int size, int force);
/**
* t4_wait_op_done_val - wait until an operation is completed
* @adapter: the adapter performing the operation
@@ -3076,8 +3074,8 @@ static int t4_fw_restart(struct adapter *adap, unsigned int mbox, int reset)
* positive errno indicates that the adapter is ~probably~ intact, a
* negative errno indicates that things are looking bad ...
*/
-static int t4_fw_upgrade(struct adapter *adap, unsigned int mbox,
- const u8 *fw_data, unsigned int size, int force)
+int t4_fw_upgrade(struct adapter *adap, unsigned int mbox,
+ const u8 *fw_data, unsigned int size, int force)
{
const struct fw_hdr *fw_hdr = (const struct fw_hdr *)fw_data;
int reset, ret;
@@ -3845,12 +3843,19 @@ static void init_link_config(struct link_config *lc, unsigned int caps)
}
}
-int t4_wait_dev_ready(struct adapter *adap)
+#define CIM_PF_NOACCESS 0xeeeeeeee
+
+int t4_wait_dev_ready(void __iomem *regs)
{
- if (t4_read_reg(adap, PL_WHOAMI) != 0xffffffff)
+ u32 whoami;
+
+ whoami = readl(regs + PL_WHOAMI);
+ if (whoami != 0xffffffff && whoami != CIM_PF_NOACCESS)
return 0;
+
msleep(500);
- return t4_read_reg(adap, PL_WHOAMI) != 0xffffffff ? 0 : -EIO;
+ whoami = readl(regs + PL_WHOAMI);
+ return (whoami != 0xffffffff && whoami != CIM_PF_NOACCESS ? 0 : -EIO);
}
struct flash_desc {
@@ -3919,10 +3924,6 @@ int t4_prep_adapter(struct adapter *adapter)
uint16_t device_id;
u32 pl_rev;
- ret = t4_wait_dev_ready(adapter);
- if (ret < 0)
- return ret;
-
get_pci_mode(adapter, &adapter->params.pci);
pl_rev = G_REV(t4_read_reg(adapter, PL_REV));
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
index 52e08103f221..5f4db2398c71 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
@@ -527,6 +527,7 @@ struct cpl_tx_pkt_lso_core {
#define LSO_LAST_SLICE (1 << 22)
#define LSO_FIRST_SLICE (1 << 23)
#define LSO_OPCODE(x) ((x) << 24)
+#define LSO_T5_XFER_SIZE(x) ((x) << 0)
__be16 ipid_ofst;
__be16 mss;
__be32 seqno_offset;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
index eee272883027..a1024db5dc13 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
@@ -72,9 +72,8 @@
#define PIDX_MASK 0x00003fffU
#define PIDX_SHIFT 0
#define PIDX(x) ((x) << PIDX_SHIFT)
-#define S_PIDX_T5 0
-#define M_PIDX_T5 0x1fffU
-#define PIDX_T5(x) (((x) >> S_PIDX_T5) & M_PIDX_T5)
+#define PIDX_SHIFT_T5 0
+#define PIDX_T5(x) ((x) << PIDX_SHIFT_T5)
#define SGE_TIMERREGS 6
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
index 8498a641b2e3..bfa398d91826 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
@@ -163,15 +163,19 @@ void t4vf_os_link_changed(struct adapter *adapter, int pidx, int link_ok)
netif_carrier_on(dev);
switch (pi->link_cfg.speed) {
- case SPEED_10000:
+ case 40000:
+ s = "40Gbps";
+ break;
+
+ case 10000:
s = "10Gbps";
break;
- case SPEED_1000:
+ case 1000:
s = "1000Mbps";
break;
- case SPEED_100:
+ case 100:
s = "100Mbps";
break;
@@ -2351,7 +2355,7 @@ static void cfg_queues(struct adapter *adapter)
struct port_info *pi = adap2pinfo(adapter, pidx);
pi->first_qset = qidx;
- pi->nqsets = is_10g_port(&pi->link_cfg) ? q10g : 1;
+ pi->nqsets = is_x_10g_port(&pi->link_cfg) ? q10g : 1;
qidx += pi->nqsets;
}
s->ethqsets = qidx;
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c
index a5fb9493dee8..85036e6b42c4 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c
@@ -1208,7 +1208,10 @@ int t4vf_eth_xmit(struct sk_buff *skb, struct net_device *dev)
lso->ipid_ofst = cpu_to_be16(0);
lso->mss = cpu_to_be16(ssi->gso_size);
lso->seqno_offset = cpu_to_be32(0);
- lso->len = cpu_to_be32(skb->len);
+ if (is_t4(adapter->params.chip))
+ lso->len = cpu_to_be32(skb->len);
+ else
+ lso->len = cpu_to_be32(LSO_T5_XFER_SIZE(skb->len));
/*
* Set up TX Packet CPL pointer, control word and perform
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h
index f412d0fa0850..95df61dcb4ce 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h
@@ -228,6 +228,12 @@ static inline bool is_10g_port(const struct link_config *lc)
return (lc->supported & SUPPORTED_10000baseT_Full) != 0;
}
+static inline bool is_x_10g_port(const struct link_config *lc)
+{
+ return (lc->supported & FW_PORT_CAP_SPEED_10G) != 0 ||
+ (lc->supported & FW_PORT_CAP_SPEED_40G) != 0;
+}
+
static inline unsigned int core_ticks_per_usec(const struct adapter *adapter)
{
return adapter->params.vpd.cclk / 1000;
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c
index 25dfeb8f28ed..e984fdc48ba2 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c
@@ -327,6 +327,8 @@ int t4vf_port_init(struct adapter *adapter, int pidx)
v |= SUPPORTED_1000baseT_Full;
if (word & FW_PORT_CAP_SPEED_10G)
v |= SUPPORTED_10000baseT_Full;
+ if (word & FW_PORT_CAP_SPEED_40G)
+ v |= SUPPORTED_40000baseSR4_Full;
if (word & FW_PORT_CAP_ANEG)
v |= SUPPORTED_Autoneg;
init_link_config(&pi->link_cfg, v);
@@ -1352,11 +1354,13 @@ int t4vf_handle_fw_rpl(struct adapter *adapter, const __be64 *rpl)
if (word & FW_PORT_CMD_TXPAUSE)
fc |= PAUSE_TX;
if (word & FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_100M))
- speed = SPEED_100;
+ speed = 100;
else if (word & FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_1G))
- speed = SPEED_1000;
+ speed = 1000;
else if (word & FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_10G))
- speed = SPEED_10000;
+ speed = 10000;
+ else if (word & FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_40G))
+ speed = 40000;
/*
* Scan all of our "ports" (Virtual Interfaces) looking for
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index 1d5e1822bb2c..9af296a1ca99 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -367,6 +367,56 @@ struct bufdesc_ex {
#define FEC_VLAN_TAG_LEN 0x04
#define FEC_ETHTYPE_LEN 0x02
+/* Controller is ENET-MAC */
+#define FEC_QUIRK_ENET_MAC (1 << 0)
+/* Controller needs driver to swap frame */
+#define FEC_QUIRK_SWAP_FRAME (1 << 1)
+/* Controller uses gasket */
+#define FEC_QUIRK_USE_GASKET (1 << 2)
+/* Controller has GBIT support */
+#define FEC_QUIRK_HAS_GBIT (1 << 3)
+/* Controller has extend desc buffer */
+#define FEC_QUIRK_HAS_BUFDESC_EX (1 << 4)
+/* Controller has hardware checksum support */
+#define FEC_QUIRK_HAS_CSUM (1 << 5)
+/* Controller has hardware vlan support */
+#define FEC_QUIRK_HAS_VLAN (1 << 6)
+/* ENET IP errata ERR006358
+ *
+ * If the ready bit in the transmit buffer descriptor (TxBD[R]) is previously
+ * detected as not set during a prior frame transmission, then the
+ * ENET_TDAR[TDAR] bit is cleared at a later time, even if additional TxBDs
+ * were added to the ring and the ENET_TDAR[TDAR] bit is set. This results in
+ * frames not being transmitted until there is a 0-to-1 transition on
+ * ENET_TDAR[TDAR].
+ */
+#define FEC_QUIRK_ERR006358 (1 << 7)
+/* ENET IP hw AVB
+ *
+ * i.MX6SX ENET IP add Audio Video Bridging (AVB) feature support.
+ * - Two class indicators on receive with configurable priority
+ * - Two class indicators and line speed timer on transmit allowing
+ * implementation class credit based shapers externally
+ * - Additional DMA registers provisioned to allow managing up to 3
+ * independent rings
+ */
+#define FEC_QUIRK_HAS_AVB (1 << 8)
+/* There is a TDAR race condition for mutliQ when the software sets TDAR
+ * and the UDMA clears TDAR simultaneously or in a small window (2-4 cycles).
+ * This will cause the udma_tx and udma_tx_arbiter state machines to hang.
+ * The issue exist at i.MX6SX enet IP.
+ */
+#define FEC_QUIRK_ERR007885 (1 << 9)
+/* ENET Block Guide/ Chapter for the iMX6SX (PELE) address one issue:
+ * After set ENET_ATCR[Capture], there need some time cycles before the counter
+ * value is capture in the register clock domain.
+ * The wait-time-cycles is at least 6 clock cycles of the slower clock between
+ * the register clock and the 1588 clock. The 1588 ts_clk is fixed to 25Mhz,
+ * register clock is 66Mhz, so the wait-time-cycles must be greater than 240ns
+ * (40ns * 6).
+ */
+#define FEC_QUIRK_BUG_CAPTURE (1 << 10)
+
struct fec_enet_priv_tx_q {
int index;
unsigned char *tx_bounce[TX_RING_SIZE];
@@ -484,12 +534,22 @@ struct fec_enet_private {
unsigned int itr_clk_rate;
u32 rx_copybreak;
+
+ /* ptp clock period in ns*/
+ unsigned int ptp_inc;
+
+ /* pps */
+ int pps_channel;
+ unsigned int reload_period;
+ int pps_enable;
+ unsigned int next_counter;
};
void fec_ptp_init(struct platform_device *pdev);
void fec_ptp_start_cyclecounter(struct net_device *ndev);
int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr);
int fec_ptp_get(struct net_device *ndev, struct ifreq *ifr);
+uint fec_ptp_check_pps_event(struct fec_enet_private *fep);
/****************************************************************************/
#endif /* FEC_H */
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 87975b5dda94..81b96cf87574 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -78,47 +78,6 @@ static void fec_enet_itr_coal_init(struct net_device *ndev);
#define FEC_ENET_RAFL_V 0x8
#define FEC_ENET_OPD_V 0xFFF0
-/* Controller is ENET-MAC */
-#define FEC_QUIRK_ENET_MAC (1 << 0)
-/* Controller needs driver to swap frame */
-#define FEC_QUIRK_SWAP_FRAME (1 << 1)
-/* Controller uses gasket */
-#define FEC_QUIRK_USE_GASKET (1 << 2)
-/* Controller has GBIT support */
-#define FEC_QUIRK_HAS_GBIT (1 << 3)
-/* Controller has extend desc buffer */
-#define FEC_QUIRK_HAS_BUFDESC_EX (1 << 4)
-/* Controller has hardware checksum support */
-#define FEC_QUIRK_HAS_CSUM (1 << 5)
-/* Controller has hardware vlan support */
-#define FEC_QUIRK_HAS_VLAN (1 << 6)
-/* ENET IP errata ERR006358
- *
- * If the ready bit in the transmit buffer descriptor (TxBD[R]) is previously
- * detected as not set during a prior frame transmission, then the
- * ENET_TDAR[TDAR] bit is cleared at a later time, even if additional TxBDs
- * were added to the ring and the ENET_TDAR[TDAR] bit is set. This results in
- * frames not being transmitted until there is a 0-to-1 transition on
- * ENET_TDAR[TDAR].
- */
-#define FEC_QUIRK_ERR006358 (1 << 7)
-/* ENET IP hw AVB
- *
- * i.MX6SX ENET IP add Audio Video Bridging (AVB) feature support.
- * - Two class indicators on receive with configurable priority
- * - Two class indicators and line speed timer on transmit allowing
- * implementation class credit based shapers externally
- * - Additional DMA registers provisioned to allow managing up to 3
- * independent rings
- */
-#define FEC_QUIRK_HAS_AVB (1 << 8)
-/* There is a TDAR race condition for mutliQ when the software sets TDAR
- * and the UDMA clears TDAR simultaneously or in a small window (2-4 cycles).
- * This will cause the udma_tx and udma_tx_arbiter state machines to hang.
- * The issue exist at i.MX6SX enet IP.
- */
-#define FEC_QUIRK_ERR007885 (1 << 9)
-
static struct platform_device_id fec_devtype[] = {
{
/* keep it for coldfire */
@@ -146,7 +105,7 @@ static struct platform_device_id fec_devtype[] = {
.driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB |
- FEC_QUIRK_ERR007885,
+ FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE,
}, {
/* sentinel */
}
@@ -1622,6 +1581,8 @@ fec_enet_interrupt(int irq, void *dev_id)
complete(&fep->mdio_done);
}
+ fec_ptp_check_pps_event(fep);
+
return ret;
}
@@ -2912,20 +2873,12 @@ static void fec_poll_controller(struct net_device *dev)
#endif
#define FEATURES_NEED_QUIESCE NETIF_F_RXCSUM
-
-static int fec_set_features(struct net_device *netdev,
+static inline void fec_enet_set_netdev_features(struct net_device *netdev,
netdev_features_t features)
{
struct fec_enet_private *fep = netdev_priv(netdev);
netdev_features_t changed = features ^ netdev->features;
- /* Quiesce the device if necessary */
- if (netif_running(netdev) && changed & FEATURES_NEED_QUIESCE) {
- napi_disable(&fep->napi);
- netif_tx_lock_bh(netdev);
- fec_stop(netdev);
- }
-
netdev->features = features;
/* Receive checksum has been changed */
@@ -2935,13 +2888,25 @@ static int fec_set_features(struct net_device *netdev,
else
fep->csum_flags &= ~FLAG_RX_CSUM_ENABLED;
}
+}
+
+static int fec_set_features(struct net_device *netdev,
+ netdev_features_t features)
+{
+ struct fec_enet_private *fep = netdev_priv(netdev);
+ netdev_features_t changed = features ^ netdev->features;
- /* Resume the device after updates */
if (netif_running(netdev) && changed & FEATURES_NEED_QUIESCE) {
+ napi_disable(&fep->napi);
+ netif_tx_lock_bh(netdev);
+ fec_stop(netdev);
+ fec_enet_set_netdev_features(netdev, features);
fec_restart(netdev);
netif_tx_wake_all_queues(netdev);
netif_tx_unlock_bh(netdev);
napi_enable(&fep->napi);
+ } else {
+ fec_enet_set_netdev_features(netdev, features);
}
return 0;
diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c
index cca3617a2321..992c8c3db553 100644
--- a/drivers/net/ethernet/freescale/fec_ptp.c
+++ b/drivers/net/ethernet/freescale/fec_ptp.c
@@ -61,6 +61,24 @@
#define FEC_T_INC_CORR_MASK 0x00007f00
#define FEC_T_INC_CORR_OFFSET 8
+#define FEC_T_CTRL_PINPER 0x00000080
+#define FEC_T_TF0_MASK 0x00000001
+#define FEC_T_TF0_OFFSET 0
+#define FEC_T_TF1_MASK 0x00000002
+#define FEC_T_TF1_OFFSET 1
+#define FEC_T_TF2_MASK 0x00000004
+#define FEC_T_TF2_OFFSET 2
+#define FEC_T_TF3_MASK 0x00000008
+#define FEC_T_TF3_OFFSET 3
+#define FEC_T_TDRE_MASK 0x00000001
+#define FEC_T_TDRE_OFFSET 0
+#define FEC_T_TMODE_MASK 0x0000003C
+#define FEC_T_TMODE_OFFSET 2
+#define FEC_T_TIE_MASK 0x00000040
+#define FEC_T_TIE_OFFSET 6
+#define FEC_T_TF_MASK 0x00000080
+#define FEC_T_TF_OFFSET 7
+
#define FEC_ATIME_CTRL 0x400
#define FEC_ATIME 0x404
#define FEC_ATIME_EVT_OFFSET 0x408
@@ -69,7 +87,143 @@
#define FEC_ATIME_INC 0x414
#define FEC_TS_TIMESTAMP 0x418
+#define FEC_TGSR 0x604
+#define FEC_TCSR(n) (0x608 + n * 0x08)
+#define FEC_TCCR(n) (0x60C + n * 0x08)
+#define MAX_TIMER_CHANNEL 3
+#define FEC_TMODE_TOGGLE 0x05
+#define FEC_HIGH_PULSE 0x0F
+
#define FEC_CC_MULT (1 << 31)
+#define FEC_COUNTER_PERIOD (1 << 31)
+#define PPS_OUPUT_RELOAD_PERIOD NSEC_PER_SEC
+#define FEC_CHANNLE_0 0
+#define DEFAULT_PPS_CHANNEL FEC_CHANNLE_0
+
+/**
+ * fec_ptp_enable_pps
+ * @fep: the fec_enet_private structure handle
+ * @enable: enable the channel pps output
+ *
+ * This function enble the PPS ouput on the timer channel.
+ */
+static int fec_ptp_enable_pps(struct fec_enet_private *fep, uint enable)
+{
+ unsigned long flags;
+ u32 val, tempval;
+ int inc;
+ struct timespec ts;
+ u64 ns;
+ u32 remainder;
+ val = 0;
+
+ if (!(fep->hwts_tx_en || fep->hwts_rx_en)) {
+ dev_err(&fep->pdev->dev, "No ptp stack is running\n");
+ return -EINVAL;
+ }
+
+ if (fep->pps_enable == enable)
+ return 0;
+
+ fep->pps_channel = DEFAULT_PPS_CHANNEL;
+ fep->reload_period = PPS_OUPUT_RELOAD_PERIOD;
+ inc = fep->ptp_inc;
+
+ spin_lock_irqsave(&fep->tmreg_lock, flags);
+
+ if (enable) {
+ /* clear capture or output compare interrupt status if have.
+ */
+ writel(FEC_T_TF_MASK, fep->hwp + FEC_TCSR(fep->pps_channel));
+
+ /* It is recommended to doulbe check the TMODE field in the
+ * TCSR register to be cleared before the first compare counter
+ * is written into TCCR register. Just add a double check.
+ */
+ val = readl(fep->hwp + FEC_TCSR(fep->pps_channel));
+ do {
+ val &= ~(FEC_T_TMODE_MASK);
+ writel(val, fep->hwp + FEC_TCSR(fep->pps_channel));
+ val = readl(fep->hwp + FEC_TCSR(fep->pps_channel));
+ } while (val & FEC_T_TMODE_MASK);
+
+ /* Dummy read counter to update the counter */
+ timecounter_read(&fep->tc);
+ /* We want to find the first compare event in the next
+ * second point. So we need to know what the ptp time
+ * is now and how many nanoseconds is ahead to get next second.
+ * The remaining nanosecond ahead before the next second would be
+ * NSEC_PER_SEC - ts.tv_nsec. Add the remaining nanoseconds
+ * to current timer would be next second.
+ */
+ tempval = readl(fep->hwp + FEC_ATIME_CTRL);
+ tempval |= FEC_T_CTRL_CAPTURE;
+ writel(tempval, fep->hwp + FEC_ATIME_CTRL);
+
+ tempval = readl(fep->hwp + FEC_ATIME);
+ /* Convert the ptp local counter to 1588 timestamp */
+ ns = timecounter_cyc2time(&fep->tc, tempval);
+ ts.tv_sec = div_u64_rem(ns, 1000000000ULL, &remainder);
+ ts.tv_nsec = remainder;
+
+ /* The tempval is less than 3 seconds, and so val is less than
+ * 4 seconds. No overflow for 32bit calculation.
+ */
+ val = NSEC_PER_SEC - (u32)ts.tv_nsec + tempval;
+
+ /* Need to consider the situation that the current time is
+ * very close to the second point, which means NSEC_PER_SEC
+ * - ts.tv_nsec is close to be zero(For example 20ns); Since the timer
+ * is still running when we calculate the first compare event, it is
+ * possible that the remaining nanoseonds run out before the compare
+ * counter is calculated and written into TCCR register. To avoid
+ * this possibility, we will set the compare event to be the next
+ * of next second. The current setting is 31-bit timer and wrap
+ * around over 2 seconds. So it is okay to set the next of next
+ * seond for the timer.
+ */
+ val += NSEC_PER_SEC;
+
+ /* We add (2 * NSEC_PER_SEC - (u32)ts.tv_nsec) to current
+ * ptp counter, which maybe cause 32-bit wrap. Since the
+ * (NSEC_PER_SEC - (u32)ts.tv_nsec) is less than 2 second.
+ * We can ensure the wrap will not cause issue. If the offset
+ * is bigger than fep->cc.mask would be a error.
+ */
+ val &= fep->cc.mask;
+ writel(val, fep->hwp + FEC_TCCR(fep->pps_channel));
+
+ /* Calculate the second the compare event timestamp */
+ fep->next_counter = (val + fep->reload_period) & fep->cc.mask;
+
+ /* * Enable compare event when overflow */
+ val = readl(fep->hwp + FEC_ATIME_CTRL);
+ val |= FEC_T_CTRL_PINPER;
+ writel(val, fep->hwp + FEC_ATIME_CTRL);
+
+ /* Compare channel setting. */
+ val = readl(fep->hwp + FEC_TCSR(fep->pps_channel));
+ val |= (1 << FEC_T_TF_OFFSET | 1 << FEC_T_TIE_OFFSET);
+ val &= ~(1 << FEC_T_TDRE_OFFSET);
+ val &= ~(FEC_T_TMODE_MASK);
+ val |= (FEC_HIGH_PULSE << FEC_T_TMODE_OFFSET);
+ writel(val, fep->hwp + FEC_TCSR(fep->pps_channel));
+
+ /* Write the second compare event timestamp and calculate
+ * the third timestamp. Refer the TCCR register detail in the spec.
+ */
+ writel(fep->next_counter, fep->hwp + FEC_TCCR(fep->pps_channel));
+ fep->next_counter = (fep->next_counter + fep->reload_period) & fep->cc.mask;
+ } else {
+ writel(0, fep->hwp + FEC_TCSR(fep->pps_channel));
+ }
+
+ fep->pps_enable = enable;
+ spin_unlock_irqrestore(&fep->tmreg_lock, flags);
+
+ return 0;
+}
+
/**
* fec_ptp_read - read raw cycle counter (to be used by time counter)
* @cc: the cyclecounter structure
@@ -82,12 +236,17 @@ static cycle_t fec_ptp_read(const struct cyclecounter *cc)
{
struct fec_enet_private *fep =
container_of(cc, struct fec_enet_private, cc);
+ const struct platform_device_id *id_entry =
+ platform_get_device_id(fep->pdev);
u32 tempval;
tempval = readl(fep->hwp + FEC_ATIME_CTRL);
tempval |= FEC_T_CTRL_CAPTURE;
writel(tempval, fep->hwp + FEC_ATIME_CTRL);
+ if (id_entry->driver_data & FEC_QUIRK_BUG_CAPTURE)
+ udelay(1);
+
return readl(fep->hwp + FEC_ATIME);
}
@@ -113,14 +272,15 @@ void fec_ptp_start_cyclecounter(struct net_device *ndev)
/* 1ns counter */
writel(inc << FEC_T_INC_OFFSET, fep->hwp + FEC_ATIME_INC);
- /* use free running count */
- writel(0, fep->hwp + FEC_ATIME_EVT_PERIOD);
+ /* use 31-bit timer counter */
+ writel(FEC_COUNTER_PERIOD, fep->hwp + FEC_ATIME_EVT_PERIOD);
- writel(FEC_T_CTRL_ENABLE, fep->hwp + FEC_ATIME_CTRL);
+ writel(FEC_T_CTRL_ENABLE | FEC_T_CTRL_PERIOD_RST,
+ fep->hwp + FEC_ATIME_CTRL);
memset(&fep->cc, 0, sizeof(fep->cc));
fep->cc.read = fec_ptp_read;
- fep->cc.mask = CLOCKSOURCE_MASK(32);
+ fep->cc.mask = CLOCKSOURCE_MASK(31);
fep->cc.shift = 31;
fep->cc.mult = FEC_CC_MULT;
@@ -143,32 +303,59 @@ void fec_ptp_start_cyclecounter(struct net_device *ndev)
*/
static int fec_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
{
- u64 diff;
unsigned long flags;
int neg_adj = 0;
- u32 mult = FEC_CC_MULT;
+ u32 i, tmp;
+ u32 corr_inc, corr_period;
+ u32 corr_ns;
+ u64 lhs, rhs;
struct fec_enet_private *fep =
container_of(ptp, struct fec_enet_private, ptp_caps);
+ if (ppb == 0)
+ return 0;
+
if (ppb < 0) {
ppb = -ppb;
neg_adj = 1;
}
- diff = mult;
- diff *= ppb;
- diff = div_u64(diff, 1000000000ULL);
+ /* In theory, corr_inc/corr_period = ppb/NSEC_PER_SEC;
+ * Try to find the corr_inc between 1 to fep->ptp_inc to
+ * meet adjustment requirement.
+ */
+ lhs = NSEC_PER_SEC;
+ rhs = (u64)ppb * (u64)fep->ptp_inc;
+ for (i = 1; i <= fep->ptp_inc; i++) {
+ if (lhs >= rhs) {
+ corr_inc = i;
+ corr_period = div_u64(lhs, rhs);
+ break;
+ }
+ lhs += NSEC_PER_SEC;
+ }
+ /* Not found? Set it to high value - double speed
+ * correct in every clock step.
+ */
+ if (i > fep->ptp_inc) {
+ corr_inc = fep->ptp_inc;
+ corr_period = 1;
+ }
+
+ if (neg_adj)
+ corr_ns = fep->ptp_inc - corr_inc;
+ else
+ corr_ns = fep->ptp_inc + corr_inc;
spin_lock_irqsave(&fep->tmreg_lock, flags);
- /*
- * dummy read to set cycle_last in tc to now.
- * So use adjusted mult to calculate when next call
- * timercounter_read.
- */
- timecounter_read(&fep->tc);
- fep->cc.mult = neg_adj ? mult - diff : mult + diff;
+ tmp = readl(fep->hwp + FEC_ATIME_INC) & FEC_T_INC_MASK;
+ tmp |= corr_ns << FEC_T_INC_CORR_OFFSET;
+ writel(tmp, fep->hwp + FEC_ATIME_INC);
+ writel(corr_period, fep->hwp + FEC_ATIME_CORR);
+ /* dummy read to update the timer. */
+ timecounter_read(&fep->tc);
spin_unlock_irqrestore(&fep->tmreg_lock, flags);
@@ -188,12 +375,19 @@ static int fec_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
container_of(ptp, struct fec_enet_private, ptp_caps);
unsigned long flags;
u64 now;
+ u32 counter;
spin_lock_irqsave(&fep->tmreg_lock, flags);
now = timecounter_read(&fep->tc);
now += delta;
+ /* Get the timer value based on adjusted timestamp.
+ * Update the counter with the masked value.
+ */
+ counter = now & fep->cc.mask;
+ writel(counter, fep->hwp + FEC_ATIME);
+
/* reset the timecounter */
timecounter_init(&fep->tc, &fep->cc, now);
@@ -244,6 +438,7 @@ static int fec_ptp_settime(struct ptp_clock_info *ptp,
u64 ns;
unsigned long flags;
+ u32 counter;
mutex_lock(&fep->ptp_clk_mutex);
/* Check the ptp clock */
@@ -254,8 +449,13 @@ static int fec_ptp_settime(struct ptp_clock_info *ptp,
ns = ts->tv_sec * 1000000000ULL;
ns += ts->tv_nsec;
+ /* Get the timer value based on timestamp.
+ * Update the counter with the masked value.
+ */
+ counter = ns & fep->cc.mask;
spin_lock_irqsave(&fep->tmreg_lock, flags);
+ writel(counter, fep->hwp + FEC_ATIME);
timecounter_init(&fep->tc, &fep->cc, ns);
spin_unlock_irqrestore(&fep->tmreg_lock, flags);
mutex_unlock(&fep->ptp_clk_mutex);
@@ -272,6 +472,15 @@ static int fec_ptp_settime(struct ptp_clock_info *ptp,
static int fec_ptp_enable(struct ptp_clock_info *ptp,
struct ptp_clock_request *rq, int on)
{
+ struct fec_enet_private *fep =
+ container_of(ptp, struct fec_enet_private, ptp_caps);
+ int ret = 0;
+
+ if (rq->type == PTP_CLK_REQ_PPS) {
+ ret = fec_ptp_enable_pps(fep, on);
+
+ return ret;
+ }
return -EOPNOTSUPP;
}
@@ -386,7 +595,7 @@ void fec_ptp_init(struct platform_device *pdev)
fep->ptp_caps.n_ext_ts = 0;
fep->ptp_caps.n_per_out = 0;
fep->ptp_caps.n_pins = 0;
- fep->ptp_caps.pps = 0;
+ fep->ptp_caps.pps = 1;
fep->ptp_caps.adjfreq = fec_ptp_adjfreq;
fep->ptp_caps.adjtime = fec_ptp_adjtime;
fep->ptp_caps.gettime = fec_ptp_gettime;
@@ -394,6 +603,7 @@ void fec_ptp_init(struct platform_device *pdev)
fep->ptp_caps.enable = fec_ptp_enable;
fep->cycle_speed = clk_get_rate(fep->clk_ptp);
+ fep->ptp_inc = NSEC_PER_SEC / fep->cycle_speed;
spin_lock_init(&fep->tmreg_lock);
@@ -409,3 +619,36 @@ void fec_ptp_init(struct platform_device *pdev)
schedule_delayed_work(&fep->time_keep, HZ);
}
+
+/**
+ * fec_ptp_check_pps_event
+ * @fep: the fec_enet_private structure handle
+ *
+ * This function check the pps event and reload the timer compare counter.
+ */
+uint fec_ptp_check_pps_event(struct fec_enet_private *fep)
+{
+ u32 val;
+ u8 channel = fep->pps_channel;
+ struct ptp_clock_event event;
+
+ val = readl(fep->hwp + FEC_TCSR(channel));
+ if (val & FEC_T_TF_MASK) {
+ /* Write the next next compare(not the next according the spec)
+ * value to the register
+ */
+ writel(fep->next_counter, fep->hwp + FEC_TCCR(channel));
+ do {
+ writel(val, fep->hwp + FEC_TCSR(channel));
+ } while (readl(fep->hwp + FEC_TCSR(channel)) & FEC_T_TF_MASK);
+
+ /* Update the counter; */
+ fep->next_counter = (fep->next_counter + fep->reload_period) & fep->cc.mask;
+
+ event.type = PTP_CLOCK_PPS;
+ ptp_clock_event(fep->ptp_clock, &event);
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c b/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c
index 2c578db401e8..08f5b911d96b 100644
--- a/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c
+++ b/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c
@@ -125,7 +125,7 @@ out:
}
#define FCC_NAPI_RX_EVENT_MSK (FCC_ENET_RXF | FCC_ENET_RXB)
-#define FCC_NAPI_TX_EVENT_MSK (FCC_ENET_TXF | FCC_ENET_TXB)
+#define FCC_NAPI_TX_EVENT_MSK (FCC_ENET_TXB)
#define FCC_RX_EVENT (FCC_ENET_RXF)
#define FCC_TX_EVENT (FCC_ENET_TXB)
#define FCC_ERR_EVENT_MSK (FCC_ENET_TXE)
diff --git a/drivers/net/ethernet/freescale/fs_enet/mac-scc.c b/drivers/net/ethernet/freescale/fs_enet/mac-scc.c
index 41aa0b475ca0..f30411f0701f 100644
--- a/drivers/net/ethernet/freescale/fs_enet/mac-scc.c
+++ b/drivers/net/ethernet/freescale/fs_enet/mac-scc.c
@@ -116,7 +116,7 @@ static int do_pd_setup(struct fs_enet_private *fep)
}
#define SCC_NAPI_RX_EVENT_MSK (SCCE_ENET_RXF | SCCE_ENET_RXB)
-#define SCC_NAPI_TX_EVENT_MSK (SCCE_ENET_TXF | SCCE_ENET_TXB)
+#define SCC_NAPI_TX_EVENT_MSK (SCCE_ENET_TXB)
#define SCC_RX_EVENT (SCCE_ENET_RXF)
#define SCC_TX_EVENT (SCCE_ENET_TXB)
#define SCC_ERR_EVENT_MSK (SCCE_ENET_TXE | SCCE_ENET_BSY)
diff --git a/drivers/net/ethernet/freescale/fsl_pq_mdio.c b/drivers/net/ethernet/freescale/fsl_pq_mdio.c
index 583e71ab7f51..964c6bf37710 100644
--- a/drivers/net/ethernet/freescale/fsl_pq_mdio.c
+++ b/drivers/net/ethernet/freescale/fsl_pq_mdio.c
@@ -28,7 +28,9 @@
#include <linux/of_device.h>
#include <asm/io.h>
+#if IS_ENABLED(CONFIG_UCC_GETH)
#include <asm/ucc.h> /* for ucc_set_qe_mux_mii_mng() */
+#endif
#include "gianfar.h"
@@ -102,19 +104,22 @@ static int fsl_pq_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
{
struct fsl_pq_mdio_priv *priv = bus->priv;
struct fsl_pq_mii __iomem *regs = priv->regs;
- u32 status;
+ unsigned int timeout;
/* Set the PHY address and the register address we want to write */
- out_be32(&regs->miimadd, (mii_id << 8) | regnum);
+ iowrite32be((mii_id << 8) | regnum, &regs->miimadd);
/* Write out the value we want */
- out_be32(&regs->miimcon, value);
+ iowrite32be(value, &regs->miimcon);
/* Wait for the transaction to finish */
- status = spin_event_timeout(!(in_be32(&regs->miimind) & MIIMIND_BUSY),
- MII_TIMEOUT, 0);
+ timeout = MII_TIMEOUT;
+ while ((ioread32be(&regs->miimind) & MIIMIND_BUSY) && timeout) {
+ cpu_relax();
+ timeout--;
+ }
- return status ? 0 : -ETIMEDOUT;
+ return timeout ? 0 : -ETIMEDOUT;
}
/*
@@ -131,25 +136,29 @@ static int fsl_pq_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
{
struct fsl_pq_mdio_priv *priv = bus->priv;
struct fsl_pq_mii __iomem *regs = priv->regs;
- u32 status;
+ unsigned int timeout;
u16 value;
/* Set the PHY address and the register address we want to read */
- out_be32(&regs->miimadd, (mii_id << 8) | regnum);
+ iowrite32be((mii_id << 8) | regnum, &regs->miimadd);
/* Clear miimcom, and then initiate a read */
- out_be32(&regs->miimcom, 0);
- out_be32(&regs->miimcom, MII_READ_COMMAND);
+ iowrite32be(0, &regs->miimcom);
+ iowrite32be(MII_READ_COMMAND, &regs->miimcom);
/* Wait for the transaction to finish, normally less than 100us */
- status = spin_event_timeout(!(in_be32(&regs->miimind) &
- (MIIMIND_NOTVALID | MIIMIND_BUSY)),
- MII_TIMEOUT, 0);
- if (!status)
+ timeout = MII_TIMEOUT;
+ while ((ioread32be(&regs->miimind) &
+ (MIIMIND_NOTVALID | MIIMIND_BUSY)) && timeout) {
+ cpu_relax();
+ timeout--;
+ }
+
+ if (!timeout)
return -ETIMEDOUT;
/* Grab the value of the register from miimstat */
- value = in_be32(&regs->miimstat);
+ value = ioread32be(&regs->miimstat);
dev_dbg(&bus->dev, "read %04x from address %x/%x\n", value, mii_id, regnum);
return value;
@@ -160,23 +169,26 @@ static int fsl_pq_mdio_reset(struct mii_bus *bus)
{
struct fsl_pq_mdio_priv *priv = bus->priv;
struct fsl_pq_mii __iomem *regs = priv->regs;
- u32 status;
+ unsigned int timeout;
mutex_lock(&bus->mdio_lock);
/* Reset the management interface */
- out_be32(&regs->miimcfg, MIIMCFG_RESET);
+ iowrite32be(MIIMCFG_RESET, &regs->miimcfg);
/* Setup the MII Mgmt clock speed */
- out_be32(&regs->miimcfg, MIIMCFG_INIT_VALUE);
+ iowrite32be(MIIMCFG_INIT_VALUE, &regs->miimcfg);
/* Wait until the bus is free */
- status = spin_event_timeout(!(in_be32(&regs->miimind) & MIIMIND_BUSY),
- MII_TIMEOUT, 0);
+ timeout = MII_TIMEOUT;
+ while ((ioread32be(&regs->miimind) & MIIMIND_BUSY) && timeout) {
+ cpu_relax();
+ timeout--;
+ }
mutex_unlock(&bus->mdio_lock);
- if (!status) {
+ if (!timeout) {
dev_err(&bus->dev, "timeout waiting for MII bus\n");
return -EBUSY;
}
@@ -433,7 +445,7 @@ static int fsl_pq_mdio_probe(struct platform_device *pdev)
tbipa = data->get_tbipa(priv->map);
- out_be32(tbipa, be32_to_cpup(prop));
+ iowrite32be(be32_to_cpup(prop), tbipa);
}
}
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index fb29d049f4e1..4fdf0aa16978 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -88,8 +88,10 @@
#include <linux/net_tstamp.h>
#include <asm/io.h>
+#ifdef CONFIG_PPC
#include <asm/reg.h>
#include <asm/mpc85xx.h>
+#endif
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <linux/module.h>
@@ -100,6 +102,8 @@
#include <linux/phy_fixed.h>
#include <linux/of.h>
#include <linux/of_net.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
#include "gianfar.h"
@@ -161,7 +165,7 @@ static void gfar_init_rxbdp(struct gfar_priv_rx_q *rx_queue, struct rxbd8 *bdp,
if (bdp == rx_queue->rx_bd_base + rx_queue->rx_ring_size - 1)
lstatus |= BD_LFLAG(RXBD_WRAP);
- eieio();
+ gfar_wmb();
bdp->lstatus = lstatus;
}
@@ -334,7 +338,7 @@ static void gfar_init_tx_rx_base(struct gfar_private *priv)
static void gfar_rx_buff_size_config(struct gfar_private *priv)
{
- int frame_size = priv->ndev->mtu + ETH_HLEN;
+ int frame_size = priv->ndev->mtu + ETH_HLEN + ETH_FCS_LEN;
/* set this when rx hw offload (TOE) functions are being used */
priv->uses_rxfcb = 0;
@@ -1061,6 +1065,7 @@ static void gfar_init_filer_table(struct gfar_private *priv)
}
}
+#ifdef CONFIG_PPC
static void __gfar_detect_errata_83xx(struct gfar_private *priv)
{
unsigned int pvr = mfspr(SPRN_PVR);
@@ -1093,6 +1098,7 @@ static void __gfar_detect_errata_85xx(struct gfar_private *priv)
((SVR_SOC_VER(svr) == SVR_P2010) && (SVR_REV(svr) < 0x20)))
priv->errata |= GFAR_ERRATA_76; /* aka eTSEC 20 */
}
+#endif
static void gfar_detect_errata(struct gfar_private *priv)
{
@@ -1101,10 +1107,12 @@ static void gfar_detect_errata(struct gfar_private *priv)
/* no plans to fix */
priv->errata |= GFAR_ERRATA_A002;
+#ifdef CONFIG_PPC
if (pvr_version_is(PVR_VER_E500V1) || pvr_version_is(PVR_VER_E500V2))
__gfar_detect_errata_85xx(priv);
else /* non-mpc85xx parts, i.e. e300 core based */
__gfar_detect_errata_83xx(priv);
+#endif
if (priv->errata)
dev_info(dev, "enabled errata workarounds, flags: 0x%x\n",
@@ -1754,26 +1762,32 @@ static void gfar_halt_nodisable(struct gfar_private *priv)
{
struct gfar __iomem *regs = priv->gfargrp[0].regs;
u32 tempval;
+ unsigned int timeout;
+ int stopped;
gfar_ints_disable(priv);
+ if (gfar_is_dma_stopped(priv))
+ return;
+
/* Stop the DMA, and wait for it to stop */
tempval = gfar_read(&regs->dmactrl);
- if ((tempval & (DMACTRL_GRS | DMACTRL_GTS)) !=
- (DMACTRL_GRS | DMACTRL_GTS)) {
- int ret;
-
- tempval |= (DMACTRL_GRS | DMACTRL_GTS);
- gfar_write(&regs->dmactrl, tempval);
+ tempval |= (DMACTRL_GRS | DMACTRL_GTS);
+ gfar_write(&regs->dmactrl, tempval);
- do {
- ret = spin_event_timeout(((gfar_read(&regs->ievent) &
- (IEVENT_GRSC | IEVENT_GTSC)) ==
- (IEVENT_GRSC | IEVENT_GTSC)), 1000000, 0);
- if (!ret && !(gfar_read(&regs->ievent) & IEVENT_GRSC))
- ret = __gfar_is_rx_idle(priv);
- } while (!ret);
+retry:
+ timeout = 1000;
+ while (!(stopped = gfar_is_dma_stopped(priv)) && timeout) {
+ cpu_relax();
+ timeout--;
}
+
+ if (!timeout)
+ stopped = gfar_is_dma_stopped(priv);
+
+ if (!stopped && !gfar_is_rx_dma_stopped(priv) &&
+ !__gfar_is_rx_idle(priv))
+ goto retry;
}
/* Halt the receive and transmit queues */
@@ -2357,18 +2371,11 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
*/
spin_lock_irqsave(&tx_queue->txlock, flags);
- /* The powerpc-specific eieio() is used, as wmb() has too strong
- * semantics (it requires synchronization between cacheable and
- * uncacheable mappings, which eieio doesn't provide and which we
- * don't need), thus requiring a more expensive sync instruction. At
- * some point, the set of architecture-independent barrier functions
- * should be expanded to include weaker barriers.
- */
- eieio();
+ gfar_wmb();
txbdp_start->lstatus = lstatus;
- eieio(); /* force lstatus write before tx_skbuff */
+ gfar_wmb(); /* force lstatus write before tx_skbuff */
tx_queue->tx_skbuff[tx_queue->skb_curtx] = skb;
@@ -3240,22 +3247,21 @@ static void gfar_set_mac_for_addr(struct net_device *dev, int num,
{
struct gfar_private *priv = netdev_priv(dev);
struct gfar __iomem *regs = priv->gfargrp[0].regs;
- int idx;
- char tmpbuf[ETH_ALEN];
u32 tempval;
u32 __iomem *macptr = &regs->macstnaddr1;
macptr += num*2;
- /* Now copy it into the mac registers backwards, cuz
- * little endian is silly
+ /* For a station address of 0x12345678ABCD in transmission
+ * order (BE), MACnADDR1 is set to 0xCDAB7856 and
+ * MACnADDR2 is set to 0x34120000.
*/
- for (idx = 0; idx < ETH_ALEN; idx++)
- tmpbuf[ETH_ALEN - 1 - idx] = addr[idx];
+ tempval = (addr[5] << 24) | (addr[4] << 16) |
+ (addr[3] << 8) | addr[2];
- gfar_write(macptr, *((u32 *) (tmpbuf)));
+ gfar_write(macptr, tempval);
- tempval = *((u32 *) (tmpbuf + 4));
+ tempval = (addr[1] << 24) | (addr[0] << 16);
gfar_write(macptr+1, tempval);
}
diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h
index 84632c569f2c..2805cfbf1765 100644
--- a/drivers/net/ethernet/freescale/gianfar.h
+++ b/drivers/net/ethernet/freescale/gianfar.h
@@ -1226,6 +1226,37 @@ static inline void gfar_write_isrg(struct gfar_private *priv)
}
}
+static inline int gfar_is_dma_stopped(struct gfar_private *priv)
+{
+ struct gfar __iomem *regs = priv->gfargrp[0].regs;
+
+ return ((gfar_read(&regs->ievent) & (IEVENT_GRSC | IEVENT_GTSC)) ==
+ (IEVENT_GRSC | IEVENT_GTSC));
+}
+
+static inline int gfar_is_rx_dma_stopped(struct gfar_private *priv)
+{
+ struct gfar __iomem *regs = priv->gfargrp[0].regs;
+
+ return gfar_read(&regs->ievent) & IEVENT_GRSC;
+}
+
+static inline void gfar_wmb(void)
+{
+#if defined(CONFIG_PPC)
+ /* The powerpc-specific eieio() is used, as wmb() has too strong
+ * semantics (it requires synchronization between cacheable and
+ * uncacheable mappings, which eieio() doesn't provide and which we
+ * don't need), thus requiring a more expensive sync instruction. At
+ * some point, the set of architecture-independent barrier functions
+ * should be expanded to include weaker barriers.
+ */
+ eieio();
+#else
+ wmb(); /* order write acesses for BD (or FCB) fields */
+#endif
+}
+
irqreturn_t gfar_receive(int irq, void *dev_id);
int startup_gfar(struct net_device *dev);
void stop_gfar(struct net_device *dev);
diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig
index 6a6d5ee51e6a..5b8300a32bf5 100644
--- a/drivers/net/ethernet/intel/Kconfig
+++ b/drivers/net/ethernet/intel/Kconfig
@@ -304,6 +304,7 @@ config FM10K
tristate "Intel(R) FM10000 Ethernet Switch Host Interface Support"
default n
depends on PCI_MSI
+ select PTP_1588_CLOCK
---help---
This driver supports Intel(R) FM10000 Ethernet Switch Host
Interface. For more information on how to identify your adapter,
@@ -319,4 +320,15 @@ config FM10K
To compile this driver as a module, choose M here. The module
will be called fm10k. MSI-X interrupt support is required
+config FM10K_VXLAN
+ bool "Virtual eXtensible Local Area Network Support"
+ default n
+ depends on FM10K && VXLAN && !(FM10K=y && VXLAN=m)
+ ---help---
+ This allows one to create VXLAN virtual interfaces that provide
+ Layer 2 Networks over Layer 3 Networks. VXLAN is often used
+ to tunnel virtual network infrastructure in virtualized environments.
+ Say Y here if you want to use Virtual eXtensible Local Area Network
+ (VXLAN) in the driver.
+
endif # NET_VENDOR_INTEL
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c
index 6c800a330d66..e645af412e76 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c
@@ -219,11 +219,10 @@ static bool fm10k_can_reuse_rx_page(struct fm10k_rx_buffer *rx_buffer,
/* flip page offset to other buffer */
rx_buffer->page_offset ^= FM10K_RX_BUFSZ;
- /* since we are the only owner of the page and we need to
- * increment it, just set the value to 2 in order to avoid
- * an unnecessary locked operation
+ /* Even if we own the page, we are not allowed to use atomic_set()
+ * This would break get_page_unless_zero() users.
*/
- atomic_set(&page->_count, 2);
+ atomic_inc(&page->_count);
#else
/* move offset up to the next cache line */
rx_buffer->page_offset += truesize;
@@ -930,6 +929,30 @@ static bool fm10k_tx_desc_push(struct fm10k_ring *tx_ring,
return i == tx_ring->count;
}
+static int __fm10k_maybe_stop_tx(struct fm10k_ring *tx_ring, u16 size)
+{
+ netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index);
+
+ smp_mb();
+
+ /* We need to check again in a case another CPU has just
+ * made room available. */
+ if (likely(fm10k_desc_unused(tx_ring) < size))
+ return -EBUSY;
+
+ /* A reprieve! - use start_queue because it doesn't call schedule */
+ netif_start_subqueue(tx_ring->netdev, tx_ring->queue_index);
+ ++tx_ring->tx_stats.restart_queue;
+ return 0;
+}
+
+static inline int fm10k_maybe_stop_tx(struct fm10k_ring *tx_ring, u16 size)
+{
+ if (likely(fm10k_desc_unused(tx_ring) >= size))
+ return 0;
+ return __fm10k_maybe_stop_tx(tx_ring, size);
+}
+
static void fm10k_tx_map(struct fm10k_ring *tx_ring,
struct fm10k_tx_buffer *first)
{
@@ -1023,13 +1046,18 @@ static void fm10k_tx_map(struct fm10k_ring *tx_ring,
tx_ring->next_to_use = i;
+ /* Make sure there is space in the ring for the next send. */
+ fm10k_maybe_stop_tx(tx_ring, DESC_NEEDED);
+
/* notify HW of packet */
- writel(i, tx_ring->tail);
+ if (netif_xmit_stopped(txring_txq(tx_ring)) || !skb->xmit_more) {
+ writel(i, tx_ring->tail);
- /* we need this if more than one processor can write to our tail
- * at a time, it synchronizes IO on IA64/Altix systems
- */
- mmiowb();
+ /* we need this if more than one processor can write to our tail
+ * at a time, it synchronizes IO on IA64/Altix systems
+ */
+ mmiowb();
+ }
return;
dma_error:
@@ -1049,30 +1077,6 @@ dma_error:
tx_ring->next_to_use = i;
}
-static int __fm10k_maybe_stop_tx(struct fm10k_ring *tx_ring, u16 size)
-{
- netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index);
-
- smp_mb();
-
- /* We need to check again in a case another CPU has just
- * made room available. */
- if (likely(fm10k_desc_unused(tx_ring) < size))
- return -EBUSY;
-
- /* A reprieve! - use start_queue because it doesn't call schedule */
- netif_start_subqueue(tx_ring->netdev, tx_ring->queue_index);
- ++tx_ring->tx_stats.restart_queue;
- return 0;
-}
-
-static inline int fm10k_maybe_stop_tx(struct fm10k_ring *tx_ring, u16 size)
-{
- if (likely(fm10k_desc_unused(tx_ring) >= size))
- return 0;
- return __fm10k_maybe_stop_tx(tx_ring, size);
-}
-
netdev_tx_t fm10k_xmit_frame_ring(struct sk_buff *skb,
struct fm10k_ring *tx_ring)
{
@@ -1117,8 +1121,6 @@ netdev_tx_t fm10k_xmit_frame_ring(struct sk_buff *skb,
fm10k_tx_map(tx_ring, first);
- fm10k_maybe_stop_tx(tx_ring, DESC_NEEDED);
-
return NETDEV_TX_OK;
out_drop:
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
index bf44a8fe711f..8811364b91cb 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
@@ -20,9 +20,9 @@
#include "fm10k.h"
#include <linux/vmalloc.h>
-#if IS_ENABLED(CONFIG_VXLAN)
+#if IS_ENABLED(CONFIG_FM10K_VXLAN)
#include <net/vxlan.h>
-#endif /* CONFIG_VXLAN */
+#endif /* CONFIG_FM10K_VXLAN */
/**
* fm10k_setup_tx_resources - allocate Tx resources (Descriptors)
@@ -556,7 +556,7 @@ int fm10k_open(struct net_device *netdev)
if (err)
goto err_set_queues;
-#if IS_ENABLED(CONFIG_VXLAN)
+#if IS_ENABLED(CONFIG_FM10K_VXLAN)
/* update VXLAN port configuration */
vxlan_get_rx_port(netdev);
@@ -785,14 +785,14 @@ static int fm10k_update_vid(struct net_device *netdev, u16 vid, bool set)
if (!(netdev->flags & IFF_PROMISC)) {
err = hw->mac.ops.update_vlan(hw, vid, 0, set);
if (err)
- return err;
+ goto err_out;
}
/* update our base MAC address */
err = hw->mac.ops.update_uc_addr(hw, interface->glort, hw->mac.addr,
vid, set, 0);
if (err)
- return err;
+ goto err_out;
/* set vid prior to syncing/unsyncing the VLAN */
interface->vid = vid + (set ? VLAN_N_VID : 0);
@@ -801,9 +801,10 @@ static int fm10k_update_vid(struct net_device *netdev, u16 vid, bool set)
__dev_uc_unsync(netdev, fm10k_uc_vlan_unsync);
__dev_mc_unsync(netdev, fm10k_mc_vlan_unsync);
+err_out:
fm10k_mbx_unlock(interface);
- return 0;
+ return err;
}
static int fm10k_vlan_rx_add_vid(struct net_device *netdev,
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
index e02036c427b9..a0cb74ab3dc6 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
@@ -1489,6 +1489,7 @@ void fm10k_up(struct fm10k_intfc *interface)
netif_tx_start_all_queues(interface->netdev);
/* kick off the service timer */
+ hw->mac.get_host_state = 1;
mod_timer(&interface->service_timer, jiffies);
}
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index ae59c0b108c5..a21b14495ebd 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -6545,11 +6545,10 @@ static bool igb_can_reuse_rx_page(struct igb_rx_buffer *rx_buffer,
/* flip page offset to other buffer */
rx_buffer->page_offset ^= IGB_RX_BUFSZ;
- /* since we are the only owner of the page and we need to
- * increment it, just set the value to 2 in order to avoid
- * an unnecessary locked operation
+ /* Even if we own the page, we are not allowed to use atomic_set()
+ * This would break get_page_unless_zero() users.
*/
- atomic_set(&page->_count, 2);
+ atomic_inc(&page->_count);
#else
/* move offset up to the next cache line */
rx_buffer->page_offset += truesize;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index d677b5a23b58..fec5212d4337 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -1865,12 +1865,10 @@ static bool ixgbe_add_rx_frag(struct ixgbe_ring *rx_ring,
/* flip page offset to other buffer */
rx_buffer->page_offset ^= truesize;
- /*
- * since we are the only owner of the page and we need to
- * increment it, just set the value to 2 in order to avoid
- * an unecessary locked operation
+ /* Even if we own the page, we are not allowed to use atomic_set()
+ * This would break get_page_unless_zero() users.
*/
- atomic_set(&page->_count, 2);
+ atomic_inc(&page->_count);
#else
/* move offset up to the next cache line */
rx_buffer->page_offset += truesize;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
index 706fc69aa0c5..97c85b859536 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
@@ -1261,6 +1261,9 @@ int ixgbe_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting)
struct ixgbe_hw *hw = &adapter->hw;
u32 regval;
+ if (vf >= adapter->num_vfs)
+ return -EINVAL;
+
adapter->vfinfo[vf].spoofchk_enabled = setting;
regval = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg));
diff --git a/drivers/net/ethernet/marvell/Kconfig b/drivers/net/ethernet/marvell/Kconfig
index b3b72ad92d4a..d323a695dfbc 100644
--- a/drivers/net/ethernet/marvell/Kconfig
+++ b/drivers/net/ethernet/marvell/Kconfig
@@ -64,7 +64,8 @@ config MVPP2
config PXA168_ETH
tristate "Marvell pxa168 ethernet support"
- depends on (CPU_PXA168 || ARCH_BERLIN || COMPILE_TEST) && HAS_IOMEM
+ depends on HAS_IOMEM && HAS_DMA
+ depends on CPU_PXA168 || ARCH_BERLIN || COMPILE_TEST
select PHYLIB
---help---
This driver supports the pxa168 Ethernet ports.
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
index a33048ee9621..01660c595f5c 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -76,10 +76,10 @@ static int mlx4_alloc_pages(struct mlx4_en_priv *priv,
page_alloc->dma = dma;
page_alloc->page_offset = frag_info->frag_align;
/* Not doing get_page() for each frag is a big win
- * on asymetric workloads.
+ * on asymetric workloads. Note we can not use atomic_set().
*/
- atomic_set(&page->_count,
- page_alloc->page_size / frag_info->frag_stride);
+ atomic_add(page_alloc->page_size / frag_info->frag_stride - 1,
+ &page->_count);
return 0;
}
diff --git a/drivers/net/ethernet/micrel/ks8842.c b/drivers/net/ethernet/micrel/ks8842.c
index 822616e3c375..0c33b92a5a81 100644
--- a/drivers/net/ethernet/micrel/ks8842.c
+++ b/drivers/net/ethernet/micrel/ks8842.c
@@ -875,13 +875,11 @@ static void ks8842_stop_dma(struct ks8842_adapter *adapter)
tx_ctl->adesc = NULL;
if (tx_ctl->chan)
- tx_ctl->chan->device->device_control(tx_ctl->chan,
- DMA_TERMINATE_ALL, 0);
+ dmaengine_terminate_all(tx_ctl->chan);
rx_ctl->adesc = NULL;
if (rx_ctl->chan)
- rx_ctl->chan->device->device_control(rx_ctl->chan,
- DMA_TERMINATE_ALL, 0);
+ dmaengine_terminate_all(rx_ctl->chan);
if (sg_dma_address(&rx_ctl->sg))
dma_unmap_single(adapter->dev, sg_dma_address(&rx_ctl->sg),
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
index ffbae293cef5..6e6f18fc5d76 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
@@ -11,7 +11,7 @@ static const struct qlcnic_mailbox_metadata qlcnic_mbx_tbl[] = {
{QLCNIC_CMD_CREATE_RX_CTX, 4, 1},
{QLCNIC_CMD_DESTROY_RX_CTX, 2, 1},
{QLCNIC_CMD_CREATE_TX_CTX, 4, 1},
- {QLCNIC_CMD_DESTROY_TX_CTX, 2, 1},
+ {QLCNIC_CMD_DESTROY_TX_CTX, 3, 1},
{QLCNIC_CMD_INTRPT_TEST, 4, 1},
{QLCNIC_CMD_SET_MTU, 4, 1},
{QLCNIC_CMD_READ_PHY, 4, 2},
@@ -32,7 +32,7 @@ static const struct qlcnic_mailbox_metadata qlcnic_mbx_tbl[] = {
{QLCNIC_CMD_CONFIGURE_ESWITCH, 4, 1},
{QLCNIC_CMD_GET_MAC_STATS, 4, 1},
{QLCNIC_CMD_GET_ESWITCH_PORT_CONFIG, 4, 3},
- {QLCNIC_CMD_GET_ESWITCH_STATS, 5, 1},
+ {QLCNIC_CMD_GET_ESWITCH_STATS, 4, 1},
{QLCNIC_CMD_CONFIG_PORT, 4, 1},
{QLCNIC_CMD_TEMP_SIZE, 4, 4},
{QLCNIC_CMD_GET_TEMP_HDR, 4, 1},
@@ -129,7 +129,7 @@ int qlcnic_82xx_issue_cmd(struct qlcnic_adapter *adapter,
}
QLCWR32(adapter, QLCNIC_SIGN_CRB_OFFSET, signature);
- for (i = 1; i < QLCNIC_CDRP_MAX_ARGS; i++)
+ for (i = 1; i < cmd->req.num; i++)
QLCWR32(adapter, QLCNIC_CDRP_ARG(i), cmd->req.arg[i]);
QLCWR32(adapter, QLCNIC_CDRP_CRB_OFFSET,
QLCNIC_CDRP_FORM_CMD(cmd->req.arg[0]));
diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h
index 60f85149fc4c..f77cce034ad4 100644
--- a/drivers/net/ethernet/sfc/nic.h
+++ b/drivers/net/ethernet/sfc/nic.h
@@ -71,9 +71,17 @@ efx_tx_desc(struct efx_tx_queue *tx_queue, unsigned int index)
return ((efx_qword_t *) (tx_queue->txd.buf.addr)) + index;
}
-/* Report whether the NIC considers this TX queue empty, given the
- * write_count used for the last doorbell push. May return false
- * negative.
+/* Get partner of a TX queue, seen as part of the same net core queue */
+static struct efx_tx_queue *efx_tx_queue_partner(struct efx_tx_queue *tx_queue)
+{
+ if (tx_queue->queue & EFX_TXQ_TYPE_OFFLOAD)
+ return tx_queue - EFX_TXQ_TYPE_OFFLOAD;
+ else
+ return tx_queue + EFX_TXQ_TYPE_OFFLOAD;
+}
+
+/* Report whether this TX queue would be empty for the given write_count.
+ * May return false negative.
*/
static inline bool __efx_nic_tx_is_empty(struct efx_tx_queue *tx_queue,
unsigned int write_count)
@@ -86,9 +94,18 @@ static inline bool __efx_nic_tx_is_empty(struct efx_tx_queue *tx_queue,
return ((empty_read_count ^ write_count) & ~EFX_EMPTY_COUNT_VALID) == 0;
}
-static inline bool efx_nic_tx_is_empty(struct efx_tx_queue *tx_queue)
+/* Decide whether we can use TX PIO, ie. write packet data directly into
+ * a buffer on the device. This can reduce latency at the expense of
+ * throughput, so we only do this if both hardware and software TX rings
+ * are empty. This also ensures that only one packet at a time can be
+ * using the PIO buffer.
+ */
+static inline bool efx_nic_may_tx_pio(struct efx_tx_queue *tx_queue)
{
- return __efx_nic_tx_is_empty(tx_queue, tx_queue->write_count);
+ struct efx_tx_queue *partner = efx_tx_queue_partner(tx_queue);
+ return tx_queue->piobuf &&
+ __efx_nic_tx_is_empty(tx_queue, tx_queue->insert_count) &&
+ __efx_nic_tx_is_empty(partner, partner->insert_count);
}
/* Decide whether to push a TX descriptor to the NIC vs merely writing
@@ -96,6 +113,8 @@ static inline bool efx_nic_tx_is_empty(struct efx_tx_queue *tx_queue)
* descriptor to an empty queue, but is otherwise pointless. Further,
* Falcon and Siena have hardware bugs (SF bug 33851) that may be
* triggered if we don't check this.
+ * We use the write_count used for the last doorbell push, to get the
+ * NIC's view of the tx queue.
*/
static inline bool efx_nic_may_push_tx_desc(struct efx_tx_queue *tx_queue,
unsigned int write_count)
diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c
index 320609842211..ee84a90e371c 100644
--- a/drivers/net/ethernet/sfc/tx.c
+++ b/drivers/net/ethernet/sfc/tx.c
@@ -132,15 +132,6 @@ unsigned int efx_tx_max_skb_descs(struct efx_nic *efx)
return max_descs;
}
-/* Get partner of a TX queue, seen as part of the same net core queue */
-static struct efx_tx_queue *efx_tx_queue_partner(struct efx_tx_queue *tx_queue)
-{
- if (tx_queue->queue & EFX_TXQ_TYPE_OFFLOAD)
- return tx_queue - EFX_TXQ_TYPE_OFFLOAD;
- else
- return tx_queue + EFX_TXQ_TYPE_OFFLOAD;
-}
-
static void efx_tx_maybe_stop_queue(struct efx_tx_queue *txq1)
{
/* We need to consider both queues that the net core sees as one */
@@ -344,6 +335,7 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
struct efx_nic *efx = tx_queue->efx;
struct device *dma_dev = &efx->pci_dev->dev;
struct efx_tx_buffer *buffer;
+ unsigned int old_insert_count = tx_queue->insert_count;
skb_frag_t *fragment;
unsigned int len, unmap_len = 0;
dma_addr_t dma_addr, unmap_addr = 0;
@@ -351,7 +343,7 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
unsigned short dma_flags;
int i = 0;
- EFX_BUG_ON_PARANOID(tx_queue->write_count != tx_queue->insert_count);
+ EFX_BUG_ON_PARANOID(tx_queue->write_count > tx_queue->insert_count);
if (skb_shinfo(skb)->gso_size)
return efx_enqueue_skb_tso(tx_queue, skb);
@@ -369,9 +361,8 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
/* Consider using PIO for short packets */
#ifdef EFX_USE_PIO
- if (skb->len <= efx_piobuf_size && tx_queue->piobuf &&
- efx_nic_tx_is_empty(tx_queue) &&
- efx_nic_tx_is_empty(efx_tx_queue_partner(tx_queue))) {
+ if (skb->len <= efx_piobuf_size && !skb->xmit_more &&
+ efx_nic_may_tx_pio(tx_queue)) {
buffer = efx_enqueue_skb_pio(tx_queue, skb);
dma_flags = EFX_TX_BUF_OPTION;
goto finish_packet;
@@ -439,13 +430,14 @@ finish_packet:
netdev_tx_sent_queue(tx_queue->core_txq, skb->len);
+ efx_tx_maybe_stop_queue(tx_queue);
+
/* Pass off to hardware */
- efx_nic_push_buffers(tx_queue);
+ if (!skb->xmit_more || netif_xmit_stopped(tx_queue->core_txq))
+ efx_nic_push_buffers(tx_queue);
tx_queue->tx_packets++;
- efx_tx_maybe_stop_queue(tx_queue);
-
return NETDEV_TX_OK;
dma_err:
@@ -458,7 +450,7 @@ finish_packet:
dev_kfree_skb_any(skb);
/* Work backwards until we hit the original insert pointer value */
- while (tx_queue->insert_count != tx_queue->write_count) {
+ while (tx_queue->insert_count != old_insert_count) {
unsigned int pkts_compl = 0, bytes_compl = 0;
--tx_queue->insert_count;
buffer = __efx_tx_queue_get_insert_buffer(tx_queue);
@@ -989,12 +981,13 @@ static int efx_tso_put_header(struct efx_tx_queue *tx_queue,
/* Remove buffers put into a tx_queue. None of the buffers must have
* an skb attached.
*/
-static void efx_enqueue_unwind(struct efx_tx_queue *tx_queue)
+static void efx_enqueue_unwind(struct efx_tx_queue *tx_queue,
+ unsigned int insert_count)
{
struct efx_tx_buffer *buffer;
/* Work backwards until we hit the original insert pointer value */
- while (tx_queue->insert_count != tx_queue->write_count) {
+ while (tx_queue->insert_count != insert_count) {
--tx_queue->insert_count;
buffer = __efx_tx_queue_get_insert_buffer(tx_queue);
efx_dequeue_buffer(tx_queue, buffer, NULL, NULL);
@@ -1258,13 +1251,14 @@ static int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue,
struct sk_buff *skb)
{
struct efx_nic *efx = tx_queue->efx;
+ unsigned int old_insert_count = tx_queue->insert_count;
int frag_i, rc;
struct tso_state state;
/* Find the packet protocol and sanity-check it */
state.protocol = efx_tso_check_protocol(skb);
- EFX_BUG_ON_PARANOID(tx_queue->write_count != tx_queue->insert_count);
+ EFX_BUG_ON_PARANOID(tx_queue->write_count > tx_queue->insert_count);
rc = tso_start(&state, efx, skb);
if (rc)
@@ -1308,11 +1302,12 @@ static int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue,
netdev_tx_sent_queue(tx_queue->core_txq, skb->len);
- /* Pass off to hardware */
- efx_nic_push_buffers(tx_queue);
-
efx_tx_maybe_stop_queue(tx_queue);
+ /* Pass off to hardware */
+ if (!skb->xmit_more || netif_xmit_stopped(tx_queue->core_txq))
+ efx_nic_push_buffers(tx_queue);
+
tx_queue->tso_bursts++;
return NETDEV_TX_OK;
@@ -1336,6 +1331,6 @@ static int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue,
dma_unmap_single(&efx->pci_dev->dev, state.header_dma_addr,
state.header_unmap_len, DMA_TO_DEVICE);
- efx_enqueue_unwind(tx_queue);
+ efx_enqueue_unwind(tx_queue, old_insert_count);
return NETDEV_TX_OK;
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
index 552bbc17863c..ccfe7e510418 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2003-2014 STMicroelectronics (R&D) Limited
* Author: Srinivas Kandagatla <srinivas.kandagatla@st.com>
- *
+ * Contributors: Giuseppe Cavallaro <peppe.cavallaro@st.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -22,45 +22,22 @@
#include <linux/of.h>
#include <linux/of_net.h>
+#define DWMAC_125MHZ 125000000
+#define DWMAC_50MHZ 50000000
+#define DWMAC_25MHZ 25000000
+#define DWMAC_2_5MHZ 2500000
+
+#define IS_PHY_IF_MODE_RGMII(iface) (iface == PHY_INTERFACE_MODE_RGMII || \
+ iface == PHY_INTERFACE_MODE_RGMII_ID || \
+ iface == PHY_INTERFACE_MODE_RGMII_RXID || \
+ iface == PHY_INTERFACE_MODE_RGMII_TXID)
+
+#define IS_PHY_IF_MODE_GBIT(iface) (IS_PHY_IF_MODE_RGMII(iface) || \
+ iface == PHY_INTERFACE_MODE_GMII)
+
+/* STiH4xx register definitions (STiH415/STiH416/STiH407/STiH410 families) */
+
/**
- * STi GMAC glue logic.
- * --------------------
- *
- * _
- * | \
- * --------|0 \ ETH_SEL_INTERNAL_NOTEXT_PHYCLK
- * phyclk | |___________________________________________
- * | | | (phyclk-in)
- * --------|1 / |
- * int-clk |_ / |
- * | _
- * | | \
- * |_______|1 \ ETH_SEL_TX_RETIME_CLK
- * | |___________________________
- * | | (tx-retime-clk)
- * _______|0 /
- * | |_ /
- * _ |
- * | \ |
- * --------|0 \ |
- * clk_125 | |__|
- * | | ETH_SEL_TXCLK_NOT_CLK125
- * --------|1 /
- * txclk |_ /
- *
- *
- * ETH_SEL_INTERNAL_NOTEXT_PHYCLK is valid only for RMII where PHY can
- * generate 50MHz clock or MAC can generate it.
- * This bit is configured by "st,ext-phyclk" property.
- *
- * ETH_SEL_TXCLK_NOT_CLK125 is only valid for gigabit modes, where the 125Mhz
- * clock either comes from clk-125 pin or txclk pin. This configuration is
- * totally driven by the board wiring. This bit is configured by
- * "st,tx-retime-src" property.
- *
- * TXCLK configuration is different for different phy interface modes
- * and changes according to link speed in modes like RGMII.
- *
* Below table summarizes the clock requirement and clock sources for
* supported phy interface modes with link speeds.
* ________________________________________________
@@ -74,44 +51,58 @@
* ------------------------------------------------
*| RGMII | 125Mhz | 25Mhz |
*| | clk-125/txclk | clkgen |
+ *| | clkgen | |
* ------------------------------------------------
*| RMII | n/a | 25Mhz |
*| | |clkgen/phyclk-in |
* ------------------------------------------------
*
- * TX lines are always retimed with a clk, which can vary depending
- * on the board configuration. Below is the table of these bits
- * in eth configuration register depending on source of retime clk.
- *
- *---------------------------------------------------------------
- * src | tx_rt_clk | int_not_ext_phyclk | txclk_n_clk125|
- *---------------------------------------------------------------
- * txclk | 0 | n/a | 1 |
- *---------------------------------------------------------------
- * ck_125| 0 | n/a | 0 |
- *---------------------------------------------------------------
- * phyclk| 1 | 0 | n/a |
- *---------------------------------------------------------------
- * clkgen| 1 | 1 | n/a |
- *---------------------------------------------------------------
+ * Register Configuration
+ *-------------------------------
+ * src |BIT(8)| BIT(7)| BIT(6)|
+ *-------------------------------
+ * txclk | 0 | n/a | 1 |
+ *-------------------------------
+ * ck_125| 0 | n/a | 0 |
+ *-------------------------------
+ * phyclk| 1 | 0 | n/a |
+ *-------------------------------
+ * clkgen| 1 | 1 | n/a |
+ *-------------------------------
*/
- /* Register definition */
+#define STIH4XX_RETIME_SRC_MASK GENMASK(8, 6)
+#define STIH4XX_ETH_SEL_TX_RETIME_CLK BIT(8)
+#define STIH4XX_ETH_SEL_INTERNAL_NOTEXT_PHYCLK BIT(7)
+#define STIH4XX_ETH_SEL_TXCLK_NOT_CLK125 BIT(6)
+
+/* STiD127 register definitions */
- /* 3 bits [8:6]
- * [6:6] ETH_SEL_TXCLK_NOT_CLK125
- * [7:7] ETH_SEL_INTERNAL_NOTEXT_PHYCLK
- * [8:8] ETH_SEL_TX_RETIME_CLK
- *
- */
+/**
+ *-----------------------
+ * src |BIT(6)| BIT(7)|
+ *-----------------------
+ * MII | 1 | n/a |
+ *-----------------------
+ * RMII | n/a | 1 |
+ * clkgen| | |
+ *-----------------------
+ * RMII | n/a | 0 |
+ * phyclk| | |
+ *-----------------------
+ * RGMII | 1 | n/a |
+ * clkgen| | |
+ *-----------------------
+ */
-#define TX_RETIME_SRC_MASK GENMASK(8, 6)
-#define ETH_SEL_TX_RETIME_CLK BIT(8)
-#define ETH_SEL_INTERNAL_NOTEXT_PHYCLK BIT(7)
-#define ETH_SEL_TXCLK_NOT_CLK125 BIT(6)
+#define STID127_RETIME_SRC_MASK GENMASK(7, 6)
+#define STID127_ETH_SEL_INTERNAL_NOTEXT_PHYCLK BIT(7)
+#define STID127_ETH_SEL_INTERNAL_NOTEXT_TXCLK BIT(6)
-#define ENMII_MASK GENMASK(5, 5)
-#define ENMII BIT(5)
+#define ENMII_MASK GENMASK(5, 5)
+#define ENMII BIT(5)
+#define EN_MASK GENMASK(1, 1)
+#define EN BIT(1)
/**
* 3 bits [4:2]
@@ -120,29 +111,23 @@
* 010-SGMII
* 100-RMII
*/
-#define MII_PHY_SEL_MASK GENMASK(4, 2)
-#define ETH_PHY_SEL_RMII BIT(4)
-#define ETH_PHY_SEL_SGMII BIT(3)
-#define ETH_PHY_SEL_RGMII BIT(2)
-#define ETH_PHY_SEL_GMII 0x0
-#define ETH_PHY_SEL_MII 0x0
-
-#define IS_PHY_IF_MODE_RGMII(iface) (iface == PHY_INTERFACE_MODE_RGMII || \
- iface == PHY_INTERFACE_MODE_RGMII_ID || \
- iface == PHY_INTERFACE_MODE_RGMII_RXID || \
- iface == PHY_INTERFACE_MODE_RGMII_TXID)
-
-#define IS_PHY_IF_MODE_GBIT(iface) (IS_PHY_IF_MODE_RGMII(iface) || \
- iface == PHY_INTERFACE_MODE_GMII)
+#define MII_PHY_SEL_MASK GENMASK(4, 2)
+#define ETH_PHY_SEL_RMII BIT(4)
+#define ETH_PHY_SEL_SGMII BIT(3)
+#define ETH_PHY_SEL_RGMII BIT(2)
+#define ETH_PHY_SEL_GMII 0x0
+#define ETH_PHY_SEL_MII 0x0
struct sti_dwmac {
- int interface;
- bool ext_phyclk;
- bool is_tx_retime_src_clk_125;
- struct clk *clk;
- int reg;
+ int interface; /* MII interface */
+ bool ext_phyclk; /* Clock from external PHY */
+ u32 tx_retime_src; /* TXCLK Retiming*/
+ struct clk *clk; /* PHY clock */
+ int ctrl_reg; /* GMAC glue-logic control register */
+ int clk_sel_reg; /* GMAC ext clk selection register */
struct device *dev;
struct regmap *regmap;
+ u32 speed;
};
static u32 phy_intf_sels[] = {
@@ -162,74 +147,133 @@ enum {
TX_RETIME_SRC_CLKGEN,
};
-static const char *const tx_retime_srcs[] = {
- [TX_RETIME_SRC_NA] = "",
- [TX_RETIME_SRC_TXCLK] = "txclk",
- [TX_RETIME_SRC_CLK_125] = "clk_125",
- [TX_RETIME_SRC_PHYCLK] = "phyclk",
- [TX_RETIME_SRC_CLKGEN] = "clkgen",
-};
-
-static u32 tx_retime_val[] = {
- [TX_RETIME_SRC_TXCLK] = ETH_SEL_TXCLK_NOT_CLK125,
+static u32 stih4xx_tx_retime_val[] = {
+ [TX_RETIME_SRC_TXCLK] = STIH4XX_ETH_SEL_TXCLK_NOT_CLK125,
[TX_RETIME_SRC_CLK_125] = 0x0,
- [TX_RETIME_SRC_PHYCLK] = ETH_SEL_TX_RETIME_CLK,
- [TX_RETIME_SRC_CLKGEN] = ETH_SEL_TX_RETIME_CLK |
- ETH_SEL_INTERNAL_NOTEXT_PHYCLK,
+ [TX_RETIME_SRC_PHYCLK] = STIH4XX_ETH_SEL_TX_RETIME_CLK,
+ [TX_RETIME_SRC_CLKGEN] = STIH4XX_ETH_SEL_TX_RETIME_CLK
+ | STIH4XX_ETH_SEL_INTERNAL_NOTEXT_PHYCLK,
};
-static void setup_retime_src(struct sti_dwmac *dwmac, u32 spd)
+static void stih4xx_fix_retime_src(void *priv, u32 spd)
{
- u32 src = 0, freq = 0;
-
- if (spd == SPEED_100) {
- if (dwmac->interface == PHY_INTERFACE_MODE_MII ||
- dwmac->interface == PHY_INTERFACE_MODE_GMII) {
- src = TX_RETIME_SRC_TXCLK;
- } else if (dwmac->interface == PHY_INTERFACE_MODE_RMII) {
- if (dwmac->ext_phyclk) {
- src = TX_RETIME_SRC_PHYCLK;
- } else {
- src = TX_RETIME_SRC_CLKGEN;
- freq = 50000000;
- }
-
- } else if (IS_PHY_IF_MODE_RGMII(dwmac->interface)) {
+ struct sti_dwmac *dwmac = priv;
+ u32 src = dwmac->tx_retime_src;
+ u32 reg = dwmac->ctrl_reg;
+ u32 freq = 0;
+
+ if (dwmac->interface == PHY_INTERFACE_MODE_MII) {
+ src = TX_RETIME_SRC_TXCLK;
+ } else if (dwmac->interface == PHY_INTERFACE_MODE_RMII) {
+ if (dwmac->ext_phyclk) {
+ src = TX_RETIME_SRC_PHYCLK;
+ } else {
src = TX_RETIME_SRC_CLKGEN;
- freq = 25000000;
+ freq = DWMAC_50MHZ;
}
+ } else if (IS_PHY_IF_MODE_RGMII(dwmac->interface)) {
+ /* On GiGa clk source can be either ext or from clkgen */
+ if (spd == SPEED_1000) {
+ freq = DWMAC_125MHZ;
+ } else {
+ /* Switch to clkgen for these speeds */
+ src = TX_RETIME_SRC_CLKGEN;
+ if (spd == SPEED_100)
+ freq = DWMAC_25MHZ;
+ else if (spd == SPEED_10)
+ freq = DWMAC_2_5MHZ;
+ }
+ }
- if (src == TX_RETIME_SRC_CLKGEN && dwmac->clk)
- clk_set_rate(dwmac->clk, freq);
+ if (src == TX_RETIME_SRC_CLKGEN && dwmac->clk && freq)
+ clk_set_rate(dwmac->clk, freq);
- } else if (spd == SPEED_1000) {
- if (dwmac->is_tx_retime_src_clk_125)
- src = TX_RETIME_SRC_CLK_125;
- else
- src = TX_RETIME_SRC_TXCLK;
+ regmap_update_bits(dwmac->regmap, reg, STIH4XX_RETIME_SRC_MASK,
+ stih4xx_tx_retime_val[src]);
+}
+
+static void stid127_fix_retime_src(void *priv, u32 spd)
+{
+ struct sti_dwmac *dwmac = priv;
+ u32 reg = dwmac->ctrl_reg;
+ u32 freq = 0;
+ u32 val = 0;
+
+ if (dwmac->interface == PHY_INTERFACE_MODE_MII) {
+ val = STID127_ETH_SEL_INTERNAL_NOTEXT_TXCLK;
+ } else if (dwmac->interface == PHY_INTERFACE_MODE_RMII) {
+ if (!dwmac->ext_phyclk) {
+ val = STID127_ETH_SEL_INTERNAL_NOTEXT_PHYCLK;
+ freq = DWMAC_50MHZ;
+ }
+ } else if (IS_PHY_IF_MODE_RGMII(dwmac->interface)) {
+ val = STID127_ETH_SEL_INTERNAL_NOTEXT_TXCLK;
+ if (spd == SPEED_1000)
+ freq = DWMAC_125MHZ;
+ else if (spd == SPEED_100)
+ freq = DWMAC_25MHZ;
+ else if (spd == SPEED_10)
+ freq = DWMAC_2_5MHZ;
}
- regmap_update_bits(dwmac->regmap, dwmac->reg,
- TX_RETIME_SRC_MASK, tx_retime_val[src]);
+ if (dwmac->clk && freq)
+ clk_set_rate(dwmac->clk, freq);
+
+ regmap_update_bits(dwmac->regmap, reg, STID127_RETIME_SRC_MASK, val);
}
-static void sti_dwmac_exit(struct platform_device *pdev, void *priv)
+static void sti_dwmac_ctrl_init(struct sti_dwmac *dwmac)
{
- struct sti_dwmac *dwmac = priv;
+ struct regmap *regmap = dwmac->regmap;
+ int iface = dwmac->interface;
+ struct device *dev = dwmac->dev;
+ struct device_node *np = dev->of_node;
+ u32 reg = dwmac->ctrl_reg;
+ u32 val;
if (dwmac->clk)
- clk_disable_unprepare(dwmac->clk);
+ clk_prepare_enable(dwmac->clk);
+
+ if (of_property_read_bool(np, "st,gmac_en"))
+ regmap_update_bits(regmap, reg, EN_MASK, EN);
+
+ regmap_update_bits(regmap, reg, MII_PHY_SEL_MASK, phy_intf_sels[iface]);
+
+ val = (iface == PHY_INTERFACE_MODE_REVMII) ? 0 : ENMII;
+ regmap_update_bits(regmap, reg, ENMII_MASK, val);
+}
+
+static int stix4xx_init(struct platform_device *pdev, void *priv)
+{
+ struct sti_dwmac *dwmac = priv;
+ u32 spd = dwmac->speed;
+
+ sti_dwmac_ctrl_init(dwmac);
+
+ stih4xx_fix_retime_src(priv, spd);
+
+ return 0;
}
-static void sti_fix_mac_speed(void *priv, unsigned int spd)
+static int stid127_init(struct platform_device *pdev, void *priv)
{
struct sti_dwmac *dwmac = priv;
+ u32 spd = dwmac->speed;
- setup_retime_src(dwmac, spd);
+ sti_dwmac_ctrl_init(dwmac);
- return;
+ stid127_fix_retime_src(priv, spd);
+
+ return 0;
}
+static void sti_dwmac_exit(struct platform_device *pdev, void *priv)
+{
+ struct sti_dwmac *dwmac = priv;
+
+ if (dwmac->clk)
+ clk_disable_unprepare(dwmac->clk);
+}
static int sti_dwmac_parse_data(struct sti_dwmac *dwmac,
struct platform_device *pdev)
{
@@ -245,6 +289,13 @@ static int sti_dwmac_parse_data(struct sti_dwmac *dwmac,
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sti-ethconf");
if (!res)
return -ENODATA;
+ dwmac->ctrl_reg = res->start;
+
+ /* clk selection from extra syscfg register */
+ dwmac->clk_sel_reg = -ENXIO;
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sti-clkconf");
+ if (res)
+ dwmac->clk_sel_reg = res->start;
regmap = syscon_regmap_lookup_by_phandle(np, "st,syscon");
if (IS_ERR(regmap))
@@ -253,53 +304,31 @@ static int sti_dwmac_parse_data(struct sti_dwmac *dwmac,
dwmac->dev = dev;
dwmac->interface = of_get_phy_mode(np);
dwmac->regmap = regmap;
- dwmac->reg = res->start;
dwmac->ext_phyclk = of_property_read_bool(np, "st,ext-phyclk");
- dwmac->is_tx_retime_src_clk_125 = false;
+ dwmac->tx_retime_src = TX_RETIME_SRC_NA;
+ dwmac->speed = SPEED_100;
if (IS_PHY_IF_MODE_GBIT(dwmac->interface)) {
const char *rs;
+ dwmac->tx_retime_src = TX_RETIME_SRC_CLKGEN;
err = of_property_read_string(np, "st,tx-retime-src", &rs);
- if (err < 0) {
- dev_err(dev, "st,tx-retime-src not specified\n");
- return err;
- }
+ if (err < 0)
+ dev_warn(dev, "Use internal clock source\n");
if (!strcasecmp(rs, "clk_125"))
- dwmac->is_tx_retime_src_clk_125 = true;
+ dwmac->tx_retime_src = TX_RETIME_SRC_CLK_125;
+ else if (!strcasecmp(rs, "txclk"))
+ dwmac->tx_retime_src = TX_RETIME_SRC_TXCLK;
+
+ dwmac->speed = SPEED_1000;
}
dwmac->clk = devm_clk_get(dev, "sti-ethclk");
-
- if (IS_ERR(dwmac->clk))
+ if (IS_ERR(dwmac->clk)) {
+ dev_warn(dev, "No phy clock provided...\n");
dwmac->clk = NULL;
-
- return 0;
-}
-
-static int sti_dwmac_init(struct platform_device *pdev, void *priv)
-{
- struct sti_dwmac *dwmac = priv;
- struct regmap *regmap = dwmac->regmap;
- int iface = dwmac->interface;
- u32 reg = dwmac->reg;
- u32 val, spd;
-
- if (dwmac->clk)
- clk_prepare_enable(dwmac->clk);
-
- regmap_update_bits(regmap, reg, MII_PHY_SEL_MASK, phy_intf_sels[iface]);
-
- val = (iface == PHY_INTERFACE_MODE_REVMII) ? 0 : ENMII;
- regmap_update_bits(regmap, reg, ENMII_MASK, val);
-
- if (IS_PHY_IF_MODE_GBIT(iface))
- spd = SPEED_1000;
- else
- spd = SPEED_100;
-
- setup_retime_src(dwmac, spd);
+ }
return 0;
}
@@ -322,9 +351,16 @@ static void *sti_dwmac_setup(struct platform_device *pdev)
return dwmac;
}
-const struct stmmac_of_data sti_gmac_data = {
- .fix_mac_speed = sti_fix_mac_speed,
+const struct stmmac_of_data stih4xx_dwmac_data = {
+ .fix_mac_speed = stih4xx_fix_retime_src,
+ .setup = sti_dwmac_setup,
+ .init = stix4xx_init,
+ .exit = sti_dwmac_exit,
+};
+
+const struct stmmac_of_data stid127_dwmac_data = {
+ .fix_mac_speed = stid127_fix_retime_src,
.setup = sti_dwmac_setup,
- .init = sti_dwmac_init,
+ .init = stid127_init,
.exit = sti_dwmac_exit,
};
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
index 5efe60ea6526..0adcf73cf722 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
@@ -134,7 +134,7 @@ static void dwmac1000_set_filter(struct mac_device_info *hw,
void __iomem *ioaddr = (void __iomem *)dev->base_addr;
unsigned int value = 0;
unsigned int perfect_addr_number = hw->unicast_filter_entries;
- u32 mc_filter[2];
+ u32 mc_filter[8];
int mcbitslog2 = hw->mcast_bits_log2;
pr_debug("%s: # mcasts %d, # unicast %d\n", __func__,
@@ -182,7 +182,7 @@ static void dwmac1000_set_filter(struct mac_device_info *hw,
struct netdev_hw_addr *ha;
netdev_for_each_uc_addr(ha, dev) {
- stmmac_get_mac_addr(ioaddr, ha->addr,
+ stmmac_set_mac_addr(ioaddr, ha->addr,
GMAC_ADDR_HIGH(reg),
GMAC_ADDR_LOW(reg));
reg++;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 44528896355d..c3c40650b309 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -144,7 +144,8 @@ extern const struct stmmac_of_data meson6_dwmac_data;
extern const struct stmmac_of_data sun7i_gmac_data;
#endif
#ifdef CONFIG_DWMAC_STI
-extern const struct stmmac_of_data sti_gmac_data;
+extern const struct stmmac_of_data stih4xx_dwmac_data;
+extern const struct stmmac_of_data stid127_dwmac_data;
#endif
#ifdef CONFIG_DWMAC_SOCFPGA
extern const struct stmmac_of_data socfpga_gmac_data;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 652171706258..db56fa7ce8f9 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -37,9 +37,10 @@ static const struct of_device_id stmmac_dt_ids[] = {
{ .compatible = "allwinner,sun7i-a20-gmac", .data = &sun7i_gmac_data},
#endif
#ifdef CONFIG_DWMAC_STI
- { .compatible = "st,stih415-dwmac", .data = &sti_gmac_data},
- { .compatible = "st,stih416-dwmac", .data = &sti_gmac_data},
- { .compatible = "st,stid127-dwmac", .data = &sti_gmac_data},
+ { .compatible = "st,stih415-dwmac", .data = &stih4xx_dwmac_data},
+ { .compatible = "st,stih416-dwmac", .data = &stih4xx_dwmac_data},
+ { .compatible = "st,stid127-dwmac", .data = &stid127_dwmac_data},
+ { .compatible = "st,stih407-dwmac", .data = &stih4xx_dwmac_data},
#endif
#ifdef CONFIG_DWMAC_SOCFPGA
{ .compatible = "altr,socfpga-stmmac", .data = &socfpga_gmac_data },
@@ -160,11 +161,16 @@ static int stmmac_probe_config_dt(struct platform_device *pdev,
if (of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr) == 0)
dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n");
- plat->mdio_bus_data = devm_kzalloc(&pdev->dev,
- sizeof(struct stmmac_mdio_bus_data),
- GFP_KERNEL);
+ if (plat->phy_bus_name)
+ plat->mdio_bus_data = NULL;
+ else
+ plat->mdio_bus_data =
+ devm_kzalloc(&pdev->dev,
+ sizeof(struct stmmac_mdio_bus_data),
+ GFP_KERNEL);
- plat->force_sf_dma_mode = of_property_read_bool(np, "snps,force_sf_dma_mode");
+ plat->force_sf_dma_mode =
+ of_property_read_bool(np, "snps,force_sf_dma_mode");
/* Set the maxmtu to a default of JUMBO_LEN in case the
* parameter is not present in the device tree.
diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c
index 15396720f489..3652afd3ec78 100644
--- a/drivers/net/ethernet/sun/sunvnet.c
+++ b/drivers/net/ethernet/sun/sunvnet.c
@@ -954,7 +954,7 @@ static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev)
spin_lock_irqsave(&port->vio.lock, flags);
dr = &port->vio.drings[VIO_DRIVER_TX_RING];
- if (unlikely(vnet_tx_dring_avail(dr) < 2)) {
+ if (unlikely(vnet_tx_dring_avail(dr) < 1)) {
if (!netif_queue_stopped(dev)) {
netif_stop_queue(dev);
@@ -1049,7 +1049,7 @@ ldc_start_done:
dev->stats.tx_bytes += port->tx_bufs[txi].skb->len;
dr->prod = (dr->prod + 1) & (VNET_TX_RING_SIZE - 1);
- if (unlikely(vnet_tx_dring_avail(dr) < 2)) {
+ if (unlikely(vnet_tx_dring_avail(dr) < 1)) {
netif_stop_queue(dev);
if (vnet_tx_dring_avail(dr) > VNET_TX_WAKEUP_THRESH(dr))
netif_wake_queue(dev);
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index ab167dc49ce4..952e1e4764b7 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -2392,6 +2392,15 @@ clean_ndev_ret:
return ret;
}
+static int cpsw_remove_child_device(struct device *dev, void *c)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+
+ of_device_unregister(pdev);
+
+ return 0;
+}
+
static int cpsw_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
@@ -2406,6 +2415,7 @@ static int cpsw_remove(struct platform_device *pdev)
cpdma_chan_destroy(priv->rxch);
cpdma_ctlr_destroy(priv->dma);
pm_runtime_disable(&pdev->dev);
+ device_for_each_child(&pdev->dev, NULL, cpsw_remove_child_device);
if (priv->data.dual_emac)
free_netdev(cpsw_get_slave_ndev(priv, 1));
free_netdev(ndev);
diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c
index 4a000f6dd6fc..657b65bf5cac 100644
--- a/drivers/net/ethernet/ti/davinci_cpdma.c
+++ b/drivers/net/ethernet/ti/davinci_cpdma.c
@@ -193,12 +193,9 @@ fail:
static void cpdma_desc_pool_destroy(struct cpdma_desc_pool *pool)
{
- unsigned long flags;
-
if (!pool)
return;
- spin_lock_irqsave(&pool->lock, flags);
WARN_ON(pool->used_desc);
if (pool->cpumap) {
dma_free_coherent(pool->dev, pool->mem_size, pool->cpumap,
@@ -206,7 +203,6 @@ static void cpdma_desc_pool_destroy(struct cpdma_desc_pool *pool)
} else {
iounmap(pool->iomap);
}
- spin_unlock_irqrestore(&pool->lock, flags);
}
static inline dma_addr_t desc_phys(struct cpdma_desc_pool *pool,
@@ -561,7 +557,6 @@ int cpdma_chan_destroy(struct cpdma_chan *chan)
cpdma_chan_stop(chan);
ctlr->channels[chan->chan_num] = NULL;
spin_unlock_irqrestore(&ctlr->lock, flags);
- kfree(chan);
return 0;
}
EXPORT_SYMBOL_GPL(cpdma_chan_destroy);
diff --git a/drivers/net/ethernet/tile/tilegx.c b/drivers/net/ethernet/tile/tilegx.c
index 69557a26f749..049747f558c9 100644
--- a/drivers/net/ethernet/tile/tilegx.c
+++ b/drivers/net/ethernet/tile/tilegx.c
@@ -423,7 +423,7 @@ static void tile_net_pop_all_buffers(int instance, int stack)
/* Provide linux buffers to mPIPE. */
static void tile_net_provide_needed_buffers(void)
{
- struct tile_net_info *info = &__get_cpu_var(per_cpu_info);
+ struct tile_net_info *info = this_cpu_ptr(&per_cpu_info);
int instance, kind;
for (instance = 0; instance < NR_MPIPE_MAX &&
info->mpipe[instance].has_iqueue; instance++) {
@@ -551,7 +551,7 @@ static inline bool filter_packet(struct net_device *dev, void *buf)
static void tile_net_receive_skb(struct net_device *dev, struct sk_buff *skb,
gxio_mpipe_idesc_t *idesc, unsigned long len)
{
- struct tile_net_info *info = &__get_cpu_var(per_cpu_info);
+ struct tile_net_info *info = this_cpu_ptr(&per_cpu_info);
struct tile_net_priv *priv = netdev_priv(dev);
int instance = priv->instance;
@@ -585,7 +585,7 @@ static void tile_net_receive_skb(struct net_device *dev, struct sk_buff *skb,
/* Handle a packet. Return true if "processed", false if "filtered". */
static bool tile_net_handle_packet(int instance, gxio_mpipe_idesc_t *idesc)
{
- struct tile_net_info *info = &__get_cpu_var(per_cpu_info);
+ struct tile_net_info *info = this_cpu_ptr(&per_cpu_info);
struct mpipe_data *md = &mpipe_data[instance];
struct net_device *dev = md->tile_net_devs_for_channel[idesc->channel];
uint8_t l2_offset;
@@ -651,7 +651,7 @@ drop:
*/
static int tile_net_poll(struct napi_struct *napi, int budget)
{
- struct tile_net_info *info = &__get_cpu_var(per_cpu_info);
+ struct tile_net_info *info = this_cpu_ptr(&per_cpu_info);
unsigned int work = 0;
gxio_mpipe_idesc_t *idesc;
int instance, i, n;
@@ -700,7 +700,7 @@ done:
/* Handle an ingress interrupt from an instance on the current cpu. */
static irqreturn_t tile_net_handle_ingress_irq(int irq, void *id)
{
- struct tile_net_info *info = &__get_cpu_var(per_cpu_info);
+ struct tile_net_info *info = this_cpu_ptr(&per_cpu_info);
napi_schedule(&info->mpipe[(uint64_t)id].napi);
return IRQ_HANDLED;
}
@@ -763,7 +763,7 @@ static enum hrtimer_restart tile_net_handle_tx_wake_timer(struct hrtimer *t)
/* Make sure the egress timer is scheduled. */
static void tile_net_schedule_egress_timer(void)
{
- struct tile_net_info *info = &__get_cpu_var(per_cpu_info);
+ struct tile_net_info *info = this_cpu_ptr(&per_cpu_info);
if (!info->egress_timer_scheduled) {
hrtimer_start(&info->egress_timer,
@@ -780,7 +780,7 @@ static void tile_net_schedule_egress_timer(void)
*/
static enum hrtimer_restart tile_net_handle_egress_timer(struct hrtimer *t)
{
- struct tile_net_info *info = &__get_cpu_var(per_cpu_info);
+ struct tile_net_info *info = this_cpu_ptr(&per_cpu_info);
unsigned long irqflags;
bool pending = false;
int i, instance;
@@ -1927,7 +1927,7 @@ static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue,
*/
static int tile_net_tx_tso(struct sk_buff *skb, struct net_device *dev)
{
- struct tile_net_info *info = &__get_cpu_var(per_cpu_info);
+ struct tile_net_info *info = this_cpu_ptr(&per_cpu_info);
struct tile_net_priv *priv = netdev_priv(dev);
int channel = priv->echannel;
int instance = priv->instance;
@@ -1996,7 +1996,7 @@ static unsigned int tile_net_tx_frags(struct frag *frags,
/* Help the kernel transmit a packet. */
static int tile_net_tx(struct sk_buff *skb, struct net_device *dev)
{
- struct tile_net_info *info = &__get_cpu_var(per_cpu_info);
+ struct tile_net_info *info = this_cpu_ptr(&per_cpu_info);
struct tile_net_priv *priv = netdev_priv(dev);
int instance = priv->instance;
struct mpipe_data *md = &mpipe_data[instance];
@@ -2138,7 +2138,7 @@ static int tile_net_set_mac_address(struct net_device *dev, void *p)
static void tile_net_netpoll(struct net_device *dev)
{
int instance = mpipe_instance(dev);
- struct tile_net_info *info = &__get_cpu_var(per_cpu_info);
+ struct tile_net_info *info = this_cpu_ptr(&per_cpu_info);
struct mpipe_data *md = &mpipe_data[instance];
disable_percpu_irq(md->ingress_irq);
@@ -2237,7 +2237,7 @@ static void tile_net_dev_init(const char *name, const uint8_t *mac)
/* Per-cpu module initialization. */
static void tile_net_init_module_percpu(void *unused)
{
- struct tile_net_info *info = &__get_cpu_var(per_cpu_info);
+ struct tile_net_info *info = this_cpu_ptr(&per_cpu_info);
int my_cpu = smp_processor_id();
int instance;
diff --git a/drivers/net/ethernet/tile/tilepro.c b/drivers/net/ethernet/tile/tilepro.c
index 88818d5054ab..fb12d31cfcf6 100644
--- a/drivers/net/ethernet/tile/tilepro.c
+++ b/drivers/net/ethernet/tile/tilepro.c
@@ -996,13 +996,13 @@ static void tile_net_register(void *dev_ptr)
PDEBUG("tile_net_register(queue_id %d)\n", queue_id);
if (!strcmp(dev->name, "xgbe0"))
- info = &__get_cpu_var(hv_xgbe0);
+ info = this_cpu_ptr(&hv_xgbe0);
else if (!strcmp(dev->name, "xgbe1"))
- info = &__get_cpu_var(hv_xgbe1);
+ info = this_cpu_ptr(&hv_xgbe1);
else if (!strcmp(dev->name, "gbe0"))
- info = &__get_cpu_var(hv_gbe0);
+ info = this_cpu_ptr(&hv_gbe0);
else if (!strcmp(dev->name, "gbe1"))
- info = &__get_cpu_var(hv_gbe1);
+ info = this_cpu_ptr(&hv_gbe1);
else
BUG();
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 0fcb5e7eb073..9e17d1a91e71 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -162,7 +162,7 @@ union sub_key {
* data: network byte order
* return: host byte order
*/
-static u32 comp_hash(u8 *key, int klen, u8 *data, int dlen)
+static u32 comp_hash(u8 *key, int klen, void *data, int dlen)
{
union sub_key subk;
int k_next = 4;
@@ -176,7 +176,7 @@ static u32 comp_hash(u8 *key, int klen, u8 *data, int dlen)
for (i = 0; i < dlen; i++) {
subk.kb = key[k_next];
k_next = (k_next + 1) % klen;
- dt = data[i];
+ dt = ((u8 *)data)[i];
for (j = 0; j < 8; j++) {
if (dt & 0x80)
ret ^= subk.ka;
@@ -190,26 +190,20 @@ static u32 comp_hash(u8 *key, int klen, u8 *data, int dlen)
static bool netvsc_set_hash(u32 *hash, struct sk_buff *skb)
{
- struct iphdr *iphdr;
+ struct flow_keys flow;
int data_len;
- bool ret = false;
- if (eth_hdr(skb)->h_proto != htons(ETH_P_IP))
+ if (!skb_flow_dissect(skb, &flow) || flow.n_proto != htons(ETH_P_IP))
return false;
- iphdr = ip_hdr(skb);
+ if (flow.ip_proto == IPPROTO_TCP)
+ data_len = 12;
+ else
+ data_len = 8;
- if (iphdr->version == 4) {
- if (iphdr->protocol == IPPROTO_TCP)
- data_len = 12;
- else
- data_len = 8;
- *hash = comp_hash(netvsc_hash_key, HASH_KEYLEN,
- (u8 *)&iphdr->saddr, data_len);
- ret = true;
- }
+ *hash = comp_hash(netvsc_hash_key, HASH_KEYLEN, &flow, data_len);
- return ret;
+ return true;
}
static u16 netvsc_select_queue(struct net_device *ndev, struct sk_buff *skb,
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 38b4fae61f04..29b3bb410781 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -260,7 +260,7 @@ static void macvlan_broadcast(struct sk_buff *skb,
mode == MACVLAN_MODE_BRIDGE) ?:
netif_rx_ni(nskb);
macvlan_count_rx(vlan, skb->len + ETH_HLEN,
- err == NET_RX_SUCCESS, 1);
+ err == NET_RX_SUCCESS, true);
}
}
}
@@ -379,7 +379,7 @@ static void macvlan_forward_source_one(struct sk_buff *skb,
nskb->pkt_type = PACKET_HOST;
ret = netif_rx(nskb);
- macvlan_count_rx(vlan, len, ret == NET_RX_SUCCESS, 0);
+ macvlan_count_rx(vlan, len, ret == NET_RX_SUCCESS, false);
}
static void macvlan_forward_source(struct sk_buff *skb,
@@ -407,7 +407,8 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb)
const struct macvlan_dev *src;
struct net_device *dev;
unsigned int len = 0;
- int ret = NET_RX_DROP;
+ int ret;
+ rx_handler_result_t handle_res;
port = macvlan_port_get_rcu(skb->dev);
if (is_multicast_ether_addr(eth->h_dest)) {
@@ -423,6 +424,7 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb)
vlan = src;
ret = macvlan_broadcast_one(skb, vlan, eth, 0) ?:
netif_rx(skb);
+ handle_res = RX_HANDLER_CONSUMED;
goto out;
}
@@ -448,17 +450,20 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb)
}
len = skb->len + ETH_HLEN;
skb = skb_share_check(skb, GFP_ATOMIC);
- if (!skb)
+ if (!skb) {
+ ret = NET_RX_DROP;
+ handle_res = RX_HANDLER_CONSUMED;
goto out;
+ }
skb->dev = dev;
skb->pkt_type = PACKET_HOST;
- ret = netif_rx(skb);
-
+ ret = NET_RX_SUCCESS;
+ handle_res = RX_HANDLER_ANOTHER;
out:
- macvlan_count_rx(vlan, len, ret == NET_RX_SUCCESS, 0);
- return RX_HANDLER_CONSUMED;
+ macvlan_count_rx(vlan, len, ret == NET_RX_SUCCESS, false);
+ return handle_res;
}
static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev)
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index 0c6adaaf898c..65e2892342bd 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -298,7 +298,7 @@ static rx_handler_result_t macvtap_handle_frame(struct sk_buff **pskb)
*/
if (q->flags & IFF_VNET_HDR)
features |= vlan->tap_features;
- if (netif_needs_gso(skb, features)) {
+ if (netif_needs_gso(dev, skb, features)) {
struct sk_buff *segs = __skb_gso_segment(skb, features, false);
if (IS_ERR(segs))
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 011dbda2b2f1..8c2a29a9bd7f 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -26,6 +26,7 @@
#include <linux/phy.h>
#include <linux/micrel_phy.h>
#include <linux/of.h>
+#include <linux/clk.h>
/* Operation Mode Strap Override */
#define MII_KSZPHY_OMSO 0x16
@@ -72,9 +73,12 @@ static int ksz_config_flags(struct phy_device *phydev)
{
int regval;
- if (phydev->dev_flags & MICREL_PHY_50MHZ_CLK) {
+ if (phydev->dev_flags & (MICREL_PHY_50MHZ_CLK | MICREL_PHY_25MHZ_CLK)) {
regval = phy_read(phydev, MII_KSZPHY_CTRL);
- regval |= KSZ8051_RMII_50MHZ_CLK;
+ if (phydev->dev_flags & MICREL_PHY_50MHZ_CLK)
+ regval |= KSZ8051_RMII_50MHZ_CLK;
+ else
+ regval &= ~KSZ8051_RMII_50MHZ_CLK;
return phy_write(phydev, MII_KSZPHY_CTRL, regval);
}
return 0;
@@ -194,8 +198,10 @@ static int ksz8021_config_init(struct phy_device *phydev)
if (rc)
dev_err(&phydev->dev, "failed to set led mode\n");
- phy_write(phydev, MII_KSZPHY_OMSO, val);
rc = ksz_config_flags(phydev);
+ if (rc < 0)
+ return rc;
+ rc = phy_write(phydev, MII_KSZPHY_OMSO, val);
return rc < 0 ? rc : 0;
}
@@ -440,6 +446,27 @@ ksz9021_wr_mmd_phyreg(struct phy_device *phydev, int ptrad, int devnum,
{
}
+static int ksz8021_probe(struct phy_device *phydev)
+{
+ struct clk *clk;
+
+ clk = devm_clk_get(&phydev->dev, "rmii-ref");
+ if (!IS_ERR(clk)) {
+ unsigned long rate = clk_get_rate(clk);
+
+ if (rate > 24500000 && rate < 25500000) {
+ phydev->dev_flags |= MICREL_PHY_25MHZ_CLK;
+ } else if (rate > 49500000 && rate < 50500000) {
+ phydev->dev_flags |= MICREL_PHY_50MHZ_CLK;
+ } else {
+ dev_err(&phydev->dev, "Clock rate out of range: %ld\n", rate);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
static struct phy_driver ksphy_driver[] = {
{
.phy_id = PHY_ID_KS8737,
@@ -462,6 +489,7 @@ static struct phy_driver ksphy_driver[] = {
.features = (PHY_BASIC_FEATURES | SUPPORTED_Pause |
SUPPORTED_Asym_Pause),
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
+ .probe = ksz8021_probe,
.config_init = ksz8021_config_init,
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
@@ -477,6 +505,7 @@ static struct phy_driver ksphy_driver[] = {
.features = (PHY_BASIC_FEATURES | SUPPORTED_Pause |
SUPPORTED_Asym_Pause),
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
+ .probe = ksz8021_probe,
.config_init = ksz8021_config_init,
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index 80e6f3430f65..68c3a3f4e0ab 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -594,7 +594,7 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if (file == ppp->owner)
ppp_shutdown_interface(ppp);
}
- if (atomic_long_read(&file->f_count) <= 2) {
+ if (atomic_long_read(&file->f_count) < 2) {
ppp_release(NULL, file);
err = 0;
} else
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index acaaf6784179..186ce541c657 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -2152,9 +2152,7 @@ static int tun_chr_fasync(int fd, struct file *file, int on)
goto out;
if (on) {
- ret = __f_setown(file, task_pid(current), PIDTYPE_PID, 0);
- if (ret)
- goto out;
+ __f_setown(file, task_pid(current), PIDTYPE_PID, 0);
tfile->flags |= TUN_FASYNC;
} else
tfile->flags &= ~TUN_FASYNC;
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 5cfd414b9a3e..e3d84c322e4e 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -26,7 +26,7 @@
#include <linux/mdio.h>
/* Version Information */
-#define DRIVER_VERSION "v1.06.1 (2014/10/01)"
+#define DRIVER_VERSION "v1.07.0 (2014/10/09)"
#define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>"
#define DRIVER_DESC "Realtek RTL8152/RTL8153 Based USB Ethernet Adapters"
#define MODULENAME "r8152"
@@ -566,6 +566,7 @@ struct r8152 {
spinlock_t rx_lock, tx_lock;
struct delayed_work schedule;
struct mii_if_info mii;
+ struct mutex control; /* use for hw setting */
struct rtl_ops {
void (*init)(struct r8152 *);
@@ -942,15 +943,8 @@ static int read_mii_word(struct net_device *netdev, int phy_id, int reg)
if (phy_id != R8152_PHY_ID)
return -EINVAL;
- ret = usb_autopm_get_interface(tp->intf);
- if (ret < 0)
- goto out;
-
ret = r8152_mdio_read(tp, reg);
- usb_autopm_put_interface(tp->intf);
-
-out:
return ret;
}
@@ -965,12 +959,7 @@ void write_mii_word(struct net_device *netdev, int phy_id, int reg, int val)
if (phy_id != R8152_PHY_ID)
return;
- if (usb_autopm_get_interface(tp->intf) < 0)
- return;
-
r8152_mdio_write(tp, reg, val);
-
- usb_autopm_put_interface(tp->intf);
}
static int
@@ -989,12 +978,16 @@ static int rtl8152_set_mac_address(struct net_device *netdev, void *p)
if (ret < 0)
goto out1;
+ mutex_lock(&tp->control);
+
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG);
pla_ocp_write(tp, PLA_IDR, BYTE_EN_SIX_BYTES, 8, addr->sa_data);
ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML);
+ mutex_unlock(&tp->control);
+
usb_autopm_put_interface(tp->intf);
out1:
return ret;
@@ -2145,6 +2138,13 @@ static int rtl8152_set_features(struct net_device *dev,
{
netdev_features_t changed = features ^ dev->features;
struct r8152 *tp = netdev_priv(dev);
+ int ret;
+
+ ret = usb_autopm_get_interface(tp->intf);
+ if (ret < 0)
+ goto out;
+
+ mutex_lock(&tp->control);
if (changed & NETIF_F_HW_VLAN_CTAG_RX) {
if (features & NETIF_F_HW_VLAN_CTAG_RX)
@@ -2153,7 +2153,12 @@ static int rtl8152_set_features(struct net_device *dev,
rtl_rx_vlan_en(tp, false);
}
- return 0;
+ mutex_unlock(&tp->control);
+
+ usb_autopm_put_interface(tp->intf);
+
+out:
+ return ret;
}
#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)
@@ -2851,6 +2856,11 @@ static void rtl_work_func_t(struct work_struct *work)
if (test_bit(RTL8152_UNPLUG, &tp->flags))
goto out1;
+ if (!mutex_trylock(&tp->control)) {
+ schedule_delayed_work(&tp->schedule, 0);
+ goto out1;
+ }
+
if (test_bit(RTL8152_LINK_CHG, &tp->flags))
set_carrier(tp);
@@ -2866,6 +2876,8 @@ static void rtl_work_func_t(struct work_struct *work)
if (test_bit(PHY_RESET, &tp->flags))
rtl_phy_reset(tp);
+ mutex_unlock(&tp->control);
+
out1:
usb_autopm_put_interface(tp->intf);
}
@@ -2885,6 +2897,8 @@ static int rtl8152_open(struct net_device *netdev)
goto out;
}
+ mutex_lock(&tp->control);
+
/* The WORK_ENABLE may be set when autoresume occurs */
if (test_bit(WORK_ENABLE, &tp->flags)) {
clear_bit(WORK_ENABLE, &tp->flags);
@@ -2913,6 +2927,8 @@ static int rtl8152_open(struct net_device *netdev)
free_all_mem(tp);
}
+ mutex_unlock(&tp->control);
+
usb_autopm_put_interface(tp->intf);
out:
@@ -2933,6 +2949,8 @@ static int rtl8152_close(struct net_device *netdev)
if (res < 0) {
rtl_drop_queued_tx(tp);
} else {
+ mutex_lock(&tp->control);
+
/* The autosuspend may have been enabled and wouldn't
* be disable when autoresume occurs, because the
* netif_running() would be false.
@@ -2945,6 +2963,9 @@ static int rtl8152_close(struct net_device *netdev)
tasklet_disable(&tp->tl);
tp->rtl_ops.down(tp);
tasklet_enable(&tp->tl);
+
+ mutex_unlock(&tp->control);
+
usb_autopm_put_interface(tp->intf);
}
@@ -3168,33 +3189,47 @@ static void r8153_init(struct r8152 *tp)
static int rtl8152_suspend(struct usb_interface *intf, pm_message_t message)
{
struct r8152 *tp = usb_get_intfdata(intf);
+ struct net_device *netdev = tp->netdev;
+ int ret = 0;
+
+ mutex_lock(&tp->control);
+
+ if (PMSG_IS_AUTO(message)) {
+ if (netif_running(netdev) && work_busy(&tp->schedule.work)) {
+ ret = -EBUSY;
+ goto out1;
+ }
- if (PMSG_IS_AUTO(message))
set_bit(SELECTIVE_SUSPEND, &tp->flags);
- else
- netif_device_detach(tp->netdev);
+ } else {
+ netif_device_detach(netdev);
+ }
- if (netif_running(tp->netdev)) {
+ if (netif_running(netdev)) {
clear_bit(WORK_ENABLE, &tp->flags);
usb_kill_urb(tp->intr_urb);
- cancel_delayed_work_sync(&tp->schedule);
tasklet_disable(&tp->tl);
if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) {
rtl_stop_rx(tp);
rtl_runtime_suspend_enable(tp, true);
} else {
+ cancel_delayed_work_sync(&tp->schedule);
tp->rtl_ops.down(tp);
}
tasklet_enable(&tp->tl);
}
+out1:
+ mutex_unlock(&tp->control);
- return 0;
+ return ret;
}
static int rtl8152_resume(struct usb_interface *intf)
{
struct r8152 *tp = usb_get_intfdata(intf);
+ mutex_lock(&tp->control);
+
if (!test_bit(SELECTIVE_SUSPEND, &tp->flags)) {
tp->rtl_ops.init(tp);
netif_device_attach(tp->netdev);
@@ -3220,6 +3255,8 @@ static int rtl8152_resume(struct usb_interface *intf)
usb_submit_urb(tp->intr_urb, GFP_KERNEL);
}
+ mutex_unlock(&tp->control);
+
return 0;
}
@@ -3230,9 +3267,13 @@ static void rtl8152_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
if (usb_autopm_get_interface(tp->intf) < 0)
return;
+ mutex_lock(&tp->control);
+
wol->supported = WAKE_ANY;
wol->wolopts = __rtl_get_wol(tp);
+ mutex_unlock(&tp->control);
+
usb_autopm_put_interface(tp->intf);
}
@@ -3245,9 +3286,13 @@ static int rtl8152_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
if (ret < 0)
goto out_set_wol;
+ mutex_lock(&tp->control);
+
__rtl_set_wol(tp, wol->wolopts);
tp->saved_wolopts = wol->wolopts & WAKE_ANY;
+ mutex_unlock(&tp->control);
+
usb_autopm_put_interface(tp->intf);
out_set_wol:
@@ -3282,11 +3327,25 @@ static
int rtl8152_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
{
struct r8152 *tp = netdev_priv(netdev);
+ int ret;
if (!tp->mii.mdio_read)
return -EOPNOTSUPP;
- return mii_ethtool_gset(&tp->mii, cmd);
+ ret = usb_autopm_get_interface(tp->intf);
+ if (ret < 0)
+ goto out;
+
+ mutex_lock(&tp->control);
+
+ ret = mii_ethtool_gset(&tp->mii, cmd);
+
+ mutex_unlock(&tp->control);
+
+ usb_autopm_put_interface(tp->intf);
+
+out:
+ return ret;
}
static int rtl8152_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
@@ -3298,8 +3357,12 @@ static int rtl8152_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
if (ret < 0)
goto out;
+ mutex_lock(&tp->control);
+
ret = rtl8152_set_speed(tp, cmd->autoneg, cmd->speed, cmd->duplex);
+ mutex_unlock(&tp->control);
+
usb_autopm_put_interface(tp->intf);
out:
@@ -3459,8 +3522,12 @@ rtl_ethtool_get_eee(struct net_device *net, struct ethtool_eee *edata)
if (ret < 0)
goto out;
+ mutex_lock(&tp->control);
+
ret = tp->rtl_ops.eee_get(tp, edata);
+ mutex_unlock(&tp->control);
+
usb_autopm_put_interface(tp->intf);
out:
@@ -3477,10 +3544,14 @@ rtl_ethtool_set_eee(struct net_device *net, struct ethtool_eee *edata)
if (ret < 0)
goto out;
+ mutex_lock(&tp->control);
+
ret = tp->rtl_ops.eee_set(tp, edata);
if (!ret)
ret = mii_nway_restart(&tp->mii);
+ mutex_unlock(&tp->control);
+
usb_autopm_put_interface(tp->intf);
out:
@@ -3522,7 +3593,9 @@ static int rtl8152_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
break;
case SIOCGMIIREG:
+ mutex_lock(&tp->control);
data->val_out = r8152_mdio_read(tp, data->reg_num);
+ mutex_unlock(&tp->control);
break;
case SIOCSMIIREG:
@@ -3530,7 +3603,9 @@ static int rtl8152_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
res = -EPERM;
break;
}
+ mutex_lock(&tp->control);
r8152_mdio_write(tp, data->reg_num, data->val_in);
+ mutex_unlock(&tp->control);
break;
default:
@@ -3723,6 +3798,7 @@ static int rtl8152_probe(struct usb_interface *intf,
goto out;
tasklet_init(&tp->tl, bottom_half, (unsigned long)tp);
+ mutex_init(&tp->control);
INIT_DELAYED_WORK(&tp->schedule, rtl_work_func_t);
netdev->netdev_ops = &rtl8152_netdev_ops;
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 3d0ce4468ce6..d75256bd1a6a 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -123,9 +123,6 @@ struct virtnet_info {
/* Host can handle any s/g split between our header and packet data */
bool any_header_sg;
- /* enable config space updates */
- bool config_enable;
-
/* Active statistics */
struct virtnet_stats __percpu *stats;
@@ -135,9 +132,6 @@ struct virtnet_info {
/* Work struct for config space updates */
struct work_struct config_work;
- /* Lock for config space updates */
- struct mutex config_lock;
-
/* Does the affinity hint is set for virtqueues? */
bool affinity_hint_set;
@@ -920,6 +914,8 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
int qnum = skb_get_queue_mapping(skb);
struct send_queue *sq = &vi->sq[qnum];
int err;
+ struct netdev_queue *txq = netdev_get_tx_queue(dev, qnum);
+ bool kick = !skb->xmit_more;
/* Free up any pending old buffers before queueing new ones. */
free_old_xmit_skbs(sq);
@@ -956,7 +952,7 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
}
}
- if (__netif_subqueue_stopped(dev, qnum) || !skb->xmit_more)
+ if (kick || netif_xmit_stopped(txq))
virtqueue_kick(sq->vq);
return NETDEV_TX_OK;
@@ -1412,13 +1408,9 @@ static void virtnet_config_changed_work(struct work_struct *work)
container_of(work, struct virtnet_info, config_work);
u16 v;
- mutex_lock(&vi->config_lock);
- if (!vi->config_enable)
- goto done;
-
if (virtio_cread_feature(vi->vdev, VIRTIO_NET_F_STATUS,
struct virtio_net_config, status, &v) < 0)
- goto done;
+ return;
if (v & VIRTIO_NET_S_ANNOUNCE) {
netdev_notify_peers(vi->dev);
@@ -1429,7 +1421,7 @@ static void virtnet_config_changed_work(struct work_struct *work)
v &= VIRTIO_NET_S_LINK_UP;
if (vi->status == v)
- goto done;
+ return;
vi->status = v;
@@ -1440,8 +1432,6 @@ static void virtnet_config_changed_work(struct work_struct *work)
netif_carrier_off(vi->dev);
netif_tx_stop_all_queues(vi->dev);
}
-done:
- mutex_unlock(&vi->config_lock);
}
static void virtnet_config_changed(struct virtio_device *vdev)
@@ -1762,8 +1752,6 @@ static int virtnet_probe(struct virtio_device *vdev)
u64_stats_init(&virtnet_stats->rx_syncp);
}
- mutex_init(&vi->config_lock);
- vi->config_enable = true;
INIT_WORK(&vi->config_work, virtnet_config_changed_work);
/* If we can receive ANY GSO packets, we must allocate large ones. */
@@ -1811,6 +1799,8 @@ static int virtnet_probe(struct virtio_device *vdev)
goto free_vqs;
}
+ virtio_device_ready(vdev);
+
/* Last of all, set up some receive buffers. */
for (i = 0; i < vi->curr_queue_pairs; i++) {
try_fill_recv(&vi->rq[i], GFP_KERNEL);
@@ -1847,6 +1837,8 @@ static int virtnet_probe(struct virtio_device *vdev)
return 0;
free_recv_bufs:
+ vi->vdev->config->reset(vdev);
+
free_receive_bufs(vi);
unregister_netdev(dev);
free_vqs:
@@ -1880,17 +1872,13 @@ static void virtnet_remove(struct virtio_device *vdev)
unregister_hotcpu_notifier(&vi->nb);
- /* Prevent config work handler from accessing the device. */
- mutex_lock(&vi->config_lock);
- vi->config_enable = false;
- mutex_unlock(&vi->config_lock);
+ /* Make sure no work handler is accessing the device. */
+ flush_work(&vi->config_work);
unregister_netdev(vi->dev);
remove_vq_common(vi);
- flush_work(&vi->config_work);
-
free_percpu(vi->stats);
free_netdev(vi->dev);
}
@@ -1903,10 +1891,8 @@ static int virtnet_freeze(struct virtio_device *vdev)
unregister_hotcpu_notifier(&vi->nb);
- /* Prevent config work handler from accessing the device */
- mutex_lock(&vi->config_lock);
- vi->config_enable = false;
- mutex_unlock(&vi->config_lock);
+ /* Make sure no work handler is accessing the device */
+ flush_work(&vi->config_work);
netif_device_detach(vi->dev);
cancel_delayed_work_sync(&vi->refill);
@@ -1921,8 +1907,6 @@ static int virtnet_freeze(struct virtio_device *vdev)
remove_vq_common(vi);
- flush_work(&vi->config_work);
-
return 0;
}
@@ -1935,6 +1919,8 @@ static int virtnet_restore(struct virtio_device *vdev)
if (err)
return err;
+ virtio_device_ready(vdev);
+
if (netif_running(vi->dev)) {
for (i = 0; i < vi->curr_queue_pairs; i++)
if (!try_fill_recv(&vi->rq[i], GFP_KERNEL))
@@ -1946,10 +1932,6 @@ static int virtnet_restore(struct virtio_device *vdev)
netif_device_attach(vi->dev);
- mutex_lock(&vi->config_lock);
- vi->config_enable = true;
- mutex_unlock(&vi->config_lock);
-
rtnl_lock();
virtnet_set_queues(vi, vi->curr_queue_pairs);
rtnl_unlock();
diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h
index 3759479f959a..5f0199f6c31e 100644
--- a/drivers/net/vmxnet3/vmxnet3_int.h
+++ b/drivers/net/vmxnet3/vmxnet3_int.h
@@ -117,7 +117,6 @@ enum {
/*
* PCI vendor and device IDs.
*/
-#define PCI_VENDOR_ID_VMWARE 0x15AD
#define PCI_DEVICE_ID_VMWARE_VMXNET3 0x07B0
#define MAX_ETHERNET_CARDS 10
#define MAX_PCI_PASSTHRU_DEVICE 6
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 2a51e6e48e1e..ca309820d39e 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -1437,9 +1437,6 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb)
if (!in6_dev)
goto out;
- if (!pskb_may_pull(skb, skb->len))
- goto out;
-
iphdr = ipv6_hdr(skb);
saddr = &iphdr->saddr;
daddr = &iphdr->daddr;
@@ -1668,6 +1665,8 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
struct pcpu_sw_netstats *tx_stats, *rx_stats;
union vxlan_addr loopback;
union vxlan_addr *remote_ip = &dst_vxlan->default_dst.remote_ip;
+ struct net_device *dev = skb->dev;
+ int len = skb->len;
tx_stats = this_cpu_ptr(src_vxlan->dev->tstats);
rx_stats = this_cpu_ptr(dst_vxlan->dev->tstats);
@@ -1691,16 +1690,16 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
u64_stats_update_begin(&tx_stats->syncp);
tx_stats->tx_packets++;
- tx_stats->tx_bytes += skb->len;
+ tx_stats->tx_bytes += len;
u64_stats_update_end(&tx_stats->syncp);
if (netif_rx(skb) == NET_RX_SUCCESS) {
u64_stats_update_begin(&rx_stats->syncp);
rx_stats->rx_packets++;
- rx_stats->rx_bytes += skb->len;
+ rx_stats->rx_bytes += len;
u64_stats_update_end(&rx_stats->syncp);
} else {
- skb->dev->stats.rx_dropped++;
+ dev->stats.rx_dropped++;
}
}
@@ -1878,7 +1877,8 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
return arp_reduce(dev, skb);
#if IS_ENABLED(CONFIG_IPV6)
else if (ntohs(eth->h_proto) == ETH_P_IPV6 &&
- skb->len >= sizeof(struct ipv6hdr) + sizeof(struct nd_msg) &&
+ pskb_may_pull(skb, sizeof(struct ipv6hdr)
+ + sizeof(struct nd_msg)) &&
ipv6_hdr(skb)->nexthdr == IPPROTO_ICMPV6) {
struct nd_msg *msg;
@@ -1887,6 +1887,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
msg->icmph.icmp6_type == NDISC_NEIGHBOUR_SOLICITATION)
return neigh_reduce(dev, skb);
}
+ eth = eth_hdr(skb);
#endif
}
diff --git a/drivers/net/wimax/Makefile b/drivers/net/wimax/Makefile
index 992bc02bc016..692184dd674a 100644
--- a/drivers/net/wimax/Makefile
+++ b/drivers/net/wimax/Makefile
@@ -1,5 +1 @@
-
obj-$(CONFIG_WIMAX_I2400M) += i2400m/
-
-# (from Sam Ravnborg) force kbuild to create built-in.o
-obj- := dummy.o
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
index e5ba6faf3281..86907e5ba6ca 100644
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
@@ -80,6 +80,7 @@ struct reg_dmn_pair_mapping {
struct ath_regulatory {
char alpha2[2];
+ enum nl80211_dfs_regions region;
u16 country_code;
u16 max_power_level;
u16 current_rd;
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index bfa0b1518da1..01a7db061c6a 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -294,7 +294,6 @@ struct ath_tx_control {
* (axq_qnum).
*/
struct ath_tx {
- u16 seq_no;
u32 txqsetup;
spinlock_t txbuflock;
struct list_head txbuf;
@@ -563,6 +562,7 @@ int ath_tx_init(struct ath_softc *sc, int nbufs);
int ath_txq_update(struct ath_softc *sc, int qnum,
struct ath9k_tx_queue_info *q);
void ath_update_max_aggr_framelen(struct ath_softc *sc, int queue, int txop);
+void ath_assign_seq(struct ath_common *common, struct sk_buff *skb);
int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ath_tx_control *txctl);
void ath_tx_cabq(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
@@ -592,6 +592,8 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw,
struct ath_vif {
struct list_head list;
+ u16 seq_no;
+
/* BSS info */
u8 bssid[ETH_ALEN];
u16 aid;
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index a6af855ef6ed..ecb783beeec2 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -144,16 +144,8 @@ static struct ath_buf *ath9k_beacon_generate(struct ieee80211_hw *hw,
mgmt_hdr->u.beacon.timestamp = avp->tsf_adjust;
info = IEEE80211_SKB_CB(skb);
- if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
- /*
- * TODO: make sure the seq# gets assigned properly (vs. other
- * TX frames)
- */
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- sc->tx.seq_no += 0x10;
- hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
- hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
- }
+
+ ath_assign_seq(common, skb);
if (vif->p2p)
ath9k_beacon_add_noa(sc, avp, skb);
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c
index c6dd7f1fed65..33b0c7aef2ea 100644
--- a/drivers/net/wireless/ath/ath9k/common.c
+++ b/drivers/net/wireless/ath/ath9k/common.c
@@ -368,11 +368,11 @@ void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
{
struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
- if (reg->power_limit != new_txpow) {
+ if (reg->power_limit != new_txpow)
ath9k_hw_set_txpowerlimit(ah, new_txpow, false);
- /* read back in case value is clamped */
- *txpower = reg->max_power_level;
- }
+
+ /* read back in case value is clamped */
+ *txpower = reg->max_power_level;
}
EXPORT_SYMBOL(ath9k_cmn_update_txpow);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index d779f4fa50e3..4014c4be6e79 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -464,6 +464,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
return -ENOMEM;
ah->dev = priv->dev;
+ ah->hw = priv->hw;
ah->hw_version.devid = devid;
ah->hw_version.usbdev = drv_info;
ah->ah_flags |= AH_USE_EEPROM;
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 156a944134dc..3bd030494986 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -734,6 +734,32 @@ static const struct ieee80211_iface_combination if_comb[] = {
#endif
};
+#ifdef CONFIG_ATH9K_CHANNEL_CONTEXT
+static void ath9k_set_mcc_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+
+ if (!ath9k_is_chanctx_enabled())
+ return;
+
+ hw->flags |= IEEE80211_HW_QUEUE_CONTROL;
+ hw->queues = ATH9K_NUM_TX_QUEUES;
+ hw->offchannel_tx_hw_queue = hw->queues - 1;
+ hw->wiphy->interface_modes &= ~ BIT(NL80211_IFTYPE_WDS);
+ hw->wiphy->iface_combinations = if_comb_multi;
+ hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb_multi);
+ hw->wiphy->max_scan_ssids = 255;
+ hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
+ hw->wiphy->max_remain_on_channel_duration = 10000;
+ hw->chanctx_data_size = sizeof(void *);
+ hw->extra_beacon_tailroom =
+ sizeof(struct ieee80211_p2p_noa_attr) + 9;
+
+ ath_dbg(common, CHAN_CTX, "Use channel contexts\n");
+}
+#endif /* CONFIG_ATH9K_CHANNEL_CONTEXT */
+
static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
{
struct ath_hw *ah = sc->sc_ah;
@@ -746,7 +772,6 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
IEEE80211_HW_SPECTRUM_MGMT |
IEEE80211_HW_REPORTS_TX_ACK_STATUS |
IEEE80211_HW_SUPPORTS_RC_TABLE |
- IEEE80211_HW_QUEUE_CONTROL |
IEEE80211_HW_SUPPORTS_HT_CCK_RATES;
if (ath9k_ps_enable)
@@ -781,24 +806,6 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
}
-#ifdef CONFIG_ATH9K_CHANNEL_CONTEXT
-
- if (ath9k_is_chanctx_enabled()) {
- hw->wiphy->interface_modes &= ~ BIT(NL80211_IFTYPE_WDS);
- hw->wiphy->iface_combinations = if_comb_multi;
- hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb_multi);
- hw->wiphy->max_scan_ssids = 255;
- hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
- hw->wiphy->max_remain_on_channel_duration = 10000;
- hw->chanctx_data_size = sizeof(void *);
- hw->extra_beacon_tailroom =
- sizeof(struct ieee80211_p2p_noa_attr) + 9;
-
- ath_dbg(common, CHAN_CTX, "Use channel contexts\n");
- }
-
-#endif /* CONFIG_ATH9K_CHANNEL_CONTEXT */
-
hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
@@ -808,12 +815,7 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
- /* allow 4 queues per channel context +
- * 1 cab queue + 1 offchannel tx queue
- */
- hw->queues = ATH9K_NUM_TX_QUEUES;
- /* last queue for offchannel */
- hw->offchannel_tx_hw_queue = hw->queues - 1;
+ hw->queues = 4;
hw->max_rates = 4;
hw->max_listen_interval = 10;
hw->max_rate_tries = 10;
@@ -837,6 +839,9 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
&common->sbands[IEEE80211_BAND_5GHZ];
+#ifdef CONFIG_ATH9K_CHANNEL_CONTEXT
+ ath9k_set_mcc_capab(sc, hw);
+#endif
ath9k_init_wow(hw);
ath9k_cmn_reload_chainmask(ah);
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 205162449b72..30c66dfcd7a0 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1162,6 +1162,9 @@ static void ath9k_assign_hw_queues(struct ieee80211_hw *hw,
{
int i;
+ if (!ath9k_is_chanctx_enabled())
+ return;
+
for (i = 0; i < IEEE80211_NUM_ACS; i++)
vif->hw_queue[i] = i;
@@ -2332,7 +2335,7 @@ static void ath9k_remove_chanctx(struct ieee80211_hw *hw,
conf->def.chan->center_freq);
ctx->assigned = false;
- ctx->hw_queue_base = -1;
+ ctx->hw_queue_base = 0;
ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_UNASSIGN);
mutex_unlock(&sc->mutex);
diff --git a/drivers/net/wireless/ath/ath9k/tx99.c b/drivers/net/wireless/ath/ath9k/tx99.c
index 8a69d08ec55c..40ab65e6882f 100644
--- a/drivers/net/wireless/ath/ath9k/tx99.c
+++ b/drivers/net/wireless/ath/ath9k/tx99.c
@@ -54,6 +54,12 @@ static struct sk_buff *ath9k_build_tx99_skb(struct ath_softc *sc)
struct ieee80211_hdr *hdr;
struct ieee80211_tx_info *tx_info;
struct sk_buff *skb;
+ struct ath_vif *avp;
+
+ if (!sc->tx99_vif)
+ return NULL;
+
+ avp = (struct ath_vif *)sc->tx99_vif->drv_priv;
skb = alloc_skb(len, GFP_KERNEL);
if (!skb)
@@ -71,7 +77,7 @@ static struct sk_buff *ath9k_build_tx99_skb(struct ath_softc *sc)
memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN);
memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
- hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
+ hdr->seq_ctrl |= cpu_to_le16(avp->seq_no);
tx_info = IEEE80211_SKB_CB(skb);
memset(tx_info, 0, sizeof(*tx_info));
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 151ae49fa57e..d6e54a3c88f6 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -169,7 +169,10 @@ static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq,
if (txq->stopped &&
txq->pending_frames < sc->tx.txq_max_pending[q]) {
- ieee80211_wake_queue(sc->hw, info->hw_queue);
+ if (ath9k_is_chanctx_enabled())
+ ieee80211_wake_queue(sc->hw, info->hw_queue);
+ else
+ ieee80211_wake_queue(sc->hw, q);
txq->stopped = false;
}
}
@@ -2139,6 +2142,28 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
return bf;
}
+void ath_assign_seq(struct ath_common *common, struct sk_buff *skb)
+{
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_vif *vif = info->control.vif;
+ struct ath_vif *avp;
+
+ if (!(info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ))
+ return;
+
+ if (!vif)
+ return;
+
+ avp = (struct ath_vif *)vif->drv_priv;
+
+ if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
+ avp->seq_no += 0x10;
+
+ hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
+ hdr->seq_ctrl |= cpu_to_le16(avp->seq_no);
+}
+
static int ath_tx_prepare(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ath_tx_control *txctl)
{
@@ -2162,17 +2187,7 @@ static int ath_tx_prepare(struct ieee80211_hw *hw, struct sk_buff *skb,
if (info->control.hw_key)
frmlen += info->control.hw_key->icv_len;
- /*
- * As a temporary workaround, assign seq# here; this will likely need
- * to be cleaned up to work better with Beacon transmission and virtual
- * BSSes.
- */
- if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
- if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
- sc->tx.seq_no += 0x10;
- hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
- hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
- }
+ ath_assign_seq(ath9k_hw_common(sc->sc_ah), skb);
if ((vif && vif->type != NL80211_IFTYPE_AP &&
vif->type != NL80211_IFTYPE_AP_VLAN) ||
@@ -2235,7 +2250,10 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
fi->txq = q;
if (++txq->pending_frames > sc->tx.txq_max_pending[q] &&
!txq->stopped) {
- ieee80211_stop_queue(sc->hw, info->hw_queue);
+ if (ath9k_is_chanctx_enabled())
+ ieee80211_stop_queue(sc->hw, info->hw_queue);
+ else
+ ieee80211_stop_queue(sc->hw, q);
txq->stopped = true;
}
}
diff --git a/drivers/net/wireless/ath/main.c b/drivers/net/wireless/ath/main.c
index 83f47af19280..338d72337604 100644
--- a/drivers/net/wireless/ath/main.c
+++ b/drivers/net/wireless/ath/main.c
@@ -79,13 +79,13 @@ void ath_printk(const char *level, const struct ath_common* common,
vaf.fmt = fmt;
vaf.va = &args;
- if (common && common->hw && common->hw->wiphy)
+ if (common && common->hw && common->hw->wiphy) {
printk("%sath: %s: %pV",
level, wiphy_name(common->hw->wiphy), &vaf);
- else
+ trace_ath_log(common->hw->wiphy, &vaf);
+ } else {
printk("%sath: %pV", level, &vaf);
-
- trace_ath_log(common->hw->wiphy, &vaf);
+ }
va_end(args);
}
diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c
index 415393dfb6fc..06ea6cc9e30a 100644
--- a/drivers/net/wireless/ath/regd.c
+++ b/drivers/net/wireless/ath/regd.c
@@ -515,6 +515,7 @@ void ath_reg_notifier_apply(struct wiphy *wiphy,
if (!request)
return;
+ reg->region = request->dfs_region;
switch (request->initiator) {
case NL80211_REGDOM_SET_BY_CORE:
/*
@@ -779,6 +780,19 @@ u32 ath_regd_get_band_ctl(struct ath_regulatory *reg,
return SD_NO_CTL;
}
+ if (ath_regd_get_eepromRD(reg) == CTRY_DEFAULT) {
+ switch (reg->region) {
+ case NL80211_DFS_FCC:
+ return CTL_FCC;
+ case NL80211_DFS_ETSI:
+ return CTL_ETSI;
+ case NL80211_DFS_JP:
+ return CTL_MKK;
+ default:
+ break;
+ }
+ }
+
switch (band) {
case IEEE80211_BAND_2GHZ:
return reg->regpair->reg_2ghz_ctl;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index f55f625fd06b..d20d4e6f391a 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -670,7 +670,6 @@ static int brcmf_sdio_get_fwnames(struct brcmf_chip *ci,
struct brcmf_sdio_dev *sdiodev)
{
int i;
- uint fw_len, nv_len;
char end;
for (i = 0; i < ARRAY_SIZE(brcmf_fwname_data); i++) {
@@ -684,25 +683,25 @@ static int brcmf_sdio_get_fwnames(struct brcmf_chip *ci,
return -ENODEV;
}
- fw_len = sizeof(sdiodev->fw_name) - 1;
- nv_len = sizeof(sdiodev->nvram_name) - 1;
/* check if firmware path is provided by module parameter */
if (brcmf_firmware_path[0] != '\0') {
- strncpy(sdiodev->fw_name, brcmf_firmware_path, fw_len);
- strncpy(sdiodev->nvram_name, brcmf_firmware_path, nv_len);
- fw_len -= strlen(sdiodev->fw_name);
- nv_len -= strlen(sdiodev->nvram_name);
+ strlcpy(sdiodev->fw_name, brcmf_firmware_path,
+ sizeof(sdiodev->fw_name));
+ strlcpy(sdiodev->nvram_name, brcmf_firmware_path,
+ sizeof(sdiodev->nvram_name));
end = brcmf_firmware_path[strlen(brcmf_firmware_path) - 1];
if (end != '/') {
- strncat(sdiodev->fw_name, "/", fw_len);
- strncat(sdiodev->nvram_name, "/", nv_len);
- fw_len--;
- nv_len--;
+ strlcat(sdiodev->fw_name, "/",
+ sizeof(sdiodev->fw_name));
+ strlcat(sdiodev->nvram_name, "/",
+ sizeof(sdiodev->nvram_name));
}
}
- strncat(sdiodev->fw_name, brcmf_fwname_data[i].bin, fw_len);
- strncat(sdiodev->nvram_name, brcmf_fwname_data[i].nv, nv_len);
+ strlcat(sdiodev->fw_name, brcmf_fwname_data[i].bin,
+ sizeof(sdiodev->fw_name));
+ strlcat(sdiodev->nvram_name, brcmf_fwname_data[i].nv,
+ sizeof(sdiodev->nvram_name));
return 0;
}
diff --git a/drivers/net/wireless/hostap/hostap_proc.c b/drivers/net/wireless/hostap/hostap_proc.c
index 8efd17c52f65..dd84557cf957 100644
--- a/drivers/net/wireless/hostap/hostap_proc.c
+++ b/drivers/net/wireless/hostap/hostap_proc.c
@@ -168,7 +168,6 @@ static int prism2_bss_list_proc_show(struct seq_file *m, void *v)
local_info_t *local = m->private;
struct list_head *ptr = v;
struct hostap_bss_info *bss;
- int i;
if (ptr == &local->bss_list) {
seq_printf(m, "#BSSID\tlast_update\tcount\tcapab_info\tSSID(txt)\t"
@@ -181,9 +180,7 @@ static int prism2_bss_list_proc_show(struct seq_file *m, void *v)
bss->bssid, bss->last_update,
bss->count, bss->capab_info);
- for (i = 0; i < bss->ssid_len; i++)
- seq_putc(m,bss->ssid[i] >= 32 && bss->ssid[i] < 127 ?
- bss->ssid[i] : '_');
+ seq_printf(m, "%*pE", (int)bss->ssid_len, bss->ssid);
seq_putc(m, '\t');
seq_printf(m, "%*phN", (int)bss->ssid_len, bss->ssid);
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
index c3d726f334e3..6fabea0309dd 100644
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
@@ -2005,7 +2005,6 @@ static void isr_indicate_associated(struct ipw2100_priv *priv, u32 status)
u32 chan;
char *txratename;
u8 bssid[ETH_ALEN];
- DECLARE_SSID_BUF(ssid);
/*
* TBD: BSSID is usually 00:00:00:00:00:00 here and not
@@ -2067,8 +2066,8 @@ static void isr_indicate_associated(struct ipw2100_priv *priv, u32 status)
break;
}
- IPW_DEBUG_INFO("%s: Associated with '%s' at %s, channel %d (BSSID=%pM)\n",
- priv->net_dev->name, print_ssid(ssid, essid, essid_len),
+ IPW_DEBUG_INFO("%s: Associated with '%*pE' at %s, channel %d (BSSID=%pM)\n",
+ priv->net_dev->name, essid_len, essid,
txratename, chan, bssid);
/* now we copy read ssid into dev */
@@ -2095,9 +2094,8 @@ static int ipw2100_set_essid(struct ipw2100_priv *priv, char *essid,
.host_command_length = ssid_len
};
int err;
- DECLARE_SSID_BUF(ssid);
- IPW_DEBUG_HC("SSID: '%s'\n", print_ssid(ssid, essid, ssid_len));
+ IPW_DEBUG_HC("SSID: '%*pE'\n", ssid_len, essid);
if (ssid_len)
memcpy(cmd.host_command_parameters, essid, ssid_len);
@@ -2138,11 +2136,8 @@ static int ipw2100_set_essid(struct ipw2100_priv *priv, char *essid,
static void isr_indicate_association_lost(struct ipw2100_priv *priv, u32 status)
{
- DECLARE_SSID_BUF(ssid);
-
IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | IPW_DL_ASSOC,
- "disassociated: '%s' %pM\n",
- print_ssid(ssid, priv->essid, priv->essid_len),
+ "disassociated: '%*pE' %pM\n", priv->essid_len, priv->essid,
priv->bssid);
priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING);
@@ -6975,7 +6970,6 @@ static int ipw2100_wx_set_essid(struct net_device *dev,
char *essid = ""; /* ANY */
int length = 0;
int err = 0;
- DECLARE_SSID_BUF(ssid);
mutex_lock(&priv->action_mutex);
if (!(priv->status & STATUS_INITIALIZED)) {
@@ -7005,8 +6999,7 @@ static int ipw2100_wx_set_essid(struct net_device *dev,
goto done;
}
- IPW_DEBUG_WX("Setting ESSID: '%s' (%d)\n",
- print_ssid(ssid, essid, length), length);
+ IPW_DEBUG_WX("Setting ESSID: '%*pE' (%d)\n", length, essid, length);
priv->essid_len = length;
memcpy(priv->essid, essid, priv->essid_len);
@@ -7027,13 +7020,12 @@ static int ipw2100_wx_get_essid(struct net_device *dev,
*/
struct ipw2100_priv *priv = libipw_priv(dev);
- DECLARE_SSID_BUF(ssid);
/* If we are associated, trying to associate, or have a statically
* configured ESSID then return that; otherwise return ANY */
if (priv->config & CFG_STATIC_ESSID || priv->status & STATUS_ASSOCIATED) {
- IPW_DEBUG_WX("Getting essid: '%s'\n",
- print_ssid(ssid, priv->essid, priv->essid_len));
+ IPW_DEBUG_WX("Getting essid: '%*pE'\n",
+ priv->essid_len, priv->essid);
memcpy(extra, priv->essid, priv->essid_len);
wrqu->essid.length = priv->essid_len;
wrqu->essid.flags = 1; /* active */
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c
index f0c3c77a48d3..edc344334a75 100644
--- a/drivers/net/wireless/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/ipw2x00/ipw2200.c
@@ -4496,7 +4496,6 @@ static void handle_scan_event(struct ipw_priv *priv)
static void ipw_rx_notification(struct ipw_priv *priv,
struct ipw_rx_notification *notif)
{
- DECLARE_SSID_BUF(ssid);
u16 size = le16_to_cpu(notif->size);
IPW_DEBUG_NOTIF("type = %i (%d bytes)\n", notif->subtype, size);
@@ -4509,9 +4508,8 @@ static void ipw_rx_notification(struct ipw_priv *priv,
case CMAS_ASSOCIATED:{
IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
IPW_DL_ASSOC,
- "associated: '%s' %pM\n",
- print_ssid(ssid, priv->essid,
- priv->essid_len),
+ "associated: '%*pE' %pM\n",
+ priv->essid_len, priv->essid,
priv->bssid);
switch (priv->ieee->iw_mode) {
@@ -4585,14 +4583,9 @@ static void ipw_rx_notification(struct ipw_priv *priv,
IPW_DEBUG(IPW_DL_NOTIF |
IPW_DL_STATE |
IPW_DL_ASSOC,
- "deauthenticated: '%s' "
- "%pM"
- ": (0x%04X) - %s\n",
- print_ssid(ssid,
- priv->
- essid,
- priv->
- essid_len),
+ "deauthenticated: '%*pE' %pM: (0x%04X) - %s\n",
+ priv->essid_len,
+ priv->essid,
priv->bssid,
le16_to_cpu(auth->status),
ipw_get_status_code
@@ -4610,9 +4603,8 @@ static void ipw_rx_notification(struct ipw_priv *priv,
IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
IPW_DL_ASSOC,
- "authenticated: '%s' %pM\n",
- print_ssid(ssid, priv->essid,
- priv->essid_len),
+ "authenticated: '%*pE' %pM\n",
+ priv->essid_len, priv->essid,
priv->bssid);
break;
}
@@ -4638,9 +4630,8 @@ static void ipw_rx_notification(struct ipw_priv *priv,
IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
IPW_DL_ASSOC,
- "disassociated: '%s' %pM\n",
- print_ssid(ssid, priv->essid,
- priv->essid_len),
+ "disassociated: '%*pE' %pM\n",
+ priv->essid_len, priv->essid,
priv->bssid);
priv->status &=
@@ -4676,9 +4667,8 @@ static void ipw_rx_notification(struct ipw_priv *priv,
switch (auth->state) {
case CMAS_AUTHENTICATED:
IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE,
- "authenticated: '%s' %pM\n",
- print_ssid(ssid, priv->essid,
- priv->essid_len),
+ "authenticated: '%*pE' %pM\n",
+ priv->essid_len, priv->essid,
priv->bssid);
priv->status |= STATUS_AUTH;
break;
@@ -4695,9 +4685,8 @@ static void ipw_rx_notification(struct ipw_priv *priv,
}
IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
IPW_DL_ASSOC,
- "deauthenticated: '%s' %pM\n",
- print_ssid(ssid, priv->essid,
- priv->essid_len),
+ "deauthenticated: '%*pE' %pM\n",
+ priv->essid_len, priv->essid,
priv->bssid);
priv->status &= ~(STATUS_ASSOCIATING |
@@ -5516,16 +5505,13 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
int roaming)
{
struct ipw_supported_rates rates;
- DECLARE_SSID_BUF(ssid);
/* Verify that this network's capability is compatible with the
* current mode (AdHoc or Infrastructure) */
if ((priv->ieee->iw_mode == IW_MODE_ADHOC &&
!(network->capability & WLAN_CAPABILITY_IBSS))) {
- IPW_DEBUG_MERGE("Network '%s (%pM)' excluded due to "
- "capability mismatch.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded due to capability mismatch.\n",
+ network->ssid_len, network->ssid,
network->bssid);
return 0;
}
@@ -5536,10 +5522,8 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
if ((network->ssid_len != match->network->ssid_len) ||
memcmp(network->ssid, match->network->ssid,
network->ssid_len)) {
- IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
- "because of non-network ESSID.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of non-network ESSID.\n",
+ network->ssid_len, network->ssid,
network->bssid);
return 0;
}
@@ -5550,17 +5534,10 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
((network->ssid_len != priv->essid_len) ||
memcmp(network->ssid, priv->essid,
min(network->ssid_len, priv->essid_len)))) {
- char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
-
- strlcpy(escaped,
- print_ssid(ssid, network->ssid,
- network->ssid_len),
- sizeof(escaped));
- IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
- "because of ESSID mismatch: '%s'.\n",
- escaped, network->bssid,
- print_ssid(ssid, priv->essid,
- priv->essid_len));
+ IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of ESSID mismatch: '%*pE'.\n",
+ network->ssid_len, network->ssid,
+ network->bssid, priv->essid_len,
+ priv->essid);
return 0;
}
}
@@ -5569,26 +5546,20 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
* testing everything else. */
if (network->time_stamp[0] < match->network->time_stamp[0]) {
- IPW_DEBUG_MERGE("Network '%s excluded because newer than "
- "current network.\n",
- print_ssid(ssid, match->network->ssid,
- match->network->ssid_len));
+ IPW_DEBUG_MERGE("Network '%*pE excluded because newer than current network.\n",
+ match->network->ssid_len, match->network->ssid);
return 0;
} else if (network->time_stamp[1] < match->network->time_stamp[1]) {
- IPW_DEBUG_MERGE("Network '%s excluded because newer than "
- "current network.\n",
- print_ssid(ssid, match->network->ssid,
- match->network->ssid_len));
+ IPW_DEBUG_MERGE("Network '%*pE excluded because newer than current network.\n",
+ match->network->ssid_len, match->network->ssid);
return 0;
}
/* Now go through and see if the requested network is valid... */
if (priv->ieee->scan_age != 0 &&
time_after(jiffies, network->last_scanned + priv->ieee->scan_age)) {
- IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
- "because of age: %ums.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of age: %ums.\n",
+ network->ssid_len, network->ssid,
network->bssid,
jiffies_to_msecs(jiffies -
network->last_scanned));
@@ -5597,10 +5568,8 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
if ((priv->config & CFG_STATIC_CHANNEL) &&
(network->channel != priv->channel)) {
- IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
- "because of channel mismatch: %d != %d.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of channel mismatch: %d != %d.\n",
+ network->ssid_len, network->ssid,
network->bssid,
network->channel, priv->channel);
return 0;
@@ -5609,10 +5578,8 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
/* Verify privacy compatibility */
if (((priv->capability & CAP_PRIVACY_ON) ? 1 : 0) !=
((network->capability & WLAN_CAPABILITY_PRIVACY) ? 1 : 0)) {
- IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
- "because of privacy mismatch: %s != %s.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of privacy mismatch: %s != %s.\n",
+ network->ssid_len, network->ssid,
network->bssid,
priv->
capability & CAP_PRIVACY_ON ? "on" : "off",
@@ -5623,22 +5590,16 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
}
if (ether_addr_equal(network->bssid, priv->bssid)) {
- IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
- "because of the same BSSID match: %pM"
- ".\n", print_ssid(ssid, network->ssid,
- network->ssid_len),
- network->bssid,
- priv->bssid);
+ IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of the same BSSID match: %pM.\n",
+ network->ssid_len, network->ssid,
+ network->bssid, priv->bssid);
return 0;
}
/* Filter out any incompatible freq / mode combinations */
if (!libipw_is_valid_mode(priv->ieee, network->mode)) {
- IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
- "because of invalid frequency/mode "
- "combination.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of invalid frequency/mode combination.\n",
+ network->ssid_len, network->ssid,
network->bssid);
return 0;
}
@@ -5646,20 +5607,15 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
/* Ensure that the rates supported by the driver are compatible with
* this AP, including verification of basic rates (mandatory) */
if (!ipw_compatible_rates(priv, network, &rates)) {
- IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
- "because configured rate mask excludes "
- "AP mandatory rate.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because configured rate mask excludes AP mandatory rate.\n",
+ network->ssid_len, network->ssid,
network->bssid);
return 0;
}
if (rates.num_rates == 0) {
- IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
- "because of no compatible rates.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of no compatible rates.\n",
+ network->ssid_len, network->ssid,
network->bssid);
return 0;
}
@@ -5671,16 +5627,14 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
/* Set up 'new' AP to this network */
ipw_copy_rates(&match->rates, &rates);
match->network = network;
- IPW_DEBUG_MERGE("Network '%s (%pM)' is a viable match.\n",
- print_ssid(ssid, network->ssid, network->ssid_len),
- network->bssid);
+ IPW_DEBUG_MERGE("Network '%*pE (%pM)' is a viable match.\n",
+ network->ssid_len, network->ssid, network->bssid);
return 1;
}
static void ipw_merge_adhoc_network(struct work_struct *work)
{
- DECLARE_SSID_BUF(ssid);
struct ipw_priv *priv =
container_of(work, struct ipw_priv, merge_networks);
struct libipw_network *network = NULL;
@@ -5710,9 +5664,8 @@ static void ipw_merge_adhoc_network(struct work_struct *work)
mutex_lock(&priv->mutex);
if ((priv->ieee->iw_mode == IW_MODE_ADHOC)) {
- IPW_DEBUG_MERGE("remove network %s\n",
- print_ssid(ssid, priv->essid,
- priv->essid_len));
+ IPW_DEBUG_MERGE("remove network %*pE\n",
+ priv->essid_len, priv->essid);
ipw_remove_current_network(priv);
}
@@ -5728,7 +5681,6 @@ static int ipw_best_network(struct ipw_priv *priv,
struct libipw_network *network, int roaming)
{
struct ipw_supported_rates rates;
- DECLARE_SSID_BUF(ssid);
/* Verify that this network's capability is compatible with the
* current mode (AdHoc or Infrastructure) */
@@ -5736,10 +5688,8 @@ static int ipw_best_network(struct ipw_priv *priv,
!(network->capability & WLAN_CAPABILITY_ESS)) ||
(priv->ieee->iw_mode == IW_MODE_ADHOC &&
!(network->capability & WLAN_CAPABILITY_IBSS))) {
- IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded due to "
- "capability mismatch.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded due to capability mismatch.\n",
+ network->ssid_len, network->ssid,
network->bssid);
return 0;
}
@@ -5750,10 +5700,8 @@ static int ipw_best_network(struct ipw_priv *priv,
if ((network->ssid_len != match->network->ssid_len) ||
memcmp(network->ssid, match->network->ssid,
network->ssid_len)) {
- IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
- "because of non-network ESSID.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of non-network ESSID.\n",
+ network->ssid_len, network->ssid,
network->bssid);
return 0;
}
@@ -5764,16 +5712,10 @@ static int ipw_best_network(struct ipw_priv *priv,
((network->ssid_len != priv->essid_len) ||
memcmp(network->ssid, priv->essid,
min(network->ssid_len, priv->essid_len)))) {
- char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
- strlcpy(escaped,
- print_ssid(ssid, network->ssid,
- network->ssid_len),
- sizeof(escaped));
- IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
- "because of ESSID mismatch: '%s'.\n",
- escaped, network->bssid,
- print_ssid(ssid, priv->essid,
- priv->essid_len));
+ IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of ESSID mismatch: '%*pE'.\n",
+ network->ssid_len, network->ssid,
+ network->bssid, priv->essid_len,
+ priv->essid);
return 0;
}
}
@@ -5781,16 +5723,10 @@ static int ipw_best_network(struct ipw_priv *priv,
/* If the old network rate is better than this one, don't bother
* testing everything else. */
if (match->network && match->network->stats.rssi > network->stats.rssi) {
- char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
- strlcpy(escaped,
- print_ssid(ssid, network->ssid, network->ssid_len),
- sizeof(escaped));
- IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded because "
- "'%s (%pM)' has a stronger signal.\n",
- escaped, network->bssid,
- print_ssid(ssid, match->network->ssid,
- match->network->ssid_len),
- match->network->bssid);
+ IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because '%*pE (%pM)' has a stronger signal.\n",
+ network->ssid_len, network->ssid,
+ network->bssid, match->network->ssid_len,
+ match->network->ssid, match->network->bssid);
return 0;
}
@@ -5798,11 +5734,8 @@ static int ipw_best_network(struct ipw_priv *priv,
* last 3 seconds, do not try and associate again... */
if (network->last_associate &&
time_after(network->last_associate + (HZ * 3UL), jiffies)) {
- IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
- "because of storming (%ums since last "
- "assoc attempt).\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of storming (%ums since last assoc attempt).\n",
+ network->ssid_len, network->ssid,
network->bssid,
jiffies_to_msecs(jiffies -
network->last_associate));
@@ -5812,10 +5745,8 @@ static int ipw_best_network(struct ipw_priv *priv,
/* Now go through and see if the requested network is valid... */
if (priv->ieee->scan_age != 0 &&
time_after(jiffies, network->last_scanned + priv->ieee->scan_age)) {
- IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
- "because of age: %ums.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of age: %ums.\n",
+ network->ssid_len, network->ssid,
network->bssid,
jiffies_to_msecs(jiffies -
network->last_scanned));
@@ -5824,10 +5755,8 @@ static int ipw_best_network(struct ipw_priv *priv,
if ((priv->config & CFG_STATIC_CHANNEL) &&
(network->channel != priv->channel)) {
- IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
- "because of channel mismatch: %d != %d.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of channel mismatch: %d != %d.\n",
+ network->ssid_len, network->ssid,
network->bssid,
network->channel, priv->channel);
return 0;
@@ -5836,10 +5765,8 @@ static int ipw_best_network(struct ipw_priv *priv,
/* Verify privacy compatibility */
if (((priv->capability & CAP_PRIVACY_ON) ? 1 : 0) !=
((network->capability & WLAN_CAPABILITY_PRIVACY) ? 1 : 0)) {
- IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
- "because of privacy mismatch: %s != %s.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of privacy mismatch: %s != %s.\n",
+ network->ssid_len, network->ssid,
network->bssid,
priv->capability & CAP_PRIVACY_ON ? "on" :
"off",
@@ -5850,31 +5777,24 @@ static int ipw_best_network(struct ipw_priv *priv,
if ((priv->config & CFG_STATIC_BSSID) &&
!ether_addr_equal(network->bssid, priv->bssid)) {
- IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
- "because of BSSID mismatch: %pM.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of BSSID mismatch: %pM.\n",
+ network->ssid_len, network->ssid,
network->bssid, priv->bssid);
return 0;
}
/* Filter out any incompatible freq / mode combinations */
if (!libipw_is_valid_mode(priv->ieee, network->mode)) {
- IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
- "because of invalid frequency/mode "
- "combination.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of invalid frequency/mode combination.\n",
+ network->ssid_len, network->ssid,
network->bssid);
return 0;
}
/* Filter out invalid channel in current GEO */
if (!libipw_is_valid_channel(priv->ieee, network->channel)) {
- IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
- "because of invalid channel in current GEO\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of invalid channel in current GEO\n",
+ network->ssid_len, network->ssid,
network->bssid);
return 0;
}
@@ -5882,20 +5802,15 @@ static int ipw_best_network(struct ipw_priv *priv,
/* Ensure that the rates supported by the driver are compatible with
* this AP, including verification of basic rates (mandatory) */
if (!ipw_compatible_rates(priv, network, &rates)) {
- IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
- "because configured rate mask excludes "
- "AP mandatory rate.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because configured rate mask excludes AP mandatory rate.\n",
+ network->ssid_len, network->ssid,
network->bssid);
return 0;
}
if (rates.num_rates == 0) {
- IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
- "because of no compatible rates.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
+ IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of no compatible rates.\n",
+ network->ssid_len, network->ssid,
network->bssid);
return 0;
}
@@ -5908,9 +5823,8 @@ static int ipw_best_network(struct ipw_priv *priv,
ipw_copy_rates(&match->rates, &rates);
match->network = network;
- IPW_DEBUG_ASSOC("Network '%s (%pM)' is a viable match.\n",
- print_ssid(ssid, network->ssid, network->ssid_len),
- network->bssid);
+ IPW_DEBUG_ASSOC("Network '%*pE (%pM)' is a viable match.\n",
+ network->ssid_len, network->ssid, network->bssid);
return 1;
}
@@ -6152,7 +6066,6 @@ static void ipw_bg_adhoc_check(struct work_struct *work)
static void ipw_debug_config(struct ipw_priv *priv)
{
- DECLARE_SSID_BUF(ssid);
IPW_DEBUG_INFO("Scan completed, no valid APs matched "
"[CFG 0x%08X]\n", priv->config);
if (priv->config & CFG_STATIC_CHANNEL)
@@ -6160,8 +6073,8 @@ static void ipw_debug_config(struct ipw_priv *priv)
else
IPW_DEBUG_INFO("Channel unlocked.\n");
if (priv->config & CFG_STATIC_ESSID)
- IPW_DEBUG_INFO("ESSID locked to '%s'\n",
- print_ssid(ssid, priv->essid, priv->essid_len));
+ IPW_DEBUG_INFO("ESSID locked to '%*pE'\n",
+ priv->essid_len, priv->essid);
else
IPW_DEBUG_INFO("ESSID unlocked.\n");
if (priv->config & CFG_STATIC_BSSID)
@@ -7385,7 +7298,6 @@ static int ipw_associate_network(struct ipw_priv *priv,
struct ipw_supported_rates *rates, int roaming)
{
int err;
- DECLARE_SSID_BUF(ssid);
if (priv->config & CFG_FIXED_RATE)
ipw_set_fixed_rate(priv, network->mode);
@@ -7451,10 +7363,9 @@ static int ipw_associate_network(struct ipw_priv *priv,
priv->assoc_request.capability &=
~cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME);
- IPW_DEBUG_ASSOC("%ssociation attempt: '%s', channel %d, "
- "802.11%c [%d], %s[:%s], enc=%s%s%s%c%c\n",
+ IPW_DEBUG_ASSOC("%ssociation attempt: '%*pE', channel %d, 802.11%c [%d], %s[:%s], enc=%s%s%s%c%c\n",
roaming ? "Rea" : "A",
- print_ssid(ssid, priv->essid, priv->essid_len),
+ priv->essid_len, priv->essid,
network->channel,
ipw_modes[priv->assoc_request.ieee_mode],
rates->num_rates,
@@ -7553,9 +7464,8 @@ static int ipw_associate_network(struct ipw_priv *priv,
return err;
}
- IPW_DEBUG(IPW_DL_STATE, "associating: '%s' %pM\n",
- print_ssid(ssid, priv->essid, priv->essid_len),
- priv->bssid);
+ IPW_DEBUG(IPW_DL_STATE, "associating: '%*pE' %pM\n",
+ priv->essid_len, priv->essid, priv->bssid);
return 0;
}
@@ -7645,7 +7555,6 @@ static int ipw_associate(void *data)
struct ipw_supported_rates *rates;
struct list_head *element;
unsigned long flags;
- DECLARE_SSID_BUF(ssid);
if (priv->ieee->iw_mode == IW_MODE_MONITOR) {
IPW_DEBUG_ASSOC("Not attempting association (monitor mode)\n");
@@ -7704,10 +7613,8 @@ static int ipw_associate(void *data)
/* If there are no more slots, expire the oldest */
list_del(&oldest->list);
target = oldest;
- IPW_DEBUG_ASSOC("Expired '%s' (%pM) from "
- "network list.\n",
- print_ssid(ssid, target->ssid,
- target->ssid_len),
+ IPW_DEBUG_ASSOC("Expired '%*pE' (%pM) from network list.\n",
+ target->ssid_len, target->ssid,
target->bssid);
list_add_tail(&target->list,
&priv->ieee->network_free_list);
@@ -9093,7 +9000,6 @@ static int ipw_wx_set_essid(struct net_device *dev,
{
struct ipw_priv *priv = libipw_priv(dev);
int length;
- DECLARE_SSID_BUF(ssid);
mutex_lock(&priv->mutex);
@@ -9118,8 +9024,7 @@ static int ipw_wx_set_essid(struct net_device *dev,
return 0;
}
- IPW_DEBUG_WX("Setting ESSID: '%s' (%d)\n",
- print_ssid(ssid, extra, length), length);
+ IPW_DEBUG_WX("Setting ESSID: '%*pE' (%d)\n", length, extra, length);
priv->essid_len = length;
memcpy(priv->essid, extra, priv->essid_len);
@@ -9138,15 +9043,14 @@ static int ipw_wx_get_essid(struct net_device *dev,
union iwreq_data *wrqu, char *extra)
{
struct ipw_priv *priv = libipw_priv(dev);
- DECLARE_SSID_BUF(ssid);
/* If we are associated, trying to associate, or have a statically
* configured ESSID then return that; otherwise return ANY */
mutex_lock(&priv->mutex);
if (priv->config & CFG_STATIC_ESSID ||
priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) {
- IPW_DEBUG_WX("Getting essid: '%s'\n",
- print_ssid(ssid, priv->essid, priv->essid_len));
+ IPW_DEBUG_WX("Getting essid: '%*pE'\n",
+ priv->essid_len, priv->essid);
memcpy(extra, priv->essid, priv->essid_len);
wrqu->essid.length = priv->essid_len;
wrqu->essid.flags = 1; /* active */
diff --git a/drivers/net/wireless/ipw2x00/libipw_rx.c b/drivers/net/wireless/ipw2x00/libipw_rx.c
index a586a85bfcfe..2d66984079bb 100644
--- a/drivers/net/wireless/ipw2x00/libipw_rx.c
+++ b/drivers/net/wireless/ipw2x00/libipw_rx.c
@@ -1120,7 +1120,6 @@ static int libipw_parse_info_param(struct libipw_info_element
*info_element, u16 length,
struct libipw_network *network)
{
- DECLARE_SSID_BUF(ssid);
u8 i;
#ifdef CONFIG_LIBIPW_DEBUG
char rates_str[64];
@@ -1151,10 +1150,9 @@ static int libipw_parse_info_param(struct libipw_info_element
memset(network->ssid + network->ssid_len, 0,
IW_ESSID_MAX_SIZE - network->ssid_len);
- LIBIPW_DEBUG_MGMT("WLAN_EID_SSID: '%s' len=%d.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
- network->ssid_len);
+ LIBIPW_DEBUG_MGMT("WLAN_EID_SSID: '%*pE' len=%d.\n",
+ network->ssid_len, network->ssid,
+ network->ssid_len);
break;
case WLAN_EID_SUPP_RATES:
@@ -1399,8 +1397,6 @@ static int libipw_network_init(struct libipw_device *ieee, struct libipw_probe_r
struct libipw_network *network,
struct libipw_rx_stats *stats)
{
- DECLARE_SSID_BUF(ssid);
-
network->qos_data.active = 0;
network->qos_data.supported = 0;
network->qos_data.param_count = 0;
@@ -1447,11 +1443,9 @@ static int libipw_network_init(struct libipw_device *ieee, struct libipw_probe_r
}
if (network->mode == 0) {
- LIBIPW_DEBUG_SCAN("Filtered out '%s (%pM)' "
- "network.\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
- network->bssid);
+ LIBIPW_DEBUG_SCAN("Filtered out '%*pE (%pM)' network.\n",
+ network->ssid_len, network->ssid,
+ network->bssid);
return 1;
}
@@ -1563,11 +1557,9 @@ static void libipw_process_probe_response(struct libipw_device
struct libipw_info_element *info_element = beacon->info_element;
#endif
unsigned long flags;
- DECLARE_SSID_BUF(ssid);
- LIBIPW_DEBUG_SCAN("'%s' (%pM"
- "): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
- print_ssid(ssid, info_element->data, info_element->len),
+ LIBIPW_DEBUG_SCAN("'%*pE' (%pM): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
+ info_element->len, info_element->data,
beacon->header.addr3,
(beacon->capability & cpu_to_le16(1 << 0xf)) ? '1' : '0',
(beacon->capability & cpu_to_le16(1 << 0xe)) ? '1' : '0',
@@ -1587,12 +1579,11 @@ static void libipw_process_probe_response(struct libipw_device
(beacon->capability & cpu_to_le16(1 << 0x0)) ? '1' : '0');
if (libipw_network_init(ieee, beacon, &network, stats)) {
- LIBIPW_DEBUG_SCAN("Dropped '%s' (%pM) via %s.\n",
- print_ssid(ssid, info_element->data,
- info_element->len),
- beacon->header.addr3,
- is_beacon(beacon->header.frame_ctl) ?
- "BEACON" : "PROBE RESPONSE");
+ LIBIPW_DEBUG_SCAN("Dropped '%*pE' (%pM) via %s.\n",
+ info_element->len, info_element->data,
+ beacon->header.addr3,
+ is_beacon(beacon->header.frame_ctl) ?
+ "BEACON" : "PROBE RESPONSE");
return;
}
@@ -1624,11 +1615,9 @@ static void libipw_process_probe_response(struct libipw_device
/* If there are no more slots, expire the oldest */
list_del(&oldest->list);
target = oldest;
- LIBIPW_DEBUG_SCAN("Expired '%s' (%pM) from "
- "network list.\n",
- print_ssid(ssid, target->ssid,
- target->ssid_len),
- target->bssid);
+ LIBIPW_DEBUG_SCAN("Expired '%*pE' (%pM) from network list.\n",
+ target->ssid_len, target->ssid,
+ target->bssid);
libipw_network_reset(target);
} else {
/* Otherwise just pull from the free list */
@@ -1638,23 +1627,21 @@ static void libipw_process_probe_response(struct libipw_device
}
#ifdef CONFIG_LIBIPW_DEBUG
- LIBIPW_DEBUG_SCAN("Adding '%s' (%pM) via %s.\n",
- print_ssid(ssid, network.ssid,
- network.ssid_len),
- network.bssid,
- is_beacon(beacon->header.frame_ctl) ?
- "BEACON" : "PROBE RESPONSE");
+ LIBIPW_DEBUG_SCAN("Adding '%*pE' (%pM) via %s.\n",
+ network.ssid_len, network.ssid,
+ network.bssid,
+ is_beacon(beacon->header.frame_ctl) ?
+ "BEACON" : "PROBE RESPONSE");
#endif
memcpy(target, &network, sizeof(*target));
network.ibss_dfs = NULL;
list_add_tail(&target->list, &ieee->network_list);
} else {
- LIBIPW_DEBUG_SCAN("Updating '%s' (%pM) via %s.\n",
- print_ssid(ssid, target->ssid,
- target->ssid_len),
- target->bssid,
- is_beacon(beacon->header.frame_ctl) ?
- "BEACON" : "PROBE RESPONSE");
+ LIBIPW_DEBUG_SCAN("Updating '%*pE' (%pM) via %s.\n",
+ target->ssid_len, target->ssid,
+ target->bssid,
+ is_beacon(beacon->header.frame_ctl) ?
+ "BEACON" : "PROBE RESPONSE");
update_network(target, &network);
network.ibss_dfs = NULL;
}
diff --git a/drivers/net/wireless/ipw2x00/libipw_wx.c b/drivers/net/wireless/ipw2x00/libipw_wx.c
index 54aba4744438..dd29f46d086b 100644
--- a/drivers/net/wireless/ipw2x00/libipw_wx.c
+++ b/drivers/net/wireless/ipw2x00/libipw_wx.c
@@ -272,7 +272,6 @@ int libipw_wx_get_scan(struct libipw_device *ieee,
char *ev = extra;
char *stop = ev + wrqu->data.length;
int i = 0;
- DECLARE_SSID_BUF(ssid);
LIBIPW_DEBUG_WX("Getting scan\n");
@@ -290,12 +289,10 @@ int libipw_wx_get_scan(struct libipw_device *ieee,
ev = libipw_translate_scan(ieee, ev, stop, network,
info);
else {
- LIBIPW_DEBUG_SCAN("Not showing network '%s ("
- "%pM)' due to age (%ums).\n",
- print_ssid(ssid, network->ssid,
- network->ssid_len),
- network->bssid,
- elapsed_jiffies_msecs(
+ LIBIPW_DEBUG_SCAN("Not showing network '%*pE (%pM)' due to age (%ums).\n",
+ network->ssid_len, network->ssid,
+ network->bssid,
+ elapsed_jiffies_msecs(
network->last_scanned));
}
}
@@ -322,7 +319,6 @@ int libipw_wx_set_encode(struct libipw_device *ieee,
int i, key, key_provided, len;
struct lib80211_crypt_data **crypt;
int host_crypto = ieee->host_encrypt || ieee->host_decrypt;
- DECLARE_SSID_BUF(ssid);
LIBIPW_DEBUG_WX("SET_ENCODE\n");
@@ -417,8 +413,8 @@ int libipw_wx_set_encode(struct libipw_device *ieee,
if (len > erq->length)
memset(sec.keys[key] + erq->length, 0,
len - erq->length);
- LIBIPW_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
- key, print_ssid(ssid, sec.keys[key], len),
+ LIBIPW_DEBUG_WX("Setting key %d to '%*pE' (%d:%d bytes)\n",
+ key, len, sec.keys[key],
erq->length, len);
sec.key_sizes[key] = len;
if (*crypt)
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
index 818b1edaaa9a..34f09ef90bb3 100644
--- a/drivers/net/wireless/libertas/cfg.c
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -590,7 +590,6 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
int chan_no = -1;
const u8 *ssid = NULL;
u8 ssid_len = 0;
- DECLARE_SSID_BUF(ssid_buf);
int len = get_unaligned_le16(pos);
pos += 2;
@@ -644,10 +643,8 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
struct ieee80211_channel *channel =
ieee80211_get_channel(wiphy, freq);
- lbs_deb_scan("scan: %pM, capa %04x, chan %2d, %s, "
- "%d dBm\n",
- bssid, capa, chan_no,
- print_ssid(ssid_buf, ssid, ssid_len),
+ lbs_deb_scan("scan: %pM, capa %04x, chan %2d, %*pE, %d dBm\n",
+ bssid, capa, chan_no, ssid_len, ssid,
LBS_SCAN_RSSI_TO_MBM(rssi)/100);
if (channel &&
@@ -1984,7 +1981,6 @@ static int lbs_join_ibss(struct wiphy *wiphy, struct net_device *dev,
struct lbs_private *priv = wiphy_priv(wiphy);
int ret = 0;
struct cfg80211_bss *bss;
- DECLARE_SSID_BUF(ssid_buf);
if (dev == priv->mesh_dev)
return -EOPNOTSUPP;
diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c
index 01a67f62696f..d0c881dd5846 100644
--- a/drivers/net/wireless/libertas/mesh.c
+++ b/drivers/net/wireless/libertas/mesh.c
@@ -93,7 +93,6 @@ static int lbs_mesh_config(struct lbs_private *priv, uint16_t action,
{
struct cmd_ds_mesh_config cmd;
struct mrvl_meshie *ie;
- DECLARE_SSID_BUF(ssid);
memset(&cmd, 0, sizeof(cmd));
cmd.channel = cpu_to_le16(chan);
@@ -122,9 +121,9 @@ static int lbs_mesh_config(struct lbs_private *priv, uint16_t action,
default:
return -1;
}
- lbs_deb_cmd("mesh config action %d type %x channel %d SSID %s\n",
- action, priv->mesh_tlv, chan,
- print_ssid(ssid, priv->mesh_ssid, priv->mesh_ssid_len));
+ lbs_deb_cmd("mesh config action %d type %x channel %d SSID %*pE\n",
+ action, priv->mesh_tlv, chan, priv->mesh_ssid_len,
+ priv->mesh_ssid);
return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv);
}
diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c
index ded967aa6ecb..706b844bce00 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c
@@ -742,35 +742,49 @@ static void rtl8180_int_disable(struct ieee80211_hw *dev)
}
static void rtl8180_conf_basic_rates(struct ieee80211_hw *dev,
- u32 rates_mask)
+ u32 basic_mask)
{
struct rtl8180_priv *priv = dev->priv;
-
- u8 max, min;
u16 reg;
-
- max = fls(rates_mask) - 1;
- min = ffs(rates_mask) - 1;
+ u32 resp_mask;
+ u8 basic_max;
+ u8 resp_max, resp_min;
+
+ resp_mask = basic_mask;
+ /* IEEE80211 says the response rate should be equal to the highest basic
+ * rate that is not faster than received frame. But it says also that if
+ * the basic rate set does not contains any rate for the current
+ * modulation class then mandatory rate set must be used for that
+ * modulation class. Eventually add OFDM mandatory rates..
+ */
+ if ((resp_mask & 0xf) == resp_mask)
+ resp_mask |= 0x150; /* 6, 12, 24Mbps */
switch (priv->chip_family) {
case RTL818X_CHIP_FAMILY_RTL8180:
/* in 8180 this is NOT a BITMAP */
+ basic_max = fls(basic_mask) - 1;
reg = rtl818x_ioread16(priv, &priv->map->BRSR);
reg &= ~3;
- reg |= max;
+ reg |= basic_max;
rtl818x_iowrite16(priv, &priv->map->BRSR, reg);
break;
case RTL818X_CHIP_FAMILY_RTL8185:
+ resp_max = fls(resp_mask) - 1;
+ resp_min = ffs(resp_mask) - 1;
/* in 8185 this is a BITMAP */
- rtl818x_iowrite16(priv, &priv->map->BRSR, rates_mask);
- rtl818x_iowrite8(priv, &priv->map->RESP_RATE, (max << 4) | min);
+ rtl818x_iowrite16(priv, &priv->map->BRSR, basic_mask);
+ rtl818x_iowrite8(priv, &priv->map->RESP_RATE, (resp_max << 4) |
+ resp_min);
break;
case RTL818X_CHIP_FAMILY_RTL8187SE:
- /* in 8187se this is a BITMAP */
- rtl818x_iowrite16(priv, &priv->map->BRSR_8187SE, rates_mask);
+ /* in 8187se this is a BITMAP. BRSR reg actually sets
+ * response rates.
+ */
+ rtl818x_iowrite16(priv, &priv->map->BRSR_8187SE, resp_mask);
break;
}
}
diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c
index 58ba71830886..40b6d1d006d7 100644
--- a/drivers/net/wireless/rtlwifi/base.c
+++ b/drivers/net/wireless/rtlwifi/base.c
@@ -467,7 +467,7 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw)
rtl_easy_concurrent_retrytimer_callback, (unsigned long)hw);
/* <2> work queue */
rtlpriv->works.hw = hw;
- rtlpriv->works.rtl_wq = alloc_workqueue(rtlpriv->cfg->name, 0, 0);
+ rtlpriv->works.rtl_wq = alloc_workqueue("%s", 0, 0, rtlpriv->cfg->name);
INIT_DELAYED_WORK(&rtlpriv->works.watchdog_wq,
(void *)rtl_watchdog_wq_callback);
INIT_DELAYED_WORK(&rtlpriv->works.ips_nic_off_wq,
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c
index 667aba81246c..25daa8715219 100644
--- a/drivers/net/wireless/rtlwifi/pci.c
+++ b/drivers/net/wireless/rtlwifi/pci.c
@@ -1796,7 +1796,8 @@ static int rtl_pci_start(struct ieee80211_hw *hw)
rtl_pci_reset_trx_ring(hw);
rtlpci->driver_is_goingto_unload = false;
- if (rtlpriv->cfg->ops->get_btc_status()) {
+ if (rtlpriv->cfg->ops->get_btc_status &&
+ rtlpriv->cfg->ops->get_btc_status()) {
rtlpriv->btcoexist.btc_ops->btc_init_variables(rtlpriv);
rtlpriv->btcoexist.btc_ops->btc_init_hal_vars(rtlpriv);
}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
index a00861b26ece..29983bc96a89 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
@@ -656,7 +656,8 @@ static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
-void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
+void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw,
+ bool (*cmd_send_packet)(struct ieee80211_hw *, struct sk_buff *))
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
@@ -722,7 +723,10 @@ void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
memcpy((u8 *)skb_put(skb, totalpacketlen),
&reserved_page_packet, totalpacketlen);
- rtstatus = rtl_cmd_send_packet(hw, skb);
+ if (cmd_send_packet)
+ rtstatus = cmd_send_packet(hw, skb);
+ else
+ rtstatus = rtl_cmd_send_packet(hw, skb);
if (rtstatus)
b_dlok = true;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h
index a815bd6273da..b64ae45dc674 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h
@@ -109,7 +109,9 @@ void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id,
u32 cmd_len, u8 *p_cmdbuffer);
void rtl92c_firmware_selfreset(struct ieee80211_hw *hw);
void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode);
-void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished);
+void rtl92c_set_fw_rsvdpagepkt
+ (struct ieee80211_hw *hw,
+ bool (*cmd_send_packet)(struct ieee80211_hw *, struct sk_buff *));
void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus);
void usb_writeN_async(struct rtl_priv *rtlpriv, u32 addr, void *data, u16 len);
void rtl92c_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
index 8ec0f031f48a..55357d69397a 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
@@ -459,7 +459,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2,
tmp_reg422 & (~BIT(6)));
- rtl92c_set_fw_rsvdpagepkt(hw, 0);
+ rtl92c_set_fw_rsvdpagepkt(hw, NULL);
_rtl92ce_set_bcn_ctrl_reg(hw, BIT(3), 0);
_rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(4));
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
index 04aa0b5f5b3d..873363acbacf 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
@@ -1592,6 +1592,20 @@ void rtl92cu_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
}
}
+bool usb_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+ /* Currently nothing happens here.
+ * Traffic stops after some seconds in WPA2 802.11n mode.
+ * Maybe because rtl8192cu chip should be set from here?
+ * If I understand correctly, the realtek vendor driver sends some urbs
+ * if its "here".
+ *
+ * This is maybe necessary:
+ * rtlpriv->cfg->ops->fill_tx_cmddesc(hw, buffer, 1, 1, skb);
+ */
+ return true;
+}
+
void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -1939,7 +1953,8 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
recover = true;
rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2,
tmp_reg422 & (~BIT(6)));
- rtl92c_set_fw_rsvdpagepkt(hw, 0);
+ rtl92c_set_fw_rsvdpagepkt(hw,
+ &usb_cmd_send_packet);
_rtl92cu_set_bcn_ctrl_reg(hw, BIT(3), 0);
_rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(4));
if (recover)
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h
index 0f7812e0c8aa..c1e33b0228c0 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h
@@ -104,7 +104,6 @@ bool rtl92cu_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid);
void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid);
int rtl92c_download_fw(struct ieee80211_hw *hw);
void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode);
-void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished);
void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus);
void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw,
u8 element_id, u32 cmd_len, u8 *p_cmdbuffer);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
index 7c5fbaf5fee0..e06bafee37f9 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
@@ -101,6 +101,12 @@ static void rtl92cu_deinit_sw_vars(struct ieee80211_hw *hw)
}
}
+/* get bt coexist status */
+static bool rtl92cu_get_btc_status(void)
+{
+ return false;
+}
+
static struct rtl_hal_ops rtl8192cu_hal_ops = {
.init_sw_vars = rtl92cu_init_sw_vars,
.deinit_sw_vars = rtl92cu_deinit_sw_vars,
@@ -148,6 +154,7 @@ static struct rtl_hal_ops rtl8192cu_hal_ops = {
.phy_set_bw_mode_callback = rtl92cu_phy_set_bw_mode_callback,
.dm_dynamic_txpower = rtl92cu_dm_dynamic_txpower,
.fill_h2c_cmd = rtl92c_fill_h2c_cmd,
+ .get_btc_status = rtl92cu_get_btc_status,
};
static struct rtl_mod_params rtl92cu_mod_params = {
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c
index dfdc9b20e4ad..1a87edca2c3f 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c
@@ -362,7 +362,7 @@ void rtl92ee_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
}
break;
default:
- RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG,
"switch case not process %x\n", variable);
break;
}
@@ -591,7 +591,7 @@ void rtl92ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
acm_ctrl &= (~ACMHW_BEQEN);
break;
default:
- RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG,
"switch case not process\n");
break;
}
@@ -710,7 +710,7 @@ void rtl92ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
}
break;
default:
- RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG,
"switch case not process %x\n", variable);
break;
}
@@ -2424,7 +2424,7 @@ void rtl92ee_set_key(struct ieee80211_hw *hw, u32 key_index,
enc_algo = CAM_AES;
break;
default:
- RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG,
"switch case not process\n");
enc_algo = CAM_TKIP;
break;
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/phy.c b/drivers/net/wireless/rtlwifi/rtl8821ae/phy.c
index 9786313dc62f..1e9570fa874f 100644
--- a/drivers/net/wireless/rtlwifi/rtl8821ae/phy.c
+++ b/drivers/net/wireless/rtlwifi/rtl8821ae/phy.c
@@ -1889,15 +1889,18 @@ static void _rtl8821ae_store_tx_power_by_rate(struct ieee80211_hw *hw,
struct rtl_phy *rtlphy = &rtlpriv->phy;
u8 rate_section = _rtl8821ae_get_rate_section_index(regaddr);
- if (band != BAND_ON_2_4G && band != BAND_ON_5G)
+ if (band != BAND_ON_2_4G && band != BAND_ON_5G) {
RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, "Invalid Band %d\n", band);
-
- if (rfpath >= MAX_RF_PATH)
+ band = BAND_ON_2_4G;
+ }
+ if (rfpath >= MAX_RF_PATH) {
RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, "Invalid RfPath %d\n", rfpath);
-
- if (txnum >= MAX_RF_PATH)
+ rfpath = MAX_RF_PATH - 1;
+ }
+ if (txnum >= MAX_RF_PATH) {
RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, "Invalid TxNum %d\n", txnum);
-
+ txnum = MAX_RF_PATH - 1;
+ }
rtlphy->tx_power_by_rate_offset[band][rfpath][txnum][rate_section] = data;
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"TxPwrByRateOffset[Band %d][RfPath %d][TxNum %d][RateSection %d] = 0x%x\n",
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c
index 10cf69c4bc42..46ee956d0235 100644
--- a/drivers/net/wireless/rtlwifi/usb.c
+++ b/drivers/net/wireless/rtlwifi/usb.c
@@ -1117,7 +1117,18 @@ int rtl_usb_probe(struct usb_interface *intf,
}
rtlpriv->cfg->ops->init_sw_leds(hw);
+ err = ieee80211_register_hw(hw);
+ if (err) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ "Can't register mac80211 hw.\n");
+ err = -ENODEV;
+ goto error_out;
+ }
+ rtlpriv->mac80211.mac80211_registered = 1;
+
+ set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status);
return 0;
+
error_out:
rtl_deinit_core(hw);
_rtl_usb_io_handler_release(hw);
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h
index 976667ae8549..6866dcf24340 100644
--- a/drivers/net/wireless/rtlwifi/wifi.h
+++ b/drivers/net/wireless/rtlwifi/wifi.h
@@ -1370,7 +1370,7 @@ struct rtl_mac {
bool rdg_en;
/*AP*/
- u8 bssid[6];
+ u8 bssid[ETH_ALEN] __aligned(2);
u32 vendor;
u8 mcs[16]; /* 16 bytes mcs for HT rates. */
u32 basic_rates; /* b/g rates */
diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c
index 9c47b897b6d2..8079c31ac5e6 100644
--- a/drivers/net/xen-netback/xenbus.c
+++ b/drivers/net/xen-netback/xenbus.c
@@ -937,22 +937,18 @@ static int read_xenbus_vif_flags(struct backend_info *be)
return 0;
}
-
-/* ** Driver Registration ** */
-
-
static const struct xenbus_device_id netback_ids[] = {
{ "vif" },
{ "" }
};
-
-static DEFINE_XENBUS_DRIVER(netback, ,
+static struct xenbus_driver netback_driver = {
+ .ids = netback_ids,
.probe = netback_probe,
.remove = netback_remove,
.uevent = netback_uevent,
.otherend_changed = frontend_changed,
-);
+};
int xenvif_xenbus_init(void)
{
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index ca82f545ec2c..cca871346a0f 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -638,7 +638,7 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (unlikely(!netif_carrier_ok(dev) ||
(slots > 1 && !xennet_can_sg(dev)) ||
- netif_needs_gso(skb, netif_skb_features(skb)))) {
+ netif_needs_gso(dev, skb, netif_skb_features(skb)))) {
spin_unlock_irqrestore(&queue->tx_lock, flags);
goto drop;
}
@@ -2300,12 +2300,6 @@ static void xennet_sysfs_delif(struct net_device *netdev)
#endif /* CONFIG_SYSFS */
-static const struct xenbus_device_id netfront_ids[] = {
- { "vif" },
- { "" }
-};
-
-
static int xennet_remove(struct xenbus_device *dev)
{
struct netfront_info *info = dev_get_drvdata(&dev->dev);
@@ -2338,12 +2332,18 @@ static int xennet_remove(struct xenbus_device *dev)
return 0;
}
-static DEFINE_XENBUS_DRIVER(netfront, ,
+static const struct xenbus_device_id netfront_ids[] = {
+ { "vif" },
+ { "" }
+};
+
+static struct xenbus_driver netfront_driver = {
+ .ids = netfront_ids,
.probe = netfront_probe,
.remove = xennet_remove,
.resume = netfront_resume,
.otherend_changed = netback_changed,
-);
+};
static int __init netif_init(void)
{