Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dledford/rdma
[linux-2.6-block.git] / drivers / net / ethernet / intel / i40e / i40e_main.c
index 70d9605a0d9e712f1bb89a38da053c8b07ee9a83..67006431726aa03c41f38c5e54bf9009e3bf9aa2 100644 (file)
@@ -289,7 +289,7 @@ struct i40e_vsi *i40e_find_vsi_from_id(struct i40e_pf *pf, u16 id)
  *
  * If not already scheduled, this puts the task into the work queue
  **/
-static void i40e_service_event_schedule(struct i40e_pf *pf)
+void i40e_service_event_schedule(struct i40e_pf *pf)
 {
        if (!test_bit(__I40E_DOWN, &pf->state) &&
            !test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state) &&
@@ -2230,7 +2230,7 @@ static int i40e_change_mtu(struct net_device *netdev, int new_mtu)
        netdev->mtu = new_mtu;
        if (netif_running(netdev))
                i40e_vsi_reinit_locked(vsi);
-
+       i40e_notify_client_of_l2_param_changes(vsi);
        return 0;
 }
 
@@ -4169,6 +4169,9 @@ static void i40e_clear_interrupt_scheme(struct i40e_pf *pf)
                free_irq(pf->msix_entries[0].vector, pf);
        }
 
+       i40e_put_lump(pf->irq_pile, pf->iwarp_base_vector,
+                     I40E_IWARP_IRQ_PILE_ID);
+
        i40e_put_lump(pf->irq_pile, 0, I40E_PILE_VALID_BIT-1);
        for (i = 0; i < pf->num_alloc_vsi; i++)
                if (pf->vsi[i])
@@ -4212,12 +4215,17 @@ static void i40e_napi_disable_all(struct i40e_vsi *vsi)
  **/
 static void i40e_vsi_close(struct i40e_vsi *vsi)
 {
+       bool reset = false;
+
        if (!test_and_set_bit(__I40E_DOWN, &vsi->state))
                i40e_down(vsi);
        i40e_vsi_free_irq(vsi);
        i40e_vsi_free_tx_resources(vsi);
        i40e_vsi_free_rx_resources(vsi);
        vsi->current_netdev_flags = 0;
+       if (test_bit(__I40E_RESET_RECOVERY_PENDING, &vsi->back->state))
+               reset = true;
+       i40e_notify_client_of_netdev_close(vsi, reset);
 }
 
 /**
@@ -4850,6 +4858,12 @@ static int i40e_vsi_config_tc(struct i40e_vsi *vsi, u8 enabled_tc)
        ctxt.info = vsi->info;
        i40e_vsi_setup_queue_map(vsi, &ctxt, enabled_tc, false);
 
+       if (vsi->back->flags & I40E_FLAG_IWARP_ENABLED) {
+               ctxt.info.valid_sections |=
+                               cpu_to_le16(I40E_AQ_VSI_PROP_QUEUE_OPT_VALID);
+               ctxt.info.queueing_opt_flags |= I40E_AQ_VSI_QUE_OPT_TCP_ENA;
+       }
+
        /* Update the VSI after updating the VSI queue-mapping information */
        ret = i40e_aq_update_vsi_params(&vsi->back->hw, &ctxt, NULL);
        if (ret) {
@@ -4993,6 +5007,7 @@ static void i40e_dcb_reconfigure(struct i40e_pf *pf)
                        if (pf->vsi[v]->netdev)
                                i40e_dcbnl_set_all(pf->vsi[v]);
                }
+               i40e_notify_client_of_l2_param_changes(pf->vsi[v]);
        }
 }
 
@@ -5191,6 +5206,11 @@ static int i40e_up_complete(struct i40e_vsi *vsi)
                }
                i40e_fdir_filter_restore(vsi);
        }
+
+       /* On the next run of the service_task, notify any clients of the new
+        * opened netdev
+        */
+       pf->flags |= I40E_FLAG_SERVICE_CLIENT_REQUESTED;
        i40e_service_event_schedule(pf);
 
        return 0;
@@ -5379,6 +5399,8 @@ int i40e_open(struct net_device *netdev)
                geneve_get_rx_port(netdev);
 #endif
 
+       i40e_notify_client_of_netdev_open(vsi);
+
        return 0;
 }
 
@@ -6043,6 +6065,7 @@ static void i40e_vsi_link_event(struct i40e_vsi *vsi, bool link_up)
        case I40E_VSI_SRIOV:
        case I40E_VSI_VMDQ2:
        case I40E_VSI_CTRL:
+       case I40E_VSI_IWARP:
        case I40E_VSI_MIRROR:
        default:
                /* there is no notification for other VSIs */
@@ -7148,6 +7171,7 @@ static void i40e_service_task(struct work_struct *work)
        i40e_vc_process_vflr_event(pf);
        i40e_watchdog_subtask(pf);
        i40e_fdir_reinit_subtask(pf);
+       i40e_client_subtask(pf);
        i40e_sync_filters_subtask(pf);
        i40e_sync_udp_filters_subtask(pf);
        i40e_clean_adminq_subtask(pf);
@@ -7550,6 +7574,7 @@ static int i40e_init_msix(struct i40e_pf *pf)
        int vectors_left;
        int v_budget, i;
        int v_actual;
+       int iwarp_requested = 0;
 
        if (!(pf->flags & I40E_FLAG_MSIX_ENABLED))
                return -ENODEV;
@@ -7563,6 +7588,7 @@ static int i40e_init_msix(struct i40e_pf *pf)
         *              is governed by number of cpus in the system.
         *      - assumes symmetric Tx/Rx pairing
         *   - The number of VMDq pairs
+        *   - The CPU count within the NUMA node if iWARP is enabled
 #ifdef I40E_FCOE
         *   - The number of FCOE qps.
 #endif
@@ -7609,6 +7635,16 @@ static int i40e_init_msix(struct i40e_pf *pf)
        }
 
 #endif
+       /* can we reserve enough for iWARP? */
+       if (pf->flags & I40E_FLAG_IWARP_ENABLED) {
+               if (!vectors_left)
+                       pf->num_iwarp_msix = 0;
+               else if (vectors_left < pf->num_iwarp_msix)
+                       pf->num_iwarp_msix = 1;
+               v_budget += pf->num_iwarp_msix;
+               vectors_left -= pf->num_iwarp_msix;
+       }
+
        /* any vectors left over go for VMDq support */
        if (pf->flags & I40E_FLAG_VMDQ_ENABLED) {
                int vmdq_vecs_wanted = pf->num_vmdq_vsis * pf->num_vmdq_qps;
@@ -7643,6 +7679,8 @@ static int i40e_init_msix(struct i40e_pf *pf)
                 * of these features based on the policy and at the end disable
                 * the features that did not get any vectors.
                 */
+               iwarp_requested = pf->num_iwarp_msix;
+               pf->num_iwarp_msix = 0;
 #ifdef I40E_FCOE
                pf->num_fcoe_qps = 0;
                pf->num_fcoe_msix = 0;
@@ -7681,17 +7719,33 @@ static int i40e_init_msix(struct i40e_pf *pf)
                        pf->num_lan_msix = 1;
                        break;
                case 3:
+                       if (pf->flags & I40E_FLAG_IWARP_ENABLED) {
+                               pf->num_lan_msix = 1;
+                               pf->num_iwarp_msix = 1;
+                       } else {
+                               pf->num_lan_msix = 2;
+                       }
 #ifdef I40E_FCOE
                        /* give one vector to FCoE */
                        if (pf->flags & I40E_FLAG_FCOE_ENABLED) {
                                pf->num_lan_msix = 1;
                                pf->num_fcoe_msix = 1;
                        }
-#else
-                       pf->num_lan_msix = 2;
 #endif
                        break;
                default:
+                       if (pf->flags & I40E_FLAG_IWARP_ENABLED) {
+                               pf->num_iwarp_msix = min_t(int, (vec / 3),
+                                                iwarp_requested);
+                               pf->num_vmdq_vsis = min_t(int, (vec / 3),
+                                                 I40E_DEFAULT_NUM_VMDQ_VSI);
+                       } else {
+                               pf->num_vmdq_vsis = min_t(int, (vec / 2),
+                                                 I40E_DEFAULT_NUM_VMDQ_VSI);
+                       }
+                       pf->num_lan_msix = min_t(int,
+                              (vec - (pf->num_iwarp_msix + pf->num_vmdq_vsis)),
+                                                             pf->num_lan_msix);
 #ifdef I40E_FCOE
                        /* give one vector to FCoE */
                        if (pf->flags & I40E_FLAG_FCOE_ENABLED) {
@@ -7699,8 +7753,6 @@ static int i40e_init_msix(struct i40e_pf *pf)
                                vec--;
                        }
 #endif
-                       /* give the rest to the PF */
-                       pf->num_lan_msix = min_t(int, vec, pf->num_lan_qps);
                        break;
                }
        }
@@ -7710,6 +7762,12 @@ static int i40e_init_msix(struct i40e_pf *pf)
                dev_info(&pf->pdev->dev, "VMDq disabled, not enough MSI-X vectors\n");
                pf->flags &= ~I40E_FLAG_VMDQ_ENABLED;
        }
