2022-04-12 07:18:14

by Davidlohr Bueso

[permalink] [raw]
Subject: [PATCH 0/6] staging: Some tasklet removals

Hi,

The following are patches to further remove tasklet users out of
staging (none of such drivers at this point should continue using
these for async work). More complex users remain, which will be dealt
with in future patches. Compile-tested only.

Thanks!

Davidlohr Bueso (6):
staging/most, dim2: convert dim2_tasklet to threaded irq
staging/wlan-ng, prism2usb: replace reaper_bh tasklet with work
staging/wlan-ng, prism2usb: replace completion_bh tasklet with work
staging/ks7010: replace SME taslet with work
staging/rtl8712: remove event_tasklet
staging/rtl8192e,ieee80211: replace ps tasklet with work

drivers/staging/ks7010/ks_hostif.c | 21 ++++++------
drivers/staging/ks7010/ks_wlan.h | 2 +-
drivers/staging/most/dim2/dim2.c | 29 +++++-----------
drivers/staging/rtl8192e/rtllib.h | 2 +-
drivers/staging/rtl8192e/rtllib_rx.c | 2 +-
drivers/staging/rtl8192e/rtllib_softmac.c | 12 ++++---
.../staging/rtl8192u/ieee80211/ieee80211.h | 2 +-
.../rtl8192u/ieee80211/ieee80211_softmac.c | 15 ++++----
drivers/staging/rtl8712/rtl871x_cmd.h | 1 -
drivers/staging/wlan-ng/hfa384x.h | 4 +--
drivers/staging/wlan-ng/hfa384x_usb.c | 34 +++++++++----------
drivers/staging/wlan-ng/prism2usb.c | 8 ++---
12 files changed, 63 insertions(+), 69 deletions(-)

--
2.26.2


2022-04-12 09:23:59

by Davidlohr Bueso

[permalink] [raw]
Subject: [PATCH 1/6] staging/most, dim2: convert dim2_tasklet to threaded irq

Tasklets have long been deprecated as being too heavy on the system
by running in irq context - and this is not a performance critical
path. If a higher priority process wants to run, it must wait for
the tasklet to finish before doing so. A more suitable equivalent
is to converted to threaded irq instead and service channels in
regular task context.

Signed-off-by: Davidlohr Bueso <[email protected]>
---
drivers/staging/most/dim2/dim2.c | 29 +++++++++--------------------
1 file changed, 9 insertions(+), 20 deletions(-)

diff --git a/drivers/staging/most/dim2/dim2.c b/drivers/staging/most/dim2/dim2.c
index 29f8ce2a47f5..97dff82b7a5f 100644
--- a/drivers/staging/most/dim2/dim2.c
+++ b/drivers/staging/most/dim2/dim2.c
@@ -45,9 +45,6 @@ MODULE_PARM_DESC(fcnt, "Num of frames per sub-buffer for sync channels as a powe

static DEFINE_SPINLOCK(dim_lock);

-static void dim2_tasklet_fn(unsigned long data);
-static DECLARE_TASKLET_OLD(dim2_tasklet, dim2_tasklet_fn);
-
/**
* struct hdm_channel - private structure to keep channel specific data
* @name: channel name
@@ -361,15 +358,9 @@ static irqreturn_t dim2_mlb_isr(int irq, void *_dev)
return IRQ_HANDLED;
}

-/**
- * dim2_tasklet_fn - tasklet function
- * @data: private data
- *
- * Service each initialized channel, if needed
- */
-static void dim2_tasklet_fn(unsigned long data)
+static irqreturn_t dim2_task_irq(int irq, void *_dev)
{
- struct dim2_hdm *dev = (struct dim2_hdm *)data;
+ struct dim2_hdm *dev = _dev;
unsigned long flags;
int ch_idx;

@@ -385,6 +376,8 @@ static void dim2_tasklet_fn(unsigned long data)
while (!try_start_dim_transfer(dev->hch + ch_idx))
continue;
}
+
+ return IRQ_HANDLED;
}

/**
@@ -392,8 +385,8 @@ static void dim2_tasklet_fn(unsigned long data)
* @irq: irq number
* @_dev: private data
*
- * Acknowledge the interrupt and schedule a tasklet to service channels.
- * Return IRQ_HANDLED.
+ * Acknowledge the interrupt and service each initialized channel,
+ * if needed, in task context.
*/
static irqreturn_t dim2_ahb_isr(int irq, void *_dev)
{
@@ -405,9 +398,7 @@ static irqreturn_t dim2_ahb_isr(int irq, void *_dev)
dim_service_ahb_int_irq(get_active_channels(dev, buffer));
spin_unlock_irqrestore(&dim_lock, flags);

- dim2_tasklet.data = (unsigned long)dev;
- tasklet_schedule(&dim2_tasklet);
- return IRQ_HANDLED;
+ return IRQ_WAKE_THREAD;
}

