ionic: remove support for mgmt device
[linux-2.6-microblaze.git] / drivers / net / ethernet / pensando / ionic / ionic_lif.c
index f8a9c1b..9d8c969 100644 (file)
 #include "ionic_ethtool.h"
 #include "ionic_debugfs.h"
 
+/* queuetype support level */
+static const u8 ionic_qtype_versions[IONIC_QTYPE_MAX] = {
+       [IONIC_QTYPE_ADMINQ]  = 0,   /* 0 = Base version with CQ support */
+       [IONIC_QTYPE_NOTIFYQ] = 0,   /* 0 = Base version */
+       [IONIC_QTYPE_RXQ]     = 0,   /* 0 = Base version with CQ+SG support */
+       [IONIC_QTYPE_TXQ]     = 1,   /* 0 = Base version with CQ+SG support
+                                     * 1 =   ... with Tx SG version 1
+                                     */
+};
+
 static void ionic_lif_rx_mode(struct ionic_lif *lif, unsigned int rx_mode);
 static int ionic_lif_addr_add(struct ionic_lif *lif, const u8 *addr);
 static int ionic_lif_addr_del(struct ionic_lif *lif, const u8 *addr);
@@ -27,6 +37,7 @@ static void ionic_lif_set_netdev_info(struct ionic_lif *lif);
 
 static int ionic_start_queues(struct ionic_lif *lif);
 static void ionic_stop_queues(struct ionic_lif *lif);
+static void ionic_lif_queue_identify(struct ionic_lif *lif);
 
 static void ionic_lif_deferred_work(struct work_struct *work)
 {
@@ -88,9 +99,6 @@ static void ionic_link_status_check(struct ionic_lif *lif)
        if (!test_bit(IONIC_LIF_F_LINK_CHECK_REQUESTED, lif->state))
                return;
 
-       if (lif->ionic->is_mgmt_nic)
-               return;
-
        link_status = le16_to_cpu(lif->info->status.link_status);
        link_up = link_status == IONIC_PORT_OPER_STATUS_UP;
 
@@ -105,7 +113,7 @@ static void ionic_link_status_check(struct ionic_lif *lif)
                        netif_carrier_on(netdev);
                }
 
-               if (netif_running(lif->netdev))
+               if (lif->netdev->flags & IFF_UP && netif_running(lif->netdev))
                        ionic_start_queues(lif);
        } else {
                if (netif_carrier_ok(netdev)) {
@@ -113,7 +121,7 @@ static void ionic_link_status_check(struct ionic_lif *lif)
                        netif_carrier_off(netdev);
                }
 
-               if (netif_running(lif->netdev))
+               if (lif->netdev->flags & IFF_UP && netif_running(lif->netdev))
                        ionic_stop_queues(lif);
        }
 
@@ -186,10 +194,10 @@ static int ionic_intr_alloc(struct ionic_lif *lif, struct ionic_intr_info *intr)
        return 0;
 }
 
-static void ionic_intr_free(struct ionic_lif *lif, int index)
+static void ionic_intr_free(struct ionic *ionic, int index)
 {
-       if (index != INTR_INDEX_NOT_ASSIGNED && index < lif->ionic->nintrs)
-               clear_bit(index, lif->ionic->intrs);
+       if (index != IONIC_INTR_INDEX_NOT_ASSIGNED && index < ionic->nintrs)
+               clear_bit(index, ionic->intrs);
 }
 
 static int ionic_qcq_enable(struct ionic_qcq *qcq)
@@ -299,7 +307,7 @@ static void ionic_qcq_free(struct ionic_lif *lif, struct ionic_qcq *qcq)
                irq_set_affinity_hint(qcq->intr.vector, NULL);
                devm_free_irq(dev, qcq->intr.vector, &qcq->napi);
                qcq->intr.vector = 0;
-               ionic_intr_free(lif, qcq->intr.index);
+               ionic_intr_free(lif->ionic, qcq->intr.index);
        }
 
        devm_kfree(dev, qcq->cq.info);
