2013-03-29 13:46:33 +08:00
|
|
|
/*
|
|
|
|
* QLogic qlcnic NIC Driver
|
|
|
|
* Copyright (c) 2009-2013 QLogic Corporation
|
|
|
|
*
|
|
|
|
* See LICENSE.qlcnic for copyright and licensing details.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "qlcnic_sriov.h"
|
|
|
|
#include "qlcnic.h"
|
2013-03-29 13:46:34 +08:00
|
|
|
#include "qlcnic_83xx_hw.h"
|
2013-03-29 13:46:33 +08:00
|
|
|
#include <linux/types.h>
|
|
|
|
|
2013-03-29 13:46:34 +08:00
|
|
|
static struct qlcnic_hardware_ops qlcnic_sriov_vf_hw_ops = {
|
|
|
|
.read_crb = qlcnic_83xx_read_crb,
|
|
|
|
.write_crb = qlcnic_83xx_write_crb,
|
|
|
|
.read_reg = qlcnic_83xx_rd_reg_indirect,
|
|
|
|
.write_reg = qlcnic_83xx_wrt_reg_indirect,
|
|
|
|
.get_mac_address = qlcnic_83xx_get_mac_address,
|
|
|
|
.setup_intr = qlcnic_83xx_setup_intr,
|
|
|
|
.alloc_mbx_args = qlcnic_83xx_alloc_mbx_args,
|
|
|
|
.get_func_no = qlcnic_83xx_get_func_no,
|
|
|
|
.api_lock = qlcnic_83xx_cam_lock,
|
|
|
|
.api_unlock = qlcnic_83xx_cam_unlock,
|
|
|
|
.process_lb_rcv_ring_diag = qlcnic_83xx_process_rcv_ring_diag,
|
|
|
|
.create_rx_ctx = qlcnic_83xx_create_rx_ctx,
|
|
|
|
.create_tx_ctx = qlcnic_83xx_create_tx_ctx,
|
|
|
|
.setup_link_event = qlcnic_83xx_setup_link_event,
|
|
|
|
.get_nic_info = qlcnic_83xx_get_nic_info,
|
|
|
|
.get_pci_info = qlcnic_83xx_get_pci_info,
|
|
|
|
.set_nic_info = qlcnic_83xx_set_nic_info,
|
|
|
|
.change_macvlan = qlcnic_83xx_sre_macaddr_change,
|
|
|
|
.napi_enable = qlcnic_83xx_napi_enable,
|
|
|
|
.napi_disable = qlcnic_83xx_napi_disable,
|
|
|
|
.config_intr_coal = qlcnic_83xx_config_intr_coal,
|
|
|
|
.config_rss = qlcnic_83xx_config_rss,
|
|
|
|
.config_hw_lro = qlcnic_83xx_config_hw_lro,
|
|
|
|
.config_promisc_mode = qlcnic_83xx_nic_set_promisc,
|
|
|
|
.change_l2_filter = qlcnic_83xx_change_l2_filter,
|
|
|
|
.get_board_info = qlcnic_83xx_get_port_info,
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct qlcnic_nic_template qlcnic_sriov_vf_ops = {
|
|
|
|
.config_bridged_mode = qlcnic_config_bridged_mode,
|
|
|
|
.config_led = qlcnic_config_led,
|
|
|
|
.cancel_idc_work = qlcnic_83xx_idc_exit,
|
|
|
|
.napi_add = qlcnic_83xx_napi_add,
|
|
|
|
.napi_del = qlcnic_83xx_napi_del,
|
|
|
|
.config_ipaddr = qlcnic_83xx_config_ipaddr,
|
|
|
|
.clear_legacy_intr = qlcnic_83xx_clear_legacy_intr,
|
|
|
|
};
|
|
|
|
|
2013-03-29 13:46:33 +08:00
|
|
|
int qlcnic_sriov_init(struct qlcnic_adapter *adapter, int num_vfs)
|
|
|
|
{
|
|
|
|
struct qlcnic_sriov *sriov;
|
|
|
|
|
|
|
|
if (!qlcnic_sriov_enable_check(adapter))
|
|
|
|
return -EIO;
|
|
|
|
|
|
|
|
sriov = kzalloc(sizeof(struct qlcnic_sriov), GFP_KERNEL);
|
|
|
|
if (!sriov)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
adapter->ahw->sriov = sriov;
|
|
|
|
sriov->num_vfs = num_vfs;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void __qlcnic_sriov_cleanup(struct qlcnic_adapter *adapter)
|
|
|
|
{
|
|
|
|
if (!qlcnic_sriov_enable_check(adapter))
|
|
|
|
return;
|
|
|
|
|
|
|
|
kfree(adapter->ahw->sriov);
|
|
|
|
}
|
|
|
|
|
2013-03-29 13:46:34 +08:00
|
|
|
static void qlcnic_sriov_vf_cleanup(struct qlcnic_adapter *adapter)
|
|
|
|
{
|
|
|
|
__qlcnic_sriov_cleanup(adapter);
|
|
|
|
}
|
|
|
|
|
2013-03-29 13:46:33 +08:00
|
|
|
void qlcnic_sriov_cleanup(struct qlcnic_adapter *adapter)
|
|
|
|
{
|
|
|
|
if (qlcnic_sriov_pf_check(adapter))
|
|
|
|
qlcnic_sriov_pf_cleanup(adapter);
|
2013-03-29 13:46:34 +08:00
|
|
|
|
|
|
|
if (qlcnic_sriov_vf_check(adapter))
|
|
|
|
qlcnic_sriov_vf_cleanup(adapter);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int qlcnic_sriov_setup_vf(struct qlcnic_adapter *adapter,
|
|
|
|
int pci_using_dac)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (!qlcnic_use_msi_x && !!qlcnic_use_msi)
|
|
|
|
dev_warn(&adapter->pdev->dev,
|
|
|
|
"83xx adapter do not support MSI interrupts\n");
|
|
|
|
|
|
|
|
err = qlcnic_setup_intr(adapter, 1);
|
|
|
|
if (err) {
|
|
|
|
dev_err(&adapter->pdev->dev, "Failed to setup interrupt\n");
|
|
|
|
goto err_out_disable_msi;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = qlcnic_83xx_setup_mbx_intr(adapter);
|
|
|
|
if (err)
|
|
|
|
goto err_out_disable_msi;
|
|
|
|
|
|
|
|
err = qlcnic_sriov_init(adapter, 1);
|
|
|
|
if (err)
|
|
|
|
goto err_out_disable_mbx_intr;
|
|
|
|
|
|
|
|
err = qlcnic_setup_netdev(adapter, adapter->netdev, pci_using_dac);
|
|
|
|
if (err)
|
|
|
|
goto err_out_cleanup_sriov;
|
|
|
|
|
|
|
|
pci_set_drvdata(adapter->pdev, adapter);
|
|
|
|
dev_info(&adapter->pdev->dev, "%s: XGbE port initialized\n",
|
|
|
|
adapter->netdev->name);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
err_out_cleanup_sriov:
|
|
|
|
__qlcnic_sriov_cleanup(adapter);
|
|
|
|
|
|
|
|
err_out_disable_mbx_intr:
|
|
|
|
qlcnic_83xx_free_mbx_intr(adapter);
|
|
|
|
|
|
|
|
err_out_disable_msi:
|
|
|
|
qlcnic_teardown_intr(adapter);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
int qlcnic_sriov_vf_init(struct qlcnic_adapter *adapter, int pci_using_dac)
|
|
|
|
{
|
|
|
|
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
|
|
|
|
|
|
|
spin_lock_init(&ahw->mbx_lock);
|
|
|
|
set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status);
|
|
|
|
ahw->msix_supported = 1;
|
2013-03-29 13:46:35 +08:00
|
|
|
adapter->flags |= QLCNIC_TX_INTR_SHARED;
|
2013-03-29 13:46:34 +08:00
|
|
|
|
|
|
|
if (qlcnic_sriov_setup_vf(adapter, pci_using_dac))
|
|
|
|
return -EIO;
|
|
|
|
|
|
|
|
if (qlcnic_read_mac_addr(adapter))
|
|
|
|
dev_warn(&adapter->pdev->dev, "failed to read mac addr\n");
|
|
|
|
|
|
|
|
set_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status);
|
|
|
|
adapter->ahw->idc.delay = QLC_83XX_IDC_FW_POLL_DELAY;
|
|
|
|
adapter->ahw->reset_context = 0;
|
|
|
|
adapter->fw_fail_cnt = 0;
|
|
|
|
clear_bit(__QLCNIC_RESETTING, &adapter->state);
|
|
|
|
adapter->need_fw_reset = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void qlcnic_sriov_vf_set_ops(struct qlcnic_adapter *adapter)
|
|
|
|
{
|
|
|
|
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
|
|
|
|
|
|
|
ahw->op_mode = QLCNIC_SRIOV_VF_FUNC;
|
|
|
|
dev_info(&adapter->pdev->dev,
|
|
|
|
"HAL Version: %d Non Privileged SRIOV function\n",
|
|
|
|
ahw->fw_hal_version);
|
|
|
|
adapter->nic_ops = &qlcnic_sriov_vf_ops;
|
|
|
|
set_bit(__QLCNIC_SRIOV_ENABLE, &adapter->state);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void qlcnic_sriov_vf_register_map(struct qlcnic_hardware_context *ahw)
|
|
|
|
{
|
|
|
|
ahw->hw_ops = &qlcnic_sriov_vf_hw_ops;
|
|
|
|
ahw->reg_tbl = (u32 *)qlcnic_83xx_reg_tbl;
|
|
|
|
ahw->ext_reg_tbl = (u32 *)qlcnic_83xx_ext_reg_tbl;
|
2013-03-29 13:46:33 +08:00
|
|
|
}
|