/**
@@ -654,14 +645,12 @@ static int poison_channel(struct most_interface *most_iface, int ch_idx)
if (!hdm_ch->is_initialized)
return -EPERM;

- tasklet_disable(&dim2_tasklet);
spin_lock_irqsave(&dim_lock, flags);
hal_ret = dim_destroy_channel(&hdm_ch->ch);
hdm_ch->is_initialized = false;
if (ch_idx == dev->atx_idx)
dev->atx_idx = -1;
spin_unlock_irqrestore(&dim_lock, flags);
- tasklet_enable(&dim2_tasklet);
if (hal_ret != DIM_NO_ERROR) {
pr_err("HAL Failed to close channel %s\n", hdm_ch->name);
ret = -EFAULT;
@@ -821,8 +810,8 @@ static int dim2_probe(struct platform_device *pdev)
goto err_shutdown_dim;
}

- ret = devm_request_irq(&pdev->dev, irq, dim2_ahb_isr, 0,
- "dim2_ahb0_int", dev);
+ ret = devm_request_threaded_irq(&pdev->dev, irq, dim2_ahb_isr,
+ dim2_task_irq, 0, "dim2_ahb0_int", dev);
if (ret) {
dev_err(&pdev->dev, "failed to request ahb0_int irq %d\n", irq);
goto err_shutdown_dim;
--
2.26.2

2022-04-12 20:42:47

by Davidlohr Bueso

[permalink] [raw]
Subject: [PATCH 6/6] staging/rtl8192e,ieee80211: replace ps tasklet with work

Tasklets have long been deprecated as being too heavy on the system
by running in irq context - and this is not a performance critical
path. If a higher priority process wants to run, it must wait for
the tasklet to finish before doing so.

rtllib_sta_ps() and ieee80211_sta_ps() will now run in process context
and have further concurrency (tasklets being serialized among themselves),
but this is done holding the ieee->lock, so it should be fine.

Signed-off-by: Davidlohr Bueso <[email protected]>
---
drivers/staging/rtl8192e/rtllib.h | 2 +-
drivers/staging/rtl8192e/rtllib_rx.c | 2 +-
drivers/staging/rtl8192e/rtllib_softmac.c | 12 ++++++++----
drivers/staging/rtl8192u/ieee80211/ieee80211.h | 2 +-
.../rtl8192u/ieee80211/ieee80211_softmac.c | 15 +++++++++------
5 files changed, 20 insertions(+), 13 deletions(-)

diff --git a/drivers/staging/rtl8192e/rtllib.h b/drivers/staging/rtl8192e/rtllib.h
index c985e4ebc545..0ecd81a81866 100644
--- a/drivers/staging/rtl8192e/rtllib.h
+++ b/drivers/staging/rtl8192e/rtllib.h
@@ -1585,7 +1585,7 @@ struct rtllib_device {
short sta_sleep;
int ps_timeout;
int ps_period;
- struct tasklet_struct ps_task;
+ struct work_struct ps_task;
u64 ps_time;
bool polling;

diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c
index eb904b42f9c6..f5a44bc6d4e4 100644
--- a/drivers/staging/rtl8192e/rtllib_rx.c
+++ b/drivers/staging/rtl8192e/rtllib_rx.c
@@ -2721,7 +2721,7 @@ static void rtllib_rx_mgt(struct rtllib_device *ieee,
if (ieee->sta_sleep || (ieee->ps != RTLLIB_PS_DISABLED &&
ieee->iw_mode == IW_MODE_INFRA &&
ieee->state == RTLLIB_LINKED))
- tasklet_schedule(&ieee->ps_task);
+ schedule_work(&ieee->ps_task);

break;

diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c
index 4b6c2295a3cf..82bf05eb1cbf 100644
--- a/drivers/staging/rtl8192e/rtllib_softmac.c
+++ b/drivers/staging/rtl8192e/rtllib_softmac.c
@@ -2042,13 +2042,17 @@ static short rtllib_sta_ps_sleep(struct rtllib_device *ieee, u64 *time)

}

-static inline void rtllib_sta_ps(struct tasklet_struct *t)
+static inline void rtllib_sta_ps(struct work_struct *work)
{
- struct rtllib_device *ieee = from_tasklet(ieee, t, ps_task);
+ struct rtllib_device *ieee;
u64 time;
short sleep;
unsigned long flags, flags2;

+ ieee = container_of(work, struct rtllib_device, ps_task);
+ if (!ieee)
+ return;
+
spin_lock_irqsave(&ieee->lock, flags);

if ((ieee->ps == RTLLIB_PS_DISABLED ||
@@ -3028,7 +3032,7 @@ int rtllib_softmac_init(struct rtllib_device *ieee)
spin_lock_init(&ieee->mgmt_tx_lock);
spin_lock_init(&ieee->beacon_lock);

- tasklet_setup(&ieee->ps_task, rtllib_sta_ps);
+ INIT_WORK(&ieee->ps_task, rtllib_sta_ps);

return 0;
}
@@ -3050,8 +3054,8 @@ void rtllib_softmac_free(struct rtllib_device *ieee)
cancel_work_sync(&ieee->associate_complete_wq);
cancel_work_sync(&ieee->ips_leave_wq);
cancel_work_sync(&ieee->wx_sync_scan_wq);
+ cancel_work_sync(&ieee->ps_task);
mutex_unlock(&ieee->wx_mutex);
- tasklet_kill(&ieee->ps_task);
}

static inline struct sk_buff *
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h
index 68c0bf9a191a..b577f9c81f85 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211.h
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h
@@ -1790,7 +1790,7 @@ struct ieee80211_device {
short sta_sleep;
int ps_timeout;
int ps_period;
- struct tasklet_struct ps_task;
+ struct work_struct ps_task;
u32 ps_th;
u32 ps_tl;

diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
index 1a43979939a8..4e8fbd2410a1 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
@@ -1687,14 +1687,17 @@ static short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h,
return 1;
}

-static inline void ieee80211_sta_ps(struct tasklet_struct *t)
+static inline void ieee80211_sta_ps(struct work_struct *work)
{
- struct ieee80211_device *ieee = from_tasklet(ieee, t, ps_task);
+ struct ieee80211_device *ieee;
u32 th, tl;
short sleep;
-
unsigned long flags, flags2;

+ ieee = container_of(work, struct ieee80211_device, ps_task);
+ if (!ieee)
+ return;
+
spin_lock_irqsave(&ieee->lock, flags);

if ((ieee->ps == IEEE80211_PS_DISABLED ||
@@ -1897,7 +1900,7 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
if (ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED &&
ieee->iw_mode == IW_MODE_INFRA &&
ieee->state == IEEE80211_LINKED))
- tasklet_schedule(&ieee->ps_task);
+ schedule_work(&ieee->ps_task);

if (WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_PROBE_RESP &&
WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_BEACON)
@@ -2602,7 +2605,7 @@ void ieee80211_softmac_init(struct ieee80211_device *ieee)
spin_lock_init(&ieee->mgmt_tx_lock);
spin_lock_init(&ieee->beacon_lock);

- tasklet_setup(&ieee->ps_task, ieee80211_sta_ps);
+ INIT_WORK(&ieee->ps_task, ieee80211_sta_ps);
}

void ieee80211_softmac_free(struct ieee80211_device *ieee)
@@ -2613,7 +2616,7 @@ void ieee80211_softmac_free(struct ieee80211_device *ieee)
del_timer_sync(&ieee->associate_timer);

cancel_delayed_work(&ieee->associate_retry_wq);
-
+ cancel_work_sync(&ieee->ps_task);
mutex_unlock(&ieee->wx_mutex);
}

--
2.26.2

2022-04-13 00:01:45

by Davidlohr Bueso

[permalink] [raw]
Subject: [PATCH 3/6] staging/wlan-ng, prism2usb: replace completion_bh tasklet with work

Tasklets have long been deprecated as being too heavy on the system
by running in irq context - and this is not a performance critical
path. If a higher priority process wants to run, it must wait for
the tasklet to finish before doing so.

The completion_bh tasklet will now run in process context and have
further concurrency (tasklets being serialized among themselves),
but this is done holding the ctlxq.lock, so it should be fine.

Signed-off-by: Davidlohr Bueso <[email protected]>
---
drivers/staging/wlan-ng/hfa384x.h | 2 +-
drivers/staging/wlan-ng/hfa384x_usb.c | 22 +++++++++++-----------
drivers/staging/wlan-ng/prism2usb.c | 6 +++---
3 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h
index 7480d808e946..0611e37df6ac 100644
--- a/drivers/staging/wlan-ng/hfa384x.h
+++ b/drivers/staging/wlan-ng/hfa384x.h
@@ -1228,7 +1228,7 @@ struct hfa384x {
struct timer_list throttle;

struct work_struct reaper_bh;
- struct tasklet_struct completion_bh;
+ struct work_struct completion_bh;

struct work_struct usb_work;

diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c
index 4000c321cb3a..33844526c797 100644
--- a/drivers/staging/wlan-ng/hfa384x_usb.c
+++ b/drivers/staging/wlan-ng/hfa384x_usb.c
@@ -191,7 +191,7 @@ static void hfa384x_usbctlx_resptimerfn(struct timer_list *t);

static void hfa384x_usb_throttlefn(struct timer_list *t);

-static void hfa384x_usbctlx_completion_task(struct tasklet_struct *t);
+static void hfa384x_usbctlx_completion_task(struct work_struct *work);

static void hfa384x_usbctlx_reaper_task(struct work_struct *work);

@@ -540,7 +540,7 @@ void hfa384x_create(struct hfa384x *hw, struct usb_device *usb)
skb_queue_head_init(&hw->authq);

INIT_WORK(&hw->reaper_bh, hfa384x_usbctlx_reaper_task);
- tasklet_setup(&hw->completion_bh, hfa384x_usbctlx_completion_task);
+ INIT_WORK(&hw->completion_bh, hfa384x_usbctlx_completion_task);
INIT_WORK(&hw->link_bh, prism2sta_processing_defer);
INIT_WORK(&hw->usb_work, hfa384x_usb_defer);

@@ -2585,10 +2585,10 @@ void hfa384x_tx_timeout(struct wlandevice *wlandev)
/*----------------------------------------------------------------
* hfa384x_usbctlx_reaper_task
*
- * Deferred work to delete dead CTLX objects
+ * Deferred work callback to delete dead CTLX objects
*
* Arguments:
- * data ptr to a struct hfa384x
+ * work contains ptr to a struct hfa384x
*
* Returns:
*
@@ -2618,21 +2618,21 @@ static void hfa384x_usbctlx_reaper_task(struct work_struct *work)
/*----------------------------------------------------------------
* hfa384x_usbctlx_completion_task
*
- * Tasklet to call completion handlers for returned CTLXs
+ * Deferred work callback to call completion handlers for returned CTLXs
*
* Arguments:
- * data ptr to struct hfa384x
+ * work contains ptr to a struct hfa384x
*
* Returns:
* Nothing
*
* Call context:
- * Interrupt
+ * Task
*----------------------------------------------------------------
*/
-static void hfa384x_usbctlx_completion_task(struct tasklet_struct *t)
+static void hfa384x_usbctlx_completion_task(struct work_struct *work)
{
- struct hfa384x *hw = from_tasklet(hw, t, completion_bh);
+ struct hfa384x *hw = container_of(work, struct hfa384x, reaper_bh);
struct hfa384x_usbctlx *ctlx, *temp;
unsigned long flags;

@@ -2743,7 +2743,7 @@ static int unlocked_usbctlx_cancel_async(struct hfa384x *hw,
* aren't active and the timers should have been stopped.
*
* The CTLX is migrated to the "completing" queue, and the completing
- * tasklet is scheduled.
+ * work is scheduled.
*
* Arguments:
* hw ptr to a struct hfa384x structure
@@ -2766,7 +2766,7 @@ static void unlocked_usbctlx_complete(struct hfa384x *hw,
* queue.
*/
list_move_tail(&ctlx->list, &hw->ctlxq.completing);
- tasklet_schedule(&hw->completion_bh);
+ schedule_work(&hw->completion_bh);

switch (ctlx->state) {
case CTLX_COMPLETE:
diff --git a/drivers/staging/wlan-ng/prism2usb.c b/drivers/staging/wlan-ng/prism2usb.c
index 36340f36b0cb..e13da7fadfff 100644
--- a/drivers/staging/wlan-ng/prism2usb.c
+++ b/drivers/staging/wlan-ng/prism2usb.c
@@ -165,8 +165,8 @@ static void prism2sta_disconnect_usb(struct usb_interface *interface)
spin_unlock_irqrestore(&hw->ctlxq.lock, flags);

/* There's no hardware to shutdown, but the driver
- * might have some tasks or tasklets that must be
- * stopped before we can tear everything down.
+ * might have some tasks that must be stopped before
+ * we can tear everything down.
*/
prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable);

@@ -181,7 +181,7 @@ static void prism2sta_disconnect_usb(struct usb_interface *interface)
usb_kill_urb(&hw->tx_urb);
usb_kill_urb(&hw->ctlx_urb);

- tasklet_kill(&hw->completion_bh);
+ cancel_work_sync(&hw->completion_bh);
cancel_work_sync(&hw->reaper_bh);

cancel_work_sync(&hw->link_bh);
--
2.26.2

2022-04-13 00:04:14

by Davidlohr Bueso

[permalink] [raw]
Subject: [PATCH 4/6] staging/ks7010: replace SME taslet with work

Tasklets have long been deprecated as being too heavy on the system
by running in irq context - and this is not a performance critical
path. If a higher priority process wants to run, it must wait for
the tasklet to finish before doing so.

The execution of the SME event will now occur in task context. There
are, however, changes in concurrency. Workqueues, unlike tasklets,
are not serialized among themselves and can run concurrently
updating sme_i.qhead. However, the current code is already exposed
in same ways, regardless of the deferral mechanism, in that
hostif_sme_enqueue() does unserialized enqueues updating sme_i.qtail.

Also get rid of the bogus (power save) tasklet enabling, as it
is never disabled to begin with.

Signed-off-by: Davidlohr Bueso <[email protected]>
---
drivers/staging/ks7010/ks_hostif.c | 21 ++++++++++-----------
drivers/staging/ks7010/ks_wlan.h | 2 +-
2 files changed, 11 insertions(+), 12 deletions(-)

diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c
index 1c63d595313d..f1aa3be4261d 100644
--- a/drivers/staging/ks7010/ks_hostif.c
+++ b/drivers/staging/ks7010/ks_hostif.c
@@ -84,10 +84,6 @@ static void ks_wlan_hw_wakeup_task(struct work_struct *work)
return;
}
}
-
- /* power save */
- if (atomic_read(&priv->sme_task.count) > 0)
- tasklet_enable(&priv->sme_task);
}

