aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/Kconfig1
-rw-r--r--drivers/net/appletalk/ipddp.c2
-rw-r--r--drivers/net/bonding/bond_3ad.c140
-rw-r--r--drivers/net/bonding/bond_alb.c51
-rw-r--r--drivers/net/bonding/bond_alb.h8
-rw-r--r--drivers/net/bonding/bond_main.c201
-rw-r--r--drivers/net/bonding/bond_procfs.c3
-rw-r--r--drivers/net/bonding/bond_sysfs_slave.c2
-rw-r--r--drivers/net/bonding/bonding.h17
-rw-r--r--drivers/net/eql.c2
-rw-r--r--drivers/net/ethernet/3com/3c59x.c2
-rw-r--r--drivers/net/ethernet/broadcom/bcmsysport.c13
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmgenet.c42
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmgenet.h2
-rw-r--r--drivers/net/ethernet/brocade/bna/bna_tx_rx.c2
-rw-r--r--drivers/net/ethernet/brocade/bna/bnad.c2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4.h2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c6
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/sge.c25
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_hw.c17
-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/fs_enet/fs_enet-main.c211
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/fs_enet.h9
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/mac-fcc.c29
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/mac-fec.c29
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/mac-scc.c29
-rw-r--r--drivers/net/ethernet/freescale/fsl_pq_mdio.c56
-rw-r--r--drivers/net/ethernet/freescale/gianfar.c68
-rw-r--r--drivers/net/ethernet/freescale/gianfar.h31
-rw-r--r--drivers/net/ethernet/intel/Kconfig1
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_txrx.c90
-rw-r--r--drivers/net/ethernet/marvell/Kconfig3
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/cmd.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_tx.c53
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c2
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c2
-rw-r--r--drivers/net/ethernet/realtek/r8169.c561
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c4
-rw-r--r--drivers/net/ethernet/toshiba/spider_net.c42
-rw-r--r--drivers/net/ethernet/via/via-velocity.c2
-rw-r--r--drivers/net/hyperv/netvsc.c15
-rw-r--r--drivers/net/ifb.c3
-rw-r--r--drivers/net/loopback.c2
-rw-r--r--drivers/net/macvlan.c3
-rw-r--r--drivers/net/phy/fixed.c16
-rw-r--r--drivers/net/ppp/ppp_generic.c2
-rw-r--r--drivers/net/team/team.c12
-rw-r--r--drivers/net/usb/asix_devices.c2
-rw-r--r--drivers/net/usb/r8152.c111
-rw-r--r--drivers/net/usb/usbnet.c14
-rw-r--r--drivers/net/vxlan.c2
-rw-r--r--drivers/net/wan/hdlc_fr.c2
-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/htc_drv_init.c1
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/tx99.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c34
-rw-r--r--drivers/net/wireless/ath/main.c8
-rw-r--r--drivers/net/wireless/libertas/cfg.c2
-rw-r--r--drivers/net/wireless/libertas_tf/main.c2
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180/dev.c36
-rw-r--r--drivers/net/wireless/rtlwifi/wifi.h2
68 files changed, 1417 insertions, 683 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index c6f6f69f8961..4706386b7d34 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -147,7 +147,6 @@ config MACVTAP
config VXLAN
tristate "Virtual eXtensible Local Area Network (VXLAN)"
depends on INET
- select NET_IP_TUNNEL
select NET_UDP_TUNNEL
---help---
This allows one to create vxlan virtual interfaces that provide
diff --git a/drivers/net/appletalk/ipddp.c b/drivers/net/appletalk/ipddp.c
index 10d0dba572c2..e90c6a7333d7 100644
--- a/drivers/net/appletalk/ipddp.c
+++ b/drivers/net/appletalk/ipddp.c
@@ -74,7 +74,7 @@ static struct net_device * __init ipddp_init(void)
if (!dev)
return ERR_PTR(-ENOMEM);
- dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
+ netif_keep_dst(dev);
strcpy(dev->name, "ipddp%d");
if (version_printed++ == 0)
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 7e9e522fd476..2110215f3528 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -102,17 +102,20 @@ static const u8 lacpdu_mcast_addr[ETH_ALEN] = MULTICAST_LACPDU_ADDR;
/* ================= main 802.3ad protocol functions ================== */
static int ad_lacpdu_send(struct port *port);
static int ad_marker_send(struct port *port, struct bond_marker *marker);
-static void ad_mux_machine(struct port *port);
+static void ad_mux_machine(struct port *port, bool *update_slave_arr);
static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port);
static void ad_tx_machine(struct port *port);
static void ad_periodic_machine(struct port *port);
-static void ad_port_selection_logic(struct port *port);
-static void ad_agg_selection_logic(struct aggregator *aggregator);
+static void ad_port_selection_logic(struct port *port, bool *update_slave_arr);
+static void ad_agg_selection_logic(struct aggregator *aggregator,
+ bool *update_slave_arr);
static void ad_clear_agg(struct aggregator *aggregator);
static void ad_initialize_agg(struct aggregator *aggregator);
static void ad_initialize_port(struct port *port, int lacp_fast);
-static void ad_enable_collecting_distributing(struct port *port);
-static void ad_disable_collecting_distributing(struct port *port);
+static void ad_enable_collecting_distributing(struct port *port,
+ bool *update_slave_arr);
+static void ad_disable_collecting_distributing(struct port *port,
+ bool *update_slave_arr);
static void ad_marker_info_received(struct bond_marker *marker_info,
struct port *port);
static void ad_marker_response_received(struct bond_marker *marker,
@@ -796,8 +799,9 @@ static int ad_marker_send(struct port *port, struct bond_marker *marker)
/**
* ad_mux_machine - handle a port's mux state machine
* @port: the port we're looking at
+ * @update_slave_arr: Does slave array need update?
*/
-static void ad_mux_machine(struct port *port)
+static void ad_mux_machine(struct port *port, bool *update_slave_arr)
{
mux_states_t last_state;
@@ -901,7 +905,8 @@ static void ad_mux_machine(struct port *port)
switch (port->sm_mux_state) {
case AD_MUX_DETACHED:
port->actor_oper_port_state &= ~AD_STATE_SYNCHRONIZATION;
- ad_disable_collecting_distributing(port);
+ ad_disable_collecting_distributing(port,
+ update_slave_arr);
port->actor_oper_port_state &= ~AD_STATE_COLLECTING;
port->actor_oper_port_state &= ~AD_STATE_DISTRIBUTING;
port->ntt = true;
@@ -913,13 +918,15 @@ static void ad_mux_machine(struct port *port)
port->actor_oper_port_state |= AD_STATE_SYNCHRONIZATION;
port->actor_oper_port_state &= ~AD_STATE_COLLECTING;
port->actor_oper_port_state &= ~AD_STATE_DISTRIBUTING;
- ad_disable_collecting_distributing(port);
+ ad_disable_collecting_distributing(port,
+ update_slave_arr);
port->ntt = true;
break;
case AD_MUX_COLLECTING_DISTRIBUTING:
port->actor_oper_port_state |= AD_STATE_COLLECTING;
port->actor_oper_port_state |= AD_STATE_DISTRIBUTING;
- ad_enable_collecting_distributing(port);
+ ad_enable_collecting_distributing(port,
+ update_slave_arr);
port->ntt = true;
break;
default:
@@ -1187,12 +1194,13 @@ static void ad_periodic_machine(struct port *port)
/**
* ad_port_selection_logic - select aggregation groups
* @port: the port we're looking at
+ * @update_slave_arr: Does slave array need update?
*
* Select aggregation groups, and assign each port for it's aggregetor. The
* selection logic is called in the inititalization (after all the handshkes),
* and after every lacpdu receive (if selected is off).
*/
-static void ad_port_selection_logic(struct port *port)
+static void ad_port_selection_logic(struct port *port, bool *update_slave_arr)
{
struct aggregator *aggregator, *free_aggregator = NULL, *temp_aggregator;
struct port *last_port = NULL, *curr_port;
@@ -1347,7 +1355,7 @@ static void ad_port_selection_logic(struct port *port)
__agg_ports_are_ready(port->aggregator));
aggregator = __get_first_agg(port);
- ad_agg_selection_logic(aggregator);
+ ad_agg_selection_logic(aggregator, update_slave_arr);
}
/* Decide if "agg" is a better choice for the new active aggregator that
@@ -1435,6 +1443,7 @@ static int agg_device_up(const struct aggregator *agg)
/**
* ad_agg_selection_logic - select an aggregation group for a team
* @aggregator: the aggregator we're looking at
+ * @update_slave_arr: Does slave array need update?
*
* It is assumed that only one aggregator may be selected for a team.
*
@@ -1457,7 +1466,8 @@ static int agg_device_up(const struct aggregator *agg)
* __get_active_agg() won't work correctly. This function should be better
* called with the bond itself, and retrieve the first agg from it.
*/
-static void ad_agg_selection_logic(struct aggregator *agg)
+static void ad_agg_selection_logic(struct aggregator *agg,
+ bool *update_slave_arr)
{
struct aggregator *best, *active, *origin;
struct bonding *bond = agg->slave->bond;
@@ -1550,6 +1560,8 @@ static void ad_agg_selection_logic(struct aggregator *agg)
__disable_port(port);
}
}
+ /* Slave array needs update. */
+ *update_slave_arr = true;
}
/* if the selected aggregator is of join individuals
@@ -1678,24 +1690,30 @@ static void ad_initialize_port(struct port *port, int lacp_fast)
/**
* ad_enable_collecting_distributing - enable a port's transmit/receive
* @port: the port we're looking at
+ * @update_slave_arr: Does slave array need update?
*
* Enable @port if it's in an active aggregator
*/
-static void ad_enable_collecting_distributing(struct port *port)
+static void ad_enable_collecting_distributing(struct port *port,
+ bool *update_slave_arr)
{
if (port->aggregator->is_active) {
pr_debug("Enabling port %d(LAG %d)\n",
port->actor_port_number,
port->aggregator->aggregator_identifier);
__enable_port(port);
+ /* Slave array needs update */
+ *update_slave_arr = true;
}
}
/**
* ad_disable_collecting_distributing - disable a port's transmit/receive
* @port: the port we're looking at
+ * @update_slave_arr: Does slave array need update?
*/
-static void ad_disable_collecting_distributing(struct port *port)
+static void ad_disable_collecting_distributing(struct port *port,
+ bool *update_slave_arr)
{
if (port->aggregator &&
!MAC_ADDRESS_EQUAL(&(port->aggregator->partner_system),
@@ -1704,6 +1722,8 @@ static void ad_disable_collecting_distributing(struct port *port)
port->actor_port_number,
port->aggregator->aggregator_identifier);
__disable_port(port);
+ /* Slave array needs an update */
+ *update_slave_arr = true;
}
}
@@ -1868,6 +1888,7 @@ void bond_3ad_unbind_slave(struct slave *slave)
struct bonding *bond = slave->bond;
struct slave *slave_iter;
struct list_head *iter;
+ bool dummy_slave_update; /* Ignore this value as caller updates array */
/* Sync against bond_3ad_state_machine_handler() */
spin_lock_bh(&bond->mode_lock);
@@ -1951,7 +1972,8 @@ void bond_3ad_unbind_slave(struct slave *slave)
ad_clear_agg(aggregator);
if (select_new_active_agg)
- ad_agg_selection_logic(__get_first_agg(port));
+ ad_agg_selection_logic(__get_first_agg(port),
+ &dummy_slave_update);
} else {
netdev_warn(bond->dev, "unbinding aggregator, and could not find a new aggregator for its ports\n");
}
@@ -1966,7 +1988,8 @@ void bond_3ad_unbind_slave(struct slave *slave)
/* select new active aggregator */
temp_aggregator = __get_first_agg(port);
if (temp_aggregator)
- ad_agg_selection_logic(temp_aggregator);
+ ad_agg_selection_logic(temp_aggregator,
+ &dummy_slave_update);
}
}
}
@@ -1996,7 +2019,8 @@ void bond_3ad_unbind_slave(struct slave *slave)
if (select_new_active_agg) {
netdev_info(bond->dev, "Removing an active aggregator\n");
/* select new active aggregator */
- ad_agg_selection_logic(__get_first_agg(port));
+ ad_agg_selection_logic(__get_first_agg(port),
+ &dummy_slave_update);
}
}
break;
@@ -2031,6 +2055,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
struct slave *slave;
struct port *port;
bool should_notify_rtnl = BOND_SLAVE_NOTIFY_LATER;
+ bool update_slave_arr = false;
/* Lock to protect data accessed by all (e.g., port->sm_vars) and
* against running with bond_3ad_unbind_slave. ad_rx_machine may run
@@ -2058,7 +2083,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
}
aggregator = __get_first_agg(port);
- ad_agg_selection_logic(aggregator);
+ ad_agg_selection_logic(aggregator, &update_slave_arr);
}
bond_3ad_set_carrier(bond);
}
@@ -2074,8 +2099,8 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
ad_rx_machine(NULL, port);
ad_periodic_machine(port);
- ad_port_selection_logic(port);
- ad_mux_machine(port);
+ ad_port_selection_logic(port, &update_slave_arr);
+ ad_mux_machine(port, &update_slave_arr);
ad_tx_machine(port);
/* turn off the BEGIN bit, since we already handled it */
@@ -2093,6 +2118,9 @@ re_arm:
rcu_read_unlock();
spin_unlock_bh(&bond->mode_lock);
+ if (update_slave_arr)
+ bond_slave_arr_work_rearm(bond, 0);
+
if (should_notify_rtnl && rtnl_trylock()) {
bond_slave_state_notify(bond);
rtnl_unlock();
@@ -2283,6 +2311,11 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
port->sm_vars |= AD_PORT_BEGIN;
spin_unlock_bh(&slave->bond->mode_lock);
+
+ /* RTNL is held and mode_lock is released so it's safe
+ * to update slave_array here.
+ */
+ bond_update_slave_arr(slave->bond, NULL);
}
/**
@@ -2377,73 +2410,6 @@ int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info)
return ret;
}
-int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
-{
- struct bonding *bond = netdev_priv(dev);
- struct slave *slave, *first_ok_slave;
- struct aggregator *agg;
- struct ad_info ad_info;
- struct list_head *iter;
- int slaves_in_agg;
- int slave_agg_no;
- int agg_id;
-
- if (__bond_3ad_get_active_agg_info(bond, &ad_info)) {
- netdev_dbg(dev, "__bond_3ad_get_active_agg_info failed\n");
- goto err_free;
- }
-
- slaves_in_agg = ad_info.ports;
- agg_id = ad_info.aggregator_id;
-
- if (slaves_in_agg == 0) {
- netdev_dbg(dev, "active aggregator is empty\n");
- goto err_free;
- }
-
- slave_agg_no = bond_xmit_hash(bond, skb) % slaves_in_agg;
- first_ok_slave = NULL;
-
- bond_for_each_slave_rcu(bond, slave, iter) {
- agg = SLAVE_AD_INFO(slave)->port.aggregator;
- if (!agg || agg->aggregator_identifier != agg_id)
- continue;
-
- if (slave_agg_no >= 0) {
- if (!first_ok_slave && bond_slave_can_tx(slave))
- first_ok_slave = slave;
- slave_agg_no--;
- continue;
- }
-
- if (bond_slave_can_tx(slave)) {
- bond_dev_queue_xmit(bond, skb, slave->dev);
- goto out;
- }
- }
-
- if (slave_agg_no >= 0) {
- netdev_err(dev, "Couldn't find a slave to tx on for aggregator ID %d\n",
- agg_id);
- goto err_free;
- }
-
- /* we couldn't find any suitable slave after the agg_no, so use the
- * first suitable found, if found.
- */
- if (first_ok_slave)
- bond_dev_queue_xmit(bond, skb, first_ok_slave->dev);
- else
- goto err_free;
-
-out:
- return NETDEV_TX_OK;
-err_free:
- /* no suitable interface, frame not sent */
- dev_kfree_skb_any(skb);
- goto out;
-}
-
int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond,
struct slave *slave)
{
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 615f3bebd019..d2eadab787c5 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -177,7 +177,6 @@ static int tlb_initialize(struct bonding *bond)
static void tlb_deinitialize(struct bonding *bond)
{
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
- struct tlb_up_slave *arr;
spin_lock_bh(&bond->mode_lock);
@@ -185,10 +184,6 @@ static void tlb_deinitialize(struct bonding *bond)
bond_info->tx_hashtbl = NULL;
spin_unlock_bh(&bond->mode_lock);
-
- arr = rtnl_dereference(bond_info->slave_arr);
- if (arr)
- kfree_rcu(arr, rcu);
}
static long long compute_gap(struct slave *slave)
@@ -1336,39 +1331,9 @@ out:
return NETDEV_TX_OK;
}
-static int bond_tlb_update_slave_arr(struct bonding *bond,
- struct slave *skipslave)
-{
- struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
- struct slave *tx_slave;
- struct list_head *iter;
- struct tlb_up_slave *new_arr, *old_arr;
-
- new_arr = kzalloc(offsetof(struct tlb_up_slave, arr[bond->slave_cnt]),
- GFP_ATOMIC);
- if (!new_arr)
- return -ENOMEM;
-
- bond_for_each_slave(bond, tx_slave, iter) {
- if (!bond_slave_can_tx(tx_slave))
- continue;
- if (skipslave == tx_slave)
- continue;
- new_arr->arr[new_arr->count++] = tx_slave;
- }
-
- old_arr = rtnl_dereference(bond_info->slave_arr);
- rcu_assign_pointer(bond_info->slave_arr, new_arr);
- if (old_arr)
- kfree_rcu(old_arr, rcu);
-
- return 0;
-}
-
int bond_tlb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
{
struct bonding *bond = netdev_priv(bond_dev);
- struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
struct ethhdr *eth_data;
struct slave *tx_slave = NULL;
u32 hash_index;
@@ -1389,12 +1354,14 @@ int bond_tlb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
hash_index & 0xFF,
skb->len);
} else {
- struct tlb_up_slave *slaves;
+ struct bond_up_slave *slaves;
+ unsigned int count;
- slaves = rcu_dereference(bond_info->slave_arr);
- if (slaves && slaves->count)
+ slaves = rcu_dereference(bond->slave_arr);
+ count = slaves ? ACCESS_ONCE(slaves->count) : 0;
+ if (likely(count))
tx_slave = slaves->arr[hash_index %
- slaves->count];
+ count];
}
break;
}
@@ -1641,10 +1608,6 @@ void bond_alb_deinit_slave(struct bonding *bond, struct slave *slave)
rlb_clear_slave(bond, slave);
}
- if (bond_is_nondyn_tlb(bond))
- if (bond_tlb_update_slave_arr(bond, slave))
- pr_err("Failed to build slave-array for TLB mode.\n");
-
}
void bond_alb_handle_link_change(struct bonding *bond, struct slave *slave, char link)
@@ -1669,7 +1632,7 @@ void bond_alb_handle_link_change(struct bonding *bond, struct slave *slave, char
}
if (bond_is_nondyn_tlb(bond)) {
- if (bond_tlb_update_slave_arr(bond, NULL))
+ if (bond_update_slave_arr(bond, NULL))
pr_err("Failed to build slave-array for TLB mode.\n");
}
}
diff --git a/drivers/net/bonding/bond_alb.h b/drivers/net/bonding/bond_alb.h
index 3c6a7ff974d7..1ad473b4ade5 100644
--- a/drivers/net/bonding/bond_alb.h
+++ b/drivers/net/bonding/bond_alb.h
@@ -139,19 +139,11 @@ struct tlb_slave_info {
*/
};
-struct tlb_up_slave {
- unsigned int count;
- struct rcu_head rcu;
- struct slave *arr[0];
-};
-
struct alb_bond_info {
struct tlb_client_info *tx_hashtbl; /* Dynamically allocated */
u32 unbalanced_load;
int tx_rebalance_counter;
int lp_counter;
- /* -------- non-dynamic tlb mode only ---------*/
- struct tlb_up_slave __rcu *slave_arr; /* Up slaves */
/* -------- rlb parameters -------- */
int rlb_enabled;
struct rlb_client_info *rx_hashtbl; /* Receive hash table */
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index c2adc2755ff6..c9ac06cfe6b7 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -210,6 +210,7 @@ static int bond_init(struct net_device *bond_dev);
static void bond_uninit(struct net_device *bond_dev);
static struct rtnl_link_stats64 *bond_get_stats(struct net_device *bond_dev,
struct rtnl_link_stats64 *stats);
+static void bond_slave_arr_handler(struct work_struct *work);
/*---------------------------- General routines -----------------------------*/
@@ -1001,7 +1002,8 @@ static netdev_features_t bond_fix_features(struct net_device *dev,
static void bond_compute_features(struct bonding *bond)
{
- unsigned int flags, dst_release_flag = IFF_XMIT_DST_RELEASE;
+ unsigned int dst_release_flag = IFF_XMIT_DST_RELEASE |
+ IFF_XMIT_DST_RELEASE_PERM;
netdev_features_t vlan_features = BOND_VLAN_FEATURES;
netdev_features_t enc_features = BOND_ENC_FEATURES;
struct net_device *bond_dev = bond->dev;
@@ -1037,8 +1039,10 @@ done:
bond_dev->gso_max_segs = gso_max_segs;
netif_set_gso_max_size(bond_dev, gso_max_size);
- flags = bond_dev->priv_flags & ~IFF_XMIT_DST_RELEASE;
- bond_dev->priv_flags = flags | dst_release_flag;
+ bond_dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
+ if ((bond_dev->priv_flags & IFF_XMIT_DST_RELEASE_PERM) &&
+ dst_release_flag == (IFF_XMIT_DST_RELEASE | IFF_XMIT_DST_RELEASE_PERM))
+ bond_dev->priv_flags |= IFF_XMIT_DST_RELEASE;
netdev_change_features(bond_dev);
}
@@ -1551,6 +1555,9 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
unblock_netpoll_tx();
}
+ if (bond_mode_uses_xmit_hash(bond))
+ bond_update_slave_arr(bond, NULL);
+
netdev_info(bond_dev, "Enslaving %s as %s interface with %s link\n",
slave_dev->name,
bond_is_active_slave(new_slave) ? "an active" : "a backup",
@@ -1668,6 +1675,9 @@ static int __bond_release_one(struct net_device *bond_dev,
if (BOND_MODE(bond) == BOND_MODE_8023AD)
bond_3ad_unbind_slave(slave);
+ if (bond_mode_uses_xmit_hash(bond))
+ bond_update_slave_arr(bond, slave);
+
netdev_info(bond_dev, "Releasing %s interface %s\n",
bond_is_active_slave(slave) ? "active" : "backup",
slave_dev->name);
@@ -1970,6 +1980,9 @@ static void bond_miimon_commit(struct bonding *bond)
bond_alb_handle_link_change(bond, slave,
BOND_LINK_UP);
+ if (BOND_MODE(bond) == BOND_MODE_XOR)
+ bond_update_slave_arr(bond, NULL);
+
if (!bond->curr_active_slave || slave == primary)
goto do_failover;
@@ -1997,6 +2010,9 @@ static void bond_miimon_commit(struct bonding *bond)
bond_alb_handle_link_change(bond, slave,
BOND_LINK_DOWN);
+ if (BOND_MODE(bond) == BOND_MODE_XOR)
+ bond_update_slave_arr(bond, NULL);
+
if (slave == rcu_access_pointer(bond->curr_active_slave))
goto do_failover;
@@ -2453,6 +2469,8 @@ static void bond_loadbalance_arp_mon(struct work_struct *work)
if (slave_state_changed) {
bond_slave_state_change(bond);
+ if (BOND_MODE(bond) == BOND_MODE_XOR)
+ bond_update_slave_arr(bond, NULL);
} else if (do_failover) {
block_netpoll_tx();
bond_select_active_slave(bond);
@@ -2829,8 +2847,20 @@ static int bond_slave_netdev_event(unsigned long event,
if (old_duplex != slave->duplex)
bond_3ad_adapter_duplex_changed(slave);
}
+ /* Refresh slave-array if applicable!
+ * If the setup does not use miimon or arpmon (mode-specific!),
+ * then these events will not cause the slave-array to be
+ * refreshed. This will cause xmit to use a slave that is not
+ * usable. Avoid such situation by refeshing the array at these
+ * events. If these (miimon/arpmon) parameters are configured
+ * then array gets refreshed twice and that should be fine!
+ */
+ if (bond_mode_uses_xmit_hash(bond))
+ bond_update_slave_arr(bond, NULL);
break;
case NETDEV_DOWN:
+ if (bond_mode_uses_xmit_hash(bond))
+ bond_update_slave_arr(bond, NULL);
break;
case NETDEV_CHANGEMTU:
/* TODO: Should slaves be allowed to
@@ -3010,6 +3040,7 @@ static void bond_work_init_all(struct bonding *bond)
else
INIT_DELAYED_WORK(&bond->arp_work, bond_loadbalance_arp_mon);
INIT_DELAYED_WORK(&bond->ad_work, bond_3ad_state_machine_handler);
+ INIT_DELAYED_WORK(&bond->slave_arr_work, bond_slave_arr_handler);
}
static void bond_work_cancel_all(struct bonding *bond)
@@ -3019,6 +3050,7 @@ static void bond_work_cancel_all(struct bonding *bond)
cancel_delayed_work_sync(&bond->alb_work);
cancel_delayed_work_sync(&bond->ad_work);
cancel_delayed_work_sync(&bond->mcast_work);
+ cancel_delayed_work_sync(&bond->slave_arr_work);
}
static int bond_open(struct net_device *bond_dev)
@@ -3068,6 +3100,9 @@ static int bond_open(struct net_device *bond_dev)
bond_3ad_initiate_agg_selection(bond, 1);
}
+ if (bond_mode_uses_xmit_hash(bond))
+ bond_update_slave_arr(bond, NULL);
+
return 0;
}
@@ -3573,20 +3608,148 @@ static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_d
return NETDEV_TX_OK;
}
-/* In bond_xmit_xor() , we determine the output device by using a pre-
- * determined xmit_hash_policy(), If the selected device is not enabled,
- * find the next active slave.
+/* Use this to update slave_array when (a) it's not appropriate to update
+ * slave_array right away (note that update_slave_array() may sleep)
+ * and / or (b) RTNL is not held.
*/
-static int bond_xmit_xor(struct sk_buff *skb, struct net_device *bond_dev)
+void bond_slave_arr_work_rearm(struct bonding *bond, unsigned long delay)
{
- struct bonding *bond = netdev_priv(bond_dev);
- int slave_cnt = ACCESS_ONCE(bond->slave_cnt);
+ queue_delayed_work(bond->wq, &bond->slave_arr_work, delay);
+}
- if (likely(slave_cnt))
- bond_xmit_slave_id(bond, skb,
- bond_xmit_hash(bond, skb) % slave_cnt);
- else
+/* Slave array work handler. Holds only RTNL */
+static void bond_slave_arr_handler(struct work_struct *work)
+{
+ struct bonding *bond = container_of(work, struct bonding,
+ slave_arr_work.work);
+ int ret;
+
+ if (!rtnl_trylock())
+ goto err;
+
+ ret = bond_update_slave_arr(bond, NULL);
+ rtnl_unlock();
+ if (ret) {
+ pr_warn_ratelimited("Failed to update slave array from WT\n");
+ goto err;
+ }
+ return;
+
+err:
+ bond_slave_arr_work_rearm(bond, 1);
+}
+
+/* Build the usable slaves array in control path for modes that use xmit-hash
+ * to determine the slave interface -
+ * (a) BOND_MODE_8023AD
+ * (b) BOND_MODE_XOR
+ * (c) BOND_MODE_TLB && tlb_dynamic_lb == 0
+ *
+ * The caller is expected to hold RTNL only and NO other lock!
+ */
+int bond_update_slave_arr(struct bonding *bond, struct slave *skipslave)
+{
+ struct slave *slave;
+ struct list_head *iter;
+ struct bond_up_slave *new_arr, *old_arr;
+ int slaves_in_agg;
+ int agg_id = 0;
+ int ret = 0;
+
+#ifdef CONFIG_LOCKDEP
+ WARN_ON(lockdep_is_held(&bond->mode_lock));
+#endif
+
+ new_arr = kzalloc(offsetof(struct bond_up_slave, arr[bond->slave_cnt]),
+ GFP_KERNEL);
+ if (!new_arr) {
+ ret = -ENOMEM;
+ pr_err("Failed to build slave-array.\n");
+ goto out;
+ }
+ if (BOND_MODE(bond) == BOND_MODE_8023AD) {
+ struct ad_info ad_info;
+
+ if (bond_3ad_get_active_agg_info(bond, &ad_info)) {
+ pr_debug("bond_3ad_get_active_agg_info failed\n");
+ kfree_rcu(new_arr, rcu);
+ /* No active aggragator means it's not safe to use
+ * the previous array.
+ */
+ old_arr = rtnl_dereference(bond->slave_arr);
+ if (old_arr) {
+ RCU_INIT_POINTER(bond->slave_arr, NULL);
+ kfree_rcu(old_arr, rcu);
+ }
+ goto out;
+ }
+ slaves_in_agg = ad_info.ports;
+ agg_id = ad_info.aggregator_id;
+ }
+ bond_for_each_slave(bond, slave, iter) {
+ if (BOND_MODE(bond) == BOND_MODE_8023AD) {
+ struct aggregator *agg;
+
+ agg = SLAVE_AD_INFO(slave)->port.aggregator;
+ if (!agg || agg->aggregator_identifier != agg_id)
+ continue;
+ }
+ if (!bond_slave_can_tx(slave))
+ continue;
+ if (skipslave == slave)
+ continue;
+ new_arr->arr[new_arr->count++] = slave;
+ }
+
+ old_arr = rtnl_dereference(bond->slave_arr);
+ rcu_assign_pointer(bond->slave_arr, new_arr);
+ if (old_arr)
+ kfree_rcu(old_arr, rcu);
+out:
+ if (ret != 0 && skipslave) {
+ int idx;
+
+ /* Rare situation where caller has asked to skip a specific
+ * slave but allocation failed (most likely!). BTW this is
+ * only possible when the call is initiated from
+ * __bond_release_one(). In this situation; overwrite the
+ * skipslave entry in the array with the last entry from the
+ * array to avoid a situation where the xmit path may choose
+ * this to-be-skipped slave to send a packet out.
+ */
+ old_arr = rtnl_dereference(bond->slave_arr);
+ for (idx = 0; idx < old_arr->count; idx++) {
+ if (skipslave == old_arr->arr[idx]) {
+ old_arr->arr[idx] =
+ old_arr->arr[old_arr->count-1];
+ old_arr->count--;
+ break;
+ }
+ }
+ }
+ return ret;
+}
+
+/* Use this Xmit function for 3AD as well as XOR modes. The current
+ * usable slave array is formed in the control path. The xmit function
+ * just calculates hash and sends the packet out.
+ */
+int bond_3ad_xor_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct bonding *bond = netdev_priv(dev);
+ struct slave *slave;
+ struct bond_up_slave *slaves;
+ unsigned int count;
+
+ slaves = rcu_dereference(bond->slave_arr);
+ count = slaves ? ACCESS_ONCE(slaves->count) : 0;
+ if (likely(count)) {
+ slave = slaves->arr[bond_xmit_hash(bond, skb) % count];
+ bond_dev_queue_xmit(bond, skb, slave->dev);
+ } else {
dev_kfree_skb_any(skb);
+ atomic_long_inc(&dev->tx_dropped);
+ }
return NETDEV_TX_OK;
}
@@ -3682,12 +3845,11 @@ static netdev_tx_t __bond_start_xmit(struct sk_buff *skb, struct net_device *dev
return bond_xmit_roundrobin(skb, dev);
case BOND_MODE_ACTIVEBACKUP:
return bond_xmit_activebackup(skb, dev);
+ case BOND_MODE_8023AD:
case BOND_MODE_XOR:
- return bond_xmit_xor(skb, dev);
+ return bond_3ad_xor_xmit(skb, dev);
case BOND_MODE_BROADCAST:
return bond_xmit_broadcast(skb, dev);
- case BOND_MODE_8023AD:
- return bond_3ad_xmit_xor(skb, dev);
case BOND_MODE_ALB:
return bond_alb_xmit(skb, dev);
case BOND_MODE_TLB:
@@ -3861,6 +4023,7 @@ static void bond_uninit(struct net_device *bond_dev)
struct bonding *bond = netdev_priv(bond_dev);
struct list_head *iter;
struct slave *slave;
+ struct bond_up_slave *arr;
bond_netpoll_cleanup(bond_dev);
@@ -3869,6 +4032,12 @@ static void bond_uninit(struct net_device *bond_dev)
__bond_release_one(bond_dev, slave->dev, true);
netdev_info(bond_dev, "Released all slaves\n");
+ arr = rtnl_dereference(bond->slave_arr);
+ if (arr) {
+ RCU_INIT_POINTER(bond->slave_arr, NULL);
+ kfree_rcu(arr, rcu);
+ }
+
list_del(&bond->bond_list);
bond_debug_unregister(bond);
diff --git a/drivers/net/bonding/bond_procfs.c b/drivers/net/bonding/bond_procfs.c
index bb09d0442aa8..a3948f8d1e53 100644
--- a/drivers/net/bonding/bond_procfs.c
+++ b/drivers/net/bonding/bond_procfs.c
@@ -73,8 +73,7 @@ static void bond_info_show_master(struct seq_file *seq)
seq_printf(seq, "\n");
- if (BOND_MODE(bond) == BOND_MODE_XOR ||
- BOND_MODE(bond) == BOND_MODE_8023AD) {
+ if (bond_mode_uses_xmit_hash(bond)) {
optval = bond_opt_get_val(BOND_OPT_XMIT_HASH,
bond->params.xmit_policy);
seq_printf(seq, "Transmit Hash Policy: %s (%d)\n",
diff --git a/drivers/net/bonding/bond_sysfs_slave.c b/drivers/net/bonding/bond_sysfs_slave.c
index 5cd532ca1cfe..b01b0ce4d1be 100644
--- a/drivers/net/bonding/bond_sysfs_slave.c
+++ b/drivers/net/bonding/bond_sysfs_slave.c
@@ -36,7 +36,7 @@ static ssize_t state_show(struct slave *slave, char *buf)
case BOND_STATE_BACKUP:
return sprintf(buf, "backup\n");
default:
- return sprintf(buf, "UNKONWN\n");
+ return sprintf(buf, "UNKNOWN\n");
}
}
static SLAVE_ATTR_RO(state);
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 57917e63b4e6..10920f0686e2 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -179,6 +179,12 @@ struct slave {
struct rtnl_link_stats64 slave_stats;
};
+struct bond_up_slave {
+ unsigned int count;
+ struct rcu_head rcu;
+ struct slave *arr[0];
+};
+
/*
* Link pseudo-state only used internally by monitors
*/
@@ -193,6 +199,7 @@ struct bonding {
struct slave __rcu *curr_active_slave;
struct slave __rcu *current_arp_slave;
struct slave __rcu *primary_slave;
+ struct bond_up_slave __rcu *slave_arr; /* Array of usable slaves */
bool force_primary;
s32 slave_cnt; /* never change this value outside the attach/detach wrappers */
int (*recv_probe)(const struct sk_buff *, struct bonding *,
@@ -222,6 +229,7 @@ struct bonding {
struct delayed_work alb_work;
struct delayed_work ad_work;
struct delayed_work mcast_work;
+ struct delayed_work slave_arr_work;
#ifdef CONFIG_DEBUG_FS
/* debugging support via debugfs */
struct dentry *debug_dir;
@@ -274,6 +282,13 @@ static inline bool bond_is_nondyn_tlb(const struct bonding *bond)
(bond->params.tlb_dynamic_lb == 0);
}
+static inline bool bond_mode_uses_xmit_hash(const struct bonding *bond)
+{
+ return (BOND_MODE(bond) == BOND_MODE_8023AD ||
+ BOND_MODE(bond) == BOND_MODE_XOR ||
+ bond_is_nondyn_tlb(bond));
+}
+
static inline bool bond_mode_uses_arp(int mode)
{
return mode != BOND_MODE_8023AD && mode != BOND_MODE_TLB &&
@@ -527,6 +542,8 @@ const char *bond_slave_link_status(s8 link);
struct bond_vlan_tag *bond_verify_device_path(struct net_device *start_dev,
struct net_device *end_dev,
int level);
+int bond_update_slave_arr(struct bonding *bond, struct slave *skipslave);
+void bond_slave_arr_work_rearm(struct bonding *bond, unsigned long delay);
#ifdef CONFIG_PROC_FS
void bond_create_proc_entry(struct bonding *bond);
diff --git a/drivers/net/eql.c b/drivers/net/eql.c
index 957e5c0cede3..a10ad74cc8d2 100644
--- a/drivers/net/eql.c
+++ b/drivers/net/eql.c
@@ -199,7 +199,7 @@ static void __init eql_setup(struct net_device *dev)
dev->type = ARPHRD_SLIP;
dev->tx_queue_len = 5; /* Hands them off fast */
- dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
+ netif_keep_dst(dev);
}
static int eql_open(struct net_device *dev)
diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c
index 86e621142d5b..41095ebad97f 100644
--- a/drivers/net/ethernet/3com/3c59x.c
+++ b/drivers/net/ethernet/3com/3c59x.c
@@ -2213,7 +2213,7 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
}
#else
- dma_addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data, skb->len, PCI_DMA_TODEVICE));
+ dma_addr = pci_map_single(VORTEX_PCI(vp), skb->data, skb->len, PCI_DMA_TODEVICE);
if (dma_mapping_error(&VORTEX_PCI(vp)->dev, dma_addr))
goto out_dma_err;
vp->tx_ring[entry].addr = cpu_to_le32(dma_addr);
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
index 77f1ff7396ac..075688188644 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
@@ -857,7 +857,8 @@ static irqreturn_t bcm_sysport_wol_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static int bcm_sysport_insert_tsb(struct sk_buff *skb, struct net_device *dev)
+static struct sk_buff *bcm_sysport_insert_tsb(struct sk_buff *skb,
+ struct net_device *dev)
{
struct sk_buff *nskb;
struct bcm_tsb *tsb;
@@ -873,7 +874,7 @@ static int bcm_sysport_insert_tsb(struct sk_buff *skb, struct net_device *dev)
if (!nskb) {
dev->stats.tx_errors++;
dev->stats.tx_dropped++;
- return -ENOMEM;
+ return NULL;
}
skb = nskb;
}
@@ -892,7 +893,7 @@ static int bcm_sysport_insert_tsb(struct sk_buff *skb, struct net_device *dev)
ip_proto = ipv6_hdr(skb)->nexthdr;
break;
default:
- return 0;
+ return skb;
}
/* Get the checksum offset and the L4 (transport) offset */
@@ -911,7 +912,7 @@ static int bcm_sysport_insert_tsb(struct sk_buff *skb, struct net_device *dev)
tsb->l4_ptr_dest_map = csum_info;
}
- return 0;
+ return skb;
}
static netdev_tx_t bcm_sysport_xmit(struct sk_buff *skb,
@@ -945,8 +946,8 @@ static netdev_tx_t bcm_sysport_xmit(struct sk_buff *skb,
/* Insert TSB and checksum infos */
if (priv->tsb_en) {
- ret = bcm_sysport_insert_tsb(skb, dev);
- if (ret) {
+ skb = bcm_sysport_insert_tsb(skb, dev);
+ if (!skb) {
ret = NETDEV_TX_OK;
goto out;
}
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
index e0a6238a74b4..fff2634b6f34 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -191,8 +191,9 @@ enum dma_reg {
DMA_STATUS,
DMA_SCB_BURST_SIZE,
DMA_ARB_CTRL,
- DMA_PRIORITY,
- DMA_RING_PRIORITY,
+ DMA_PRIORITY_0,
+ DMA_PRIORITY_1,
+ DMA_PRIORITY_2,
};
static const u8 bcmgenet_dma_regs_v3plus[] = {
@@ -201,8 +202,9 @@ static const u8 bcmgenet_dma_regs_v3plus[] = {
[DMA_STATUS] = 0x08,
[DMA_SCB_BURST_SIZE] = 0x0C,
[DMA_ARB_CTRL] = 0x2C,
- [DMA_PRIORITY] = 0x30,
- [DMA_RING_PRIORITY] = 0x38,
+ [DMA_PRIORITY_0] = 0x30,
+ [DMA_PRIORITY_1] = 0x34,
+ [DMA_PRIORITY_2] = 0x38,
};
static const u8 bcmgenet_dma_regs_v2[] = {
@@ -211,8 +213,9 @@ static const u8 bcmgenet_dma_regs_v2[] = {
[DMA_STATUS] = 0x08,
[DMA_SCB_BURST_SIZE] = 0x0C,
[DMA_ARB_CTRL] = 0x30,
- [DMA_PRIORITY] = 0x34,
- [DMA_RING_PRIORITY] = 0x3C,
+ [DMA_PRIORITY_0] = 0x34,
+ [DMA_PRIORITY_1] = 0x38,
+ [DMA_PRIORITY_2] = 0x3C,
};
static const u8 bcmgenet_dma_regs_v1[] = {
@@ -220,8 +223,9 @@ static const u8 bcmgenet_dma_regs_v1[] = {
[DMA_STATUS] = 0x04,
[DMA_SCB_BURST_SIZE] = 0x0C,
[DMA_ARB_CTRL] = 0x30,
- [DMA_PRIORITY] = 0x34,
- [DMA_RING_PRIORITY] = 0x3C,
+ [DMA_PRIORITY_0] = 0x34,
+ [DMA_PRIORITY_1] = 0x38,
+ [DMA_PRIORITY_2] = 0x3C,
};
/* Set at runtime once bcmgenet version is known */
@@ -1696,7 +1700,8 @@ static void bcmgenet_init_multiq(struct net_device *dev)
{
struct bcmgenet_priv *priv = netdev_priv(dev);
unsigned int i, dma_enable;
- u32 reg, dma_ctrl, ring_cfg = 0, dma_priority = 0;
+ u32 reg, dma_ctrl, ring_cfg = 0;
+ u32 dma_priority[3] = {0, 0, 0};
if (!netif_is_multiqueue(dev)) {
netdev_warn(dev, "called with non multi queue aware HW\n");
@@ -1721,22 +1726,25 @@ static void bcmgenet_init_multiq(struct net_device *dev)
/* Configure ring as descriptor ring and setup priority */
ring_cfg |= 1 << i;
- dma_priority |= ((GENET_Q0_PRIORITY + i) <<
- (GENET_MAX_MQ_CNT + 1) * i);
dma_ctrl |= 1 << (i + DMA_RING_BUF_EN_SHIFT);
+
+ dma_priority[DMA_PRIO_REG_INDEX(i)] |=
+ ((GENET_Q0_PRIORITY + i) << DMA_PRIO_REG_SHIFT(i));
}
+ /* Set ring 16 priority and program the hardware registers */
+ dma_priority[DMA_PRIO_REG_INDEX(DESC_INDEX)] |=
+ ((GENET_Q0_PRIORITY + priv->hw_params->tx_queues) <<
+ DMA_PRIO_REG_SHIFT(DESC_INDEX));
+ bcmgenet_tdma_writel(priv, dma_priority[0], DMA_PRIORITY_0);
+ bcmgenet_tdma_writel(priv, dma_priority[1], DMA_PRIORITY_1);
+ bcmgenet_tdma_writel(priv, dma_priority[2], DMA_PRIORITY_2);
+
/* Enable rings */
reg = bcmgenet_tdma_readl(priv, DMA_RING_CFG);
reg |= ring_cfg;
bcmgenet_tdma_writel(priv, reg, DMA_RING_CFG);
- /* Use configured rings priority and set ring #16 priority */
- reg = bcmgenet_tdma_readl(priv, DMA_RING_PRIORITY);
- reg |= ((GENET_Q0_PRIORITY + priv->hw_params->tx_queues) << 20);
- reg |= dma_priority;
- bcmgenet_tdma_writel(priv, reg, DMA_PRIORITY);
-
/* Configure ring as descriptor ring and re-enable DMA if enabled */
reg = bcmgenet_tdma_readl(priv, DMA_CTRL);
reg |= dma_ctrl;
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
index 321b1db8c14b..dbf524ea3b19 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
@@ -401,6 +401,8 @@ struct bcmgenet_mib_counters {
#define DMA_ARBITER_MODE_MASK 0x03
#define DMA_RING_BUF_PRIORITY_MASK 0x1F
#define DMA_RING_BUF_PRIORITY_SHIFT 5
+#define DMA_PRIO_REG_INDEX(q) ((q) / 6)
+#define DMA_PRIO_REG_SHIFT(q) (((q) % 6) * DMA_RING_BUF_PRIORITY_SHIFT)
#define DMA_RATE_ADJ_MASK 0xFF
/* Tx/Rx Dma Descriptor common bits*/
diff --git a/drivers/net/ethernet/brocade/bna/bna_tx_rx.c b/drivers/net/ethernet/brocade/bna/bna_tx_rx.c
index 8ee3fdcc17cd..5fac411c52f4 100644
--- a/drivers/net/ethernet/brocade/bna/bna_tx_rx.c
+++ b/drivers/net/ethernet/brocade/bna/bna_tx_rx.c
@@ -3410,7 +3410,7 @@ bna_bfi_tx_enet_start(struct bna_tx *tx)
cfg_req->tx_cfg.vlan_mode = BFI_ENET_TX_VLAN_WI;
cfg_req->tx_cfg.vlan_id = htons((u16)tx->txf_vlan_id);
- cfg_req->tx_cfg.admit_tagged_frame = BNA_STATUS_T_DISABLED;
+ cfg_req->tx_cfg.admit_tagged_frame = BNA_STATUS_T_ENABLED;
cfg_req->tx_cfg.apply_vlan_filter = BNA_STATUS_T_DISABLED;
bfa_msgq_cmd_set(&tx->msgq_cmd, NULL, NULL,
diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c
index ffc92a41d75b..153cafac323c 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.c
+++ b/drivers/net/ethernet/brocade/bna/bnad.c
@@ -2864,7 +2864,7 @@ bnad_txq_wi_prepare(struct bnad *bnad, struct bna_tcb *tcb,
txqent->hdr.wi.opcode = htons(BNA_TXQ_WI_SEND);
txqent->hdr.wi.lso_mss = 0;
- if (unlikely(skb->len > (bnad->netdev->mtu + ETH_HLEN))) {
+ if (unlikely(skb->len > (bnad->netdev->mtu + VLAN_ETH_HLEN))) {
BNAD_UPDATE_CTR(bnad, tx_skb_non_tso_too_long);
return -EINVAL;
}
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index 9b2c669b6522..410ed5805a9a 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);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 321f3d9385c9..5b38e955af6e 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -6137,7 +6137,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 +6530,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) {
diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c
index bb7851e0b4c6..5e1b314e11af 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
@@ -850,13 +850,14 @@ static void write_sgl(const struct sk_buff *skb, struct sge_txq *q,
*end = 0;
}
-/* This function copies 64 byte coalesced work request to
- * memory mapped BAR2 space(user space writes).
- * For coalesced WR SGE, fetches data from the FIFO instead of from Host.
+/* This function copies a tx_desc struct to memory mapped BAR2 space(user space
+ * writes). For coalesced WR SGE, fetches data from the FIFO instead of from
+ * Host.
*/
-static void cxgb_pio_copy(u64 __iomem *dst, u64 *src)
+static void cxgb_pio_copy(u64 __iomem *dst, struct tx_desc *desc)
{
- int count = 8;
+ int count = sizeof(*desc) / sizeof(u64);
+ u64 *src = (u64 *)desc;
while (count) {
writeq(*src, dst);
@@ -914,12 +915,9 @@ static inline void ring_tx_db(struct adapter *adap, struct sge_txq *q, int n)
int index = (q->pidx
? (q->pidx - 1)
: (q->size - 1));
- unsigned int *wr = (unsigned int *)&q->desc[index];
- cxgb_pio_copy((u64 __iomem *)
- (adap->bar2 + q->udb +
- SGE_UDB_WCDOORBELL),
- (u64 *)wr);
+ cxgb_pio_copy(adap->bar2 + q->udb + SGE_UDB_WCDOORBELL,
+ q->desc + index);
} else {
writel(val, adap->bar2 + q->udb + SGE_UDB_KDOORBELL);
}
@@ -1125,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) |
@@ -2258,7 +2259,7 @@ static u64 udb_address(struct adapter *adap, unsigned int cntxt_id,
(QUEUESPERPAGEPF1 - QUEUESPERPAGEPF0) * adap->fn);
udb_density = 1 << ((qpp >> s_qpp) & QUEUESPERPAGEPF0_MASK);
qpshift = PAGE_SHIFT - ilog2(udb_density);
- udb = cntxt_id << qpshift;
+ udb = (u64)cntxt_id << qpshift;
udb &= PAGE_MASK;
page = udb / PAGE_SIZE;
udb += (cntxt_id - (page * udb_density)) * SGE_UDB_SIZE;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
index 22d7581341a9..1fff1495fe31 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
@@ -3845,12 +3845,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 +3926,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/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
index 748fd24d3d9e..c92c3b7876ca 100644
--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
+++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
@@ -215,139 +215,23 @@ static int fs_enet_rx_napi(struct napi_struct *napi, int budget)
return received;
}
-/* non NAPI receive function */
-static int fs_enet_rx_non_napi(struct net_device *dev)
+static int fs_enet_tx_napi(struct napi_struct *napi, int budget)
{
- struct fs_enet_private *fep = netdev_priv(dev);
- const struct fs_platform_info *fpi = fep->fpi;
- cbd_t __iomem *bdp;
- struct sk_buff *skb, *skbn, *skbt;
- int received = 0;
- u16 pkt_len, sc;
- int curidx;
- /*
- * First, grab all of the stats for the incoming packet.
- * These get messed up if we get called due to a busy condition.
- */
- bdp = fep->cur_rx;
-
- while (((sc = CBDR_SC(bdp)) & BD_ENET_RX_EMPTY) == 0) {
-
- curidx = bdp - fep->rx_bd_base;
-
- /*
- * Since we have allocated space to hold a complete frame,
- * the last indicator should be set.
- */
- if ((sc & BD_ENET_RX_LAST) == 0)
- dev_warn(fep->dev, "rcv is not +last\n");
-
- /*
- * Check for errors.
- */
- if (sc & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_CL |
- BD_ENET_RX_NO | BD_ENET_RX_CR | BD_ENET_RX_OV)) {
- fep->stats.rx_errors++;
- /* Frame too long or too short. */
- if (sc & (BD_ENET_RX_LG | BD_ENET_RX_SH))
- fep->stats.rx_length_errors++;
- /* Frame alignment */
- if (sc & (BD_ENET_RX_NO | BD_ENET_RX_CL))
- fep->stats.rx_frame_errors++;
- /* CRC Error */
- if (sc & BD_ENET_RX_CR)
- fep->stats.rx_crc_errors++;
- /* FIFO overrun */
- if (sc & BD_ENET_RX_OV)
- fep->stats.rx_crc_errors++;
-
- skb = fep->rx_skbuff[curidx];
-
- dma_unmap_single(fep->dev, CBDR_BUFADDR(bdp),
- L1_CACHE_ALIGN(PKT_MAXBUF_SIZE),
- DMA_FROM_DEVICE);
-
- skbn = skb;
-
- } else {
-
- skb = fep->rx_skbuff[curidx];
-
- dma_unmap_single(fep->dev, CBDR_BUFADDR(bdp),
- L1_CACHE_ALIGN(PKT_MAXBUF_SIZE),
- DMA_FROM_DEVICE);
-
- /*
- * Process the incoming frame.
- */
- fep->stats.rx_packets++;
- pkt_len = CBDR_DATLEN(bdp) - 4; /* remove CRC */
- fep->stats.rx_bytes += pkt_len + 4;
-
- if (pkt_len <= fpi->rx_copybreak) {
- /* +2 to make IP header L1 cache aligned */
- skbn = netdev_alloc_skb(dev, pkt_len + 2);
- if (skbn != NULL) {
- skb_reserve(skbn, 2); /* align IP header */
- skb_copy_from_linear_data(skb,
- skbn->data, pkt_len);
- /* swap */
- skbt = skb;
- skb = skbn;
- skbn = skbt;
- }
- } else {
- skbn = netdev_alloc_skb(dev, ENET_RX_FRSIZE);
-
- if (skbn)
- skb_align(skbn, ENET_RX_ALIGN);
- }
-
- if (skbn != NULL) {
- skb_put(skb, pkt_len); /* Make room */
- skb->protocol = eth_type_trans(skb, dev);
- received++;
- netif_rx(skb);
- } else {
- fep->stats.rx_dropped++;
- skbn = skb;
- }
- }
-
- fep->rx_skbuff[curidx] = skbn;
- CBDW_BUFADDR(bdp, dma_map_single(fep->dev, skbn->data,
- L1_CACHE_ALIGN(PKT_MAXBUF_SIZE),
- DMA_FROM_DEVICE));
- CBDW_DATLEN(bdp, 0);
- CBDW_SC(bdp, (sc & ~BD_ENET_RX_STATS) | BD_ENET_RX_EMPTY);
-
- /*
- * Update BD pointer to next entry.
- */
- if ((sc & BD_ENET_RX_WRAP) == 0)
- bdp++;
- else
- bdp = fep->rx_bd_base;
-
- (*fep->ops->rx_bd_done)(dev);
- }
-
- fep->cur_rx = bdp;
-
- return 0;
-}
-
-static void fs_enet_tx(struct net_device *dev)
-{
- struct fs_enet_private *fep = netdev_priv(dev);
+ struct fs_enet_private *fep = container_of(napi, struct fs_enet_private,
+ napi_tx);
+ struct net_device *dev = fep->ndev;
cbd_t __iomem *bdp;
struct sk_buff *skb;
int dirtyidx, do_wake, do_restart;
u16 sc;
+ int has_tx_work = 0;
spin_lock(&fep->tx_lock);
bdp = fep->dirty_tx;
+ /* clear TX status bits for napi*/
+ (*fep->ops->napi_clear_tx_event)(dev);
+
do_wake = do_restart = 0;
while (((sc = CBDR_SC(bdp)) & BD_ENET_TX_READY) == 0) {
dirtyidx = bdp - fep->tx_bd_base;
@@ -400,7 +284,7 @@ static void fs_enet_tx(struct net_device *dev)
/*
* Free the sk buffer associated with this last transmit.
*/
- dev_kfree_skb_irq(skb);
+ dev_kfree_skb(skb);
fep->tx_skbuff[dirtyidx] = NULL;
/*
@@ -417,6 +301,7 @@ static void fs_enet_tx(struct net_device *dev)
*/
if (!fep->tx_free++)
do_wake = 1;
+ has_tx_work = 1;
}
fep->dirty_tx = bdp;
@@ -424,10 +309,19 @@ static void fs_enet_tx(struct net_device *dev)
if (do_restart)
(*fep->ops->tx_restart)(dev);
+ if (!has_tx_work) {
+ napi_complete(napi);
+ (*fep->ops->napi_enable_tx)(dev);
+ }
+
spin_unlock(&fep->tx_lock);
if (do_wake)
netif_wake_queue(dev);
+
+ if (has_tx_work)
+ return budget;
+ return 0;
}
/*
@@ -453,8 +347,7 @@ fs_enet_interrupt(int irq, void *dev_id)
nr++;
int_clr_events = int_events;
- if (fpi->use_napi)
- int_clr_events &= ~fep->ev_napi_rx;
+ int_clr_events &= ~fep->ev_napi_rx;
(*fep->ops->clear_int_events)(dev, int_clr_events);
@@ -462,23 +355,28 @@ fs_enet_interrupt(int irq, void *dev_id)
(*fep->ops->ev_error)(dev, int_events);
if (int_events & fep->ev_rx) {
- if (!fpi->use_napi)
- fs_enet_rx_non_napi(dev);
- else {
- napi_ok = napi_schedule_prep(&fep->napi);
-
- (*fep->ops->napi_disable_rx)(dev);
- (*fep->ops->clear_int_events)(dev, fep->ev_napi_rx);
-
- /* NOTE: it is possible for FCCs in NAPI mode */
- /* to submit a spurious interrupt while in poll */
- if (napi_ok)
- __napi_schedule(&fep->napi);
- }
+ napi_ok = napi_schedule_prep(&fep->napi);
+
+ (*fep->ops->napi_disable_rx)(dev);
+ (*fep->ops->clear_int_events)(dev, fep->ev_napi_rx);
+
+ /* NOTE: it is possible for FCCs in NAPI mode */
+ /* to submit a spurious interrupt while in poll */
+ if (napi_ok)
+ __napi_schedule(&fep->napi);
}
- if (int_events & fep->ev_tx)
- fs_enet_tx(dev);
+ if (int_events & fep->ev_tx) {
+ napi_ok = napi_schedule_prep(&fep->napi_tx);
+
+ (*fep->ops->napi_disable_tx)(dev);
+ (*fep->ops->clear_int_events)(dev, fep->ev_napi_tx);
+
+ /* NOTE: it is possible for FCCs in NAPI mode */
+ /* to submit a spurious interrupt while in poll */
+ if (napi_ok)
+ __napi_schedule(&fep->napi_tx);
+ }
}
handled = nr > 0;
@@ -611,7 +509,6 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
cbd_t __iomem *bdp;
int curidx;
u16 sc;
- unsigned long flags;
#ifdef CONFIG_FS_ENET_MPC5121_FEC
if (((unsigned long)skb->data) & 0x3) {
@@ -626,7 +523,7 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
}
#endif
- spin_lock_irqsave(&fep->tx_lock, flags);
+ spin_lock(&fep->tx_lock);
/*
* Fill in a Tx ring entry
@@ -635,7 +532,7 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (!fep->tx_free || (CBDR_SC(bdp) & BD_ENET_TX_READY)) {
netif_stop_queue(dev);
- spin_unlock_irqrestore(&fep->tx_lock, flags);
+ spin_unlock(&fep->tx_lock);
/*
* Ooops. All transmit buffers are full. Bail out.
@@ -691,7 +588,7 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
(*fep->ops->tx_kickstart)(dev);
- spin_unlock_irqrestore(&fep->tx_lock, flags);
+ spin_unlock(&fep->tx_lock);
return NETDEV_TX_OK;
}
@@ -811,24 +708,24 @@ static int fs_enet_open(struct net_device *dev)
/* not doing this, will cause a crash in fs_enet_rx_napi */
fs_init_bds(fep->ndev);
- if (fep->fpi->use_napi)
- napi_enable(&fep->napi);
+ napi_enable(&fep->napi);
+ napi_enable(&fep->napi_tx);
/* Install our interrupt handler. */
r = request_irq(fep->interrupt, fs_enet_interrupt, IRQF_SHARED,
"fs_enet-mac", dev);
if (r != 0) {
dev_err(fep->dev, "Could not allocate FS_ENET IRQ!");
- if (fep->fpi->use_napi)
- napi_disable(&fep->napi);
+ napi_disable(&fep->napi);
+ napi_disable(&fep->napi_tx);
return -EINVAL;
}
err = fs_init_phy(dev);
if (err) {
free_irq(fep->interrupt, dev);
- if (fep->fpi->use_napi)
- napi_disable(&fep->napi);
+ napi_disable(&fep->napi);
+ napi_disable(&fep->napi_tx);
return err;
}
phy_start(fep->phydev);
@@ -845,8 +742,8 @@ static int fs_enet_close(struct net_device *dev)
netif_stop_queue(dev);
netif_carrier_off(dev);
- if (fep->fpi->use_napi)
- napi_disable(&fep->napi);
+ napi_disable(&fep->napi);
+ napi_disable(&fep->napi_tx);
phy_stop(fep->phydev);
spin_lock_irqsave(&fep->lock, flags);
@@ -1022,7 +919,6 @@ static int fs_enet_probe(struct platform_device *ofdev)
fpi->rx_ring = 32;
fpi->tx_ring = 32;
fpi->rx_copybreak = 240;
- fpi->use_napi = 1;
fpi->napi_weight = 17;
fpi->phy_node = of_parse_phandle(ofdev->dev.of_node, "phy-handle", 0);
if (!fpi->phy_node && of_phy_is_fixed_link(ofdev->dev.of_node)) {
@@ -1102,9 +998,8 @@ static int fs_enet_probe(struct platform_device *ofdev)
ndev->netdev_ops = &fs_enet_netdev_ops;
ndev->watchdog_timeo = 2 * HZ;
- if (fpi->use_napi)
- netif_napi_add(ndev, &fep->napi, fs_enet_rx_napi,
- fpi->napi_weight);
+ netif_napi_add(ndev, &fep->napi, fs_enet_rx_napi, fpi->napi_weight);
+ netif_napi_add(ndev, &fep->napi_tx, fs_enet_tx_napi, 2);
ndev->ethtool_ops = &fs_ethtool_ops;
diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet.h b/drivers/net/ethernet/freescale/fs_enet/fs_enet.h
index 1ece4b1a689e..3a4b49e0e717 100644
--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet.h
+++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet.h
@@ -84,6 +84,9 @@ struct fs_ops {
void (*napi_clear_rx_event)(struct net_device *dev);
void (*napi_enable_rx)(struct net_device *dev);
void (*napi_disable_rx)(struct net_device *dev);
+ void (*napi_clear_tx_event)(struct net_device *dev);
+ void (*napi_enable_tx)(struct net_device *dev);
+ void (*napi_disable_tx)(struct net_device *dev);
void (*rx_bd_done)(struct net_device *dev);
void (*tx_kickstart)(struct net_device *dev);
u32 (*get_int_events)(struct net_device *dev);
@@ -119,6 +122,7 @@ struct phy_info {
struct fs_enet_private {
struct napi_struct napi;
+ struct napi_struct napi_tx;
struct device *dev; /* pointer back to the device (must be initialized first) */
struct net_device *ndev;
spinlock_t lock; /* during all ops except TX pckt processing */
@@ -149,6 +153,7 @@ struct fs_enet_private {
/* event masks */
u32 ev_napi_rx; /* mask of NAPI rx events */
+ u32 ev_napi_tx; /* mask of NAPI rx events */
u32 ev_rx; /* rx event mask */
u32 ev_tx; /* tx event mask */
u32 ev_err; /* error event mask */
@@ -191,8 +196,8 @@ void fs_cleanup_bds(struct net_device *dev);
#define DRV_MODULE_NAME "fs_enet"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "1.0"
-#define DRV_MODULE_RELDATE "Aug 8, 2005"
+#define DRV_MODULE_VERSION "1.1"
+#define DRV_MODULE_RELDATE "Sep 22, 2014"
/***************************************************************************/
diff --git a/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c b/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c
index f5383abbf399..08f5b911d96b 100644
--- a/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c
+++ b/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c
@@ -125,6 +125,7 @@ out:
}
#define FCC_NAPI_RX_EVENT_MSK (FCC_ENET_RXF | FCC_ENET_RXB)
+#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)
@@ -137,6 +138,7 @@ static int setup_data(struct net_device *dev)
return -EINVAL;
fep->ev_napi_rx = FCC_NAPI_RX_EVENT_MSK;
+ fep->ev_napi_tx = FCC_NAPI_TX_EVENT_MSK;
fep->ev_rx = FCC_RX_EVENT;
fep->ev_tx = FCC_TX_EVENT;
fep->ev_err = FCC_ERR_EVENT_MSK;
@@ -446,6 +448,30 @@ static void napi_disable_rx(struct net_device *dev)
C16(fccp, fcc_fccm, FCC_NAPI_RX_EVENT_MSK);
}
+static void napi_clear_tx_event(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ fcc_t __iomem *fccp = fep->fcc.fccp;
+
+ W16(fccp, fcc_fcce, FCC_NAPI_TX_EVENT_MSK);
+}
+
+static void napi_enable_tx(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ fcc_t __iomem *fccp = fep->fcc.fccp;
+
+ S16(fccp, fcc_fccm, FCC_NAPI_TX_EVENT_MSK);
+}
+
+static void napi_disable_tx(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ fcc_t __iomem *fccp = fep->fcc.fccp;
+
+ C16(fccp, fcc_fccm, FCC_NAPI_TX_EVENT_MSK);
+}
+
static void rx_bd_done(struct net_device *dev)
{
/* nothing */
@@ -572,6 +598,9 @@ const struct fs_ops fs_fcc_ops = {
.napi_clear_rx_event = napi_clear_rx_event,
.napi_enable_rx = napi_enable_rx,
.napi_disable_rx = napi_disable_rx,
+ .napi_clear_tx_event = napi_clear_tx_event,
+ .napi_enable_tx = napi_enable_tx,
+ .napi_disable_tx = napi_disable_tx,
.rx_bd_done = rx_bd_done,
.tx_kickstart = tx_kickstart,
.get_int_events = get_int_events,
diff --git a/drivers/net/ethernet/freescale/fs_enet/mac-fec.c b/drivers/net/ethernet/freescale/fs_enet/mac-fec.c
index 1eedfba2ad3c..3d4e08be1709 100644
--- a/drivers/net/ethernet/freescale/fs_enet/mac-fec.c
+++ b/drivers/net/ethernet/freescale/fs_enet/mac-fec.c
@@ -110,6 +110,7 @@ static int do_pd_setup(struct fs_enet_private *fep)
}
#define FEC_NAPI_RX_EVENT_MSK (FEC_ENET_RXF | FEC_ENET_RXB)
+#define FEC_NAPI_TX_EVENT_MSK (FEC_ENET_TXF | FEC_ENET_TXB)
#define FEC_RX_EVENT (FEC_ENET_RXF)
#define FEC_TX_EVENT (FEC_ENET_TXF)
#define FEC_ERR_EVENT_MSK (FEC_ENET_HBERR | FEC_ENET_BABR | \
@@ -126,6 +127,7 @@ static int setup_data(struct net_device *dev)
fep->fec.htlo = 0;
fep->ev_napi_rx = FEC_NAPI_RX_EVENT_MSK;
+ fep->ev_napi_tx = FEC_NAPI_TX_EVENT_MSK;
fep->ev_rx = FEC_RX_EVENT;
fep->ev_tx = FEC_TX_EVENT;
fep->ev_err = FEC_ERR_EVENT_MSK;
@@ -415,6 +417,30 @@ static void napi_disable_rx(struct net_device *dev)
FC(fecp, imask, FEC_NAPI_RX_EVENT_MSK);
}
+static void napi_clear_tx_event(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ struct fec __iomem *fecp = fep->fec.fecp;
+
+ FW(fecp, ievent, FEC_NAPI_TX_EVENT_MSK);
+}
+
+static void napi_enable_tx(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ struct fec __iomem *fecp = fep->fec.fecp;
+
+ FS(fecp, imask, FEC_NAPI_TX_EVENT_MSK);
+}
+
+static void napi_disable_tx(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ struct fec __iomem *fecp = fep->fec.fecp;
+
+ FC(fecp, imask, FEC_NAPI_TX_EVENT_MSK);
+}
+
static void rx_bd_done(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
@@ -487,6 +513,9 @@ const struct fs_ops fs_fec_ops = {
.napi_clear_rx_event = napi_clear_rx_event,
.napi_enable_rx = napi_enable_rx,
.napi_disable_rx = napi_disable_rx,
+ .napi_clear_tx_event = napi_clear_tx_event,
+ .napi_enable_tx = napi_enable_tx,
+ .napi_disable_tx = napi_disable_tx,
.rx_bd_done = rx_bd_done,
.tx_kickstart = tx_kickstart,
.get_int_events = get_int_events,
diff --git a/drivers/net/ethernet/freescale/fs_enet/mac-scc.c b/drivers/net/ethernet/freescale/fs_enet/mac-scc.c
index 90b3b19b7cd3..f30411f0701f 100644
--- a/drivers/net/ethernet/freescale/fs_enet/mac-scc.c
+++ b/drivers/net/ethernet/freescale/fs_enet/mac-scc.c
@@ -116,6 +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_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)
@@ -130,6 +131,7 @@ static int setup_data(struct net_device *dev)
fep->scc.htlo = 0;
fep->ev_napi_rx = SCC_NAPI_RX_EVENT_MSK;
+ fep->ev_napi_tx = SCC_NAPI_TX_EVENT_MSK;
fep->ev_rx = SCC_RX_EVENT;
fep->ev_tx = SCC_TX_EVENT | SCCE_ENET_TXE;
fep->ev_err = SCC_ERR_EVENT_MSK;
@@ -398,6 +400,30 @@ static void napi_disable_rx(struct net_device *dev)
C16(sccp, scc_sccm, SCC_NAPI_RX_EVENT_MSK);
}
+static void napi_clear_tx_event(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ scc_t __iomem *sccp = fep->scc.sccp;
+
+ W16(sccp, scc_scce, SCC_NAPI_TX_EVENT_MSK);
+}
+
+static void napi_enable_tx(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ scc_t __iomem *sccp = fep->scc.sccp;
+
+ S16(sccp, scc_sccm, SCC_NAPI_TX_EVENT_MSK);
+}
+
+static void napi_disable_tx(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ scc_t __iomem *sccp = fep->scc.sccp;
+
+ C16(sccp, scc_sccm, SCC_NAPI_TX_EVENT_MSK);
+}
+
static void rx_bd_done(struct net_device *dev)
{
/* nothing */
@@ -471,6 +497,9 @@ const struct fs_ops fs_scc_ops = {
.napi_clear_rx_event = napi_clear_rx_event,
.napi_enable_rx = napi_enable_rx,
.napi_disable_rx = napi_disable_rx,
+ .napi_clear_tx_event = napi_clear_tx_event,
+ .napi_enable_tx = napi_enable_tx,
+ .napi_disable_tx = napi_disable_tx,
.rx_bd_done = rx_bd_done,
.tx_kickstart = tx_kickstart,
.get_int_events = get_int_events,
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..379b1a578d3d 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;
}
@@ -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..6919adb66f53 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,
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index 267992b3de8a..3195d82e4942 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -2053,6 +2053,47 @@ static void i40e_create_tx_ctx(struct i40e_ring *tx_ring,
}
/**
+ * __i40e_maybe_stop_tx - 2nd level check for tx stop conditions
+ * @tx_ring: the ring to be checked
+ * @size: the size buffer we want to assure is available
+ *
+ * Returns -EBUSY if a stop is needed, else 0
+ **/
+static inline int __i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size)
+{
+ netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index);
+ /* Memory barrier before checking head and tail */
+ smp_mb();
+
+ /* Check again in a case another CPU has just made room available. */
+ if (likely(I40E_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;
+}
+
+/**
+ * i40e_maybe_stop_tx - 1st level check for tx stop conditions
+ * @tx_ring: the ring to be checked
+ * @size: the size buffer we want to assure is available
+ *
+ * Returns 0 if stop is not needed
+ **/
+#ifdef I40E_FCOE
+int i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size)
+#else
+static int i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size)
+#endif
+{
+ if (likely(I40E_DESC_UNUSED(tx_ring) >= size))
+ return 0;
+ return __i40e_maybe_stop_tx(tx_ring, size);
+}
+
+/**
* i40e_tx_map - Build the Tx descriptor
* @tx_ring: ring to send buffer on
* @skb: send buffer
@@ -2195,8 +2236,12 @@ static void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
tx_ring->next_to_use = i;
+ i40e_maybe_stop_tx(tx_ring, DESC_NEEDED);
/* notify HW of packet */
- writel(i, tx_ring->tail);
+ if (!skb->xmit_more ||
+ netif_xmit_stopped(netdev_get_tx_queue(tx_ring->netdev,
+ tx_ring->queue_index)))
+ writel(i, tx_ring->tail);
return;
@@ -2218,47 +2263,6 @@ dma_error:
}
/**
- * __i40e_maybe_stop_tx - 2nd level check for tx stop conditions
- * @tx_ring: the ring to be checked
- * @size: the size buffer we want to assure is available
- *
- * Returns -EBUSY if a stop is needed, else 0
- **/
-static inline int __i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size)
-{
- netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index);
- /* Memory barrier before checking head and tail */
- smp_mb();
-
- /* Check again in a case another CPU has just made room available. */
- if (likely(I40E_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;
-}
-
-/**
- * i40e_maybe_stop_tx - 1st level check for tx stop conditions
- * @tx_ring: the ring to be checked
- * @size: the size buffer we want to assure is available
- *
- * Returns 0 if stop is not needed
- **/
-#ifdef I40E_FCOE
-int i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size)
-#else
-static int i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size)
-#endif
-{
- if (likely(I40E_DESC_UNUSED(tx_ring) >= size))
- return 0;
- return __i40e_maybe_stop_tx(tx_ring, size);
-}
-
-/**
* i40e_xmit_descriptor_count - calculate number of tx descriptors needed
* @skb: send buffer
* @tx_ring: ring to send buffer on
@@ -2372,8 +2376,6 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
i40e_tx_map(tx_ring, skb, first, tx_flags, hdr_len,
td_cmd, td_offset);
- i40e_maybe_stop_tx(tx_ring, DESC_NEEDED);
-
return NETDEV_TX_OK;
out_drop:
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/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c
index 436c82f64304..b16e1b95566f 100644
--- a/drivers/net/ethernet/mellanox/mlx4/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c
@@ -1705,7 +1705,7 @@ static int mlx4_master_activate_admin_state(struct mlx4_priv *priv, int slave)
if (err) {
vp_oper->vlan_idx = NO_INDX;
mlx4_warn(&priv->dev,
- "No vlan resorces slave %d, port %d\n",
+ "No vlan resources slave %d, port %d\n",
slave, port);
return err;
}
@@ -1721,7 +1721,7 @@ static int mlx4_master_activate_admin_state(struct mlx4_priv *priv, int slave)
err = vp_oper->mac_idx;
vp_oper->mac_idx = NO_INDX;
mlx4_warn(&priv->dev,
- "No mac resorces slave %d, port %d\n",
+ "No mac resources slave %d, port %d\n",
slave, port);
return err;
}
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
index 92a7cf46d9af..34c137878545 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
@@ -392,7 +392,8 @@ static bool mlx4_en_process_tx_cq(struct net_device *dev,
if (!priv->port_up)
return true;
- prefetchw(&ring->tx_queue->dql.limit);
+ netdev_txq_bql_complete_prefetchw(ring->tx_queue);
+
index = cons_index & size_mask;
cqe = mlx4_en_get_cqe(buf, index, priv->cqe_size) + factor;
last_nr_txbb = ACCESS_ONCE(ring->last_nr_txbb);
@@ -706,6 +707,7 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
void *fragptr = NULL;
bool bounce = false;
bool send_doorbell;
+ bool stop_queue;
bool inline_ok;
u32 ring_cons;
@@ -735,32 +737,8 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
if (vlan_tx_tag_present(skb))
vlan_tag = vlan_tx_tag_get(skb);
- /* Check available TXBBs And 2K spare for prefetch */
- if (unlikely(((int)(ring->prod - ring_cons)) >
- ring->size - HEADROOM - MAX_DESC_TXBBS)) {
- /* every full Tx ring stops queue */
- netif_tx_stop_queue(ring->tx_queue);
- ring->queue_stopped++;
-
- /* If queue was emptied after the if, and before the
- * stop_queue - need to wake the queue, or else it will remain
- * stopped forever.
- * Need a memory barrier to make sure ring->cons was not
- * updated before queue was stopped.
- */
- wmb();
- ring_cons = ACCESS_ONCE(ring->cons);
- if (unlikely(((int)(ring->prod - ring_cons)) <=
- ring->size - HEADROOM - MAX_DESC_TXBBS)) {
- netif_tx_wake_queue(ring->tx_queue);
- ring->wake_queue++;
- } else {
- return NETDEV_TX_BUSY;
- }
- }
-
- prefetchw(&ring->tx_queue->dql);
+ netdev_txq_bql_enqueue_prefetchw(ring->tx_queue);
/* Track current inflight packets for performance analysis */
AVG_PERF_COUNTER(priv->pstats.inflight_avg,
@@ -929,6 +907,13 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
skb_tx_timestamp(skb);
+ /* Check available TXBBs And 2K spare for prefetch */
+ stop_queue = (int)(ring->prod - ring_cons) >
+ ring->size - HEADROOM - MAX_DESC_TXBBS;
+ if (unlikely(stop_queue)) {
+ netif_tx_stop_queue(ring->tx_queue);
+ ring->queue_stopped++;
+ }
send_doorbell = !skb->xmit_more || netif_xmit_stopped(ring->tx_queue);
real_size = (real_size / 16) & 0x3f;
@@ -973,6 +958,22 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
}
}
+ if (unlikely(stop_queue)) {
+ /* If queue was emptied after the if (stop_queue) , and before
+ * the netif_tx_stop_queue() - need to wake the queue,
+ * or else it will remain stopped forever.
+ * Need a memory barrier to make sure ring->cons was not
+ * updated before queue was stopped.
+ */
+ smp_rmb();
+
+ ring_cons = ACCESS_ONCE(ring->cons);
+ if (unlikely(((int)(ring->prod - ring_cons)) <=
+ ring->size - HEADROOM - MAX_DESC_TXBBS)) {
+ netif_tx_wake_queue(ring->tx_queue);
+ ring->wake_queue++;
+ }
+ }
return NETDEV_TX_OK;
tx_drop_unmap:
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c
index db4280ce9c09..716fc37ada5a 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c
@@ -922,7 +922,7 @@ int netxen_config_ipaddr(struct netxen_adapter *adapter, __be32 ip, int cmd)
rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
if (rv != 0) {
- printk(KERN_ERR "%s: could not notify %s IP 0x%x reuqest\n",
+ printk(KERN_ERR "%s: could not notify %s IP 0x%x request\n",
adapter->netdev->name,
(cmd == NX_IP_UP) ? "Add" : "Remove", ip);
}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index 8102673cb37f..69b46c051cc0 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -941,7 +941,7 @@ void qlcnic_82xx_config_ipaddr(struct qlcnic_adapter *adapter,
rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
if (rv != 0)
dev_err(&adapter->netdev->dev,
- "could not notify %s IP 0x%x reuqest\n",
+ "could not notify %s IP 0x%x request\n",
(cmd == QLCNIC_IP_UP) ? "Add" : "Remove", ip);
}
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index 54476ba42477..cf154f74cba1 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -155,6 +155,9 @@ enum mac_version {
RTL_GIGA_MAC_VER_46,
RTL_GIGA_MAC_VER_47,
RTL_GIGA_MAC_VER_48,
+ RTL_GIGA_MAC_VER_49,
+ RTL_GIGA_MAC_VER_50,
+ RTL_GIGA_MAC_VER_51,
RTL_GIGA_MAC_NONE = 0xff,
};
@@ -302,6 +305,15 @@ static const struct {
[RTL_GIGA_MAC_VER_48] =
_R("RTL8107e", RTL_TD_1, FIRMWARE_8107E_2,
JUMBO_1K, false),
+ [RTL_GIGA_MAC_VER_49] =
+ _R("RTL8168ep/8111ep", RTL_TD_1, NULL,
+ JUMBO_9K, false),
+ [RTL_GIGA_MAC_VER_50] =
+ _R("RTL8168ep/8111ep", RTL_TD_1, NULL,
+ JUMBO_9K, false),
+ [RTL_GIGA_MAC_VER_51] =
+ _R("RTL8168ep/8111ep", RTL_TD_1, NULL,
+ JUMBO_9K, false),
};
#undef _R
@@ -400,6 +412,10 @@ enum rtl_registers {
FuncEvent = 0xf0,
FuncEventMask = 0xf4,
FuncPresetState = 0xf8,
+ IBCR0 = 0xf8,
+ IBCR2 = 0xf9,
+ IBIMR0 = 0xfa,
+ IBISR0 = 0xfb,
FuncForceEvent = 0xfc,
};
@@ -467,6 +483,7 @@ enum rtl8168_registers {
#define ERIAR_EXGMAC (0x00 << ERIAR_TYPE_SHIFT)
#define ERIAR_MSIX (0x01 << ERIAR_TYPE_SHIFT)
#define ERIAR_ASF (0x02 << ERIAR_TYPE_SHIFT)
+#define ERIAR_OOB (0x02 << ERIAR_TYPE_SHIFT)
#define ERIAR_MASK_SHIFT 12
#define ERIAR_MASK_0001 (0x1 << ERIAR_MASK_SHIFT)
#define ERIAR_MASK_0011 (0x3 << ERIAR_MASK_SHIFT)
@@ -935,40 +952,6 @@ static const struct rtl_cond name = { \
\
static bool name ## _check(struct rtl8169_private *tp)
-DECLARE_RTL_COND(rtl_ocpar_cond)
-{
- void __iomem *ioaddr = tp->mmio_addr;
-
- return RTL_R32(OCPAR) & OCPAR_FLAG;
-}
-
-static u32 ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg)
-{
- void __iomem *ioaddr = tp->mmio_addr;
-
- RTL_W32(OCPAR, ((u32)mask & 0x0f) << 12 | (reg & 0x0fff));
-
- return rtl_udelay_loop_wait_high(tp, &rtl_ocpar_cond, 100, 20) ?
- RTL_R32(OCPDR) : ~0;
-}
-
-static void ocp_write(struct rtl8169_private *tp, u8 mask, u16 reg, u32 data)
-{
- void __iomem *ioaddr = tp->mmio_addr;
-
- RTL_W32(OCPDR, data);
- RTL_W32(OCPAR, OCPAR_FLAG | ((u32)mask & 0x0f) << 12 | (reg & 0x0fff));
-
- rtl_udelay_loop_wait_low(tp, &rtl_ocpar_cond, 100, 20);
-}
-
-DECLARE_RTL_COND(rtl_eriar_cond)
-{
- void __iomem *ioaddr = tp->mmio_addr;
-
- return RTL_R32(ERIAR) & ERIAR_FLAG;
-}
-
static bool rtl_ocp_reg_failure(struct rtl8169_private *tp, u32 reg)
{
if (reg & 0xffff0001) {
@@ -1110,6 +1093,13 @@ static int r8169_mdio_read(struct rtl8169_private *tp, int reg)
return value;
}
+DECLARE_RTL_COND(rtl_ocpar_cond)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ return RTL_R32(OCPAR) & OCPAR_FLAG;
+}
+
static void r8168dp_1_mdio_access(struct rtl8169_private *tp, int reg, u32 data)
{
void __iomem *ioaddr = tp->mmio_addr;
@@ -1245,6 +1235,13 @@ static u16 rtl_ephy_read(struct rtl8169_private *tp, int reg_addr)
RTL_R32(EPHYAR) & EPHYAR_DATA_MASK : ~0;
}
+DECLARE_RTL_COND(rtl_eriar_cond)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ return RTL_R32(ERIAR) & ERIAR_FLAG;
+}
+
static void rtl_eri_write(struct rtl8169_private *tp, int addr, u32 mask,
u32 val, int type)
{
@@ -1276,6 +1273,73 @@ static void rtl_w0w1_eri(struct rtl8169_private *tp, int addr, u32 mask, u32 p,
rtl_eri_write(tp, addr, mask, (val & ~m) | p, type);
}
+static u32 r8168dp_ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ RTL_W32(OCPAR, ((u32)mask & 0x0f) << 12 | (reg & 0x0fff));
+ return rtl_udelay_loop_wait_high(tp, &rtl_ocpar_cond, 100, 20) ?
+ RTL_R32(OCPDR) : ~0;
+}
+
+static u32 r8168ep_ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg)
+{
+ return rtl_eri_read(tp, reg, ERIAR_OOB);
+}
+
+static u32 ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg)
+{
+ switch (tp->mac_version) {
+ case RTL_GIGA_MAC_VER_27:
+ case RTL_GIGA_MAC_VER_28:
+ case RTL_GIGA_MAC_VER_31:
+ return r8168dp_ocp_read(tp, mask, reg);
+ case RTL_GIGA_MAC_VER_49:
+ case RTL_GIGA_MAC_VER_50:
+ case RTL_GIGA_MAC_VER_51:
+ return r8168ep_ocp_read(tp, mask, reg);
+ default:
+ BUG();
+ return ~0;
+ }
+}
+
+static void r8168dp_ocp_write(struct rtl8169_private *tp, u8 mask, u16 reg,
+ u32 data)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ RTL_W32(OCPDR, data);
+ RTL_W32(OCPAR, OCPAR_FLAG | ((u32)mask & 0x0f) << 12 | (reg & 0x0fff));
+ rtl_udelay_loop_wait_low(tp, &rtl_ocpar_cond, 100, 20);
+}
+
+static void r8168ep_ocp_write(struct rtl8169_private *tp, u8 mask, u16 reg,
+ u32 data)
+{
+ rtl_eri_write(tp, reg, ((u32)mask & 0x0f) << ERIAR_MASK_SHIFT,
+ data, ERIAR_OOB);
+}
+
+static void ocp_write(struct rtl8169_private *tp, u8 mask, u16 reg, u32 data)
+{
+ switch (tp->mac_version) {
+ case RTL_GIGA_MAC_VER_27:
+ case RTL_GIGA_MAC_VER_28:
+ case RTL_GIGA_MAC_VER_31:
+ r8168dp_ocp_write(tp, mask, reg, data);
+ break;
+ case RTL_GIGA_MAC_VER_49:
+ case RTL_GIGA_MAC_VER_50:
+ case RTL_GIGA_MAC_VER_51:
+ r8168ep_ocp_write(tp, mask, reg, data);
+ break;
+ default:
+ BUG();
+ break;
+ }
+}
+
static void rtl8168_oob_notify(struct rtl8169_private *tp, u8 cmd)
{
rtl_eri_write(tp, 0xe8, ERIAR_MASK_0001, cmd, ERIAR_EXGMAC);
@@ -1301,27 +1365,116 @@ DECLARE_RTL_COND(rtl_ocp_read_cond)
return ocp_read(tp, 0x0f, reg) & 0x00000800;
}
-static void rtl8168_driver_start(struct rtl8169_private *tp)
+DECLARE_RTL_COND(rtl_ep_ocp_read_cond)
{
- rtl8168_oob_notify(tp, OOB_CMD_DRIVER_START);
+ return ocp_read(tp, 0x0f, 0x124) & 0x00000001;
+}
+
+DECLARE_RTL_COND(rtl_ocp_tx_cond)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ return RTL_R8(IBISR0) & 0x02;
+}
+static void rtl8168dp_driver_start(struct rtl8169_private *tp)
+{
+ rtl8168_oob_notify(tp, OOB_CMD_DRIVER_START);
rtl_msleep_loop_wait_high(tp, &rtl_ocp_read_cond, 10, 10);
}
-static void rtl8168_driver_stop(struct rtl8169_private *tp)
+static void rtl8168ep_driver_start(struct rtl8169_private *tp)
{
- rtl8168_oob_notify(tp, OOB_CMD_DRIVER_STOP);
+ ocp_write(tp, 0x01, 0x180, OOB_CMD_DRIVER_START);
+ ocp_write(tp, 0x01, 0x30, ocp_read(tp, 0x01, 0x30) | 0x01);
+ rtl_msleep_loop_wait_high(tp, &rtl_ep_ocp_read_cond, 10, 10);
+}
+
+static void rtl8168_driver_start(struct rtl8169_private *tp)
+{
+ switch (tp->mac_version) {
+ case RTL_GIGA_MAC_VER_27:
+ case RTL_GIGA_MAC_VER_28:
+ case RTL_GIGA_MAC_VER_31:
+ rtl8168dp_driver_start(tp);
+ break;
+ case RTL_GIGA_MAC_VER_49:
+ case RTL_GIGA_MAC_VER_50:
+ case RTL_GIGA_MAC_VER_51:
+ rtl8168ep_driver_start(tp);
+ break;
+ default:
+ BUG();
+ break;
+ }
+}
+static void rtl8168dp_driver_stop(struct rtl8169_private *tp)
+{
+ rtl8168_oob_notify(tp, OOB_CMD_DRIVER_STOP);
rtl_msleep_loop_wait_low(tp, &rtl_ocp_read_cond, 10, 10);
}
-static int r8168_check_dash(struct rtl8169_private *tp)
+static void rtl8168ep_driver_stop(struct rtl8169_private *tp)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ RTL_W8(IBCR2, RTL_R8(IBCR2) & ~0x01);
+ rtl_msleep_loop_wait_low(tp, &rtl_ocp_tx_cond, 50, 2000);
+ RTL_W8(IBISR0, RTL_R8(IBISR0) | 0x20);
+ RTL_W8(IBCR0, RTL_R8(IBCR0) & ~0x01);
+ ocp_write(tp, 0x01, 0x180, OOB_CMD_DRIVER_STOP);
+ ocp_write(tp, 0x01, 0x30, ocp_read(tp, 0x01, 0x30) | 0x01);
+ rtl_msleep_loop_wait_low(tp, &rtl_ep_ocp_read_cond, 10, 10);
+}
+
+static void rtl8168_driver_stop(struct rtl8169_private *tp)
+{
+ switch (tp->mac_version) {
+ case RTL_GIGA_MAC_VER_27:
+ case RTL_GIGA_MAC_VER_28:
+ case RTL_GIGA_MAC_VER_31:
+ rtl8168dp_driver_stop(tp);
+ break;
+ case RTL_GIGA_MAC_VER_49:
+ case RTL_GIGA_MAC_VER_50:
+ case RTL_GIGA_MAC_VER_51:
+ rtl8168ep_driver_stop(tp);
+ break;
+ default:
+ BUG();
+ break;
+ }
+}
+
+static int r8168dp_check_dash(struct rtl8169_private *tp)
{
u16 reg = rtl8168_get_ocp_reg(tp);
return (ocp_read(tp, 0x0f, reg) & 0x00008000) ? 1 : 0;
}
+static int r8168ep_check_dash(struct rtl8169_private *tp)
+{
+ return (ocp_read(tp, 0x0f, 0x128) & 0x00000001) ? 1 : 0;
+}
+
+static int r8168_check_dash(struct rtl8169_private *tp)
+{
+ switch (tp->mac_version) {
+ case RTL_GIGA_MAC_VER_27:
+ case RTL_GIGA_MAC_VER_28:
+ case RTL_GIGA_MAC_VER_31:
+ return r8168dp_check_dash(tp);
+ case RTL_GIGA_MAC_VER_49:
+ case RTL_GIGA_MAC_VER_50:
+ case RTL_GIGA_MAC_VER_51:
+ return r8168ep_check_dash(tp);
+ default:
+ return 0;
+ }
+}
+
struct exgmac_reg {
u16 addr;
u16 mask;
@@ -1553,6 +1706,9 @@ static u32 __rtl8169_get_wol(struct rtl8169_private *tp)
case RTL_GIGA_MAC_VER_46:
case RTL_GIGA_MAC_VER_47:
case RTL_GIGA_MAC_VER_48:
+ case RTL_GIGA_MAC_VER_49:
+ case RTL_GIGA_MAC_VER_50:
+ case RTL_GIGA_MAC_VER_51:
if (rtl_eri_read(tp, 0xdc, ERIAR_EXGMAC) & MagicPacket_v2)
wolopts |= WAKE_MAGIC;
break;
@@ -1620,6 +1776,9 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
case RTL_GIGA_MAC_VER_46:
case RTL_GIGA_MAC_VER_47:
case RTL_GIGA_MAC_VER_48:
+ case RTL_GIGA_MAC_VER_49:
+ case RTL_GIGA_MAC_VER_50:
+ case RTL_GIGA_MAC_VER_51:
tmp = ARRAY_SIZE(cfg) - 1;
if (wolopts & WAKE_MAGIC)
rtl_w0w1_eri(tp,
@@ -2126,6 +2285,11 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp,
u32 val;
int mac_version;
} mac_info[] = {
+ /* 8168EP family. */
+ { 0x7cf00000, 0x50200000, RTL_GIGA_MAC_VER_51 },
+ { 0x7cf00000, 0x50100000, RTL_GIGA_MAC_VER_50 },
+ { 0x7cf00000, 0x50000000, RTL_GIGA_MAC_VER_49 },
+
/* 8168H family. */
{ 0x7cf00000, 0x54100000, RTL_GIGA_MAC_VER_46 },
{ 0x7cf00000, 0x54000000, RTL_GIGA_MAC_VER_45 },
@@ -3741,6 +3905,139 @@ static void rtl8168h_2_hw_phy_config(struct rtl8169_private *tp)
rtl_writephy(tp, 0x1f, 0x0000);
}
+static void rtl8168ep_1_hw_phy_config(struct rtl8169_private *tp)
+{
+ /* Enable PHY auto speed down */
+ rtl_writephy(tp, 0x1f, 0x0a44);
+ rtl_w0w1_phy(tp, 0x11, 0x000c, 0x0000);
+ rtl_writephy(tp, 0x1f, 0x0000);
+
+ /* patch 10M & ALDPS */
+ rtl_writephy(tp, 0x1f, 0x0bcc);
+ rtl_w0w1_phy(tp, 0x14, 0x0000, 0x0100);
+ rtl_writephy(tp, 0x1f, 0x0a44);
+ rtl_w0w1_phy(tp, 0x11, 0x00c0, 0x0000);
+ rtl_writephy(tp, 0x1f, 0x0a43);
+ rtl_writephy(tp, 0x13, 0x8084);
+ rtl_w0w1_phy(tp, 0x14, 0x0000, 0x6000);
+ rtl_w0w1_phy(tp, 0x10, 0x1003, 0x0000);
+ rtl_writephy(tp, 0x1f, 0x0000);
+
+ /* Enable EEE auto-fallback function */
+ rtl_writephy(tp, 0x1f, 0x0a4b);
+ rtl_w0w1_phy(tp, 0x11, 0x0004, 0x0000);
+ rtl_writephy(tp, 0x1f, 0x0000);
+
+ /* Enable UC LPF tune function */
+ rtl_writephy(tp, 0x1f, 0x0a43);
+ rtl_writephy(tp, 0x13, 0x8012);
+ rtl_w0w1_phy(tp, 0x14, 0x8000, 0x0000);
+ rtl_writephy(tp, 0x1f, 0x0000);
+
+ /* set rg_sel_sdm_rate */
+ rtl_writephy(tp, 0x1f, 0x0c42);
+ rtl_w0w1_phy(tp, 0x11, 0x4000, 0x2000);
+ rtl_writephy(tp, 0x1f, 0x0000);
+
+ /* Check ALDPS bit, disable it if enabled */
+ rtl_writephy(tp, 0x1f, 0x0a43);
+ if (rtl_readphy(tp, 0x10) & 0x0004)
+ rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0004);
+
+ rtl_writephy(tp, 0x1f, 0x0000);
+}
+
+static void rtl8168ep_2_hw_phy_config(struct rtl8169_private *tp)
+{
+ /* patch 10M & ALDPS */
+ rtl_writephy(tp, 0x1f, 0x0bcc);
+ rtl_w0w1_phy(tp, 0x14, 0x0000, 0x0100);
+ rtl_writephy(tp, 0x1f, 0x0a44);
+ rtl_w0w1_phy(tp, 0x11, 0x00c0, 0x0000);
+ rtl_writephy(tp, 0x1f, 0x0a43);
+ rtl_writephy(tp, 0x13, 0x8084);
+ rtl_w0w1_phy(tp, 0x14, 0x0000, 0x6000);
+ rtl_w0w1_phy(tp, 0x10, 0x1003, 0x0000);
+ rtl_writephy(tp, 0x1f, 0x0000);
+
+ /* Enable UC LPF tune function */
+ rtl_writephy(tp, 0x1f, 0x0a43);
+ rtl_writephy(tp, 0x13, 0x8012);
+ rtl_w0w1_phy(tp, 0x14, 0x8000, 0x0000);
+ rtl_writephy(tp, 0x1f, 0x0000);
+
+ /* Set rg_sel_sdm_rate */
+ rtl_writephy(tp, 0x1f, 0x0c42);
+ rtl_w0w1_phy(tp, 0x11, 0x4000, 0x2000);
+ rtl_writephy(tp, 0x1f, 0x0000);
+
+ /* Channel estimation parameters */
+ rtl_writephy(tp, 0x1f, 0x0a43);
+ rtl_writephy(tp, 0x13, 0x80f3);
+ rtl_w0w1_phy(tp, 0x14, 0x8b00, ~0x8bff);
+ rtl_writephy(tp, 0x13, 0x80f0);
+ rtl_w0w1_phy(tp, 0x14, 0x3a00, ~0x3aff);
+ rtl_writephy(tp, 0x13, 0x80ef);
+ rtl_w0w1_phy(tp, 0x14, 0x0500, ~0x05ff);
+ rtl_writephy(tp, 0x13, 0x80f6);
+ rtl_w0w1_phy(tp, 0x14, 0x6e00, ~0x6eff);
+ rtl_writephy(tp, 0x13, 0x80ec);
+ rtl_w0w1_phy(tp, 0x14, 0x6800, ~0x68ff);
+ rtl_writephy(tp, 0x13, 0x80ed);
+ rtl_w0w1_phy(tp, 0x14, 0x7c00, ~0x7cff);
+ rtl_writephy(tp, 0x13, 0x80f2);
+ rtl_w0w1_phy(tp, 0x14, 0xf400, ~0xf4ff);
+ rtl_writephy(tp, 0x13, 0x80f4);
+ rtl_w0w1_phy(tp, 0x14, 0x8500, ~0x85ff);
+ rtl_writephy(tp, 0x1f, 0x0a43);
+ rtl_writephy(tp, 0x13, 0x8110);
+ rtl_w0w1_phy(tp, 0x14, 0xa800, ~0xa8ff);
+ rtl_writephy(tp, 0x13, 0x810f);
+ rtl_w0w1_phy(tp, 0x14, 0x1d00, ~0x1dff);
+ rtl_writephy(tp, 0x13, 0x8111);
+ rtl_w0w1_phy(tp, 0x14, 0xf500, ~0xf5ff);
+ rtl_writephy(tp, 0x13, 0x8113);
+ rtl_w0w1_phy(tp, 0x14, 0x6100, ~0x61ff);
+ rtl_writephy(tp, 0x13, 0x8115);
+ rtl_w0w1_phy(tp, 0x14, 0x9200, ~0x92ff);
+ rtl_writephy(tp, 0x13, 0x810e);
+ rtl_w0w1_phy(tp, 0x14, 0x0400, ~0x04ff);
+ rtl_writephy(tp, 0x13, 0x810c);
+ rtl_w0w1_phy(tp, 0x14, 0x7c00, ~0x7cff);
+ rtl_writephy(tp, 0x13, 0x810b);
+ rtl_w0w1_phy(tp, 0x14, 0x5a00, ~0x5aff);
+ rtl_writephy(tp, 0x1f, 0x0a43);
+ rtl_writephy(tp, 0x13, 0x80d1);
+ rtl_w0w1_phy(tp, 0x14, 0xff00, ~0xffff);
+ rtl_writephy(tp, 0x13, 0x80cd);
+ rtl_w0w1_phy(tp, 0x14, 0x9e00, ~0x9eff);
+ rtl_writephy(tp, 0x13, 0x80d3);
+ rtl_w0w1_phy(tp, 0x14, 0x0e00, ~0x0eff);
+ rtl_writephy(tp, 0x13, 0x80d5);
+ rtl_w0w1_phy(tp, 0x14, 0xca00, ~0xcaff);
+ rtl_writephy(tp, 0x13, 0x80d7);
+ rtl_w0w1_phy(tp, 0x14, 0x8400, ~0x84ff);
+
+ /* Force PWM-mode */
+ rtl_writephy(tp, 0x1f, 0x0bcd);
+ rtl_writephy(tp, 0x14, 0x5065);
+ rtl_writephy(tp, 0x14, 0xd065);
+ rtl_writephy(tp, 0x1f, 0x0bc8);
+ rtl_writephy(tp, 0x12, 0x00ed);
+ rtl_writephy(tp, 0x1f, 0x0bcd);
+ rtl_writephy(tp, 0x14, 0x1065);
+ rtl_writephy(tp, 0x14, 0x9065);
+ rtl_writephy(tp, 0x14, 0x1065);
+ rtl_writephy(tp, 0x1f, 0x0000);
+
+ /* Check ALDPS bit, disable it if enabled */
+ rtl_writephy(tp, 0x1f, 0x0a43);
+ if (rtl_readphy(tp, 0x10) & 0x0004)
+ rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0004);
+
+ rtl_writephy(tp, 0x1f, 0x0000);
+}
+
static void rtl8102e_hw_phy_config(struct rtl8169_private *tp)
{
static const struct phy_reg phy_reg_init[] = {
@@ -3940,6 +4237,14 @@ static void rtl_hw_phy_config(struct net_device *dev)
rtl8168h_2_hw_phy_config(tp);
break;
+ case RTL_GIGA_MAC_VER_49:
+ rtl8168ep_1_hw_phy_config(tp);
+ break;
+ case RTL_GIGA_MAC_VER_50:
+ case RTL_GIGA_MAC_VER_51:
+ rtl8168ep_2_hw_phy_config(tp);
+ break;
+
case RTL_GIGA_MAC_VER_41:
default:
break;
@@ -4154,6 +4459,9 @@ static void rtl_init_mdio_ops(struct rtl8169_private *tp)
case RTL_GIGA_MAC_VER_46:
case RTL_GIGA_MAC_VER_47:
case RTL_GIGA_MAC_VER_48:
+ case RTL_GIGA_MAC_VER_49:
+ case RTL_GIGA_MAC_VER_50:
+ case RTL_GIGA_MAC_VER_51:
ops->write = r8168g_mdio_write;
ops->read = r8168g_mdio_read;
break;
@@ -4212,6 +4520,9 @@ static void rtl_wol_suspend_quirk(struct rtl8169_private *tp)
case RTL_GIGA_MAC_VER_46:
case RTL_GIGA_MAC_VER_47:
case RTL_GIGA_MAC_VER_48:
+ case RTL_GIGA_MAC_VER_49:
+ case RTL_GIGA_MAC_VER_50:
+ case RTL_GIGA_MAC_VER_51:
RTL_W32(RxConfig, RTL_R32(RxConfig) |
AcceptBroadcast | AcceptMulticast | AcceptMyPhys);
break;
@@ -4356,7 +4667,10 @@ static void r8168_pll_power_down(struct rtl8169_private *tp)
if ((tp->mac_version == RTL_GIGA_MAC_VER_27 ||
tp->mac_version == RTL_GIGA_MAC_VER_28 ||
- tp->mac_version == RTL_GIGA_MAC_VER_31) &&
+ tp->mac_version == RTL_GIGA_MAC_VER_31 ||
+ tp->mac_version == RTL_GIGA_MAC_VER_49 ||
+ tp->mac_version == RTL_GIGA_MAC_VER_50 ||
+ tp->mac_version == RTL_GIGA_MAC_VER_51) &&
r8168_check_dash(tp)) {
return;
}
@@ -4387,10 +4701,13 @@ static void r8168_pll_power_down(struct rtl8169_private *tp)
case RTL_GIGA_MAC_VER_44:
case RTL_GIGA_MAC_VER_45:
case RTL_GIGA_MAC_VER_46:
+ case RTL_GIGA_MAC_VER_50:
+ case RTL_GIGA_MAC_VER_51:
RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80);
break;
case RTL_GIGA_MAC_VER_40:
case RTL_GIGA_MAC_VER_41:
+ case RTL_GIGA_MAC_VER_49:
rtl_w0w1_eri(tp, 0x1a8, ERIAR_MASK_1111, 0x00000000,
0xfc000000, ERIAR_EXGMAC);
RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80);
@@ -4415,10 +4732,13 @@ static void r8168_pll_power_up(struct rtl8169_private *tp)
case RTL_GIGA_MAC_VER_44:
case RTL_GIGA_MAC_VER_45:
case RTL_GIGA_MAC_VER_46:
+ case RTL_GIGA_MAC_VER_50:
+ case RTL_GIGA_MAC_VER_51:
RTL_W8(PMCH, RTL_R8(PMCH) | 0xc0);
break;
case RTL_GIGA_MAC_VER_40:
case RTL_GIGA_MAC_VER_41:
+ case RTL_GIGA_MAC_VER_49:
RTL_W8(PMCH, RTL_R8(PMCH) | 0xc0);
rtl_w0w1_eri(tp, 0x1a8, ERIAR_MASK_1111, 0xfc000000,
0x00000000, ERIAR_EXGMAC);
@@ -4493,6 +4813,9 @@ static void rtl_init_pll_power_ops(struct rtl8169_private *tp)
case RTL_GIGA_MAC_VER_44:
case RTL_GIGA_MAC_VER_45:
case RTL_GIGA_MAC_VER_46:
+ case RTL_GIGA_MAC_VER_49:
+ case RTL_GIGA_MAC_VER_50:
+ case RTL_GIGA_MAC_VER_51:
ops->down = r8168_pll_power_down;
ops->up = r8168_pll_power_up;
break;
@@ -4547,6 +4870,9 @@ static void rtl_init_rxcfg(struct rtl8169_private *tp)
case RTL_GIGA_MAC_VER_46:
case RTL_GIGA_MAC_VER_47:
case RTL_GIGA_MAC_VER_48:
+ case RTL_GIGA_MAC_VER_49:
+ case RTL_GIGA_MAC_VER_50:
+ case RTL_GIGA_MAC_VER_51:
RTL_W32(RxConfig, RX128_INT_EN | RX_DMA_BURST | RX_EARLY_OFF);
break;
default:
@@ -4712,6 +5038,9 @@ static void rtl_init_jumbo_ops(struct rtl8169_private *tp)
case RTL_GIGA_MAC_VER_46:
case RTL_GIGA_MAC_VER_47:
case RTL_GIGA_MAC_VER_48:
+ case RTL_GIGA_MAC_VER_49:
+ case RTL_GIGA_MAC_VER_50:
+ case RTL_GIGA_MAC_VER_51:
default:
ops->disable = NULL;
ops->enable = NULL;
@@ -4828,7 +5157,10 @@ static void rtl8169_hw_reset(struct rtl8169_private *tp)
tp->mac_version == RTL_GIGA_MAC_VER_45 ||
tp->mac_version == RTL_GIGA_MAC_VER_46 ||
tp->mac_version == RTL_GIGA_MAC_VER_47 ||
- tp->mac_version == RTL_GIGA_MAC_VER_48) {
+ tp->mac_version == RTL_GIGA_MAC_VER_48 ||
+ tp->mac_version == RTL_GIGA_MAC_VER_49 ||
+ tp->mac_version == RTL_GIGA_MAC_VER_50 ||
+ tp->mac_version == RTL_GIGA_MAC_VER_51) {
RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq);
rtl_udelay_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 666);
} else {
@@ -5754,6 +6086,120 @@ static void rtl_hw_start_8168h_1(struct rtl8169_private *tp)
r8168_mac_ocp_write(tp, 0xc09e, 0x0000);
}
+static void rtl_hw_start_8168ep(struct rtl8169_private *tp)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+ struct pci_dev *pdev = tp->pci_dev;
+
+ RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
+
+ rtl_eri_write(tp, 0xc8, ERIAR_MASK_0101, 0x00080002, ERIAR_EXGMAC);
+ rtl_eri_write(tp, 0xcc, ERIAR_MASK_0001, 0x2f, ERIAR_EXGMAC);
+ rtl_eri_write(tp, 0xd0, ERIAR_MASK_0001, 0x5f, ERIAR_EXGMAC);
+ rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
+
+ rtl_csi_access_enable_1(tp);
+
+ rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
+
+ rtl_w0w1_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
+ rtl_w0w1_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
+
+ rtl_w0w1_eri(tp, 0xd4, ERIAR_MASK_1111, 0x1f80, 0x00, ERIAR_EXGMAC);
+
+ rtl_eri_write(tp, 0x5f0, ERIAR_MASK_0011, 0x4f87, ERIAR_EXGMAC);
+
+ RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+ RTL_W32(MISC, RTL_R32(MISC) & ~RXDV_GATED_EN);
+ RTL_W8(MaxTxPacketSize, EarlySize);
+
+ rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
+ rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
+
+ /* Adjust EEE LED frequency */
+ RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
+
+ rtl_w0w1_eri(tp, 0x2fc, ERIAR_MASK_0001, 0x01, 0x06, ERIAR_EXGMAC);
+
+ RTL_W8(DLLPR, RTL_R8(DLLPR) & ~TX_10M_PS_EN);
+
+ rtl_pcie_state_l2l3_enable(tp, false);
+}
+
+static void rtl_hw_start_8168ep_1(struct rtl8169_private *tp)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+ static const struct ephy_info e_info_8168ep_1[] = {
+ { 0x00, 0xffff, 0x10ab },
+ { 0x06, 0xffff, 0xf030 },
+ { 0x08, 0xffff, 0x2006 },
+ { 0x0d, 0xffff, 0x1666 },
+ { 0x0c, 0x3ff0, 0x0000 }
+ };
+
+ /* disable aspm and clock request before access ephy */
+ RTL_W8(Config2, RTL_R8(Config2) & ~ClkReqEn);
+ RTL_W8(Config5, RTL_R8(Config5) & ~ASPM_en);
+ rtl_ephy_init(tp, e_info_8168ep_1, ARRAY_SIZE(e_info_8168ep_1));
+
+ rtl_hw_start_8168ep(tp);
+}
+
+static void rtl_hw_start_8168ep_2(struct rtl8169_private *tp)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+ static const struct ephy_info e_info_8168ep_2[] = {
+ { 0x00, 0xffff, 0x10a3 },
+ { 0x19, 0xffff, 0xfc00 },
+ { 0x1e, 0xffff, 0x20ea }
+ };
+
+ /* disable aspm and clock request before access ephy */
+ RTL_W8(Config2, RTL_R8(Config2) & ~ClkReqEn);
+ RTL_W8(Config5, RTL_R8(Config5) & ~ASPM_en);
+ rtl_ephy_init(tp, e_info_8168ep_2, ARRAY_SIZE(e_info_8168ep_2));
+
+ rtl_hw_start_8168ep(tp);
+
+ RTL_W8(DLLPR, RTL_R8(DLLPR) & ~PFM_EN);
+ RTL_W8(DLLPR, RTL_R8(MISC_1) & ~PFM_D3COLD_EN);
+}
+
+static void rtl_hw_start_8168ep_3(struct rtl8169_private *tp)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+ u32 data;
+ static const struct ephy_info e_info_8168ep_3[] = {
+ { 0x00, 0xffff, 0x10a3 },
+ { 0x19, 0xffff, 0x7c00 },
+ { 0x1e, 0xffff, 0x20eb },
+ { 0x0d, 0xffff, 0x1666 }
+ };
+
+ /* disable aspm and clock request before access ephy */
+ RTL_W8(Config2, RTL_R8(Config2) & ~ClkReqEn);
+ RTL_W8(Config5, RTL_R8(Config5) & ~ASPM_en);
+ rtl_ephy_init(tp, e_info_8168ep_3, ARRAY_SIZE(e_info_8168ep_3));
+
+ rtl_hw_start_8168ep(tp);
+
+ RTL_W8(DLLPR, RTL_R8(DLLPR) & ~PFM_EN);
+ RTL_W8(DLLPR, RTL_R8(MISC_1) & ~PFM_D3COLD_EN);
+
+ data = r8168_mac_ocp_read(tp, 0xd3e2);
+ data &= 0xf000;
+ data |= 0x0271;
+ r8168_mac_ocp_write(tp, 0xd3e2, data);
+
+ data = r8168_mac_ocp_read(tp, 0xd3e4);
+ data &= 0xff00;
+ r8168_mac_ocp_write(tp, 0xd3e4, data);
+
+ data = r8168_mac_ocp_read(tp, 0xe860);
+ data |= 0x0080;
+ r8168_mac_ocp_write(tp, 0xe860, data);
+}
+
static void rtl_hw_start_8168(struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
@@ -5869,6 +6315,18 @@ static void rtl_hw_start_8168(struct net_device *dev)
rtl_hw_start_8168h_1(tp);
break;
+ case RTL_GIGA_MAC_VER_49:
+ rtl_hw_start_8168ep_1(tp);
+ break;
+
+ case RTL_GIGA_MAC_VER_50:
+ rtl_hw_start_8168ep_2(tp);
+ break;
+
+ case RTL_GIGA_MAC_VER_51:
+ rtl_hw_start_8168ep_3(tp);
+ break;
+
default:
printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n",
dev->name, tp->mac_version);
@@ -7399,7 +7857,10 @@ static void rtl_remove_one(struct pci_dev *pdev)
if ((tp->mac_version == RTL_GIGA_MAC_VER_27 ||
tp->mac_version == RTL_GIGA_MAC_VER_28 ||
- tp->mac_version == RTL_GIGA_MAC_VER_31) &&
+ tp->mac_version == RTL_GIGA_MAC_VER_31 ||
+ tp->mac_version == RTL_GIGA_MAC_VER_49 ||
+ tp->mac_version == RTL_GIGA_MAC_VER_50 ||
+ tp->mac_version == RTL_GIGA_MAC_VER_51) &&
r8168_check_dash(tp)) {
rtl8168_driver_stop(tp);
}
@@ -7556,6 +8017,9 @@ static void rtl_hw_initialize(struct rtl8169_private *tp)
case RTL_GIGA_MAC_VER_46:
case RTL_GIGA_MAC_VER_47:
case RTL_GIGA_MAC_VER_48:
+ case RTL_GIGA_MAC_VER_49:
+ case RTL_GIGA_MAC_VER_50:
+ case RTL_GIGA_MAC_VER_51:
rtl_hw_init_8168g(tp);
break;
@@ -7708,6 +8172,9 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
case RTL_GIGA_MAC_VER_46:
case RTL_GIGA_MAC_VER_47:
case RTL_GIGA_MAC_VER_48:
+ case RTL_GIGA_MAC_VER_49:
+ case RTL_GIGA_MAC_VER_50:
+ case RTL_GIGA_MAC_VER_51:
if (rtl_eri_read(tp, 0xdc, ERIAR_EXGMAC) & MagicPacket_v2)
tp->features |= RTL_FEATURE_WOL;
if ((RTL_R8(Config3) & LinkUp) != 0)
@@ -7756,7 +8223,10 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tp->mac_version == RTL_GIGA_MAC_VER_45 ||
tp->mac_version == RTL_GIGA_MAC_VER_46 ||
tp->mac_version == RTL_GIGA_MAC_VER_47 ||
- tp->mac_version == RTL_GIGA_MAC_VER_48) {
+ tp->mac_version == RTL_GIGA_MAC_VER_48 ||
+ tp->mac_version == RTL_GIGA_MAC_VER_49 ||
+ tp->mac_version == RTL_GIGA_MAC_VER_50 ||
+ tp->mac_version == RTL_GIGA_MAC_VER_51) {
u16 mac_addr[3];
*(u32 *)&mac_addr[0] = rtl_eri_read(tp, 0xe0, ERIAR_EXGMAC);
@@ -7835,7 +8305,10 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if ((tp->mac_version == RTL_GIGA_MAC_VER_27 ||
tp->mac_version == RTL_GIGA_MAC_VER_28 ||
- tp->mac_version == RTL_GIGA_MAC_VER_31) &&
+ tp->mac_version == RTL_GIGA_MAC_VER_31 ||
+ tp->mac_version == RTL_GIGA_MAC_VER_49 ||
+ tp->mac_version == RTL_GIGA_MAC_VER_50 ||
+ tp->mac_version == RTL_GIGA_MAC_VER_51) &&
r8168_check_dash(tp)) {
rtl8168_driver_start(tp);
}
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/toshiba/spider_net.c b/drivers/net/ethernet/toshiba/spider_net.c
index 3e38f67c6011..8e9371a3388a 100644
--- a/drivers/net/ethernet/toshiba/spider_net.c
+++ b/drivers/net/ethernet/toshiba/spider_net.c
@@ -267,34 +267,6 @@ spider_net_set_promisc(struct spider_net_card *card)
}
/**
- * spider_net_get_mac_address - read mac address from spider card
- * @card: device structure
- *
- * reads MAC address from GMACUNIMACU and GMACUNIMACL registers
- */
-static int
-spider_net_get_mac_address(struct net_device *netdev)
-{
- struct spider_net_card *card = netdev_priv(netdev);
- u32 macl, macu;
-
- macl = spider_net_read_reg(card, SPIDER_NET_GMACUNIMACL);
- macu = spider_net_read_reg(card, SPIDER_NET_GMACUNIMACU);
-
- netdev->dev_addr[0] = (macu >> 24) & 0xff;
- netdev->dev_addr[1] = (macu >> 16) & 0xff;
- netdev->dev_addr[2] = (macu >> 8) & 0xff;
- netdev->dev_addr[3] = macu & 0xff;
- netdev->dev_addr[4] = (macl >> 8) & 0xff;
- netdev->dev_addr[5] = macl & 0xff;
-
- if (!is_valid_ether_addr(&netdev->dev_addr[0]))
- return -EINVAL;
-
- return 0;
-}
-
-/**
* spider_net_get_descr_status -- returns the status of a descriptor
* @descr: descriptor to look at
*
@@ -1345,15 +1317,17 @@ spider_net_set_mac(struct net_device *netdev, void *p)
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
+ memcpy(netdev->dev_addr, addr->sa_data, ETH_ALEN);
+
/* switch off GMACTPE and GMACRPE */
regvalue = spider_net_read_reg(card, SPIDER_NET_GMACOPEMD);
regvalue &= ~((1 << 5) | (1 << 6));
spider_net_write_reg(card, SPIDER_NET_GMACOPEMD, regvalue);
/* write mac */
- macu = (addr->sa_data[0]<<24) + (addr->sa_data[1]<<16) +
- (addr->sa_data[2]<<8) + (addr->sa_data[3]);
- macl = (addr->sa_data[4]<<8) + (addr->sa_data[5]);
+ macu = (netdev->dev_addr[0]<<24) + (netdev->dev_addr[1]<<16) +
+ (netdev->dev_addr[2]<<8) + (netdev->dev_addr[3]);
+ macl = (netdev->dev_addr[4]<<8) + (netdev->dev_addr[5]);
spider_net_write_reg(card, SPIDER_NET_GMACUNIMACU, macu);
spider_net_write_reg(card, SPIDER_NET_GMACUNIMACL, macl);
@@ -1364,12 +1338,6 @@ spider_net_set_mac(struct net_device *netdev, void *p)
spider_net_set_promisc(card);
- /* look up, whether we have been successful */
- if (spider_net_get_mac_address(netdev))
- return -EADDRNOTAVAIL;
- if (memcmp(netdev->dev_addr,addr->sa_data,netdev->addr_len))
- return -EADDRNOTAVAIL;
-
return 0;
}
diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c
index f5fbc12d3e10..a43e8492b1ce 100644
--- a/drivers/net/ethernet/via/via-velocity.c
+++ b/drivers/net/ethernet/via/via-velocity.c
@@ -2056,7 +2056,7 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx)
struct sk_buff *skb;
if (rd->rdesc0.RSR & (RSR_STP | RSR_EDP)) {
- VELOCITY_PRT(MSG_LEVEL_VERBOSE, KERN_ERR " %s : the received frame span multple RDs.\n", vptr->netdev->name);
+ VELOCITY_PRT(MSG_LEVEL_VERBOSE, KERN_ERR " %s : the received frame spans multiple RDs.\n", vptr->netdev->name);
stats->rx_length_errors++;
return -EINVAL;
}
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index 977984bc238a..7d76c9523395 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -717,6 +717,7 @@ int netvsc_send(struct hv_device *device,
unsigned int section_index = NETVSC_INVALID_INDEX;
u32 msg_size = 0;
struct sk_buff *skb;
+ u16 q_idx = packet->q_idx;
net_device = get_outbound_net_device(device);
@@ -781,24 +782,24 @@ int netvsc_send(struct hv_device *device,
if (ret == 0) {
atomic_inc(&net_device->num_outstanding_sends);
- atomic_inc(&net_device->queue_sends[packet->q_idx]);
+ atomic_inc(&net_device->queue_sends[q_idx]);
if (hv_ringbuf_avail_percent(&out_channel->outbound) <
RING_AVAIL_PERCENT_LOWATER) {
netif_tx_stop_queue(netdev_get_tx_queue(
- ndev, packet->q_idx));
+ ndev, q_idx));
if (atomic_read(&net_device->
- queue_sends[packet->q_idx]) < 1)
+ queue_sends[q_idx]) < 1)
netif_tx_wake_queue(netdev_get_tx_queue(
- ndev, packet->q_idx));
+ ndev, q_idx));
}
} else if (ret == -EAGAIN) {
netif_tx_stop_queue(netdev_get_tx_queue(
- ndev, packet->q_idx));
- if (atomic_read(&net_device->queue_sends[packet->q_idx]) < 1) {
+ ndev, q_idx));
+ if (atomic_read(&net_device->queue_sends[q_idx]) < 1) {
netif_tx_wake_queue(netdev_get_tx_queue(
- ndev, packet->q_idx));
+ ndev, q_idx));
ret = -ENOSPC;
}
} else {
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index d2d4a3d2237f..34f846b4bd05 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -185,7 +185,8 @@ static void ifb_setup(struct net_device *dev)
dev->flags |= IFF_NOARP;
dev->flags &= ~IFF_MULTICAST;
- dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING);
+ dev->priv_flags &= ~IFF_TX_SKB_SHARING;
+ netif_keep_dst(dev);
eth_hw_addr_random(dev);
}
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index 8f2262540561..c76283c2f84a 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -169,7 +169,7 @@ static void loopback_setup(struct net_device *dev)
dev->type = ARPHRD_LOOPBACK; /* 0x0001*/
dev->flags = IFF_LOOPBACK;
dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
- dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
+ netif_keep_dst(dev);
dev->hw_features = NETIF_F_ALL_TSO | NETIF_F_UFO;
dev->features = NETIF_F_SG | NETIF_F_FRAGLIST
| NETIF_F_ALL_TSO
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index e8a453f1b458..38b4fae61f04 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -1025,7 +1025,8 @@ void macvlan_common_setup(struct net_device *dev)
{
ether_setup(dev);
- dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING);
+ dev->priv_flags &= ~IFF_TX_SKB_SHARING;
+ netif_keep_dst(dev);
dev->priv_flags |= IFF_UNICAST_FLT;
dev->netdev_ops = &macvlan_netdev_ops;
dev->destructor = free_netdev;
diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c
index 5b19fbbda6d4..47872caa0081 100644
--- a/drivers/net/phy/fixed.c
+++ b/drivers/net/phy/fixed.c
@@ -233,9 +233,9 @@ EXPORT_SYMBOL_GPL(fixed_phy_del);
static int phy_fixed_addr;
static DEFINE_SPINLOCK(phy_fixed_addr_lock);
-int fixed_phy_register(unsigned int irq,
- struct fixed_phy_status *status,
- struct device_node *np)
+struct phy_device *fixed_phy_register(unsigned int irq,
+ struct fixed_phy_status *status,
+ struct device_node *np)
{
struct fixed_mdio_bus *fmb = &platform_fmb;
struct phy_device *phy;
@@ -246,19 +246,19 @@ int fixed_phy_register(unsigned int irq,
spin_lock(&phy_fixed_addr_lock);
if (phy_fixed_addr == PHY_MAX_ADDR) {
spin_unlock(&phy_fixed_addr_lock);
- return -ENOSPC;
+ return ERR_PTR(-ENOSPC);
}
phy_addr = phy_fixed_addr++;
spin_unlock(&phy_fixed_addr_lock);
ret = fixed_phy_add(PHY_POLL, phy_addr, status);
if (ret < 0)
- return ret;
+ return ERR_PTR(ret);
phy = get_phy_device(fmb->mii_bus, phy_addr, false);
if (!phy || IS_ERR(phy)) {
fixed_phy_del(phy_addr);
- return -EINVAL;
+ return ERR_PTR(-EINVAL);
}
of_node_get(np);
@@ -269,10 +269,10 @@ int fixed_phy_register(unsigned int irq,
phy_device_free(phy);
of_node_put(np);
fixed_phy_del(phy_addr);
- return ret;
+ return ERR_PTR(ret);
}
- return 0;
+ return phy;
}
static int __init fixed_mdio_bus_init(void)
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index fa0d71727894..80e6f3430f65 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -1103,7 +1103,7 @@ static void ppp_setup(struct net_device *dev)
dev->type = ARPHRD_PPP;
dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
dev->features |= NETIF_F_NETNS_LOCAL;
- dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
+ netif_keep_dst(dev);
}
/*
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 2277c3679a51..2368395d8ae5 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -647,7 +647,7 @@ static void team_notify_peers(struct team *team)
{
if (!team->notify_peers.count || !netif_running(team->dev))
return;
- atomic_set(&team->notify_peers.count_pending, team->notify_peers.count);
+ atomic_add(team->notify_peers.count, &team->notify_peers.count_pending);
schedule_delayed_work(&team->notify_peers.dw, 0);
}
@@ -687,7 +687,7 @@ static void team_mcast_rejoin(struct team *team)
{
if (!team->mcast_rejoin.count || !netif_running(team->dev))
return;
- atomic_set(&team->mcast_rejoin.count_pending, team->mcast_rejoin.count);
+ atomic_add(team->mcast_rejoin.count, &team->mcast_rejoin.count_pending);
schedule_delayed_work(&team->mcast_rejoin.dw, 0);
}
@@ -970,7 +970,8 @@ static void __team_compute_features(struct team *team)
struct team_port *port;
u32 vlan_features = TEAM_VLAN_FEATURES & NETIF_F_ALL_FOR_ALL;
unsigned short max_hard_header_len = ETH_HLEN;
- unsigned int flags, dst_release_flag = IFF_XMIT_DST_RELEASE;
+ unsigned int dst_release_flag = IFF_XMIT_DST_RELEASE |
+ IFF_XMIT_DST_RELEASE_PERM;
list_for_each_entry(port, &team->port_list, list) {
vlan_features = netdev_increment_features(vlan_features,
@@ -985,8 +986,9 @@ static void __team_compute_features(struct team *team)
team->dev->vlan_features = vlan_features;
team->dev->hard_header_len = max_hard_header_len;
- flags = team->dev->priv_flags & ~IFF_XMIT_DST_RELEASE;
- team->dev->priv_flags = flags | dst_release_flag;
+ team->dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
+ if (dst_release_flag == (IFF_XMIT_DST_RELEASE | IFF_XMIT_DST_RELEASE_PERM))
+ team->dev->priv_flags |= IFF_XMIT_DST_RELEASE;
netdev_change_features(team->dev);
}
diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c
index 5d194093f3e1..2c05f6cdb12f 100644
--- a/drivers/net/usb/asix_devices.c
+++ b/drivers/net/usb/asix_devices.c
@@ -890,7 +890,7 @@ static const struct driver_info ax88772_info = {
.unbind = ax88772_unbind,
.status = asix_status,
.link_reset = ax88772_link_reset,
- .reset = ax88772_reset,
+ .reset = ax88772_link_reset,
.flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR | FLAG_MULTI_PACKET,
.rx_fixup = asix_rx_fixup_common,
.tx_fixup = asix_tx_fixup,
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index b9a98152815b..864159eb744e 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
@@ -980,9 +969,16 @@ static int rtl8152_set_mac_address(struct net_device *netdev, void *p)
{
struct r8152 *tp = netdev_priv(netdev);
struct sockaddr *addr = p;
+ int ret = -EADDRNOTAVAIL;
if (!is_valid_ether_addr(addr->sa_data))
- return -EADDRNOTAVAIL;
+ goto out1;
+
+ ret = usb_autopm_get_interface(tp->intf);
+ if (ret < 0)
+ goto out1;
+
+ mutex_lock(&tp->control);
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
@@ -990,7 +986,11 @@ static int rtl8152_set_mac_address(struct net_device *netdev, void *p)
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);
- return 0;
+ mutex_unlock(&tp->control);
+
+ usb_autopm_put_interface(tp->intf);
+out1:
+ return ret;
}
static int set_ethernet_addr(struct r8152 *tp)
@@ -2138,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)
@@ -2146,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)
@@ -2844,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);
@@ -2859,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);
}
@@ -2878,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);
@@ -2906,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:
@@ -2926,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.
@@ -2938,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);
}
@@ -3162,6 +3190,8 @@ static int rtl8152_suspend(struct usb_interface *intf, pm_message_t message)
{
struct r8152 *tp = usb_get_intfdata(intf);
+ mutex_lock(&tp->control);
+
if (PMSG_IS_AUTO(message))
set_bit(SELECTIVE_SUSPEND, &tp->flags);
else
@@ -3181,6 +3211,8 @@ static int rtl8152_suspend(struct usb_interface *intf, pm_message_t message)
tasklet_enable(&tp->tl);
}
+ mutex_unlock(&tp->control);
+
return 0;
}
@@ -3188,6 +3220,8 @@ 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);
@@ -3213,6 +3247,8 @@ static int rtl8152_resume(struct usb_interface *intf)
usb_submit_urb(tp->intr_urb, GFP_KERNEL);
}
+ mutex_unlock(&tp->control);
+
return 0;
}
@@ -3223,9 +3259,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);
}
@@ -3238,9 +3278,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:
@@ -3275,11 +3319,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)
@@ -3291,8 +3349,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:
@@ -3452,8 +3514,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:
@@ -3470,7 +3536,13 @@ 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);
@@ -3513,7 +3585,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:
@@ -3521,7 +3595,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:
@@ -3714,6 +3790,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/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 5173821a9575..20615bbd693b 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -69,8 +69,9 @@
// reawaken network queue this soon after stopping; else watchdog barks
#define TX_TIMEOUT_JIFFIES (5*HZ)
-// throttle rx/tx briefly after some faults, so khubd might disconnect()
-// us (it polls at HZ/4 usually) before we report too many false errors.
+/* throttle rx/tx briefly after some faults, so hub_wq might disconnect()
+ * us (it polls at HZ/4 usually) before we report too many false errors.
+ */
#define THROTTLE_JIFFIES (HZ/8)
// between wakeups
@@ -595,9 +596,9 @@ static void rx_complete (struct urb *urb)
"rx shutdown, code %d\n", urb_status);
goto block;
- /* we get controller i/o faults during khubd disconnect() delays.
+ /* we get controller i/o faults during hub_wq disconnect() delays.
* throttle down resubmits, to avoid log floods; just temporarily,
- * so we still recover when the fault isn't a khubd delay.
+ * so we still recover when the fault isn't a hub_wq delay.
*/
case -EPROTO:
case -ETIME:
@@ -1185,8 +1186,9 @@ static void tx_complete (struct urb *urb)
case -ESHUTDOWN: // hardware gone
break;
- // like rx, tx gets controller i/o faults during khubd delays
- // and so it uses the same throttling mechanism.
+ /* like rx, tx gets controller i/o faults during hub_wq
+ * delays and so it uses the same throttling mechanism.
+ */
case -EPROTO:
case -ETIME:
case -EILSEQ:
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 2af795d6ba05..2a51e6e48e1e 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -2193,7 +2193,7 @@ static void vxlan_setup(struct net_device *dev)
dev->hw_features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
dev->hw_features |= NETIF_F_GSO_SOFTWARE;
dev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX;
- dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
+ netif_keep_dst(dev);
dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
INIT_LIST_HEAD(&vxlan->next);
diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c
index e5c7e6165a4b..3ebed1c40abb 100644
--- a/drivers/net/wan/hdlc_fr.c
+++ b/drivers/net/wan/hdlc_fr.c
@@ -1047,7 +1047,7 @@ static void pvc_setup(struct net_device *dev)
dev->flags = IFF_POINTOPOINT;
dev->hard_header_len = 10;
dev->addr_len = 2;
- dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
+ netif_keep_dst(dev);
}
static const struct net_device_ops pvc_ops = {
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/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/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 205162449b72..6f6a974f7fdb 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -2332,7 +2332,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..493a183d0aaf 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -2139,6 +2139,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 +2184,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) ||
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/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
index 22884ba7d6cc..818b1edaaa9a 100644
--- a/drivers/net/wireless/libertas/cfg.c
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -1354,7 +1354,7 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev,
wait_event_interruptible_timeout(priv->scan_q,
(priv->scan_req == NULL),
(15 * HZ));
- lbs_deb_assoc("assoc: scanning competed\n");
+ lbs_deb_assoc("assoc: scanning completed\n");
}
/* Find the BSS we want using available scan results */
diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c
index 088de9d25c39..25c5acc78bd1 100644
--- a/drivers/net/wireless/libertas_tf/main.c
+++ b/drivers/net/wireless/libertas_tf/main.c
@@ -332,7 +332,7 @@ static int lbtf_op_start(struct ieee80211_hw *hw)
err_prog_firmware:
priv->hw_reset_device(card);
- lbtf_deb_leave_args(LBTF_DEB_MACOPS, "error programing fw; ret=%d", ret);
+ lbtf_deb_leave_args(LBTF_DEB_MACOPS, "error programming fw; ret=%d", ret);
return ret;
}
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/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 */