]> Pileus Git - ~andy/linux/blobdiff - drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[~andy/linux] / drivers / net / ethernet / qlogic / qlcnic / qlcnic_83xx_hw.c
index b1cb0ffb15c70d1970f3cbebab28ff7f8e8530ce..03eb2ad9611a9c04da6ef97b7eecfd09f0c13609 100644 (file)
@@ -15,6 +15,7 @@
 
 #define RSS_HASHTYPE_IP_TCP            0x3
 #define QLC_83XX_FW_MBX_CMD            0
+#define QLC_SKIP_INACTIVE_PCI_REGS     7
 
 static const struct qlcnic_mailbox_metadata qlcnic_83xx_mbx_tbl[] = {
        {QLCNIC_CMD_CONFIGURE_IP_ADDR, 6, 1},
@@ -34,7 +35,7 @@ static const struct qlcnic_mailbox_metadata qlcnic_83xx_mbx_tbl[] = {
        {QLCNIC_CMD_READ_MAX_MTU, 4, 2},
        {QLCNIC_CMD_READ_MAX_LRO, 4, 2},
        {QLCNIC_CMD_MAC_ADDRESS, 4, 3},
-       {QLCNIC_CMD_GET_PCI_INFO, 1, 66},
+       {QLCNIC_CMD_GET_PCI_INFO, 1, 129},
        {QLCNIC_CMD_GET_NIC_INFO, 2, 19},
        {QLCNIC_CMD_SET_NIC_INFO, 32, 1},
        {QLCNIC_CMD_GET_ESWITCH_CAPABILITY, 4, 3},
@@ -68,7 +69,7 @@ static const struct qlcnic_mailbox_metadata qlcnic_83xx_mbx_tbl[] = {
        {QLCNIC_CMD_CONFIG_VPORT, 4, 4},
        {QLCNIC_CMD_BC_EVENT_SETUP, 2, 1},
        {QLCNIC_CMD_DCB_QUERY_CAP, 1, 2},
-       {QLCNIC_CMD_DCB_QUERY_PARAM, 2, 50},
+       {QLCNIC_CMD_DCB_QUERY_PARAM, 1, 50},
 };
 
 const u32 qlcnic_83xx_ext_reg_tbl[] = {
@@ -289,6 +290,7 @@ int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter)
                if (qlcnic_sriov_vf_check(adapter))
                        return -EINVAL;
                num_msix = 1;
+               adapter->drv_tx_rings = QLCNIC_SINGLE_RING;
        }
        /* setup interrupt mapping table for fw */
        ahw->intr_tbl = vzalloc(num_msix *
@@ -315,12 +317,12 @@ int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter)
        return 0;
 }
 
-inline void qlcnic_83xx_clear_legacy_intr_mask(struct qlcnic_adapter *adapter)
+static inline void qlcnic_83xx_clear_legacy_intr_mask(struct qlcnic_adapter *adapter)
 {
        writel(0, adapter->tgt_mask_reg);
 }
 