static void ks_wlan_do_power_save(struct ks_wlan_private *priv)
@@ -2200,10 +2196,13 @@ static void hostif_sme_execute(struct ks_wlan_private *priv, int event)
}
}

-static
-void hostif_sme_task(struct tasklet_struct *t)
+static void hostif_sme_work(struct work_struct *work)
{
- struct ks_wlan_private *priv = from_tasklet(priv, t, sme_task);
+ struct ks_wlan_private *priv;
+
+ priv = container_of(work, struct ks_wlan_private, sme_work);
+ if (!priv)
+ return;

if (priv->dev_state < DEVICE_STATE_BOOT)
return;
@@ -2214,7 +2213,7 @@ void hostif_sme_task(struct tasklet_struct *t)
hostif_sme_execute(priv, priv->sme_i.event_buff[priv->sme_i.qhead]);
inc_smeqhead(priv);
if (cnt_smeqbody(priv) > 0)
- tasklet_schedule(&priv->sme_task);
+ schedule_work(&priv->sme_work);
}

/* send to Station Management Entity module */
@@ -2229,7 +2228,7 @@ void hostif_sme_enqueue(struct ks_wlan_private *priv, u16 event)
netdev_err(priv->net_dev, "sme queue buffer overflow\n");
}

- tasklet_schedule(&priv->sme_task);
+ schedule_work(&priv->sme_work);
}