@@ -345,7 +353,7 @@ static void ionic_link_qcq_interrupts(struct ionic_qcq *src_qcq,
                                      struct ionic_qcq *n_qcq)
 {
        if (WARN_ON(n_qcq->flags & IONIC_QCQ_F_INTR)) {
-               ionic_intr_free(n_qcq->cq.lif, n_qcq->intr.index);
+               ionic_intr_free(n_qcq->cq.lif->ionic, n_qcq->intr.index);
                n_qcq->flags &= ~IONIC_QCQ_F_INTR;
        }
 
@@ -444,7 +452,7 @@ static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type,
                        cpumask_set_cpu(new->intr.cpu,
                                        &new->intr.affinity_mask);
        } else {
-               new->intr.index = INTR_INDEX_NOT_ASSIGNED;
+               new->intr.index = IONIC_INTR_INDEX_NOT_ASSIGNED;
        }
 
        new->cq.info = devm_kzalloc(dev, sizeof(*new->cq.info) * num_descs,
@@ -497,7 +505,7 @@ err_out_free_irq:
                devm_free_irq(dev, new->intr.vector, &new->napi);
 err_out_free_intr:
        if (flags & IONIC_QCQ_F_INTR)
-               ionic_intr_free(lif, new->intr.index);
+               ionic_intr_free(lif->ionic, new->intr.index);
 err_out:
        dev_err(dev, "qcq alloc of %s%d failed %d\n", name, index, err);
        return err;
@@ -597,6 +605,7 @@ static int ionic_lif_txq_init(struct ionic_lif *lif, struct ionic_qcq *qcq)
                        .opcode = IONIC_CMD_Q_INIT,
                        .lif_index = cpu_to_le16(lif->index),
                        .type = q->type,
+                       .ver = lif->qtype_info[q->type].version,
                        .index = cpu_to_le32(q->index),
                        .flags = cpu_to_le16(IONIC_QINIT_F_IRQ |
                                             IONIC_QINIT_F_SG),
@@ -614,6 +623,8 @@ static int ionic_lif_txq_init(struct ionic_lif *lif, struct ionic_qcq *qcq)
        dev_dbg(dev, "txq_init.index %d\n", ctx.cmd.q_init.index);
        dev_dbg(dev, "txq_init.ring_base 0x%llx\n", ctx.cmd.q_init.ring_base);
        dev_dbg(dev, "txq_init.ring_size %d\n", ctx.cmd.q_init.ring_size);
+       dev_dbg(dev, "txq_init.flags 0x%x\n", ctx.cmd.q_init.flags);
+       dev_dbg(dev, "txq_init.ver %d\n", ctx.cmd.q_init.ver);
 
        q->tail = q->info;
        q->head = q->tail;
@@ -646,6 +657,7 @@ static int ionic_lif_rxq_init(struct ionic_lif *lif, struct ionic_qcq *qcq)
                        .opcode = IONIC_CMD_Q_INIT,
                        .lif_index = cpu_to_le16(lif->index),
                        .type = q->type,
+                       .ver = lif->qtype_info[q->type].version,
                        .index = cpu_to_le32(q->index),
                        .flags = cpu_to_le16(IONIC_QINIT_F_IRQ |
                                             IONIC_QINIT_F_SG),
@@ -663,6 +675,8 @@ static int ionic_lif_rxq_init(struct ionic_lif *lif, struct ionic_qcq *qcq)
        dev_dbg(dev, "rxq_init.index %d\n", ctx.cmd.q_init.index);
        dev_dbg(dev, "rxq_init.ring_base 0x%llx\n", ctx.cmd.q_init.ring_base);
        dev_dbg(dev, "rxq_init.ring_size %d\n", ctx.cmd.q_init.ring_size);
+       dev_dbg(dev, "rxq_init.flags 0x%x\n", ctx.cmd.q_init.flags);
+       dev_dbg(dev, "rxq_init.ver %d\n", ctx.cmd.q_init.ver);
 
        q->tail = q->info;
        q->head = q->tail;
@@ -726,7 +740,7 @@ static bool ionic_notifyq_service(struct ionic_cq *cq,
                }
                break;
        default:
-               netdev_warn(netdev, "Notifyq unknown event ecode=%d eid=%lld\n",
+               netdev_warn(netdev, "Notifyq event ecode=%d eid=%lld\n",
                            comp->event.ecode, eid);
                break;
        }
@@ -775,8 +789,8 @@ static int ionic_adminq_napi(struct napi_struct *napi, int budget)
        return max(n_work, a_work);
 }
 
