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

Commit 2dfe0e1f authored by Eilon Greenstein's avatar Eilon Greenstein Committed by David S. Miller
Browse files

bnx2x: Handling load failures



Failures on load were not handled correctly - separate the flow to handle

different failures

Signed-off-by: default avatarEilon Greenstein <eilong@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e94d8af3
Loading
Loading
Loading
Loading
+88 −66
Original line number Original line Diff line number Diff line
@@ -6328,7 +6328,7 @@ static void bnx2x_set_rx_mode(struct net_device *dev);
static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
{
{
	u32 load_code;
	u32 load_code;
	int i, rc;
	int i, rc = 0;
#ifdef BNX2X_STOP_ON_ERROR
#ifdef BNX2X_STOP_ON_ERROR
	if (unlikely(bp->panic))
	if (unlikely(bp->panic))
		return -EPERM;
		return -EPERM;
@@ -6336,48 +6336,6 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)


	bp->state = BNX2X_STATE_OPENING_WAIT4_LOAD;
	bp->state = BNX2X_STATE_OPENING_WAIT4_LOAD;


	/* Send LOAD_REQUEST command to MCP
	   Returns the type of LOAD command:
	   if it is the first port to be initialized
	   common blocks should be initialized, otherwise - not
	*/
	if (!BP_NOMCP(bp)) {
		load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ);
		if (!load_code) {
			BNX2X_ERR("MCP response failure, aborting\n");
			return -EBUSY;
		}
		if (load_code == FW_MSG_CODE_DRV_LOAD_REFUSED)
			return -EBUSY; /* other port in diagnostic mode */

	} else {
		int port = BP_PORT(bp);

		DP(NETIF_MSG_IFUP, "NO MCP load counts before us %d, %d, %d\n",
		   load_count[0], load_count[1], load_count[2]);
		load_count[0]++;
		load_count[1 + port]++;
		DP(NETIF_MSG_IFUP, "NO MCP new load counts       %d, %d, %d\n",
		   load_count[0], load_count[1], load_count[2]);
		if (load_count[0] == 1)
			load_code = FW_MSG_CODE_DRV_LOAD_COMMON;
		else if (load_count[1 + port] == 1)
			load_code = FW_MSG_CODE_DRV_LOAD_PORT;
		else
			load_code = FW_MSG_CODE_DRV_LOAD_FUNCTION;
	}

	if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) ||
	    (load_code == FW_MSG_CODE_DRV_LOAD_PORT))
		bp->port.pmf = 1;
	else
		bp->port.pmf = 0;
	DP(NETIF_MSG_LINK, "pmf %d\n", bp->port.pmf);

	/* if we can't use MSI-X we only need one fp,
	 * so try to enable MSI-X with the requested number of fp's
	 * and fallback to inta with one fp
	 */
	if (use_inta) {
	if (use_inta) {
		bp->num_queues = 1;
		bp->num_queues = 1;


@@ -6392,7 +6350,15 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
		else
		else
			bp->num_queues = 1;
			bp->num_queues = 1;


		if (bnx2x_enable_msix(bp)) {
		DP(NETIF_MSG_IFUP,
		   "set number of queues to %d\n", bp->num_queues);

		/* if we can't use MSI-X we only need one fp,
		 * so try to enable MSI-X with the requested number of fp's
		 * and fallback to MSI or legacy INTx with one fp
		 */
		rc = bnx2x_enable_msix(bp);
		if (rc) {
			/* failed to enable MSI-X */
			/* failed to enable MSI-X */
			bp->num_queues = 1;
			bp->num_queues = 1;
			if (use_multi)
			if (use_multi)
@@ -6400,8 +6366,6 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
					  " to enable MSI-X\n");
					  " to enable MSI-X\n");
		}
		}
	}
	}
	DP(NETIF_MSG_IFUP,
	   "set number of queues to %d\n", bp->num_queues);


	if (bnx2x_alloc_mem(bp))
	if (bnx2x_alloc_mem(bp))
		return -ENOMEM;
		return -ENOMEM;
