Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1e9e9901 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'qlcnic'



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: default avatarDavid S. Miller <davem@davemloft.net>
parents 61f15982 cbccb18f
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -429,6 +429,7 @@ struct qlcnic_hardware_context {

	u16 port_type;
	u16 board_type;
	u16 supported_type;

	u16 link_speed;
	u16 link_duplex;
@@ -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);
+83 −12
Original line number Diff line number Diff line
@@ -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;
		}
@@ -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)) {
@@ -754,14 +753,12 @@ 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;
		}
		mbx_err_code = QLCNIC_MBX_STATUS(fw_data);
@@ -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;

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

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

@@ -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;

+2 −2
Original line number Diff line number Diff line
@@ -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 *);
@@ -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
+13 −9
Original line number Diff line number Diff line
@@ -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,
@@ -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);
}

/**
@@ -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;
	}
@@ -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;
+27 −27
Original line number Diff line number Diff line
@@ -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",
@@ -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;
@@ -276,9 +289,6 @@ 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);

		if (val == QLCNIC_PORT_MODE_802_3_AP) {
@@ -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));
		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, adapter->ahw->link_speed);
			ecmd->autoneg = adapter->ahw->link_autoneg;
			ecmd->duplex = adapter->ahw->link_duplex;
			ethtool_cmd_speed_set(ecmd, ahw->link_speed);
			ecmd->autoneg = ahw->link_autoneg;
			ecmd->duplex = ahw->link_duplex;
			goto skip;
		}

@@ -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;
@@ -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);
@@ -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);
Loading