+
+       if ((pf->flags & I40E_FLAG_IWARP_ENABLED) &&
+           (pf->num_iwarp_msix == 0)) {
+               dev_info(&pf->pdev->dev, "IWARP disabled, not enough MSI-X vectors\n");
+               pf->flags &= ~I40E_FLAG_IWARP_ENABLED;
+       }
 #ifdef I40E_FCOE
 
        if ((pf->flags & I40E_FLAG_FCOE_ENABLED) && (pf->num_fcoe_msix == 0)) {
@@ -7801,6 +7859,7 @@ static int i40e_init_interrupt_scheme(struct i40e_pf *pf)
                vectors = i40e_init_msix(pf);
                if (vectors < 0) {
                        pf->flags &= ~(I40E_FLAG_MSIX_ENABLED   |
+                                      I40E_FLAG_IWARP_ENABLED  |
 #ifdef I40E_FCOE
                                       I40E_FLAG_FCOE_ENABLED   |
 #endif
@@ -8474,6 +8533,12 @@ static int i40e_sw_init(struct i40e_pf *pf)
                pf->num_vmdq_qps = i40e_default_queues_per_vmdq(pf);
        }
 
+       if (pf->hw.func_caps.iwarp) {
+               pf->flags |= I40E_FLAG_IWARP_ENABLED;
+               /* IWARP needs one extra vector for CQP just like MISC.*/
+               pf->num_iwarp_msix = (int)num_online_cpus() + 1;
+       }
+
 #ifdef I40E_FCOE
        i40e_init_pf_fcoe(pf);
 
@@ -9328,6 +9393,13 @@ static int i40e_add_vsi(struct i40e_vsi *vsi)
                                cpu_to_le16(I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB);
                }
 
+               if (vsi->back->flags & I40E_FLAG_IWARP_ENABLED) {
+                       ctxt.info.valid_sections |=
+                               cpu_to_le16(I40E_AQ_VSI_PROP_QUEUE_OPT_VALID);
+                       ctxt.info.queueing_opt_flags |=
+                                               I40E_AQ_VSI_QUE_OPT_TCP_ENA;
+               }
+
                ctxt.info.valid_sections |= cpu_to_le16(I40E_AQ_VSI_PROP_VLAN_VALID);
                ctxt.info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_MODE_ALL;
                if (pf->vf[vsi->vf_id].spoofchk) {
@@ -9351,6 +9423,10 @@ static int i40e_add_vsi(struct i40e_vsi *vsi)
                break;
 
 #endif /* I40E_FCOE */
+       case I40E_VSI_IWARP:
+               /* send down message to iWARP */
+               break;
+
        default:
                return -ENODEV;
        }
@@ -10467,6 +10543,7 @@ static void i40e_determine_queue_usage(struct i40e_pf *pf)
 
                /* make sure all the fancies are disabled */
                pf->flags &= ~(I40E_FLAG_RSS_ENABLED    |
+                              I40E_FLAG_IWARP_ENABLED  |
 #ifdef I40E_FCOE
                               I40E_FLAG_FCOE_ENABLED   |
 #endif
@@ -10484,6 +10561,7 @@ static void i40e_determine_queue_usage(struct i40e_pf *pf)
                queues_left -= pf->num_lan_qps;
 
                pf->flags &= ~(I40E_FLAG_RSS_ENABLED    |
+                              I40E_FLAG_IWARP_ENABLED  |
 #ifdef I40E_FCOE
                               I40E_FLAG_FCOE_ENABLED   |
 #endif
@@ -11059,7 +11137,17 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        }
 #endif /* CONFIG_PCI_IOV */
 
-       pfs_found++;
+       if (pf->flags & I40E_FLAG_IWARP_ENABLED) {
+               pf->iwarp_base_vector = i40e_get_lump(pf, pf->irq_pile,
+                                                     pf->num_iwarp_msix,
+                                                     I40E_IWARP_IRQ_PILE_ID);
+               if (pf->iwarp_base_vector < 0) {
+                       dev_info(&pdev->dev,
+                                "failed to get tracking for %d vectors for IWARP err=%d\n",
+                                pf->num_iwarp_msix, pf->iwarp_base_vector);
+                       pf->flags &= ~I40E_FLAG_IWARP_ENABLED;
+               }
+       }
 
        i40e_dbg_pf_init(pf);
 
@@ -11070,6 +11158,12 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        mod_timer(&pf->service_timer,
                  round_jiffies(jiffies + pf->service_timer_period));
 
+       /* add this PF to client device list and launch a client service task */
+       err = i40e_lan_add_device(pf);
+       if (err)
+               dev_info(&pdev->dev, "Failed to add PF to client API service list: %d\n",
+                        err);
+
 #ifdef I40E_FCOE
        /* create FCoE interface */
        i40e_fcoe_vsi_setup(pf);
@@ -11245,6 +11339,13 @@ static void i40e_remove(struct pci_dev *pdev)
        if (pf->vsi[pf->lan_vsi])
                i40e_vsi_release(pf->vsi[pf->lan_vsi]);
 
+       /* remove attached clients */
+       ret_code = i40e_lan_del_device(pf);
+       if (ret_code) {
+               dev_warn(&pdev->dev, "Failed to delete client device: %d\n",
+                        ret_code);
+       }
+
        /* shutdown and destroy the HMC */
        if (hw->hmc.hmc_obj) {
                ret_code = i40e_shutdown_lan_hmc(hw);