qlcnic: 83xx ethtool interface routines
83xx ethtool interface routines Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com> Signed-off-by: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com> Signed-off-by: Jitendra Kalsaria <jitendra.kalsaria@qlogic.com> Signed-off-by: Sony Chacko <sony.chacko@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
4e60ac4641
Коммит
7e38d04bcb
|
@ -352,6 +352,7 @@ struct qlcnic_rx_buffer {
|
||||||
|
|
||||||
#define QLCNIC_INTR_DEFAULT 0x04
|
#define QLCNIC_INTR_DEFAULT 0x04
|
||||||
#define QLCNIC_CONFIG_INTR_COALESCE 3
|
#define QLCNIC_CONFIG_INTR_COALESCE 3
|
||||||
|
#define QLCNIC_DEV_INFO_SIZE 1
|
||||||
|
|
||||||
struct qlcnic_nic_intr_coalesce {
|
struct qlcnic_nic_intr_coalesce {
|
||||||
u8 type;
|
u8 type;
|
||||||
|
@ -942,6 +943,7 @@ struct qlcnic_ipaddr {
|
||||||
#define __QLCNIC_AER 5
|
#define __QLCNIC_AER 5
|
||||||
#define __QLCNIC_DIAG_RES_ALLOC 6
|
#define __QLCNIC_DIAG_RES_ALLOC 6
|
||||||
#define __QLCNIC_LED_ENABLE 7
|
#define __QLCNIC_LED_ENABLE 7
|
||||||
|
#define __QLCNIC_ELB_INPROGRESS 8
|
||||||
|
|
||||||
#define QLCNIC_INTERRUPT_TEST 1
|
#define QLCNIC_INTERRUPT_TEST 1
|
||||||
#define QLCNIC_LOOPBACK_TEST 2
|
#define QLCNIC_LOOPBACK_TEST 2
|
||||||
|
|
|
@ -2383,3 +2383,375 @@ int qlcnic_83xx_flash_read32(struct qlcnic_adapter *adapter, u32 flash_addr,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int qlcnic_83xx_test_link(struct qlcnic_adapter *adapter)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
u32 config = 0, state;
|
||||||
|
struct qlcnic_cmd_args cmd;
|
||||||
|
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
||||||
|
|
||||||
|
state = readl(ahw->pci_base0 + QLC_83XX_LINK_STATE(ahw->pci_func));
|
||||||
|
if (!QLC_83xx_FUNC_VAL(state, ahw->pci_func)) {
|
||||||
|
dev_info(&adapter->pdev->dev, "link state down\n");
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_LINK_STATUS);
|
||||||
|
err = qlcnic_issue_cmd(adapter, &cmd);
|
||||||
|
if (err) {
|
||||||
|
dev_info(&adapter->pdev->dev,
|
||||||
|
"Get Link Status Command failed: 0x%x\n", err);
|
||||||
|
goto out;
|
||||||
|
} else {
|
||||||
|
config = cmd.rsp.arg[1];
|
||||||
|
switch (QLC_83XX_CURRENT_LINK_SPEED(config)) {
|
||||||
|
case QLC_83XX_10M_LINK:
|
||||||
|
ahw->link_speed = SPEED_10;
|
||||||
|
break;
|
||||||
|
case QLC_83XX_100M_LINK:
|
||||||
|
ahw->link_speed = SPEED_100;
|
||||||
|
break;
|
||||||
|
case QLC_83XX_1G_LINK:
|
||||||
|
ahw->link_speed = SPEED_1000;
|
||||||
|
break;
|
||||||
|
case QLC_83XX_10G_LINK:
|
||||||
|
ahw->link_speed = SPEED_10000;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ahw->link_speed = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
config = cmd.rsp.arg[3];
|
||||||
|
if (config & 1)
|
||||||
|
err = 1;
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
qlcnic_free_mbx_args(&cmd);
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
int qlcnic_83xx_get_settings(struct qlcnic_adapter *adapter)
|
||||||
|
{
|
||||||
|
u32 config = 0;
|
||||||
|
int status = 0;
|
||||||
|
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
||||||
|
|
||||||
|
/* Get port configuration info */
|
||||||
|
status = qlcnic_83xx_get_port_info(adapter);
|
||||||
|
/* Get Link Status related info */
|
||||||
|
config = qlcnic_83xx_test_link(adapter);
|
||||||
|
ahw->module_type = QLC_83XX_SFP_MODULE_TYPE(config);
|
||||||
|
/* hard code until there is a way to get it from flash */
|
||||||
|
ahw->board_type = QLCNIC_BRDTYPE_83XX_10G;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
int qlcnic_83xx_set_settings(struct qlcnic_adapter *adapter,
|
||||||
|
struct ethtool_cmd *ecmd)
|
||||||
|
{
|
||||||
|
int status = 0;
|
||||||
|
u32 config = adapter->ahw->port_config;
|
||||||
|
|
||||||
|
if (ecmd->autoneg)
|
||||||
|
adapter->ahw->port_config |= BIT_15;
|
||||||
|
|
||||||
|
switch (ethtool_cmd_speed(ecmd)) {
|
||||||
|
case SPEED_10:
|
||||||
|
adapter->ahw->port_config |= BIT_8;
|
||||||
|
break;
|
||||||
|
case SPEED_100:
|
||||||
|
adapter->ahw->port_config |= BIT_9;
|
||||||
|
break;
|
||||||
|
case SPEED_1000:
|
||||||
|
adapter->ahw->port_config |= BIT_10;
|
||||||
|
break;
|
||||||
|
case SPEED_10000:
|
||||||
|
adapter->ahw->port_config |= BIT_11;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = qlcnic_83xx_set_port_config(adapter);
|
||||||
|
if (status) {
|
||||||
|
dev_info(&adapter->pdev->dev,
|
||||||
|
"Faild to Set Link Speed and autoneg.\n");
|
||||||
|
adapter->ahw->port_config = config;
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u64 *qlcnic_83xx_copy_stats(struct qlcnic_cmd_args *cmd,
|
||||||
|
u64 *data, int index)
|
||||||
|
{
|
||||||
|
u32 low, hi;
|
||||||
|
u64 val;
|
||||||
|
|
||||||
|
low = cmd->rsp.arg[index];
|
||||||
|
hi = cmd->rsp.arg[index + 1];
|
||||||
|
val = (((u64) low) | (((u64) hi) << 32));
|
||||||
|
*data++ = val;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u64 *qlcnic_83xx_fill_stats(struct qlcnic_adapter *adapter,
|
||||||
|
struct qlcnic_cmd_args *cmd, u64 *data,
|
||||||
|
int type, int *ret)
|
||||||
|
{
|
||||||
|
int err, k, total_regs;
|
||||||
|
|
||||||
|
*ret = 0;
|
||||||
|
err = qlcnic_issue_cmd(adapter, cmd);
|
||||||
|
if (err != QLCNIC_RCODE_SUCCESS) {
|
||||||
|
dev_info(&adapter->pdev->dev,
|
||||||
|
"Error in get statistics mailbox command\n");
|
||||||
|
*ret = -EIO;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
total_regs = cmd->rsp.num;
|
||||||
|
switch (type) {
|
||||||
|
case QLC_83XX_STAT_MAC:
|
||||||
|
/* fill in MAC tx counters */
|
||||||
|
for (k = 2; k < 28; k += 2)
|
||||||
|
data = qlcnic_83xx_copy_stats(cmd, data, k);
|
||||||
|
/* skip 24 bytes of reserved area */
|
||||||
|
/* fill in MAC rx counters */
|
||||||
|
for (k += 6; k < 60; k += 2)
|
||||||
|
data = qlcnic_83xx_copy_stats(cmd, data, k);
|
||||||
|
/* skip 24 bytes of reserved area */
|
||||||
|
/* fill in MAC rx frame stats */
|
||||||
|
for (k += 6; k < 80; k += 2)
|
||||||
|
data = qlcnic_83xx_copy_stats(cmd, data, k);
|
||||||
|
break;
|
||||||
|
case QLC_83XX_STAT_RX:
|
||||||
|
for (k = 2; k < 8; k += 2)
|
||||||
|
data = qlcnic_83xx_copy_stats(cmd, data, k);
|
||||||
|
/* skip 8 bytes of reserved data */
|
||||||
|
for (k += 2; k < 24; k += 2)
|
||||||
|
data = qlcnic_83xx_copy_stats(cmd, data, k);
|
||||||
|
/* skip 8 bytes containing RE1FBQ error data */
|
||||||
|
for (k += 2; k < total_regs; k += 2)
|
||||||
|
data = qlcnic_83xx_copy_stats(cmd, data, k);
|
||||||
|
break;
|
||||||
|
case QLC_83XX_STAT_TX:
|
||||||
|
for (k = 2; k < 10; k += 2)
|
||||||
|
data = qlcnic_83xx_copy_stats(cmd, data, k);
|
||||||
|
/* skip 8 bytes of reserved data */
|
||||||
|
for (k += 2; k < total_regs; k += 2)
|
||||||
|
data = qlcnic_83xx_copy_stats(cmd, data, k);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dev_warn(&adapter->pdev->dev, "Unknown get statistics mode\n");
|
||||||
|
*ret = -EIO;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void qlcnic_83xx_get_stats(struct qlcnic_adapter *adapter, u64 *data)
|
||||||
|
{
|
||||||
|
struct qlcnic_cmd_args cmd;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_STATISTICS);
|
||||||
|
/* Get Tx stats */
|
||||||
|
cmd.req.arg[1] = BIT_1 | (adapter->tx_ring->ctx_id << 16);
|
||||||
|
cmd.rsp.num = QLC_83XX_TX_STAT_REGS;
|
||||||
|
data = qlcnic_83xx_fill_stats(adapter, &cmd, data,
|
||||||
|
QLC_83XX_STAT_TX, &ret);
|
||||||
|
if (ret) {
|
||||||
|
dev_info(&adapter->pdev->dev, "Error getting MAC stats\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
/* Get MAC stats */
|
||||||
|
cmd.req.arg[1] = BIT_2 | (adapter->portnum << 16);
|
||||||
|
cmd.rsp.num = QLC_83XX_MAC_STAT_REGS;
|
||||||
|
memset(cmd.rsp.arg, 0, sizeof(u32) * cmd.rsp.num);
|
||||||
|
data = qlcnic_83xx_fill_stats(adapter, &cmd, data,
|
||||||
|
QLC_83XX_STAT_MAC, &ret);
|
||||||
|
if (ret) {
|
||||||
|
dev_info(&adapter->pdev->dev,
|
||||||
|
"Error getting Rx stats\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
/* Get Rx stats */
|
||||||
|
cmd.req.arg[1] = adapter->recv_ctx->context_id << 16;
|
||||||
|
cmd.rsp.num = QLC_83XX_RX_STAT_REGS;
|
||||||
|
memset(cmd.rsp.arg, 0, sizeof(u32) * cmd.rsp.num);
|
||||||
|
data = qlcnic_83xx_fill_stats(adapter, &cmd, data,
|
||||||
|
QLC_83XX_STAT_RX, &ret);
|
||||||
|
if (ret)
|
||||||
|
dev_info(&adapter->pdev->dev,
|
||||||
|
"Error getting Tx stats\n");
|
||||||
|
out:
|
||||||
|
qlcnic_free_mbx_args(&cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int qlcnic_83xx_reg_test(struct qlcnic_adapter *adapter)
|
||||||
|
{
|
||||||
|
u32 major, minor, sub;
|
||||||
|
|
||||||
|
major = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MAJOR);
|
||||||
|
minor = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MINOR);
|
||||||
|
sub = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_SUB);
|
||||||
|
|
||||||
|
if (adapter->fw_version != QLCNIC_VERSION_CODE(major, minor, sub)) {
|
||||||
|
dev_info(&adapter->pdev->dev, "%s: Reg test failed\n",
|
||||||
|
__func__);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int qlcnic_83xx_get_regs_len(struct qlcnic_adapter *adapter)
|
||||||
|
{
|
||||||
|
return (ARRAY_SIZE(qlcnic_83xx_ext_reg_tbl) *
|
||||||
|
sizeof(adapter->ahw->ext_reg_tbl)) +
|
||||||
|
(ARRAY_SIZE(qlcnic_83xx_reg_tbl) +
|
||||||
|
sizeof(adapter->ahw->reg_tbl));
|
||||||
|
}
|
||||||
|
|
||||||
|
int qlcnic_83xx_get_registers(struct qlcnic_adapter *adapter, u32 *regs_buff)
|
||||||
|
{
|
||||||
|
int i, j = 0;
|
||||||
|
|
||||||
|
for (i = QLCNIC_DEV_INFO_SIZE + 1;
|
||||||
|
j < ARRAY_SIZE(qlcnic_83xx_reg_tbl); i++, j++)
|
||||||
|
regs_buff[i] = QLC_SHARED_REG_RD32(adapter, j);
|
||||||
|
|
||||||
|
for (j = 0; j < ARRAY_SIZE(qlcnic_83xx_ext_reg_tbl); j++)
|
||||||
|
regs_buff[i++] = QLCRDX(adapter->ahw, j);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int qlcnic_83xx_interrupt_test(struct qlcnic_adapter *adapter,
|
||||||
|
struct qlcnic_cmd_args *cmd)
|
||||||
|
{
|
||||||
|
u8 val;
|
||||||
|
int ret;
|
||||||
|
u32 data;
|
||||||
|
u16 intrpt_id, id;
|
||||||
|
|
||||||
|
if (adapter->flags & QLCNIC_MSIX_ENABLED)
|
||||||
|
intrpt_id = adapter->ahw->intr_tbl[0].id;
|
||||||
|
else
|
||||||
|
intrpt_id = QLCRDX(adapter->ahw, QLCNIC_DEF_INT_ID);
|
||||||
|
|
||||||
|
cmd->req.arg[1] = 1;
|
||||||
|
cmd->req.arg[2] = intrpt_id;
|
||||||
|
cmd->req.arg[3] = BIT_0;
|
||||||
|
|
||||||
|
ret = qlcnic_issue_cmd(adapter, cmd);
|
||||||
|
data = cmd->rsp.arg[2];
|
||||||
|
id = LSW(data);
|
||||||
|
val = LSB(MSW(data));
|
||||||
|
if (id != intrpt_id)
|
||||||
|
dev_info(&adapter->pdev->dev,
|
||||||
|
"Interrupt generated: 0x%x, requested:0x%x\n",
|
||||||
|
id, intrpt_id);
|
||||||
|
if (val)
|
||||||
|
dev_info(&adapter->pdev->dev,
|
||||||
|
"Interrupt test error: 0x%x\n", val);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void qlcnic_83xx_get_pauseparam(struct qlcnic_adapter *adapter,
|
||||||
|
struct ethtool_pauseparam *pause)
|
||||||
|
{
|
||||||
|
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
||||||
|
int status = 0;
|
||||||
|
u32 config;
|
||||||
|
|
||||||
|
status = qlcnic_83xx_get_port_config(adapter);
|
||||||
|
if (status) {
|
||||||
|
dev_err(&adapter->pdev->dev,
|
||||||
|
"%s: Get Pause Config failed\n", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
config = ahw->port_config;
|
||||||
|
if (config & QLC_83XX_CFG_STD_PAUSE) {
|
||||||
|
if (config & QLC_83XX_CFG_STD_TX_PAUSE)
|
||||||
|
pause->tx_pause = 1;
|
||||||
|
if (config & QLC_83XX_CFG_STD_RX_PAUSE)
|
||||||
|
pause->rx_pause = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (QLC_83XX_AUTONEG(config))
|
||||||
|
pause->autoneg = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int qlcnic_83xx_set_pauseparam(struct qlcnic_adapter *adapter,
|
||||||
|
struct ethtool_pauseparam *pause)
|
||||||
|
{
|
||||||
|
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
||||||
|
int status = 0;
|
||||||
|
u32 config;
|
||||||
|
|
||||||
|
status = qlcnic_83xx_get_port_config(adapter);
|
||||||
|
if (status) {
|
||||||
|
dev_err(&adapter->pdev->dev,
|
||||||
|
"%s: Get Pause Config failed.\n", __func__);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
config = ahw->port_config;
|
||||||
|
|
||||||
|
if (ahw->port_type == QLCNIC_GBE) {
|
||||||
|
if (pause->autoneg)
|
||||||
|
ahw->port_config |= QLC_83XX_ENABLE_AUTONEG;
|
||||||
|
if (!pause->autoneg)
|
||||||
|
ahw->port_config &= ~QLC_83XX_ENABLE_AUTONEG;
|
||||||
|
} else if ((ahw->port_type == QLCNIC_XGBE) && (pause->autoneg)) {
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(config & QLC_83XX_CFG_STD_PAUSE))
|
||||||
|
ahw->port_config |= QLC_83XX_CFG_STD_PAUSE;
|
||||||
|
|
||||||
|
if (pause->rx_pause && pause->tx_pause) {
|
||||||
|
ahw->port_config |= QLC_83XX_CFG_STD_TX_RX_PAUSE;
|
||||||
|
} else if (pause->rx_pause && !pause->tx_pause) {
|
||||||
|
ahw->port_config &= ~QLC_83XX_CFG_STD_TX_PAUSE;
|
||||||
|
ahw->port_config |= QLC_83XX_CFG_STD_RX_PAUSE;
|
||||||
|
} else if (pause->tx_pause && !pause->rx_pause) {
|
||||||
|
ahw->port_config &= ~QLC_83XX_CFG_STD_RX_PAUSE;
|
||||||
|
ahw->port_config |= QLC_83XX_CFG_STD_TX_PAUSE;
|
||||||
|
} else if (!pause->rx_pause && !pause->tx_pause) {
|
||||||
|
ahw->port_config &= ~QLC_83XX_CFG_STD_TX_RX_PAUSE;
|
||||||
|
}
|
||||||
|
status = qlcnic_83xx_set_port_config(adapter);
|
||||||
|
if (status) {
|
||||||
|
dev_err(&adapter->pdev->dev,
|
||||||
|
"%s: Set Pause Config failed.\n", __func__);
|
||||||
|
ahw->port_config = config;
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int qlcnic_83xx_read_flash_status_reg(struct qlcnic_adapter *adapter)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
|
||||||
|
QLC_83XX_FLASH_OEM_READ_SIG);
|
||||||
|
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
|
||||||
|
QLC_83XX_FLASH_READ_CTRL);
|
||||||
|
ret = qlcnic_83xx_poll_flash_status_reg(adapter);
|
||||||
|
if (ret)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
ret = qlcnic_83xx_rd_reg_indirect(adapter, QLC_83XX_FLASH_RDDATA);
|
||||||
|
return ret & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
int qlcnic_83xx_flash_test(struct qlcnic_adapter *adapter)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
|
||||||
|
status = qlcnic_83xx_read_flash_status_reg(adapter);
|
||||||
|
if (status == -EIO) {
|
||||||
|
dev_info(&adapter->pdev->dev, "%s: EEPROM test failed.\n",
|
||||||
|
__func__);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -337,8 +337,6 @@ void qlcnic_83xx_napi_disable(struct qlcnic_adapter *);
|
||||||
int qlcnic_83xx_config_led(struct qlcnic_adapter *, u32, u32);
|
int qlcnic_83xx_config_led(struct qlcnic_adapter *, u32, u32);
|
||||||
void qlcnic_ind_wr(struct qlcnic_adapter *, u32, u32);
|
void qlcnic_ind_wr(struct qlcnic_adapter *, u32, u32);
|
||||||
int qlcnic_ind_rd(struct qlcnic_adapter *, u32);
|
int qlcnic_ind_rd(struct qlcnic_adapter *, u32);
|
||||||
void qlcnic_83xx_get_stats(struct qlcnic_adapter *,
|
|
||||||
struct ethtool_stats *, u64 *);
|
|
||||||
int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *);
|
int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *);
|
||||||
int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *,
|
int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *,
|
||||||
struct qlcnic_host_tx_ring *, int);
|
struct qlcnic_host_tx_ring *, int);
|
||||||
|
@ -409,4 +407,18 @@ int qlcnic_83xx_get_vnic_vport_info(struct qlcnic_adapter *,
|
||||||
int qlcnic_83xx_get_vnic_pf_info(struct qlcnic_adapter *, struct qlcnic_info *);
|
int qlcnic_83xx_get_vnic_pf_info(struct qlcnic_adapter *, struct qlcnic_info *);
|
||||||
|
|
||||||
void qlcnic_83xx_get_minidump_template(struct qlcnic_adapter *);
|
void qlcnic_83xx_get_minidump_template(struct qlcnic_adapter *);
|
||||||
|
void qlcnic_83xx_get_stats(struct qlcnic_adapter *adapter, u64 *data);
|
||||||
|
int qlcnic_83xx_get_settings(struct qlcnic_adapter *);
|
||||||
|
int qlcnic_83xx_set_settings(struct qlcnic_adapter *, struct ethtool_cmd *);
|
||||||
|
void qlcnic_83xx_get_pauseparam(struct qlcnic_adapter *,
|
||||||
|
struct ethtool_pauseparam *);
|
||||||
|
int qlcnic_83xx_set_pauseparam(struct qlcnic_adapter *,
|
||||||
|
struct ethtool_pauseparam *);
|
||||||
|
int qlcnic_83xx_test_link(struct qlcnic_adapter *);
|
||||||
|
int qlcnic_83xx_reg_test(struct qlcnic_adapter *);
|
||||||
|
int qlcnic_83xx_get_regs_len(struct qlcnic_adapter *);
|
||||||
|
int qlcnic_83xx_get_registers(struct qlcnic_adapter *, u32 *);
|
||||||
|
int qlcnic_83xx_interrupt_test(struct qlcnic_adapter *,
|
||||||
|
struct qlcnic_cmd_args *);
|
||||||
|
int qlcnic_83xx_flash_test(struct qlcnic_adapter *);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -22,42 +22,37 @@ struct qlcnic_stats {
|
||||||
|
|
||||||
#define QLC_SIZEOF(m) FIELD_SIZEOF(struct qlcnic_adapter, m)
|
#define QLC_SIZEOF(m) FIELD_SIZEOF(struct qlcnic_adapter, m)
|
||||||
#define QLC_OFF(m) offsetof(struct qlcnic_adapter, m)
|
#define QLC_OFF(m) offsetof(struct qlcnic_adapter, m)
|
||||||
|
static const u32 qlcnic_fw_dump_level[] = {
|
||||||
|
0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff
|
||||||
|
};
|
||||||
|
|
||||||
static const struct qlcnic_stats qlcnic_gstrings_stats[] = {
|
static const struct qlcnic_stats qlcnic_gstrings_stats[] = {
|
||||||
{"xmit_called",
|
{"xmit_called", QLC_SIZEOF(stats.xmitcalled),
|
||||||
QLC_SIZEOF(stats.xmitcalled), QLC_OFF(stats.xmitcalled)},
|
QLC_OFF(stats.xmitcalled)},
|
||||||
{"xmit_finished",
|
{"xmit_finished", QLC_SIZEOF(stats.xmitfinished),
|
||||||
QLC_SIZEOF(stats.xmitfinished), QLC_OFF(stats.xmitfinished)},
|
QLC_OFF(stats.xmitfinished)},
|
||||||
{"rx_dropped",
|
{"rx_dropped", QLC_SIZEOF(stats.rxdropped), QLC_OFF(stats.rxdropped)},
|
||||||
QLC_SIZEOF(stats.rxdropped), QLC_OFF(stats.rxdropped)},
|
{"tx_dropped", QLC_SIZEOF(stats.txdropped), QLC_OFF(stats.txdropped)},
|
||||||
{"tx_dropped",
|
{"csummed", QLC_SIZEOF(stats.csummed), QLC_OFF(stats.csummed)},
|
||||||
QLC_SIZEOF(stats.txdropped), QLC_OFF(stats.txdropped)},
|
{"rx_pkts", QLC_SIZEOF(stats.rx_pkts), QLC_OFF(stats.rx_pkts)},
|
||||||
{"csummed",
|
{"lro_pkts", QLC_SIZEOF(stats.lro_pkts), QLC_OFF(stats.lro_pkts)},
|
||||||
QLC_SIZEOF(stats.csummed), QLC_OFF(stats.csummed)},
|
{"rx_bytes", QLC_SIZEOF(stats.rxbytes), QLC_OFF(stats.rxbytes)},
|
||||||
{"rx_pkts",
|
{"tx_bytes", QLC_SIZEOF(stats.txbytes), QLC_OFF(stats.txbytes)},
|
||||||
QLC_SIZEOF(stats.rx_pkts), QLC_OFF(stats.rx_pkts)},
|
{"lrobytes", QLC_SIZEOF(stats.lrobytes), QLC_OFF(stats.lrobytes)},
|
||||||
{"lro_pkts",
|
{"lso_frames", QLC_SIZEOF(stats.lso_frames), QLC_OFF(stats.lso_frames)},
|
||||||
QLC_SIZEOF(stats.lro_pkts), QLC_OFF(stats.lro_pkts)},
|
{"xmit_on", QLC_SIZEOF(stats.xmit_on), QLC_OFF(stats.xmit_on)},
|
||||||
{"rx_bytes",
|
{"xmit_off", QLC_SIZEOF(stats.xmit_off), QLC_OFF(stats.xmit_off)},
|
||||||
QLC_SIZEOF(stats.rxbytes), QLC_OFF(stats.rxbytes)},
|
|
||||||
{"tx_bytes",
|
|
||||||
QLC_SIZEOF(stats.txbytes), QLC_OFF(stats.txbytes)},
|
|
||||||
{"lrobytes",
|
|
||||||
QLC_SIZEOF(stats.lrobytes), QLC_OFF(stats.lrobytes)},
|
|
||||||
{"lso_frames",
|
|
||||||
QLC_SIZEOF(stats.lso_frames), QLC_OFF(stats.lso_frames)},
|
|
||||||
{"xmit_on",
|
|
||||||
QLC_SIZEOF(stats.xmit_on), QLC_OFF(stats.xmit_on)},
|
|
||||||
{"xmit_off",
|
|
||||||
QLC_SIZEOF(stats.xmit_off), QLC_OFF(stats.xmit_off)},
|
|
||||||
{"skb_alloc_failure", QLC_SIZEOF(stats.skb_alloc_failure),
|
{"skb_alloc_failure", QLC_SIZEOF(stats.skb_alloc_failure),
|
||||||
QLC_OFF(stats.skb_alloc_failure)},
|
QLC_OFF(stats.skb_alloc_failure)},
|
||||||
{"null rxbuf",
|
{"null rxbuf", QLC_SIZEOF(stats.null_rxbuf), QLC_OFF(stats.null_rxbuf)},
|
||||||
QLC_SIZEOF(stats.null_rxbuf), QLC_OFF(stats.null_rxbuf)},
|
|
||||||
{"rx dma map error", QLC_SIZEOF(stats.rx_dma_map_error),
|
{"rx dma map error", QLC_SIZEOF(stats.rx_dma_map_error),
|
||||||
QLC_OFF(stats.rx_dma_map_error)},
|
QLC_OFF(stats.rx_dma_map_error)},
|
||||||
{"tx dma map error", QLC_SIZEOF(stats.tx_dma_map_error),
|
{"tx dma map error", QLC_SIZEOF(stats.tx_dma_map_error),
|
||||||
QLC_OFF(stats.tx_dma_map_error)},
|
QLC_OFF(stats.tx_dma_map_error)},
|
||||||
|
{"mac_filter_limit_overrun", QLC_SIZEOF(stats.mac_filter_limit_overrun),
|
||||||
|
QLC_OFF(stats.mac_filter_limit_overrun)},
|
||||||
|
{"spurious intr", QLC_SIZEOF(stats.spurious_intr),
|
||||||
|
QLC_OFF(stats.spurious_intr)},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -78,7 +73,15 @@ static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = {
|
||||||
"tx numbytes",
|
"tx numbytes",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char qlcnic_mac_stats_strings [][ETH_GSTRING_LEN] = {
|
static const char qlcnic_83xx_tx_stats_strings[][ETH_GSTRING_LEN] = {
|
||||||
|
"ctx_tx_bytes",
|
||||||
|
"ctx_tx_pkts",
|
||||||
|
"ctx_tx_errors",
|
||||||
|
"ctx_tx_dropped_pkts",
|
||||||
|
"ctx_tx_num_buffers",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char qlcnic_83xx_mac_stats_strings[][ETH_GSTRING_LEN] = {
|
||||||
"mac_tx_frames",
|
"mac_tx_frames",
|
||||||
"mac_tx_bytes",
|
"mac_tx_bytes",
|
||||||
"mac_tx_mcast_pkts",
|
"mac_tx_mcast_pkts",
|
||||||
|
@ -110,25 +113,62 @@ static const char qlcnic_mac_stats_strings [][ETH_GSTRING_LEN] = {
|
||||||
"mac_rx_length_large",
|
"mac_rx_length_large",
|
||||||
"mac_rx_jabber",
|
"mac_rx_jabber",
|
||||||
"mac_rx_dropped",
|
"mac_rx_dropped",
|
||||||
"mac_rx_crc_error",
|
"mac_crc_error",
|
||||||
"mac_align_error",
|
"mac_align_error",
|
||||||
};
|
};
|
||||||
|
|
||||||
#define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats)
|
#define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats)
|
||||||
#define QLCNIC_MAC_STATS_LEN ARRAY_SIZE(qlcnic_mac_stats_strings)
|
static const char qlcnic_83xx_rx_stats_strings[][ETH_GSTRING_LEN] = {
|
||||||
#define QLCNIC_DEVICE_STATS_LEN ARRAY_SIZE(qlcnic_device_gstrings_stats)
|
"ctx_rx_bytes",
|
||||||
#define QLCNIC_TOTAL_STATS_LEN QLCNIC_STATS_LEN + QLCNIC_MAC_STATS_LEN
|
"ctx_rx_pkts",
|
||||||
|
"ctx_lro_pkt_cnt",
|
||||||
|
"ctx_ip_csum_error",
|
||||||
|
"ctx_rx_pkts_wo_ctx",
|
||||||
|
"ctx_rx_pkts_dropped_wo_sts",
|
||||||
|
"ctx_rx_osized_pkts",
|
||||||
|
"ctx_rx_pkts_dropped_wo_rds",
|
||||||
|
"ctx_rx_unexpected_mcast_pkts",
|
||||||
|
"ctx_invalid_mac_address",
|
||||||
|
"ctx_rx_rds_ring_prim_attemoted",
|
||||||
|
"ctx_rx_rds_ring_prim_success",
|
||||||
|
"ctx_num_lro_flows_added",
|
||||||
|
"ctx_num_lro_flows_removed",
|
||||||
|
"ctx_num_lro_flows_active",
|
||||||
|
"ctx_pkts_dropped_unknown",
|
||||||
|
};
|
||||||
|
|
||||||
static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
|
static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
|
||||||
"Register_Test_on_offline",
|
"Register_Test_on_offline",
|
||||||
"Link_Test_on_offline",
|
"Link_Test_on_offline",
|
||||||
"Interrupt_Test_offline",
|
"Interrupt_Test_offline",
|
||||||
"Internal_Loopback_offline",
|
"Internal_Loopback_offline",
|
||||||
"External_Loopback_offline"
|
"EEPROM_Test_offline"
|
||||||
};
|
};
|
||||||
|
|
||||||
#define QLCNIC_TEST_LEN ARRAY_SIZE(qlcnic_gstrings_test)
|
#define QLCNIC_TEST_LEN ARRAY_SIZE(qlcnic_gstrings_test)
|
||||||
|
|
||||||
|
static inline int qlcnic_82xx_statistics(void)
|
||||||
|
{
|
||||||
|
return QLCNIC_STATS_LEN + ARRAY_SIZE(qlcnic_83xx_mac_stats_strings);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int qlcnic_83xx_statistics(void)
|
||||||
|
{
|
||||||
|
return ARRAY_SIZE(qlcnic_83xx_tx_stats_strings) +
|
||||||
|
ARRAY_SIZE(qlcnic_83xx_mac_stats_strings) +
|
||||||
|
ARRAY_SIZE(qlcnic_83xx_rx_stats_strings);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int qlcnic_dev_statistics_len(struct qlcnic_adapter *adapter)
|
||||||
|
{
|
||||||
|
if (qlcnic_82xx_check(adapter))
|
||||||
|
return qlcnic_82xx_statistics();
|
||||||
|
else if (qlcnic_83xx_check(adapter))
|
||||||
|
return qlcnic_83xx_statistics();
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
#define QLCNIC_RING_REGS_COUNT 20
|
#define QLCNIC_RING_REGS_COUNT 20
|
||||||
#define QLCNIC_RING_REGS_LEN (QLCNIC_RING_REGS_COUNT * sizeof(u32))
|
#define QLCNIC_RING_REGS_LEN (QLCNIC_RING_REGS_COUNT * sizeof(u32))
|
||||||
#define QLCNIC_MAX_EEPROM_LEN 1024
|
#define QLCNIC_MAX_EEPROM_LEN 1024
|
||||||
|
@ -148,6 +188,12 @@ static const u32 diag_registers[] = {
|
||||||
QLCNIC_PEG_ALIVE_COUNTER,
|
QLCNIC_PEG_ALIVE_COUNTER,
|
||||||
QLCNIC_PEG_HALT_STATUS1,
|
QLCNIC_PEG_HALT_STATUS1,
|
||||||
QLCNIC_PEG_HALT_STATUS2,
|
QLCNIC_PEG_HALT_STATUS2,
|
||||||
|
-1
|
||||||
|
};
|
||||||
|
|
||||||
|
static const u32 ext_diag_registers[] = {
|
||||||
|
CRB_XG_STATE_P3P,
|
||||||
|
ISR_INT_STATE_REG,
|
||||||
QLCNIC_CRB_PEG_NET_0+0x3c,
|
QLCNIC_CRB_PEG_NET_0+0x3c,
|
||||||
QLCNIC_CRB_PEG_NET_1+0x3c,
|
QLCNIC_CRB_PEG_NET_1+0x3c,
|
||||||
QLCNIC_CRB_PEG_NET_2+0x3c,
|
QLCNIC_CRB_PEG_NET_2+0x3c,
|
||||||
|
@ -156,12 +202,19 @@ static const u32 diag_registers[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
#define QLCNIC_MGMT_API_VERSION 2
|
#define QLCNIC_MGMT_API_VERSION 2
|
||||||
#define QLCNIC_DEV_INFO_SIZE 1
|
#define QLCNIC_ETHTOOL_REGS_VER 3
|
||||||
#define QLCNIC_ETHTOOL_REGS_VER 2
|
|
||||||
static int qlcnic_get_regs_len(struct net_device *dev)
|
static int qlcnic_get_regs_len(struct net_device *dev)
|
||||||
{
|
{
|
||||||
return sizeof(diag_registers) + QLCNIC_RING_REGS_LEN +
|
struct qlcnic_adapter *adapter = netdev_priv(dev);
|
||||||
QLCNIC_DEV_INFO_SIZE + 1;
|
u32 len;
|
||||||
|
|
||||||
|
if (qlcnic_83xx_check(adapter))
|
||||||
|
len = qlcnic_83xx_get_regs_len(adapter);
|
||||||
|
else
|
||||||
|
len = sizeof(ext_diag_registers) + sizeof(diag_registers);
|
||||||
|
|
||||||
|
return QLCNIC_RING_REGS_LEN + len + QLCNIC_DEV_INFO_SIZE + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int qlcnic_get_eeprom_len(struct net_device *dev)
|
static int qlcnic_get_eeprom_len(struct net_device *dev)
|
||||||
|
@ -174,10 +227,9 @@ qlcnic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
|
||||||
{
|
{
|
||||||
struct qlcnic_adapter *adapter = netdev_priv(dev);
|
struct qlcnic_adapter *adapter = netdev_priv(dev);
|
||||||
u32 fw_major, fw_minor, fw_build;
|
u32 fw_major, fw_minor, fw_build;
|
||||||
|
fw_major = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MAJOR);
|
||||||
fw_major = QLCRD32(adapter, QLCNIC_FW_VERSION_MAJOR);
|
fw_minor = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MINOR);
|
||||||
fw_minor = QLCRD32(adapter, QLCNIC_FW_VERSION_MINOR);
|
fw_build = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_SUB);
|
||||||
fw_build = QLCRD32(adapter, QLCNIC_FW_VERSION_SUB);
|
|
||||||
snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
|
snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
|
||||||
"%d.%d.%d", fw_major, fw_minor, fw_build);
|
"%d.%d.%d", fw_major, fw_minor, fw_build);
|
||||||
|
|
||||||
|
@ -192,7 +244,10 @@ static int
|
||||||
qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
|
qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
|
||||||
{
|
{
|
||||||
struct qlcnic_adapter *adapter = netdev_priv(dev);
|
struct qlcnic_adapter *adapter = netdev_priv(dev);
|
||||||
|
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
||||||
|
u32 speed, reg;
|
||||||
int check_sfp_module = 0;
|
int check_sfp_module = 0;
|
||||||
|
u16 pcifn = ahw->pci_func;
|
||||||
|
|
||||||
/* read which mode */
|
/* read which mode */
|
||||||
if (adapter->ahw->port_type == QLCNIC_GBE) {
|
if (adapter->ahw->port_type == QLCNIC_GBE) {
|
||||||
|
@ -213,9 +268,12 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
|
||||||
ecmd->autoneg = adapter->ahw->link_autoneg;
|
ecmd->autoneg = adapter->ahw->link_autoneg;
|
||||||
|
|
||||||
} else if (adapter->ahw->port_type == QLCNIC_XGBE) {
|
} else if (adapter->ahw->port_type == QLCNIC_XGBE) {
|
||||||
u32 val;
|
u32 val = 0;
|
||||||
|
if (qlcnic_83xx_check(adapter))
|
||||||
|
qlcnic_83xx_get_settings(adapter);
|
||||||
|
else
|
||||||
|
val = QLCRD32(adapter, QLCNIC_PORT_MODE_ADDR);
|
||||||
|
|
||||||
val = QLCRD32(adapter, QLCNIC_PORT_MODE_ADDR);
|
|
||||||
if (val == QLCNIC_PORT_MODE_802_3_AP) {
|
if (val == QLCNIC_PORT_MODE_802_3_AP) {
|
||||||
ecmd->supported = SUPPORTED_1000baseT_Full;
|
ecmd->supported = SUPPORTED_1000baseT_Full;
|
||||||
ecmd->advertising = ADVERTISED_1000baseT_Full;
|
ecmd->advertising = ADVERTISED_1000baseT_Full;
|
||||||
|
@ -225,6 +283,12 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (netif_running(dev) && adapter->ahw->has_link_events) {
|
if (netif_running(dev) && adapter->ahw->has_link_events) {
|
||||||
|
if (qlcnic_82xx_check(adapter)) {
|
||||||
|
reg = QLCRD32(adapter,
|
||||||
|
P3P_LINK_SPEED_REG(pcifn));
|
||||||
|
speed = P3P_LINK_SPEED_VAL(pcifn, reg);
|
||||||
|
ahw->link_speed = speed * P3P_LINK_SPEED_MHZ;
|
||||||
|
}
|
||||||
ethtool_cmd_speed_set(ecmd, adapter->ahw->link_speed);
|
ethtool_cmd_speed_set(ecmd, adapter->ahw->link_speed);
|
||||||
ecmd->autoneg = adapter->ahw->link_autoneg;
|
ecmd->autoneg = adapter->ahw->link_autoneg;
|
||||||
ecmd->duplex = adapter->ahw->link_duplex;
|
ecmd->duplex = adapter->ahw->link_duplex;
|
||||||
|
@ -294,6 +358,13 @@ skip:
|
||||||
ecmd->port = PORT_TP;
|
ecmd->port = PORT_TP;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case QLCNIC_BRDTYPE_83XX_10G:
|
||||||
|
ecmd->autoneg = AUTONEG_DISABLE;
|
||||||
|
ecmd->supported |= (SUPPORTED_FIBRE | SUPPORTED_TP);
|
||||||
|
ecmd->advertising |= (ADVERTISED_FIBRE | ADVERTISED_TP);
|
||||||
|
ecmd->port = PORT_FIBRE;
|
||||||
|
check_sfp_module = netif_running(dev) && ahw->has_link_events;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
dev_err(&adapter->pdev->dev, "Unsupported board model %d\n",
|
dev_err(&adapter->pdev->dev, "Unsupported board model %d\n",
|
||||||
adapter->ahw->board_type);
|
adapter->ahw->board_type);
|
||||||
|
@ -321,16 +392,10 @@ skip:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int qlcnic_set_port_config(struct qlcnic_adapter *adapter,
|
||||||
qlcnic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
|
struct ethtool_cmd *ecmd)
|
||||||
{
|
{
|
||||||
u32 config = 0;
|
u32 ret = 0, config = 0;
|
||||||
u32 ret = 0;
|
|
||||||
struct qlcnic_adapter *adapter = netdev_priv(dev);
|
|
||||||
|
|
||||||
if (adapter->ahw->port_type != QLCNIC_GBE)
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
|
|
||||||
/* read which mode */
|
/* read which mode */
|
||||||
if (ecmd->duplex)
|
if (ecmd->duplex)
|
||||||
config |= 0x1;
|
config |= 0x1;
|
||||||
|
@ -358,6 +423,24 @@ qlcnic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
else if (ret)
|
else if (ret)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int qlcnic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
|
||||||
|
{
|
||||||
|
u32 ret = 0;
|
||||||
|
struct qlcnic_adapter *adapter = netdev_priv(dev);
|
||||||
|
|
||||||
|
if (adapter->ahw->port_type != QLCNIC_GBE)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
if (qlcnic_83xx_check(adapter))
|
||||||
|
ret = qlcnic_83xx_set_settings(adapter, ecmd);
|
||||||
|
else
|
||||||
|
ret = qlcnic_set_port_config(adapter, ecmd);
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
adapter->ahw->link_speed = ethtool_cmd_speed(ecmd);
|
adapter->ahw->link_speed = ethtool_cmd_speed(ecmd);
|
||||||
adapter->ahw->link_duplex = ecmd->duplex;
|
adapter->ahw->link_duplex = ecmd->duplex;
|
||||||
|
@ -370,6 +453,19 @@ qlcnic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
|
||||||
return dev->netdev_ops->ndo_open(dev);
|
return dev->netdev_ops->ndo_open(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int qlcnic_82xx_get_registers(struct qlcnic_adapter *adapter,
|
||||||
|
u32 *regs_buff)
|
||||||
|
{
|
||||||
|
int i, j = 0;
|
||||||
|
|
||||||
|
for (i = QLCNIC_DEV_INFO_SIZE + 1; diag_registers[j] != -1; j++, i++)
|
||||||
|
regs_buff[i] = QLC_SHARED_REG_RD32(adapter, diag_registers[j]);
|
||||||
|
j = 0;
|
||||||
|
while (ext_diag_registers[j] != -1)
|
||||||
|
regs_buff[i++] = QLCRD32(adapter, ext_diag_registers[j++]);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
|
qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
|
||||||
{
|
{
|
||||||
|
@ -377,17 +473,20 @@ qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
|
||||||
struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
|
struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
|
||||||
struct qlcnic_host_sds_ring *sds_ring;
|
struct qlcnic_host_sds_ring *sds_ring;
|
||||||
u32 *regs_buff = p;
|
u32 *regs_buff = p;
|
||||||
int ring, i = 0, j = 0;
|
int ring, i = 0;
|
||||||
|
|
||||||
memset(p, 0, qlcnic_get_regs_len(dev));
|
memset(p, 0, qlcnic_get_regs_len(dev));
|
||||||
|
|
||||||
regs->version = (QLCNIC_ETHTOOL_REGS_VER << 24) |
|
regs->version = (QLCNIC_ETHTOOL_REGS_VER << 24) |
|
||||||
(adapter->ahw->revision_id << 16) | (adapter->pdev)->device;
|
(adapter->ahw->revision_id << 16) | (adapter->pdev)->device;
|
||||||
|
|
||||||
regs_buff[0] = (0xcafe0000 | (QLCNIC_DEV_INFO_SIZE & 0xffff));
|
regs_buff[0] = (0xcafe0000 | (QLCNIC_DEV_INFO_SIZE & 0xffff));
|
||||||
regs_buff[1] = QLCNIC_MGMT_API_VERSION;
|
regs_buff[1] = QLCNIC_MGMT_API_VERSION;
|
||||||
|
|
||||||
for (i = QLCNIC_DEV_INFO_SIZE + 1; diag_registers[j] != -1; j++, i++)
|
if (qlcnic_82xx_check(adapter))
|
||||||
regs_buff[i] = QLCRD32(adapter, diag_registers[j]);
|
i = qlcnic_82xx_get_registers(adapter, regs_buff);
|
||||||
|
else
|
||||||
|
i = qlcnic_83xx_get_registers(adapter, regs_buff);
|
||||||
|
|
||||||
if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
|
if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
|
||||||
return;
|
return;
|
||||||
|
@ -415,6 +514,10 @@ static u32 qlcnic_test_link(struct net_device *dev)
|
||||||
struct qlcnic_adapter *adapter = netdev_priv(dev);
|
struct qlcnic_adapter *adapter = netdev_priv(dev);
|
||||||
u32 val;
|
u32 val;
|
||||||
|
|
||||||
|
if (qlcnic_83xx_check(adapter)) {
|
||||||
|
val = qlcnic_83xx_test_link(adapter);
|
||||||
|
return (val & 1) ? 0 : 1;
|
||||||
|
}
|
||||||
val = QLCRD32(adapter, CRB_XG_STATE_P3P);
|
val = QLCRD32(adapter, CRB_XG_STATE_P3P);
|
||||||
val = XG_LINK_STATE_P3P(adapter->ahw->pci_func, val);
|
val = XG_LINK_STATE_P3P(adapter->ahw->pci_func, val);
|
||||||
return (val == XG_LINK_UP_P3P) ? 0 : 1;
|
return (val == XG_LINK_UP_P3P) ? 0 : 1;
|
||||||
|
@ -426,8 +529,10 @@ qlcnic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
|
||||||
{
|
{
|
||||||
struct qlcnic_adapter *adapter = netdev_priv(dev);
|
struct qlcnic_adapter *adapter = netdev_priv(dev);
|
||||||
int offset;
|
int offset;
|
||||||
int ret;
|
int ret = -1;
|
||||||
|
|
||||||
|
if (qlcnic_83xx_check(adapter))
|
||||||
|
return 0;
|
||||||
if (eeprom->len == 0)
|
if (eeprom->len == 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
@ -435,8 +540,9 @@ qlcnic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
|
||||||
((adapter->pdev)->device << 16);
|
((adapter->pdev)->device << 16);
|
||||||
offset = eeprom->offset;
|
offset = eeprom->offset;
|
||||||
|
|
||||||
ret = qlcnic_rom_fast_read_words(adapter, offset, bytes,
|
if (qlcnic_82xx_check(adapter))
|
||||||
eeprom->len);
|
ret = qlcnic_rom_fast_read_words(adapter, offset, bytes,
|
||||||
|
eeprom->len);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -547,6 +653,10 @@ qlcnic_get_pauseparam(struct net_device *netdev,
|
||||||
int port = adapter->ahw->physical_port;
|
int port = adapter->ahw->physical_port;
|
||||||
__u32 val;
|
__u32 val;
|
||||||
|
|
||||||
|
if (qlcnic_83xx_check(adapter)) {
|
||||||
|
qlcnic_83xx_get_pauseparam(adapter, pause);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (adapter->ahw->port_type == QLCNIC_GBE) {
|
if (adapter->ahw->port_type == QLCNIC_GBE) {
|
||||||
if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS))
|
if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS))
|
||||||
return;
|
return;
|
||||||
|
@ -592,6 +702,9 @@ qlcnic_set_pauseparam(struct net_device *netdev,
|
||||||
int port = adapter->ahw->physical_port;
|
int port = adapter->ahw->physical_port;
|
||||||
__u32 val;
|
__u32 val;
|
||||||
|
|
||||||
|
if (qlcnic_83xx_check(adapter))
|
||||||
|
return qlcnic_83xx_set_pauseparam(adapter, pause);
|
||||||
|
|
||||||
/* read mode */
|
/* read mode */
|
||||||
if (adapter->ahw->port_type == QLCNIC_GBE) {
|
if (adapter->ahw->port_type == QLCNIC_GBE) {
|
||||||
if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS))
|
if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS))
|
||||||
|
@ -606,6 +719,7 @@ qlcnic_set_pauseparam(struct net_device *netdev,
|
||||||
|
|
||||||
QLCWR32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port),
|
QLCWR32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port),
|
||||||
val);
|
val);
|
||||||
|
QLCWR32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port), val);
|
||||||
/* set autoneg */
|
/* set autoneg */
|
||||||
val = QLCRD32(adapter, QLCNIC_NIU_GB_PAUSE_CTL);
|
val = QLCRD32(adapter, QLCNIC_NIU_GB_PAUSE_CTL);
|
||||||
switch (port) {
|
switch (port) {
|
||||||
|
@ -668,6 +782,9 @@ static int qlcnic_reg_test(struct net_device *dev)
|
||||||
struct qlcnic_adapter *adapter = netdev_priv(dev);
|
struct qlcnic_adapter *adapter = netdev_priv(dev);
|
||||||
u32 data_read;
|
u32 data_read;
|
||||||
|
|
||||||
|
if (qlcnic_83xx_check(adapter))
|
||||||
|
return qlcnic_83xx_reg_test(adapter);
|
||||||
|
|
||||||
data_read = QLCRD32(adapter, QLCNIC_PCIX_PH_REG(0));
|
data_read = QLCRD32(adapter, QLCNIC_PCIX_PH_REG(0));
|
||||||
if ((data_read & 0xffff) != adapter->pdev->vendor)
|
if ((data_read & 0xffff) != adapter->pdev->vendor)
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -675,16 +792,30 @@ static int qlcnic_reg_test(struct net_device *dev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int qlcnic_eeprom_test(struct net_device *dev)
|
||||||
|
{
|
||||||
|
struct qlcnic_adapter *adapter = netdev_priv(dev);
|
||||||
|
|
||||||
|
if (qlcnic_82xx_check(adapter))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return qlcnic_83xx_flash_test(adapter);
|
||||||
|
}
|
||||||
|
|
||||||
static int qlcnic_get_sset_count(struct net_device *dev, int sset)
|
static int qlcnic_get_sset_count(struct net_device *dev, int sset)
|
||||||
{
|
{
|
||||||
|
int len;
|
||||||
|
|
||||||
struct qlcnic_adapter *adapter = netdev_priv(dev);
|
struct qlcnic_adapter *adapter = netdev_priv(dev);
|
||||||
switch (sset) {
|
switch (sset) {
|
||||||
case ETH_SS_TEST:
|
case ETH_SS_TEST:
|
||||||
return QLCNIC_TEST_LEN;
|
return QLCNIC_TEST_LEN;
|
||||||
case ETH_SS_STATS:
|
case ETH_SS_STATS:
|
||||||
if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
|
len = qlcnic_dev_statistics_len(adapter) + QLCNIC_STATS_LEN;
|
||||||
return QLCNIC_TOTAL_STATS_LEN + QLCNIC_DEVICE_STATS_LEN;
|
if ((adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
|
||||||
return QLCNIC_TOTAL_STATS_LEN;
|
qlcnic_83xx_check(adapter))
|
||||||
|
return len;
|
||||||
|
return qlcnic_82xx_statistics();
|
||||||
default:
|
default:
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
@ -707,8 +838,12 @@ static int qlcnic_irq_test(struct net_device *netdev)
|
||||||
adapter->ahw->diag_cnt = 0;
|
adapter->ahw->diag_cnt = 0;
|
||||||
qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_INTRPT_TEST);
|
qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_INTRPT_TEST);
|
||||||
|
|
||||||
cmd.req.arg[1] = adapter->ahw->pci_func;
|
if (qlcnic_83xx_check(adapter)) {
|
||||||
ret = qlcnic_issue_cmd(adapter, &cmd);
|
ret = qlcnic_83xx_interrupt_test(adapter, &cmd);
|
||||||
|
} else {
|
||||||
|
cmd.req.arg[1] = adapter->ahw->pci_func;
|
||||||
|
ret = qlcnic_issue_cmd(adapter, &cmd);
|
||||||
|
}
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -760,11 +895,10 @@ static int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode)
|
||||||
skb = netdev_alloc_skb(adapter->netdev, QLCNIC_ILB_PKT_SIZE);
|
skb = netdev_alloc_skb(adapter->netdev, QLCNIC_ILB_PKT_SIZE);
|
||||||
qlcnic_create_loopback_buff(skb->data, adapter->mac_addr);
|
qlcnic_create_loopback_buff(skb->data, adapter->mac_addr);
|
||||||
skb_put(skb, QLCNIC_ILB_PKT_SIZE);
|
skb_put(skb, QLCNIC_ILB_PKT_SIZE);
|
||||||
|
|
||||||
adapter->ahw->diag_cnt = 0;
|
adapter->ahw->diag_cnt = 0;
|
||||||
qlcnic_xmit_frame(skb, adapter->netdev);
|
qlcnic_xmit_frame(skb, adapter->netdev);
|
||||||
|
|
||||||
loop = 0;
|
loop = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
msleep(1);
|
msleep(1);
|
||||||
qlcnic_process_rcv_ring_diag(sds_ring);
|
qlcnic_process_rcv_ring_diag(sds_ring);
|
||||||
|
@ -775,18 +909,18 @@ static int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode)
|
||||||
dev_kfree_skb_any(skb);
|
dev_kfree_skb_any(skb);
|
||||||
|
|
||||||
if (!adapter->ahw->diag_cnt)
|
if (!adapter->ahw->diag_cnt)
|
||||||
QLCDB(adapter, DRV,
|
dev_warn(&adapter->pdev->dev,
|
||||||
"LB Test: packet #%d was not received\n", i + 1);
|
"LB Test: packet #%d was not received\n",
|
||||||
|
i + 1);
|
||||||
else
|
else
|
||||||
cnt++;
|
cnt++;
|
||||||
}
|
}
|
||||||
if (cnt != i) {
|
if (cnt != i) {
|
||||||
dev_warn(&adapter->pdev->dev, "LB Test failed\n");
|
dev_err(&adapter->pdev->dev,
|
||||||
if (mode != QLCNIC_ILB_MODE) {
|
"LB Test: failed, TX[%d], RX[%d]\n", i, cnt);
|
||||||
|
if (mode != QLCNIC_ILB_MODE)
|
||||||
dev_warn(&adapter->pdev->dev,
|
dev_warn(&adapter->pdev->dev,
|
||||||
"WARNING: Please make sure external"
|
"WARNING: Please check loopback cable\n");
|
||||||
"loopback connector is plugged in\n");
|
|
||||||
}
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -797,20 +931,23 @@ static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
|
||||||
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
||||||
int max_sds_rings = adapter->max_sds_rings;
|
int max_sds_rings = adapter->max_sds_rings;
|
||||||
struct qlcnic_host_sds_ring *sds_ring;
|
struct qlcnic_host_sds_ring *sds_ring;
|
||||||
|
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
||||||
int loop = 0;
|
int loop = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!(adapter->ahw->capabilities &
|
if (qlcnic_83xx_check(adapter))
|
||||||
QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK)) {
|
goto skip_cap;
|
||||||
netdev_info(netdev, "Firmware is not loopback test capable\n");
|
if (!(ahw->capabilities & QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK)) {
|
||||||
|
dev_info(&adapter->pdev->dev,
|
||||||
|
"Firmware do not support loopback test\n");
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
skip_cap:
|
||||||
QLCDB(adapter, DRV, "%s loopback test in progress\n",
|
dev_warn(&adapter->pdev->dev, "%s loopback test in progress\n",
|
||||||
mode == QLCNIC_ILB_MODE ? "internal" : "external");
|
mode == QLCNIC_ILB_MODE ? "internal" : "external");
|
||||||
if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
|
if (ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
|
||||||
netdev_warn(netdev, "Loopback test not supported for non "
|
dev_warn(&adapter->pdev->dev,
|
||||||
"privilege function\n");
|
"Loopback test not supported in nonprivileged mode\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -822,12 +959,14 @@ static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
|
||||||
goto clear_it;
|
goto clear_it;
|
||||||
|
|
||||||
sds_ring = &adapter->recv_ctx->sds_rings[0];
|
sds_ring = &adapter->recv_ctx->sds_rings[0];
|
||||||
|
|
||||||
ret = qlcnic_set_lb_mode(adapter, mode);
|
ret = qlcnic_set_lb_mode(adapter, mode);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto free_res;
|
goto free_res;
|
||||||
|
|
||||||
adapter->ahw->diag_cnt = 0;
|
if (qlcnic_83xx_check(adapter))
|
||||||
|
goto skip_fw_msg;
|
||||||
|
|
||||||
|
ahw->diag_cnt = 0;
|
||||||
do {
|
do {
|
||||||
msleep(500);
|
msleep(500);
|
||||||
qlcnic_process_rcv_ring_diag(sds_ring);
|
qlcnic_process_rcv_ring_diag(sds_ring);
|
||||||
|
@ -840,10 +979,22 @@ static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
|
||||||
ret = adapter->ahw->diag_cnt;
|
ret = adapter->ahw->diag_cnt;
|
||||||
goto free_res;
|
goto free_res;
|
||||||
}
|
}
|
||||||
} while (!QLCNIC_IS_LB_CONFIGURED(adapter->ahw->loopback_state));
|
} while (!QLCNIC_IS_LB_CONFIGURED(ahw->loopback_state));
|
||||||
|
skip_fw_msg:
|
||||||
|
if (qlcnic_83xx_check(adapter)) {
|
||||||
|
/* wait until firmware report link up before running traffic */
|
||||||
|
loop = 0;
|
||||||
|
do {
|
||||||
|
msleep(500);
|
||||||
|
if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) {
|
||||||
|
dev_info(&adapter->pdev->dev,
|
||||||
|
"No linkup event after LB req\n");
|
||||||
|
ret = -QLCNIC_FW_NOT_RESPOND;
|
||||||
|
goto free_res;
|
||||||
|
}
|
||||||
|
} while ((adapter->ahw->linkup && ahw->has_link_events) != 1);
|
||||||
|
}
|
||||||
ret = qlcnic_do_lb_test(adapter, mode);
|
ret = qlcnic_do_lb_test(adapter, mode);
|
||||||
|
|
||||||
qlcnic_clear_lb_mode(adapter, mode);
|
qlcnic_clear_lb_mode(adapter, mode);
|
||||||
|
|
||||||
free_res:
|
free_res:
|
||||||
|
@ -877,20 +1028,18 @@ qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
|
||||||
data[3] = qlcnic_loopback_test(dev, QLCNIC_ILB_MODE);
|
data[3] = qlcnic_loopback_test(dev, QLCNIC_ILB_MODE);
|
||||||
if (data[3])
|
if (data[3])
|
||||||
eth_test->flags |= ETH_TEST_FL_FAILED;
|
eth_test->flags |= ETH_TEST_FL_FAILED;
|
||||||
if (eth_test->flags & ETH_TEST_FL_EXTERNAL_LB) {
|
|
||||||
data[4] = qlcnic_loopback_test(dev, QLCNIC_ELB_MODE);
|
data[4] = qlcnic_eeprom_test(dev);
|
||||||
if (data[4])
|
if (data[4])
|
||||||
eth_test->flags |= ETH_TEST_FL_FAILED;
|
eth_test->flags |= ETH_TEST_FL_FAILED;
|
||||||
eth_test->flags |= ETH_TEST_FL_EXTERNAL_LB_DONE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
|
qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 *data)
|
||||||
{
|
{
|
||||||
struct qlcnic_adapter *adapter = netdev_priv(dev);
|
struct qlcnic_adapter *adapter = netdev_priv(dev);
|
||||||
int index, i, j;
|
int index, i, num_stats;
|
||||||
|
|
||||||
switch (stringset) {
|
switch (stringset) {
|
||||||
case ETH_SS_TEST:
|
case ETH_SS_TEST:
|
||||||
|
@ -903,14 +1052,34 @@ qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
|
||||||
qlcnic_gstrings_stats[index].stat_string,
|
qlcnic_gstrings_stats[index].stat_string,
|
||||||
ETH_GSTRING_LEN);
|
ETH_GSTRING_LEN);
|
||||||
}
|
}
|
||||||
for (j = 0; j < QLCNIC_MAC_STATS_LEN; index++, j++) {
|
if (qlcnic_83xx_check(adapter)) {
|
||||||
memcpy(data + index * ETH_GSTRING_LEN,
|
num_stats = ARRAY_SIZE(qlcnic_83xx_tx_stats_strings);
|
||||||
qlcnic_mac_stats_strings[j],
|
for (i = 0; i < num_stats; i++, index++)
|
||||||
ETH_GSTRING_LEN);
|
memcpy(data + index * ETH_GSTRING_LEN,
|
||||||
|
qlcnic_83xx_tx_stats_strings[i],
|
||||||
|
ETH_GSTRING_LEN);
|
||||||
|
num_stats = ARRAY_SIZE(qlcnic_83xx_mac_stats_strings);
|
||||||
|
for (i = 0; i < num_stats; i++, index++)
|
||||||
|
memcpy(data + index * ETH_GSTRING_LEN,
|
||||||
|
qlcnic_83xx_mac_stats_strings[i],
|
||||||
|
ETH_GSTRING_LEN);
|
||||||
|
num_stats = ARRAY_SIZE(qlcnic_83xx_rx_stats_strings);
|
||||||
|
for (i = 0; i < num_stats; i++, index++)
|
||||||
|
memcpy(data + index * ETH_GSTRING_LEN,
|
||||||
|
qlcnic_83xx_rx_stats_strings[i],
|
||||||
|
ETH_GSTRING_LEN);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
num_stats = ARRAY_SIZE(qlcnic_83xx_mac_stats_strings);
|
||||||
|
for (i = 0; i < num_stats; i++, index++)
|
||||||
|
memcpy(data + index * ETH_GSTRING_LEN,
|
||||||
|
qlcnic_83xx_mac_stats_strings[i],
|
||||||
|
ETH_GSTRING_LEN);
|
||||||
}
|
}
|
||||||
if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
|
if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
|
||||||
return;
|
return;
|
||||||
for (i = 0; i < QLCNIC_DEVICE_STATS_LEN; index++, i++) {
|
num_stats = ARRAY_SIZE(qlcnic_device_gstrings_stats);
|
||||||
|
for (i = 0; i < num_stats; index++, i++) {
|
||||||
memcpy(data + index * ETH_GSTRING_LEN,
|
memcpy(data + index * ETH_GSTRING_LEN,
|
||||||
qlcnic_device_gstrings_stats[i],
|
qlcnic_device_gstrings_stats[i],
|
||||||
ETH_GSTRING_LEN);
|
ETH_GSTRING_LEN);
|
||||||
|
@ -919,89 +1088,84 @@ qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
qlcnic_fill_stats(int *index, u64 *data, void *stats, int type)
|
qlcnic_fill_stats(u64 *data, void *stats, int type)
|
||||||
{
|
{
|
||||||
int ind = *index;
|
|
||||||
|
|
||||||
if (type == QLCNIC_MAC_STATS) {
|
if (type == QLCNIC_MAC_STATS) {
|
||||||
struct qlcnic_mac_statistics *mac_stats =
|
struct qlcnic_mac_statistics *mac_stats =
|
||||||
(struct qlcnic_mac_statistics *)stats;
|
(struct qlcnic_mac_statistics *)stats;
|
||||||
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_frames);
|
*data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_frames);
|
||||||
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_bytes);
|
*data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_bytes);
|
||||||
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_mcast_pkts);
|
*data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_mcast_pkts);
|
||||||
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_bcast_pkts);
|
*data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_bcast_pkts);
|
||||||
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_pause_cnt);
|
*data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_pause_cnt);
|
||||||
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_ctrl_pkt);
|
*data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_ctrl_pkt);
|
||||||
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_64b_pkts);
|
*data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_64b_pkts);
|
||||||
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_127b_pkts);
|
*data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_127b_pkts);
|
||||||
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_255b_pkts);
|
*data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_255b_pkts);
|
||||||
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_511b_pkts);
|
*data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_511b_pkts);
|
||||||
data[ind++] =
|
*data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_1023b_pkts);
|
||||||
QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_1023b_pkts);
|
*data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_1518b_pkts);
|
||||||
data[ind++] =
|
*data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_gt_1518b_pkts);
|
||||||
QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_1518b_pkts);
|
*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_frames);
|
||||||
data[ind++] =
|
*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_bytes);
|
||||||
QLCNIC_FILL_STATS(mac_stats->mac_tx_gt_1518b_pkts);
|
*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_mcast_pkts);
|
||||||
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_frames);
|
*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_bcast_pkts);
|
||||||
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_bytes);
|
*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_pause_cnt);
|
||||||
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_mcast_pkts);
|
*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_ctrl_pkt);
|
||||||
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_bcast_pkts);
|
*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_64b_pkts);
|
||||||
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_pause_cnt);
|
*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_127b_pkts);
|
||||||
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_ctrl_pkt);
|
*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_255b_pkts);
|
||||||
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_64b_pkts);
|
*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_511b_pkts);
|
||||||
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_127b_pkts);
|
*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_1023b_pkts);
|
||||||
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_255b_pkts);
|
*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_1518b_pkts);
|
||||||
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_511b_pkts);
|
*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_gt_1518b_pkts);
|
||||||
data[ind++] =
|
*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_error);
|
||||||
QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_1023b_pkts);
|
*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_small);
|
||||||
data[ind++] =
|
*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_large);
|
||||||
QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_1518b_pkts);
|
*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_jabber);
|
||||||
data[ind++] =
|
*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_dropped);
|
||||||
QLCNIC_FILL_STATS(mac_stats->mac_rx_gt_1518b_pkts);
|
*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_crc_error);
|
||||||
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_error);
|
*data++ = QLCNIC_FILL_STATS(mac_stats->mac_align_error);
|
||||||
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_small);
|
|
||||||
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_large);
|
|
||||||
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_jabber);
|
|
||||||
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_dropped);
|
|
||||||
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_crc_error);
|
|
||||||
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_align_error);
|
|
||||||
} else if (type == QLCNIC_ESW_STATS) {
|
} else if (type == QLCNIC_ESW_STATS) {
|
||||||
struct __qlcnic_esw_statistics *esw_stats =
|
struct __qlcnic_esw_statistics *esw_stats =
|
||||||
(struct __qlcnic_esw_statistics *)stats;
|
(struct __qlcnic_esw_statistics *)stats;
|
||||||
data[ind++] = QLCNIC_FILL_STATS(esw_stats->unicast_frames);
|
*data++ = QLCNIC_FILL_STATS(esw_stats->unicast_frames);
|
||||||
data[ind++] = QLCNIC_FILL_STATS(esw_stats->multicast_frames);
|
*data++ = QLCNIC_FILL_STATS(esw_stats->multicast_frames);
|
||||||
data[ind++] = QLCNIC_FILL_STATS(esw_stats->broadcast_frames);
|
*data++ = QLCNIC_FILL_STATS(esw_stats->broadcast_frames);
|
||||||
data[ind++] = QLCNIC_FILL_STATS(esw_stats->dropped_frames);
|
*data++ = QLCNIC_FILL_STATS(esw_stats->dropped_frames);
|
||||||
data[ind++] = QLCNIC_FILL_STATS(esw_stats->errors);
|
*data++ = QLCNIC_FILL_STATS(esw_stats->errors);
|
||||||
data[ind++] = QLCNIC_FILL_STATS(esw_stats->local_frames);
|
*data++ = QLCNIC_FILL_STATS(esw_stats->local_frames);
|
||||||
data[ind++] = QLCNIC_FILL_STATS(esw_stats->numbytes);
|
*data++ = QLCNIC_FILL_STATS(esw_stats->numbytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
*index = ind;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void qlcnic_get_ethtool_stats(struct net_device *dev,
|
||||||
qlcnic_get_ethtool_stats(struct net_device *dev,
|
struct ethtool_stats *stats, u64 *data)
|
||||||
struct ethtool_stats *stats, u64 * data)
|
|
||||||
{
|
{
|
||||||
struct qlcnic_adapter *adapter = netdev_priv(dev);
|
struct qlcnic_adapter *adapter = netdev_priv(dev);
|
||||||
struct qlcnic_esw_statistics port_stats;
|
struct qlcnic_esw_statistics port_stats;
|
||||||
struct qlcnic_mac_statistics mac_stats;
|
struct qlcnic_mac_statistics mac_stats;
|
||||||
int index, ret;
|
int index, ret, length, size;
|
||||||
|
char *p;
|
||||||
|
|
||||||
for (index = 0; index < QLCNIC_STATS_LEN; index++) {
|
memset(data, 0, stats->n_stats * sizeof(u64));
|
||||||
char *p =
|
length = QLCNIC_STATS_LEN;
|
||||||
(char *)adapter +
|
for (index = 0; index < length; index++) {
|
||||||
qlcnic_gstrings_stats[index].stat_offset;
|
p = (char *)adapter + qlcnic_gstrings_stats[index].stat_offset;
|
||||||
data[index] =
|
size = qlcnic_gstrings_stats[index].sizeof_stat;
|
||||||
(qlcnic_gstrings_stats[index].sizeof_stat ==
|
*data++ = (size == sizeof(u64)) ? (*(u64 *)p) : ((*(u32 *)p));
|
||||||
sizeof(u64)) ? *(u64 *)p:(*(u32 *)p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Retrieve MAC statistics from firmware */
|
if (qlcnic_83xx_check(adapter)) {
|
||||||
memset(&mac_stats, 0, sizeof(struct qlcnic_mac_statistics));
|
if (adapter->ahw->linkup)
|
||||||
qlcnic_get_mac_stats(adapter, &mac_stats);
|
qlcnic_83xx_get_stats(adapter, data);
|
||||||
qlcnic_fill_stats(&index, data, &mac_stats, QLCNIC_MAC_STATS);
|
return;
|
||||||
|
} else {
|
||||||
|
/* Retrieve MAC statistics from firmware */
|
||||||
|
memset(&mac_stats, 0, sizeof(struct qlcnic_mac_statistics));
|
||||||
|
qlcnic_get_mac_stats(adapter, &mac_stats);
|
||||||
|
qlcnic_fill_stats(data, &mac_stats, QLCNIC_MAC_STATS);
|
||||||
|
}
|
||||||
|
|
||||||
if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
|
if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
|
||||||
return;
|
return;
|
||||||
|
@ -1012,14 +1176,13 @@ qlcnic_get_ethtool_stats(struct net_device *dev,
|
||||||
if (ret)
|
if (ret)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
qlcnic_fill_stats(&index, data, &port_stats.rx, QLCNIC_ESW_STATS);
|
qlcnic_fill_stats(data, &port_stats.rx, QLCNIC_ESW_STATS);
|
||||||
|
|
||||||
ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func,
|
ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func,
|
||||||
QLCNIC_QUERY_TX_COUNTER, &port_stats.tx);
|
QLCNIC_QUERY_TX_COUNTER, &port_stats.tx);
|
||||||
if (ret)
|
if (ret)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
qlcnic_fill_stats(&index, data, &port_stats.tx, QLCNIC_ESW_STATS);
|
qlcnic_fill_stats(data, &port_stats.tx, QLCNIC_ESW_STATS);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int qlcnic_set_led(struct net_device *dev,
|
static int qlcnic_set_led(struct net_device *dev,
|
||||||
|
@ -1029,6 +1192,8 @@ static int qlcnic_set_led(struct net_device *dev,
|
||||||
int max_sds_rings = adapter->max_sds_rings;
|
int max_sds_rings = adapter->max_sds_rings;
|
||||||
int err = -EIO, active = 1;
|
int err = -EIO, active = 1;
|
||||||
|
|
||||||
|
if (qlcnic_83xx_check(adapter))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
|
if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
|
||||||
netdev_warn(dev, "LED test not supported for non "
|
netdev_warn(dev, "LED test not supported for non "
|
||||||
"privilege function\n");
|
"privilege function\n");
|
||||||
|
@ -1095,6 +1260,8 @@ qlcnic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
|
||||||
struct qlcnic_adapter *adapter = netdev_priv(dev);
|
struct qlcnic_adapter *adapter = netdev_priv(dev);
|
||||||
u32 wol_cfg;
|
u32 wol_cfg;
|
||||||
|
|
||||||
|
if (qlcnic_83xx_check(adapter))
|
||||||
|
return;
|
||||||
wol->supported = 0;
|
wol->supported = 0;
|
||||||
wol->wolopts = 0;
|
wol->wolopts = 0;
|
||||||
|
|
||||||
|
@ -1113,8 +1280,10 @@ qlcnic_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
|
||||||
struct qlcnic_adapter *adapter = netdev_priv(dev);
|
struct qlcnic_adapter *adapter = netdev_priv(dev);
|
||||||
u32 wol_cfg;
|
u32 wol_cfg;
|
||||||
|
|
||||||
if (wol->wolopts & ~WAKE_MAGIC)
|
if (qlcnic_83xx_check(adapter))
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
if (wol->wolopts & ~WAKE_MAGIC)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV);
|
wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV);
|
||||||
if (!(wol_cfg & (1 << adapter->portnum)))
|
if (!(wol_cfg & (1 << adapter->portnum)))
|
||||||
|
@ -1306,7 +1475,7 @@ qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
netdev_info(netdev, "Forcing a FW dump\n");
|
netdev_info(netdev, "Forcing a FW dump\n");
|
||||||
qlcnic_dev_request_reset(adapter, 0);
|
qlcnic_dev_request_reset(adapter, val->flag);
|
||||||
break;
|
break;
|
||||||
case QLCNIC_DISABLE_FW_DUMP:
|
case QLCNIC_DISABLE_FW_DUMP:
|
||||||
if (fw_dump->enable && fw_dump->tmpl_hdr) {
|
if (fw_dump->enable && fw_dump->tmpl_hdr) {
|
||||||
|
@ -1326,7 +1495,7 @@ qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val)
|
||||||
return 0;
|
return 0;
|
||||||
case QLCNIC_FORCE_FW_RESET:
|
case QLCNIC_FORCE_FW_RESET:
|
||||||
netdev_info(netdev, "Forcing a FW reset\n");
|
netdev_info(netdev, "Forcing a FW reset\n");
|
||||||
qlcnic_dev_request_reset(adapter, 0);
|
qlcnic_dev_request_reset(adapter, val->flag);
|
||||||
adapter->flags &= ~QLCNIC_FW_RESET_OWNER;
|
adapter->flags &= ~QLCNIC_FW_RESET_OWNER;
|
||||||
return 0;
|
return 0;
|
||||||
case QLCNIC_SET_QUIESCENT:
|
case QLCNIC_SET_QUIESCENT:
|
||||||
|
@ -1340,8 +1509,8 @@ qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val)
|
||||||
netdev_err(netdev, "FW dump not supported\n");
|
netdev_err(netdev, "FW dump not supported\n");
|
||||||
return -ENOTSUPP;
|
return -ENOTSUPP;
|
||||||
}
|
}
|
||||||
for (i = 0; i < ARRAY_SIZE(FW_DUMP_LEVELS); i++) {
|
for (i = 0; i < ARRAY_SIZE(qlcnic_fw_dump_level); i++) {
|
||||||
if (val->flag == FW_DUMP_LEVELS[i]) {
|
if (val->flag == qlcnic_fw_dump_level[i]) {
|
||||||
fw_dump->tmpl_hdr->drv_cap_mask =
|
fw_dump->tmpl_hdr->drv_cap_mask =
|
||||||
val->flag;
|
val->flag;
|
||||||
netdev_info(netdev, "Driver mask changed to: 0x%x\n",
|
netdev_info(netdev, "Driver mask changed to: 0x%x\n",
|
||||||
|
@ -1385,10 +1554,3 @@ const struct ethtool_ops qlcnic_ethtool_ops = {
|
||||||
.get_dump_data = qlcnic_get_dump_data,
|
.get_dump_data = qlcnic_get_dump_data,
|
||||||
.set_dump = qlcnic_set_dump,
|
.set_dump = qlcnic_set_dump,
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct ethtool_ops qlcnic_ethtool_failed_ops = {
|
|
||||||
.get_settings = qlcnic_get_settings,
|
|
||||||
.get_drvinfo = qlcnic_get_drvinfo,
|
|
||||||
.set_msglevel = qlcnic_set_msglevel,
|
|
||||||
.get_msglevel = qlcnic_get_msglevel,
|
|
||||||
};
|
|
||||||
|
|
|
@ -909,7 +909,7 @@ int qlcnic_set_features(struct net_device *netdev, netdev_features_t features)
|
||||||
if (!(changed & NETIF_F_LRO))
|
if (!(changed & NETIF_F_LRO))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
netdev->features = features ^ NETIF_F_LRO;
|
netdev->features ^= NETIF_F_LRO;
|
||||||
|
|
||||||
if (qlcnic_config_hw_lro(adapter, hw_lro))
|
if (qlcnic_config_hw_lro(adapter, hw_lro))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
|
@ -878,8 +878,8 @@ qlcnic_set_netdev_features(struct qlcnic_adapter *adapter,
|
||||||
if (qlcnic_83xx_check(adapter))
|
if (qlcnic_83xx_check(adapter))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
features = (NETIF_F_SG | NETIF_F_IP_CSUM |
|
features = (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
|
||||||
NETIF_F_IPV6_CSUM | NETIF_F_GRO);
|
NETIF_F_IPV6_CSUM | NETIF_F_GRO);
|
||||||
vlan_features = (NETIF_F_SG | NETIF_F_IP_CSUM |
|
vlan_features = (NETIF_F_SG | NETIF_F_IP_CSUM |
|
||||||
NETIF_F_IPV6_CSUM);
|
NETIF_F_IPV6_CSUM);
|
||||||
|
|
||||||
|
@ -894,12 +894,17 @@ qlcnic_set_netdev_features(struct qlcnic_adapter *adapter,
|
||||||
if (esw_cfg->offload_flags & BIT_0) {
|
if (esw_cfg->offload_flags & BIT_0) {
|
||||||
netdev->features |= features;
|
netdev->features |= features;
|
||||||
adapter->rx_csum = 1;
|
adapter->rx_csum = 1;
|
||||||
if (!(esw_cfg->offload_flags & BIT_1))
|
if (!(esw_cfg->offload_flags & BIT_1)) {
|
||||||
netdev->features &= ~NETIF_F_TSO;
|
netdev->features &= ~NETIF_F_TSO;
|
||||||
if (!(esw_cfg->offload_flags & BIT_2))
|
features &= ~NETIF_F_TSO;
|
||||||
|
}
|
||||||
|
if (!(esw_cfg->offload_flags & BIT_2)) {
|
||||||
netdev->features &= ~NETIF_F_TSO6;
|
netdev->features &= ~NETIF_F_TSO6;
|
||||||
|
features &= ~NETIF_F_TSO6;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
netdev->features &= ~features;
|
netdev->features &= ~features;
|
||||||
|
features &= ~features;
|
||||||
adapter->rx_csum = 0;
|
adapter->rx_csum = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1518,7 +1523,10 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
|
||||||
if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
|
if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
|
||||||
for (ring = 0; ring < adapter->max_sds_rings; ring++) {
|
for (ring = 0; ring < adapter->max_sds_rings; ring++) {
|
||||||
sds_ring = &adapter->recv_ctx->sds_rings[ring];
|
sds_ring = &adapter->recv_ctx->sds_rings[ring];
|
||||||
qlcnic_enable_int(sds_ring);
|
if (qlcnic_82xx_check(adapter))
|
||||||
|
qlcnic_enable_int(sds_ring);
|
||||||
|
else
|
||||||
|
qlcnic_83xx_enable_intr(adapter, sds_ring);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1605,7 +1613,7 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev,
|
||||||
|
|
||||||
SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_ops);
|
SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_ops);
|
||||||
|
|
||||||
netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM |
|
netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
|
||||||
NETIF_F_IPV6_CSUM | NETIF_F_GRO |
|
NETIF_F_IPV6_CSUM | NETIF_F_GRO |
|
||||||
NETIF_F_HW_VLAN_RX);
|
NETIF_F_HW_VLAN_RX);
|
||||||
netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM |
|
netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM |
|
||||||
|
@ -1627,6 +1635,7 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev,
|
||||||
if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
|
if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
|
||||||
netdev->features |= NETIF_F_LRO;
|
netdev->features |= NETIF_F_LRO;
|
||||||
|
|
||||||
|
netdev->hw_features = netdev->features;
|
||||||
netdev->irq = adapter->msix_entries[0].vector;
|
netdev->irq = adapter->msix_entries[0].vector;
|
||||||
|
|
||||||
err = register_netdev(netdev);
|
err = register_netdev(netdev);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче