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

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

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: default avatarTaku Izumi <izumi.taku@jp.fujitsu.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9acf51cb
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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;
};

+63 −0
Original line number Diff line number Diff line
@@ -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);