Skip to content

Commit

Permalink
Merge branch 'qlcnic'
Browse files Browse the repository at this point in the history
Shahed Shaikh says:

====================
This patch series has following bug fixes:
* Fix a bug in unicast MAC address setting in adapter.
  Driver was not deleting older unicast MAC while adding new one.
* Fix an ethtool stats string array by adding missing string entry
  and fix a typo.
* Fix module paramter description. Bracket ')' was missing.
* Fix port status provided though 'ethtool <device>' for 83xx adapter.
* Fix reset recovery path in case of transmit timeout.
* Fix reset recovery during diagnostic tests by preserving
  current device status information.
* Fix mailbox response handling. Driver was not maintaining poll time properly.
* Fix validation of link event command.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed May 11, 2013
2 parents 61f1598 + cbccb18 commit 1e9e990
Show file tree
Hide file tree
Showing 9 changed files with 167 additions and 69 deletions.
2 changes: 2 additions & 0 deletions drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,7 @@ struct qlcnic_hardware_context {

u16 port_type;
u16 board_type;
u16 supported_type;

u16 link_speed;
u16 link_duplex;
Expand Down Expand Up @@ -1514,6 +1515,7 @@ void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter);
void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter);
void qlcnic_82xx_add_sysfs(struct qlcnic_adapter *adapter);
void qlcnic_82xx_remove_sysfs(struct qlcnic_adapter *adapter);
int qlcnic_82xx_get_settings(struct qlcnic_adapter *, struct ethtool_cmd *);

int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32);
int qlcnicvf_config_led(struct qlcnic_adapter *, u32, u32);
Expand Down
95 changes: 83 additions & 12 deletions drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -696,15 +696,14 @@ u32 qlcnic_83xx_mac_rcode(struct qlcnic_adapter *adapter)
return 1;
}

u32 qlcnic_83xx_mbx_poll(struct qlcnic_adapter *adapter)
u32 qlcnic_83xx_mbx_poll(struct qlcnic_adapter *adapter, u32 *wait_time)
{
u32 data;
unsigned long wait_time = 0;
struct qlcnic_hardware_context *ahw = adapter->ahw;
/* wait for mailbox completion */
do {
data = QLCRDX(ahw, QLCNIC_FW_MBX_CTRL);
if (++wait_time > QLCNIC_MBX_TIMEOUT) {
if (++(*wait_time) > QLCNIC_MBX_TIMEOUT) {
data = QLCNIC_RCODE_TIMEOUT;
break;
}
Expand All @@ -720,8 +719,8 @@ int qlcnic_83xx_mbx_op(struct qlcnic_adapter *adapter,
u16 opcode;
u8 mbx_err_code;
unsigned long flags;
u32 rsp, mbx_val, fw_data, rsp_num, mbx_cmd;
struct qlcnic_hardware_context *ahw = adapter->ahw;
u32 rsp, mbx_val, fw_data, rsp_num, mbx_cmd, wait_time = 0;

opcode = LSW(cmd->req.arg[0]);
if (!test_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status)) {
Expand Down Expand Up @@ -754,15 +753,13 @@ int qlcnic_83xx_mbx_op(struct qlcnic_adapter *adapter,
/* Signal FW about the impending command */
QLCWRX(ahw, QLCNIC_HOST_MBX_CTRL, QLCNIC_SET_OWNER);
poll:
rsp = qlcnic_83xx_mbx_poll(adapter);
rsp = qlcnic_83xx_mbx_poll(adapter, &wait_time);
if (rsp != QLCNIC_RCODE_TIMEOUT) {
/* Get the FW response data */
fw_data = readl(QLCNIC_MBX_FW(ahw, 0));
if (fw_data & QLCNIC_MBX_ASYNC_EVENT) {
__qlcnic_83xx_process_aen(adapter);
mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL);
if (mbx_val)
goto poll;
goto poll;
}
mbx_err_code = QLCNIC_MBX_STATUS(fw_data);
rsp_num = QLCNIC_MBX_NUM_REGS(fw_data);
Expand Down Expand Up @@ -1276,11 +1273,13 @@ int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter,
return err;
}

static int qlcnic_83xx_diag_alloc_res(struct net_device *netdev, int test)
static int qlcnic_83xx_diag_alloc_res(struct net_device *netdev, int test,
int num_sds_ring)
{
struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct qlcnic_host_sds_ring *sds_ring;
struct qlcnic_host_rds_ring *rds_ring;
u16 adapter_state = adapter->is_up;
u8 ring;
int ret;

Expand All @@ -1304,6 +1303,10 @@ static int qlcnic_83xx_diag_alloc_res(struct net_device *netdev, int test)
ret = qlcnic_fw_create_ctx(adapter);
if (ret) {
qlcnic_detach(adapter);
if (adapter_state == QLCNIC_ADAPTER_UP_MAGIC) {
adapter->max_sds_rings = num_sds_ring;
qlcnic_attach(adapter);
}
netif_device_attach(netdev);
return ret;
}
Expand Down Expand Up @@ -1596,7 +1599,8 @@ int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode)
if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
return -EBUSY;

ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST);
ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST,
max_sds_rings);
if (ret)
goto fail_diag_alloc;

Expand Down Expand Up @@ -2830,6 +2834,23 @@ int qlcnic_83xx_test_link(struct qlcnic_adapter *adapter)
break;
}
config = cmd.rsp.arg[3];
if (QLC_83XX_SFP_PRESENT(config)) {
switch (ahw->module_type) {
case LINKEVENT_MODULE_OPTICAL_UNKNOWN:
case LINKEVENT_MODULE_OPTICAL_SRLR:
case LINKEVENT_MODULE_OPTICAL_LRM:
case LINKEVENT_MODULE_OPTICAL_SFP_1G:
ahw->supported_type = PORT_FIBRE;
break;
case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE:
case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN:
case LINKEVENT_MODULE_TWINAX:
ahw->supported_type = PORT_TP;
break;
default:
ahw->supported_type = PORT_OTHER;
}
}
if (config & 1)
err = 1;
}
Expand All @@ -2838,7 +2859,8 @@ int qlcnic_83xx_test_link(struct qlcnic_adapter *adapter)
return config;
}