-inline void qlcnic_83xx_set_legacy_intr_mask(struct qlcnic_adapter *adapter)
+static inline void qlcnic_83xx_set_legacy_intr_mask(struct qlcnic_adapter *adapter)
 {
        if (adapter->tgt_mask_reg)
                writel(1, adapter->tgt_mask_reg);
@@ -340,7 +342,7 @@ void qlcnic_83xx_disable_intr(struct qlcnic_adapter *adapter,
        writel(1, sds_ring->crb_intr_mask);
 }
 
-inline void qlcnic_83xx_enable_legacy_msix_mbx_intr(struct qlcnic_adapter
+static inline void qlcnic_83xx_enable_legacy_msix_mbx_intr(struct qlcnic_adapter
                                                    *adapter)
 {
        u32 mask;
@@ -447,8 +449,9 @@ irqreturn_t qlcnic_83xx_intr(int irq, void *data)
 
        qlcnic_83xx_poll_process_aen(adapter);
 
-       if (ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
-               ahw->diag_cnt++;
+       if (ahw->diag_test) {
+               if (ahw->diag_test == QLCNIC_INTERRUPT_TEST)
+                       ahw->diag_cnt++;
                qlcnic_83xx_enable_legacy_msix_mbx_intr(adapter);
                return IRQ_HANDLED;
        }
@@ -636,7 +639,7 @@ int qlcnic_83xx_get_port_info(struct qlcnic_adapter *adapter)
 void qlcnic_83xx_set_mac_filter_count(struct qlcnic_adapter *adapter)
 {
        struct qlcnic_hardware_context *ahw = adapter->ahw;
-       u16 act_pci_fn = ahw->act_pci_func;
+       u16 act_pci_fn = ahw->total_nic_func;
        u16 count;
 
        ahw->max_mc_count = QLC_83XX_MAX_MC_COUNT;
@@ -1345,11 +1348,6 @@ static int qlcnic_83xx_diag_alloc_res(struct net_device *netdev, int test,
        }
 
        if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) {
-               /* disable and free mailbox interrupt */
-               if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
-                       qlcnic_83xx_enable_mbx_poll(adapter);
-                       qlcnic_83xx_free_mbx_intr(adapter);
-               }
                adapter->ahw->loopback_state = 0;
                adapter->ahw->hw_ops->setup_link_event(adapter, 1);
        }
@@ -1363,33 +1361,20 @@ static void qlcnic_83xx_diag_free_res(struct net_device *netdev,
 {
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
        struct qlcnic_host_sds_ring *sds_ring;
-       int ring, err;
+       int ring;
 
        clear_bit(__QLCNIC_DEV_UP, &adapter->state);
        if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
                for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
                        sds_ring = &adapter->recv_ctx->sds_rings[ring];
-                       qlcnic_83xx_disable_intr(adapter, sds_ring);
-                       if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
-                               qlcnic_83xx_enable_mbx_poll(adapter);
+                       if (adapter->flags & QLCNIC_MSIX_ENABLED)
+                               qlcnic_83xx_disable_intr(adapter, sds_ring);
                }
        }
 
        qlcnic_fw_destroy_ctx(adapter);
        qlcnic_detach(adapter);
 
-       if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) {
-               if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
-                       err = qlcnic_83xx_setup_mbx_intr(adapter);
-                       qlcnic_83xx_disable_mbx_poll(adapter);
-                       if (err) {
-                               dev_err(&adapter->pdev->dev,
-                                       "%s: failed to setup mbx interrupt\n",
-                                       __func__);
-                               goto out;
-                       }
-               }
-       }
        adapter->ahw->diag_test = 0;
        adapter->drv_sds_rings = drv_sds_rings;
 
@@ -1399,9 +1384,6 @@ static void qlcnic_83xx_diag_free_res(struct net_device *netdev,
        if (netif_running(netdev))
                __qlcnic_up(adapter, netdev);
 
-       if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST &&
-           !(adapter->flags & QLCNIC_MSIX_ENABLED))
-               qlcnic_83xx_disable_mbx_poll(adapter);
 out:
        netif_device_attach(netdev);
 }
@@ -1518,8 +1500,7 @@ int  qlcnic_83xx_set_led(struct net_device *netdev,
        return err;
 }
 
-void qlcnic_83xx_register_nic_idc_func(struct qlcnic_adapter *adapter,
-                                      int enable)
+void qlcnic_83xx_initialize_nic(struct qlcnic_adapter *adapter, int enable)
 {
        struct qlcnic_cmd_args cmd;
        int status;
@@ -1527,21 +1508,21 @@ void qlcnic_83xx_register_nic_idc_func(struct qlcnic_adapter *adapter,
        if (qlcnic_sriov_vf_check(adapter))
                return;
 
-       if (enable) {
+       if (enable)
                status = qlcnic_alloc_mbx_args(&cmd, adapter,
                                               QLCNIC_CMD_INIT_NIC_FUNC);
-               if (status)
-                       return;
-
-               cmd.req.arg[1] = BIT_0 | BIT_31;
-       } else {
+       else
                status = qlcnic_alloc_mbx_args(&cmd, adapter,
                                               QLCNIC_CMD_STOP_NIC_FUNC);
-               if (status)
-                       return;
 
-               cmd.req.arg[1] = BIT_0 | BIT_31;
-       }
+       if (status)
+               return;
+
+       cmd.req.arg[1] = QLC_REGISTER_LB_IDC | QLC_INIT_FW_RESOURCES;
+
+       if (adapter->dcb)
+               cmd.req.arg[1] |= QLC_REGISTER_DCB_AEN;
+
        status = qlcnic_issue_cmd(adapter, &cmd);
        if (status)
                dev_err(&adapter->pdev->dev,
@@ -1637,7 +1618,7 @@ int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode)
 
        cmd->type = QLC_83XX_MBX_CMD_NO_WAIT;
        qlcnic_83xx_set_interface_id_promisc(adapter, &temp);
-       cmd->req.arg[1] = (mode ? 1 : 0) | temp;
+       cmd->req.arg[1] = mode | temp;
        err = qlcnic_issue_cmd(adapter, cmd);
        if (!err)
                return err;
@@ -1704,12 +1685,6 @@ int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode)
                }
        } while ((adapter->ahw->linkup && ahw->has_link_events) != 1);
 
-       /* Make sure carrier is off and queue is stopped during loopback */
-       if (netif_running(netdev)) {
-               netif_carrier_off(netdev);
-               netif_tx_stop_all_queues(netdev);
-       }
-
        ret = qlcnic_do_lb_test(adapter, mode);
 
        qlcnic_83xx_clear_lb_mode(adapter, mode);
@@ -2141,6 +2116,7 @@ static void qlcnic_83xx_handle_link_aen(struct qlcnic_adapter *adapter,
        ahw->link_autoneg = MSB(MSW(data[3]));
        ahw->module_type = MSB(LSW(data[3]));
        ahw->has_link_events = 1;
+       ahw->lb_mode = data[4] & QLCNIC_LB_MODE_MASK;
        qlcnic_advert_link_change(adapter, link_status);
 }
 
