Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 351259
b: refs/heads/master
c: 7e38d04
h: refs/heads/master
i:
  351257: 8fb1b4f
  351255: 2f4d0f0
v: v3
  • Loading branch information
Sony Chacko authored and David S. Miller committed Jan 2, 2013
1 parent 7605cf3 commit 969a533
Show file tree
Hide file tree
Showing 7 changed files with 751 additions and 194 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 4e60ac46414b2815d6e37e76fe6e3fb6dc4843c7
refs/heads/master: 7e38d04bcb405e3cbba15132cecadd2e9c571fdf
2 changes: 2 additions & 0 deletions trunk/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ struct qlcnic_rx_buffer {

#define QLCNIC_INTR_DEFAULT 0x04
#define QLCNIC_CONFIG_INTR_COALESCE 3
#define QLCNIC_DEV_INFO_SIZE 1

struct qlcnic_nic_intr_coalesce {
u8 type;
Expand Down Expand Up @@ -942,6 +943,7 @@ struct qlcnic_ipaddr {
#define __QLCNIC_AER 5
#define __QLCNIC_DIAG_RES_ALLOC 6
#define __QLCNIC_LED_ENABLE 7
#define __QLCNIC_ELB_INPROGRESS 8

#define QLCNIC_INTERRUPT_TEST 1
#define QLCNIC_LOOPBACK_TEST 2
Expand Down
372 changes: 372 additions & 0 deletions trunk/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -2383,3 +2383,375 @@ int qlcnic_83xx_flash_read32(struct qlcnic_adapter *adapter, u32 flash_addr,

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;
}
Loading

0 comments on commit 969a533

Please sign in to comment.