Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[firefly-linux-kernel-4.4.55.git] / drivers / net / ethernet / broadcom / bnx2x / bnx2x_sriov.c
index 6adfa2093581ef611960e0c9fe364b69726d6de5..2ce7c7471367812bc88375ab600211c7b2a437db 100644 (file)
@@ -20,7 +20,9 @@
 #include "bnx2x.h"
 #include "bnx2x_init.h"
 #include "bnx2x_cmn.h"
+#include "bnx2x_sp.h"
 #include <linux/crc32.h>
+#include <linux/if_vlan.h>
 
 /* General service functions */
 static void storm_memset_vf_to_pf(struct bnx2x *bp, u16 abs_fid,
@@ -555,8 +557,7 @@ static int bnx2x_vfop_config_list(struct bnx2x *bp,
                rc = bnx2x_config_vlan_mac(bp, vlan_mac);
                if (rc >= 0) {
                        cnt += pos->add ? 1 : -1;
-                       list_del(&pos->link);
-                       list_add(&pos->link, &rollback_list);
+                       list_move(&pos->link, &rollback_list);
                        rc = 0;
                } else if (rc == -EEXIST) {
                        rc = 0;
@@ -958,6 +959,12 @@ op_err:
        BNX2X_ERR("QSETUP[%d:%d] error: rc %d\n", vf->abs_vfid, qid, vfop->rc);
 op_done:
        case BNX2X_VFOP_QSETUP_DONE:
+               vf->cfg_flags |= VF_CFG_VLAN;
+               smp_mb__before_clear_bit();
+               set_bit(BNX2X_SP_RTNL_HYPERVISOR_VLAN,
+                       &bp->sp_rtnl_state);
+               smp_mb__after_clear_bit();
+               schedule_delayed_work(&bp->sp_rtnl_task, 0);
                bnx2x_vfop_end(bp, vf, vfop);
                return;
        default:
@@ -1459,7 +1466,6 @@ static u8 bnx2x_vf_is_pcie_pending(struct bnx2x *bp, u8 abs_vfid)
                return bnx2x_is_pcie_pending(dev);
 
 unknown_dev:
-       BNX2X_ERR("Unknown device\n");
        return false;
 }
 
@@ -1926,20 +1932,22 @@ int bnx2x_iov_init_one(struct bnx2x *bp, int int_mode_param,
 
        /* SRIOV can be enabled only with MSIX */
        if (int_mode_param == BNX2X_INT_MODE_MSI ||
-           int_mode_param == BNX2X_INT_MODE_INTX)
+           int_mode_param == BNX2X_INT_MODE_INTX) {
                BNX2X_ERR("Forced MSI/INTx mode is incompatible with SRIOV\n");
+               return 0;
+       }
 
        err = -EIO;
        /* verify ari is enabled */
        if (!bnx2x_ari_enabled(bp->pdev)) {
-               BNX2X_ERR("ARI not supported, SRIOV can not be enabled\n");
-               return err;
+               BNX2X_ERR("ARI not supported (check pci bridge ARI forwarding), SRIOV can not be enabled\n");
+               return 0;
        }
 
        /* verify igu is in normal mode */
        if (CHIP_INT_MODE_IS_BC(bp)) {
                BNX2X_ERR("IGU not normal mode,  SRIOV can not be enabled\n");
-               return err;
+               return 0;
        }
 
        /* allocate the vfs database */
@@ -1964,8 +1972,10 @@ int bnx2x_iov_init_one(struct bnx2x *bp, int int_mode_param,
        if (iov->total == 0)
                goto failed;
 
-       /* calculate the actual number of VFs */
-       iov->nr_virtfn = min_t(u16, iov->total, (u16)num_vfs_param);
+       iov->nr_virtfn = min_t(u16, iov->total, num_vfs_param);
+
+       DP(BNX2X_MSG_IOV, "num_vfs_param was %d, nr_virtfn was %d\n",
+          num_vfs_param, iov->nr_virtfn);
 
        /* allocate the vf array */
        bp->vfdb->vfs = kzalloc(sizeof(struct bnx2x_virtf) *
@@ -2378,8 +2388,8 @@ int bnx2x_iov_eq_sp_event(struct bnx2x *bp, union event_ring_elem *elem)
                goto get_vf;
        case EVENT_RING_OPCODE_MALICIOUS_VF:
                abs_vfid = elem->message.data.malicious_vf_event.vf_id;
-               DP(BNX2X_MSG_IOV, "Got VF MALICIOUS notification abs_vfid=%d\n",
-                  abs_vfid);
+               DP(BNX2X_MSG_IOV, "Got VF MALICIOUS notification abs_vfid=%d err_id=0x%x\n",
+                  abs_vfid, elem->message.data.malicious_vf_event.err_id);
                goto get_vf;
        default:
                return 1;
@@ -2436,8 +2446,8 @@ get_vf:
                /* Do nothing for now */
                break;
        case EVENT_RING_OPCODE_MALICIOUS_VF:
-               DP(BNX2X_MSG_IOV, "got VF [%d] MALICIOUS notification\n",
-                  vf->abs_vfid);
+               DP(BNX2X_MSG_IOV, "Got VF MALICIOUS notification abs_vfid=%d error id %x\n",
+                  abs_vfid, elem->message.data.malicious_vf_event.err_id);
                /* Do nothing for now */
                break;
        }
@@ -3012,21 +3022,138 @@ void bnx2x_unlock_vf_pf_channel(struct bnx2x *bp, struct bnx2x_virtf *vf,
        vf->op_current = CHANNEL_TLV_NONE;
 }
 
-void bnx2x_enable_sriov(struct bnx2x *bp)
+int bnx2x_sriov_configure(struct pci_dev *dev, int num_vfs_param)
 {
-       int rc = 0;
 
-       /* disbale sriov in case it is still enabled */
+       struct bnx2x *bp = netdev_priv(pci_get_drvdata(dev));
+
+       DP(BNX2X_MSG_IOV, "bnx2x_sriov_configure called with %d, BNX2X_NR_VIRTFN(bp) was %d\n",
+          num_vfs_param, BNX2X_NR_VIRTFN(bp));
+
+       /* HW channel is only operational when PF is up */
+       if (bp->state != BNX2X_STATE_OPEN) {
+               BNX2X_ERR("VF num configurtion via sysfs not supported while PF is down");
+               return -EINVAL;
+       }
+
+       /* we are always bound by the total_vfs in the configuration space */
+       if (num_vfs_param > BNX2X_NR_VIRTFN(bp)) {
+               BNX2X_ERR("truncating requested number of VFs (%d) down to maximum allowed (%d)\n",
+                         num_vfs_param, BNX2X_NR_VIRTFN(bp));
+               num_vfs_param = BNX2X_NR_VIRTFN(bp);
+       }
+
+       bp->requested_nr_virtfn = num_vfs_param;
+       if (num_vfs_param == 0) {
+               pci_disable_sriov(dev);
+               return 0;
+       } else {
+               return bnx2x_enable_sriov(bp);
+       }
+}
+
+int bnx2x_enable_sriov(struct bnx2x *bp)
+{
+       int rc = 0, req_vfs = bp->requested_nr_virtfn;
+
+       rc = pci_enable_sriov(bp->pdev, req_vfs);
+       if (rc) {
+               BNX2X_ERR("pci_enable_sriov failed with %d\n", rc);
+               return rc;
+       }
+       DP(BNX2X_MSG_IOV, "sriov enabled (%d vfs)\n", req_vfs);
+       return req_vfs;
+}
+
+void bnx2x_pf_set_vfs_vlan(struct bnx2x *bp)
+{
+       int vfidx;
+       struct pf_vf_bulletin_content *bulletin;
+
+       DP(BNX2X_MSG_IOV, "configuring vlan for VFs from sp-task\n");
+       for_each_vf(bp, vfidx) {
+       bulletin = BP_VF_BULLETIN(bp, vfidx);
+               if (BP_VF(bp, vfidx)->cfg_flags & VF_CFG_VLAN)
+                       bnx2x_set_vf_vlan(bp->dev, vfidx, bulletin->vlan, 0);
+       }
+}
+
+void bnx2x_disable_sriov(struct bnx2x *bp)
+{
        pci_disable_sriov(bp->pdev);
-       DP(BNX2X_MSG_IOV, "sriov disabled\n");
+}
+
+static int bnx2x_vf_ndo_sanity(struct bnx2x *bp, int vfidx,
+                              struct bnx2x_virtf *vf)
+{
+       if (!IS_SRIOV(bp)) {
+               BNX2X_ERR("vf ndo called though sriov is disabled\n");
+               return -EINVAL;
+       }
+
+       if (vfidx >= BNX2X_NR_VIRTFN(bp)) {
+               BNX2X_ERR("vf ndo called for uninitialized VF. vfidx was %d BNX2X_NR_VIRTFN was %d\n",
+                         vfidx, BNX2X_NR_VIRTFN(bp));
+               return -EINVAL;
+       }
+
+       if (!vf) {
+               BNX2X_ERR("vf ndo called but vf was null. vfidx was %d\n",
+                         vfidx);
+               return -EINVAL;
+       }
 
-       /* enable sriov */
-       DP(BNX2X_MSG_IOV, "vf num (%d)\n", (bp->vfdb->sriov.nr_virtfn));
-       rc = pci_enable_sriov(bp->pdev, (bp->vfdb->sriov.nr_virtfn));
+       return 0;
+}
+
+int bnx2x_get_vf_config(struct net_device *dev, int vfidx,
+                       struct ifla_vf_info *ivi)
+{
+       struct bnx2x *bp = netdev_priv(dev);
+       struct bnx2x_virtf *vf = BP_VF(bp, vfidx);
+       struct bnx2x_vlan_mac_obj *mac_obj = &bnx2x_vfq(vf, 0, mac_obj);
+       struct bnx2x_vlan_mac_obj *vlan_obj = &bnx2x_vfq(vf, 0, vlan_obj);
+       struct pf_vf_bulletin_content *bulletin = BP_VF_BULLETIN(bp, vfidx);
+       int rc;
+
+       /* sanity */
+       rc = bnx2x_vf_ndo_sanity(bp, vfidx, vf);
        if (rc)
-               BNX2X_ERR("pci_enable_sriov failed with %d\n", rc);
-       else
-               DP(BNX2X_MSG_IOV, "sriov enabled\n");
+               return rc;
+       if (!mac_obj || !vlan_obj || !bulletin) {
+               BNX2X_ERR("VF partially initialized\n");
+               return -EINVAL;
+       }
+
+       ivi->vf = vfidx;
+       ivi->qos = 0;
+       ivi->tx_rate = 10000; /* always 10G. TBA take from link struct */
+       ivi->spoofchk = 1; /*always enabled */
+       if (vf->state == VF_ENABLED) {
+               /* mac and vlan are in vlan_mac objects */
+               mac_obj->get_n_elements(bp, mac_obj, 1, (u8 *)&ivi->mac,
+                                       0, ETH_ALEN);
+               vlan_obj->get_n_elements(bp, vlan_obj, 1, (u8 *)&ivi->vlan,
+                                        0, VLAN_HLEN);
+       } else {
+               /* mac */
+               if (bulletin->valid_bitmap & (1 << MAC_ADDR_VALID))
+                       /* mac configured by ndo so its in bulletin board */
+                       memcpy(&ivi->mac, bulletin->mac, ETH_ALEN);
+               else
+                       /* funtion has not been loaded yet. Show mac as 0s */
+                       memset(&ivi->mac, 0, ETH_ALEN);
+
+               /* vlan */
+               if (bulletin->valid_bitmap & (1 << VLAN_VALID))
+                       /* vlan configured by ndo so its in bulletin board */
+                       memcpy(&ivi->vlan, &bulletin->vlan, VLAN_HLEN);
+               else
+                       /* funtion has not been loaded yet. Show vlans as 0s */
+                       memset(&ivi->vlan, 0, VLAN_HLEN);
+       }
+
+       return 0;
 }
 
 /* New mac for VF. Consider these cases:
@@ -3044,23 +3171,19 @@ void bnx2x_enable_sriov(struct bnx2x *bp)
  * VF to configure any mac for itself except for this mac. In case of a race
  * where the VF fails to see the new post on its bulletin board before sending a
  * mac configuration request, the PF will simply fail the request and VF can try
- * again after consulting its bulletin board
+ * again after consulting its bulletin board.
  */
-int bnx2x_set_vf_mac(struct net_device *dev, int queue, u8 *mac)
+int bnx2x_set_vf_mac(struct net_device *dev, int vfidx, u8 *mac)
 {
        struct bnx2x *bp = netdev_priv(dev);
-       int rc, q_logical_state, vfidx = queue;
+       int rc, q_logical_state;
        struct bnx2x_virtf *vf = BP_VF(bp, vfidx);
        struct pf_vf_bulletin_content *bulletin = BP_VF_BULLETIN(bp, vfidx);
 
-       /* if SRIOV is disabled there is nothing to do (and somewhere, someone
-        * has erred).
-        */
-       if (!IS_SRIOV(bp)) {
-               BNX2X_ERR("bnx2x_set_vf_mac called though sriov is disabled\n");
-               return -EINVAL;
-       }
-
+       /* sanity */
+       rc = bnx2x_vf_ndo_sanity(bp, vfidx, vf);
+       if (rc)
+               return rc;
        if (!is_valid_ether_addr(mac)) {
                BNX2X_ERR("mac address invalid\n");
                return -EINVAL;
@@ -3085,7 +3208,7 @@ int bnx2x_set_vf_mac(struct net_device *dev, int queue, u8 *mac)
        if (vf->state == VF_ENABLED &&
            q_logical_state == BNX2X_Q_LOGICAL_STATE_ACTIVE) {
                /* configure the mac in device on this vf's queue */
-               unsigned long flags = 0;
+               unsigned long ramrod_flags = 0;
                struct bnx2x_vlan_mac_obj *mac_obj = &bnx2x_vfq(vf, 0, mac_obj);
 
                /* must lock vfpf channel to protect against vf flows */
@@ -3106,14 +3229,133 @@ int bnx2x_set_vf_mac(struct net_device *dev, int queue, u8 *mac)
                }
 
                /* configure the new mac to device */
-               __set_bit(RAMROD_COMP_WAIT, &flags);
+               __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
                bnx2x_set_mac_one(bp, (u8 *)&bulletin->mac, mac_obj, true,
-                                 BNX2X_ETH_MAC, &flags);
+                                 BNX2X_ETH_MAC, &ramrod_flags);
 
                bnx2x_unlock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_MAC);
        }
 
-       return rc;
+       return 0;
+}
+
+int bnx2x_set_vf_vlan(struct net_device *dev, int vfidx, u16 vlan, u8 qos)
+{
+       struct bnx2x *bp = netdev_priv(dev);
+       int rc, q_logical_state;
+       struct bnx2x_virtf *vf = BP_VF(bp, vfidx);
+       struct pf_vf_bulletin_content *bulletin = BP_VF_BULLETIN(bp, vfidx);
+
+       /* sanity */
+       rc = bnx2x_vf_ndo_sanity(bp, vfidx, vf);
+       if (rc)
+               return rc;
+
+       if (vlan > 4095) {
+               BNX2X_ERR("illegal vlan value %d\n", vlan);
+               return -EINVAL;
+       }
+
+       DP(BNX2X_MSG_IOV, "configuring VF %d with VLAN %d qos %d\n",
+          vfidx, vlan, 0);
+
+       /* update PF's copy of the VF's bulletin. No point in posting the vlan
+        * to the VF since it doesn't have anything to do with it. But it useful
+        * to store it here in case the VF is not up yet and we can only
+        * configure the vlan later when it does.
+        */
+       bulletin->valid_bitmap |= 1 << VLAN_VALID;
+       bulletin->vlan = vlan;
+
+       /* is vf initialized and queue set up? */
+       q_logical_state =
+               bnx2x_get_q_logical_state(bp, &bnx2x_vfq(vf, 0, sp_obj));
+       if (vf->state == VF_ENABLED &&
+           q_logical_state == BNX2X_Q_LOGICAL_STATE_ACTIVE) {
+               /* configure the vlan in device on this vf's queue */
+               unsigned long ramrod_flags = 0;
+               unsigned long vlan_mac_flags = 0;
+               struct bnx2x_vlan_mac_obj *vlan_obj =
+                       &bnx2x_vfq(vf, 0, vlan_obj);
+               struct bnx2x_vlan_mac_ramrod_params ramrod_param;
+               struct bnx2x_queue_state_params q_params = {NULL};
+               struct bnx2x_queue_update_params *update_params;
+
+               memset(&ramrod_param, 0, sizeof(ramrod_param));
+
+               /* must lock vfpf channel to protect against vf flows */
+               bnx2x_lock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_VLAN);
+
+               /* remove existing vlans */
+               __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
+               rc = vlan_obj->delete_all(bp, vlan_obj, &vlan_mac_flags,
+                                         &ramrod_flags);
+               if (rc) {
+                       BNX2X_ERR("failed to delete vlans\n");
+                       return -EINVAL;
+               }
+
+               /* send queue update ramrod to configure default vlan and silent
+                * vlan removal
+                */
+               __set_bit(RAMROD_COMP_WAIT, &q_params.ramrod_flags);
+               q_params.cmd = BNX2X_Q_CMD_UPDATE;
+               q_params.q_obj = &bnx2x_vfq(vf, 0, sp_obj);
+               update_params = &q_params.params.update;
+               __set_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN_CHNG,
+                         &update_params->update_flags);
+               __set_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM_CHNG,
+                         &update_params->update_flags);
+
+               if (vlan == 0) {
+                       /* if vlan is 0 then we want to leave the VF traffic
+                        * untagged, and leave the incoming traffic untouched
+                        * (i.e. do not remove any vlan tags).
+                        */
+                       __clear_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN,
+                                   &update_params->update_flags);
+                       __clear_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM,
+                                   &update_params->update_flags);
+               } else {
+                       /* configure the new vlan to device */
+                       __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
+                       ramrod_param.vlan_mac_obj = vlan_obj;
+                       ramrod_param.ramrod_flags = ramrod_flags;
+                       ramrod_param.user_req.u.vlan.vlan = vlan;
+                       ramrod_param.user_req.cmd = BNX2X_VLAN_MAC_ADD;
+                       rc = bnx2x_config_vlan_mac(bp, &ramrod_param);
+                       if (rc) {
+                               BNX2X_ERR("failed to configure vlan\n");
+                               return -EINVAL;
+                       }
+
+                       /* configure default vlan to vf queue and set silent
+                        * vlan removal (the vf remains unaware of this vlan).
+                        */
+                       update_params = &q_params.params.update;
+                       __set_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN,
+                                 &update_params->update_flags);
+                       __set_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM,
+                                 &update_params->update_flags);
+                       update_params->def_vlan = vlan;
+               }
+
+               /* Update the Queue state */
+               rc = bnx2x_queue_state_change(bp, &q_params);
+               if (rc) {
+                       BNX2X_ERR("Failed to configure default VLAN\n");
+                       return rc;
+               }
+
+               /* clear the flag indicating that this VF needs its vlan
+                * (will only be set if the HV configured th Vlan before vf was
+                * and we were called because the VF came up later
+                */
+               vf->cfg_flags &= ~VF_CFG_VLAN;
+
+               bnx2x_unlock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_VLAN);
+       }
+       return 0;
 }
 
 /* crc is the first field in the bulletin board. compute the crc over the
@@ -3165,20 +3407,26 @@ enum sample_bulletin_result bnx2x_sample_bulletin(struct bnx2x *bp)
                memcpy(bp->dev->dev_addr, bulletin.mac, ETH_ALEN);
        }
 
+       /* the vlan in bulletin board is valid and is new */
+       if (bulletin.valid_bitmap & 1 << VLAN_VALID)
+               memcpy(&bulletin.vlan, &bp->old_bulletin.vlan, VLAN_HLEN);
+
        /* copy new bulletin board to bp */
        bp->old_bulletin = bulletin;
 
        return PFVF_BULLETIN_UPDATED;
 }
 
