Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[cascardo/linux.git] / drivers / net / ethernet / emulex / benet / be_main.c
index d1cf127..5366864 100644 (file)
@@ -854,9 +854,9 @@ static void unmap_tx_frag(struct device *dev, struct be_eth_wrb *wrb,
 }
 
 /* Grab a WRB header for xmit */
-static u16 be_tx_get_wrb_hdr(struct be_tx_obj *txo)
+static u32 be_tx_get_wrb_hdr(struct be_tx_obj *txo)
 {
-       u16 head = txo->q.head;
+       u32 head = txo->q.head;
 
        queue_head_inc(&txo->q);
        return head;
@@ -900,7 +900,7 @@ static void be_tx_setup_wrb_frag(struct be_tx_obj *txo, dma_addr_t busaddr,
  * WRBs of the current packet are unmapped. Invoked to handle tx setup errors.
  */
 static void be_xmit_restore(struct be_adapter *adapter,
-                           struct be_tx_obj *txo, u16 head, bool map_single,
+                           struct be_tx_obj *txo, u32 head, bool map_single,
                            u32 copied)
 {
        struct device *dev;
@@ -935,7 +935,7 @@ static u32 be_xmit_enqueue(struct be_adapter *adapter, struct be_tx_obj *txo,
        struct device *dev = &adapter->pdev->dev;
        struct be_queue_info *txq = &txo->q;
        bool map_single = false;
-       u16 head = txq->head;
+       u32 head = txq->head;
        dma_addr_t busaddr;
        int len;
 
@@ -1128,6 +1128,8 @@ static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter,
                                           struct sk_buff *skb,
                                           struct be_wrb_params *wrb_params)
 {
+       int err;
+
        /* Lancer, SH and BE3 in SRIOV mode have a bug wherein
         * packets that are 32b or less may cause a transmit stall
         * on that port. The workaround is to pad such packets
@@ -1144,6 +1146,13 @@ static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter,
                        return NULL;
        }
 
+       /* The stack can send us skbs with length greater than
+        * what the HW can handle. Trim the extra bytes.
+        */
+       WARN_ON_ONCE(skb->len > BE_MAX_GSO_SIZE);
+       err = pskb_trim(skb, BE_MAX_GSO_SIZE);
+       WARN_ON(err);
+
        return skb;
 }
 
@@ -1468,6 +1477,9 @@ static int be_vlan_rem_vid(struct net_device *netdev, __be16 proto, u16 vid)
        if (lancer_chip(adapter) && vid == 0)
                return 0;
 
+       if (!test_bit(vid, adapter->vids))
+               return 0;
+
        clear_bit(vid, adapter->vids);
        adapter->vlans_added--;
 
@@ -1919,8 +1931,7 @@ static u32 be_get_eq_delay_mult_enc(struct be_eq_obj *eqo)
        if (!aic->enable)
                return 0;
 
-       if (time_before_eq(now, aic->jiffies) ||
-           jiffies_to_msecs(now - aic->jiffies) < 1)
+       if (jiffies_to_msecs(now - aic->jiffies) < 1)
                eqd = aic->prev_eqd;
        else
                eqd = be_get_new_eqd(eqo);
@@ -1993,7 +2004,7 @@ static struct be_rx_page_info *get_rx_page_info(struct be_rx_obj *rxo)
        struct be_adapter *adapter = rxo->adapter;
        struct be_rx_page_info *rx_page_info;
        struct be_queue_info *rxq = &rxo->q;
-       u16 frag_idx = rxq->tail;
+       u32 frag_idx = rxq->tail;
 
        rx_page_info = &rxo->page_info_tbl[frag_idx];
        BUG_ON(!rx_page_info->page);
@@ -2404,10 +2415,11 @@ static u16 be_tx_compl_process(struct be_adapter *adapter,
 {
        struct sk_buff **sent_skbs = txo->sent_skb_list;
        struct be_queue_info *txq = &txo->q;
-       u16 frag_index, num_wrbs = 0;
        struct sk_buff *skb = NULL;
        bool unmap_skb_hdr = false;
        struct be_eth_wrb *wrb;
+       u16 num_wrbs = 0;
+       u32 frag_index;
 
        do {
                if (sent_skbs[txq->tail]) {
@@ -2519,10 +2531,11 @@ static void be_rx_cq_clean(struct be_rx_obj *rxo)
 
 static void be_tx_compl_clean(struct be_adapter *adapter)
 {
-       u16 end_idx, notified_idx, cmpl = 0, timeo = 0, num_wrbs = 0;
        struct device *dev = &adapter->pdev->dev;
+       u16 cmpl = 0, timeo = 0, num_wrbs = 0;
        struct be_tx_compl_info *txcp;
        struct be_queue_info *txq;
+       u32 end_idx, notified_idx;
        struct be_tx_obj *txo;
        int i, pending_txqs;
 
@@ -3368,6 +3381,7 @@ done:
 
 static void be_rx_qs_destroy(struct be_adapter *adapter)
 {
+       struct rss_info *rss = &adapter->rss_info;
        struct be_queue_info *q;
        struct be_rx_obj *rxo;
        int i;
@@ -3394,6 +3408,12 @@ static void be_rx_qs_destroy(struct be_adapter *adapter)
                }
                be_queue_free(adapter, q);
        }
+
+       if (rss->rss_flags) {
+               rss->rss_flags = RSS_ENABLE_NONE;
+               be_cmd_rss_config(adapter, rss->rsstable, rss->rss_flags,
+                                 128, rss->rss_hkey);
+       }
 }
 
 static void be_disable_if_filters(struct be_adapter *adapter)
@@ -3514,20 +3534,21 @@ static int be_rx_qs_create(struct be_adapter *adapter)
                if (!BEx_chip(adapter))
                        rss->rss_flags |= RSS_ENABLE_UDP_IPV4 |
                                RSS_ENABLE_UDP_IPV6;
+
+               netdev_rss_key_fill(rss_key, RSS_HASH_KEY_LEN);
+               rc = be_cmd_rss_config(adapter, rss->rsstable, rss->rss_flags,
+                                      RSS_INDIR_TABLE_LEN, rss_key);
+               if (rc) {
+                       rss->rss_flags = RSS_ENABLE_NONE;
+                       return rc;
+               }
+
+               memcpy(rss->rss_hkey, rss_key, RSS_HASH_KEY_LEN);
        } else {
                /* Disable RSS, if only default RX Q is created */
                rss->rss_flags = RSS_ENABLE_NONE;
        }
 
-       netdev_rss_key_fill(rss_key, RSS_HASH_KEY_LEN);
-       rc = be_cmd_rss_config(adapter, rss->rsstable, rss->rss_flags,
-                              RSS_INDIR_TABLE_LEN, rss_key);
-       if (rc) {
-               rss->rss_flags = RSS_ENABLE_NONE;
-               return rc;
-       }
-
-       memcpy(rss->rss_hkey, rss_key, RSS_HASH_KEY_LEN);
 
        /* Post 1 less than RXQ-len to avoid head being equal to tail,
         * which is a queue empty condition
@@ -3794,18 +3815,15 @@ static u16 be_calculate_vf_qs(struct be_adapter *adapter, u16 num_vfs)
        struct be_resources res = adapter->pool_res;
        u16 num_vf_qs = 1;
 
-       /* Distribute the queue resources equally among the PF and it's VFs
+       /* Distribute the queue resources among the PF and it's VFs
         * Do not distribute queue resources in multi-channel configuration.
         */
        if (num_vfs && !be_is_mc(adapter)) {
-               /* If number of VFs requested is 8 less than max supported,
-                * assign 8 queue pairs to the PF and divide the remaining
-                * resources evenly among the VFs
-                */
-               if (num_vfs < (be_max_vfs(adapter) - 8))
-                       num_vf_qs = (res.max_rss_qs - 8) / num_vfs;
-               else
-                       num_vf_qs = res.max_rss_qs / num_vfs;
+                /* Divide the qpairs evenly among the VFs and the PF, capped
+                 * at VF-EQ-count. Any remainder qpairs belong to the PF.
+                 */
+               num_vf_qs = min(SH_VF_MAX_NIC_EQS,
+                               res.max_rss_qs / (num_vfs + 1));
 
                /* Skyhawk-R chip supports only MAX_RSS_IFACES RSS capable
                 * interfaces per port. Provide RSS on VFs, only if number
@@ -4084,6 +4102,7 @@ static void be_setup_init(struct be_adapter *adapter)
        adapter->if_handle = -1;
        adapter->be3_native = false;
        adapter->if_flags = 0;
+       adapter->phy_state = BE_UNKNOWN_PHY_STATE;
        if (be_physfn(adapter))
                adapter->cmd_privileges = MAX_PRIVILEGES;
        else
@@ -4267,10 +4286,10 @@ static void be_schedule_worker(struct be_adapter *adapter)
        adapter->flags |= BE_FLAGS_WORKER_SCHEDULED;
 }
 
-static void be_schedule_err_detection(struct be_adapter *adapter)
+static void be_schedule_err_detection(struct be_adapter *adapter, u32 delay)
 {
        schedule_delayed_work(&adapter->be_err_detection_work,
-                             msecs_to_jiffies(1000));
+                             msecs_to_jiffies(delay));
        adapter->flags |= BE_FLAGS_ERR_DETECTION_SCHEDULED;
 }
 
@@ -4309,6 +4328,23 @@ err:
        return status;
 }
 
+static int be_if_create(struct be_adapter *adapter)
+{
+       u32 en_flags = BE_IF_FLAGS_RSS | BE_IF_FLAGS_DEFQ_RSS;
+       u32 cap_flags = be_if_cap_flags(adapter);
+       int status;
+
+       if (adapter->cfg_num_qs == 1)
+               cap_flags &= ~(BE_IF_FLAGS_DEFQ_RSS | BE_IF_FLAGS_RSS);
+
+       en_flags &= cap_flags;
+       /* will enable all the needed filter flags in be_open() */
+       status = be_cmd_if_create(adapter, be_if_cap_flags(adapter), en_flags,
+                                 &adapter->if_handle, 0);
+
+       return status;
+}
+
 int be_update_queues(struct be_adapter *adapter)
 {
        struct net_device *netdev = adapter->netdev;
@@ -4326,6 +4362,9 @@ int be_update_queues(struct be_adapter *adapter)
                be_msix_disable(adapter);
 
        be_clear_queues(adapter);
+       status = be_cmd_if_destroy(adapter, adapter->if_handle,  0);
+       if (status)
+               return status;
 
        if (!msix_enabled(adapter)) {
                status = be_msix_enable(adapter);
@@ -4333,6 +4372,10 @@ int be_update_queues(struct be_adapter *adapter)
                        return status;
        }
 
+       status = be_if_create(adapter);
+       if (status)
+               return status;
+
        status = be_setup_queues(adapter);
        if (status)
                return status;
@@ -4397,7 +4440,6 @@ static int be_func_init(struct be_adapter *adapter)
 static int be_setup(struct be_adapter *adapter)
 {
        struct device *dev = &adapter->pdev->dev;
-       u32 en_flags;
        int status;
 
        status = be_func_init(adapter);
@@ -4430,10 +4472,7 @@ static int be_setup(struct be_adapter *adapter)
                goto err;
 
        /* will enable all the needed filter flags in be_open() */
-       en_flags = BE_IF_FLAGS_RSS | BE_IF_FLAGS_DEFQ_RSS;
-       en_flags = en_flags & be_if_cap_flags(adapter);
-       status = be_cmd_if_create(adapter, be_if_cap_flags(adapter), en_flags,
-                                 &adapter->if_handle, 0);
+       status = be_if_create(adapter);
        if (status)
                goto err;
 
@@ -4591,6 +4630,9 @@ static int be_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
 
        /* BE and Lancer chips support VEB mode only */
        if (BEx_chip(adapter) || lancer_chip(adapter)) {
+               /* VEB is disabled in non-SR-IOV profiles on BE3/Lancer */
+               if (!pci_sriov_get_totalvfs(adapter->pdev))
+                       return 0;
                hsw_mode = PORT_FWD_TYPE_VEB;
        } else {
                status = be_cmd_get_hsw_config(adapter, NULL, 0,
@@ -4806,7 +4848,7 @@ static void be_netdev_init(struct net_device *netdev)
        netdev->hw_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 |
                NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM |
                NETIF_F_HW_VLAN_CTAG_TX;
-       if (be_multi_rxq(adapter))
+       if ((be_if_cap_flags(adapter) & BE_IF_FLAGS_RSS))
                netdev->hw_features |= NETIF_F_RXHASH;
 
        netdev->features |= netdev->hw_features |
@@ -4819,7 +4861,7 @@ static void be_netdev_init(struct net_device *netdev)
 
        netdev->flags |= IFF_MULTICAST;
 
-       netif_set_gso_max_size(netdev, 65535 - ETH_HLEN);
+       netif_set_gso_max_size(netdev, BE_MAX_GSO_SIZE - ETH_HLEN);
 
        netdev->netdev_ops = &be_netdev_ops;
 
@@ -4861,21 +4903,27 @@ static int be_resume(struct be_adapter *adapter)
 
 static int be_err_recover(struct be_adapter *adapter)
 {
-       struct device *dev = &adapter->pdev->dev;
        int status;
 
+       /* Error recovery is supported only Lancer as of now */
+       if (!lancer_chip(adapter))
+               return -EIO;
+
+       /* Wait for adapter to reach quiescent state before
+        * destroying queues
+        */
+       status = be_fw_wait_ready(adapter);
+       if (status)
+               goto err;
+
+       be_cleanup(adapter);
+
        status = be_resume(adapter);
        if (status)
                goto err;
 
-       dev_info(dev, "Adapter recovery successful\n");
        return 0;
 err:
-       if (be_physfn(adapter))
-               dev_err(dev, "Adapter recovery failed\n");
-       else
-               dev_err(dev, "Re-trying adapter recovery\n");
-
        return status;
 }
 
@@ -4884,21 +4932,43 @@ static void be_err_detection_task(struct work_struct *work)
        struct be_adapter *adapter =
                                container_of(work, struct be_adapter,
                                             be_err_detection_work.work);
-       int status = 0;
+       struct device *dev = &adapter->pdev->dev;
+       int recovery_status;
+       int delay = ERR_DETECTION_DELAY;
 
        be_detect_error(adapter);
 
-       if (be_check_error(adapter, BE_ERROR_HW)) {
-               be_cleanup(adapter);
-
-               /* As of now error recovery support is in Lancer only */
-               if (lancer_chip(adapter))
-                       status = be_err_recover(adapter);
+       if (be_check_error(adapter, BE_ERROR_HW))
+               recovery_status = be_err_recover(adapter);
+       else
+               goto reschedule_task;
+
+       if (!recovery_status) {
+               adapter->recovery_retries = 0;
+               dev_info(dev, "Adapter recovery successful\n");
+               goto reschedule_task;
+       } else if (be_virtfn(adapter)) {
+               /* For VFs, check if PF have allocated resources
+                * every second.
+                */
+               dev_err(dev, "Re-trying adapter recovery\n");
+               goto reschedule_task;
+       } else if (adapter->recovery_retries++ <
+                  MAX_ERR_RECOVERY_RETRY_COUNT) {
+               /* In case of another error during recovery, it takes 30 sec
+                * for adapter to come out of error. Retry error recovery after
+                * this time interval.
+                */
+               dev_err(&adapter->pdev->dev, "Re-trying adapter recovery\n");
+               delay = ERR_RECOVERY_RETRY_DELAY;
+               goto reschedule_task;
+       } else {
+               dev_err(dev, "Adapter recovery failed\n");
        }
 
-       /* Always attempt recovery on VFs */
-       if (!status || be_virtfn(adapter))
-               be_schedule_err_detection(adapter);
+       return;
+reschedule_task:
+       be_schedule_err_detection(adapter, delay);
 }
 
 static void be_log_sfp_info(struct be_adapter *adapter)
@@ -4908,11 +4978,13 @@ static void be_log_sfp_info(struct be_adapter *adapter)
        status = be_cmd_query_sfp_info(adapter);
        if (!status) {
                dev_err(&adapter->pdev->dev,
-                       "Unqualified SFP+ detected on %c from %s part no: %s",
-                       adapter->port_name, adapter->phy.vendor_name,
+                       "Port %c: %s Vendor: %s part no: %s",
+                       adapter->port_name,
+                       be_misconfig_evt_port_state[adapter->phy_state],
+                       adapter->phy.vendor_name,
                        adapter->phy.vendor_pn);
        }
-       adapter->flags &= ~BE_FLAGS_EVT_INCOMPATIBLE_SFP;
+       adapter->flags &= ~BE_FLAGS_PHY_MISCONFIGURED;
 }
 
 static void be_worker(struct work_struct *work)
@@ -4956,7 +5028,7 @@ static void be_worker(struct work_struct *work)
        if (!skyhawk_chip(adapter))
                be_eqd_update(adapter, false);
 
-       if (adapter->flags & BE_FLAGS_EVT_INCOMPATIBLE_SFP)
+       if (adapter->flags & BE_FLAGS_PHY_MISCONFIGURED)
                be_log_sfp_info(adapter);
 
 reschedule:
@@ -5298,7 +5370,7 @@ static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id)
 
        be_roce_dev_add(adapter);
 
-       be_schedule_err_detection(adapter);
+       be_schedule_err_detection(adapter, ERR_DETECTION_DELAY);
 
        /* On Die temperature not supported for VF. */
        if (be_physfn(adapter) && IS_ENABLED(CONFIG_BE2NET_HWMON)) {
@@ -5365,7 +5437,7 @@ static int be_pci_resume(struct pci_dev *pdev)
        if (status)
                return status;
 
-       be_schedule_err_detection(adapter);
+       be_schedule_err_detection(adapter, ERR_DETECTION_DELAY);
 
        if (adapter->wol_en)
                be_setup_wol(adapter, false);
@@ -5401,6 +5473,8 @@ static pci_ers_result_t be_eeh_err_detected(struct pci_dev *pdev,
 
        dev_err(&adapter->pdev->dev, "EEH error detected\n");
 
+       be_roce_dev_remove(adapter);
+
        if (!be_check_error(adapter, BE_ERROR_EEH)) {
                be_set_error(adapter, BE_ERROR_EEH);
 
@@ -5465,7 +5539,9 @@ static void be_eeh_resume(struct pci_dev *pdev)
        if (status)
                goto err;
 
-       be_schedule_err_detection(adapter);
+       be_roce_dev_add(adapter);
+
+       be_schedule_err_detection(adapter, ERR_DETECTION_DELAY);
        return;
 err:
        dev_err(&adapter->pdev->dev, "EEH resume failed\n");