diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-13 12:40:34 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-13 12:40:34 +0400 |
commit | 42a2d923cc349583ebf6fdd52a7d35e1c2f7e6bd (patch) | |
tree | 2b2b0c03b5389c1301800119333967efafd994ca /drivers/net/ethernet/emulex/benet | |
parent | 5cbb3d216e2041700231bcfc383ee5f8b7fc8b74 (diff) | |
parent | 75ecab1df14d90e86cebef9ec5c76befde46e65f (diff) | |
download | linux-42a2d923cc349583ebf6fdd52a7d35e1c2f7e6bd.tar.xz |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking updates from David Miller:
1) The addition of nftables. No longer will we need protocol aware
firewall filtering modules, it can all live in userspace.
At the core of nftables is a, for lack of a better term, virtual
machine that executes byte codes to inspect packet or metadata
(arriving interface index, etc.) and make verdict decisions.
Besides support for loading packet contents and comparing them, the
interpreter supports lookups in various datastructures as
fundamental operations. For example sets are supports, and
therefore one could create a set of whitelist IP address entries
which have ACCEPT verdicts attached to them, and use the appropriate
byte codes to do such lookups.
Since the interpreted code is composed in userspace, userspace can
do things like optimize things before giving it to the kernel.
Another major improvement is the capability of atomically updating
portions of the ruleset. In the existing netfilter implementation,
one has to update the entire rule set in order to make a change and
this is very expensive.
Userspace tools exist to create nftables rules using existing
netfilter rule sets, but both kernel implementations will need to
co-exist for quite some time as we transition from the old to the
new stuff.
Kudos to Patrick McHardy, Pablo Neira Ayuso, and others who have
worked so hard on this.
2) Daniel Borkmann and Hannes Frederic Sowa made several improvements
to our pseudo-random number generator, mostly used for things like
UDP port randomization and netfitler, amongst other things.
In particular the taus88 generater is updated to taus113, and test
cases are added.
3) Support 64-bit rates in HTB and TBF schedulers, from Eric Dumazet
and Yang Yingliang.
4) Add support for new 577xx tigon3 chips to tg3 driver, from Nithin
Sujir.
5) Fix two fatal flaws in TCP dynamic right sizing, from Eric Dumazet,
Neal Cardwell, and Yuchung Cheng.
6) Allow IP_TOS and IP_TTL to be specified in sendmsg() ancillary
control message data, much like other socket option attributes.
From Francesco Fusco.
7) Allow applications to specify a cap on the rate computed
automatically by the kernel for pacing flows, via a new
SO_MAX_PACING_RATE socket option. From Eric Dumazet.
8) Make the initial autotuned send buffer sizing in TCP more closely
reflect actual needs, from Eric Dumazet.
9) Currently early socket demux only happens for TCP sockets, but we
can do it for connected UDP sockets too. Implementation from Shawn
Bohrer.
10) Refactor inet socket demux with the goal of improving hash demux
performance for listening sockets. With the main goals being able
to use RCU lookups on even request sockets, and eliminating the
listening lock contention. From Eric Dumazet.
11) The bonding layer has many demuxes in it's fast path, and an RCU
conversion was started back in 3.11, several changes here extend the
RCU usage to even more locations. From Ding Tianhong and Wang
Yufen, based upon suggestions by Nikolay Aleksandrov and Veaceslav
Falico.
12) Allow stackability of segmentation offloads to, in particular, allow
segmentation offloading over tunnels. From Eric Dumazet.
13) Significantly improve the handling of secret keys we input into the
various hash functions in the inet hashtables, TCP fast open, as
well as syncookies. From Hannes Frederic Sowa. The key fundamental
operation is "net_get_random_once()" which uses static keys.
Hannes even extended this to ipv4/ipv6 fragmentation handling and
our generic flow dissector.
14) The generic driver layer takes care now to set the driver data to
NULL on device removal, so it's no longer necessary for drivers to
explicitly set it to NULL any more. Many drivers have been cleaned
up in this way, from Jingoo Han.
15) Add a BPF based packet scheduler classifier, from Daniel Borkmann.
16) Improve CRC32 interfaces and generic SKB checksum iterators so that
SCTP's checksumming can more cleanly be handled. Also from Daniel
Borkmann.
17) Add a new PMTU discovery mode, IP_PMTUDISC_INTERFACE, which forces
using the interface MTU value. This helps avoid PMTU attacks,
particularly on DNS servers. From Hannes Frederic Sowa.
18) Use generic XPS for transmit queue steering rather than internal
(re-)implementation in virtio-net. From Jason Wang.
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1622 commits)
random32: add test cases for taus113 implementation
random32: upgrade taus88 generator to taus113 from errata paper
random32: move rnd_state to linux/random.h
random32: add prandom_reseed_late() and call when nonblocking pool becomes initialized
random32: add periodic reseeding
random32: fix off-by-one in seeding requirement
PHY: Add RTL8201CP phy_driver to realtek
xtsonic: add missing platform_set_drvdata() in xtsonic_probe()
macmace: add missing platform_set_drvdata() in mace_probe()
ethernet/arc/arc_emac: add missing platform_set_drvdata() in arc_emac_probe()
ipv6: protect for_each_sk_fl_rcu in mem_check with rcu_read_lock_bh
vlan: Implement vlan_dev_get_egress_qos_mask as an inline.
ixgbe: add warning when max_vfs is out of range.
igb: Update link modes display in ethtool
netfilter: push reasm skb through instead of original frag skbs
ip6_output: fragment outgoing reassembled skb properly
MAINTAINERS: mv643xx_eth: take over maintainership from Lennart
net_sched: tbf: support of 64bit rates
ixgbe: deleting dfwd stations out of order can cause null ptr deref
ixgbe: fix build err, num_rx_queues is only available with CONFIG_RPS
...
Diffstat (limited to 'drivers/net/ethernet/emulex/benet')
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be.h | 177 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_cmds.c | 27 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_cmds.h | 332 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_ethtool.c | 40 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_main.c | 315 |
5 files changed, 622 insertions, 269 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index c99dac6a9ddf..f4825db5d179 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h @@ -34,7 +34,7 @@ #include "be_hw.h" #include "be_roce.h" -#define DRV_VER "4.9.134.0u" +#define DRV_VER "4.9.224.0u" #define DRV_NAME "be2net" #define BE_NAME "Emulex BladeEngine2" #define BE3_NAME "Emulex BladeEngine3" @@ -89,7 +89,7 @@ static inline char *nic_name(struct pci_dev *pdev) #define BE_NUM_VLANS_SUPPORTED 64 #define BE_UMC_NUM_VLANS_SUPPORTED 15 -#define BE_MAX_EQD 96u +#define BE_MAX_EQD 128u #define BE_MAX_TX_FRAG_COUNT 30 #define EVNT_Q_LEN 1024 @@ -199,8 +199,37 @@ struct be_eq_obj { u16 spurious_intr; struct napi_struct napi; struct be_adapter *adapter; + +#ifdef CONFIG_NET_RX_BUSY_POLL +#define BE_EQ_IDLE 0 +#define BE_EQ_NAPI 1 /* napi owns this EQ */ +#define BE_EQ_POLL 2 /* poll owns this EQ */ +#define BE_EQ_LOCKED (BE_EQ_NAPI | BE_EQ_POLL) +#define BE_EQ_NAPI_YIELD 4 /* napi yielded this EQ */ +#define BE_EQ_POLL_YIELD 8 /* poll yielded this EQ */ +#define BE_EQ_YIELD (BE_EQ_NAPI_YIELD | BE_EQ_POLL_YIELD) +#define BE_EQ_USER_PEND (BE_EQ_POLL | BE_EQ_POLL_YIELD) + unsigned int state; + spinlock_t lock; /* lock to serialize napi and busy-poll */ +#endif /* CONFIG_NET_RX_BUSY_POLL */ } ____cacheline_aligned_in_smp; +struct be_aic_obj { /* Adaptive interrupt coalescing (AIC) info */ + bool enable; + u32 min_eqd; /* in usecs */ + u32 max_eqd; /* in usecs */ + u32 prev_eqd; /* in usecs */ + u32 et_eqd; /* configured val when aic is off */ + ulong jiffies; + u64 rx_pkts_prev; /* Used to calculate RX pps */ + u64 tx_reqs_prev; /* Used to calculate TX pps */ +}; + +enum { + NAPI_POLLING, + BUSY_POLLING +}; + struct be_mcc_obj { struct be_queue_info q; struct be_queue_info cq; @@ -215,6 +244,7 @@ struct be_tx_stats { u64 tx_compl; ulong tx_jiffies; u32 tx_stops; + u32 tx_drv_drops; /* pkts dropped by driver */ struct u64_stats_sync sync; struct u64_stats_sync sync_compl; }; @@ -239,15 +269,12 @@ struct be_rx_page_info { struct be_rx_stats { u64 rx_bytes; u64 rx_pkts; - u64 rx_pkts_prev; - ulong rx_jiffies; u32 rx_drops_no_skbs; /* skb allocation errors */ u32 rx_drops_no_frags; /* HW has no fetched frags */ u32 rx_post_fail; /* page post alloc failures */ u32 rx_compl; u32 rx_mcast_pkts; u32 rx_compl_err; /* completions with err set */ - u32 rx_pps; /* pkts per second */ struct u64_stats_sync sync; }; @@ -316,6 +343,11 @@ struct be_drv_stats { u32 rx_input_fifo_overflow_drop; u32 pmem_fifo_overflow_drop; u32 jabber_events; + u32 rx_roce_bytes_lsd; + u32 rx_roce_bytes_msd; + u32 rx_roce_frames; + u32 roce_drops_payload_len; + u32 roce_drops_crc; }; struct be_vf_cfg { @@ -405,6 +437,7 @@ struct be_adapter { u32 big_page_size; /* Compounded page size shared by rx wrbs */ struct be_drv_stats drv_stats; + struct be_aic_obj aic_obj[MAX_EVT_QS]; u16 vlans_added; u8 vlan_tag[VLAN_N_VID]; u8 vlan_prio_bmap; /* Available Priority BitMap */ @@ -437,7 +470,6 @@ struct be_adapter { u32 rx_fc; /* Rx flow control */ u32 tx_fc; /* Tx flow control */ bool stats_cmd_sent; - u32 if_type; struct { u32 size; u32 total_size; @@ -472,8 +504,8 @@ struct be_adapter { #define be_physfn(adapter) (!adapter->virtfn) #define sriov_enabled(adapter) (adapter->num_vfs > 0) -#define sriov_want(adapter) (be_max_vfs(adapter) && num_vfs && \ - be_physfn(adapter)) +#define sriov_want(adapter) (be_physfn(adapter) && \ + (num_vfs || pci_num_vf(adapter->pdev))) #define for_all_vfs(adapter, vf_cfg, i) \ for (i = 0, vf_cfg = &adapter->vf_cfg[i]; i < adapter->num_vfs; \ i++, vf_cfg++) @@ -546,6 +578,10 @@ extern const struct ethtool_ops be_ethtool_ops; for (i = 0, eqo = &adapter->eq_obj[i]; i < adapter->num_evt_qs; \ i++, eqo++) +#define for_all_rx_queues_on_eq(adapter, eqo, rxo, i) \ + for (i = eqo->idx, rxo = &adapter->rx_obj[i]; i < adapter->num_rx_qs;\ + i += adapter->num_evt_qs, rxo += adapter->num_evt_qs) + #define is_mcc_eqo(eqo) (eqo->idx == 0) #define mcc_eqo(adapter) (&adapter->eq_obj[0]) @@ -696,6 +732,115 @@ static inline int qnq_async_evt_rcvd(struct be_adapter *adapter) return adapter->flags & BE_FLAGS_QNQ_ASYNC_EVT_RCVD; } +#ifdef CONFIG_NET_RX_BUSY_POLL +static inline bool be_lock_napi(struct be_eq_obj *eqo) +{ + bool status = true; + + spin_lock(&eqo->lock); /* BH is already disabled */ + if (eqo->state & BE_EQ_LOCKED) { + WARN_ON(eqo->state & BE_EQ_NAPI); + eqo->state |= BE_EQ_NAPI_YIELD; + status = false; + } else { + eqo->state = BE_EQ_NAPI; + } + spin_unlock(&eqo->lock); + return status; +} + +static inline void be_unlock_napi(struct be_eq_obj *eqo) +{ + spin_lock(&eqo->lock); /* BH is already disabled */ + + WARN_ON(eqo->state & (BE_EQ_POLL | BE_EQ_NAPI_YIELD)); + eqo->state = BE_EQ_IDLE; + + spin_unlock(&eqo->lock); +} + +static inline bool be_lock_busy_poll(struct be_eq_obj *eqo) +{ + bool status = true; + + spin_lock_bh(&eqo->lock); + if (eqo->state & BE_EQ_LOCKED) { + eqo->state |= BE_EQ_POLL_YIELD; + status = false; + } else { + eqo->state |= BE_EQ_POLL; + } + spin_unlock_bh(&eqo->lock); + return status; +} + +static inline void be_unlock_busy_poll(struct be_eq_obj *eqo) +{ + spin_lock_bh(&eqo->lock); + + WARN_ON(eqo->state & (BE_EQ_NAPI)); + eqo->state = BE_EQ_IDLE; + + spin_unlock_bh(&eqo->lock); +} + +static inline void be_enable_busy_poll(struct be_eq_obj *eqo) +{ + spin_lock_init(&eqo->lock); + eqo->state = BE_EQ_IDLE; +} + +static inline void be_disable_busy_poll(struct be_eq_obj *eqo) +{ + local_bh_disable(); + + /* It's enough to just acquire napi lock on the eqo to stop + * be_busy_poll() from processing any queueus. + */ + while (!be_lock_napi(eqo)) + mdelay(1); + + local_bh_enable(); +} + +#else /* CONFIG_NET_RX_BUSY_POLL */ + +static inline bool be_lock_napi(struct be_eq_obj *eqo) +{ + return true; +} + +static inline void be_unlock_napi(struct be_eq_obj *eqo) +{ +} + +static inline bool be_lock_busy_poll(struct be_eq_obj *eqo) +{ + return false; +} + +static inline void be_unlock_busy_poll(struct be_eq_obj *eqo) +{ +} + +static inline void be_enable_busy_poll(struct be_eq_obj *eqo) +{ +} + +static inline void be_disable_busy_poll(struct be_eq_obj *eqo) +{ +} +#endif /* CONFIG_NET_RX_BUSY_POLL */ + +void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, + u16 num_popped); +void be_link_status_update(struct be_adapter *adapter, u8 link_status); +void be_parse_stats(struct be_adapter *adapter); +int be_load_fw(struct be_adapter *adapter, u8 *func); +bool be_is_wol_supported(struct be_adapter *adapter); +bool be_pause_supported(struct be_adapter *adapter); +u32 be_get_fw_log_level(struct be_adapter *adapter); + static inline int fw_major_num(const char *fw_ver) { int fw_major = 0; @@ -705,27 +850,19 @@ static inline int fw_major_num(const char *fw_ver) return fw_major; } -extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, - u16 num_popped); -extern void be_link_status_update(struct be_adapter *adapter, u8 link_status); -extern void be_parse_stats(struct be_adapter *adapter); -extern int be_load_fw(struct be_adapter *adapter, u8 *func); -extern bool be_is_wol_supported(struct be_adapter *adapter); -extern bool be_pause_supported(struct be_adapter *adapter); -extern u32 be_get_fw_log_level(struct be_adapter *adapter); int be_update_queues(struct be_adapter *adapter); int be_poll(struct napi_struct *napi, int budget); /* * internal function to initialize-cleanup roce device. */ -extern void be_roce_dev_add(struct be_adapter *); -extern void be_roce_dev_remove(struct be_adapter *); +void be_roce_dev_add(struct be_adapter *); +void be_roce_dev_remove(struct be_adapter *); /* * internal function to open-close roce device during ifup-ifdown. */ -extern void be_roce_dev_open(struct be_adapter *); -extern void be_roce_dev_close(struct be_adapter *); +void be_roce_dev_open(struct be_adapter *); +void be_roce_dev_close(struct be_adapter *); #endif /* BE_H */ diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index c08fd32bb8e5..7fb0edfe3d24 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -522,7 +522,7 @@ static u16 be_POST_stage_get(struct be_adapter *adapter) return sem & POST_STAGE_MASK; } -int lancer_wait_ready(struct be_adapter *adapter) +static int lancer_wait_ready(struct be_adapter *adapter) { #define SLIPORT_READY_TIMEOUT 30 u32 sliport_status; @@ -1436,8 +1436,12 @@ int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd) OPCODE_ETH_GET_STATISTICS, nonemb_cmd->size, wrb, nonemb_cmd); /* version 1 of the cmd is not supported only by BE2 */ - if (!BE2_chip(adapter)) + if (BE2_chip(adapter)) + hdr->version = 0; + if (BE3_chip(adapter) || lancer_chip(adapter)) hdr->version = 1; + else + hdr->version = 2; be_mcc_notify(adapter); adapter->stats_cmd_sent = true; @@ -1719,11 +1723,12 @@ err: /* set the EQ delay interval of an EQ to specified value * Uses async mcc */ -int be_cmd_modify_eqd(struct be_adapter *adapter, u32 eq_id, u32 eqd) +int be_cmd_modify_eqd(struct be_adapter *adapter, struct be_set_eqd *set_eqd, + int num) { struct be_mcc_wrb *wrb; struct be_cmd_req_modify_eq_delay *req; - int status = 0; + int status = 0, i; spin_lock_bh(&adapter->mcc_lock); @@ -1737,13 +1742,15 @@ int be_cmd_modify_eqd(struct be_adapter *adapter, u32 eq_id, u32 eqd) be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, OPCODE_COMMON_MODIFY_EQ_DELAY, sizeof(*req), wrb, NULL); - req->num_eq = cpu_to_le32(1); - req->delay[0].eq_id = cpu_to_le32(eq_id); - req->delay[0].phase = 0; - req->delay[0].delay_multiplier = cpu_to_le32(eqd); + req->num_eq = cpu_to_le32(num); + for (i = 0; i < num; i++) { + req->set_eqd[i].eq_id = cpu_to_le32(set_eqd[i].eq_id); + req->set_eqd[i].phase = 0; + req->set_eqd[i].delay_multiplier = + cpu_to_le32(set_eqd[i].delay_multiplier); + } be_mcc_notify(adapter); - err: spin_unlock_bh(&adapter->mcc_lock); return status; @@ -3520,7 +3527,7 @@ int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain) struct be_cmd_enable_disable_vf *req; int status; - if (!lancer_chip(adapter)) + if (BEx_chip(adapter)) return 0; spin_lock_bh(&adapter->mcc_lock); diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h index 108ca8abf0af..edf3e8a0ff83 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.h +++ b/drivers/net/ethernet/emulex/benet/be_cmds.h @@ -1057,14 +1057,16 @@ struct be_cmd_resp_get_flow_control { } __packed; /******************** Modify EQ Delay *******************/ +struct be_set_eqd { + u32 eq_id; + u32 phase; + u32 delay_multiplier; +}; + struct be_cmd_req_modify_eq_delay { struct be_cmd_req_hdr hdr; u32 num_eq; - struct { - u32 eq_id; - u32 phase; - u32 delay_multiplier; - } delay[8]; + struct be_set_eqd set_eqd[MAX_EVT_QS]; } __packed; struct be_cmd_resp_modify_eq_delay { @@ -1660,6 +1662,67 @@ struct be_erx_stats_v1 { u32 rsvd[4]; }; +struct be_port_rxf_stats_v2 { + u32 rsvd0[10]; + u32 roce_bytes_received_lsd; + u32 roce_bytes_received_msd; + u32 rsvd1[5]; + u32 roce_frames_received; + u32 rx_crc_errors; + u32 rx_alignment_symbol_errors; + u32 rx_pause_frames; + u32 rx_priority_pause_frames; + u32 rx_control_frames; + u32 rx_in_range_errors; + u32 rx_out_range_errors; + u32 rx_frame_too_long; + u32 rx_address_filtered; + u32 rx_dropped_too_small; + u32 rx_dropped_too_short; + u32 rx_dropped_header_too_small; + u32 rx_dropped_tcp_length; + u32 rx_dropped_runt; + u32 rsvd2[10]; + u32 rx_ip_checksum_errs; + u32 rx_tcp_checksum_errs; + u32 rx_udp_checksum_errs; + u32 rsvd3[7]; + u32 rx_switched_unicast_packets; + u32 rx_switched_multicast_packets; + u32 rx_switched_broadcast_packets; + u32 rsvd4[3]; + u32 tx_pauseframes; + u32 tx_priority_pauseframes; + u32 tx_controlframes; + u32 rsvd5[10]; + u32 rxpp_fifo_overflow_drop; + u32 rx_input_fifo_overflow_drop; + u32 pmem_fifo_overflow_drop; + u32 jabber_events; + u32 rsvd6[3]; + u32 rx_drops_payload_size; + u32 rx_drops_clipped_header; + u32 rx_drops_crc; + u32 roce_drops_payload_len; + u32 roce_drops_crc; + u32 rsvd7[19]; +}; + +struct be_rxf_stats_v2 { + struct be_port_rxf_stats_v2 port[4]; + u32 rsvd0[2]; + u32 rx_drops_no_pbuf; + u32 rx_drops_no_txpb; + u32 rx_drops_no_erx_descr; + u32 rx_drops_no_tpre_descr; + u32 rsvd1[6]; + u32 rx_drops_too_many_frags; + u32 rx_drops_invalid_ring; + u32 forwarded_packets; + u32 rx_drops_mtu; + u32 rsvd2[35]; +}; + struct be_hw_stats_v1 { struct be_rxf_stats_v1 rxf; u32 rsvd0[BE_TXP_SW_SZ]; @@ -1678,6 +1741,29 @@ struct be_cmd_resp_get_stats_v1 { struct be_hw_stats_v1 hw_stats; }; +struct be_erx_stats_v2 { + u32 rx_drops_no_fragments[136]; /* dwordS 0 to 135*/ + u32 rsvd[3]; +}; + +struct be_hw_stats_v2 { + struct be_rxf_stats_v2 rxf; + u32 rsvd0[BE_TXP_SW_SZ]; + struct be_erx_stats_v2 erx; + struct be_pmem_stats pmem; + u32 rsvd1[18]; +}; + +struct be_cmd_req_get_stats_v2 { + struct be_cmd_req_hdr hdr; + u8 rsvd[sizeof(struct be_hw_stats_v2)]; +}; + +struct be_cmd_resp_get_stats_v2 { + struct be_cmd_resp_hdr hdr; + struct be_hw_stats_v2 hw_stats; +}; + /************** get fat capabilites *******************/ #define MAX_MODULES 27 #define MAX_MODES 4 @@ -1865,137 +1951,119 @@ struct be_cmd_resp_get_iface_list { struct be_if_desc if_desc; }; -extern int be_pci_fnum_get(struct be_adapter *adapter); -extern int be_fw_wait_ready(struct be_adapter *adapter); -extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, - bool permanent, u32 if_handle, u32 pmac_id); -extern int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr, - u32 if_id, u32 *pmac_id, u32 domain); -extern int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, - int pmac_id, u32 domain); -extern int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, - u32 en_flags, u32 *if_handle, u32 domain); -extern int be_cmd_if_destroy(struct be_adapter *adapter, int if_handle, - u32 domain); -extern int be_cmd_eq_create(struct be_adapter *adapter, struct be_eq_obj *eqo); -extern int be_cmd_cq_create(struct be_adapter *adapter, - struct be_queue_info *cq, struct be_queue_info *eq, - bool no_delay, int num_cqe_dma_coalesce); -extern int be_cmd_mccq_create(struct be_adapter *adapter, - struct be_queue_info *mccq, - struct be_queue_info *cq); -extern int be_cmd_txq_create(struct be_adapter *adapter, - struct be_tx_obj *txo); -extern int be_cmd_rxq_create(struct be_adapter *adapter, - struct be_queue_info *rxq, u16 cq_id, - u16 frag_size, u32 if_id, u32 rss, u8 *rss_id); -extern int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q, - int type); -extern int be_cmd_rxq_destroy(struct be_adapter *adapter, - struct be_queue_info *q); -extern int be_cmd_link_status_query(struct be_adapter *adapter, u16 *link_speed, - u8 *link_status, u32 dom); -extern int be_cmd_reset(struct be_adapter *adapter); -extern int be_cmd_get_stats(struct be_adapter *adapter, - struct be_dma_mem *nonemb_cmd); -extern int lancer_cmd_get_pport_stats(struct be_adapter *adapter, - struct be_dma_mem *nonemb_cmd); -extern int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver, - char *fw_on_flash); - -extern int be_cmd_modify_eqd(struct be_adapter *adapter, u32 eq_id, u32 eqd); -extern int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, - u16 *vtag_array, u32 num, bool untagged, - bool promiscuous); -extern int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 status); -extern int be_cmd_set_flow_control(struct be_adapter *adapter, - u32 tx_fc, u32 rx_fc); -extern int be_cmd_get_flow_control(struct be_adapter *adapter, - u32 *tx_fc, u32 *rx_fc); -extern int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num, +int be_pci_fnum_get(struct be_adapter *adapter); +int be_fw_wait_ready(struct be_adapter *adapter); +int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, + bool permanent, u32 if_handle, u32 pmac_id); +int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr, u32 if_id, + u32 *pmac_id, u32 domain); +int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, int pmac_id, + u32 domain); +int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags, + u32 *if_handle, u32 domain); +int be_cmd_if_destroy(struct be_adapter *adapter, int if_handle, u32 domain); +int be_cmd_eq_create(struct be_adapter *adapter, struct be_eq_obj *eqo); +int be_cmd_cq_create(struct be_adapter *adapter, struct be_queue_info *cq, + struct be_queue_info *eq, bool no_delay, + int num_cqe_dma_coalesce); +int be_cmd_mccq_create(struct be_adapter *adapter, struct be_queue_info *mccq, + struct be_queue_info *cq); +int be_cmd_txq_create(struct be_adapter *adapter, struct be_tx_obj *txo); +int be_cmd_rxq_create(struct be_adapter *adapter, struct be_queue_info *rxq, + u16 cq_id, u16 frag_size, u32 if_id, u32 rss, u8 *rss_id); +int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q, + int type); +int be_cmd_rxq_destroy(struct be_adapter *adapter, struct be_queue_info *q); +int be_cmd_link_status_query(struct be_adapter *adapter, u16 *link_speed, + u8 *link_status, u32 dom); +int be_cmd_reset(struct be_adapter *adapter); +int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd); +int lancer_cmd_get_pport_stats(struct be_adapter *adapter, + struct be_dma_mem *nonemb_cmd); +int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver, + char *fw_on_flash); +int be_cmd_modify_eqd(struct be_adapter *adapter, struct be_set_eqd *, int num); +int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array, + u32 num, bool untagged, bool promiscuous); +int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 status); +int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc); +int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc); +int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num, u32 *function_mode, u32 *function_caps, u16 *asic_rev); -extern int be_cmd_reset_function(struct be_adapter *adapter); -extern int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable, - u32 rss_hash_opts, u16 table_size); -extern int be_process_mcc(struct be_adapter *adapter); -extern int be_cmd_set_beacon_state(struct be_adapter *adapter, - u8 port_num, u8 beacon, u8 status, u8 state); -extern int be_cmd_get_beacon_state(struct be_adapter *adapter, - u8 port_num, u32 *state); -extern int be_cmd_write_flashrom(struct be_adapter *adapter, - struct be_dma_mem *cmd, u32 flash_oper, - u32 flash_opcode, u32 buf_size); -extern int lancer_cmd_write_object(struct be_adapter *adapter, - struct be_dma_mem *cmd, - u32 data_size, u32 data_offset, - const char *obj_name, - u32 *data_written, u8 *change_status, - u8 *addn_status); +int be_cmd_reset_function(struct be_adapter *adapter); +int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable, + u32 rss_hash_opts, u16 table_size); +int be_process_mcc(struct be_adapter *adapter); +int be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num, u8 beacon, + u8 status, u8 state); +int be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num, + u32 *state); +int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, + u32 flash_oper, u32 flash_opcode, u32 buf_size); +int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd, + u32 data_size, u32 data_offset, + const char *obj_name, u32 *data_written, + u8 *change_status, u8 *addn_status); int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd, - u32 data_size, u32 data_offset, const char *obj_name, - u32 *data_read, u32 *eof, u8 *addn_status); + u32 data_size, u32 data_offset, const char *obj_name, + u32 *data_read, u32 *eof, u8 *addn_status); int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, - int offset); -extern int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac, - struct be_dma_mem *nonemb_cmd); -extern int be_cmd_fw_init(struct be_adapter *adapter); -extern int be_cmd_fw_clean(struct be_adapter *adapter); -extern void be_async_mcc_enable(struct be_adapter *adapter); -extern void be_async_mcc_disable(struct be_adapter *adapter); -extern int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num, - u32 loopback_type, u32 pkt_size, - u32 num_pkts, u64 pattern); -extern int be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern, - u32 byte_cnt, struct be_dma_mem *cmd); -extern int be_cmd_get_seeprom_data(struct be_adapter *adapter, - struct be_dma_mem *nonemb_cmd); -extern int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num, - u8 loopback_type, u8 enable); -extern int be_cmd_get_phy_info(struct be_adapter *adapter); -extern int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain); -extern void be_detect_error(struct be_adapter *adapter); -extern int be_cmd_get_die_temperature(struct be_adapter *adapter); -extern int be_cmd_get_cntl_attributes(struct be_adapter *adapter); -extern int be_cmd_req_native_mode(struct be_adapter *adapter); -extern int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size); -extern void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf); -extern int be_cmd_get_fn_privileges(struct be_adapter *adapter, - u32 *privilege, u32 domain); -extern int be_cmd_set_fn_privileges(struct be_adapter *adapter, - u32 privileges, u32 vf_num); -extern int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac, - bool *pmac_id_active, u32 *pmac_id, - u8 domain); -extern int be_cmd_get_active_mac(struct be_adapter *adapter, u32 pmac_id, - u8 *mac); -extern int be_cmd_get_perm_mac(struct be_adapter *adapter, u8 *mac); -extern int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array, - u8 mac_count, u32 domain); -extern int be_cmd_set_mac(struct be_adapter *adapter, u8 *mac, int if_id, - u32 dom); -extern int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid, - u32 domain, u16 intf_id, u16 hsw_mode); -extern int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid, - u32 domain, u16 intf_id, u8 *mode); -extern int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter); -extern int be_cmd_get_ext_fat_capabilites(struct be_adapter *adapter, - struct be_dma_mem *cmd); -extern int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter, - struct be_dma_mem *cmd, - struct be_fat_conf_params *cfgs); -extern int lancer_wait_ready(struct be_adapter *adapter); -extern int lancer_physdev_ctrl(struct be_adapter *adapter, u32 mask); -extern int lancer_initiate_dump(struct be_adapter *adapter); -extern bool dump_present(struct be_adapter *adapter); -extern int lancer_test_and_set_rdy_state(struct be_adapter *adapter); -extern int be_cmd_query_port_name(struct be_adapter *adapter, u8 *port_name); + int offset); +int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac, + struct be_dma_mem *nonemb_cmd); +int be_cmd_fw_init(struct be_adapter *adapter); +int be_cmd_fw_clean(struct be_adapter *adapter); +void be_async_mcc_enable(struct be_adapter *adapter); +void be_async_mcc_disable(struct be_adapter *adapter); +int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num, + u32 loopback_type, u32 pkt_size, u32 num_pkts, + u64 pattern); +int be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern, u32 byte_cnt, + struct be_dma_mem *cmd); +int be_cmd_get_seeprom_data(struct be_adapter *adapter, + struct be_dma_mem *nonemb_cmd); +int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num, + u8 loopback_type, u8 enable); +int be_cmd_get_phy_info(struct be_adapter *adapter); +int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain); +void be_detect_error(struct be_adapter *adapter); +int be_cmd_get_die_temperature(struct be_adapter *adapter); +int be_cmd_get_cntl_attributes(struct be_adapter *adapter); +int be_cmd_req_native_mode(struct be_adapter *adapter); +int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size); +void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf); +int be_cmd_get_fn_privileges(struct be_adapter *adapter, u32 *privilege, + u32 domain); +int be_cmd_set_fn_privileges(struct be_adapter *adapter, u32 privileges, + u32 vf_num); +int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac, + bool *pmac_id_active, u32 *pmac_id, u8 domain); +int be_cmd_get_active_mac(struct be_adapter *adapter, u32 pmac_id, u8 *mac); +int be_cmd_get_perm_mac(struct be_adapter *adapter, u8 *mac); +int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array, u8 mac_count, + u32 domain); +int be_cmd_set_mac(struct be_adapter *adapter, u8 *mac, int if_id, u32 dom); +int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid, u32 domain, + u16 intf_id, u16 hsw_mode); +int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid, u32 domain, + u16 intf_id, u8 *mode); +int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter); +int be_cmd_get_ext_fat_capabilites(struct be_adapter *adapter, + struct be_dma_mem *cmd); +int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter, + struct be_dma_mem *cmd, + struct be_fat_conf_params *cfgs); +int lancer_physdev_ctrl(struct be_adapter *adapter, u32 mask); +int lancer_initiate_dump(struct be_adapter *adapter); +bool dump_present(struct be_adapter *adapter); +int lancer_test_and_set_rdy_state(struct be_adapter *adapter); +int be_cmd_query_port_name(struct be_adapter *adapter, u8 *port_name); int be_cmd_get_func_config(struct be_adapter *adapter, struct be_resources *res); int be_cmd_get_profile_config(struct be_adapter *adapter, struct be_resources *res, u8 domain); -extern int be_cmd_set_profile_config(struct be_adapter *adapter, u32 bps, - u8 domain); -extern int be_cmd_get_if_id(struct be_adapter *adapter, - struct be_vf_cfg *vf_cfg, int vf_num); -extern int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain); -extern int be_cmd_intr_set(struct be_adapter *adapter, bool intr_enable); +int be_cmd_set_profile_config(struct be_adapter *adapter, u32 bps, u8 domain); +int be_cmd_get_if_id(struct be_adapter *adapter, struct be_vf_cfg *vf_cfg, + int vf_num); +int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain); +int be_cmd_intr_set(struct be_adapter *adapter, bool intr_enable); diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c index b440a1fac77b..08330034d9ef 100644 --- a/drivers/net/ethernet/emulex/benet/be_ethtool.c +++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c @@ -116,7 +116,12 @@ static const struct be_ethtool_stat et_stats[] = { {DRVSTAT_INFO(rx_drops_mtu)}, /* Number of packets dropped due to random early drop function */ {DRVSTAT_INFO(eth_red_drops)}, - {DRVSTAT_INFO(be_on_die_temperature)} + {DRVSTAT_INFO(be_on_die_temperature)}, + {DRVSTAT_INFO(rx_roce_bytes_lsd)}, + {DRVSTAT_INFO(rx_roce_bytes_msd)}, + {DRVSTAT_INFO(rx_roce_frames)}, + {DRVSTAT_INFO(roce_drops_payload_len)}, + {DRVSTAT_INFO(roce_drops_crc)} }; #define ETHTOOL_STATS_NUM ARRAY_SIZE(et_stats) @@ -155,7 +160,9 @@ static const struct be_ethtool_stat et_tx_stats[] = { /* Number of times the TX queue was stopped due to lack * of spaces in the TXQ. */ - {DRVSTAT_TX_INFO(tx_stops)} + {DRVSTAT_TX_INFO(tx_stops)}, + /* Pkts dropped in the driver's transmit path */ + {DRVSTAT_TX_INFO(tx_drv_drops)} }; #define ETHTOOL_TXSTATS_NUM (ARRAY_SIZE(et_tx_stats)) @@ -290,19 +297,19 @@ static int be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *et) { struct be_adapter *adapter = netdev_priv(netdev); - struct be_eq_obj *eqo = &adapter->eq_obj[0]; + struct be_aic_obj *aic = &adapter->aic_obj[0]; - et->rx_coalesce_usecs = eqo->cur_eqd; - et->rx_coalesce_usecs_high = eqo->max_eqd; - et->rx_coalesce_usecs_low = eqo->min_eqd; + et->rx_coalesce_usecs = aic->prev_eqd; + et->rx_coalesce_usecs_high = aic->max_eqd; + et->rx_coalesce_usecs_low = aic->min_eqd; - et->tx_coalesce_usecs = eqo->cur_eqd; - et->tx_coalesce_usecs_high = eqo->max_eqd; - et->tx_coalesce_usecs_low = eqo->min_eqd; + et->tx_coalesce_usecs = aic->prev_eqd; + et->tx_coalesce_usecs_high = aic->max_eqd; + et->tx_coalesce_usecs_low = aic->min_eqd; - et->use_adaptive_rx_coalesce = eqo->enable_aic; - et->use_adaptive_tx_coalesce = eqo->enable_aic; + et->use_adaptive_rx_coalesce = aic->enable; + et->use_adaptive_tx_coalesce = aic->enable; return 0; } @@ -314,14 +321,17 @@ static int be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *et) { struct be_adapter *adapter = netdev_priv(netdev); + struct be_aic_obj *aic = &adapter->aic_obj[0]; struct be_eq_obj *eqo; int i; for_all_evt_queues(adapter, eqo, i) { - eqo->enable_aic = et->use_adaptive_rx_coalesce; - eqo->max_eqd = min(et->rx_coalesce_usecs_high, BE_MAX_EQD); - eqo->min_eqd = min(et->rx_coalesce_usecs_low, eqo->max_eqd); - eqo->eqd = et->rx_coalesce_usecs; + aic->enable = et->use_adaptive_rx_coalesce; + aic->max_eqd = min(et->rx_coalesce_usecs_high, BE_MAX_EQD); + aic->min_eqd = min(et->rx_coalesce_usecs_low, aic->max_eqd); + aic->et_eqd = min(et->rx_coalesce_usecs, aic->max_eqd); + aic->et_eqd = max(aic->et_eqd, aic->min_eqd); + aic++; } return 0; diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 53ed58b492c8..741d3bff5ae7 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -22,6 +22,7 @@ #include <asm/div64.h> #include <linux/aer.h> #include <linux/if_bridge.h> +#include <net/busy_poll.h> MODULE_VERSION(DRV_VER); MODULE_DEVICE_TABLE(pci, be_dev_ids); @@ -306,10 +307,14 @@ static void *hw_stats_from_cmd(struct be_adapter *adapter) struct be_cmd_resp_get_stats_v0 *cmd = adapter->stats_cmd.va; return &cmd->hw_stats; - } else { + } else if (BE3_chip(adapter)) { struct be_cmd_resp_get_stats_v1 *cmd = adapter->stats_cmd.va; return &cmd->hw_stats; + } else { + struct be_cmd_resp_get_stats_v2 *cmd = adapter->stats_cmd.va; + + return &cmd->hw_stats; } } @@ -320,10 +325,14 @@ static void *be_erx_stats_from_cmd(struct be_adapter *adapter) struct be_hw_stats_v0 *hw_stats = hw_stats_from_cmd(adapter); return &hw_stats->erx; - } else { + } else if (BE3_chip(adapter)) { struct be_hw_stats_v1 *hw_stats = hw_stats_from_cmd(adapter); return &hw_stats->erx; + } else { + struct be_hw_stats_v2 *hw_stats = hw_stats_from_cmd(adapter); + + return &hw_stats->erx; } } @@ -422,6 +431,60 @@ static void populate_be_v1_stats(struct be_adapter *adapter) adapter->drv_stats.eth_red_drops = pmem_sts->eth_red_drops; } +static void populate_be_v2_stats(struct be_adapter *adapter) +{ + struct be_hw_stats_v2 *hw_stats = hw_stats_from_cmd(adapter); + struct be_pmem_stats *pmem_sts = &hw_stats->pmem; + struct be_rxf_stats_v2 *rxf_stats = &hw_stats->rxf; + struct be_port_rxf_stats_v2 *port_stats = + &rxf_stats->port[adapter->port_num]; + struct be_drv_stats *drvs = &adapter->drv_stats; + + be_dws_le_to_cpu(hw_stats, sizeof(*hw_stats)); + drvs->pmem_fifo_overflow_drop = port_stats->pmem_fifo_overflow_drop; + drvs->rx_priority_pause_frames = port_stats->rx_priority_pause_frames; + drvs->rx_pause_frames = port_stats->rx_pause_frames; + drvs->rx_crc_errors = port_stats->rx_crc_errors; + drvs->rx_control_frames = port_stats->rx_control_frames; + drvs->rx_in_range_errors = port_stats->rx_in_range_errors; + drvs->rx_frame_too_long = port_stats->rx_frame_too_long; + drvs->rx_dropped_runt = port_stats->rx_dropped_runt; + drvs->rx_ip_checksum_errs = port_stats->rx_ip_checksum_errs; + drvs->rx_tcp_checksum_errs = port_stats->rx_tcp_checksum_errs; + drvs->rx_udp_checksum_errs = port_stats->rx_udp_checksum_errs; + drvs->rx_dropped_tcp_length = port_stats->rx_dropped_tcp_length; + drvs->rx_dropped_too_small = port_stats->rx_dropped_too_small; + drvs->rx_dropped_too_short = port_stats->rx_dropped_too_short; + drvs->rx_out_range_errors = port_stats->rx_out_range_errors; + drvs->rx_dropped_header_too_small = + port_stats->rx_dropped_header_too_small; + drvs->rx_input_fifo_overflow_drop = + port_stats->rx_input_fifo_overflow_drop; + drvs->rx_address_filtered = port_stats->rx_address_filtered; + drvs->rx_alignment_symbol_errors = + port_stats->rx_alignment_symbol_errors; + drvs->rxpp_fifo_overflow_drop = port_stats->rxpp_fifo_overflow_drop; + drvs->tx_pauseframes = port_stats->tx_pauseframes; + drvs->tx_controlframes = port_stats->tx_controlframes; + drvs->tx_priority_pauseframes = port_stats->tx_priority_pauseframes; + drvs->jabber_events = port_stats->jabber_events; + drvs->rx_drops_no_pbuf = rxf_stats->rx_drops_no_pbuf; + drvs->rx_drops_no_erx_descr = rxf_stats->rx_drops_no_erx_descr; + drvs->forwarded_packets = rxf_stats->forwarded_packets; + drvs->rx_drops_mtu = rxf_stats->rx_drops_mtu; + drvs->rx_drops_no_tpre_descr = rxf_stats->rx_drops_no_tpre_descr; + drvs->rx_drops_too_many_frags = rxf_stats->rx_drops_too_many_frags; + adapter->drv_stats.eth_red_drops = pmem_sts->eth_red_drops; + if (be_roce_supported(adapter)) { + drvs->rx_roce_bytes_lsd = port_stats->roce_bytes_received_lsd; + drvs->rx_roce_bytes_msd = port_stats->roce_bytes_received_msd; + drvs->rx_roce_frames = port_stats->roce_frames_received; + drvs->roce_drops_crc = port_stats->roce_drops_crc; + drvs->roce_drops_payload_len = + port_stats->roce_drops_payload_len; + } +} + static void populate_lancer_stats(struct be_adapter *adapter) { @@ -489,7 +552,7 @@ static void populate_erx_stats(struct be_adapter *adapter, void be_parse_stats(struct be_adapter *adapter) { - struct be_erx_stats_v1 *erx = be_erx_stats_from_cmd(adapter); + struct be_erx_stats_v2 *erx = be_erx_stats_from_cmd(adapter); struct be_rx_obj *rxo; int i; u32 erx_stat; @@ -499,11 +562,13 @@ void be_parse_stats(struct be_adapter *adapter) } else { if (BE2_chip(adapter)) populate_be_v0_stats(adapter); - else - /* for BE3 and Skyhawk */ + else if (BE3_chip(adapter)) + /* for BE3 */ populate_be_v1_stats(adapter); + else + populate_be_v2_stats(adapter); - /* as erx_v1 is longer than v0, ok to use v1 for v0 access */ + /* erx_v2 is longer than v0, v1. use v2 for v0, v1 access */ for_all_rx_queues(adapter, rxo, i) { erx_stat = erx->rx_drops_no_fragments[rxo->q.id]; populate_erx_stats(adapter, rxo, erx_stat); @@ -935,8 +1000,10 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, struct net_device *netdev) u32 start = txq->head; skb = be_xmit_workarounds(adapter, skb, &skip_hw_vlan); - if (!skb) + if (!skb) { + tx_stats(txo)->tx_drv_drops++; return NETDEV_TX_OK; + } wrb_cnt = wrb_cnt_for_skb(adapter, skb, &dummy_wrb); @@ -965,6 +1032,7 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, struct net_device *netdev) be_tx_stats_update(txo, wrb_cnt, copied, gso_segs, stopped); } else { txq->head = start; + tx_stats(txo)->tx_drv_drops++; dev_kfree_skb_any(skb); } return NETDEV_TX_OK; @@ -1275,53 +1343,79 @@ static int be_set_vf_tx_rate(struct net_device *netdev, return status; } -static void be_eqd_update(struct be_adapter *adapter, struct be_eq_obj *eqo) +static void be_aic_update(struct be_aic_obj *aic, u64 rx_pkts, u64 tx_pkts, + ulong now) { - struct be_rx_stats *stats = rx_stats(&adapter->rx_obj[eqo->idx]); - ulong now = jiffies; - ulong delta = now - stats->rx_jiffies; - u64 pkts; - unsigned int start, eqd; + aic->rx_pkts_prev = rx_pkts; + aic->tx_reqs_prev = tx_pkts; + aic->jiffies = now; +} - if (!eqo->enable_aic) { - eqd = eqo->eqd; - goto modify_eqd; - } +static void be_eqd_update(struct be_adapter *adapter) +{ + struct be_set_eqd set_eqd[MAX_EVT_QS]; + int eqd, i, num = 0, start; + struct be_aic_obj *aic; + struct be_eq_obj *eqo; + struct be_rx_obj *rxo; + struct be_tx_obj *txo; + u64 rx_pkts, tx_pkts; + ulong now; + u32 pps, delta; - if (eqo->idx >= adapter->num_rx_qs) - return; + for_all_evt_queues(adapter, eqo, i) { + aic = &adapter->aic_obj[eqo->idx]; + if (!aic->enable) { + if (aic->jiffies) + aic->jiffies = 0; + eqd = aic->et_eqd; + goto modify_eqd; + } - stats = rx_stats(&adapter->rx_obj[eqo->idx]); + rxo = &adapter->rx_obj[eqo->idx]; + do { + start = u64_stats_fetch_begin_bh(&rxo->stats.sync); + rx_pkts = rxo->stats.rx_pkts; + } while (u64_stats_fetch_retry_bh(&rxo->stats.sync, start)); - /* Wrapped around */ - if (time_before(now, stats->rx_jiffies)) { - stats->rx_jiffies = now; - return; - } + txo = &adapter->tx_obj[eqo->idx]; + do { + start = u64_stats_fetch_begin_bh(&txo->stats.sync); + tx_pkts = txo->stats.tx_reqs; + } while (u64_stats_fetch_retry_bh(&txo->stats.sync, start)); - /* Update once a second */ - if (delta < HZ) - return; - do { - start = u64_stats_fetch_begin_bh(&stats->sync); - pkts = stats->rx_pkts; - } while (u64_stats_fetch_retry_bh(&stats->sync, start)); - - stats->rx_pps = (unsigned long)(pkts - stats->rx_pkts_prev) / (delta / HZ); - stats->rx_pkts_prev = pkts; - stats->rx_jiffies = now; - eqd = (stats->rx_pps / 110000) << 3; - eqd = min(eqd, eqo->max_eqd); - eqd = max(eqd, eqo->min_eqd); - if (eqd < 10) - eqd = 0; + /* Skip, if wrapped around or first calculation */ + now = jiffies; + if (!aic->jiffies || time_before(now, aic->jiffies) || + rx_pkts < aic->rx_pkts_prev || + tx_pkts < aic->tx_reqs_prev) { + be_aic_update(aic, rx_pkts, tx_pkts, now); + continue; + } + + delta = jiffies_to_msecs(now - aic->jiffies); + pps = (((u32)(rx_pkts - aic->rx_pkts_prev) * 1000) / delta) + + (((u32)(tx_pkts - aic->tx_reqs_prev) * 1000) / delta); + eqd = (pps / 15000) << 2; + + if (eqd < 8) + eqd = 0; + eqd = min_t(u32, eqd, aic->max_eqd); + eqd = max_t(u32, eqd, aic->min_eqd); + be_aic_update(aic, rx_pkts, tx_pkts, now); modify_eqd: - if (eqd != eqo->cur_eqd) { - be_cmd_modify_eqd(adapter, eqo->q.id, eqd); - eqo->cur_eqd = eqd; + if (eqd != aic->prev_eqd) { + set_eqd[num].delay_multiplier = (eqd * 65)/100; + set_eqd[num].eq_id = eqo->q.id; + aic->prev_eqd = eqd; + num++; + } } + + if (num) + be_cmd_modify_eqd(adapter, set_eqd, num); } static void be_rx_stats_update(struct be_rx_obj *rxo, @@ -1463,7 +1557,7 @@ static void skb_fill_rx_data(struct be_rx_obj *rxo, struct sk_buff *skb, } /* Process the RX completion indicated by rxcp when GRO is disabled */ -static void be_rx_compl_process(struct be_rx_obj *rxo, +static void be_rx_compl_process(struct be_rx_obj *rxo, struct napi_struct *napi, struct be_rx_compl_info *rxcp) { struct be_adapter *adapter = rxo->adapter; @@ -1488,7 +1582,7 @@ static void be_rx_compl_process(struct be_rx_obj *rxo, skb_record_rx_queue(skb, rxo - &adapter->rx_obj[0]); if (netdev->features & NETIF_F_RXHASH) skb->rxhash = rxcp->rss_hash; - + skb_mark_napi_id(skb, napi); if (rxcp->vlanf) __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), rxcp->vlan_tag); @@ -1546,6 +1640,7 @@ static void be_rx_compl_process_gro(struct be_rx_obj *rxo, skb_record_rx_queue(skb, rxo - &adapter->rx_obj[0]); if (adapter->netdev->features & NETIF_F_RXHASH) skb->rxhash = rxcp->rss_hash; + skb_mark_napi_id(skb, napi); if (rxcp->vlanf) __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), rxcp->vlan_tag); @@ -1726,6 +1821,8 @@ static void be_post_rx_frags(struct be_rx_obj *rxo, gfp_t gfp) if (posted) { atomic_add(posted, &rxq->used); + if (rxo->rx_post_starved) + rxo->rx_post_starved = false; be_rxq_notify(adapter, rxq->id, posted); } else if (atomic_read(&rxq->used) == 0) { /* Let be_worker replenish when memory is available */ @@ -1928,6 +2025,7 @@ static void be_evt_queues_destroy(struct be_adapter *adapter) if (eqo->q.created) { be_eq_clean(eqo); be_cmd_q_destroy(adapter, &eqo->q, QTYPE_EQ); + napi_hash_del(&eqo->napi); netif_napi_del(&eqo->napi); } be_queue_free(adapter, &eqo->q); @@ -1938,6 +2036,7 @@ static int be_evt_queues_create(struct be_adapter *adapter) { struct be_queue_info *eq; struct be_eq_obj *eqo; + struct be_aic_obj *aic; int i, rc; adapter->num_evt_qs = min_t(u16, num_irqs(adapter), @@ -1946,11 +2045,13 @@ static int be_evt_queues_create(struct be_adapter *adapter) for_all_evt_queues(adapter, eqo, i) { netif_napi_add(adapter->netdev, &eqo->napi, be_poll, BE_NAPI_WEIGHT); + napi_hash_add(&eqo->napi); + aic = &adapter->aic_obj[i]; eqo->adapter = adapter; eqo->tx_budget = BE_TX_BUDGET; eqo->idx = i; - eqo->max_eqd = BE_MAX_EQD; - eqo->enable_aic = true; + aic->max_eqd = BE_MAX_EQD; + aic->enable = true; eq = &eqo->q; rc = be_queue_alloc(adapter, eq, EVNT_Q_LEN, @@ -2167,7 +2268,7 @@ static inline bool do_gro(struct be_rx_compl_info *rxcp) } static int be_process_rx(struct be_rx_obj *rxo, struct napi_struct *napi, - int budget) + int budget, int polling) { struct be_adapter *adapter = rxo->adapter; struct be_queue_info *rx_cq = &rxo->cq; @@ -2198,10 +2299,12 @@ static int be_process_rx(struct be_rx_obj *rxo, struct napi_struct *napi, goto loop_continue; } - if (do_gro(rxcp)) + /* Don't do gro when we're busy_polling */ + if (do_gro(rxcp) && polling != BUSY_POLLING) be_rx_compl_process_gro(rxo, napi, rxcp); else - be_rx_compl_process(rxo, rxcp); + be_rx_compl_process(rxo, napi, rxcp); + loop_continue: be_rx_stats_update(rxo, rxcp); } @@ -2209,7 +2312,11 @@ loop_continue: if (work_done) { be_cq_notify(adapter, rx_cq->id, true, work_done); - if (atomic_read(&rxo->q.used) < RX_FRAGS_REFILL_WM) + /* When an rx-obj gets into post_starved state, just + * let be_worker do the posting. + */ + if (atomic_read(&rxo->q.used) < RX_FRAGS_REFILL_WM && + !rxo->rx_post_starved) be_post_rx_frags(rxo, GFP_ATOMIC); } @@ -2254,6 +2361,7 @@ int be_poll(struct napi_struct *napi, int budget) struct be_eq_obj *eqo = container_of(napi, struct be_eq_obj, napi); struct be_adapter *adapter = eqo->adapter; int max_work = 0, work, i, num_evts; + struct be_rx_obj *rxo; bool tx_done; num_evts = events_get(eqo); @@ -2266,13 +2374,18 @@ int be_poll(struct napi_struct *napi, int budget) max_work = budget; } - /* This loop will iterate twice for EQ0 in which - * completions of the last RXQ (default one) are also processed - * For other EQs the loop iterates only once - */ - for (i = eqo->idx; i < adapter->num_rx_qs; i += adapter->num_evt_qs) { - work = be_process_rx(&adapter->rx_obj[i], napi, budget); - max_work = max(work, max_work); + if (be_lock_napi(eqo)) { + /* This loop will iterate twice for EQ0 in which + * completions of the last RXQ (default one) are also processed + * For other EQs the loop iterates only once + */ + for_all_rx_queues_on_eq(adapter, eqo, rxo, i) { + work = be_process_rx(rxo, napi, budget, NAPI_POLLING); + max_work = max(work, max_work); + } + be_unlock_napi(eqo); + } else { + max_work = budget; } if (is_mcc_eqo(eqo)) @@ -2288,6 +2401,28 @@ int be_poll(struct napi_struct *napi, int budget) return max_work; } +#ifdef CONFIG_NET_RX_BUSY_POLL +static int be_busy_poll(struct napi_struct *napi) +{ + struct be_eq_obj *eqo = container_of(napi, struct be_eq_obj, napi); + struct be_adapter *adapter = eqo->adapter; + struct be_rx_obj *rxo; + int i, work = 0; + + if (!be_lock_busy_poll(eqo)) + return LL_FLUSH_BUSY; + + for_all_rx_queues_on_eq(adapter, eqo, rxo, i) { + work = be_process_rx(rxo, napi, 4, BUSY_POLLING); + if (work) + break; + } + + be_unlock_busy_poll(eqo); + return work; +} +#endif + void be_detect_error(struct be_adapter *adapter) { u32 ue_lo = 0, ue_hi = 0, ue_lo_mask = 0, ue_hi_mask = 0; @@ -2519,9 +2654,11 @@ static int be_close(struct net_device *netdev) be_roce_dev_close(adapter); - if (adapter->flags & BE_FLAGS_NAPI_ENABLED) { - for_all_evt_queues(adapter, eqo, i) + for_all_evt_queues(adapter, eqo, i) { + if (adapter->flags & BE_FLAGS_NAPI_ENABLED) { napi_disable(&eqo->napi); + be_disable_busy_poll(eqo); + } adapter->flags &= ~BE_FLAGS_NAPI_ENABLED; } @@ -2632,6 +2769,7 @@ static int be_open(struct net_device *netdev) for_all_evt_queues(adapter, eqo, i) { napi_enable(&eqo->napi); + be_enable_busy_poll(eqo); be_eq_notify(adapter, eqo->q.id, true, false, 0); } adapter->flags |= BE_FLAGS_NAPI_ENABLED; @@ -2937,7 +3075,8 @@ static int be_vf_setup(struct be_adapter *adapter) goto err; vf_cfg->def_vid = def_vlan; - be_cmd_enable_vf(adapter, vf + 1); + if (!old_vfs) + be_cmd_enable_vf(adapter, vf + 1); } if (!old_vfs) { @@ -2962,12 +3101,12 @@ static void BEx_get_resources(struct be_adapter *adapter, struct pci_dev *pdev = adapter->pdev; bool use_sriov = false; - if (BE3_chip(adapter) && be_physfn(adapter)) { + if (BE3_chip(adapter) && sriov_want(adapter)) { int max_vfs; max_vfs = pci_sriov_get_totalvfs(pdev); res->max_vfs = max_vfs > 0 ? min(MAX_VFS, max_vfs) : 0; - use_sriov = res->max_vfs && num_vfs; + use_sriov = res->max_vfs; } if (be_physfn(adapter)) @@ -2983,8 +3122,9 @@ static void BEx_get_resources(struct be_adapter *adapter, res->max_vlans = BE_NUM_VLANS_SUPPORTED; res->max_mcast_mac = BE_MAX_MC; + /* For BE3 1Gb ports, F/W does not properly support multiple TXQs */ if (BE2_chip(adapter) || use_sriov || be_is_mc(adapter) || - !be_physfn(adapter)) + !be_physfn(adapter) || (adapter->port_num > 1)) res->max_tx_qs = 1; else res->max_tx_qs = BE3_MAX_TX_QS; @@ -3026,14 +3166,6 @@ static int be_get_resources(struct be_adapter *adapter) adapter->res = res; } - /* For BE3 only check if FW suggests a different max-txqs value */ - if (BE3_chip(adapter)) { - status = be_cmd_get_profile_config(adapter, &res, 0); - if (!status && res.max_tx_qs) - adapter->res.max_tx_qs = - min(adapter->res.max_tx_qs, res.max_tx_qs); - } - /* For Lancer, SH etc read per-function resource limits from FW. * GET_FUNC_CONFIG returns per function guaranteed limits. * GET_PROFILE_CONFIG returns PCI-E related limits PF-pool limits @@ -3264,7 +3396,7 @@ static int be_setup(struct be_adapter *adapter) be_cmd_set_flow_control(adapter, adapter->tx_fc, adapter->rx_fc); - if (be_physfn(adapter) && num_vfs) { + if (sriov_want(adapter)) { if (be_max_vfs(adapter)) be_vf_setup(adapter); else @@ -3906,6 +4038,9 @@ static const struct net_device_ops be_netdev_ops = { #endif .ndo_bridge_setlink = be_ndo_bridge_setlink, .ndo_bridge_getlink = be_ndo_bridge_getlink, +#ifdef CONFIG_NET_RX_BUSY_POLL + .ndo_busy_poll = be_busy_poll +#endif }; static void be_netdev_init(struct net_device *netdev) @@ -3966,11 +4101,6 @@ static int be_roce_map_pci_bars(struct be_adapter *adapter) static int be_map_pci_bars(struct be_adapter *adapter) { u8 __iomem *addr; - u32 sli_intf; - - pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, &sli_intf); - adapter->if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >> - SLI_INTF_IF_TYPE_SHIFT; if (BEx_chip(adapter) && be_physfn(adapter)) { adapter->csr = pci_iomap(adapter->pdev, 2, 0); @@ -4083,9 +4213,11 @@ static int be_stats_init(struct be_adapter *adapter) cmd->size = sizeof(struct lancer_cmd_req_pport_stats); else if (BE2_chip(adapter)) cmd->size = sizeof(struct be_cmd_req_get_stats_v0); - else - /* BE3 and Skyhawk */ + else if (BE3_chip(adapter)) cmd->size = sizeof(struct be_cmd_req_get_stats_v1); + else + /* ALL non-BE ASICs */ + cmd->size = sizeof(struct be_cmd_req_get_stats_v2); cmd->va = dma_zalloc_coherent(&adapter->pdev->dev, cmd->size, &cmd->dma, GFP_KERNEL); @@ -4119,7 +4251,6 @@ static void be_remove(struct pci_dev *pdev) pci_disable_pcie_error_reporting(pdev); - pci_set_drvdata(pdev, NULL); pci_release_regions(pdev); pci_disable_device(pdev); @@ -4268,7 +4399,6 @@ static void be_worker(struct work_struct *work) struct be_adapter *adapter = container_of(work, struct be_adapter, work.work); struct be_rx_obj *rxo; - struct be_eq_obj *eqo; int i; /* when interrupts are not yet enabled, just reap any pending @@ -4293,14 +4423,14 @@ static void be_worker(struct work_struct *work) be_cmd_get_die_temperature(adapter); for_all_rx_queues(adapter, rxo, i) { - if (rxo->rx_post_starved) { - rxo->rx_post_starved = false; + /* Replenish RX-queues starved due to memory + * allocation failures. + */ + if (rxo->rx_post_starved) be_post_rx_frags(rxo, GFP_KERNEL); - } } - for_all_evt_queues(adapter, eqo, i) - be_eqd_update(adapter, eqo); + be_eqd_update(adapter); reschedule: adapter->work_counter++; @@ -4376,9 +4506,11 @@ static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id) } } - status = pci_enable_pcie_error_reporting(pdev); - if (status) - dev_info(&pdev->dev, "Could not use PCIe error reporting\n"); + if (be_physfn(adapter)) { + status = pci_enable_pcie_error_reporting(pdev); + if (!status) + dev_info(&pdev->dev, "PCIe error reporting enabled\n"); + } status = be_ctrl_init(adapter); if (status) @@ -4449,7 +4581,6 @@ ctrl_clean: be_ctrl_cleanup(adapter); free_netdev: free_netdev(netdev); - pci_set_drvdata(pdev, NULL); rel_reg: pci_release_regions(pdev); disable_dev: |