int qlcnic_83xx_get_settings(struct qlcnic_adapter *adapter)
int qlcnic_83xx_get_settings(struct qlcnic_adapter *adapter,
struct ethtool_cmd *ecmd)
{
u32 config = 0;
int status = 0;
Expand All @@ -2851,6 +2873,54 @@ int qlcnic_83xx_get_settings(struct qlcnic_adapter *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;

if (netif_running(adapter->netdev) && ahw->has_link_events) {
ethtool_cmd_speed_set(ecmd, ahw->link_speed);
ecmd->duplex = ahw->link_duplex;
ecmd->autoneg = ahw->link_autoneg;
} else {
ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN);
ecmd->duplex = DUPLEX_UNKNOWN;
ecmd->autoneg = AUTONEG_DISABLE;
}

if (ahw->port_type == QLCNIC_XGBE) {
ecmd->supported = SUPPORTED_1000baseT_Full;
ecmd->advertising = ADVERTISED_1000baseT_Full;
} else {
ecmd->supported = (SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Half |
SUPPORTED_100baseT_Full |
SUPPORTED_1000baseT_Half |
SUPPORTED_1000baseT_Full);
ecmd->advertising = (ADVERTISED_100baseT_Half |
ADVERTISED_100baseT_Full |
ADVERTISED_1000baseT_Half |
ADVERTISED_1000baseT_Full);
}

switch (ahw->supported_type) {
case PORT_FIBRE:
ecmd->supported |= SUPPORTED_FIBRE;
ecmd->advertising |= ADVERTISED_FIBRE;
ecmd->port = PORT_FIBRE;
ecmd->transceiver = XCVR_EXTERNAL;
break;
case PORT_TP:
ecmd->supported |= SUPPORTED_TP;
ecmd->advertising |= ADVERTISED_TP;
ecmd->port = PORT_TP;
ecmd->transceiver = XCVR_INTERNAL;
break;
default:
ecmd->supported |= SUPPORTED_FIBRE;
ecmd->advertising |= ADVERTISED_FIBRE;
ecmd->port = PORT_OTHER;
ecmd->transceiver = XCVR_EXTERNAL;
break;
}
ecmd->phy_address = ahw->physical_port;
return status;
}

