qed: Add Light L2 support
[linux-2.6-microblaze.git] / drivers / net / ethernet / qlogic / qed / qed_main.c
index c7dc34b..48cdf62 100644 (file)
 #include <linux/etherdevice.h>
 #include <linux/vmalloc.h>
 #include <linux/qed/qed_if.h>
+#include <linux/qed/qed_ll2_if.h>
 
 #include "qed.h"
 #include "qed_sriov.h"
 #include "qed_sp.h"
 #include "qed_dev_api.h"
+#include "qed_ll2.h"
 #include "qed_mcp.h"
 #include "qed_hw.h"
 #include "qed_selftest.h"
@@ -51,8 +53,6 @@ MODULE_FIRMWARE(QED_FW_FILE_NAME);
 
 static int __init qed_init(void)
 {
-       pr_notice("qed_init called\n");
-
        pr_info("%s", version);
 
        return 0;
@@ -106,8 +106,7 @@ static void qed_free_pci(struct qed_dev *cdev)
 /* Performs PCI initializations as well as initializing PCI-related parameters
  * in the device structrue. Returns 0 in case of success.
  */
-static int qed_init_pci(struct qed_dev *cdev,
-                       struct pci_dev *pdev)
+static int qed_init_pci(struct qed_dev *cdev, struct pci_dev *pdev)
 {
        u8 rev_id;
        int rc;
@@ -263,8 +262,7 @@ static struct qed_dev *qed_alloc_cdev(struct pci_dev *pdev)
 }
 
 /* Sets the requested power state */
-static int qed_set_power_state(struct qed_dev *cdev,
-                              pci_power_t state)
+static int qed_set_power_state(struct qed_dev *cdev, pci_power_t state)
 {
        if (!cdev)
                return -ENODEV;
@@ -366,8 +364,8 @@ static int qed_enable_msix(struct qed_dev *cdev,
                DP_NOTICE(cdev,
                          "Trying to enable MSI-X with less vectors (%d out of %d)\n",
                          cnt, int_params->in.num_vectors);
-               rc = pci_enable_msix_exact(cdev->pdev,
-                                          int_params->msix_table, cnt);
+               rc = pci_enable_msix_exact(cdev->pdev, int_params->msix_table,
+                                          cnt);
                if (!rc)
                        rc = cnt;
        }
@@ -439,6 +437,11 @@ static int qed_set_int_mode(struct qed_dev *cdev, bool force_mode)
        }
 
 out:
+       if (!rc)
+               DP_INFO(cdev, "Using %s interrupts\n",
+                       int_params->out.int_mode == QED_INT_MODE_INTA ?
+                       "INTa" : int_params->out.int_mode == QED_INT_MODE_MSI ?
+                       "MSI" : "MSIX");
        cdev->int_coalescing_mode = QED_COAL_MODE_ENABLE;
 
        return rc;
@@ -514,19 +517,18 @@ static irqreturn_t qed_single_int(int irq, void *dev_instance)
 int qed_slowpath_irq_req(struct qed_hwfn *hwfn)
 {
        struct qed_dev *cdev = hwfn->cdev;
+       u32 int_mode;
        int rc = 0;
        u8 id;
 
-       if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) {
+       int_mode = cdev->int_params.out.int_mode;
+       if (int_mode == QED_INT_MODE_MSIX) {
                id = hwfn->my_id;
                snprintf(hwfn->name, NAME_SIZE, "sp-%d-%02x:%02x.%02x",
                         id, cdev->pdev->bus->number,
                         PCI_SLOT(cdev->pdev->devfn), hwfn->abs_pf_id);
                rc = request_irq(cdev->int_params.msix_table[id].vector,
                                 qed_msix_sp_int, 0, hwfn->name, hwfn->sp_dpc);
-               if (!rc)
-                       DP_VERBOSE(hwfn, (NETIF_MSG_INTR | QED_MSG_SP),
-                                  "Requested slowpath MSI-X\n");
        } else {
                unsigned long flags = 0;
 
@@ -541,6 +543,13 @@ int qed_slowpath_irq_req(struct qed_hwfn *hwfn)
                                 flags, cdev->name, cdev);
        }
 
+       if (rc)
+               DP_NOTICE(cdev, "request_irq failed, rc = %d\n", rc);
+       else
+               DP_VERBOSE(hwfn, (NETIF_MSG_INTR | QED_MSG_SP),
+                          "Requested slowpath %s\n",
+                          (int_mode == QED_INT_MODE_MSIX) ? "MSI-X" : "IRQ");
+
        return rc;
 }
 
