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

Commit 478567be authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: ipa: Reset GSI channel before gsi_dealloc_channel() call"

parents f2905d39 db268145
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -384,6 +384,11 @@ int atl_update_eth_stats(struct atl_nic *nic);
void atl_adjust_eth_stats(struct atl_ether_stats *stats,
	struct atl_ether_stats *base, bool add);
void atl_fwd_release_rings(struct atl_nic *nic);
#ifdef CONFIG_ATLFWD_FWD
int atl_fwd_resume_rings(struct atl_nic *nic);
#else
static inline int atl_fwd_resume_rings(struct atl_nic *nic) { return 0; }
#endif
int atl_get_lpi_timer(struct atl_nic *nic, uint32_t *lpi_delay);
int atl_mdio_hwsem_get(struct atl_hw *hw);
void atl_mdio_hwsem_put(struct atl_hw *hw);
+80 −17
Original line number Diff line number Diff line
@@ -593,12 +593,47 @@ void atl_fwd_release_event(struct atl_fwd_event *evt)
}
EXPORT_SYMBOL(atl_fwd_release_event);

int atl_fwd_request_event(struct atl_fwd_event *evt)
static int atl_fwd_init_event(struct atl_fwd_event *evt)
{
	struct atl_fwd_ring *ring = evt->ring;
	int dir_tx = atl_fwd_ring_tx(ring);
	struct atl_nic *nic = ring->nic;
	struct atl_hw *hw = &nic->hw;
	bool tx_wb = !!(evt->flags & ATL_FWD_EVT_TXWB);
	int idx;
	int ret;

	if (tx_wb) {
		struct atl_hw_ring *hwring = &ring->hw;

		atl_write(hw, ATL_TX_RING_HEAD_WB_LSW(hwring),
			  evt->tx_head_wrb);
		atl_write(hw, ATL_TX_RING_HEAD_WB_MSW(hwring),
			  upper_32_bits(evt->tx_head_wrb));
		return 0;
	}

	idx = evt->idx;

	ret = atl_fwd_set_msix_vec(nic, evt);
	if (ret)
		return ret;

	atl_set_intr_bits(&nic->hw, ring->idx,
			  dir_tx ? -1 : idx,
			  dir_tx ? idx : -1);

	atl_write_bit(hw, ATL_INTR_AUTO_CLEAR, idx, 1);
	atl_write_bit(hw, ATL_INTR_AUTO_MASK, idx,
		      !!(evt->flags & ATL_FWD_EVT_AUTOMASK));

	return 0;
}

int atl_fwd_request_event(struct atl_fwd_event *evt)
{
	struct atl_fwd_ring *ring = evt->ring;
	struct atl_nic *nic = ring->nic;
	unsigned long *map = &nic->fwd.msi_map;
	bool tx_wb = !!(evt->flags & ATL_FWD_EVT_TXWB);
	int idx;
@@ -631,13 +666,9 @@ int atl_fwd_request_event(struct atl_fwd_event *evt)
	ring->evt = evt;

	if (tx_wb) {
		struct atl_hw_ring *hwring = &ring->hw;

		atl_write(hw, ATL_TX_RING_HEAD_WB_LSW(hwring),
			evt->tx_head_wrb);
		atl_write(hw, ATL_TX_RING_HEAD_WB_MSW(hwring),
			upper_32_bits(evt->tx_head_wrb));
		return 0;
		ret = atl_fwd_init_event(evt);
		if (ret)
			goto fail;
	}

	idx = find_next_zero_bit(map, ATL_NUM_MSI_VECS, ATL_FWD_MSI_BASE);
@@ -649,20 +680,12 @@ int atl_fwd_request_event(struct atl_fwd_event *evt)

	evt->idx = idx;

	ret = atl_fwd_set_msix_vec(nic, evt);
	ret = atl_fwd_init_event(evt);
	if (ret)
		goto fail;

	__set_bit(idx, map);

	atl_set_intr_bits(&nic->hw, ring->idx,
		dir_tx ? -1 : idx,
		dir_tx ? idx : -1);

	atl_write_bit(hw, ATL_INTR_AUTO_CLEAR, idx, 1);
	atl_write_bit(hw, ATL_INTR_AUTO_MASK, idx,
		!!(evt->flags & ATL_FWD_EVT_AUTOMASK));

	return 0;

fail:
@@ -681,10 +704,12 @@ int atl_fwd_enable_event(struct atl_fwd_event *evt)
			return -EINVAL;

		atl_write_bit(hw, ATL_TX_RING_CTL(&ring->hw), 28, 1);
		ring->state |= ATL_FWR_ST_EVT_ENABLED;
		return 0;
	}

	atl_intr_enable(hw, BIT(evt->idx));
	ring->state |= ATL_FWR_ST_EVT_ENABLED;
	return 0;
}
EXPORT_SYMBOL(atl_fwd_enable_event);
@@ -699,10 +724,12 @@ int atl_fwd_disable_event(struct atl_fwd_event *evt)
			return -EINVAL;

		atl_write_bit(hw, ATL_TX_RING_CTL(&ring->hw), 28, 0);
		ring->state &= ~ATL_FWR_ST_EVT_ENABLED;
		return 0;
	}

	atl_intr_disable(hw, BIT(evt->idx));
	ring->state &= ~ATL_FWR_ST_EVT_ENABLED;
	return 0;
}
EXPORT_SYMBOL(atl_fwd_disable_event);
@@ -721,3 +748,39 @@ int atl_fwd_transmit_skb(struct net_device *ndev, struct sk_buff *skb)
}
EXPORT_SYMBOL(atl_fwd_transmit_skb);

int atl_fwd_resume_rings(struct atl_nic *nic)
{
	struct atl_fwd_ring **rings = nic->fwd.rings[0];
	int i;
	int ret;

	for (i = 0; i < ATL_NUM_FWD_RINGS * 2; i++) {
		struct atl_fwd_ring *ring = rings[i];

		if (!ring)
			continue;

		atl_fwd_init_ring(ring);

		if (ring->evt) {
			ret = atl_fwd_init_event(ring->evt);
			if (ret)
				return ret;

			if (ring->state & ATL_FWR_ST_EVT_ENABLED) {
				ret = atl_fwd_enable_event(ring->evt);
				if (ret)
					return ret;
			}
		}

		if (ring->state & ATL_FWR_ST_ENABLED) {
			ret = atl_fwd_enable_ring(ring);
			if (ret)
				return ret;
		}
	}

	return 0;
}
+1 −0
Original line number Diff line number Diff line
@@ -364,6 +364,7 @@ int atl_fwd_transmit_skb(struct net_device *ndev, struct sk_buff *skb);

enum atl_fwd_ring_state {
	ATL_FWR_ST_ENABLED = BIT(0),
	ATL_FWR_ST_EVT_ENABLED = BIT(1),
};

#endif
+10 −0
Original line number Diff line number Diff line
@@ -490,7 +490,10 @@ static int atl_suspend_common(struct device *dev, bool deep)
			atl_dev_err("Enable WoL failed: %d\n", -ret);
	}

	pci_save_state(pdev);
	pci_disable_device(pdev);
	pci_set_power_state(pdev, PCI_D3hot);

	__clear_bit(ATL_ST_ENABLED, &nic->state);

	rtnl_unlock();
@@ -516,6 +519,9 @@ static int atl_resume_common(struct device *dev, bool deep)

	rtnl_lock();

	pci_set_power_state(pdev, PCI_D0);
	pci_restore_state(pdev);

	ret = pci_enable_device_mem(pdev);
	if (ret)
		goto exit;
@@ -540,6 +546,10 @@ static int atl_resume_common(struct device *dev, bool deep)
	if (ret)
		goto exit;

	ret = atl_fwd_resume_rings(nic);
	if (ret)
		goto exit;

	netif_device_attach(nic->ndev);

exit:
+8 −0
Original line number Diff line number Diff line
@@ -222,6 +222,14 @@ int ipa_eth_gsi_dealloc(struct ipa_eth_channel *ch)
	}

	if (ep_ctx->gsi_chan_hdl != ~0) {
		gsi_rc = gsi_reset_channel(ep_ctx->gsi_chan_hdl);
		if (gsi_rc != GSI_STATUS_SUCCESS) {
			ipa_eth_dev_err(ch->eth_dev,
				"Failed to reset channel %u",
				ep_ctx->gsi_chan_hdl);
			return gsi_rc;
		}

		gsi_rc = gsi_dealloc_channel(ep_ctx->gsi_chan_hdl);
		if (gsi_rc != GSI_STATUS_SUCCESS) {
			ipa_eth_dev_err(ch->eth_dev,