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

Commit eb5f10c2 authored by Sreenivasa Honnur's avatar Sreenivasa Honnur Committed by David S. Miller
Browse files

vxge: Allow multiple functions with INTA.



- Allow multiple functions with INTA.
- Removed the condition to allow only one vpath with INTA
- Ensure that the alarm bit in titan_mask_all_int register is cleared when
  driver exits.

Signed-off-by: default avatarSreenivasa Honnur <sreenivasa.honnur@neterion.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent fa41fd10
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -3882,6 +3882,30 @@ __vxge_hw_vpath_tim_configure(struct __vxge_hw_device *hldev, u32 vp_id)
	return status;
}

void
vxge_hw_vpath_tti_ci_set(struct __vxge_hw_device *hldev, u32 vp_id)
{
	struct __vxge_hw_virtualpath *vpath;
	struct vxge_hw_vpath_reg __iomem *vp_reg;
	struct vxge_hw_vp_config *config;
	u64 val64;

	vpath = &hldev->virtual_paths[vp_id];
	vp_reg = vpath->vp_reg;
	config = vpath->vp_config;

	if (config->fifo.enable == VXGE_HW_FIFO_ENABLE) {
		val64 = readq(&vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_TX]);

		if (config->tti.timer_ci_en != VXGE_HW_TIM_TIMER_CI_ENABLE) {
			config->tti.timer_ci_en = VXGE_HW_TIM_TIMER_CI_ENABLE;
			val64 |= VXGE_HW_TIM_CFG1_INT_NUM_TIMER_CI;
			writeq(val64,
			&vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_TX]);
		}
	}
	return;
}
/*
 * __vxge_hw_vpath_initialize
 * This routine is the final phase of init which initializes the
+36 −56
Original line number Diff line number Diff line
@@ -2435,7 +2435,6 @@ static int vxge_add_isr(struct vxgedev *vdev)
	int ret = 0;
#ifdef CONFIG_PCI_MSI
	int vp_idx = 0, intr_idx = 0, intr_cnt = 0, msix_idx = 0, irq_req = 0;
	u64 function_mode = vdev->config.device_hw_info.function_mode;
	int pci_fun = PCI_FUNC(vdev->pdev->devfn);

	if (vdev->config.intr_type == MSI_X)
@@ -2444,20 +2443,9 @@ static int vxge_add_isr(struct vxgedev *vdev)
	if (ret) {
		vxge_debug_init(VXGE_ERR,
			"%s: Enabling MSI-X Failed", VXGE_DRIVER_NAME);
		if ((function_mode == VXGE_HW_FUNCTION_MODE_MULTI_FUNCTION) &&
			test_and_set_bit(__VXGE_STATE_CARD_UP,
				&driver_config->inta_dev_open))
			return VXGE_HW_FAIL;
		else {
		vxge_debug_init(VXGE_ERR,
			"%s: Defaulting to INTA", VXGE_DRIVER_NAME);
		vdev->config.intr_type = INTA;
			vxge_hw_device_set_intr_type(vdev->devh,
				VXGE_HW_INTR_MODE_IRQLINE);
			vxge_close_vpaths(vdev, 1);
			vdev->no_of_vpath = 1;
			vdev->stats.vpaths_open = 1;
		}
	}

	if (vdev->config.intr_type == MSI_X) {
@@ -2505,25 +2493,12 @@ static int vxge_add_isr(struct vxgedev *vdev)
					"%s: MSIX - %d  Registration failed",
					vdev->ndev->name, intr_cnt);
				vxge_rem_msix_isr(vdev);
				if ((function_mode ==
					VXGE_HW_FUNCTION_MODE_MULTI_FUNCTION) &&
					test_and_set_bit(__VXGE_STATE_CARD_UP,
						&driver_config->inta_dev_open))
					return VXGE_HW_FAIL;
				else {
					vxge_hw_device_set_intr_type(
						vdev->devh,
						VXGE_HW_INTR_MODE_IRQLINE);
				vdev->config.intr_type = INTA;
				vxge_debug_init(VXGE_ERR,
					"%s: Defaulting to INTA"
					, vdev->ndev->name);
					vxge_close_vpaths(vdev, 1);
					vdev->no_of_vpath = 1;
					vdev->stats.vpaths_open = 1;
					goto INTA_MODE;
			}
			}

			if (irq_req) {
				/* We requested for this msix interrupt */
@@ -2555,24 +2530,12 @@ static int vxge_add_isr(struct vxgedev *vdev)
				"%s: MSIX - %d Registration failed",
				vdev->ndev->name, intr_cnt);
			vxge_rem_msix_isr(vdev);
			if ((function_mode ==
				VXGE_HW_FUNCTION_MODE_MULTI_FUNCTION) &&
				test_and_set_bit(__VXGE_STATE_CARD_UP,
						&driver_config->inta_dev_open))
				return VXGE_HW_FAIL;
			else {
				vxge_hw_device_set_intr_type(vdev->devh,
						VXGE_HW_INTR_MODE_IRQLINE);
			vdev->config.intr_type = INTA;
			vxge_debug_init(VXGE_ERR,
				"%s: Defaulting to INTA",
				vdev->ndev->name);
				vxge_close_vpaths(vdev, 1);
				vdev->no_of_vpath = 1;
				vdev->stats.vpaths_open = 1;
				goto INTA_MODE;
		}
		}

		vxge_hw_vpath_msix_unmask(vdev->vpaths[vp_idx].handle,
					intr_idx - 2);
@@ -2584,6 +2547,10 @@ static int vxge_add_isr(struct vxgedev *vdev)
	snprintf(vdev->desc[0], VXGE_INTR_STRLEN, "%s:vxge", vdev->ndev->name);

	if (vdev->config.intr_type == INTA) {
		vxge_hw_device_set_intr_type(vdev->devh,
			VXGE_HW_INTR_MODE_IRQLINE);
		vxge_hw_vpath_tti_ci_set(vdev->devh,
			vdev->vpaths[0].device_id);
		ret = request_irq((int) vdev->pdev->irq,
			vxge_isr_napi,
			IRQF_SHARED, vdev->desc[0], vdev);
@@ -2688,13 +2655,6 @@ vxge_open(struct net_device *dev)
	 * initialized */
	netif_carrier_off(dev);

	/* Check for another device already opn with INTA */
	if ((function_mode == VXGE_HW_FUNCTION_MODE_MULTI_FUNCTION) &&
		test_bit(__VXGE_STATE_CARD_UP, &driver_config->inta_dev_open)) {
		ret = -EPERM;
		goto out0;
	}

	/* Open VPATHs */
	status = vxge_open_vpaths(vdev);
	if (status != VXGE_HW_OK) {
@@ -2983,7 +2943,6 @@ int do_vxge_close(struct net_device *dev, int do_io)
	vxge_debug_entryexit(VXGE_TRACE,
		"%s: %s:%d  Exiting...", dev->name, __func__, __LINE__);

	clear_bit(__VXGE_STATE_CARD_UP, &driver_config->inta_dev_open);
	clear_bit(__VXGE_STATE_RESET_CARD, &vdev->state);

	return 0;
@@ -4397,6 +4356,27 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
	}

	kfree(device_config);

	/*
	 * INTA is shared in multi-function mode. This is unlike the INTA
	 * implementation in MR mode, where each VH has its own INTA message.
	 * - INTA is masked (disabled) as long as at least one function sets
	 * its TITAN_MASK_ALL_INT.ALARM bit.
	 * - INTA is unmasked (enabled) when all enabled functions have cleared
	 * their own TITAN_MASK_ALL_INT.ALARM bit.
	 * The TITAN_MASK_ALL_INT ALARM & TRAFFIC bits are cleared on power up.
	 * Though this driver leaves the top level interrupts unmasked while
	 * leaving the required module interrupt bits masked on exit, there
	 * could be a rougue driver around that does not follow this procedure
	 * resulting in a failure to generate interrupts. The following code is
	 * present to prevent such a failure.
	 */

	if (ll_config.device_hw_info.function_mode ==
		VXGE_HW_FUNCTION_MODE_MULTI_FUNCTION)
		if (vdev->config.intr_type == INTA)
			vxge_hw_device_unmask_all(hldev);

	vxge_debug_entryexit(VXGE_TRACE, "%s: %s:%d  Exiting...",
		vdev->ndev->name, __func__, __LINE__);

+0 −1
Original line number Diff line number Diff line
@@ -112,7 +112,6 @@ enum vxge_mac_addr_state {
struct vxge_drv_config {
	int config_dev_cnt;
	int total_dev_cnt;
	unsigned long inta_dev_open;
	int g_no_cpus;
	unsigned int vpath_per_dev;
};
+2 −0
Original line number Diff line number Diff line
@@ -295,6 +295,8 @@ void vxge_hw_device_intr_enable(struct __vxge_hw_device *hldev)
	u64 val64;
	u32 val32;

	vxge_hw_device_mask_all(hldev);

	for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {

		if (!(hldev->vpaths_deployed & vxge_mBIT(i)))
+2 −0
Original line number Diff line number Diff line
@@ -2389,6 +2389,8 @@ vxge_hw_channel_dtr_free(struct __vxge_hw_channel *channel, void *dtrh);

int
vxge_hw_channel_dtr_count(struct __vxge_hw_channel *channel);
void
vxge_hw_vpath_tti_ci_set(struct __vxge_hw_device *hldev, u32 vp_id);

/* ========================== PRIVATE API ================================= */