@@ -581,6 +590,8 @@ static int qed_nic_stop(struct qed_dev *cdev)
                }
        }
 
+       qed_dbg_pf_exit(cdev);
+
        return rc;
 }
 
@@ -599,7 +610,16 @@ static int qed_nic_reset(struct qed_dev *cdev)
 
 static int qed_nic_setup(struct qed_dev *cdev)
 {
-       int rc;
+       int rc, i;
+
+       /* Determine if interface is going to require LL2 */
+       if (QED_LEADING_HWFN(cdev)->hw_info.personality != QED_PCI_ETH) {
+               for (i = 0; i < cdev->num_hwfns; i++) {
+                       struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
+
+                       p_hwfn->using_ll2 = true;
+               }
+       }
 
        rc = qed_resc_alloc(cdev);
        if (rc)
@@ -834,13 +854,13 @@ static int qed_slowpath_start(struct qed_dev *cdev,
        if (IS_PF(cdev)) {
                /* Allocate stream for unzipping */
                rc = qed_alloc_stream_mem(cdev);
-               if (rc) {
-                       DP_NOTICE(cdev, "Failed to allocate stream memory\n");
+               if (rc)
                        goto err2;
-               }
 
                /* First Dword used to diffrentiate between various sources */
                data = cdev->firmware->data + sizeof(u32);
+
+               qed_dbg_pf_init(cdev);
        }
 
        memset(&tunn_info, 0, sizeof(tunn_info));
@@ -864,6 +884,12 @@ static int qed_slowpath_start(struct qed_dev *cdev,
        DP_INFO(cdev,
                "HW initialization and function start completed successfully\n");
 
+       /* Allocate LL2 interface if needed */
+       if (QED_LEADING_HWFN(cdev)->using_ll2) {
+               rc = qed_ll2_alloc_if(cdev);
+               if (rc)
+                       goto err3;
+       }
        if (IS_PF(cdev)) {
                hwfn = QED_LEADING_HWFN(cdev);
                drv_version.version = (params->drv_major << 24) |
@@ -884,6 +910,8 @@ static int qed_slowpath_start(struct qed_dev *cdev,
 
        return 0;
 
+err3:
+       qed_hw_stop(cdev);
 err2:
        qed_hw_timers_stop_all(cdev);
        if (IS_PF(cdev))
@@ -906,6 +934,8 @@ static int qed_slowpath_stop(struct qed_dev *cdev)
        if (!cdev)
                return -ENODEV;
 
+       qed_ll2_dealloc_if(cdev);
+
        if (IS_PF(cdev)) {
                qed_free_stream_mem(cdev);
                if (IS_QED_ETH_IF(cdev))
@@ -974,8 +1004,7 @@ static u32 qed_sb_init(struct qed_dev *cdev,
 }
 
 static u32 qed_sb_release(struct qed_dev *cdev,
-                         struct qed_sb_info *sb_info,
-                         u16 sb_id)
+                         struct qed_sb_info *sb_info, u16 sb_id)
 {
        struct qed_hwfn *p_hwfn;
        int hwfn_index;
@@ -1025,20 +1054,23 @@ static int qed_set_link(struct qed_dev *cdev, struct qed_link_params *params)
                link_params->speed.autoneg = params->autoneg;
        if (params->override_flags & QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS) {
                link_params->speed.advertised_speeds = 0;
-               if ((params->adv_speeds & SUPPORTED_1000baseT_Half) ||
-                   (params->adv_speeds & SUPPORTED_1000baseT_Full))
+               if ((params->adv_speeds & QED_LM_1000baseT_Half_BIT) ||
+                   (params->adv_speeds & QED_LM_1000baseT_Full_BIT))
+                       link_params->speed.advertised_speeds |=
+                           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
+               if (params->adv_speeds & QED_LM_10000baseKR_Full_BIT)
                        link_params->speed.advertised_speeds |=
-                               NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
-               if (params->adv_speeds & SUPPORTED_10000baseKR_Full)
+                           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G;
+               if (params->adv_speeds & QED_LM_25000baseKR_Full_BIT)
                        link_params->speed.advertised_speeds |=
-                               NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G;
-               if (params->adv_speeds & SUPPORTED_40000baseLR4_Full)
+                           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G;
+               if (params->adv_speeds & QED_LM_40000baseLR4_Full_BIT)
                        link_params->speed.advertised_speeds |=
-                               NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G;
-               if (params->adv_speeds & 0)
+                           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G;
+               if (params->adv_speeds & QED_LM_50000baseKR2_Full_BIT)
                        link_params->speed.advertised_speeds |=
-                               NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G;
-               if (params->adv_speeds & 0)
+                           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G;
+               if (params->adv_speeds & QED_LM_100000baseKR4_Full_BIT)
                        link_params->speed.advertised_speeds |=
                            NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G;
        }
@@ -1168,50 +1200,56 @@ static void qed_fill_link(struct qed_hwfn *hwfn,
                if_link->link_up = true;
 
        /* TODO - at the moment assume supported and advertised speed equal */
-       if_link->supported_caps = SUPPORTED_FIBRE;
+       if_link->supported_caps = QED_LM_FIBRE_BIT;
        if (params.speed.autoneg)
-               if_link->supported_caps |= SUPPORTED_Autoneg;
+               if_link->supported_caps |= QED_LM_Autoneg_BIT;
        if (params.pause.autoneg ||
            (params.pause.forced_rx && params.pause.forced_tx))
-               if_link->supported_caps |= SUPPORTED_Asym_Pause;
+               if_link->supported_caps |= QED_LM_Asym_Pause_BIT;
        if (params.pause.autoneg || params.pause.forced_rx ||
            params.pause.forced_tx)
-               if_link->supported_caps |= SUPPORTED_Pause;
+               if_link->supported_caps |= QED_LM_Pause_BIT;
 
        if_link->advertised_caps = if_link->supported_caps;
        if (params.speed.advertised_speeds &
            NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G)
-               if_link->advertised_caps |= SUPPORTED_1000baseT_Half |
-                                          SUPPORTED_1000baseT_Full;
+               if_link->advertised_caps |= QED_LM_1000baseT_Half_BIT |
+                   QED_LM_1000baseT_Full_BIT;
        if (params.speed.advertised_speeds &
            NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G)
-               if_link->advertised_caps |= SUPPORTED_10000baseKR_Full;
+               if_link->advertised_caps |= QED_LM_10000baseKR_Full_BIT;
        if (params.speed.advertised_speeds &
-               NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G)
-               if_link->advertised_caps |= SUPPORTED_40000baseLR4_Full;
+           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G)
+               if_link->advertised_caps |= QED_LM_25000baseKR_Full_BIT;
        if (params.speed.advertised_speeds &
-               NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G)
-               if_link->advertised_caps |= 0;
+           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G)
+               if_link->advertised_caps |= QED_LM_40000baseLR4_Full_BIT;
+       if (params.speed.advertised_speeds &
+           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G)
+               if_link->advertised_caps |= QED_LM_50000baseKR2_Full_BIT;
        if (params.speed.advertised_speeds &
            NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G)
-               if_link->advertised_caps |= 0;
+               if_link->advertised_caps |= QED_LM_100000baseKR4_Full_BIT;
 
        if (link_caps.speed_capabilities &
            NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G)
-               if_link->supported_caps |= SUPPORTED_1000baseT_Half |
-                                          SUPPORTED_1000baseT_Full;
+               if_link->supported_caps |= QED_LM_1000baseT_Half_BIT |
+                   QED_LM_1000baseT_Full_BIT;
        if (link_caps.speed_capabilities &
            NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G)
-               if_link->supported_caps |= SUPPORTED_10000baseKR_Full;
+               if_link->supported_caps |= QED_LM_10000baseKR_Full_BIT;
+       if (link_caps.speed_capabilities &
+           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G)
+               if_link->supported_caps |= QED_LM_25000baseKR_Full_BIT;
        if (link_caps.speed_capabilities &
-               NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G)
-               if_link->supported_caps |= SUPPORTED_40000baseLR4_Full;
+           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G)
+               if_link->supported_caps |= QED_LM_40000baseLR4_Full_BIT;
        if (link_caps.speed_capabilities &
-               NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G)
-               if_link->supported_caps |= 0;
+           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G)
+               if_link->supported_caps |= QED_LM_50000baseKR2_Full_BIT;
        if (link_caps.speed_capabilities &
            NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G)
-               if_link->supported_caps |= 0;
+               if_link->supported_caps |= QED_LM_100000baseKR4_Full_BIT;
 
        if (link.link_up)
                if_link->speed = link.speed;
@@ -1231,33 +1269,29 @@ static void qed_fill_link(struct qed_hwfn *hwfn,
                if_link->pause_config |= QED_LINK_PAUSE_TX_ENABLE;
 
        /* Link partner capabilities */
-       if (link.partner_adv_speed &
-           QED_LINK_PARTNER_SPEED_1G_HD)
-               if_link->lp_caps |= SUPPORTED_1000baseT_Half;
-       if (link.partner_adv_speed &
-           QED_LINK_PARTNER_SPEED_1G_FD)
-               if_link->lp_caps |= SUPPORTED_1000baseT_Full;
-       if (link.partner_adv_speed &
-           QED_LINK_PARTNER_SPEED_10G)
-               if_link->lp_caps |= SUPPORTED_10000baseKR_Full;
-       if (link.partner_adv_speed &
-           QED_LINK_PARTNER_SPEED_40G)
-               if_link->lp_caps |= SUPPORTED_40000baseLR4_Full;
-       if (link.partner_adv_speed &
-           QED_LINK_PARTNER_SPEED_50G)
-               if_link->lp_caps |= 0;
-       if (link.partner_adv_speed &
-           QED_LINK_PARTNER_SPEED_100G)
-               if_link->lp_caps |= 0;
+       if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_1G_HD)
+               if_link->lp_caps |= QED_LM_1000baseT_Half_BIT;
+       if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_1G_FD)
+               if_link->lp_caps |= QED_LM_1000baseT_Full_BIT;
+       if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_10G)
+               if_link->lp_caps |= QED_LM_10000baseKR_Full_BIT;
+       if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_25G)
+               if_link->lp_caps |= QED_LM_25000baseKR_Full_BIT;
+       if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_40G)
+               if_link->lp_caps |= QED_LM_40000baseLR4_Full_BIT;
+       if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_50G)
+               if_link->lp_caps |= QED_LM_50000baseKR2_Full_BIT;
+       if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_100G)
+               if_link->lp_caps |= QED_LM_100000baseKR4_Full_BIT;
 
        if (link.an_complete)