-void bnx2x_vf_map_doorbells(struct bnx2x *bp)
+void __iomem *bnx2x_vf_doorbells(struct bnx2x *bp)
 {
        /* vf doorbells are embedded within the regview */
-       bp->doorbells = bp->regview + PXP_VF_ADDR_DB_START;
+       return bp->regview + PXP_VF_ADDR_DB_START;
 }
 
 int bnx2x_vf_pci_alloc(struct bnx2x *bp)
 {
+       mutex_init(&bp->vf2pf_mutex);
+
        /* allocate vf2pf mailbox for vf to pf channel */
        BNX2X_PCI_ALLOC(bp->vf2pf_mbox, &bp->vf2pf_mbox_mapping,
                        sizeof(struct bnx2x_vf_mbx_msg));
@@ -3196,3 +3444,26 @@ alloc_mem_err:
                       sizeof(union pf_vf_bulletin));
        return -ENOMEM;
 }
+
+int bnx2x_open_epilog(struct bnx2x *bp)
+{
+       /* Enable sriov via delayed work. This must be done via delayed work
+        * because it causes the probe of the vf devices to be run, which invoke
+        * register_netdevice which must have rtnl lock taken. As we are holding
+        * the lock right now, that could only work if the probe would not take
+        * the lock. However, as the probe of the vf may be called from other
+        * contexts as well (such as passthrough to vm failes) it can't assume
+        * the lock is being held for it. Using delayed work here allows the
+        * probe code to simply take the lock (i.e. wait for it to be released
+        * if it is being held). We only want to do this if the number of VFs
+        * was set before PF driver was loaded.
+        */
+       if (IS_SRIOV(bp) && BNX2X_NR_VIRTFN(bp)) {
+               smp_mb__before_clear_bit();
+               set_bit(BNX2X_SP_RTNL_ENABLE_SRIOV, &bp->sp_rtnl_state);
+               smp_mb__after_clear_bit();
+               schedule_delayed_work(&bp->sp_rtnl_task, 0);
+       }
+
+       return 0;
+}