fjes: raise_intr_rxdata_task

This patch add raise_intr_rxdata_task.
Extended Socket Network Device is shared memory
based, so someone's transmission denotes other's
reception. In order to notify receivers, sender
has to raise interruption of receivers.
raise_intr_rxdata_task does this work.

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:25 +09:00 committed by David S. Miller
parent 9acf51cbf7
commit b772b9dc63
2 changed files with 67 additions and 0 deletions

View file

@ -50,6 +50,10 @@ struct fjes_adapter {
bool irq_registered;
struct workqueue_struct *txrx_wq;
struct work_struct raise_intr_rxdata_task;
struct fjes_hw hw;
};

View file

@ -52,6 +52,7 @@ static int fjes_close(struct net_device *);
static int fjes_setup_resources(struct fjes_adapter *);
static void fjes_free_resources(struct fjes_adapter *);
static netdev_tx_t fjes_xmit_frame(struct sk_buff *, struct net_device *);
static void fjes_raise_intr_rxdata_task(struct work_struct *);
static irqreturn_t fjes_intr(int, void*);
static int fjes_acpi_add(struct acpi_device *);
@ -276,6 +277,8 @@ static int fjes_close(struct net_device *netdev)
fjes_free_irq(adapter);
cancel_work_sync(&adapter->raise_intr_rxdata_task);
fjes_hw_wait_epstop(hw);
fjes_free_resources(adapter);
@ -404,6 +407,54 @@ static void fjes_free_resources(struct fjes_adapter *adapter)
}
}
static void fjes_raise_intr_rxdata_task(struct work_struct *work)
{
struct fjes_adapter *adapter = container_of(work,
struct fjes_adapter, raise_intr_rxdata_task);
struct fjes_hw *hw = &adapter->hw;
enum ep_partner_status pstatus;
int max_epid, my_epid, epid;
my_epid = hw->my_epid;
max_epid = hw->max_epid;
for (epid = 0; epid < max_epid; epid++)
hw->ep_shm_info[epid].tx_status_work = 0;
for (epid = 0; epid < max_epid; epid++) {
if (epid == my_epid)
continue;
pstatus = fjes_hw_get_partner_ep_status(hw, epid);
if (pstatus == EP_PARTNER_SHARED) {
hw->ep_shm_info[epid].tx_status_work =
hw->ep_shm_info[epid].tx.info->v1i.tx_status;
if (hw->ep_shm_info[epid].tx_status_work ==
FJES_TX_DELAY_SEND_PENDING) {
hw->ep_shm_info[epid].tx.info->v1i.tx_status =
FJES_TX_DELAY_SEND_NONE;
}
}
}
for (epid = 0; epid < max_epid; epid++) {
if (epid == my_epid)
continue;
pstatus = fjes_hw_get_partner_ep_status(hw, epid);
if ((hw->ep_shm_info[epid].tx_status_work ==
FJES_TX_DELAY_SEND_PENDING) &&
(pstatus == EP_PARTNER_SHARED) &&
!(hw->ep_shm_info[epid].rx.info->v1i.rx_status)) {
fjes_hw_raise_interrupt(hw, epid,
REG_ICTL_MASK_RX_DATA);
}
}
usleep_range(500, 1000);
}
static int fjes_tx_send(struct fjes_adapter *adapter, int dest,
void *data, size_t len)
{
@ -416,6 +467,9 @@ static int fjes_tx_send(struct fjes_adapter *adapter, int dest,
adapter->hw.ep_shm_info[dest].tx.info->v1i.tx_status =
FJES_TX_DELAY_SEND_PENDING;
if (!work_pending(&adapter->raise_intr_rxdata_task))
queue_work(adapter->txrx_wq,
&adapter->raise_intr_rxdata_task);
retval = 0;
return retval;
@ -630,6 +684,11 @@ static int fjes_probe(struct platform_device *plat_dev)
adapter->force_reset = false;
adapter->open_guard = false;
adapter->txrx_wq = create_workqueue(DRV_NAME "/txrx");
INIT_WORK(&adapter->raise_intr_rxdata_task,
fjes_raise_intr_rxdata_task);
res = platform_get_resource(plat_dev, IORESOURCE_MEM, 0);
hw->hw_res.start = res->start;
hw->hw_res.size = res->end - res->start + 1;
@ -669,6 +728,10 @@ static int fjes_remove(struct platform_device *plat_dev)
struct fjes_adapter *adapter = netdev_priv(netdev);
struct fjes_hw *hw = &adapter->hw;
cancel_work_sync(&adapter->raise_intr_rxdata_task);
if (adapter->txrx_wq)
destroy_workqueue(adapter->txrx_wq);
unregister_netdev(netdev);
fjes_hw_exit(hw);