]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/net/ethernet/emulex/benet/be_main.c
Merge remote-tracking branch 'net-next/master'
[karo-tx-linux.git] / drivers / net / ethernet / emulex / benet / be_main.c
index 8ae79acd7db851c2867220aa5b72d5943fc14ec6..77b4a8ae87a6ca64684d7103ee53a08446e060bc 100644 (file)
@@ -306,9 +306,13 @@ 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,9 +324,13 @@ 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++;
@@ -4362,9 +4450,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)
@@ -4435,7 +4525,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: