mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	netxen_nic: fix cdrp race condition
Reading CRB registers(if reqd) before releasing the api lock. Signed-off-by: Sritej Velaga <sritej.velaga@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									e1f4c485cd
								
							
						
					
					
						commit
						2dcd5d95ad
					
				
					 2 changed files with 85 additions and 68 deletions
				
			
		| 
						 | 
					@ -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
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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,
 | 
					 | 
				
			||||||
			adapter->tx_context_id,
 | 
					 | 
				
			||||||
			NX_DESTROY_CTX_RESET,
 | 
					 | 
				
			||||||
			0,
 | 
					 | 
				
			||||||
			NX_CDRP_CMD_DESTROY_TX_CTX)) {
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset(&cmd, 0, sizeof(cmd));
 | 
				
			||||||
 | 
						cmd.req.arg1 = adapter->tx_context_id;
 | 
				
			||||||
 | 
						cmd.req.arg2 = NX_DESTROY_CTX_RESET;
 | 
				
			||||||
 | 
						cmd.req.arg3 = 0;
 | 
				
			||||||
 | 
						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,
 | 
						memset(&cmd, 0, sizeof(cmd));
 | 
				
			||||||
			adapter->ahw.pci_func,
 | 
						cmd.req.arg1 = reg;
 | 
				
			||||||
			NXHAL_VERSION,
 | 
						cmd.req.arg2 = 0;
 | 
				
			||||||
			reg,
 | 
						cmd.req.arg3 = 0;
 | 
				
			||||||
			0,
 | 
						cmd.req.cmd = NX_CDRP_CMD_READ_PHY;
 | 
				
			||||||
			0,
 | 
						cmd.rsp.arg1 = 1;
 | 
				
			||||||
			NX_CDRP_CMD_READ_PHY);
 | 
						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,
 | 
						memset(&cmd, 0, sizeof(cmd));
 | 
				
			||||||
			adapter->ahw.pci_func,
 | 
						cmd.req.arg1 = reg;
 | 
				
			||||||
			NXHAL_VERSION,
 | 
						cmd.req.arg2 = val;
 | 
				
			||||||
			reg,
 | 
						cmd.req.arg3 = 0;
 | 
				
			||||||
			val,
 | 
						cmd.req.cmd = NX_CDRP_CMD_WRITE_PHY;
 | 
				
			||||||
			0,
 | 
						rcode = netxen_issue_cmd(adapter, &cmd);
 | 
				
			||||||
			NX_CDRP_CMD_WRITE_PHY);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (rcode != NX_RCODE_SUCCESS)
 | 
						if (rcode != NX_RCODE_SUCCESS)
 | 
				
			||||||
		return -EIO;
 | 
							return -EIO;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue