]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
net: propagate tc filter chain index down the ndo_setup_tc call
[mirror_ubuntu-bionic-kernel.git] / drivers / net / ethernet / chelsio / cxgb4 / cxgb4_main.c
index 38a5c6764bb50f45124c212db37e11d2cc777076..ff8bcf56bf3f3647ca4a92fd7839da520cf42321 100644 (file)
@@ -891,7 +891,7 @@ static u16 cxgb_select_queue(struct net_device *dev, struct sk_buff *skb,
         * The skb's priority is determined via the VLAN Tag Priority Code
         * Point field.
         */
-       if (cxgb4_dcb_enabled(dev)) {
+       if (cxgb4_dcb_enabled(dev) && !is_kdump_kernel()) {
                u16 vlan_tci;
                int err;
 
@@ -1093,10 +1093,12 @@ int cxgb4_alloc_stid(struct tid_info *t, int family, void *data)
                 * This is equivalent to 4 TIDs. With CLIP enabled it
                 * needs 2 TIDs.
                 */
-               if (family == PF_INET)
-                       t->stids_in_use++;
-               else
+               if (family == PF_INET6) {
                        t->stids_in_use += 2;
+                       t->v6_stids_in_use += 2;
+               } else {
+                       t->stids_in_use++;
+               }
        }
        spin_unlock_bh(&t->stid_lock);
        return stid;
@@ -1150,13 +1152,16 @@ void cxgb4_free_stid(struct tid_info *t, unsigned int stid, int family)
                bitmap_release_region(t->stid_bmap, stid, 1);
        t->stid_tab[stid].data = NULL;
        if (stid < t->nstids) {
-               if (family == PF_INET)
-                       t->stids_in_use--;
-               else
+               if (family == PF_INET6) {
                        t->stids_in_use -= 2;
+                       t->v6_stids_in_use -= 2;
+               } else {
+                       t->stids_in_use--;
+               }
        } else {
                t->sftids_in_use--;
        }
+
        spin_unlock_bh(&t->stid_lock);
 }
 EXPORT_SYMBOL(cxgb4_free_stid);
@@ -1232,7 +1237,8 @@ static void process_tid_release_list(struct work_struct *work)
  * Release a TID and inform HW.  If we are unable to allocate the release
  * message we defer to a work queue.
  */
-void cxgb4_remove_tid(struct tid_info *t, unsigned int chan, unsigned int tid)
+void cxgb4_remove_tid(struct tid_info *t, unsigned int chan, unsigned int tid,
+                     unsigned short family)
 {
        struct sk_buff *skb;
        struct adapter *adap = container_of(t, struct adapter, tids);
@@ -1241,10 +1247,18 @@ void cxgb4_remove_tid(struct tid_info *t, unsigned int chan, unsigned int tid)
 
        if (t->tid_tab[tid]) {
                t->tid_tab[tid] = NULL;
-               if (t->hash_base && (tid >= t->hash_base))
-                       atomic_dec(&t->hash_tids_in_use);
-               else
-                       atomic_dec(&t->tids_in_use);
+               atomic_dec(&t->conns_in_use);
+               if (t->hash_base && (tid >= t->hash_base)) {
+                       if (family == AF_INET6)
+                               atomic_sub(2, &t->hash_tids_in_use);
+                       else
+                               atomic_dec(&t->hash_tids_in_use);
+               } else {
+                       if (family == AF_INET6)
+                               atomic_sub(2, &t->tids_in_use);
+                       else
+                               atomic_dec(&t->tids_in_use);
+               }
        }
 
        skb = alloc_skb(sizeof(struct cpl_tid_release), GFP_ATOMIC);
@@ -1292,10 +1306,12 @@ static int tid_init(struct tid_info *t)
        spin_lock_init(&t->ftid_lock);
 
        t->stids_in_use = 0;
+       t->v6_stids_in_use = 0;
        t->sftids_in_use = 0;
        t->afree = NULL;
        t->atids_in_use = 0;
        atomic_set(&t->tids_in_use, 0);
+       atomic_set(&t->conns_in_use, 0);
        atomic_set(&t->hash_tids_in_use, 0);
 
        /* Setup the free list for atid_tab and clear the stid bitmap. */
@@ -2196,10 +2212,14 @@ static int cxgb_up(struct adapter *adap)
                if (err)
                        goto irq_err;
        }
+
+       mutex_lock(&uld_mutex);
        enable_rx(adap);
        t4_sge_start(adap);
        t4_intr_enable(adap);
        adap->flags |= FULL_INIT_DONE;
+       mutex_unlock(&uld_mutex);
+
        notify_ulds(adap, CXGB4_STATE_UP);
 #if IS_ENABLED(CONFIG_IPV6)
        update_clip(adap);
@@ -2245,6 +2265,13 @@ static int cxgb_open(struct net_device *dev)
                        return err;
        }
 