static inline void hostif_aplist_init(struct ks_wlan_private *priv)
@@ -2254,7 +2253,7 @@ static inline void hostif_sme_init(struct ks_wlan_private *priv)
priv->sme_i.qtail = 0;
spin_lock_init(&priv->sme_i.sme_spin);
priv->sme_i.sme_flag = 0;
- tasklet_setup(&priv->sme_task, hostif_sme_task);
+ INIT_WORK(&priv->sme_work, hostif_sme_work);
}

static inline void hostif_wpa_init(struct ks_wlan_private *priv)
@@ -2312,5 +2311,5 @@ int hostif_init(struct ks_wlan_private *priv)

void hostif_exit(struct ks_wlan_private *priv)
{
- tasklet_kill(&priv->sme_task);
+ cancel_work_sync(&priv->sme_work);
}
diff --git a/drivers/staging/ks7010/ks_wlan.h b/drivers/staging/ks7010/ks_wlan.h
index 7aaf8d780939..3e9a91b5131c 100644
--- a/drivers/staging/ks7010/ks_wlan.h
+++ b/drivers/staging/ks7010/ks_wlan.h
@@ -449,7 +449,7 @@ struct ks_wlan_private {
struct sme_info sme_i;
u8 *rxp;
unsigned int rx_size;
- struct tasklet_struct sme_task;
+ struct work_struct sme_work;
struct work_struct wakeup_work;
int scan_ind_count;

--
2.26.2