Expand Down Expand Up @@ -3046,7 +3116,8 @@ int qlcnic_83xx_interrupt_test(struct net_device *netdev)
if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
return -EIO;

ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST);
ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST,
max_sds_rings);
if (ret)
goto fail_diag_irq;

Expand Down
4 changes: 2 additions & 2 deletions drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,7 @@ 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_stats(struct qlcnic_adapter *adapter, u64 *data);
int qlcnic_83xx_get_settings(struct qlcnic_adapter *);
int qlcnic_83xx_get_settings(struct qlcnic_adapter *, struct ethtool_cmd *);
int qlcnic_83xx_set_settings(struct qlcnic_adapter *, struct ethtool_cmd *);
void qlcnic_83xx_get_pauseparam(struct qlcnic_adapter *,
struct ethtool_pauseparam *);
Expand All @@ -620,7 +620,7 @@ int qlcnic_83xx_flash_test(struct qlcnic_adapter *);
int qlcnic_83xx_enable_flash_write(struct qlcnic_adapter *);
int qlcnic_83xx_disable_flash_write(struct qlcnic_adapter *);
u32 qlcnic_83xx_mac_rcode(struct qlcnic_adapter *);
u32 qlcnic_83xx_mbx_poll(struct qlcnic_adapter *);
u32 qlcnic_83xx_mbx_poll(struct qlcnic_adapter *, u32 *);
void qlcnic_83xx_enable_mbx_poll(struct qlcnic_adapter *);
void qlcnic_83xx_disable_mbx_poll(struct qlcnic_adapter *);
#endif
22 changes: 13 additions & 9 deletions drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -435,10 +435,6 @@ static void qlcnic_83xx_idc_attach_driver(struct qlcnic_adapter *adapter)
}
done:
netif_device_attach(netdev);
if (netif_running(netdev)) {
netif_carrier_on(netdev);
netif_wake_queue(netdev);
}
}

static int qlcnic_83xx_idc_enter_failed_state(struct qlcnic_adapter *adapter,
Expand Down Expand Up @@ -642,15 +638,21 @@ static int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter)

static void qlcnic_83xx_idc_update_idc_params(struct qlcnic_adapter *adapter)
{
struct qlcnic_hardware_context *ahw = adapter->ahw;

qlcnic_83xx_idc_update_drv_presence_reg(adapter, 1, 1);
clear_bit(__QLCNIC_RESETTING, &adapter->state);
set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status);
qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1);
set_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status);
adapter->ahw->idc.quiesce_req = 0;
adapter->ahw->idc.delay = QLC_83XX_IDC_FW_POLL_DELAY;
adapter->ahw->idc.err_code = 0;
adapter->ahw->idc.collect_dump = 0;

ahw->idc.quiesce_req = 0;
ahw->idc.delay = QLC_83XX_IDC_FW_POLL_DELAY;
ahw->idc.err_code = 0;
ahw->idc.collect_dump = 0;
ahw->reset_context = 0;
adapter->tx_timeo_cnt = 0;

clear_bit(__QLCNIC_RESETTING, &adapter->state);
}