-               if_link->lp_caps |= SUPPORTED_Autoneg;
+               if_link->lp_caps |= QED_LM_Autoneg_BIT;
 
        if (link.partner_adv_pause)
-               if_link->lp_caps |= SUPPORTED_Pause;
+               if_link->lp_caps |= QED_LM_Pause_BIT;
        if (link.partner_adv_pause == QED_LINK_PARTNER_ASYMMETRIC_PAUSE ||
            link.partner_adv_pause == QED_LINK_PARTNER_BOTH_PAUSE)
-               if_link->lp_caps |= SUPPORTED_Asym_Pause;
+               if_link->lp_caps |= QED_LM_Asym_Pause_BIT;
 }
 
 static void qed_get_current_link(struct qed_dev *cdev,
@@ -1385,9 +1419,32 @@ const struct qed_common_ops qed_common_ops_pass = {
        .get_link = &qed_get_current_link,
        .drain = &qed_drain,
        .update_msglvl = &qed_init_dp,
+       .dbg_all_data = &qed_dbg_all_data,
+       .dbg_all_data_size = &qed_dbg_all_data_size,
        .chain_alloc = &qed_chain_alloc,
        .chain_free = &qed_chain_free,
        .get_coalesce = &qed_get_coalesce,
        .set_coalesce = &qed_set_coalesce,
        .set_led = &qed_set_led,
 };
+
+void qed_get_protocol_stats(struct qed_dev *cdev,
+                           enum qed_mcp_protocol_type type,
+                           union qed_mcp_protocol_stats *stats)
+{
+       struct qed_eth_stats eth_stats;
+
+       memset(stats, 0, sizeof(*stats));
+
+       switch (type) {
+       case QED_MCP_LAN_STATS:
+               qed_get_vport_stats(cdev, &eth_stats);
+               stats->lan_stats.ucast_rx_pkts = eth_stats.rx_ucast_pkts;
+               stats->lan_stats.ucast_tx_pkts = eth_stats.tx_ucast_pkts;
+               stats->lan_stats.fcs_err = -1;
+               break;
+       default:
+               DP_ERR(cdev, "Invalid protocol type = %d\n", type);
+               return;
+       }
+}