@@ -6410,30 +6374,85 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
		bnx2x_fp(bp, i, disable_tpa) =
		bnx2x_fp(bp, i, disable_tpa) =
					((bp->flags & TPA_ENABLE_FLAG) == 0);
					((bp->flags & TPA_ENABLE_FLAG) == 0);


	for_each_queue(bp, i)
		netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
			       bnx2x_poll, 128);

#ifdef BNX2X_STOP_ON_ERROR
	for_each_queue(bp, i) {
		struct bnx2x_fastpath *fp = &bp->fp[i];

		fp->poll_no_work = 0;
		fp->poll_calls = 0;
		fp->poll_max_calls = 0;
		fp->poll_complete = 0;
		fp->poll_exit = 0;
	}
#endif
	bnx2x_napi_enable(bp);

	if (bp->flags & USING_MSIX_FLAG) {
	if (bp->flags & USING_MSIX_FLAG) {
		rc = bnx2x_req_msix_irqs(bp);
		rc = bnx2x_req_msix_irqs(bp);
		if (rc) {
		if (rc) {
			pci_disable_msix(bp->pdev);
			pci_disable_msix(bp->pdev);
			goto load_error;
			goto load_error1;
		}
		}
		printk(KERN_INFO PFX "%s: using MSI-X\n", bp->dev->name);
	} else {
	} else {
		bnx2x_ack_int(bp);
		bnx2x_ack_int(bp);
		rc = bnx2x_req_irq(bp);
		rc = bnx2x_req_irq(bp);
		if (rc) {
		if (rc) {
			BNX2X_ERR("IRQ request failed, aborting\n");
			BNX2X_ERR("IRQ request failed  rc %d, aborting\n", rc);
			goto load_error;
			goto load_error1;
		}
		}
	}
	}


	for_each_queue(bp, i)
	/* Send LOAD_REQUEST command to MCP
		netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
	   Returns the type of LOAD command:
			       bnx2x_poll, 128);
	   if it is the first port to be initialized
	   common blocks should be initialized, otherwise - not
	*/
	if (!BP_NOMCP(bp)) {
		load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ);
		if (!load_code) {
			BNX2X_ERR("MCP response failure, aborting\n");
			rc = -EBUSY;
			goto load_error2;
		}
		if (load_code == FW_MSG_CODE_DRV_LOAD_REFUSED) {
			rc = -EBUSY; /* other port in diagnostic mode */
			goto load_error2;
		}

	} else {
		int port = BP_PORT(bp);

		DP(NETIF_MSG_IFUP, "NO MCP load counts before us %d, %d, %d\n",
		   load_count[0], load_count[1], load_count[2]);
		load_count[0]++;
		load_count[1 + port]++;
		DP(NETIF_MSG_IFUP, "NO MCP new load counts       %d, %d, %d\n",
		   load_count[0], load_count[1], load_count[2]);
		if (load_count[0] == 1)
			load_code = FW_MSG_CODE_DRV_LOAD_COMMON;
		else if (load_count[1 + port] == 1)
			load_code = FW_MSG_CODE_DRV_LOAD_PORT;
		else
			load_code = FW_MSG_CODE_DRV_LOAD_FUNCTION;
	}

	if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) ||
	    (load_code == FW_MSG_CODE_DRV_LOAD_PORT))
		bp->port.pmf = 1;
	else
		bp->port.pmf = 0;
	DP(NETIF_MSG_LINK, "pmf %d\n", bp->port.pmf);


	/* Initialize HW */
	/* Initialize HW */
	rc = bnx2x_init_hw(bp, load_code);
	rc = bnx2x_init_hw(bp, load_code);
	if (rc) {
	if (rc) {
		BNX2X_ERR("HW init failed, aborting\n");
		BNX2X_ERR("HW init failed, aborting\n");
		goto load_int_disable;
		goto load_error2;
	}
	}


	/* Setup NIC internals and enable interrupts */
	/* Setup NIC internals and enable interrupts */