+       /* It's possible that the basic port information could have
+        * changed since we first read it.
+        */
+       err = t4_update_port_info(pi);
+       if (err < 0)
+               return err;
+
        err = link_start(dev);
        if (!err)
                netif_tx_start_all_queues(dev);
@@ -2556,6 +2583,8 @@ static int cxgb_get_vf_config(struct net_device *dev,
        if (vf >= adap->num_vfs)
                return -EINVAL;
        ivi->vf = vf;
+       ivi->max_tx_rate = adap->vfinfo[vf].tx_rate;
+       ivi->min_tx_rate = 0;
        ether_addr_copy(ivi->mac, adap->vfinfo[vf].vf_mac_addr);
        return 0;
 }
@@ -2572,6 +2601,109 @@ static int cxgb_get_phys_port_id(struct net_device *dev,
        return 0;
 }
 
+static int cxgb_set_vf_rate(struct net_device *dev, int vf, int min_tx_rate,
+                           int max_tx_rate)
+{
+       struct port_info *pi = netdev_priv(dev);
+       struct adapter *adap = pi->adapter;
+       struct fw_port_cmd port_cmd, port_rpl;
+       u32 link_status, speed = 0;
+       u32 fw_pfvf, fw_class;
+       int class_id = vf;
+       int link_ok, ret;
+       u16 pktsize;
+
+       if (vf >= adap->num_vfs)
+               return -EINVAL;
+
+       if (min_tx_rate) {
+               dev_err(adap->pdev_dev,
+                       "Min tx rate (%d) (> 0) for VF %d is Invalid.\n",
+                       min_tx_rate, vf);
+               return -EINVAL;
+       }
+       /* Retrieve link details for VF port */
+       memset(&port_cmd, 0, sizeof(port_cmd));
+       port_cmd.op_to_portid = cpu_to_be32(FW_CMD_OP_V(FW_PORT_CMD) |
+                                           FW_CMD_REQUEST_F |
+                                           FW_CMD_READ_F |
+                                           FW_PORT_CMD_PORTID_V(pi->port_id));
+       port_cmd.action_to_len16 =
+               cpu_to_be32(FW_PORT_CMD_ACTION_V(FW_PORT_ACTION_GET_PORT_INFO) |
+                           FW_LEN16(port_cmd));
+       ret = t4_wr_mbox(adap, adap->mbox, &port_cmd, sizeof(port_cmd),
+                        &port_rpl);
+       if (ret != FW_SUCCESS) {
+               dev_err(adap->pdev_dev,
+                       "Failed to get link status for VF %d\n", vf);
+               return -EINVAL;
+       }
+       link_status = be32_to_cpu(port_rpl.u.info.lstatus_to_modtype);
+       link_ok = (link_status & FW_PORT_CMD_LSTATUS_F) != 0;
+       if (!link_ok) {
+               dev_err(adap->pdev_dev, "Link down for VF %d\n", vf);
+               return -EINVAL;
+       }
+       /* Determine link speed */
+       if (link_status & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_100M))
+               speed = 100;
+       else if (link_status & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_1G))
+               speed = 1000;
+       else if (link_status & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_10G))
+               speed = 10000;
+       else if (link_status & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_25G))
+               speed = 25000;
+       else if (link_status & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_40G))
+               speed = 40000;
+       else if (link_status & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_100G))
+               speed = 100000;
+
+       if (max_tx_rate > speed) {
+               dev_err(adap->pdev_dev,
+                       "Max tx rate %d for VF %d can't be > link-speed %u",
+                       max_tx_rate, vf, speed);
+               return -EINVAL;
+       }
+       pktsize = be16_to_cpu(port_rpl.u.info.mtu);
+       /* subtract ethhdr size and 4 bytes crc since, f/w appends it */
+       pktsize = pktsize - sizeof(struct ethhdr) - 4;
+       /* subtract ipv4 hdr size, tcp hdr size to get typical IPv4 MSS size */
+       pktsize = pktsize - sizeof(struct iphdr) - sizeof(struct tcphdr);
+       /* configure Traffic Class for rate-limiting */
+       ret = t4_sched_params(adap, SCHED_CLASS_TYPE_PACKET,
+                             SCHED_CLASS_LEVEL_CL_RL,
+                             SCHED_CLASS_MODE_CLASS,
+                             SCHED_CLASS_RATEUNIT_BITS,
+                             SCHED_CLASS_RATEMODE_ABS,
+                             pi->port_id, class_id, 0,
+                             max_tx_rate * 1000, 0, pktsize);
+       if (ret) {
+               dev_err(adap->pdev_dev, "Err %d for Traffic Class config\n",
+                       ret);
+               return -EINVAL;
+       }
+       dev_info(adap->pdev_dev,
+                "Class %d with MSS %u configured with rate %u\n",
+                class_id, pktsize, max_tx_rate);
+
+       /* bind VF to configured Traffic Class */
+       fw_pfvf = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_PFVF) |
+                  FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_PFVF_SCHEDCLASS_ETH));
+       fw_class = class_id;
+       ret = t4_set_params(adap, adap->mbox, adap->pf, vf + 1, 1, &fw_pfvf,
+                           &fw_class);
+       if (ret) {
+               dev_err(adap->pdev_dev,
+                       "Err %d in binding VF %d to Traffic Class %d\n",
+                       ret, vf, class_id);
+               return -EINVAL;
+       }
+       dev_info(adap->pdev_dev, "PF %d VF %d is bound to Class %d\n",
+                adap->pf, vf, class_id);
+       adap->vfinfo[vf].tx_rate = max_tx_rate;
+       return 0;
+}
+
 #endif
 
 static int cxgb_set_mac_addr(struct net_device *dev, void *p)
@@ -2691,12 +2823,15 @@ static int cxgb_set_tx_maxrate(struct net_device *dev, int index, u32 rate)
        return err;
 }
 
-static int cxgb_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
-                        struct tc_to_netdev *tc)
+static int cxgb_setup_tc(struct net_device *dev, u32 handle, u32 chain_index,
+                        __be16 proto, struct tc_to_netdev *tc)
 {
        struct port_info *pi = netdev2pinfo(dev);
        struct adapter *adap = netdev2adap(dev);
 
+       if (chain_index)
+               return -EOPNOTSUPP;
+
        if (!(adap->flags & FULL_INIT_DONE)) {
                dev_err(adap->pdev_dev,
                        "Failed to setup tc on port %d. Link Down?\n",
@@ -2720,6 +2855,16 @@ static int cxgb_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
        return -EOPNOTSUPP;
 }
 
+static netdev_features_t cxgb_fix_features(struct net_device *dev,
+                                          netdev_features_t features)
+{
+       /* Disable GRO, if RX_CSUM is disabled */
+       if (!(features & NETIF_F_RXCSUM))
+               features &= ~NETIF_F_GRO;
+
+       return features;
+}
+
 static const struct net_device_ops cxgb4_netdev_ops = {
        .ndo_open             = cxgb_open,
        .ndo_stop             = cxgb_close,
@@ -2741,6 +2886,7 @@ static const struct net_device_ops cxgb4_netdev_ops = {
 #endif /* CONFIG_CHELSIO_T4_FCOE */
        .ndo_set_tx_maxrate   = cxgb_set_tx_maxrate,
        .ndo_setup_tc         = cxgb_setup_tc,
+       .ndo_fix_features     = cxgb_fix_features,
 };
 
 #ifdef CONFIG_PCI_IOV
@@ -2748,6 +2894,7 @@ static const struct net_device_ops cxgb4_mgmt_netdev_ops = {
        .ndo_open             = dummy_open,
        .ndo_set_vf_mac       = cxgb_set_vf_mac,
        .ndo_get_vf_config    = cxgb_get_vf_config,
+       .ndo_set_vf_rate      = cxgb_set_vf_rate,
        .ndo_get_phys_port_id = cxgb_get_phys_port_id,
 };
 #endif
@@ -2771,6 +2918,9 @@ void t4_fatal_err(struct adapter *adap)
 {
        int port;
 
+       if (pci_channel_offline(adap->pdev))
+               return;
+
        /* Disable the SGE since ULDs are going to free resources that
         * could be exposed to the adapter.  RDMA MWs for example...
         */
@@ -3882,9 +4032,10 @@ static pci_ers_result_t eeh_err_detected(struct pci_dev *pdev,
        spin_lock(&adap->stats_lock);
        for_each_port(adap, i) {
                struct net_device *dev = adap->port[i];
-
-               netif_device_detach(dev);
-               netif_carrier_off(dev);
+               if (dev) {
+                       netif_device_detach(dev);
+                       netif_carrier_off(dev);
+               }
        }
        spin_unlock(&adap->stats_lock);
        disable_interrupts(adap);
@@ -3963,12 +4114,13 @@ static void eeh_resume(struct pci_dev *pdev)
        rtnl_lock();
        for_each_port(adap, i) {
                struct net_device *dev = adap->port[i];
-
-               if (netif_running(dev)) {
-                       link_start(dev);
-                       cxgb_set_rxmode(dev);
+               if (dev) {
+                       if (netif_running(dev)) {
+                               link_start(dev);
+                               cxgb_set_rxmode(dev);
+                       }
+                       netif_device_attach(dev);
                }
-               netif_device_attach(dev);
        }
        rtnl_unlock();
 }
@@ -4007,10 +4159,7 @@ static void cfg_queues(struct adapter *adap)
 
        /* Reduce memory usage in kdump environment, disable all offload.
         */
-       if (is_kdump_kernel()) {
-               adap->params.offload = 0;
-               adap->params.crypto = 0;
-       } else if (is_uld(adap) && t4_uld_mem_alloc(adap)) {
+       if (is_kdump_kernel() || (is_uld(adap) && t4_uld_mem_alloc(adap))) {
                adap->params.offload = 0;
                adap->params.crypto = 0;
        }
@@ -4031,7 +4180,7 @@ static void cfg_queues(struct adapter *adap)
                struct port_info *pi = adap2pinfo(adap, i);
 
                pi->first_qset = qidx;
-               pi->nqsets = 8;
+               pi->nqsets = is_kdump_kernel() ? 1 : 8;
                qidx += pi->nqsets;
        }
 #else /* !CONFIG_CHELSIO_T4_DCB */
@@ -4044,6 +4193,9 @@ static void cfg_queues(struct adapter *adap)
        if (q10g > netif_get_num_default_rss_queues())
                q10g = netif_get_num_default_rss_queues();
 
+       if (is_kdump_kernel())
+               q10g = 1;
+
        for_each_port(adap, i) {
                struct port_info *pi = adap2pinfo(adap, i);
 
@@ -4949,6 +5101,8 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                netif_set_real_num_tx_queues(adapter->port[i], pi->nqsets);
                netif_set_real_num_rx_queues(adapter->port[i], pi->nqsets);
 
+               netif_carrier_off(adapter->port[i]);
+
                err = register_netdev(adapter->port[i]);
                if (err)
                        break;