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

Commit 2dcd5d95 authored by Sritej Velaga's avatar Sritej Velaga Committed by David S. Miller
Browse files

netxen_nic: fix cdrp race condition



Reading CRB registers(if reqd) before releasing the api lock.

Signed-off-by: default avatarSritej Velaga <sritej.velaga@qlogic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e1f4c485
Loading
Loading
Loading
Loading
+12 −0
Original line number Original line Diff line number Diff line
@@ -686,6 +686,18 @@ struct netxen_recv_context {
	dma_addr_t phys_addr;
	dma_addr_t phys_addr;
};
};


struct _cdrp_cmd {
	u32 cmd;
	u32 arg1;
	u32 arg2;
	u32 arg3;
};

struct netxen_cmd_args {
	struct _cdrp_cmd req;
	struct _cdrp_cmd rsp;
};

/* New HW context creation */
/* New HW context creation */


#define NX_OS_CRB_RETRY_COUNT	4000
#define NX_OS_CRB_RETRY_COUNT	4000
+77 −72
Original line number Original line Diff line number Diff line
@@ -48,28 +48,27 @@ netxen_poll_rsp(struct netxen_adapter *adapter)
}
}


static u32
static u32
netxen_issue_cmd(struct netxen_adapter *adapter,
netxen_issue_cmd(struct netxen_adapter *adapter, struct netxen_cmd_args *cmd)
	u32 pci_fn, u32 version, u32 arg1, u32 arg2, u32 arg3, u32 cmd)
{
{
	u32 rsp;
	u32 rsp;
	u32 signature = 0;
	u32 signature = 0;
	u32 rcode = NX_RCODE_SUCCESS;
	u32 rcode = NX_RCODE_SUCCESS;


	signature = NX_CDRP_SIGNATURE_MAKE(pci_fn, version);
	signature = NX_CDRP_SIGNATURE_MAKE(adapter->ahw.pci_func,

						NXHAL_VERSION);
	/* Acquire semaphore before accessing CRB */
	/* Acquire semaphore before accessing CRB */
	if (netxen_api_lock(adapter))
	if (netxen_api_lock(adapter))
		return NX_RCODE_TIMEOUT;
		return NX_RCODE_TIMEOUT;


	NXWR32(adapter, NX_SIGN_CRB_OFFSET, signature);
	NXWR32(adapter, NX_SIGN_CRB_OFFSET, signature);


	NXWR32(adapter, NX_ARG1_CRB_OFFSET, arg1);
	NXWR32(adapter, NX_ARG1_CRB_OFFSET, cmd->req.arg1);


	NXWR32(adapter, NX_ARG2_CRB_OFFSET, arg2);
	NXWR32(adapter, NX_ARG2_CRB_OFFSET, cmd->req.arg2);


	NXWR32(adapter, NX_ARG3_CRB_OFFSET, arg3);
	NXWR32(adapter, NX_ARG3_CRB_OFFSET, cmd->req.arg3);


	NXWR32(adapter, NX_CDRP_CRB_OFFSET, NX_CDRP_FORM_CMD(cmd));
	NXWR32(adapter, NX_CDRP_CRB_OFFSET, NX_CDRP_FORM_CMD(cmd->req.cmd));


	rsp = netxen_poll_rsp(adapter);
	rsp = netxen_poll_rsp(adapter);


@@ -83,8 +82,15 @@ netxen_issue_cmd(struct netxen_adapter *adapter,


		printk(KERN_ERR "%s: failed card response code:0x%x\n",
		printk(KERN_ERR "%s: failed card response code:0x%x\n",
				netxen_nic_driver_name, rcode);
				netxen_nic_driver_name, rcode);
	} else if (rsp == NX_CDRP_RSP_OK) {
		if (cmd->rsp.arg2)
			cmd->rsp.arg2 = NXRD32(adapter, NX_ARG2_CRB_OFFSET);
		if (cmd->rsp.arg3)
			cmd->rsp.arg3 = NXRD32(adapter, NX_ARG3_CRB_OFFSET);
	}
	}


	if (cmd->rsp.arg1)
		cmd->rsp.arg1 = NXRD32(adapter, NX_ARG1_CRB_OFFSET);
	/* Release semaphore */
	/* Release semaphore */
	netxen_api_unlock(adapter);
	netxen_api_unlock(adapter);


@@ -96,15 +102,16 @@ nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu)
{
{
	u32 rcode = NX_RCODE_SUCCESS;
	u32 rcode = NX_RCODE_SUCCESS;
	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
	struct netxen_cmd_args cmd;

	memset(&cmd, 0, sizeof(cmd));
	cmd.req.cmd = NX_CDRP_CMD_SET_MTU;
	cmd.req.arg1 = recv_ctx->context_id;
	cmd.req.arg2 = mtu;
	cmd.req.arg3 = 0;


	if (recv_ctx->state == NX_HOST_CTX_STATE_ACTIVE)
	if (recv_ctx->state == NX_HOST_CTX_STATE_ACTIVE)
		rcode = netxen_issue_cmd(adapter,
		netxen_issue_cmd(adapter, &cmd);
				adapter->ahw.pci_func,
				NXHAL_VERSION,
				recv_ctx->context_id,
				mtu,
				0,
				NX_CDRP_CMD_SET_MTU);


	if (rcode != NX_RCODE_SUCCESS)
	if (rcode != NX_RCODE_SUCCESS)
		return -EIO;
		return -EIO;
@@ -116,15 +123,14 @@ int
nx_fw_cmd_set_gbe_port(struct netxen_adapter *adapter,
nx_fw_cmd_set_gbe_port(struct netxen_adapter *adapter,
			u32 speed, u32 duplex, u32 autoneg)
			u32 speed, u32 duplex, u32 autoneg)
{
{
	struct netxen_cmd_args cmd;


	return netxen_issue_cmd(adapter,
	memset(&cmd, 0, sizeof(cmd));
				adapter->ahw.pci_func,
	cmd.req.cmd = NX_CDRP_CMD_CONFIG_GBE_PORT;
				NXHAL_VERSION,
	cmd.req.arg1 = speed;
				speed,
	cmd.req.arg2 = duplex;
				duplex,
	cmd.req.arg3 = autoneg;
				autoneg,
	return netxen_issue_cmd(adapter, &cmd);
				NX_CDRP_CMD_CONFIG_GBE_PORT);

}
}


static int
static int
@@ -139,6 +145,7 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
	nx_cardrsp_sds_ring_t *prsp_sds;
	nx_cardrsp_sds_ring_t *prsp_sds;
	struct nx_host_rds_ring *rds_ring;
	struct nx_host_rds_ring *rds_ring;
	struct nx_host_sds_ring *sds_ring;
	struct nx_host_sds_ring *sds_ring;
	struct netxen_cmd_args cmd;


	dma_addr_t hostrq_phys_addr, cardrsp_phys_addr;
	dma_addr_t hostrq_phys_addr, cardrsp_phys_addr;
	u64 phys_addr;
	u64 phys_addr;
@@ -218,13 +225,12 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
	}
	}


	phys_addr = hostrq_phys_addr;
	phys_addr = hostrq_phys_addr;
	err = netxen_issue_cmd(adapter,
	memset(&cmd, 0, sizeof(cmd));
			adapter->ahw.pci_func,
	cmd.req.arg1 = (u32)(phys_addr >> 32);
			NXHAL_VERSION,
	cmd.req.arg2 = (u32)(phys_addr & 0xffffffff);
			(u32)(phys_addr >> 32),
	cmd.req.arg3 = rq_size;
			(u32)(phys_addr & 0xffffffff),
	cmd.req.cmd = NX_CDRP_CMD_CREATE_RX_CTX;
			rq_size,
	err = netxen_issue_cmd(adapter, &cmd);
			NX_CDRP_CMD_CREATE_RX_CTX);
	if (err) {
	if (err) {
		printk(KERN_WARNING
		printk(KERN_WARNING
			"Failed to create rx ctx in firmware%d\n", err);
			"Failed to create rx ctx in firmware%d\n", err);
@@ -273,15 +279,15 @@ static void
nx_fw_cmd_destroy_rx_ctx(struct netxen_adapter *adapter)
nx_fw_cmd_destroy_rx_ctx(struct netxen_adapter *adapter)
{
{
	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
	struct netxen_cmd_args cmd;


	if (netxen_issue_cmd(adapter,
	memset(&cmd, 0, sizeof(cmd));
			adapter->ahw.pci_func,
	cmd.req.arg1 = recv_ctx->context_id;
			NXHAL_VERSION,
	cmd.req.arg2 = NX_DESTROY_CTX_RESET;
			recv_ctx->context_id,
	cmd.req.arg3 = 0;
			NX_DESTROY_CTX_RESET,
	cmd.req.cmd = NX_CDRP_CMD_DESTROY_RX_CTX;
			0,
			NX_CDRP_CMD_DESTROY_RX_CTX)) {


	if (netxen_issue_cmd(adapter, &cmd)) {
		printk(KERN_WARNING
		printk(KERN_WARNING
			"%s: Failed to destroy rx ctx in firmware\n",
			"%s: Failed to destroy rx ctx in firmware\n",
			netxen_nic_driver_name);
			netxen_nic_driver_name);
@@ -302,6 +308,7 @@ nx_fw_cmd_create_tx_ctx(struct netxen_adapter *adapter)
	dma_addr_t	rq_phys_addr, rsp_phys_addr;
	dma_addr_t	rq_phys_addr, rsp_phys_addr;
	struct nx_host_tx_ring *tx_ring = adapter->tx_ring;
	struct nx_host_tx_ring *tx_ring = adapter->tx_ring;
	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
	struct netxen_cmd_args cmd;


	rq_size = SIZEOF_HOSTRQ_TX(nx_hostrq_tx_ctx_t);
	rq_size = SIZEOF_HOSTRQ_TX(nx_hostrq_tx_ctx_t);
	rq_addr = pci_alloc_consistent(adapter->pdev,
	rq_addr = pci_alloc_consistent(adapter->pdev,
@@ -345,13 +352,12 @@ nx_fw_cmd_create_tx_ctx(struct netxen_adapter *adapter)
	prq_cds->ring_size = cpu_to_le32(tx_ring->num_desc);
	prq_cds->ring_size = cpu_to_le32(tx_ring->num_desc);


	phys_addr = rq_phys_addr;
	phys_addr = rq_phys_addr;
	err = netxen_issue_cmd(adapter,
	memset(&cmd, 0, sizeof(cmd));
			adapter->ahw.pci_func,
	cmd.req.arg1 = (u32)(phys_addr >> 32);
			NXHAL_VERSION,
	cmd.req.arg2 = ((u32)phys_addr & 0xffffffff);
			(u32)(phys_addr >> 32),
	cmd.req.arg3 = rq_size;
			((u32)phys_addr & 0xffffffff),
	cmd.req.cmd = NX_CDRP_CMD_CREATE_TX_CTX;
			rq_size,
	err = netxen_issue_cmd(adapter, &cmd);
			NX_CDRP_CMD_CREATE_TX_CTX);


	if (err == NX_RCODE_SUCCESS) {
	if (err == NX_RCODE_SUCCESS) {
		temp = le32_to_cpu(prsp->cds_ring.host_producer_crb);
		temp = le32_to_cpu(prsp->cds_ring.host_producer_crb);
@@ -380,14 +386,14 @@ nx_fw_cmd_create_tx_ctx(struct netxen_adapter *adapter)
static void
static void
nx_fw_cmd_destroy_tx_ctx(struct netxen_adapter *adapter)
nx_fw_cmd_destroy_tx_ctx(struct netxen_adapter *adapter)
{
{
	if (netxen_issue_cmd(adapter,
	struct netxen_cmd_args cmd;
			adapter->ahw.pci_func,

			NXHAL_VERSION,
	memset(&cmd, 0, sizeof(cmd));
			adapter->tx_context_id,
	cmd.req.arg1 = adapter->tx_context_id;
			NX_DESTROY_CTX_RESET,
	cmd.req.arg2 = NX_DESTROY_CTX_RESET;
			0,
	cmd.req.arg3 = 0;
			NX_CDRP_CMD_DESTROY_TX_CTX)) {
	cmd.req.cmd = NX_CDRP_CMD_DESTROY_TX_CTX;

	if (netxen_issue_cmd(adapter, &cmd)) {
		printk(KERN_WARNING
		printk(KERN_WARNING
			"%s: Failed to destroy tx ctx in firmware\n",
			"%s: Failed to destroy tx ctx in firmware\n",
			netxen_nic_driver_name);
			netxen_nic_driver_name);
@@ -398,34 +404,33 @@ int
nx_fw_cmd_query_phy(struct netxen_adapter *adapter, u32 reg, u32 *val)
nx_fw_cmd_query_phy(struct netxen_adapter *adapter, u32 reg, u32 *val)
{
{
	u32 rcode;
	u32 rcode;

	struct netxen_cmd_args cmd;
	rcode = netxen_issue_cmd(adapter,

			adapter->ahw.pci_func,
	memset(&cmd, 0, sizeof(cmd));
			NXHAL_VERSION,
	cmd.req.arg1 = reg;
			reg,
	cmd.req.arg2 = 0;
			0,
	cmd.req.arg3 = 0;
			0,
	cmd.req.cmd = NX_CDRP_CMD_READ_PHY;
			NX_CDRP_CMD_READ_PHY);
	cmd.rsp.arg1 = 1;

	rcode = netxen_issue_cmd(adapter, &cmd);
	if (rcode != NX_RCODE_SUCCESS)
	if (rcode != NX_RCODE_SUCCESS)
		return -EIO;
		return -EIO;


	return NXRD32(adapter, NX_ARG1_CRB_OFFSET);
	return cmd.rsp.arg1;
}
}


int
int
nx_fw_cmd_set_phy(struct netxen_adapter *adapter, u32 reg, u32 val)
nx_fw_cmd_set_phy(struct netxen_adapter *adapter, u32 reg, u32 val)
{
{
	u32 rcode;
	u32 rcode;

	struct netxen_cmd_args cmd;
	rcode = netxen_issue_cmd(adapter,

			adapter->ahw.pci_func,
	memset(&cmd, 0, sizeof(cmd));
			NXHAL_VERSION,
	cmd.req.arg1 = reg;
			reg,
	cmd.req.arg2 = val;
			val,
	cmd.req.arg3 = 0;
			0,
	cmd.req.cmd = NX_CDRP_CMD_WRITE_PHY;
			NX_CDRP_CMD_WRITE_PHY);
	rcode = netxen_issue_cmd(adapter, &cmd);

	if (rcode != NX_RCODE_SUCCESS)
	if (rcode != NX_RCODE_SUCCESS)
		return -EIO;
		return -EIO;