/**
Expand Down Expand Up @@ -851,6 +853,7 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter)
/* Check for soft reset request */
if (ahw->reset_context &&
!(val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY)) {
adapter->ahw->reset_context = 0;
qlcnic_83xx_idc_tx_soft_reset(adapter);
return ret;
}
Expand Down Expand Up @@ -914,6 +917,7 @@ static int qlcnic_83xx_idc_need_quiesce_state(struct qlcnic_adapter *adapter)
static int qlcnic_83xx_idc_failed_state(struct qlcnic_adapter *adapter)
{
dev_err(&adapter->pdev->dev, "%s: please restart!!\n", __func__);
clear_bit(__QLCNIC_RESETTING, &adapter->state);
adapter->ahw->idc.err_code = -EIO;

return 0;
Expand Down
54 changes: 27 additions & 27 deletions drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,12 +131,13 @@ static const char qlcnic_83xx_rx_stats_strings[][ETH_GSTRING_LEN] = {
"ctx_lro_pkt_cnt",
"ctx_ip_csum_error",
"ctx_rx_pkts_wo_ctx",
"ctx_rx_pkts_dropped_wo_sts",
"ctx_rx_pkts_drop_wo_sds_on_card",
"ctx_rx_pkts_drop_wo_sds_on_host",
"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_attempted",
"ctx_rx_rds_ring_prim_success",
"ctx_num_lro_flows_added",
"ctx_num_lro_flows_removed",
Expand Down Expand Up @@ -251,6 +252,18 @@ static int
qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
{
struct qlcnic_adapter *adapter = netdev_priv(dev);

if (qlcnic_82xx_check(adapter))
return qlcnic_82xx_get_settings(adapter, ecmd);
else if (qlcnic_83xx_check(adapter))
return qlcnic_83xx_get_settings(adapter, ecmd);

return -EIO;
}

int qlcnic_82xx_get_settings(struct qlcnic_adapter *adapter,
struct ethtool_cmd *ecmd)
{
struct qlcnic_hardware_context *ahw = adapter->ahw;
u32 speed, reg;
int check_sfp_module = 0;
Expand All @@ -276,10 +289,7 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)

} else if (adapter->ahw->port_type == QLCNIC_XGBE) {
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) {
ecmd->supported = SUPPORTED_1000baseT_Full;
Expand All @@ -289,16 +299,13 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
ecmd->advertising = ADVERTISED_10000baseT_Full;
}

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);
ecmd->autoneg = adapter->ahw->link_autoneg;
ecmd->duplex = adapter->ahw->link_duplex;
if (netif_running(adapter->netdev) && ahw->has_link_events) {
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, ahw->link_speed);
ecmd->autoneg = ahw->link_autoneg;
ecmd->duplex = ahw->link_duplex;
goto skip;
}

Expand Down Expand Up @@ -340,8 +347,8 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
case QLCNIC_BRDTYPE_P3P_10G_SFP_QT:
ecmd->advertising |= ADVERTISED_TP;
ecmd->supported |= SUPPORTED_TP;
check_sfp_module = netif_running(dev) &&
adapter->ahw->has_link_events;
check_sfp_module = netif_running(adapter->netdev) &&
ahw->has_link_events;
case QLCNIC_BRDTYPE_P3P_10G_XFP:
ecmd->supported |= SUPPORTED_FIBRE;
ecmd->advertising |= ADVERTISED_FIBRE;
Expand All @@ -355,8 +362,8 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
ecmd->advertising |=
(ADVERTISED_FIBRE | ADVERTISED_TP);
ecmd->port = PORT_FIBRE;
check_sfp_module = netif_running(dev) &&
adapter->ahw->has_link_events;
check_sfp_module = netif_running(adapter->netdev) &&
ahw->has_link_events;
} else {
ecmd->autoneg = AUTONEG_ENABLE;
ecmd->supported |= (SUPPORTED_TP | SUPPORTED_Autoneg);
Expand All @@ -365,13 +372,6 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
ecmd->port = PORT_TP;
}
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:
dev_err(&adapter->pdev->dev, "Unsupported board model %d\n",
adapter->ahw->board_type);
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ struct qlcnic_mailbox_metadata {

#define QLCNIC_SET_OWNER 1
#define QLCNIC_CLR_OWNER 0
#define QLCNIC_MBX_TIMEOUT 10000
#define QLCNIC_MBX_TIMEOUT 5000

#define QLCNIC_MBX_RSP_OK 1
#define QLCNIC_MBX_PORT_RSP_OK 0x1a
Expand Down
Loading

0 comments on commit 1e9e990

Please sign in to comment.