@@ -6445,7 +6464,7 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
		if (!load_code) {
		if (!load_code) {
			BNX2X_ERR("MCP response failure, aborting\n");
			BNX2X_ERR("MCP response failure, aborting\n");
			rc = -EBUSY;
			rc = -EBUSY;
			goto load_rings_free;
			goto load_error3;
		}
		}
	}
	}


@@ -6454,7 +6473,7 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
	rc = bnx2x_setup_leading(bp);
	rc = bnx2x_setup_leading(bp);
	if (rc) {
	if (rc) {
		BNX2X_ERR("Setup leading failed!\n");
		BNX2X_ERR("Setup leading failed!\n");
		goto load_netif_stop;
		goto load_error3;
	}
	}


	if (CHIP_IS_E1H(bp))
	if (CHIP_IS_E1H(bp))
@@ -6467,7 +6486,7 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
		for_each_nondefault_queue(bp, i) {
		for_each_nondefault_queue(bp, i) {
			rc = bnx2x_setup_multi(bp, i);
			rc = bnx2x_setup_multi(bp, i);
			if (rc)
			if (rc)
				goto load_netif_stop;
				goto load_error3;
		}
		}


	if (CHIP_IS_E1(bp))
	if (CHIP_IS_E1(bp))
@@ -6483,18 +6502,18 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
	case LOAD_NORMAL:
	case LOAD_NORMAL:
		/* Tx queue should be only reenabled */
		/* Tx queue should be only reenabled */
		netif_wake_queue(bp->dev);
		netif_wake_queue(bp->dev);
		/* Initialize the receive filter. */
		bnx2x_set_rx_mode(bp->dev);
		bnx2x_set_rx_mode(bp->dev);
		break;
		break;


	case LOAD_OPEN:
	case LOAD_OPEN:
		netif_start_queue(bp->dev);
		netif_start_queue(bp->dev);
		/* Initialize the receive filter. */
		bnx2x_set_rx_mode(bp->dev);
		bnx2x_set_rx_mode(bp->dev);
		if (bp->flags & USING_MSIX_FLAG)
			printk(KERN_INFO PFX "%s: using MSI-X\n",
			       bp->dev->name);
		break;
		break;


	case LOAD_DIAG:
	case LOAD_DIAG:
		/* Initialize the receive filter. */
		bnx2x_set_rx_mode(bp->dev);
		bnx2x_set_rx_mode(bp->dev);
		bp->state = BNX2X_STATE_DIAG;
		bp->state = BNX2X_STATE_DIAG;
		break;
		break;
@@ -6512,20 +6531,23 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)


	return 0;
	return 0;


load_netif_stop:
load_error3:
	bnx2x_napi_disable(bp);
	bnx2x_int_disable_sync(bp, 1);
load_rings_free:
	if (!BP_NOMCP(bp)) {
		bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP);
		bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE);
	}
	bp->port.pmf = 0;
	/* Free SKBs, SGEs, TPA pool and driver internals */
	/* Free SKBs, SGEs, TPA pool and driver internals */
	bnx2x_free_skbs(bp);
	bnx2x_free_skbs(bp);
	for_each_queue(bp, i)
	for_each_queue(bp, i)
		bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE);
		bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE);
load_int_disable:
load_error2:
	bnx2x_int_disable_sync(bp, 1);
	/* Release IRQs */
	/* Release IRQs */
	bnx2x_free_irq(bp);
	bnx2x_free_irq(bp);
load_error:
load_error1:
	bnx2x_napi_disable(bp);
	bnx2x_free_mem(bp);
	bnx2x_free_mem(bp);
	bp->port.pmf = 0;


	/* TBD we really need to reset the chip
	/* TBD we really need to reset the chip
	   if we want to recover from this */
	   if we want to recover from this */