fjes: handle receive cancellation request interrupt

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

Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Taku Izumi 2015-08-21 17:29:37 +09:00 committed by David S. Miller
parent b5a9152d99
commit cb79eaaec4
1 changed files with 78 additions and 0 deletions

View File

@ -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);