-static void ionic_get_stats64(struct net_device *netdev,
-                             struct rtnl_link_stats64 *ns)
+void ionic_get_stats64(struct net_device *netdev,
+                      struct rtnl_link_stats64 *ns)
 {
        struct ionic_lif *lif = netdev_priv(netdev);
        struct ionic_lif_stats *ls;
@@ -1176,10 +1190,6 @@ static int ionic_init_nic_features(struct ionic_lif *lif)
        netdev_features_t features;
        int err;
 
-       /* no netdev features on the management device */
-       if (lif->ionic->is_mgmt_nic)
-               return 0;
-
        /* set up what we expect to support by default */
        features = NETIF_F_HW_VLAN_CTAG_TX |
                   NETIF_F_HW_VLAN_CTAG_RX |
@@ -1509,17 +1519,25 @@ static void ionic_txrx_free(struct ionic_lif *lif)
 
 static int ionic_txrx_alloc(struct ionic_lif *lif)
 {
+       unsigned int sg_desc_sz;
        unsigned int flags;
        unsigned int i;
        int err = 0;
 
+       if (lif->qtype_info[IONIC_QTYPE_TXQ].version >= 1 &&
+           lif->qtype_info[IONIC_QTYPE_TXQ].sg_desc_sz ==
+                                         sizeof(struct ionic_txq_sg_desc_v1))
+               sg_desc_sz = sizeof(struct ionic_txq_sg_desc_v1);
+       else
+               sg_desc_sz = sizeof(struct ionic_txq_sg_desc);
+
        flags = IONIC_QCQ_F_TX_STATS | IONIC_QCQ_F_SG;
        for (i = 0; i < lif->nxqs; i++) {
                err = ionic_qcq_alloc(lif, IONIC_QTYPE_TXQ, i, "tx", flags,
                                      lif->ntxq_descs,
                                      sizeof(struct ionic_txq_desc),
                                      sizeof(struct ionic_txq_comp),
-                                     sizeof(struct ionic_txq_sg_desc),
+                                     sg_desc_sz,
                                      lif->kern_pid, &lif->txqcqs[i].qcq);
                if (err)
                        goto err_out;
@@ -1682,7 +1700,7 @@ int ionic_stop(struct net_device *netdev)
 {
        struct ionic_lif *lif = netdev_priv(netdev);
 
-       if (test_bit(IONIC_LIF_F_FW_RESET, lif->state))
+       if (!netif_device_present(netdev))
                return 0;
 
        ionic_stop_queues(lif);
@@ -1699,6 +1717,9 @@ static int ionic_get_vf_config(struct net_device *netdev,
        struct ionic *ionic = lif->ionic;
        int ret = 0;
 
+       if (!netif_device_present(netdev))
+               return -EBUSY;
+
        down_read(&ionic->vf_op_lock);
 
        if (vf >= pci_num_vf(ionic->pdev) || !ionic->vfs) {
@@ -1726,6 +1747,9 @@ static int ionic_get_vf_stats(struct net_device *netdev, int vf,
        struct ionic_lif_stats *vs;
        int ret = 0;
 
+       if (!netif_device_present(netdev))
+               return -EBUSY;
+
        down_read(&ionic->vf_op_lock);
 
        if (vf >= pci_num_vf(ionic->pdev) || !ionic->vfs) {
@@ -1761,6 +1785,9 @@ static int ionic_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
        if (!(is_zero_ether_addr(mac) || is_valid_ether_addr(mac)))
                return -EINVAL;
 
+       if (!netif_device_present(netdev))
+               return -EBUSY;
+
        down_write(&ionic->vf_op_lock);
 
        if (vf >= pci_num_vf(ionic->pdev) || !ionic->vfs) {
@@ -1792,6 +1819,9 @@ static int ionic_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan,
        if (proto != htons(ETH_P_8021Q))
                return -EPROTONOSUPPORT;
 
+       if (!netif_device_present(netdev))
+               return -EBUSY;
+
        down_write(&ionic->vf_op_lock);
 
        if (vf >= pci_num_vf(ionic->pdev) || !ionic->vfs) {
@@ -1818,6 +1848,9 @@ static int ionic_set_vf_rate(struct net_device *netdev, int vf,
        if (tx_min)
                return -EINVAL;
 
+       if (!netif_device_present(netdev))
+               return -EBUSY;
+
        down_write(&ionic->vf_op_lock);
 
        if (vf >= pci_num_vf(ionic->pdev) || !ionic->vfs) {
@@ -1840,6 +1873,9 @@ static int ionic_set_vf_spoofchk(struct net_device *netdev, int vf, bool set)
        u8 data = set;  /* convert to u8 for config */
        int ret;
 
+       if (!netif_device_present(netdev))
+               return -EBUSY;
+
        down_write(&ionic->vf_op_lock);
 
        if (vf >= pci_num_vf(ionic->pdev) || !ionic->vfs) {
@@ -1862,6 +1898,9 @@ static int ionic_set_vf_trust(struct net_device *netdev, int vf, bool set)
        u8 data = set;  /* convert to u8 for config */
        int ret;
 
+       if (!netif_device_present(netdev))
+               return -EBUSY;
+
        down_write(&ionic->vf_op_lock);
 
        if (vf >= pci_num_vf(ionic->pdev) || !ionic->vfs) {
@@ -1898,6 +1937,9 @@ static int ionic_set_vf_link_state(struct net_device *netdev, int vf, int set)
                return -EINVAL;
        }
 
+       if (!netif_device_present(netdev))
+               return -EBUSY;
+
        down_write(&ionic->vf_op_lock);
 
        if (vf >= pci_num_vf(ionic->pdev) || !ionic->vfs) {
@@ -2065,9 +2107,17 @@ int ionic_lifs_alloc(struct ionic *ionic)
 
        /* only build the first lif, others are for later features */
        set_bit(0, ionic->lifbits);
+
        lif = ionic_lif_alloc(ionic, 0);
+       if (IS_ERR_OR_NULL(lif)) {
+               clear_bit(0, ionic->lifbits);
+               return -ENOMEM;
+       }
+
+       lif->lif_type = IONIC_LIF_TYPE_CLASSIC;
+       ionic_lif_queue_identify(lif);
 
-       return PTR_ERR_OR_ZERO(lif);
+       return 0;
 }
 
 static void ionic_lif_reset(struct ionic_lif *lif)
@@ -2292,6 +2342,7 @@ static int ionic_lif_notifyq_init(struct ionic_lif *lif)
                        .opcode = IONIC_CMD_Q_INIT,
                        .lif_index = cpu_to_le16(lif->index),
                        .type = q->type,
+                       .ver = lif->qtype_info[q->type].version,
                        .index = cpu_to_le32(q->index),
                        .flags = cpu_to_le16(IONIC_QINIT_F_IRQ |
                                             IONIC_QINIT_F_ENA),
@@ -2536,12 +2587,6 @@ int ionic_lifs_register(struct ionic *ionic)
 {
        int err;
 
-       /* the netdev is not registered on the management device, it is
-        * only used as a vehicle for napi operations on the adminq
-        */
-       if (ionic->is_mgmt_nic)
-               return 0;
-
        INIT_WORK(&ionic->nb_work, ionic_lif_notify_work);
 
        ionic->nb.notifier_call = ionic_lif_notify;
@@ -2578,6 +2623,80 @@ void ionic_lifs_unregister(struct ionic *ionic)
                unregister_netdev(ionic->master_lif->netdev);
 }
 
+static void ionic_lif_queue_identify(struct ionic_lif *lif)
+{
+       struct ionic *ionic = lif->ionic;
+       union ionic_q_identity *q_ident;
+       struct ionic_dev *idev;
+       int qtype;
+       int err;
+
+       idev = &lif->ionic->idev;
+       q_ident = (union ionic_q_identity *)&idev->dev_cmd_regs->data;
+
+       for (qtype = 0; qtype < ARRAY_SIZE(ionic_qtype_versions); qtype++) {
+               struct ionic_qtype_info *qti = &lif->qtype_info[qtype];
+
+               /* filter out the ones we know about */
+               switch (qtype) {
+               case IONIC_QTYPE_ADMINQ:
+               case IONIC_QTYPE_NOTIFYQ:
+               case IONIC_QTYPE_RXQ:
+               case IONIC_QTYPE_TXQ:
+                       break;
+               default:
+                       continue;
+               }
+
+               memset(qti, 0, sizeof(*qti));
+
+               mutex_lock(&ionic->dev_cmd_lock);
+               ionic_dev_cmd_queue_identify(idev, lif->lif_type, qtype,
+                                            ionic_qtype_versions[qtype]);
+               err = ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT);
+               if (!err) {
+                       qti->version   = q_ident->version;
+                       qti->supported = q_ident->supported;
+                       qti->features  = le64_to_cpu(q_ident->features);
+                       qti->desc_sz   = le16_to_cpu(q_ident->desc_sz);
+                       qti->comp_sz   = le16_to_cpu(q_ident->comp_sz);
+                       qti->sg_desc_sz   = le16_to_cpu(q_ident->sg_desc_sz);
+                       qti->max_sg_elems = le16_to_cpu(q_ident->max_sg_elems);
+                       qti->sg_desc_stride = le16_to_cpu(q_ident->sg_desc_stride);
+               }
+               mutex_unlock(&ionic->dev_cmd_lock);
+
+               if (err == -EINVAL) {
+                       dev_err(ionic->dev, "qtype %d not supported\n", qtype);
+                       continue;
+               } else if (err == -EIO) {
+                       dev_err(ionic->dev, "q_ident failed, not supported on older FW\n");
+                       return;
+               } else if (err) {
+                       dev_err(ionic->dev, "q_ident failed, qtype %d: %d\n",
+                               qtype, err);
+                       return;
+               }
+
+               dev_dbg(ionic->dev, " qtype[%d].version = %d\n",
+                       qtype, qti->version);
+               dev_dbg(ionic->dev, " qtype[%d].supported = 0x%02x\n",
+                       qtype, qti->supported);
+               dev_dbg(ionic->dev, " qtype[%d].features = 0x%04llx\n",
+                       qtype, qti->features);
+               dev_dbg(ionic->dev, " qtype[%d].desc_sz = %d\n",
+                       qtype, qti->desc_sz);
+               dev_dbg(ionic->dev, " qtype[%d].comp_sz = %d\n",
+                       qtype, qti->comp_sz);
+               dev_dbg(ionic->dev, " qtype[%d].sg_desc_sz = %d\n",
+                       qtype, qti->sg_desc_sz);
+               dev_dbg(ionic->dev, " qtype[%d].max_sg_elems = %d\n",
+                       qtype, qti->max_sg_elems);
+               dev_dbg(ionic->dev, " qtype[%d].sg_desc_stride = %d\n",
+                       qtype, qti->sg_desc_stride);
+       }
+}
+
 int ionic_lif_identify(struct ionic *ionic, u8 lif_type,
                       union ionic_lif_identity *lid)
 {