@@ -2293,11 +2269,37 @@ out:
        return err;
 }
 
+int qlcnic_get_pci_func_type(struct qlcnic_adapter *adapter, u16 type,
+                            u16 *nic, u16 *fcoe, u16 *iscsi)
+{
+       struct device *dev = &adapter->pdev->dev;
+       int err = 0;
+
+       switch (type) {
+       case QLCNIC_TYPE_NIC:
+               (*nic)++;
+               break;
+       case QLCNIC_TYPE_FCOE:
+               (*fcoe)++;
+               break;
+       case QLCNIC_TYPE_ISCSI:
+               (*iscsi)++;
+               break;
+       default:
+               dev_err(dev, "%s: Unknown PCI type[%x]\n",
+                       __func__, type);
+               err = -EIO;
+       }
+
+       return err;
+}
+
 int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter,
                             struct qlcnic_pci_info *pci_info)
 {
        struct qlcnic_hardware_context *ahw = adapter->ahw;
        struct device *dev = &adapter->pdev->dev;
+       u16 nic = 0, fcoe = 0, iscsi = 0;
        struct qlcnic_cmd_args cmd;
        int i, err = 0, j = 0;
        u32 temp;
@@ -2308,16 +2310,20 @@ int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter,
 
        err = qlcnic_issue_cmd(adapter, &cmd);
 
-       ahw->act_pci_func = 0;
+       ahw->total_nic_func = 0;
        if (err == QLCNIC_RCODE_SUCCESS) {
                ahw->max_pci_func = cmd.rsp.arg[1] & 0xFF;
-               for (i = 2, j = 0; j < QLCNIC_MAX_PCI_FUNC; j++, pci_info++) {
+               for (i = 2, j = 0; j < ahw->max_vnic_func; j++, pci_info++) {
                        pci_info->id = cmd.rsp.arg[i] & 0xFFFF;
                        pci_info->active = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16;
                        i++;
+                       if (!pci_info->active) {
+                               i += QLC_SKIP_INACTIVE_PCI_REGS;
+                               continue;
+                       }
                        pci_info->type = cmd.rsp.arg[i] & 0xFFFF;
-                       if (pci_info->type == QLCNIC_TYPE_NIC)
-                               ahw->act_pci_func++;
+                       err = qlcnic_get_pci_func_type(adapter, pci_info->type,
+                                                      &nic, &fcoe, &iscsi);
                        temp = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16;
                        pci_info->default_port = temp;
                        i++;
@@ -2335,6 +2341,13 @@ int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter,
                err = -EIO;
        }
 
+       ahw->total_nic_func = nic;
+       ahw->total_pci_func = nic + fcoe + iscsi;
+       if (ahw->total_nic_func == 0 || ahw->total_pci_func == 0) {
+               dev_err(dev, "%s: Invalid function count: total nic func[%x], total pci func[%x]\n",
+                       __func__, ahw->total_nic_func, ahw->total_pci_func);
+               err = -EIO;
+       }
        qlcnic_free_mbx_args(&cmd);
 
        return err;
@@ -3754,6 +3767,19 @@ static void qlcnic_83xx_decode_mbx_rsp(struct qlcnic_adapter *adapter,
        return;
 }
 
+static inline void qlcnic_dump_mailbox_registers(struct qlcnic_adapter *adapter)
+{
+       struct qlcnic_hardware_context *ahw = adapter->ahw;
+       u32 offset;
+
+       offset = QLCRDX(ahw, QLCNIC_DEF_INT_MASK);
+       dev_info(&adapter->pdev->dev, "Mbx interrupt mask=0x%x, Mbx interrupt enable=0x%x, Host mbx control=0x%x, Fw mbx control=0x%x",
+                readl(ahw->pci_base0 + offset),
+                QLCRDX(ahw, QLCNIC_MBX_INTR_ENBL),
+                QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL),
+                QLCRDX(ahw, QLCNIC_FW_MBX_CTRL));
+}
+
 static void qlcnic_83xx_mailbox_worker(struct work_struct *work)
 {
        struct qlcnic_mailbox *mbx = container_of(work, struct qlcnic_mailbox,
@@ -3798,6 +3824,8 @@ static void qlcnic_83xx_mailbox_worker(struct work_struct *work)
                                __func__, cmd->cmd_op, cmd->type, ahw->pci_func,
                                ahw->op_mode);
                        clear_bit(QLC_83XX_MBX_READY, &mbx->status);
+                       qlcnic_dump_mailbox_registers(adapter);
+                       qlcnic_83xx_get_mbx_data(adapter, cmd);
                        qlcnic_dump_mbx(adapter, cmd);
                        qlcnic_83xx_idc_request_reset(adapter,
                                                      QLCNIC_FORCE_FW_DUMP_KEY);