aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/emulex/benet/be_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/emulex/benet/be_main.c')
-rw-r--r--drivers/net/ethernet/emulex/benet/be_main.c227
1 files changed, 158 insertions, 69 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 2c38cc402119..393e3dc05a36 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -306,10 +306,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 +324,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 +430,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 +551,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 +561,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 +999,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 +1031,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 +1342,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,
@@ -1938,6 +2031,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 +2040,12 @@ 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);
+ 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,
@@ -2937,7 +3032,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 +3058,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 +3079,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 +3123,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
@@ -3258,7 +3347,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
@@ -4077,9 +4166,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);
@@ -4113,7 +4204,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);
@@ -4262,7 +4352,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,8 +4382,7 @@ static void be_worker(struct work_struct *work)
}
}
- for_all_evt_queues(adapter, eqo, i)
- be_eqd_update(adapter, eqo);
+ be_eqd_update(adapter);
reschedule:
adapter->work_counter++;
@@ -4370,9 +4458,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)
@@ -4443,7 +4533,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: