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

Commit cb79eaae authored by Taku Izumi's avatar Taku Izumi Committed by David S. Miller
Browse files

fjes: handle receive cancellation request interrupt



This patch adds implementation of handling IRQ
of other receiver's receive cancellation request.

Signed-off-by: default avatarTaku Izumi <izumi.taku@jp.fujitsu.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b5a9152d
Loading
Loading
Loading
Loading
+78 −0
Original line number Diff line number Diff line
@@ -820,6 +820,74 @@ static int fjes_vlan_rx_kill_vid(struct net_device *netdev,
	return 0;
}

static void fjes_txrx_stop_req_irq(struct fjes_adapter *adapter,
				   int src_epid)
{
	struct fjes_hw *hw = &adapter->hw;
	enum ep_partner_status status;

	status = fjes_hw_get_partner_ep_status(hw, src_epid);
	switch (status) {
	case EP_PARTNER_UNSHARE:
	case EP_PARTNER_COMPLETE:
	default:
		break;
	case EP_PARTNER_WAITING:
		if (src_epid < hw->my_epid) {
			hw->ep_shm_info[src_epid].tx.info->v1i.rx_status |=
				FJES_RX_STOP_REQ_DONE;

			clear_bit(src_epid, &hw->txrx_stop_req_bit);
			set_bit(src_epid, &adapter->unshare_watch_bitmask);

			if (!work_pending(&adapter->unshare_watch_task))
				queue_work(adapter->control_wq,
					   &adapter->unshare_watch_task);
		}
		break;
	case EP_PARTNER_SHARED:
		if (hw->ep_shm_info[src_epid].rx.info->v1i.rx_status &
		    FJES_RX_STOP_REQ_REQUEST) {
			set_bit(src_epid, &hw->epstop_req_bit);
			if (!work_pending(&hw->epstop_task))
				queue_work(adapter->control_wq,
					   &hw->epstop_task);
		}
		break;
	}
}

static void fjes_stop_req_irq(struct fjes_adapter *adapter, int src_epid)
{
	struct fjes_hw *hw = &adapter->hw;
	enum ep_partner_status status;

	set_bit(src_epid, &hw->hw_info.buffer_unshare_reserve_bit);

	status = fjes_hw_get_partner_ep_status(hw, src_epid);
	switch (status) {
	case EP_PARTNER_WAITING:
		hw->ep_shm_info[src_epid].tx.info->v1i.rx_status |=
				FJES_RX_STOP_REQ_DONE;
		clear_bit(src_epid, &hw->txrx_stop_req_bit);
		/* fall through */
	case EP_PARTNER_UNSHARE:
	case EP_PARTNER_COMPLETE:
	default:
		set_bit(src_epid, &adapter->unshare_watch_bitmask);
		if (!work_pending(&adapter->unshare_watch_task))
			queue_work(adapter->control_wq,
				   &adapter->unshare_watch_task);
		break;
	case EP_PARTNER_SHARED:
		set_bit(src_epid, &hw->epstop_req_bit);

		if (!work_pending(&hw->epstop_task))
			queue_work(adapter->control_wq, &hw->epstop_task);
		break;
	}
}

static void fjes_update_zone_irq(struct fjes_adapter *adapter,
				 int src_epid)
{
@@ -842,6 +910,16 @@ static irqreturn_t fjes_intr(int irq, void *data)
		if (icr & REG_ICTL_MASK_RX_DATA)
			fjes_rx_irq(adapter, icr & REG_IS_MASK_EPID);

		if (icr & REG_ICTL_MASK_DEV_STOP_REQ)
			fjes_stop_req_irq(adapter, icr & REG_IS_MASK_EPID);

		if (icr & REG_ICTL_MASK_TXRX_STOP_REQ)
			fjes_txrx_stop_req_irq(adapter, icr & REG_IS_MASK_EPID);

		if (icr & REG_ICTL_MASK_TXRX_STOP_DONE)
			fjes_hw_set_irqmask(hw,
					    REG_ICTL_MASK_TXRX_STOP_DONE, true);

		if (icr & REG_ICTL_MASK_INFO_UPDATE)
			fjes_update_zone_irq(adapter, icr & REG_IS_MASK_EPID);