[net-next v3 12/15] net: ibmvnic: Convert tasklet API to new bottom half workqueue mechanism
Migrate tasklet APIs to the new bottom half workqueue mechanism. It replaces all occurrences of tasklet usage with the appropriate workqueue APIs throughout the ibmvnic driver. This transition ensures compatibility with the latest design and enhances performance. Signed-off-by: Allen Pais --- drivers/net/ethernet/ibm/ibmvnic.c | 24 drivers/net/ethernet/ibm/ibmvnic.h | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 23ebeb143987..0156efeff96a 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -2737,7 +2737,7 @@ static const char *reset_reason_to_string(enum ibmvnic_reset_reason reason) /* * Initialize the init_done completion and return code values. We * can get a transport event just after registering the CRQ and the - * tasklet will use this to communicate the transport event. To ensure + * bh work will use this to communicate the transport event. To ensure * we don't miss the notification/error, initialize these _before_ * regisering the CRQ. */ @@ -4447,7 +4447,7 @@ static void send_request_cap(struct ibmvnic_adapter *adapter, int retry) int cap_reqs; /* We send out 6 or 7 REQUEST_CAPABILITY CRQs below (depending on -* the PROMISC flag). Initialize this count upfront. When the tasklet +* the PROMISC flag). Initialize this count upfront. When the bh work * receives a response to all of these, it will send the next protocol * message (QUERY_IP_OFFLOAD). */ @@ -4983,7 +4983,7 @@ static void send_query_cap(struct ibmvnic_adapter *adapter) int cap_reqs; /* We send out 25 QUERY_CAPABILITY CRQs below. Initialize this count -* upfront. When the tasklet receives a response to all of these, it +* upfront. When the bh work receives a response to all of these, it * can send out the next protocol messaage (REQUEST_CAPABILITY). */ cap_reqs = 25; @@ -5495,7 +5495,7 @@ static int handle_login_rsp(union ibmvnic_crq *login_rsp_crq, int i; /* CHECK: Test/set of login_pending does not need to be atomic -* because only ibmvnic_tasklet tests/clears this. +* because only ibmvnic_bh_work tests/clears this. */ if (!adapter->login_pending) { netdev_warn(netdev, "Ignoring unexpected login response\n"); @@ -6081,13 +6081,13 @@ static irqreturn_t ibmvnic_interrupt(int irq, void *instance) { struct ibmvnic_adapter *adapter = instance; - tasklet_schedule(&adapter->tasklet); + queue_work(system_bh_wq, &adapter->bh_work); return IRQ_HANDLED; } -static void ibmvnic_tasklet(struct tasklet_struct *t) +static void ibmvnic_bh_work(struct work_struct *work) { - struct ibmvnic_adapter *adapter = from_tasklet(adapter, t, tasklet); + struct ibmvnic_adapter *adapter = from_work(adapter, work, bh_work); struct ibmvnic_crq_queue *queue = &adapter->crq; union ibmvnic_crq *crq; unsigned long flags; @@ -6168,7 +6168,7 @@ static void release_crq_queue(struct ibmvnic_adapter *adapter) netdev_dbg(adapter->netdev, "Releasing CRQ\n"); free_irq(vdev->irq, adapter); - tasklet_kill(&adapter->tasklet); + cancel_work_sync(&adapter->bh_work); do { rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address); } while (rc == H_BUSY || H_IS_LONG_BUSY(rc)); @@ -6219,7 +6219,7 @@ static int init_crq_queue(struct ibmvnic_adapter *adapter) retrc = 0; - tasklet_setup(&adapter->tasklet, (void *)ibmvnic_tasklet); + INIT_WORK(&adapter->bh_work, (void *)ibmvnic_bh_work); netdev_dbg(adapter->netdev, "registering irq 0x%x\n", vdev->irq); snprintf(crq->name, sizeof(crq->name), "ibmvnic-%x", @@ -6241,12 +6241,12 @@ static int init_crq_queue(struct ibmvnic_adapter *adapter) spin_lock_init(&crq->lock); /* process any CRQs that were queued before we enabled interrupts */ - tasklet_schedule(&adapter->tasklet); + queue_work(system_bh_wq, &adapter->bh_work); return retrc; req_irq_failed: - tasklet_kill(&adapter->tasklet); + cancel_work_sync(&adapter->bh_work); do { rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address); } while (rc == H_BUSY || H_IS_LONG_BUSY(rc)); @@ -6639,7 +6639,7 @@ static int ibmvnic_resume(struct device *dev) if (adapter->state != VNIC_OPEN) return 0; - tasklet_schedule(&adapter->tasklet); + queue_work(system_bh_wq, &adapter->bh_work); return 0; } diff --git a/drivers/net/ethernet/ibm/ibmvnic.h b/drivers/net/
[PATCH 12/15] net: ibmvnic: Convert tasklet API to new bottom half workqueue mechanism
Migrate tasklet APIs to the new bottom half workqueue mechanism. It replaces all occurrences of tasklet usage with the appropriate workqueue APIs throughout the ibmvnic driver. This transition ensures compatibility with the latest design and enhances performance. Signed-off-by: Allen Pais --- drivers/net/ethernet/ibm/ibmvnic.c | 24 drivers/net/ethernet/ibm/ibmvnic.h | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 5e9a93bdb518..2e817a560c3a 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -2725,7 +2725,7 @@ static const char *reset_reason_to_string(enum ibmvnic_reset_reason reason) /* * Initialize the init_done completion and return code values. We * can get a transport event just after registering the CRQ and the - * tasklet will use this to communicate the transport event. To ensure + * bh work will use this to communicate the transport event. To ensure * we don't miss the notification/error, initialize these _before_ * regisering the CRQ. */ @@ -4429,7 +4429,7 @@ static void send_request_cap(struct ibmvnic_adapter *adapter, int retry) int cap_reqs; /* We send out 6 or 7 REQUEST_CAPABILITY CRQs below (depending on -* the PROMISC flag). Initialize this count upfront. When the tasklet +* the PROMISC flag). Initialize this count upfront. When the bh work * receives a response to all of these, it will send the next protocol * message (QUERY_IP_OFFLOAD). */ @@ -4965,7 +4965,7 @@ static void send_query_cap(struct ibmvnic_adapter *adapter) int cap_reqs; /* We send out 25 QUERY_CAPABILITY CRQs below. Initialize this count -* upfront. When the tasklet receives a response to all of these, it +* upfront. When the bh work receives a response to all of these, it * can send out the next protocol messaage (REQUEST_CAPABILITY). */ cap_reqs = 25; @@ -5477,7 +5477,7 @@ static int handle_login_rsp(union ibmvnic_crq *login_rsp_crq, int i; /* CHECK: Test/set of login_pending does not need to be atomic -* because only ibmvnic_tasklet tests/clears this. +* because only ibmvnic_bh_work tests/clears this. */ if (!adapter->login_pending) { netdev_warn(netdev, "Ignoring unexpected login response\n"); @@ -6063,13 +6063,13 @@ static irqreturn_t ibmvnic_interrupt(int irq, void *instance) { struct ibmvnic_adapter *adapter = instance; - tasklet_schedule(&adapter->tasklet); + queue_work(system_bh_wq, &adapter->bh_work); return IRQ_HANDLED; } -static void ibmvnic_tasklet(struct tasklet_struct *t) +static void ibmvnic_bh_work(struct work_struct *work) { - struct ibmvnic_adapter *adapter = from_tasklet(adapter, t, tasklet); + struct ibmvnic_adapter *adapter = from_work(adapter, work, bh_work); struct ibmvnic_crq_queue *queue = &adapter->crq; union ibmvnic_crq *crq; unsigned long flags; @@ -6150,7 +6150,7 @@ static void release_crq_queue(struct ibmvnic_adapter *adapter) netdev_dbg(adapter->netdev, "Releasing CRQ\n"); free_irq(vdev->irq, adapter); - tasklet_kill(&adapter->tasklet); + cancel_work_sync(&adapter->bh_work); do { rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address); } while (rc == H_BUSY || H_IS_LONG_BUSY(rc)); @@ -6201,7 +6201,7 @@ static int init_crq_queue(struct ibmvnic_adapter *adapter) retrc = 0; - tasklet_setup(&adapter->tasklet, (void *)ibmvnic_tasklet); + INIT_WORK(&adapter->bh_work, (void *)ibmvnic_bh_work); netdev_dbg(adapter->netdev, "registering irq 0x%x\n", vdev->irq); snprintf(crq->name, sizeof(crq->name), "ibmvnic-%x", @@ -6223,12 +6223,12 @@ static int init_crq_queue(struct ibmvnic_adapter *adapter) spin_lock_init(&crq->lock); /* process any CRQs that were queued before we enabled interrupts */ - tasklet_schedule(&adapter->tasklet); + queue_work(system_bh_wq, &adapter->bh_work); return retrc; req_irq_failed: - tasklet_kill(&adapter->tasklet); + cancel_work_sync(&adapter->bh_work); do { rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address); } while (rc == H_BUSY || H_IS_LONG_BUSY(rc)); @@ -6621,7 +6621,7 @@ static int ibmvnic_resume(struct device *dev) if (adapter->state != VNIC_OPEN) return 0; - tasklet_schedule(&adapter->tasklet); + queue_work(system_bh_wq, &adapter->bh_work); return 0; } diff --git a/drivers/net/ethernet/ibm/ibmvnic.h b/drivers/net/
Re: [PATCH 9/9] mmc: Convert from tasklet to BH workqueue
> On Jun 3, 2024, at 5:38 AM, Aubin Constans > wrote: > > On 27/03/2024 17:03, Allen Pais wrote: >> EXTERNAL EMAIL: Do not click links or open attachments unless you know the >> content is safe >> The only generic interface to execute asynchronously in the BH context is >> tasklet; however, it's marked deprecated and has some design flaws. To >> replace tasklets, BH workqueue support was recently added. A BH workqueue >> behaves similarly to regular workqueues except that the queued work items >> are executed in the BH context. >> This patch converts drivers/infiniband/* from tasklet to BH workqueue. >> Based on the work done by Tejun Heo >> Branch: https://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git for-6.10 >> Signed-off-by: Allen Pais >> --- >> drivers/mmc/host/atmel-mci.c | 35 - > [...] > > For atmel-mci, judging from a few simple tests, performance is preserved. > E.g. writing to a SD Card on the SAMA5D3-Xplained board: > time dd if=/dev/zero of=/opt/_del_me bs=4k count=64k > > Base 6.9.0 : 0.07user 5.05system 0:18.92elapsed 27%CPU > Patched 6.9.0+: 0.12user 4.92system 0:18.76elapsed 26%CPU > > However, please resolve what checkpatch is complaining about: > scripts/checkpatch.pl --strict > PATCH-9-9-mmc-Convert-from-tasklet-to-BH-workqueue.mbox > > WARNING: please, no space before tabs > #72: FILE: drivers/mmc/host/atmel-mci.c:367: > +^Istruct work_struct ^Iwork;$ > > Same as discussions on the USB patch[1] and others in this series, I am also > in favour of "workqueue" or similar in the comments, rather than just "work". Will send out a new version. Thank you very much for testing and providing your review. - Allen > > Apart from that: > Tested-by: Aubin Constans > Acked-by: Aubin Constans > > Thanks. > > [1]: > https://lore.kernel.org/linux-mmc/caomdwslippfm3oztpjzz4uf4m+e_8qaotemckbxawlnktqx...@mail.gmail.com/
Re: [PATCH 1/1] [RFC] ethernet: Convert from tasklet to BH workqueue
Paolo, > On Wed, 2024-05-08 at 21:16 +0100, Simon Horman wrote: > > * As this patch seems to involve many non-trivial changes > > it seems to me that it would be best to break it up somehow. > > To allow proper review. > > I would like to stress this latest point: it looks like the changes to > all the drivers are completely independent. If so, you have to break > the series on a per driver basis. Since the total number of patch will > be higher then 15 (maximum size allowed on netdev) you will have to > split this in several smaller series. > Right, it's a valid point. Per-driver might not work. Depending on the driver and changes, I will try and make it an independent series. > Beyond making the change reviewable, it will allow eventually reverting > the changes individually, should that cause any regressions. > Thank you, I understand the concern here. Will work on it in v2. Thank you very much for your time and suggestions. - Allen
Re: [PATCH 1/1] [RFC] ethernet: Convert from tasklet to BH workqueue
> > > On Tue, May 07, 2024 at 07:01:11PM +0000, Allen Pais wrote: > > > > The only generic interface to execute asynchronously in the BH context > > > > is > > > > tasklet; however, it's marked deprecated and has some design flaws. To > > > > replace tasklets, BH workqueue support was recently added. A BH > > > > workqueue > > > > behaves similarly to regular workqueues except that the queued work > > > > items > > > > are executed in the BH context. > > > > > > > > This patch converts drivers/ethernet/* from tasklet to BH workqueue. > > > > > > I doubt you're going to get many comments on this patch, being so large > > > and spread across all drivers. I'm not going to bother trying to edit > > > this down to something more sensible, I'll just plonk my comment here. > > > > > > For the mvpp2 driver, you're only updating a comment - and looking at > > > it, the comment no longer reflects the code. It doesn't make use of > > > tasklets at all. That makes the comment wrong whether or not it's > > > updated. So I suggest rather than doing a search and replace for > > > "tasklet" to "BH blahblah" (sorry, I don't remember what you replaced > > > it with) just get rid of that bit of the comment. > > > > > > > Thank you Russell. > > > > I will get rid of the comment. If it helps, I can create a patch for each > > driver. We did that in the past, with this series, I thought it would be > > easier to apply one patch. > > Hi Allen and Russell, > > My 2c worth: > > * In general non bug-fix patches for networking code should be targeted at > net-next. This means that they should include net-next in the subject, > and be based on that tree. > > Subject: [PATCH net-next] ... > > * This series does not appear to apply to net-next > > * This series appears to depend on code which is not present in net-next. > f.e. disable_work_sync > > * The Infiniband patches should probably be submitted separately > to the relevant maintainers > > * As this patch seems to involve many non-trivial changes > it seems to me that it would be best to break it up somehow. > To allow proper review. > > * Patch-sets for net-next should be limited to 15 patches, > so perhaps multiple sequential batches would be a way forwards. > > Link: https://docs.kernel.org/process/maintainer-netdev.html Thank you very much for taking the time to write back. Since the patches that are necessary for this series are not in net-next, I could not target net-next. I will wait for the patches to land in net-next, and the v2 will be broken into multiple smaller sets(per driver). Thanks. Allen
Re: [PATCH 1/1] [RFC] ethernet: Convert from tasklet to BH workqueue
On Tue, May 7, 2024 at 12:23 PM Russell King (Oracle) wrote: > > On Tue, May 07, 2024 at 07:01:11PM +, Allen Pais wrote: > > The only generic interface to execute asynchronously in the BH context is > > tasklet; however, it's marked deprecated and has some design flaws. To > > replace tasklets, BH workqueue support was recently added. A BH workqueue > > behaves similarly to regular workqueues except that the queued work items > > are executed in the BH context. > > > > This patch converts drivers/ethernet/* from tasklet to BH workqueue. > > I doubt you're going to get many comments on this patch, being so large > and spread across all drivers. I'm not going to bother trying to edit > this down to something more sensible, I'll just plonk my comment here. > > For the mvpp2 driver, you're only updating a comment - and looking at > it, the comment no longer reflects the code. It doesn't make use of > tasklets at all. That makes the comment wrong whether or not it's > updated. So I suggest rather than doing a search and replace for > "tasklet" to "BH blahblah" (sorry, I don't remember what you replaced > it with) just get rid of that bit of the comment. > Thank you Russell. I will get rid of the comment. If it helps, I can create a patch for each driver. We did that in the past, with this series, I thought it would be easier to apply one patch. Thanks, - Allen
[PATCH 1/1] [RFC] ethernet: Convert from tasklet to BH workqueue
The only generic interface to execute asynchronously in the BH context is tasklet; however, it's marked deprecated and has some design flaws. To replace tasklets, BH workqueue support was recently added. A BH workqueue behaves similarly to regular workqueues except that the queued work items are executed in the BH context. This patch converts drivers/ethernet/* from tasklet to BH workqueue. Based on the work done by Tejun Heo Branch: https://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git disable_work-v1 Signed-off-by: Allen Pais --- drivers/infiniband/hw/mlx4/cq.c | 2 +- drivers/infiniband/hw/mlx5/cq.c | 2 +- drivers/net/ethernet/alteon/acenic.c | 26 +++ drivers/net/ethernet/alteon/acenic.h | 7 +- drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 30 drivers/net/ethernet/amd/xgbe/xgbe-i2c.c | 16 ++--- drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 16 ++--- drivers/net/ethernet/amd/xgbe/xgbe-pci.c | 4 +- drivers/net/ethernet/amd/xgbe/xgbe.h | 11 +-- drivers/net/ethernet/broadcom/cnic.c | 19 ++--- drivers/net/ethernet/broadcom/cnic.h | 2 +- drivers/net/ethernet/cadence/macb.h | 3 +- drivers/net/ethernet/cadence/macb_main.c | 10 +-- .../net/ethernet/cavium/liquidio/lio_core.c | 4 +- .../net/ethernet/cavium/liquidio/lio_main.c | 25 +++ .../ethernet/cavium/liquidio/lio_vf_main.c| 10 +-- .../ethernet/cavium/liquidio/octeon_droq.c| 4 +- .../ethernet/cavium/liquidio/octeon_main.h| 5 +- .../net/ethernet/cavium/octeon/octeon_mgmt.c | 12 ++-- drivers/net/ethernet/cavium/thunder/nic.h | 5 +- .../net/ethernet/cavium/thunder/nicvf_main.c | 24 +++ .../ethernet/cavium/thunder/nicvf_queues.c| 5 +- .../ethernet/cavium/thunder/nicvf_queues.h| 3 +- drivers/net/ethernet/chelsio/cxgb/sge.c | 19 ++--- drivers/net/ethernet/chelsio/cxgb4/cxgb4.h| 9 +-- .../net/ethernet/chelsio/cxgb4/cxgb4_main.c | 2 +- .../ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c | 4 +- .../net/ethernet/chelsio/cxgb4/cxgb4_uld.c| 2 +- drivers/net/ethernet/chelsio/cxgb4/sge.c | 41 +-- drivers/net/ethernet/chelsio/cxgb4vf/sge.c| 6 +- drivers/net/ethernet/dlink/sundance.c | 41 +-- .../net/ethernet/huawei/hinic/hinic_hw_cmdq.c | 2 +- .../net/ethernet/huawei/hinic/hinic_hw_eqs.c | 17 +++-- .../net/ethernet/huawei/hinic/hinic_hw_eqs.h | 2 +- drivers/net/ethernet/ibm/ehea/ehea.h | 3 +- drivers/net/ethernet/ibm/ehea/ehea_main.c | 14 ++-- drivers/net/ethernet/ibm/ibmvnic.c| 24 +++ drivers/net/ethernet/ibm/ibmvnic.h| 2 +- drivers/net/ethernet/jme.c| 72 +-- drivers/net/ethernet/jme.h| 9 +-- .../net/ethernet/marvell/mvpp2/mvpp2_main.c | 2 +- drivers/net/ethernet/marvell/skge.c | 12 ++-- drivers/net/ethernet/marvell/skge.h | 3 +- drivers/net/ethernet/mediatek/mtk_wed_wo.c| 12 ++-- drivers/net/ethernet/mediatek/mtk_wed_wo.h| 3 +- drivers/net/ethernet/mellanox/mlx4/cq.c | 42 +-- drivers/net/ethernet/mellanox/mlx4/eq.c | 10 +-- drivers/net/ethernet/mellanox/mlx4/mlx4.h | 11 +-- drivers/net/ethernet/mellanox/mlx5/core/cq.c | 38 +- drivers/net/ethernet/mellanox/mlx5/core/eq.c | 12 ++-- .../ethernet/mellanox/mlx5/core/fpga/conn.c | 15 ++-- .../ethernet/mellanox/mlx5/core/fpga/conn.h | 3 +- .../net/ethernet/mellanox/mlx5/core/lib/eq.h | 11 +-- drivers/net/ethernet/mellanox/mlxsw/pci.c | 29 drivers/net/ethernet/micrel/ks8842.c | 29 drivers/net/ethernet/micrel/ksz884x.c | 37 +- drivers/net/ethernet/microchip/lan743x_ptp.c | 2 +- drivers/net/ethernet/natsemi/ns83820.c| 10 +-- drivers/net/ethernet/netronome/nfp/nfd3/dp.c | 7 +- .../net/ethernet/netronome/nfp/nfd3/nfd3.h| 2 +- drivers/net/ethernet/netronome/nfp/nfdk/dp.c | 6 +- .../net/ethernet/netronome/nfp/nfdk/nfdk.h| 3 +- drivers/net/ethernet/netronome/nfp/nfp_net.h | 4 +- .../ethernet/netronome/nfp/nfp_net_common.c | 12 ++-- .../net/ethernet/netronome/nfp/nfp_net_dp.h | 4 +- drivers/net/ethernet/ni/nixge.c | 19 ++--- drivers/net/ethernet/qlogic/qed/qed.h | 2 +- drivers/net/ethernet/qlogic/qed/qed_int.c | 6 +- drivers/net/ethernet/qlogic/qed/qed_int.h | 4 +- drivers/net/ethernet/qlogic/qed/qed_main.c| 20 +++--- drivers/net/ethernet/sfc/falcon/farch.c | 4 +- drivers/net/ethernet/sfc/falcon/net_driver.h | 2 +- drivers/net/ethernet/sfc/falcon/selftest.c| 2 +- drivers/net/ethernet/sfc/net_driver.h | 2 +- drivers/net/ethernet/sfc/selftest.c | 2 +- drivers/net/ethernet/sfc/siena/farch.c| 4 +- drivers/net/ethernet/sfc/siena/net_driver.h | 2 +- drivers/net/ethernet/sfc/siena/selftest.c | 2 +- driver
[PATCH 0/1] Convert tasklets to BH workqueues in ethernet drivers
This series focuses on converting the existing implementation of tasklets to bottom half (BH) workqueues across various Ethernet drivers under drivers/net/ethernet/*. Impact: The conversion is expected to maintain or improve the performance of the affected drivers. It also improves the maintainability and readability of the driver code. Testing: - Conducted standard network throughput and latency benchmarks to ensure performance parity or improvement. - Ran kernel regression tests to verify that changes do not introduce new issues. I appreciate your review and feedback on this patch series. And additional tested would be really helpful. Allen Pais (1): [RFC] ethernet: Convert from tasklet to BH workqueue drivers/infiniband/hw/mlx4/cq.c | 2 +- drivers/infiniband/hw/mlx5/cq.c | 2 +- drivers/net/ethernet/alteon/acenic.c | 26 +++ drivers/net/ethernet/alteon/acenic.h | 7 +- drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 30 drivers/net/ethernet/amd/xgbe/xgbe-i2c.c | 16 ++--- drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 16 ++--- drivers/net/ethernet/amd/xgbe/xgbe-pci.c | 4 +- drivers/net/ethernet/amd/xgbe/xgbe.h | 11 +-- drivers/net/ethernet/broadcom/cnic.c | 19 ++--- drivers/net/ethernet/broadcom/cnic.h | 2 +- drivers/net/ethernet/cadence/macb.h | 3 +- drivers/net/ethernet/cadence/macb_main.c | 10 +-- .../net/ethernet/cavium/liquidio/lio_core.c | 4 +- .../net/ethernet/cavium/liquidio/lio_main.c | 25 +++ .../ethernet/cavium/liquidio/lio_vf_main.c| 10 +-- .../ethernet/cavium/liquidio/octeon_droq.c| 4 +- .../ethernet/cavium/liquidio/octeon_main.h| 5 +- .../net/ethernet/cavium/octeon/octeon_mgmt.c | 12 ++-- drivers/net/ethernet/cavium/thunder/nic.h | 5 +- .../net/ethernet/cavium/thunder/nicvf_main.c | 24 +++ .../ethernet/cavium/thunder/nicvf_queues.c| 5 +- .../ethernet/cavium/thunder/nicvf_queues.h| 3 +- drivers/net/ethernet/chelsio/cxgb/sge.c | 19 ++--- drivers/net/ethernet/chelsio/cxgb4/cxgb4.h| 9 +-- .../net/ethernet/chelsio/cxgb4/cxgb4_main.c | 2 +- .../ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c | 4 +- .../net/ethernet/chelsio/cxgb4/cxgb4_uld.c| 2 +- drivers/net/ethernet/chelsio/cxgb4/sge.c | 41 +-- drivers/net/ethernet/chelsio/cxgb4vf/sge.c| 6 +- drivers/net/ethernet/dlink/sundance.c | 41 +-- .../net/ethernet/huawei/hinic/hinic_hw_cmdq.c | 2 +- .../net/ethernet/huawei/hinic/hinic_hw_eqs.c | 17 +++-- .../net/ethernet/huawei/hinic/hinic_hw_eqs.h | 2 +- drivers/net/ethernet/ibm/ehea/ehea.h | 3 +- drivers/net/ethernet/ibm/ehea/ehea_main.c | 14 ++-- drivers/net/ethernet/ibm/ibmvnic.c| 24 +++ drivers/net/ethernet/ibm/ibmvnic.h| 2 +- drivers/net/ethernet/jme.c| 72 +-- drivers/net/ethernet/jme.h| 9 +-- .../net/ethernet/marvell/mvpp2/mvpp2_main.c | 2 +- drivers/net/ethernet/marvell/skge.c | 12 ++-- drivers/net/ethernet/marvell/skge.h | 3 +- drivers/net/ethernet/mediatek/mtk_wed_wo.c| 12 ++-- drivers/net/ethernet/mediatek/mtk_wed_wo.h| 3 +- drivers/net/ethernet/mellanox/mlx4/cq.c | 42 +-- drivers/net/ethernet/mellanox/mlx4/eq.c | 10 +-- drivers/net/ethernet/mellanox/mlx4/mlx4.h | 11 +-- drivers/net/ethernet/mellanox/mlx5/core/cq.c | 38 +- drivers/net/ethernet/mellanox/mlx5/core/eq.c | 12 ++-- .../ethernet/mellanox/mlx5/core/fpga/conn.c | 15 ++-- .../ethernet/mellanox/mlx5/core/fpga/conn.h | 3 +- .../net/ethernet/mellanox/mlx5/core/lib/eq.h | 11 +-- drivers/net/ethernet/mellanox/mlxsw/pci.c | 29 drivers/net/ethernet/micrel/ks8842.c | 29 drivers/net/ethernet/micrel/ksz884x.c | 37 +- drivers/net/ethernet/microchip/lan743x_ptp.c | 2 +- drivers/net/ethernet/natsemi/ns83820.c| 10 +-- drivers/net/ethernet/netronome/nfp/nfd3/dp.c | 7 +- .../net/ethernet/netronome/nfp/nfd3/nfd3.h| 2 +- drivers/net/ethernet/netronome/nfp/nfdk/dp.c | 6 +- .../net/ethernet/netronome/nfp/nfdk/nfdk.h| 3 +- drivers/net/ethernet/netronome/nfp/nfp_net.h | 4 +- .../ethernet/netronome/nfp/nfp_net_common.c | 12 ++-- .../net/ethernet/netronome/nfp/nfp_net_dp.h | 4 +- drivers/net/ethernet/ni/nixge.c | 19 ++--- drivers/net/ethernet/qlogic/qed/qed.h | 2 +- drivers/net/ethernet/qlogic/qed/qed_int.c | 6 +- drivers/net/ethernet/qlogic/qed/qed_int.h | 4 +- drivers/net/ethernet/qlogic/qed/qed_main.c| 20 +++--- drivers/net/ethernet/sfc/falcon/farch.c | 4 +- drivers/net/ethernet/sfc/falcon/net_driver.h | 2 +- drivers/net/ethernet/sfc/falcon/selftest.c| 2 +- drivers/net/ethernet/sfc/net_driver.h | 2 +- drivers/net/ethernet/sfc/selftest.c | 2
Re: [PATCH] [RFC] scsi: Convert from tasklet to BH workqueue
> On May 2, 2024, at 7:03 PM, Michael Ellerman wrote: > > Allen Pais writes: >> The only generic interface to execute asynchronously in the BH context is >> tasklet; however, it's marked deprecated and has some design flaws. To >> replace tasklets, BH workqueue support was recently added. A BH workqueue >> behaves similarly to regular workqueues except that the queued work items >> are executed in the BH context. >> >> This patch converts drivers/scsi/* from tasklet to BH workqueue. >> >> Based on the work done by Tejun Heo >> Branch: https://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git for-6.10 >> >> Signed-off-by: Allen Pais >> --- >> drivers/scsi/aic7xxx/aic7xxx_osm.c | 2 +- >> drivers/scsi/aic94xx/aic94xx_hwi.c | 14 ++-- >> drivers/scsi/aic94xx/aic94xx_hwi.h | 5 +- >> drivers/scsi/aic94xx/aic94xx_scb.c | 36 +- >> drivers/scsi/aic94xx/aic94xx_task.c | 14 ++-- >> drivers/scsi/aic94xx/aic94xx_tmf.c | 34 - >> drivers/scsi/esas2r/esas2r.h| 12 ++-- >> drivers/scsi/esas2r/esas2r_init.c | 14 ++-- >> drivers/scsi/esas2r/esas2r_int.c| 18 ++--- >> drivers/scsi/esas2r/esas2r_io.c | 2 +- >> drivers/scsi/esas2r/esas2r_main.c | 16 ++--- >> drivers/scsi/ibmvscsi/ibmvfc.c | 16 ++--- >> drivers/scsi/ibmvscsi/ibmvfc.h | 3 +- >> drivers/scsi/ibmvscsi/ibmvscsi.c| 16 ++--- >> drivers/scsi/ibmvscsi/ibmvscsi.h| 3 +- >> drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c| 15 ++-- >> drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.h| 3 +- > > Something there is giving me a build failure (ppc64le_guest_defconfig): > > + make -s 'CC=ccache powerpc64le-linux-gnu-gcc' -j 4 > /linux/drivers/scsi/ibmvscsi/ibmvscsi.c: In function > 'ibmvscsi_init_crq_queue': > Error: /linux/drivers/scsi/ibmvscsi/ibmvscsi.c:370:331: error: > 'ibmvscsi_work' undeclared (first use in this function) > /linux/drivers/scsi/ibmvscsi/ibmvscsi.c:370:331: note: each undeclared > identifier is reported only once for each function it appears in > /linux/scripts/Makefile.build:244: recipe for target > 'drivers/scsi/ibmvscsi/ibmvscsi.o' failed > /linux/scripts/Makefile.build:485: recipe for target 'drivers/scsi/ibmvscsi' > failed > /linux/scripts/Makefile.build:485: recipe for target 'drivers/scsi' failed > /linux/scripts/Makefile.build:485: recipe for target 'drivers' failed > /linux/drivers/scsi/ibmvscsi/ibmvscsi.c: In function 'ibmvscsi_probe': > Error: /linux/drivers/scsi/ibmvscsi/ibmvscsi.c:2255:78: error: passing > argument 1 of 'kthread_create_on_node' from incompatible pointer type > [-Werror=incompatible-pointer-types] > In file included from /linux/drivers/scsi/ibmvscsi/ibmvscsi.c:56:0: > /linux/include/linux/kthread.h:11:21: note: expected 'int (*)(void *)' but > argument is of type 'int (*)(struct work_struct *)' > struct task_struct *kthread_create_on_node(int (*threadfn)(void *data), > ^ > /linux/drivers/scsi/ibmvscsi/ibmvscsi.c: At top level: > Warning: /linux/drivers/scsi/ibmvscsi/ibmvscsi.c:212:13: warning: > 'ibmvscsi_task' defined but not used [-Wunused-function] > static void ibmvscsi_task(void *data) > ^ > Warning: cc1: warning: unrecognized command line option > '-Wno-shift-negative-value' > Warning: cc1: warning: unrecognized command line option > '-Wno-stringop-overflow' > cc1: some warnings being treated as errors > make[6]: *** [drivers/scsi/ibmvscsi/ibmvscsi.o] Error 1 > make[5]: *** [drivers/scsi/ibmvscsi] Error 2 > make[4]: *** [drivers/scsi] Error 2 > make[3]: *** [drivers] Error 2 > make[3]: *** Waiting for unfinished jobs > > Full log here: > https://github.com/linuxppc/linux-snowpatch/actions/runs/8930174372/job/24529645923 Thank you for testing it out. Unfortunately, I did not cross-compile it. Will fix this in v2. - Allen > > Cross compile instructions if you're keen: > https://github.com/linuxppc/wiki/wiki/Building-powerpc-kernels > > cheers
[PATCH] [RFC] scsi: Convert from tasklet to BH workqueue
The only generic interface to execute asynchronously in the BH context is tasklet; however, it's marked deprecated and has some design flaws. To replace tasklets, BH workqueue support was recently added. A BH workqueue behaves similarly to regular workqueues except that the queued work items are executed in the BH context. This patch converts drivers/scsi/* from tasklet to BH workqueue. Based on the work done by Tejun Heo Branch: https://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git for-6.10 Signed-off-by: Allen Pais --- drivers/scsi/aic7xxx/aic7xxx_osm.c | 2 +- drivers/scsi/aic94xx/aic94xx_hwi.c | 14 ++-- drivers/scsi/aic94xx/aic94xx_hwi.h | 5 +- drivers/scsi/aic94xx/aic94xx_scb.c | 36 +- drivers/scsi/aic94xx/aic94xx_task.c | 14 ++-- drivers/scsi/aic94xx/aic94xx_tmf.c | 34 - drivers/scsi/esas2r/esas2r.h| 12 ++-- drivers/scsi/esas2r/esas2r_init.c | 14 ++-- drivers/scsi/esas2r/esas2r_int.c| 18 ++--- drivers/scsi/esas2r/esas2r_io.c | 2 +- drivers/scsi/esas2r/esas2r_main.c | 16 ++--- drivers/scsi/ibmvscsi/ibmvfc.c | 16 ++--- drivers/scsi/ibmvscsi/ibmvfc.h | 3 +- drivers/scsi/ibmvscsi/ibmvscsi.c| 16 ++--- drivers/scsi/ibmvscsi/ibmvscsi.h| 3 +- drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c| 15 ++-- drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.h| 3 +- drivers/scsi/isci/host.c| 12 ++-- drivers/scsi/isci/host.h| 8 +-- drivers/scsi/isci/init.c| 4 +- drivers/scsi/megaraid/mega_common.h | 5 +- drivers/scsi/megaraid/megaraid_mbox.c | 21 +++--- drivers/scsi/megaraid/megaraid_sas.h| 4 +- drivers/scsi/megaraid/megaraid_sas_base.c | 32 - drivers/scsi/megaraid/megaraid_sas_fusion.c | 16 ++--- drivers/scsi/mvsas/mv_init.c| 27 --- drivers/scsi/mvsas/mv_sas.h | 9 +-- drivers/scsi/pm8001/pm8001_init.c | 55 --- drivers/scsi/pm8001/pm8001_sas.h| 2 +- drivers/scsi/pmcraid.c | 78 +++-- drivers/scsi/pmcraid.h | 5 +- 31 files changed, 251 insertions(+), 250 deletions(-) diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index b0c4f2345321..42f76391f589 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -797,7 +797,7 @@ struct scsi_host_template aic7xxx_driver_template = { .target_destroy = ahc_linux_target_destroy, }; -/ Tasklet Handler */ +/ Work Handler */ static inline unsigned int ahc_build_scsiid(struct ahc_softc *ahc, diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.c b/drivers/scsi/aic94xx/aic94xx_hwi.c index 9dda296c0152..b08f0231e562 100644 --- a/drivers/scsi/aic94xx/aic94xx_hwi.c +++ b/drivers/scsi/aic94xx/aic94xx_hwi.c @@ -246,7 +246,7 @@ static void asd_get_max_scb_ddb(struct asd_ha_struct *asd_ha) /* -- Done List initialization -- */ -static void asd_dl_tasklet_handler(unsigned long); +static void asd_dl_work_handler(struct work_struct *); static int asd_init_dl(struct asd_ha_struct *asd_ha) { @@ -259,8 +259,7 @@ static int asd_init_dl(struct asd_ha_struct *asd_ha) asd_ha->seq.dl = asd_ha->seq.actual_dl->vaddr; asd_ha->seq.dl_toggle = ASD_DEF_DL_TOGGLE; asd_ha->seq.dl_next = 0; - tasklet_init(&asd_ha->seq.dl_tasklet, asd_dl_tasklet_handler, -(unsigned long) asd_ha); + INIT_WORK(&asd_ha->seq.dl_work, asd_dl_work_handler); return 0; } @@ -709,10 +708,9 @@ static void asd_chip_reset(struct asd_ha_struct *asd_ha) /* -- Done List Routines -- */ -static void asd_dl_tasklet_handler(unsigned long data) +static void asd_dl_work_handler(struct work_struct *t) { - struct asd_ha_struct *asd_ha = (struct asd_ha_struct *) data; - struct asd_seq_data *seq = &asd_ha->seq; + struct asd_seq_data *seq = from_work(seq, t, dl_work); unsigned long flags; while (1) { @@ -739,7 +737,7 @@ static void asd_dl_tasklet_handler(unsigned long data) seq->pending--; spin_unlock_irqrestore(&seq->pend_q_lock, flags); out: - ascb->tasklet_complete(ascb, dl); + ascb->work_complete(ascb, dl); next_1: seq->dl_next = (seq->dl_next + 1) & (ASD_DL_SIZE-1); @@ -756,7 +754,7 @@ static void asd_dl_tasklet_handler(unsigned long data) */ static void asd_process_donelist_isr(struct asd_ha_struct *asd_ha) { - tasklet_schedule(&asd_ha->seq.dl_tasklet); + queue_work(system
[PATCH 0/1] Convert tasklets to bottom half workqueues
I am submitting this patch which converts instances of tasklets in drivers/scsi/* to bottom half workqueues. I appreciate your feedback and suggestion on the changes. Note: The patch is only compile tested. In the patcheset, you will notice *FIXME* in two places: 1. pm8001/pm8001_init.c @ pm8001_work(struct work_struct *t) 2. pmcraid.c @ pmcraid_work_function(struct work_struct *t) The current implementation limits context-aware processing within work functions due to the lack of a mechanism to identify the source work_struct in the array. The proposed solution wraps each work_struct with a struct work_wrapper, adding crucial context like the array index and a reference to the parent data structure. Ex: #define SOME_CONSTANT 10 struct xxx_data { . struct work_struct work[SOME_CONSTANT]: . }; The xxx_data module currently uses an array of work_structs for scheduling work, but it lacks the ability to identify which array element is associated with a specific invocation of the work function. This limitation prevents the execution of context-specific actions based on the source of the work request. The proposed solution is to introduce a struct work_wrapper that encapsulates each work_struct along with additional metadata, including an index and a pointer to the parent xxx_data structure. This enhancement allows the work function to access necessary context information. Changes: 1. Definition of struct work_wrapper: struct work_wrapper { struct work_struct work; struct xxx_data *data; int index; }; struct xxx_data { struct work_wrapper work[SOME_CONSTANT]; }; During initialization: for (int i = 0; i < SOME_CONSTANT; i++) { p->work[i].data = p; p->work[i].index = i; INIT_WORK(&p->work[i].work, work_func); } And it's usage in the handler: void work_func(struct work_struct *t) { struct work_wrapper *wrapper = from_work(wrapper, t, work); struct xxx_data *a = wrapper->data; int index = wrapper->index; } If the above is solution is acceptable, I can have the same incorporated in version 2. Thanks. Allen Pais (1): [RFC] scsi: Convert from tasklet to BH workqueue drivers/scsi/aic7xxx/aic7xxx_osm.c | 2 +- drivers/scsi/aic94xx/aic94xx_hwi.c | 14 ++-- drivers/scsi/aic94xx/aic94xx_hwi.h | 5 +- drivers/scsi/aic94xx/aic94xx_scb.c | 36 +- drivers/scsi/aic94xx/aic94xx_task.c | 14 ++-- drivers/scsi/aic94xx/aic94xx_tmf.c | 34 +- drivers/scsi/esas2r/esas2r.h| 12 ++-- drivers/scsi/esas2r/esas2r_init.c | 14 ++-- drivers/scsi/esas2r/esas2r_int.c| 18 ++--- drivers/scsi/esas2r/esas2r_io.c | 2 +- drivers/scsi/esas2r/esas2r_main.c | 16 ++--- drivers/scsi/ibmvscsi/ibmvfc.c | 16 ++--- drivers/scsi/ibmvscsi/ibmvfc.h | 3 +- drivers/scsi/ibmvscsi/ibmvscsi.c| 16 ++--- drivers/scsi/ibmvscsi/ibmvscsi.h| 3 +- drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c| 15 ++--- drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.h| 3 +- drivers/scsi/isci/host.c| 12 ++-- drivers/scsi/isci/host.h| 8 +-- drivers/scsi/isci/init.c| 4 +- drivers/scsi/megaraid/mega_common.h | 5 +- drivers/scsi/megaraid/megaraid_mbox.c | 21 +++--- drivers/scsi/megaraid/megaraid_sas.h| 4 +- drivers/scsi/megaraid/megaraid_sas_base.c | 32 + drivers/scsi/megaraid/megaraid_sas_fusion.c | 16 ++--- drivers/scsi/mvsas/mv_init.c| 27 drivers/scsi/mvsas/mv_sas.h | 9 +-- drivers/scsi/pm8001/pm8001_init.c | 57 drivers/scsi/pm8001/pm8001_sas.h| 2 +- drivers/scsi/pmcraid.c | 75 ++--- drivers/scsi/pmcraid.h | 5 +- 31 files changed, 249 insertions(+), 251 deletions(-) -- 2.17.1
Re: [PATCH 8/9] drivers/media/*: Convert from tasklet to BH workqueue
> On Apr 24, 2024, at 2:12 AM, Hans Verkuil wrote: > > On 27/03/2024 17:03, Allen Pais wrote: >> The only generic interface to execute asynchronously in the BH context is >> tasklet; however, it's marked deprecated and has some design flaws. To >> replace tasklets, BH workqueue support was recently added. A BH workqueue >> behaves similarly to regular workqueues except that the queued work items >> are executed in the BH context. >> >> This patch converts drivers/media/* from tasklet to BH workqueue. >> >> Based on the work done by Tejun Heo >> Branch: https://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git for-6.10 >> >> Signed-off-by: Allen Pais >> --- >> drivers/media/pci/bt8xx/bt878.c | 8 ++-- >> drivers/media/pci/bt8xx/bt878.h | 3 +- >> drivers/media/pci/bt8xx/dvb-bt8xx.c | 9 ++-- >> drivers/media/pci/ddbridge/ddbridge.h | 3 +- >> drivers/media/pci/mantis/hopper_cards.c | 2 +- >> drivers/media/pci/mantis/mantis_cards.c | 2 +- >> drivers/media/pci/mantis/mantis_common.h | 3 +- >> drivers/media/pci/mantis/mantis_dma.c | 5 ++- >> drivers/media/pci/mantis/mantis_dma.h | 2 +- >> drivers/media/pci/mantis/mantis_dvb.c | 12 +++--- >> drivers/media/pci/ngene/ngene-core.c | 23 ++- >> drivers/media/pci/ngene/ngene.h | 5 ++- >> drivers/media/pci/smipcie/smipcie-main.c | 18 >> drivers/media/pci/smipcie/smipcie.h | 3 +- >> drivers/media/pci/ttpci/budget-av.c | 3 +- >> drivers/media/pci/ttpci/budget-ci.c | 27 ++-- >> drivers/media/pci/ttpci/budget-core.c | 10 ++--- >> drivers/media/pci/ttpci/budget.h | 5 ++- >> drivers/media/pci/tw5864/tw5864-core.c| 2 +- >> drivers/media/pci/tw5864/tw5864-video.c | 13 +++--- >> drivers/media/pci/tw5864/tw5864.h | 7 ++-- >> drivers/media/platform/intel/pxa_camera.c | 15 +++ >> drivers/media/platform/marvell/mcam-core.c| 11 ++--- >> drivers/media/platform/marvell/mcam-core.h| 3 +- >> .../st/sti/c8sectpfe/c8sectpfe-core.c | 15 +++ >> .../st/sti/c8sectpfe/c8sectpfe-core.h | 2 +- >> drivers/media/radio/wl128x/fmdrv.h| 7 ++-- >> drivers/media/radio/wl128x/fmdrv_common.c | 41 ++- >> drivers/media/rc/mceusb.c | 2 +- >> drivers/media/usb/ttusb-dec/ttusb_dec.c | 21 +- >> 30 files changed, 151 insertions(+), 131 deletions(-) >> >> diff --git a/drivers/media/pci/bt8xx/bt878.c >> b/drivers/media/pci/bt8xx/bt878.c >> index 90972d6952f1..983ec29108f0 100644 >> --- a/drivers/media/pci/bt8xx/bt878.c >> +++ b/drivers/media/pci/bt8xx/bt878.c >> @@ -300,8 +300,8 @@ static irqreturn_t bt878_irq(int irq, void *dev_id) >> } >> if (astat & BT878_ARISCI) { >> bt->finished_block = (stat & BT878_ARISCS) >> 28; >> -if (bt->tasklet.callback) >> -tasklet_schedule(&bt->tasklet); >> +if (bt->work.func) >> +queue_work(system_bh_wq, > > I stopped reviewing here: this clearly has not been compile tested. > > Also please check the patch with 'checkpatch.pl --strict' and fix the > reported issues. > > Regards, > > Hans Hans, Thanks for taking the time out to review. This was a mistake, I sent out a v2 which had This fixed. I am working on v3 based on some of the comments I received recently. Will Appreciate your review when it is sent out. Allen > >> break; >> } >> count++; >> @@ -478,8 +478,8 @@ static int bt878_probe(struct pci_dev *dev, const struct >> pci_device_id *pci_id) >> btwrite(0, BT878_AINT_MASK); >> bt878_num++; >> >> -if (!bt->tasklet.func) >> -tasklet_disable(&bt->tasklet); >> +if (!bt->work.func) >> +disable_work_sync(&bt->work); >> >> return 0; >> >> diff --git a/drivers/media/pci/bt8xx/bt878.h >> b/drivers/media/pci/bt8xx/bt878.h >> index fde8db293c54..b9ce78e5116b 100644 >> --- a/drivers/media/pci/bt8xx/bt878.h >> +++ b/drivers/media/pci/bt8xx/bt878.h >> @@ -14,6 +14,7 @@ >> #include >> #include >> #include >> +#include >> >> #include "bt848.h" >> #include "bttv.h
Re: [PATCH 1/9] hyperv: Convert from tasklet to BH workqueue
> The only generic interface to execute asynchronously in the BH context is > tasklet; however, it's marked deprecated and has some design flaws. To > replace tasklets, BH workqueue support was recently added. A BH workqueue > behaves similarly to regular workqueues except that the queued work items > are executed in the BH context. > > This patch converts drivers/hv/* from tasklet to BH workqueue. > > Based on the work done by Tejun Heo > Branch: https://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git for-6.10 > > Signed-off-by: Allen Pais > --- > drivers/hv/channel.c | 8 > drivers/hv/channel_mgmt.c | 5 ++--- > drivers/hv/connection.c | 9 + > drivers/hv/hv.c | 3 +-- > drivers/hv/hv_balloon.c | 4 ++-- > drivers/hv/hv_fcopy.c | 8 > drivers/hv/hv_kvp.c | 8 > drivers/hv/hv_snapshot.c | 8 > drivers/hv/hyperv_vmbus.h | 9 + > drivers/hv/vmbus_drv.c| 19 ++- > include/linux/hyperv.h| 2 +- > 11 files changed, 42 insertions(+), 41 deletions(-) Wei, I need to send out a v2 as I did not include the second patch that updates drivers/pci/controller/pci-hyperv.c Thanks.
Re: [PATCH 7/9] s390: Convert from tasklet to BH workqueue
> > > > Signed-off-by: Allen Pais > > --- > > drivers/s390/block/dasd.c | 42 > > drivers/s390/block/dasd_int.h | 10 +++--- > > drivers/s390/char/con3270.c| 27 > > drivers/s390/crypto/ap_bus.c | 24 +++--- > > drivers/s390/crypto/ap_bus.h | 2 +- > > drivers/s390/crypto/zcrypt_msgtype50.c | 2 +- > > drivers/s390/crypto/zcrypt_msgtype6.c | 4 +-- > > drivers/s390/net/ctcm_fsms.c | 4 +-- > > drivers/s390/net/ctcm_main.c | 15 - > > drivers/s390/net/ctcm_main.h | 5 +-- > > drivers/s390/net/ctcm_mpc.c| 12 +++ > > drivers/s390/net/ctcm_mpc.h| 7 ++-- > > drivers/s390/net/lcs.c | 26 +++ > > drivers/s390/net/lcs.h | 2 +- > > drivers/s390/net/qeth_core_main.c | 2 +- > > drivers/s390/scsi/zfcp_qdio.c | 45 +- > > drivers/s390/scsi/zfcp_qdio.h | 9 +++--- > > 17 files changed, 117 insertions(+), 121 deletions(-) > > > > > We're looking into the best way to test this. > > For drivers/s390/net/ctcm* and drivers/s390/net/lcs*: > Acked-by: Alexandra Winter Thank you very much. > > > [...] > > diff --git a/drivers/s390/net/qeth_core_main.c > > b/drivers/s390/net/qeth_core_main.c > > index a0cce6872075..10ea95abc753 100644 > > --- a/drivers/s390/net/qeth_core_main.c > > +++ b/drivers/s390/net/qeth_core_main.c > > @@ -2911,7 +2911,7 @@ static int qeth_init_input_buffer(struct qeth_card > > *card, > > } > > > > /* > > - * since the buffer is accessed only from the input_tasklet > > + * since the buffer is accessed only from the input_work > >* there shouldn't be a need to synchronize; also, since we use > >* the QETH_IN_BUF_REQUEUE_THRESHOLD we should never run out off > >* buffers > > I propose to delete the whole comment block. There have been many changes and > I don't think it is helpful for the current qeth driver. Sure, I will have it fixed in v2. - Allen
Re: [PATCH 2/9] dma: Convert from tasklet to BH workqueue
> >> > Since almost every driver associates the tasklet with the > >> > dma_chan, we could go one step further and add the > >> > work_queue structure directly into struct dma_chan, > >> > with the wrapper operating on the dma_chan rather than > >> > the work_queue. > >> > >> I think that is very great idea. having this wrapped in dma_chan would > >> be very good way as well > >> > >> Am not sure if Allen is up for it :-) > > > > Thanks Arnd, I know we did speak about this at LPC. I did start > > working on using completion. I dropped it as I thought it would > > be easier to move to workqueues. > > It's definitely easier to do the workqueue conversion as a first > step, and I agree adding support for the completion right away is > probably too much. Moving the work_struct into the dma_chan > is probably not too hard though, if you leave your current > approach for the cases where the tasklet is part of the > dma_dev rather than the dma_chan. > Alright, I will work on moving work_struck into the dma_chan and leave the dma_dev as is (using bh workqueues) and post a RFC. Once reviewed, I could move to the next step. Thank you. - Allen
Re: [PATCH 6/9] ipmi: Convert from tasklet to BH workqueue
> > > > > > > > Fair point. Could you please let me know once you have had a chance > > > > to test > > > > these changes. Meanwhile, I will work on RFC wherein IPMI will have its > > > > own > > > > workqueue. > > > > > > > > Thanks for taking time out to review. > > > > > > After looking and thinking about it a bit, a BH context is still > > > probably the best for this. > > > > > > I have tested this patch under load and various scenarios and it seems > > > to work ok. So: > > > > > > Tested-by: Corey Minyard > > > Acked-by: Corey Minyard > > > > > > Or I can take this into my tree. > > > > > > -corey > > > > Thank you very much. I think it should be okay for you to carry it into > > your tree. > > Ok, it's in my for-next tree. I fixed the directory reference, and I > changed all the comments where you changed "tasklet" to "work" to > instead say "workqueue". > Thank you very much for fixing it. - Allen
Re: [PATCH 6/9] ipmi: Convert from tasklet to BH workqueue
> > > I believe that work queues items are execute single-threaded for a work > > > queue, so this should be good. I need to test this, though. It may be > > > that an IPMI device can have its own work queue; it may not be important > > > to run it in bh context. > > > > Fair point. Could you please let me know once you have had a chance to > > test > > these changes. Meanwhile, I will work on RFC wherein IPMI will have its own > > workqueue. > > > > Thanks for taking time out to review. > > After looking and thinking about it a bit, a BH context is still > probably the best for this. > > I have tested this patch under load and various scenarios and it seems > to work ok. So: > > Tested-by: Corey Minyard > Acked-by: Corey Minyard > > Or I can take this into my tree. > > -corey Thank you very much. I think it should be okay for you to carry it into your tree. - Allen
Re: [PATCH 2/9] dma: Convert from tasklet to BH workqueue
> > >> The only generic interface to execute asynchronously in the BH context is > > >> tasklet; however, it's marked deprecated and has some design flaws. To > > >> replace tasklets, BH workqueue support was recently added. A BH workqueue > > >> behaves similarly to regular workqueues except that the queued work items > > >> are executed in the BH context. > > > > > > Thanks for conversion, am happy with BH alternative as it helps in > > > dmaengine where we need shortest possible time between tasklet and > > > interrupt handling to maximize dma performance > > > > I still feel that we want something different for dmaengine, > > at least in the long run. As we have discussed in the past, > > the tasklet context in these drivers is what the callbacks > > from the dma client device is run in, and a lot of these probably > > want something other than tasklet context, e.g. just call > > complete() on a client-provided completion structure. > > > > Instead of open-coding the use of the system_bh_wq in each > > dmaengine, how about we start with a custom WQ_BH > > specifically for the dmaengine subsystem and wrap them > > inside of another interface. > > > > Since almost every driver associates the tasklet with the > > dma_chan, we could go one step further and add the > > work_queue structure directly into struct dma_chan, > > with the wrapper operating on the dma_chan rather than > > the work_queue. > > I think that is very great idea. having this wrapped in dma_chan would > be very good way as well > > Am not sure if Allen is up for it :-) Thanks Arnd, I know we did speak about this at LPC. I did start working on using completion. I dropped it as I thought it would be easier to move to workqueues. Vinod, I would like to give this a shot and put out a RFC, I would really appreciate review and feedback. Thanks, Allen > > -- > ~Vinod >
Re: [PATCH 4/9] USB: Convert from tasklet to BH workqueue
> > > > This patch converts drivers/infiniband/* from tasklet to BH workqueue. > > > > Based on the work done by Tejun Heo > > Branch: https://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git for-6.10 > > > > Signed-off-by: Allen Pais > > --- > > > diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c > > index c0e005670d67..88d8e1c366cd 100644 > > --- a/drivers/usb/core/hcd.c > > +++ b/drivers/usb/core/hcd.c > > > @@ -1662,10 +1663,9 @@ static void __usb_hcd_giveback_urb(struct urb *urb) > > usb_put_urb(urb); > > } > > > > -static void usb_giveback_urb_bh(struct work_struct *work) > > +static void usb_giveback_urb_bh(struct work_struct *t) > > { > > - struct giveback_urb_bh *bh = > > - container_of(work, struct giveback_urb_bh, bh); > > + struct giveback_urb_bh *bh = from_work(bh, t, bh); > > struct list_head local_list; > > > > spin_lock_irq(&bh->lock); > > Is there any reason for this apparently pointless change of a local > variable's name? No, it was done just to keep things consistent across the kernel. I can revert it back to *work if you'd prefer. Thanks. > > Alan Stern > -- - Allen
Re: [PATCH 6/9] ipmi: Convert from tasklet to BH workqueue
On Wed, Mar 27, 2024 at 11:05 AM Corey Minyard wrote: > > On Wed, Mar 27, 2024 at 04:03:11PM +, Allen Pais wrote: > > The only generic interface to execute asynchronously in the BH context is > > tasklet; however, it's marked deprecated and has some design flaws. To > > replace tasklets, BH workqueue support was recently added. A BH workqueue > > behaves similarly to regular workqueues except that the queued work items > > are executed in the BH context. > > > > This patch converts drivers/infiniband/* from tasklet to BH workqueue. > > I think you mean drivers/char/ipmi/* here. My apologies, my scripts messed up the commit messages for this series. Will have it fixed in v2. > > I believe that work queues items are execute single-threaded for a work > queue, so this should be good. I need to test this, though. It may be > that an IPMI device can have its own work queue; it may not be important > to run it in bh context. Fair point. Could you please let me know once you have had a chance to test these changes. Meanwhile, I will work on RFC wherein IPMI will have its own workqueue. Thanks for taking time out to review. - Allen > > -corey > > > > > Based on the work done by Tejun Heo > > Branch: https://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git for-6.10 > > > > Signed-off-by: Allen Pais > > --- > > drivers/char/ipmi/ipmi_msghandler.c | 30 ++--- > > 1 file changed, 15 insertions(+), 15 deletions(-) > > > > diff --git a/drivers/char/ipmi/ipmi_msghandler.c > > b/drivers/char/ipmi/ipmi_msghandler.c > > index b0eedc4595b3..fce2a2dbdc82 100644 > > --- a/drivers/char/ipmi/ipmi_msghandler.c > > +++ b/drivers/char/ipmi/ipmi_msghandler.c > > @@ -36,12 +36,13 @@ > > #include > > #include > > #include > > +#include > > > > #define IPMI_DRIVER_VERSION "39.2" > > > > static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void); > > static int ipmi_init_msghandler(void); > > -static void smi_recv_tasklet(struct tasklet_struct *t); > > +static void smi_recv_work(struct work_struct *t); > > static void handle_new_recv_msgs(struct ipmi_smi *intf); > > static void need_waiter(struct ipmi_smi *intf); > > static int handle_one_recv_msg(struct ipmi_smi *intf, > > @@ -498,13 +499,13 @@ struct ipmi_smi { > > /* > >* Messages queued for delivery. If delivery fails (out of memory > >* for instance), They will stay in here to be processed later in a > > - * periodic timer interrupt. The tasklet is for handling received > > + * periodic timer interrupt. The work is for handling received > >* messages directly from the handler. > >*/ > > spinlock_t waiting_rcv_msgs_lock; > > struct list_head waiting_rcv_msgs; > > atomic_t watchdog_pretimeouts_to_deliver; > > - struct tasklet_struct recv_tasklet; > > + struct work_struct recv_work; > > > > spinlock_t xmit_msgs_lock; > > struct list_head xmit_msgs; > > @@ -704,7 +705,7 @@ static void clean_up_interface_data(struct ipmi_smi > > *intf) > > struct cmd_rcvr *rcvr, *rcvr2; > > struct list_head list; > > > > - tasklet_kill(&intf->recv_tasklet); > > + cancel_work_sync(&intf->recv_work); > > > > free_smi_msg_list(&intf->waiting_rcv_msgs); > > free_recv_msg_list(&intf->waiting_events); > > @@ -1319,7 +1320,7 @@ static void free_user(struct kref *ref) > > { > > struct ipmi_user *user = container_of(ref, struct ipmi_user, > > refcount); > > > > - /* SRCU cleanup must happen in task context. */ > > + /* SRCU cleanup must happen in work context. */ > > queue_work(remove_work_wq, &user->remove_work); > > } > > > > @@ -3605,8 +3606,7 @@ int ipmi_add_smi(struct module *owner, > > intf->curr_seq = 0; > > spin_lock_init(&intf->waiting_rcv_msgs_lock); > > INIT_LIST_HEAD(&intf->waiting_rcv_msgs); > > - tasklet_setup(&intf->recv_tasklet, > > - smi_recv_tasklet); > > + INIT_WORK(&intf->recv_work, smi_recv_work); > > atomic_set(&intf->watchdog_pretimeouts_to_deliver, 0); > > spin_lock_init(&intf->xmit_msgs_lock); > > INIT_LIST_HEAD(&intf->xmit_msgs); > > @@ -4779,7 +4779,7 @@ static void handle_new_recv_msgs(struct ipmi_smi > > *intf) > >* To p
Re: [PATCH 2/9] dma: Convert from tasklet to BH workqueue
> > Subsytem is dmaengine, can you rename this to dmaengine: ... My apologies, will have it fixed in v2. > > On 27-03-24, 16:03, Allen Pais wrote: > > The only generic interface to execute asynchronously in the BH context is > > tasklet; however, it's marked deprecated and has some design flaws. To > > replace tasklets, BH workqueue support was recently added. A BH workqueue > > behaves similarly to regular workqueues except that the queued work items > > are executed in the BH context. > > Thanks for conversion, am happy with BH alternative as it helps in > dmaengine where we need shortest possible time between tasklet and > interrupt handling to maximize dma performance > > > > > This patch converts drivers/dma/* from tasklet to BH workqueue. > > > > > Based on the work done by Tejun Heo > > Branch: git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git for-6.10 > > > > Signed-off-by: Allen Pais > > --- > > drivers/dma/altera-msgdma.c | 15 > > drivers/dma/apple-admac.c | 15 > > drivers/dma/at_hdmac.c| 2 +- > > drivers/dma/at_xdmac.c| 15 > > drivers/dma/bcm2835-dma.c | 2 +- > > drivers/dma/dma-axi-dmac.c| 2 +- > > drivers/dma/dma-jz4780.c | 2 +- > > .../dma/dw-axi-dmac/dw-axi-dmac-platform.c| 2 +- > > drivers/dma/dw-edma/dw-edma-core.c| 2 +- > > drivers/dma/dw/core.c | 13 +++ > > drivers/dma/dw/regs.h | 3 +- > > drivers/dma/ep93xx_dma.c | 15 > > drivers/dma/fsl-edma-common.c | 2 +- > > drivers/dma/fsl-qdma.c| 2 +- > > drivers/dma/fsl_raid.c| 11 +++--- > > drivers/dma/fsl_raid.h| 2 +- > > drivers/dma/fsldma.c | 15 > > drivers/dma/fsldma.h | 3 +- > > drivers/dma/hisi_dma.c| 2 +- > > drivers/dma/hsu/hsu.c | 2 +- > > drivers/dma/idma64.c | 4 +-- > > drivers/dma/img-mdc-dma.c | 2 +- > > drivers/dma/imx-dma.c | 27 +++--- > > drivers/dma/imx-sdma.c| 6 ++-- > > drivers/dma/ioat/dma.c| 17 - > > drivers/dma/ioat/dma.h| 5 +-- > > drivers/dma/ioat/init.c | 2 +- > > drivers/dma/k3dma.c | 19 +- > > drivers/dma/mediatek/mtk-cqdma.c | 35 ++- > > drivers/dma/mediatek/mtk-hsdma.c | 2 +- > > drivers/dma/mediatek/mtk-uart-apdma.c | 4 +-- > > drivers/dma/mmp_pdma.c| 13 +++ > > drivers/dma/mmp_tdma.c| 11 +++--- > > drivers/dma/mpc512x_dma.c | 17 - > > drivers/dma/mv_xor.c | 13 +++ > > drivers/dma/mv_xor.h | 5 +-- > > drivers/dma/mv_xor_v2.c | 23 ++-- > > drivers/dma/mxs-dma.c | 13 +++ > > drivers/dma/nbpfaxi.c | 15 > > drivers/dma/owl-dma.c | 2 +- > > drivers/dma/pch_dma.c | 17 - > > drivers/dma/pl330.c | 31 > > drivers/dma/plx_dma.c | 13 +++ > > drivers/dma/ppc4xx/adma.c | 17 - > > drivers/dma/ppc4xx/adma.h | 5 +-- > > drivers/dma/pxa_dma.c | 2 +- > > drivers/dma/qcom/bam_dma.c| 35 ++- > > drivers/dma/qcom/gpi.c| 18 +- > > drivers/dma/qcom/hidma.c | 11 +++--- > > drivers/dma/qcom/hidma.h | 5 +-- > > drivers/dma/qcom/hidma_ll.c | 11 +++--- > > drivers/dma/qcom/qcom_adm.c | 2 +- > > drivers/dma/sa11x0-dma.c | 27 +++--- > > drivers/dma/sf-pdma/sf-pdma.c | 23 ++-- > > drivers/dma/sf-pdma/sf-pdma.h | 5 +-- > > drivers/dma/sprd-dma.c| 2 +- > > drivers/dma/st_fdma.c | 2 +- > > drivers/dma
Re: [PATCH 9/9] mmc: Convert from tasklet to BH workqueue
On Thu, Mar 28, 2024 at 3:16 AM Christian Loehle wrote: > > On 27/03/2024 16:03, Allen Pais wrote: > > The only generic interface to execute asynchronously in the BH context is > > tasklet; however, it's marked deprecated and has some design flaws. To > > replace tasklets, BH workqueue support was recently added. A BH workqueue > > behaves similarly to regular workqueues except that the queued work items > > are executed in the BH context. > > > > This patch converts drivers/infiniband/* from tasklet to BH workqueue. > s/infiniband/mmc Will fix it in v2. > > > > Based on the work done by Tejun Heo > > Branch: https://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git for-6.10 > > > > Signed-off-by: Allen Pais > > --- > > drivers/mmc/host/atmel-mci.c | 35 - > > drivers/mmc/host/au1xmmc.c| 37 - > > drivers/mmc/host/cb710-mmc.c | 15 ++-- > > drivers/mmc/host/cb710-mmc.h | 3 +- > > drivers/mmc/host/dw_mmc.c | 25 --- > > drivers/mmc/host/dw_mmc.h | 9 ++- > For dw_mmc: > Performance numbers look good FWIW. > for i in $(seq 0 5); do echo performance > > /sys/devices/system/cpu/cpu$i/cpufreq/scaling_governor; done > for i in $(seq 0 4); do fio --name=test --rw=randread --bs=4k --runtime=30 > --time_based --filename=/dev/mmcblk1 --minimal --numjobs=6 --iodepth=32 > --group_reporting | awk -F ";" '{print $8}'; sleep 30; done > Baseline: > 1758 > 1773 > 1619 > 1835 > 1639 > to: > 1743 > 1643 > 1860 > 1638 > 1872 > (I'd call that equivalent). > This is on a RK3399. > I would prefer most of the naming to change from "work" to "workqueue" in the > driver > code. > Apart from that: > Reviewed-by: Christian Loehle > Tested-by: Christian Loehle Thank you very much for testing and the review. Will have your concerns addressed in v2. - Allen
Re: [PATCH 4/9] USB: Convert from tasklet to BH workqueue
> > The only generic interface to execute asynchronously in the BH context is > > tasklet; however, it's marked deprecated and has some design flaws. To > > replace tasklets, BH workqueue support was recently added. A BH workqueue > > behaves similarly to regular workqueues except that the queued work items > > are executed in the BH context. > > > > This patch converts drivers/infiniband/* from tasklet to BH workqueue. > > No it does not, I think your changelog is wrong :( Whoops, sorry about that. I messed up the commit messages. I will fix it in v2. > > > > > Based on the work done by Tejun Heo > > Branch: https://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git for-6.10 > > > > Signed-off-by: Allen Pais > > --- > > drivers/usb/atm/usbatm.c| 55 +++-- > > drivers/usb/atm/usbatm.h| 3 +- > > drivers/usb/core/hcd.c | 22 ++-- > > drivers/usb/gadget/udc/fsl_qe_udc.c | 21 +-- > > drivers/usb/gadget/udc/fsl_qe_udc.h | 4 +-- > > drivers/usb/host/ehci-sched.c | 2 +- > > drivers/usb/host/fhci-hcd.c | 3 +- > > drivers/usb/host/fhci-sched.c | 10 +++--- > > drivers/usb/host/fhci.h | 5 +-- > > drivers/usb/host/xhci-dbgcap.h | 3 +- > > drivers/usb/host/xhci-dbgtty.c | 15 > > include/linux/usb/cdc_ncm.h | 2 +- > > include/linux/usb/usbnet.h | 2 +- > > 13 files changed, 76 insertions(+), 71 deletions(-) > > > > diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c > > index 2da6615fbb6f..74849f24e52e 100644 > > --- a/drivers/usb/atm/usbatm.c > > +++ b/drivers/usb/atm/usbatm.c > > @@ -17,7 +17,7 @@ > > * - Removed the limit on the number of devices > > * - Module now autoloads on device plugin > > * - Merged relevant parts of sarlib > > - * - Replaced the kernel thread with a tasklet > > + * - Replaced the kernel thread with a work > > a "work"? will fix the comments. > > > * - New packet transmission code > > * - Changed proc file contents > > * - Fixed all known SMP races > > @@ -68,6 +68,7 @@ > > #include > > #include > > #include > > +#include > > > > #ifdef VERBOSE_DEBUG > > static int usbatm_print_packet(struct usbatm_data *instance, const > > unsigned char *data, int len); > > @@ -249,7 +250,7 @@ static void usbatm_complete(struct urb *urb) > > /* vdbg("%s: urb 0x%p, status %d, actual_length %d", > >__func__, urb, status, urb->actual_length); */ > > > > - /* Can be invoked from task context, protect against interrupts */ > > + /* Can be invoked from work context, protect against interrupts */ > > "workqueue"? This too seems wrong. > > Same for other comment changes in this patch. Thanks for the quick review, I will fix the comments and send out v2. - Alle > thanks, > > greg k-h >
[PATCH 5/9] mailbox: Convert from tasklet to BH workqueue
The only generic interface to execute asynchronously in the BH context is tasklet; however, it's marked deprecated and has some design flaws. To replace tasklets, BH workqueue support was recently added. A BH workqueue behaves similarly to regular workqueues except that the queued work items are executed in the BH context. This patch converts drivers/infiniband/* from tasklet to BH workqueue. Based on the work done by Tejun Heo Branch: https://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git for-6.10 Signed-off-by: Allen Pais --- drivers/mailbox/bcm-pdc-mailbox.c | 21 +++-- drivers/mailbox/imx-mailbox.c | 16 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/drivers/mailbox/bcm-pdc-mailbox.c b/drivers/mailbox/bcm-pdc-mailbox.c index 1768d3d5aaa0..242e7504a628 100644 --- a/drivers/mailbox/bcm-pdc-mailbox.c +++ b/drivers/mailbox/bcm-pdc-mailbox.c @@ -43,6 +43,7 @@ #include #include #include +#include #define PDC_SUCCESS 0 @@ -293,8 +294,8 @@ struct pdc_state { unsigned int pdc_irq; - /* tasklet for deferred processing after DMA rx interrupt */ - struct tasklet_struct rx_tasklet; + /* work for deferred processing after DMA rx interrupt */ + struct work_struct rx_work; /* Number of bytes of receive status prior to each rx frame */ u32 rx_status_len; @@ -952,18 +953,18 @@ static irqreturn_t pdc_irq_handler(int irq, void *data) iowrite32(intstatus, pdcs->pdc_reg_vbase + PDC_INTSTATUS_OFFSET); /* Wakeup IRQ thread */ - tasklet_schedule(&pdcs->rx_tasklet); + queue_work(system_bh_wq, &pdcs->rx_work); return IRQ_HANDLED; } /** - * pdc_tasklet_cb() - Tasklet callback that runs the deferred processing after + * pdc_work_cb() - Work callback that runs the deferred processing after * a DMA receive interrupt. Reenables the receive interrupt. * @t: Pointer to the Altera sSGDMA channel structure */ -static void pdc_tasklet_cb(struct tasklet_struct *t) +static void pdc_work_cb(struct work_struct *t) { - struct pdc_state *pdcs = from_tasklet(pdcs, t, rx_tasklet); + struct pdc_state *pdcs = from_work(pdcs, t, rx_work); pdc_receive(pdcs); @@ -1577,8 +1578,8 @@ static int pdc_probe(struct platform_device *pdev) pdc_hw_init(pdcs); - /* Init tasklet for deferred DMA rx processing */ - tasklet_setup(&pdcs->rx_tasklet, pdc_tasklet_cb); + /* Init work for deferred DMA rx processing */ + INIT_WORK(&pdcs->rx_work, pdc_work_cb); err = pdc_interrupts_init(pdcs); if (err) @@ -1595,7 +1596,7 @@ static int pdc_probe(struct platform_device *pdev) return PDC_SUCCESS; cleanup_buf_pool: - tasklet_kill(&pdcs->rx_tasklet); + cancel_work_sync(&pdcs->rx_work); dma_pool_destroy(pdcs->rx_buf_pool); cleanup_ring_pool: @@ -1611,7 +1612,7 @@ static void pdc_remove(struct platform_device *pdev) pdc_free_debugfs(); - tasklet_kill(&pdcs->rx_tasklet); + cancel_work_sync(&pdcs->rx_work); pdc_hw_disable(pdcs); diff --git a/drivers/mailbox/imx-mailbox.c b/drivers/mailbox/imx-mailbox.c index 5c1d09cad761..933727f89431 100644 --- a/drivers/mailbox/imx-mailbox.c +++ b/drivers/mailbox/imx-mailbox.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "mailbox.h" @@ -80,7 +81,7 @@ struct imx_mu_con_priv { charirq_desc[IMX_MU_CHAN_NAME_SIZE]; enum imx_mu_chan_type type; struct mbox_chan*chan; - struct tasklet_struct txdb_tasklet; + struct work_struct txdb_work; }; struct imx_mu_priv { @@ -232,7 +233,7 @@ static int imx_mu_generic_tx(struct imx_mu_priv *priv, break; case IMX_MU_TYPE_TXDB: imx_mu_xcr_rmw(priv, IMX_MU_GCR, IMX_MU_xCR_GIRn(priv->dcfg->type, cp->idx), 0); - tasklet_schedule(&cp->txdb_tasklet); + queue_work(system_bh_wq, &cp->txdb_work); break; case IMX_MU_TYPE_TXDB_V2: imx_mu_xcr_rmw(priv, IMX_MU_GCR, IMX_MU_xCR_GIRn(priv->dcfg->type, cp->idx), 0); @@ -420,7 +421,7 @@ static int imx_mu_seco_tx(struct imx_mu_priv *priv, struct imx_mu_con_priv *cp, } /* Simulate hack for mbox framework */ - tasklet_schedule(&cp->txdb_tasklet); + queue_work(system_bh_wq, &cp->txdb_work); break; default: @@ -484,9 +485,9 @@ static int imx_mu_seco_rxdb(struct imx_mu_priv *priv, struct imx_mu_con_priv *cp return err; } -static void imx_mu_txdb_tasklet(unsigned long data) +static void imx_mu_txdb_work(struct work_struct *t) { - struct imx_mu_con_priv *cp = (struct imx_mu_con_priv *)data; + struct imx_mu_con_priv *
[PATCH 7/9] s390: Convert from tasklet to BH workqueue
The only generic interface to execute asynchronously in the BH context is tasklet; however, it's marked deprecated and has some design flaws. To replace tasklets, BH workqueue support was recently added. A BH workqueue behaves similarly to regular workqueues except that the queued work items are executed in the BH context. This patch converts drivers/infiniband/* from tasklet to BH workqueue. Based on the work done by Tejun Heo Branch: https://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git for-6.10 Note: Not tested. Please test/review. Signed-off-by: Allen Pais --- drivers/s390/block/dasd.c | 42 drivers/s390/block/dasd_int.h | 10 +++--- drivers/s390/char/con3270.c| 27 drivers/s390/crypto/ap_bus.c | 24 +++--- drivers/s390/crypto/ap_bus.h | 2 +- drivers/s390/crypto/zcrypt_msgtype50.c | 2 +- drivers/s390/crypto/zcrypt_msgtype6.c | 4 +-- drivers/s390/net/ctcm_fsms.c | 4 +-- drivers/s390/net/ctcm_main.c | 15 - drivers/s390/net/ctcm_main.h | 5 +-- drivers/s390/net/ctcm_mpc.c| 12 +++ drivers/s390/net/ctcm_mpc.h| 7 ++-- drivers/s390/net/lcs.c | 26 +++ drivers/s390/net/lcs.h | 2 +- drivers/s390/net/qeth_core_main.c | 2 +- drivers/s390/scsi/zfcp_qdio.c | 45 +- drivers/s390/scsi/zfcp_qdio.h | 9 +++--- 17 files changed, 117 insertions(+), 121 deletions(-) diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 0a97cfedd706..c6f9910f0a98 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -54,8 +54,8 @@ MODULE_LICENSE("GPL"); * SECTION: prototypes for static functions of dasd.c */ static int dasd_flush_block_queue(struct dasd_block *); -static void dasd_device_tasklet(unsigned long); -static void dasd_block_tasklet(unsigned long); +static void dasd_device_work(struct work_struct *); +static void dasd_block_work(struct work_struct *); static void do_kick_device(struct work_struct *); static void do_reload_device(struct work_struct *); static void do_requeue_requests(struct work_struct *); @@ -114,9 +114,8 @@ struct dasd_device *dasd_alloc_device(void) dasd_init_chunklist(&device->erp_chunks, device->erp_mem, PAGE_SIZE); dasd_init_chunklist(&device->ese_chunks, device->ese_mem, PAGE_SIZE * 2); spin_lock_init(&device->mem_lock); - atomic_set(&device->tasklet_scheduled, 0); - tasklet_init(&device->tasklet, dasd_device_tasklet, -(unsigned long) device); + atomic_set(&device->work_scheduled, 0); + INIT_WORK(&device->bh, dasd_device_work); INIT_LIST_HEAD(&device->ccw_queue); timer_setup(&device->timer, dasd_device_timeout, 0); INIT_WORK(&device->kick_work, do_kick_device); @@ -154,9 +153,8 @@ struct dasd_block *dasd_alloc_block(void) /* open_count = 0 means device online but not in use */ atomic_set(&block->open_count, -1); - atomic_set(&block->tasklet_scheduled, 0); - tasklet_init(&block->tasklet, dasd_block_tasklet, -(unsigned long) block); + atomic_set(&block->work_scheduled, 0); + INIT_WORK(&block->bh, dasd_block_work); INIT_LIST_HEAD(&block->ccw_queue); spin_lock_init(&block->queue_lock); INIT_LIST_HEAD(&block->format_list); @@ -2148,12 +2146,12 @@ EXPORT_SYMBOL_GPL(dasd_flush_device_queue); /* * Acquire the device lock and process queues for the device. */ -static void dasd_device_tasklet(unsigned long data) +static void dasd_device_work(struct work_struct *t) { - struct dasd_device *device = (struct dasd_device *) data; + struct dasd_device *device = from_work(device, t, bh); struct list_head final_queue; - atomic_set (&device->tasklet_scheduled, 0); + atomic_set (&device->work_scheduled, 0); INIT_LIST_HEAD(&final_queue); spin_lock_irq(get_ccwdev_lock(device->cdev)); /* Check expire time of first request on the ccw queue. */ @@ -2174,15 +2172,15 @@ static void dasd_device_tasklet(unsigned long data) } /* - * Schedules a call to dasd_tasklet over the device tasklet. + * Schedules a call to dasd_work over the device wq. */ void dasd_schedule_device_bh(struct dasd_device *device) { /* Protect against rescheduling. */ - if (atomic_cmpxchg (&device->tasklet_scheduled, 0, 1) != 0) + if (atomic_cmpxchg (&device->work_scheduled, 0, 1) != 0) return; dasd_get_device(device); - tasklet_hi_schedule(&device->tasklet); + queue_work(system_bh_highpri_wq, &device->bh); } EXPORT_SYMBOL(
[PATCH 9/9] mmc: Convert from tasklet to BH workqueue
The only generic interface to execute asynchronously in the BH context is tasklet; however, it's marked deprecated and has some design flaws. To replace tasklets, BH workqueue support was recently added. A BH workqueue behaves similarly to regular workqueues except that the queued work items are executed in the BH context. This patch converts drivers/infiniband/* from tasklet to BH workqueue. Based on the work done by Tejun Heo Branch: https://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git for-6.10 Signed-off-by: Allen Pais --- drivers/mmc/host/atmel-mci.c | 35 - drivers/mmc/host/au1xmmc.c| 37 - drivers/mmc/host/cb710-mmc.c | 15 ++-- drivers/mmc/host/cb710-mmc.h | 3 +- drivers/mmc/host/dw_mmc.c | 25 --- drivers/mmc/host/dw_mmc.h | 9 ++- drivers/mmc/host/omap.c | 17 +++-- drivers/mmc/host/renesas_sdhi.h | 3 +- drivers/mmc/host/renesas_sdhi_internal_dmac.c | 24 +++--- drivers/mmc/host/renesas_sdhi_sys_dmac.c | 9 +-- drivers/mmc/host/sdhci-bcm-kona.c | 2 +- drivers/mmc/host/tifm_sd.c| 15 ++-- drivers/mmc/host/tmio_mmc.h | 3 +- drivers/mmc/host/tmio_mmc_core.c | 4 +- drivers/mmc/host/uniphier-sd.c| 13 ++-- drivers/mmc/host/via-sdmmc.c | 25 --- drivers/mmc/host/wbsd.c | 75 ++- drivers/mmc/host/wbsd.h | 10 +-- 18 files changed, 167 insertions(+), 157 deletions(-) diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index dba826db739a..0a92a7fd020f 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -284,12 +285,12 @@ struct atmel_mci_dma { * EVENT_DATA_ERROR is pending. * @stop_cmdr: Value to be loaded into CMDR when the stop command is * to be sent. - * @tasklet: Tasklet running the request state machine. + * @work: Work running the request state machine. * @pending_events: Bitmask of events flagged by the interrupt handler - * to be processed by the tasklet. + * to be processed by the work. * @completed_events: Bitmask of events which the state machine has * processed. - * @state: Tasklet state. + * @state: Work state. * @queue: List of slots waiting for access to the controller. * @need_clock_update: Update the clock rate before the next request. * @need_reset: Reset controller before next request. @@ -363,7 +364,7 @@ struct atmel_mci { u32 data_status; u32 stop_cmdr; - struct tasklet_struct tasklet; + struct work_struct work; unsigned long pending_events; unsigned long completed_events; enum atmel_mci_statestate; @@ -761,7 +762,7 @@ static void atmci_timeout_timer(struct timer_list *t) host->need_reset = 1; host->state = STATE_END_REQUEST; smp_wmb(); - tasklet_schedule(&host->tasklet); + queue_work(system_bh_wq, &host->work); } static inline unsigned int atmci_ns_to_clocks(struct atmel_mci *host, @@ -983,7 +984,7 @@ static void atmci_pdc_complete(struct atmel_mci *host) dev_dbg(&host->pdev->dev, "(%s) set pending xfer complete\n", __func__); atmci_set_pending(host, EVENT_XFER_COMPLETE); - tasklet_schedule(&host->tasklet); + queue_work(system_bh_wq, &host->work); } static void atmci_dma_cleanup(struct atmel_mci *host) @@ -997,7 +998,7 @@ static void atmci_dma_cleanup(struct atmel_mci *host) } /* - * This function is called by the DMA driver from tasklet context. + * This function is called by the DMA driver from work context. */ static void atmci_dma_complete(void *arg) { @@ -1020,7 +1021,7 @@ static void atmci_dma_complete(void *arg) dev_dbg(&host->pdev->dev, "(%s) set pending xfer complete\n", __func__); atmci_set_pending(host, EVENT_XFER_COMPLETE); - tasklet_schedule(&host->tasklet); + queue_work(system_bh_wq, &host->work); /* * Regardless of what the documentation says, we have @@ -1033,7 +1034,7 @@ static void atmci_dma_complete(void *arg) * haven't seen all the potential error bits yet. * * The interrupt handler will schedule a different -* tasklet to finish things up when the data transfer +* work to finish things up when the data transfer * is completely done. * * We may not complete the mmc request here anyway @@ -1
[PATCH 8/9] drivers/media/*: Convert from tasklet to BH workqueue
The only generic interface to execute asynchronously in the BH context is tasklet; however, it's marked deprecated and has some design flaws. To replace tasklets, BH workqueue support was recently added. A BH workqueue behaves similarly to regular workqueues except that the queued work items are executed in the BH context. This patch converts drivers/media/* from tasklet to BH workqueue. Based on the work done by Tejun Heo Branch: https://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git for-6.10 Signed-off-by: Allen Pais --- drivers/media/pci/bt8xx/bt878.c | 8 ++-- drivers/media/pci/bt8xx/bt878.h | 3 +- drivers/media/pci/bt8xx/dvb-bt8xx.c | 9 ++-- drivers/media/pci/ddbridge/ddbridge.h | 3 +- drivers/media/pci/mantis/hopper_cards.c | 2 +- drivers/media/pci/mantis/mantis_cards.c | 2 +- drivers/media/pci/mantis/mantis_common.h | 3 +- drivers/media/pci/mantis/mantis_dma.c | 5 ++- drivers/media/pci/mantis/mantis_dma.h | 2 +- drivers/media/pci/mantis/mantis_dvb.c | 12 +++--- drivers/media/pci/ngene/ngene-core.c | 23 ++- drivers/media/pci/ngene/ngene.h | 5 ++- drivers/media/pci/smipcie/smipcie-main.c | 18 drivers/media/pci/smipcie/smipcie.h | 3 +- drivers/media/pci/ttpci/budget-av.c | 3 +- drivers/media/pci/ttpci/budget-ci.c | 27 ++-- drivers/media/pci/ttpci/budget-core.c | 10 ++--- drivers/media/pci/ttpci/budget.h | 5 ++- drivers/media/pci/tw5864/tw5864-core.c| 2 +- drivers/media/pci/tw5864/tw5864-video.c | 13 +++--- drivers/media/pci/tw5864/tw5864.h | 7 ++-- drivers/media/platform/intel/pxa_camera.c | 15 +++ drivers/media/platform/marvell/mcam-core.c| 11 ++--- drivers/media/platform/marvell/mcam-core.h| 3 +- .../st/sti/c8sectpfe/c8sectpfe-core.c | 15 +++ .../st/sti/c8sectpfe/c8sectpfe-core.h | 2 +- drivers/media/radio/wl128x/fmdrv.h| 7 ++-- drivers/media/radio/wl128x/fmdrv_common.c | 41 ++- drivers/media/rc/mceusb.c | 2 +- drivers/media/usb/ttusb-dec/ttusb_dec.c | 21 +- 30 files changed, 151 insertions(+), 131 deletions(-) diff --git a/drivers/media/pci/bt8xx/bt878.c b/drivers/media/pci/bt8xx/bt878.c index 90972d6952f1..983ec29108f0 100644 --- a/drivers/media/pci/bt8xx/bt878.c +++ b/drivers/media/pci/bt8xx/bt878.c @@ -300,8 +300,8 @@ static irqreturn_t bt878_irq(int irq, void *dev_id) } if (astat & BT878_ARISCI) { bt->finished_block = (stat & BT878_ARISCS) >> 28; - if (bt->tasklet.callback) - tasklet_schedule(&bt->tasklet); + if (bt->work.func) + queue_work(system_bh_wq, break; } count++; @@ -478,8 +478,8 @@ static int bt878_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) btwrite(0, BT878_AINT_MASK); bt878_num++; - if (!bt->tasklet.func) - tasklet_disable(&bt->tasklet); + if (!bt->work.func) + disable_work_sync(&bt->work); return 0; diff --git a/drivers/media/pci/bt8xx/bt878.h b/drivers/media/pci/bt8xx/bt878.h index fde8db293c54..b9ce78e5116b 100644 --- a/drivers/media/pci/bt8xx/bt878.h +++ b/drivers/media/pci/bt8xx/bt878.h @@ -14,6 +14,7 @@ #include #include #include +#include #include "bt848.h" #include "bttv.h" @@ -120,7 +121,7 @@ struct bt878 { dma_addr_t risc_dma; u32 risc_pos; - struct tasklet_struct tasklet; + struct work_struct work; int shutdown; }; diff --git a/drivers/media/pci/bt8xx/dvb-bt8xx.c b/drivers/media/pci/bt8xx/dvb-bt8xx.c index 390cbba6c065..8c0e1fa764a4 100644 --- a/drivers/media/pci/bt8xx/dvb-bt8xx.c +++ b/drivers/media/pci/bt8xx/dvb-bt8xx.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -39,9 +40,9 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); #define IF_FREQUENCYx6 217/* 6 * 36.167MHz */ -static void dvb_bt8xx_task(struct tasklet_struct *t) +static void dvb_bt8xx_task(struct work_struct *t) { - struct bt878 *bt = from_tasklet(bt, t, tasklet); + struct bt878 *bt = from_work(bt, t, work); struct dvb_bt8xx_card *card = dev_get_drvdata(&bt->adapter->dev); dprintk("%d\n", card->bt->finished_block); @@ -782,7 +783,7 @@ static int dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type) goto err_disconnect_frontend; } - tasklet_setup(&card->bt->tasklet, dvb_bt8xx_task); + INIT_WORK(&card->bt->work, dvb_bt8xx_task); f
[PATCH 6/9] ipmi: Convert from tasklet to BH workqueue
The only generic interface to execute asynchronously in the BH context is tasklet; however, it's marked deprecated and has some design flaws. To replace tasklets, BH workqueue support was recently added. A BH workqueue behaves similarly to regular workqueues except that the queued work items are executed in the BH context. This patch converts drivers/infiniband/* from tasklet to BH workqueue. Based on the work done by Tejun Heo Branch: https://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git for-6.10 Signed-off-by: Allen Pais --- drivers/char/ipmi/ipmi_msghandler.c | 30 ++--- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index b0eedc4595b3..fce2a2dbdc82 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -36,12 +36,13 @@ #include #include #include +#include #define IPMI_DRIVER_VERSION "39.2" static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void); static int ipmi_init_msghandler(void); -static void smi_recv_tasklet(struct tasklet_struct *t); +static void smi_recv_work(struct work_struct *t); static void handle_new_recv_msgs(struct ipmi_smi *intf); static void need_waiter(struct ipmi_smi *intf); static int handle_one_recv_msg(struct ipmi_smi *intf, @@ -498,13 +499,13 @@ struct ipmi_smi { /* * Messages queued for delivery. If delivery fails (out of memory * for instance), They will stay in here to be processed later in a -* periodic timer interrupt. The tasklet is for handling received +* periodic timer interrupt. The work is for handling received * messages directly from the handler. */ spinlock_t waiting_rcv_msgs_lock; struct list_head waiting_rcv_msgs; atomic_t watchdog_pretimeouts_to_deliver; - struct tasklet_struct recv_tasklet; + struct work_struct recv_work; spinlock_t xmit_msgs_lock; struct list_head xmit_msgs; @@ -704,7 +705,7 @@ static void clean_up_interface_data(struct ipmi_smi *intf) struct cmd_rcvr *rcvr, *rcvr2; struct list_head list; - tasklet_kill(&intf->recv_tasklet); + cancel_work_sync(&intf->recv_work); free_smi_msg_list(&intf->waiting_rcv_msgs); free_recv_msg_list(&intf->waiting_events); @@ -1319,7 +1320,7 @@ static void free_user(struct kref *ref) { struct ipmi_user *user = container_of(ref, struct ipmi_user, refcount); - /* SRCU cleanup must happen in task context. */ + /* SRCU cleanup must happen in work context. */ queue_work(remove_work_wq, &user->remove_work); } @@ -3605,8 +3606,7 @@ int ipmi_add_smi(struct module *owner, intf->curr_seq = 0; spin_lock_init(&intf->waiting_rcv_msgs_lock); INIT_LIST_HEAD(&intf->waiting_rcv_msgs); - tasklet_setup(&intf->recv_tasklet, -smi_recv_tasklet); + INIT_WORK(&intf->recv_work, smi_recv_work); atomic_set(&intf->watchdog_pretimeouts_to_deliver, 0); spin_lock_init(&intf->xmit_msgs_lock); INIT_LIST_HEAD(&intf->xmit_msgs); @@ -4779,7 +4779,7 @@ static void handle_new_recv_msgs(struct ipmi_smi *intf) * To preserve message order, quit if we * can't handle a message. Add the message * back at the head, this is safe because this -* tasklet is the only thing that pulls the +* work is the only thing that pulls the * messages. */ list_add(&smi_msg->link, &intf->waiting_rcv_msgs); @@ -4812,10 +4812,10 @@ static void handle_new_recv_msgs(struct ipmi_smi *intf) } } -static void smi_recv_tasklet(struct tasklet_struct *t) +static void smi_recv_work(struct work_struct *t) { unsigned long flags = 0; /* keep us warning-free. */ - struct ipmi_smi *intf = from_tasklet(intf, t, recv_tasklet); + struct ipmi_smi *intf = from_work(intf, t, recv_work); int run_to_completion = intf->run_to_completion; struct ipmi_smi_msg *newmsg = NULL; @@ -4866,7 +4866,7 @@ void ipmi_smi_msg_received(struct ipmi_smi *intf, /* * To preserve message order, we keep a queue and deliver from -* a tasklet. +* a work. */ if (!run_to_completion) spin_lock_irqsave(&intf->waiting_rcv_msgs_lock, flags); @@ -4887,9 +4887,9 @@ void ipmi_smi_msg_received(struct ipmi_smi *intf, spin_unlock_irqrestore(&intf->xmit_msgs_lock, flags); if (run_to_completion) - smi_recv_tasklet(&intf->recv_tasklet); + sm
[PATCH 4/9] USB: Convert from tasklet to BH workqueue
The only generic interface to execute asynchronously in the BH context is tasklet; however, it's marked deprecated and has some design flaws. To replace tasklets, BH workqueue support was recently added. A BH workqueue behaves similarly to regular workqueues except that the queued work items are executed in the BH context. This patch converts drivers/infiniband/* from tasklet to BH workqueue. Based on the work done by Tejun Heo Branch: https://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git for-6.10 Signed-off-by: Allen Pais --- drivers/usb/atm/usbatm.c| 55 +++-- drivers/usb/atm/usbatm.h| 3 +- drivers/usb/core/hcd.c | 22 ++-- drivers/usb/gadget/udc/fsl_qe_udc.c | 21 +-- drivers/usb/gadget/udc/fsl_qe_udc.h | 4 +-- drivers/usb/host/ehci-sched.c | 2 +- drivers/usb/host/fhci-hcd.c | 3 +- drivers/usb/host/fhci-sched.c | 10 +++--- drivers/usb/host/fhci.h | 5 +-- drivers/usb/host/xhci-dbgcap.h | 3 +- drivers/usb/host/xhci-dbgtty.c | 15 include/linux/usb/cdc_ncm.h | 2 +- include/linux/usb/usbnet.h | 2 +- 13 files changed, 76 insertions(+), 71 deletions(-) diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c index 2da6615fbb6f..74849f24e52e 100644 --- a/drivers/usb/atm/usbatm.c +++ b/drivers/usb/atm/usbatm.c @@ -17,7 +17,7 @@ * - Removed the limit on the number of devices * - Module now autoloads on device plugin * - Merged relevant parts of sarlib - * - Replaced the kernel thread with a tasklet + * - Replaced the kernel thread with a work * - New packet transmission code * - Changed proc file contents * - Fixed all known SMP races @@ -68,6 +68,7 @@ #include #include #include +#include #ifdef VERBOSE_DEBUG static int usbatm_print_packet(struct usbatm_data *instance, const unsigned char *data, int len); @@ -249,7 +250,7 @@ static void usbatm_complete(struct urb *urb) /* vdbg("%s: urb 0x%p, status %d, actual_length %d", __func__, urb, status, urb->actual_length); */ - /* Can be invoked from task context, protect against interrupts */ + /* Can be invoked from work context, protect against interrupts */ spin_lock_irqsave(&channel->lock, flags); /* must add to the back when receiving; doesn't matter when sending */ @@ -269,7 +270,7 @@ static void usbatm_complete(struct urb *urb) /* throttle processing in case of an error */ mod_timer(&channel->delay, jiffies + msecs_to_jiffies(THROTTLE_MSECS)); } else - tasklet_schedule(&channel->tasklet); + queue_work(system_bh_wq, &channel->work); } @@ -511,10 +512,10 @@ static unsigned int usbatm_write_cells(struct usbatm_data *instance, ** receive ** **/ -static void usbatm_rx_process(struct tasklet_struct *t) +static void usbatm_rx_process(struct work_struct *t) { - struct usbatm_data *instance = from_tasklet(instance, t, - rx_channel.tasklet); + struct usbatm_data *instance = from_work(instance, t, + rx_channel.work); struct urb *urb; while ((urb = usbatm_pop_urb(&instance->rx_channel))) { @@ -565,10 +566,10 @@ static void usbatm_rx_process(struct tasklet_struct *t) ** send ** ***/ -static void usbatm_tx_process(struct tasklet_struct *t) +static void usbatm_tx_process(struct work_struct *t) { - struct usbatm_data *instance = from_tasklet(instance, t, - tx_channel.tasklet); + struct usbatm_data *instance = from_work(instance, t, + tx_channel.work); struct sk_buff *skb = instance->current_skb; struct urb *urb = NULL; const unsigned int buf_size = instance->tx_channel.buf_size; @@ -632,13 +633,13 @@ static void usbatm_cancel_send(struct usbatm_data *instance, } spin_unlock_irq(&instance->sndqueue.lock); - tasklet_disable(&instance->tx_channel.tasklet); + disable_work_sync(&instance->tx_channel.work); if ((skb = instance->current_skb) && (UDSL_SKB(skb)->atm.vcc == vcc)) { atm_dbg(instance, "%s: popping current skb (0x%p)\n", __func__, skb); instance->current_skb = NULL; usbatm_pop(vcc, skb); } - tasklet_enable(&instance->tx_channel.tasklet); + enable_and_queue_work(system_bh_wq, &instance->tx_channel.work); } static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) @@ -677,7 +678,7 @@ static int usbatm_atm_send(struct
[PATCH 3/9] IB: Convert from tasklet to BH workqueue
The only generic interface to execute asynchronously in the BH context is tasklet; however, it's marked deprecated and has some design flaws. To replace tasklets, BH workqueue support was recently added. A BH workqueue behaves similarly to regular workqueues except that the queued work items are executed in the BH context. This patch converts drivers/infiniband/* from tasklet to BH workqueue. Based on the work done by Tejun Heo Branch: https://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git for-6.10 Signed-off-by: Allen Pais --- drivers/infiniband/hw/bnxt_re/bnxt_re.h| 3 +- drivers/infiniband/hw/bnxt_re/qplib_fp.c | 21 ++-- drivers/infiniband/hw/bnxt_re/qplib_fp.h | 2 +- drivers/infiniband/hw/bnxt_re/qplib_rcfw.c | 25 --- drivers/infiniband/hw/bnxt_re/qplib_rcfw.h | 2 +- drivers/infiniband/hw/erdma/erdma.h| 3 +- drivers/infiniband/hw/erdma/erdma_eq.c | 11 --- drivers/infiniband/hw/hfi1/rc.c| 2 +- drivers/infiniband/hw/hfi1/sdma.c | 37 +++--- drivers/infiniband/hw/hfi1/sdma.h | 9 +++--- drivers/infiniband/hw/hfi1/tid_rdma.c | 6 ++-- drivers/infiniband/hw/irdma/ctrl.c | 2 +- drivers/infiniband/hw/irdma/hw.c | 24 +++--- drivers/infiniband/hw/irdma/main.h | 5 +-- drivers/infiniband/hw/qib/qib.h| 7 ++-- drivers/infiniband/hw/qib/qib_iba7322.c| 9 +++--- drivers/infiniband/hw/qib/qib_rc.c | 16 +- drivers/infiniband/hw/qib/qib_ruc.c| 4 +-- drivers/infiniband/hw/qib/qib_sdma.c | 11 --- drivers/infiniband/sw/rdmavt/qp.c | 2 +- 20 files changed, 106 insertions(+), 95 deletions(-) diff --git a/drivers/infiniband/hw/bnxt_re/bnxt_re.h b/drivers/infiniband/hw/bnxt_re/bnxt_re.h index 9dca451ed522..f511c8415806 100644 --- a/drivers/infiniband/hw/bnxt_re/bnxt_re.h +++ b/drivers/infiniband/hw/bnxt_re/bnxt_re.h @@ -42,6 +42,7 @@ #include #include "hw_counters.h" #include +#include #define ROCE_DRV_MODULE_NAME "bnxt_re" #define BNXT_RE_DESC "Broadcom NetXtreme-C/E RoCE Driver" @@ -162,7 +163,7 @@ struct bnxt_re_dev { u8 cur_prio_map; /* FP Notification Queue (CQ & SRQ) */ - struct tasklet_struct nq_task; + struct work_struct nq_work; /* RCFW Channel */ struct bnxt_qplib_rcfw rcfw; diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.c b/drivers/infiniband/hw/bnxt_re/qplib_fp.c index 439d0c7c5d0c..052906982cdf 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c +++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include "roce_hsi.h" @@ -294,9 +295,9 @@ static void __wait_for_all_nqes(struct bnxt_qplib_cq *cq, u16 cnq_events) } } -static void bnxt_qplib_service_nq(struct tasklet_struct *t) +static void bnxt_qplib_service_nq(struct work_struct *t) { - struct bnxt_qplib_nq *nq = from_tasklet(nq, t, nq_tasklet); + struct bnxt_qplib_nq *nq = from_work(nq, t, nq_work); struct bnxt_qplib_hwq *hwq = &nq->hwq; struct bnxt_qplib_cq *cq; int budget = nq->budget; @@ -394,7 +395,7 @@ void bnxt_re_synchronize_nq(struct bnxt_qplib_nq *nq) int budget = nq->budget; nq->budget = nq->hwq.max_elements; - bnxt_qplib_service_nq(&nq->nq_tasklet); + bnxt_qplib_service_nq(&nq->nq_work); nq->budget = budget; } @@ -409,7 +410,7 @@ static irqreturn_t bnxt_qplib_nq_irq(int irq, void *dev_instance) prefetch(bnxt_qplib_get_qe(hwq, sw_cons, NULL)); /* Fan out to CPU affinitized kthreads? */ - tasklet_schedule(&nq->nq_tasklet); + queue_work(system_bh_wq, &nq->nq_work); return IRQ_HANDLED; } @@ -430,8 +431,8 @@ void bnxt_qplib_nq_stop_irq(struct bnxt_qplib_nq *nq, bool kill) nq->name = NULL; if (kill) - tasklet_kill(&nq->nq_tasklet); - tasklet_disable(&nq->nq_tasklet); + cancel_work_sync(&nq->nq_work); + disable_work_sync(&nq->nq_work); } void bnxt_qplib_disable_nq(struct bnxt_qplib_nq *nq) @@ -465,9 +466,9 @@ int bnxt_qplib_nq_start_irq(struct bnxt_qplib_nq *nq, int nq_indx, nq->msix_vec = msix_vector; if (need_init) - tasklet_setup(&nq->nq_tasklet, bnxt_qplib_service_nq); + INIT_WORK(&nq->nq_work, bnxt_qplib_service_nq); else - tasklet_enable(&nq->nq_tasklet); + enable_and_queue_work(system_bh_wq, &nq->nq_work); nq->name = kasprintf(GFP_KERNEL, "bnxt_re-nq-%d@pci:%s", nq_indx, pci_name(res->pdev)); @@ -477,7 +478,7 @@ int bnxt_qplib_nq_star
[PATCH 2/9] dma: Convert from tasklet to BH workqueue
The only generic interface to execute asynchronously in the BH context is tasklet; however, it's marked deprecated and has some design flaws. To replace tasklets, BH workqueue support was recently added. A BH workqueue behaves similarly to regular workqueues except that the queued work items are executed in the BH context. This patch converts drivers/dma/* from tasklet to BH workqueue. Based on the work done by Tejun Heo Branch: git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git for-6.10 Signed-off-by: Allen Pais --- drivers/dma/altera-msgdma.c | 15 drivers/dma/apple-admac.c | 15 drivers/dma/at_hdmac.c| 2 +- drivers/dma/at_xdmac.c| 15 drivers/dma/bcm2835-dma.c | 2 +- drivers/dma/dma-axi-dmac.c| 2 +- drivers/dma/dma-jz4780.c | 2 +- .../dma/dw-axi-dmac/dw-axi-dmac-platform.c| 2 +- drivers/dma/dw-edma/dw-edma-core.c| 2 +- drivers/dma/dw/core.c | 13 +++ drivers/dma/dw/regs.h | 3 +- drivers/dma/ep93xx_dma.c | 15 drivers/dma/fsl-edma-common.c | 2 +- drivers/dma/fsl-qdma.c| 2 +- drivers/dma/fsl_raid.c| 11 +++--- drivers/dma/fsl_raid.h| 2 +- drivers/dma/fsldma.c | 15 drivers/dma/fsldma.h | 3 +- drivers/dma/hisi_dma.c| 2 +- drivers/dma/hsu/hsu.c | 2 +- drivers/dma/idma64.c | 4 +-- drivers/dma/img-mdc-dma.c | 2 +- drivers/dma/imx-dma.c | 27 +++--- drivers/dma/imx-sdma.c| 6 ++-- drivers/dma/ioat/dma.c| 17 - drivers/dma/ioat/dma.h| 5 +-- drivers/dma/ioat/init.c | 2 +- drivers/dma/k3dma.c | 19 +- drivers/dma/mediatek/mtk-cqdma.c | 35 ++- drivers/dma/mediatek/mtk-hsdma.c | 2 +- drivers/dma/mediatek/mtk-uart-apdma.c | 4 +-- drivers/dma/mmp_pdma.c| 13 +++ drivers/dma/mmp_tdma.c| 11 +++--- drivers/dma/mpc512x_dma.c | 17 - drivers/dma/mv_xor.c | 13 +++ drivers/dma/mv_xor.h | 5 +-- drivers/dma/mv_xor_v2.c | 23 ++-- drivers/dma/mxs-dma.c | 13 +++ drivers/dma/nbpfaxi.c | 15 drivers/dma/owl-dma.c | 2 +- drivers/dma/pch_dma.c | 17 - drivers/dma/pl330.c | 31 drivers/dma/plx_dma.c | 13 +++ drivers/dma/ppc4xx/adma.c | 17 - drivers/dma/ppc4xx/adma.h | 5 +-- drivers/dma/pxa_dma.c | 2 +- drivers/dma/qcom/bam_dma.c| 35 ++- drivers/dma/qcom/gpi.c| 18 +- drivers/dma/qcom/hidma.c | 11 +++--- drivers/dma/qcom/hidma.h | 5 +-- drivers/dma/qcom/hidma_ll.c | 11 +++--- drivers/dma/qcom/qcom_adm.c | 2 +- drivers/dma/sa11x0-dma.c | 27 +++--- drivers/dma/sf-pdma/sf-pdma.c | 23 ++-- drivers/dma/sf-pdma/sf-pdma.h | 5 +-- drivers/dma/sprd-dma.c| 2 +- drivers/dma/st_fdma.c | 2 +- drivers/dma/ste_dma40.c | 17 - drivers/dma/sun6i-dma.c | 33 - drivers/dma/tegra186-gpc-dma.c| 2 +- drivers/dma/tegra20-apb-dma.c | 19 +- drivers/dma/tegra210-adma.c | 2 +- drivers/dma/ti/edma.c | 2 +- drivers/dma/ti/k3-udma.c | 11 +++--- drivers/dma/ti/omap-dma.c | 2 +- drivers/dma/timb_dma.c| 23 ++-- drivers/dma/txx9dmac.c| 29 +++ drivers/dma/txx9dmac.h| 5 +-- drivers/dma/virt-dma.c| 9 ++--- drivers/dma/virt-dma.h| 9 ++--- drivers/dma/xgene-dma.c | 21 +-- drivers/dma/xilinx/xilinx_dma.c | 23 ++-- drivers/dma/xilinx/xilinx_dpdma.c | 21 +-- drivers/dma/xilinx/zynqmp_dma.c | 21 +-- 74 files changed, 442 insertions(+), 395 deletions(-) diff --
[PATCH 1/9] hyperv: Convert from tasklet to BH workqueue
The only generic interface to execute asynchronously in the BH context is tasklet; however, it's marked deprecated and has some design flaws. To replace tasklets, BH workqueue support was recently added. A BH workqueue behaves similarly to regular workqueues except that the queued work items are executed in the BH context. This patch converts drivers/hv/* from tasklet to BH workqueue. Based on the work done by Tejun Heo Branch: https://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git for-6.10 Signed-off-by: Allen Pais --- drivers/hv/channel.c | 8 drivers/hv/channel_mgmt.c | 5 ++--- drivers/hv/connection.c | 9 + drivers/hv/hv.c | 3 +-- drivers/hv/hv_balloon.c | 4 ++-- drivers/hv/hv_fcopy.c | 8 drivers/hv/hv_kvp.c | 8 drivers/hv/hv_snapshot.c | 8 drivers/hv/hyperv_vmbus.h | 9 + drivers/hv/vmbus_drv.c| 19 ++- include/linux/hyperv.h| 2 +- 11 files changed, 42 insertions(+), 41 deletions(-) diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index adbf674355b2..876d78eb4dce 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -859,7 +859,7 @@ void vmbus_reset_channel_cb(struct vmbus_channel *channel) unsigned long flags; /* -* vmbus_on_event(), running in the per-channel tasklet, can race +* vmbus_on_event(), running in the per-channel work, can race * with vmbus_close_internal() in the case of SMP guest, e.g., when * the former is accessing channel->inbound.ring_buffer, the latter * could be freeing the ring_buffer pages, so here we must stop it @@ -871,7 +871,7 @@ void vmbus_reset_channel_cb(struct vmbus_channel *channel) * and that the channel ring buffer is no longer being accessed, cf. * the calls to napi_disable() in netvsc_device_remove(). */ - tasklet_disable(&channel->callback_event); + disable_work_sync(&channel->callback_event); /* See the inline comments in vmbus_chan_sched(). */ spin_lock_irqsave(&channel->sched_lock, flags); @@ -880,8 +880,8 @@ void vmbus_reset_channel_cb(struct vmbus_channel *channel) channel->sc_creation_callback = NULL; - /* Re-enable tasklet for use on re-open */ - tasklet_enable(&channel->callback_event); + /* Re-enable work for use on re-open */ + enable_and_queue_work(system_bh_wq, &channel->callback_event); } static int vmbus_close_internal(struct vmbus_channel *channel) diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 2f4d09ce027a..58397071a0de 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -353,8 +353,7 @@ static struct vmbus_channel *alloc_channel(void) INIT_LIST_HEAD(&channel->sc_list); - tasklet_init(&channel->callback_event, -vmbus_on_event, (unsigned long)channel); + INIT_WORK(&channel->callback_event, vmbus_on_event); hv_ringbuffer_pre_init(channel); @@ -366,7 +365,7 @@ static struct vmbus_channel *alloc_channel(void) */ static void free_channel(struct vmbus_channel *channel) { - tasklet_kill(&channel->callback_event); + cancel_work_sync(&channel->callback_event); vmbus_remove_channel_attr_group(channel); kobject_put(&channel->kobj); diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c index 3cabeeabb1ca..f2a3394a8303 100644 --- a/drivers/hv/connection.c +++ b/drivers/hv/connection.c @@ -372,12 +372,13 @@ struct vmbus_channel *relid2channel(u32 relid) * 3. Once we return, enable signaling from the host. Once this *state is set we check to see if additional packets are *available to read. In this case we repeat the process. - *If this tasklet has been running for a long time + *If this work has been running for a long time *then reschedule ourselves. */ -void vmbus_on_event(unsigned long data) +void vmbus_on_event(struct work_struct *t) { - struct vmbus_channel *channel = (void *) data; + struct vmbus_channel *channel = from_work(channel, t, + callback_event); void (*callback_fn)(void *context); trace_vmbus_on_event(channel); @@ -401,7 +402,7 @@ void vmbus_on_event(unsigned long data) return; hv_begin_read(&channel->inbound); - tasklet_schedule(&channel->callback_event); + queue_work(system_bh_wq, &channel->callback_event); } /* diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index a8ad728354cb..2af92f08f9ce 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -119,8 +119,7 @@ int hv_synic_alloc(void) for_each_present_cpu(cpu) { hv_cpu = per_cpu_ptr(hv_context.cpu_context, cpu); - tasklet_init(&hv_cpu->msg_dpc
[PATCH 0/9] Convert Tasklets to BH Workqueues
This patch series represents a significant shift in how asynchronous execution in the bottom half (BH) context is handled within the kernel. Traditionally, tasklets have been the go-to mechanism for such operations. This series introduces the conversion of existing tasklet implementations to the newly supported BH workqueues, marking a pivotal enhancement in how asynchronous tasks are managed and executed. Background and Motivation: Tasklets have served as the kernel's lightweight mechanism for scheduling bottom-half processing, providing a simple interface for deferring work from interrupt context. There have been increasing requests and motivations to deprecate and eventually remove tasklets in favor of more modern and flexible mechanisms. Introduction of BH Workqueues: BH workqueues are designed to behave similarly to regular workqueues with the added benefit of execution in the BH context. Conversion Details: The conversion process involved identifying all instances where tasklets were used within the kernel and replacing them with BH workqueue implementations. This patch series is a first step toward broader adoption of BH workqueues across the kernel, and soon other subsystems using tasklets will undergo a similar transition. The groundwork laid here could serve as a blueprint for such future conversions. Testing Request: In addition to a thorough review of these changes, I kindly request that the reviwers engage in both functional and performance testing of this patch series. Specifically, benchmarks that measure interrupt handling efficiency, latency, and throughput. I welcome your feedback, suggestions, and any further discussion on this patch series. Additional Info: Based on the work done by Tejun Heo Branch: https://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git for-6.10 Allen Pais (9): hyperv: Convert from tasklet to BH workqueue dma: Convert from tasklet to BH workqueue IB: Convert from tasklet to BH workqueue USB: Convert from tasklet to BH workqueue mailbox: Convert from tasklet to BH workqueue ipmi: Convert from tasklet to BH workqueue s390: Convert from tasklet to BH workqueue drivers/media/*: Convert from tasklet to BH workqueue mmc: Convert from tasklet to BH workqueue drivers/char/ipmi/ipmi_msghandler.c | 30 drivers/dma/altera-msgdma.c | 15 ++-- drivers/dma/apple-admac.c | 15 ++-- drivers/dma/at_hdmac.c| 2 +- drivers/dma/at_xdmac.c| 15 ++-- drivers/dma/bcm2835-dma.c | 2 +- drivers/dma/dma-axi-dmac.c| 2 +- drivers/dma/dma-jz4780.c | 2 +- .../dma/dw-axi-dmac/dw-axi-dmac-platform.c| 2 +- drivers/dma/dw-edma/dw-edma-core.c| 2 +- drivers/dma/dw/core.c | 13 ++-- drivers/dma/dw/regs.h | 3 +- drivers/dma/ep93xx_dma.c | 15 ++-- drivers/dma/fsl-edma-common.c | 2 +- drivers/dma/fsl-qdma.c| 2 +- drivers/dma/fsl_raid.c| 11 +-- drivers/dma/fsl_raid.h| 2 +- drivers/dma/fsldma.c | 15 ++-- drivers/dma/fsldma.h | 3 +- drivers/dma/hisi_dma.c| 2 +- drivers/dma/hsu/hsu.c | 2 +- drivers/dma/idma64.c | 4 +- drivers/dma/img-mdc-dma.c | 2 +- drivers/dma/imx-dma.c | 27 +++ drivers/dma/imx-sdma.c| 6 +- drivers/dma/ioat/dma.c| 17 +++-- drivers/dma/ioat/dma.h| 5 +- drivers/dma/ioat/init.c | 2 +- drivers/dma/k3dma.c | 19 ++--- drivers/dma/mediatek/mtk-cqdma.c | 35 - drivers/dma/mediatek/mtk-hsdma.c | 2 +- drivers/dma/mediatek/mtk-uart-apdma.c | 4 +- drivers/dma/mmp_pdma.c| 13 ++-- drivers/dma/mmp_tdma.c| 11 +-- drivers/dma/mpc512x_dma.c | 17 +++-- drivers/dma/mv_xor.c | 13 ++-- drivers/dma/mv_xor.h | 5 +- drivers/dma/mv_xor_v2.c | 23 +++--- drivers/dma/mxs-dma.c | 13 ++-- drivers/dma/nbpfaxi.c | 15 ++-- drivers/dma/owl-dma.c | 2 +- drivers/dma/pch_dma.c | 17 +++-- drivers/dma/pl330.c | 31 drivers/dma/plx_dma.c | 13 ++-- drivers/dma/ppc4xx/adma.c | 17 +++-- drivers/dma/ppc4xx/adma.h | 5 +- drivers/dma/pxa_dma.c | 2 +- drivers/dma/qcom/bam_dma.c| 35 - driver
Re: [PATCH 0/8] scsi: convert tasklets to use new tasklet_setup()
> > > > > > > > Commit 12cc923f1ccc ("tasklet: Introduce new initialization > > > > API")' introduced a new tasklet initialization API. This series > > > > converts all the scsi drivers to use the new tasklet_setup() API > > > > > > I've got to say I agree with Jens, this was a silly obfuscation: > > > > > > +#define from_tasklet(var, callback_tasklet, tasklet_fieldname) \ > > > + container_of(callback_tasklet, typeof(*var), > > > tasklet_fieldname) > > > > > > Just use container_of directly since we all understand what it > > > does. > > > > But then the lines get really long, wrapped, etc. > > I really don't think that's a problem but if you want to add a new > generic container_of that does typeof instead of insisting on the type, > I'd be sort of OK with that ... provided you don't gratuitously alter > the argument order. > > The thing I object to is that this encourages everyone to roll their > own unnecessary container_of type macros in spite of the fact that it's > function is wholly generic. It's fine if you're eliminating one of the > arguments, or actually making the macro specific to the type, but in > this case you're not, you're making a completely generic macro where > the name is the only thing that's specific to this case. > > > This is what the timer_struct conversion did too (added a > > container_of wrapper), so I think it makes sense here too. > > I didn't see that one to object to it ... Since we could not get the generic API accepted, can I send out V2 which would use container_of()? Thanks, -- - Allen
Re: [PATCH 00/10] sound: convert tasklets to use new tasklet_setup()
Takashi, > > > > These patches which I wasn't CCed on and which need their subject lines > > > > fixing :( . With the subject lines fixed I guess so so > > > > > Extremely sorry. I thought I had it covered. How would you like it > > > worded? > > > > ASoC: > > To be more exact, "ASoC:" prefix is for sound/soc/*, and for the rest > sound/*, use "ALSA:" prefix please. I could not get the generic API accepted upstream. We would stick to from_tasklet() or container_of(). Could I go ahead and send out V2 using from_tasklet() with subject line fixed? Thanks, -- - Allen
Re: [PATCH 00/10] sound: convert tasklets to use new tasklet_setup()
> > > Mark, may I apply those ASoC patches through my tree together with > > others? Those seem targeting to 5.9, and I have a patch set to > > convert to tasklet for 5.10, which would be better manageable when > > based on top of those changes. > > These patches which I wasn't CCed on and which need their subject lines > fixing :( . With the subject lines fixed I guess so so Extremely sorry. I thought I had it covered. How would you like it worded? > Acked-by: Mark Brown > > but judging from some of the other threads about similar patches that I > was randomly CCed on I'm not sure people like from_tasklet() so perhaps > there might be issues. Yes, there is a new macro by name cast_out() is suggested in place of from_tasklet(). Hopefully it will go in soon. Will spin out V2 with the change and also re-word subject line. > Allen, as documented in submitting-patches.rst please send patches to > the maintainers for the code you would like to change. The normal > kernel workflow is that people apply patches from their inboxes, if they > aren't copied they are likely to not see the patch at all and it is much > more difficult to apply patches. I understand, I'll take care of it in the future. Thank you. -- - Allen
Re: [PATCH 00/10] sound: convert tasklets to use new tasklet_setup()
> > Well, then at the next time, please mention it explicitly in the cover > letter. Usually this kind of API conversion isn't done during rc. Or > it's done systematically via script or such. So unless mentioned, > it's not expected to be carried to 5.9. Sorry for having missed the detail. Will take care of it in the future. > > In anyway, if the final purpose is to drop the old tasklet API and > that's the plan for 5.9, all tree-wide changes have to be done in > 5.9 beforehand. Was that the decision? The idea was to land the tree-wide changes as part of 5.9 > > > > I have a patch set to drop the whole tasklet usage in sound/* > > > (destined for 5.10, to be submitted soon), so if that's for 5.10, > > > it'll be likely superfluous. > > > > I have picked patches from your tree to adapt to this new API. > > Those can be picked in 5.10 I suppose. > > Adapting the changes are trivial, don't worry. It was just a question > of how to organize changes. Sure, Thank you. - Allen
Re: [PATCH 06/20] ethernet: chelsio: convert tasklets to use new tasklet_setup() API
> > You need to adjust kdoc when you change functions: > > drivers/net/ethernet/chelsio/cxgb4/sge.c:2664: warning: Function parameter or > member 't' not described in 'restart_ctrlq' > drivers/net/ethernet/chelsio/cxgb4/sge.c:2664: warning: Excess function > parameter 'data' description in 'restart_ctrlq' > drivers/net/ethernet/chelsio/cxgb4/sge.c:2965: warning: Function parameter or > member 't' not described in 'restart_ofldq' > drivers/net/ethernet/chelsio/cxgb4/sge.c:2965: warning: Excess function > parameter 'data' description in 'restart_ofldq' Thanks, will fix it and spin V2. -- - Allen
Re: [PATCH 00/10] sound: convert tasklets to use new tasklet_setup()
> > Is this targeted for 5.9 or 5.10? This is targeted for 5.9. > I have a patch set to drop the whole tasklet usage in sound/* > (destined for 5.10, to be submitted soon), so if that's for 5.10, > it'll be likely superfluous. I have picked patches from your tree to adapt to this new API. Those can be picked in 5.10 I suppose. Thanks.
[PATCH 7/7] usb: mos7720: convert tasklets to use new tasklet_setup() API
From: Allen Pais In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/usb/serial/mos7720.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 2ec4eeacebc7..5eed1078fac8 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -282,11 +282,12 @@ static void destroy_urbtracker(struct kref *kref) * port callback had to be deferred because the disconnect mutex could not be * obtained at the time. */ -static void send_deferred_urbs(unsigned long _mos_parport) +static void send_deferred_urbs(struct tasklet_struct *t) { int ret_val; unsigned long flags; - struct mos7715_parport *mos_parport = (void *)_mos_parport; + struct mos7715_parport *mos_parport = from_tasklet(mos_parport, t, + urb_tasklet); struct urbtracker *urbtrack, *tmp; struct list_head *cursor, *next; struct device *dev; @@ -716,8 +717,7 @@ static int mos7715_parport_init(struct usb_serial *serial) INIT_LIST_HEAD(&mos_parport->deferred_urbs); usb_set_serial_data(serial, mos_parport); /* hijack private pointer */ mos_parport->serial = serial; - tasklet_init(&mos_parport->urb_tasklet, send_deferred_urbs, -(unsigned long) mos_parport); + tasklet_setup(&mos_parport->urb_tasklet, send_deferred_urbs); init_completion(&mos_parport->syncmsg_compl); /* cycle parallel port reset bit */ -- 2.17.1
[PATCH 6/7] usb: xhci: convert tasklets to use new tasklet_setup() API
From: Allen Pais In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/usb/host/xhci-dbgtty.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/host/xhci-dbgtty.c b/drivers/usb/host/xhci-dbgtty.c index b8918f73a432..ae4e4ab638b5 100644 --- a/drivers/usb/host/xhci-dbgtty.c +++ b/drivers/usb/host/xhci-dbgtty.c @@ -288,14 +288,14 @@ static const struct tty_operations dbc_tty_ops = { .unthrottle = dbc_tty_unthrottle, }; -static void dbc_rx_push(unsigned long _port) +static void dbc_rx_push(struct tasklet_struct *t) { struct dbc_request *req; struct tty_struct *tty; unsigned long flags; booldo_push = false; booldisconnect = false; - struct dbc_port *port = (void *)_port; + struct dbc_port *port = from_tasklet(port, t, push); struct list_head*queue = &port->read_queue; spin_lock_irqsave(&port->port_lock, flags); @@ -382,7 +382,7 @@ xhci_dbc_tty_init_port(struct xhci_dbc *dbc, struct dbc_port *port) { tty_port_init(&port->port); spin_lock_init(&port->port_lock); - tasklet_init(&port->push, dbc_rx_push, (unsigned long)port); + tasklet_setup(&port->push, dbc_rx_push); INIT_LIST_HEAD(&port->read_pool); INIT_LIST_HEAD(&port->read_queue); INIT_LIST_HEAD(&port->write_pool); -- 2.17.1
[PATCH 5/7] usb/gadget: fsl_qe_udc: convert tasklets to use new tasklet_setup() API
From: Allen Pais In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/usb/gadget/udc/fsl_qe_udc.c | 7 +++ 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/usb/gadget/udc/fsl_qe_udc.c b/drivers/usb/gadget/udc/fsl_qe_udc.c index 2707be628298..fa66449b3907 100644 --- a/drivers/usb/gadget/udc/fsl_qe_udc.c +++ b/drivers/usb/gadget/udc/fsl_qe_udc.c @@ -923,9 +923,9 @@ static int qe_ep_rxframe_handle(struct qe_ep *ep) return 0; } -static void ep_rx_tasklet(unsigned long data) +static void ep_rx_tasklet(struct tasklet_struct *t) { - struct qe_udc *udc = (struct qe_udc *)data; + struct qe_udc *udc = from_tasklet(udc, t, rx_tasklet); struct qe_ep *ep; struct qe_frame *pframe; struct qe_bd __iomem *bd; @@ -2553,8 +2553,7 @@ static int qe_udc_probe(struct platform_device *ofdev) DMA_TO_DEVICE); } - tasklet_init(&udc->rx_tasklet, ep_rx_tasklet, - (unsigned long)udc); + tasklet_setup(&udc->rx_tasklet, ep_rx_tasklet); /* request irq and disable DR */ udc->usb_irq = irq_of_parse_and_map(np, 0); if (!udc->usb_irq) { -- 2.17.1
[PATCH 4/7] usb/gadget: f_midi: convert tasklets to use new tasklet_setup() API
From: Allen Pais In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/usb/gadget/function/f_midi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c index 46af0aa07e2e..85cb15734aa8 100644 --- a/drivers/usb/gadget/function/f_midi.c +++ b/drivers/usb/gadget/function/f_midi.c @@ -698,9 +698,9 @@ static void f_midi_transmit(struct f_midi *midi) f_midi_drop_out_substreams(midi); } -static void f_midi_in_tasklet(unsigned long data) +static void f_midi_in_tasklet(struct tasklet_struct *t) { - struct f_midi *midi = (struct f_midi *) data; + struct f_midi *midi = from_tasklet(midi, t, tasklet); f_midi_transmit(midi); } @@ -875,7 +875,7 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f) int status, n, jack = 1, i = 0, endpoint_descriptor_index = 0; midi->gadget = cdev->gadget; - tasklet_init(&midi->tasklet, f_midi_in_tasklet, (unsigned long) midi); + tasklet_setup(&midi->tasklet, f_midi_in_tasklet); status = f_midi_register_card(midi); if (status < 0) goto fail_register; -- 2.17.1
[PATCH 3/7] usb: hcd: convert tasklets to use new tasklet_setup() API
From: Allen Pais In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/usb/core/hcd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index a33b849e8beb..2c6b9578a7d3 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1657,9 +1657,9 @@ static void __usb_hcd_giveback_urb(struct urb *urb) usb_put_urb(urb); } -static void usb_giveback_urb_bh(unsigned long param) +static void usb_giveback_urb_bh(struct tasklet_struct *t) { - struct giveback_urb_bh *bh = (struct giveback_urb_bh *)param; + struct giveback_urb_bh *bh = from_tasklet(bh, t, bh); struct list_head local_list; spin_lock_irq(&bh->lock); @@ -2403,7 +2403,7 @@ static void init_giveback_urb_bh(struct giveback_urb_bh *bh) spin_lock_init(&bh->lock); INIT_LIST_HEAD(&bh->head); - tasklet_init(&bh->bh, usb_giveback_urb_bh, (unsigned long)bh); + tasklet_setup(&bh->bh, usb_giveback_urb_bh); } struct usb_hcd *__usb_create_hcd(const struct hc_driver *driver, -- 2.17.1
[PATCH 2/7] usb: c67x00: convert tasklets to use new tasklet_setup() API
From: Allen Pais In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/usb/c67x00/c67x00-sched.c | 7 +++ 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/usb/c67x00/c67x00-sched.c b/drivers/usb/c67x00/c67x00-sched.c index f7f6229082ca..6275cb77a15b 100644 --- a/drivers/usb/c67x00/c67x00-sched.c +++ b/drivers/usb/c67x00/c67x00-sched.c @@ -1122,9 +1122,9 @@ static void c67x00_do_work(struct c67x00_hcd *c67x00) /* -- */ -static void c67x00_sched_tasklet(unsigned long __c67x00) +static void c67x00_sched_tasklet(struct tasklet_struct *t) { - struct c67x00_hcd *c67x00 = (struct c67x00_hcd *)__c67x00; + struct c67x00_hcd *c67x00 = from_tasklet(c67x00, t, tasklet); c67x00_do_work(c67x00); } @@ -1135,8 +1135,7 @@ void c67x00_sched_kick(struct c67x00_hcd *c67x00) int c67x00_sched_start_scheduler(struct c67x00_hcd *c67x00) { - tasklet_init(&c67x00->tasklet, c67x00_sched_tasklet, -(unsigned long)c67x00); + tasklet_setup(&c67x00->tasklet, c67x00_sched_tasklet); return 0; } -- 2.17.1
[PATCH 1/7] usb: atm: convert tasklets to use new tasklet_setup() API
From: Allen Pais In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/usb/atm/usbatm.c | 14 -- 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c index 4e12a32ca392..56fe30d247da 100644 --- a/drivers/usb/atm/usbatm.c +++ b/drivers/usb/atm/usbatm.c @@ -511,9 +511,10 @@ static unsigned int usbatm_write_cells(struct usbatm_data *instance, ** receive ** **/ -static void usbatm_rx_process(unsigned long data) +static void usbatm_rx_process(struct tasklet_struct *t) { - struct usbatm_data *instance = (struct usbatm_data *)data; + struct usbatm_data *instance = from_tasklet(instance, t, + rx_channel.tasklet); struct urb *urb; while ((urb = usbatm_pop_urb(&instance->rx_channel))) { @@ -564,9 +565,10 @@ static void usbatm_rx_process(unsigned long data) ** send ** ***/ -static void usbatm_tx_process(unsigned long data) +static void usbatm_tx_process(struct tasklet_struct *t) { - struct usbatm_data *instance = (struct usbatm_data *)data; + struct usbatm_data *instance = from_tasklet(instance, t, + tx_channel.tasklet); struct sk_buff *skb = instance->current_skb; struct urb *urb = NULL; const unsigned int buf_size = instance->tx_channel.buf_size; @@ -1069,8 +1071,8 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id, usbatm_init_channel(&instance->rx_channel); usbatm_init_channel(&instance->tx_channel); - tasklet_init(&instance->rx_channel.tasklet, usbatm_rx_process, (unsigned long)instance); - tasklet_init(&instance->tx_channel.tasklet, usbatm_tx_process, (unsigned long)instance); + tasklet_setup(&instance->rx_channel.tasklet, usbatm_rx_process); + tasklet_setup(&instance->tx_channel.tasklet, usbatm_tx_process); instance->rx_channel.stride = ATM_CELL_SIZE + driver->rx_padding; instance->tx_channel.stride = ATM_CELL_SIZE + driver->tx_padding; instance->rx_channel.usbatm = instance->tx_channel.usbatm = instance; -- 2.17.1
[PATCH 0/7] usb: convert tasklets to use new tasklet_setup()
From: Allen Pais Commit 12cc923f1ccc ("tasklet: Introduce new initialization API")' introduced a new tasklet initialization API. This series converts all the usb drivers to use the new tasklet_setup() API Allen Pais (7): usb: atm: convert tasklets to use new tasklet_setup() API usb: c67x00: convert tasklets to use new tasklet_setup() API usb: hcd: convert tasklets to use new tasklet_setup() API usb/gadget: f_midi: convert tasklets to use new tasklet_setup() API usb/gadget: fsl_qe_udc: convert tasklets to use new tasklet_setup() API usb: xhci: convert tasklets to use new tasklet_setup() API usb: mos7720: convert tasklets to use new tasklet_setup() API drivers/usb/atm/usbatm.c | 14 -- drivers/usb/c67x00/c67x00-sched.c| 7 +++ drivers/usb/core/hcd.c | 6 +++--- drivers/usb/gadget/function/f_midi.c | 6 +++--- drivers/usb/gadget/udc/fsl_qe_udc.c | 7 +++ drivers/usb/host/xhci-dbgtty.c | 6 +++--- drivers/usb/serial/mos7720.c | 8 7 files changed, 27 insertions(+), 27 deletions(-) -- 2.17.1
[PATCH 10/10] sound: ua101: convert tasklets to use new tasklet_setup() API
From: Allen Pais In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- sound/usb/misc/ua101.c | 7 +++ 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c index 884e740a785c..3b2dce1043f5 100644 --- a/sound/usb/misc/ua101.c +++ b/sound/usb/misc/ua101.c @@ -247,9 +247,9 @@ static inline void add_with_wraparound(struct ua101 *ua, *value -= ua->playback.queue_length; } -static void playback_tasklet(unsigned long data) +static void playback_tasklet(struct tasklet_struct *t) { - struct ua101 *ua = (void *)data; + struct ua101 *ua = from_tasklet(ua, t, playback_tasklet); unsigned long flags; unsigned int frames; struct ua101_urb *urb; @@ -1218,8 +1218,7 @@ static int ua101_probe(struct usb_interface *interface, spin_lock_init(&ua->lock); mutex_init(&ua->mutex); INIT_LIST_HEAD(&ua->ready_playback_urbs); - tasklet_init(&ua->playback_tasklet, -playback_tasklet, (unsigned long)ua); + tasklet_setup(&ua->playback_tasklet, playback_tasklet); init_waitqueue_head(&ua->alsa_capture_wait); init_waitqueue_head(&ua->rate_feedback_wait); init_waitqueue_head(&ua->alsa_playback_wait); -- 2.17.1
[PATCH 09/10] sound: midi: convert tasklets to use new tasklet_setup() API
From: Allen Pais In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- sound/usb/midi.c | 7 +++ 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sound/usb/midi.c b/sound/usb/midi.c index df639fe03118..e8287a05e36b 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c @@ -344,10 +344,9 @@ static void snd_usbmidi_do_output(struct snd_usb_midi_out_endpoint *ep) spin_unlock_irqrestore(&ep->buffer_lock, flags); } -static void snd_usbmidi_out_tasklet(unsigned long data) +static void snd_usbmidi_out_tasklet(struct tasklet_struct *t) { - struct snd_usb_midi_out_endpoint *ep = - (struct snd_usb_midi_out_endpoint *) data; + struct snd_usb_midi_out_endpoint *ep = from_tasklet(ep, t, tasklet); snd_usbmidi_do_output(ep); } @@ -1441,7 +1440,7 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi *umidi, } spin_lock_init(&ep->buffer_lock); - tasklet_init(&ep->tasklet, snd_usbmidi_out_tasklet, (unsigned long)ep); + tasklet_setup(&ep->tasklet, snd_usbmidi_out_tasklet); init_waitqueue_head(&ep->drain_wait); for (i = 0; i < 0x10; ++i) -- 2.17.1
[PATCH 08/10] sound/soc: txx9: convert tasklets to use new tasklet_setup() API
From: Allen Pais In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- sound/soc/txx9/txx9aclc.c | 7 +++ 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sound/soc/txx9/txx9aclc.c b/sound/soc/txx9/txx9aclc.c index 4b1cd4da3e36..939b33ec39f5 100644 --- a/sound/soc/txx9/txx9aclc.c +++ b/sound/soc/txx9/txx9aclc.c @@ -134,9 +134,9 @@ txx9aclc_dma_submit(struct txx9aclc_dmadata *dmadata, dma_addr_t buf_dma_addr) #define NR_DMA_CHAIN 2 -static void txx9aclc_dma_tasklet(unsigned long data) +static void txx9aclc_dma_tasklet(struct tasklet_struct *t) { - struct txx9aclc_dmadata *dmadata = (struct txx9aclc_dmadata *)data; + struct txx9aclc_dmadata *dmadata = from_tasklet(dmadata, t, tasklet); struct dma_chan *chan = dmadata->dma_chan; struct dma_async_tx_descriptor *desc; struct snd_pcm_substream *substream = dmadata->substream; @@ -352,8 +352,7 @@ static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev, "playback" : "capture"); return -EBUSY; } - tasklet_init(&dmadata->tasklet, txx9aclc_dma_tasklet, -(unsigned long)dmadata); + tasklet_setup(&dmadata->tasklet, txx9aclc_dma_tasklet); return 0; } -- 2.17.1
[PATCH 07/10] sound/soc: sh: convert tasklets to use new tasklet_setup() API
From: Allen Pais In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- sound/soc/sh/siu_pcm.c | 10 -- 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/sound/soc/sh/siu_pcm.c b/sound/soc/sh/siu_pcm.c index bd9de77c35f3..50fc7810723e 100644 --- a/sound/soc/sh/siu_pcm.c +++ b/sound/soc/sh/siu_pcm.c @@ -198,9 +198,9 @@ static int siu_pcm_rd_set(struct siu_port *port_info, return 0; } -static void siu_io_tasklet(unsigned long data) +static void siu_io_tasklet(struct tasklet_struct *t) { - struct siu_stream *siu_stream = (struct siu_stream *)data; + struct siu_stream *siu_stream = from_tasklet(siu_stream, t, tasklet); struct snd_pcm_substream *substream = siu_stream->substream; struct device *dev = substream->pcm->card->dev; struct snd_pcm_runtime *rt = substream->runtime; @@ -520,10 +520,8 @@ static int siu_pcm_new(struct snd_soc_component *component, (*port_info)->pcm = pcm; /* IO tasklets */ - tasklet_init(&(*port_info)->playback.tasklet, siu_io_tasklet, -(unsigned long)&(*port_info)->playback); - tasklet_init(&(*port_info)->capture.tasklet, siu_io_tasklet, -(unsigned long)&(*port_info)->capture); + tasklet_setup(&(*port_info)->playback.tasklet, siu_io_tasklet); + tasklet_setup(&(*port_info)->capture.tasklet, siu_io_tasklet); } dev_info(card->dev, "SuperH SIU driver initialized.\n"); -- 2.17.1
[PATCH 06/10] sound/soc: fsl_esai: convert tasklets to use new tasklet_setup() API
From: Allen Pais In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- sound/soc/fsl/fsl_esai.c | 7 +++ 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index 4ae36099ae82..79b861afd986 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -708,9 +708,9 @@ static void fsl_esai_trigger_stop(struct fsl_esai *esai_priv, bool tx) ESAI_xFCR_xFR, 0); } -static void fsl_esai_hw_reset(unsigned long arg) +static void fsl_esai_hw_reset(struct tasklet_struct *t) { - struct fsl_esai *esai_priv = (struct fsl_esai *)arg; + struct fsl_esai *esai_priv = from_tasklet(esai_priv, t, task); bool tx = true, rx = false, enabled[2]; unsigned long lock_flags; u32 tfcr, rfcr; @@ -1070,8 +1070,7 @@ static int fsl_esai_probe(struct platform_device *pdev) return ret; } - tasklet_init(&esai_priv->task, fsl_esai_hw_reset, -(unsigned long)esai_priv); + tasklet_setup(&esai_priv->task, fsl_esai_hw_reset); pm_runtime_enable(&pdev->dev); -- 2.17.1
[PATCH 05/10] sound: rm9652: convert tasklets to use new tasklet_setup() API
From: Allen Pais In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- sound/pci/rme9652/hdsp.c | 6 +++--- sound/pci/rme9652/hdspm.c | 7 +++ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 227aece17e39..dda56ecfd33b 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -3791,9 +3791,9 @@ static int snd_hdsp_set_defaults(struct hdsp *hdsp) return 0; } -static void hdsp_midi_tasklet(unsigned long arg) +static void hdsp_midi_tasklet(struct tasklet_struct *t) { - struct hdsp *hdsp = (struct hdsp *)arg; + struct hdsp *hdsp = from_tasklet(hdsp, t, midi_tasklet); if (hdsp->midi[0].pending) snd_hdsp_midi_input_read (&hdsp->midi[0]); @@ -5182,7 +5182,7 @@ static int snd_hdsp_create(struct snd_card *card, spin_lock_init(&hdsp->lock); - tasklet_init(&hdsp->midi_tasklet, hdsp_midi_tasklet, (unsigned long)hdsp); + tasklet_setup(&hdsp->midi_tasklet, hdsp_midi_tasklet); pci_read_config_word(hdsp->pci, PCI_CLASS_REVISION, &hdsp->firmware_rev); hdsp->firmware_rev &= 0xff; diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 0fa49f4d15cf..572350aaf18d 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -2169,9 +2169,9 @@ static int snd_hdspm_create_midi(struct snd_card *card, } -static void hdspm_midi_tasklet(unsigned long arg) +static void hdspm_midi_tasklet(struct tasklet_struct *t) { - struct hdspm *hdspm = (struct hdspm *)arg; + struct hdspm *hdspm = from_tasklet(hdspm, t, midi_tasklet); int i = 0; while (i < hdspm->midiPorts) { @@ -6836,8 +6836,7 @@ static int snd_hdspm_create(struct snd_card *card, } - tasklet_init(&hdspm->midi_tasklet, - hdspm_midi_tasklet, (unsigned long) hdspm); + tasklet_setup(&hdspm->midi_tasklet, hdspm_midi_tasklet); if (hdspm->io_type != MADIface) { -- 2.17.1
[PATCH 04/10] sound: riptide: convert tasklets to use new tasklet_setup() API
From: Allen Pais In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- sound/pci/riptide/riptide.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index b4f300281822..098c69b3b7aa 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c @@ -1070,9 +1070,9 @@ getmixer(struct cmdif *cif, short num, unsigned short *rval, return 0; } -static void riptide_handleirq(unsigned long dev_id) +static void riptide_handleirq(struct tasklet_struct *t) { - struct snd_riptide *chip = (void *)dev_id; + struct snd_riptide *chip = from_tasklet(chip, t, riptide_tq); struct cmdif *cif = chip->cif; struct snd_pcm_substream *substream[PLAYBACK_SUBSTREAMS + 1]; struct snd_pcm_runtime *runtime; @@ -1843,7 +1843,7 @@ snd_riptide_create(struct snd_card *card, struct pci_dev *pci, chip->received_irqs = 0; chip->handled_irqs = 0; chip->cif = NULL; - tasklet_init(&chip->riptide_tq, riptide_handleirq, (unsigned long)chip); + tasklet_setup(&chip->riptide_tq, riptide_handleirq); if ((chip->res_port = request_region(chip->port, 64, "RIPTIDE")) == NULL) { -- 2.17.1
[PATCH 03/10] sound: asihpi: convert tasklets to use new tasklet_setup() API
From: Allen Pais In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- sound/pci/asihpi/asihpi.c | 9 - 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c index 023c35a2a951..35e76480306e 100644 --- a/sound/pci/asihpi/asihpi.c +++ b/sound/pci/asihpi/asihpi.c @@ -921,10 +921,10 @@ static void snd_card_asihpi_timer_function(struct timer_list *t) add_timer(&dpcm->timer); } -static void snd_card_asihpi_int_task(unsigned long data) +static void snd_card_asihpi_int_task(struct tasklet_struct *t) { - struct hpi_adapter *a = (struct hpi_adapter *)data; - struct snd_card_asihpi *asihpi; + struct snd_card_asihpi *asihpi = from_tasklet(asihpi, t, t); + struct hpi_adapter *a = asihpi->hpi; WARN_ON(!a || !a->snd_card || !a->snd_card->private_data); asihpi = (struct snd_card_asihpi *)a->snd_card->private_data; @@ -2871,8 +2871,7 @@ static int snd_asihpi_probe(struct pci_dev *pci_dev, if (hpi->interrupt_mode) { asihpi->pcm_start = snd_card_asihpi_pcm_int_start; asihpi->pcm_stop = snd_card_asihpi_pcm_int_stop; - tasklet_init(&asihpi->t, snd_card_asihpi_int_task, - (unsigned long)hpi); + tasklet_setup(&asihpi->t, snd_card_asihpi_int_task); hpi->interrupt_callback = snd_card_asihpi_isr; } else { asihpi->pcm_start = snd_card_asihpi_pcm_timer_start; -- 2.17.1
[PATCH 02/10] sound: firewire: convert tasklets to use new tasklet_setup() API
From: Allen Pais In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- sound/firewire/amdtp-stream.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index f8586f75441d..ee1c428b1fd3 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -64,7 +64,7 @@ #define IT_PKT_HEADER_SIZE_CIP 8 // For 2 CIP header. #define IT_PKT_HEADER_SIZE_NO_CIP 0 // Nothing. -static void pcm_period_tasklet(unsigned long data); +static void pcm_period_tasklet(struct tasklet_struct *t); /** * amdtp_stream_init - initialize an AMDTP stream structure @@ -94,7 +94,7 @@ int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit, s->flags = flags; s->context = ERR_PTR(-1); mutex_init(&s->mutex); - tasklet_init(&s->period_tasklet, pcm_period_tasklet, (unsigned long)s); + tasklet_setup(&s->period_tasklet, pcm_period_tasklet); s->packet_index = 0; init_waitqueue_head(&s->callback_wait); @@ -441,9 +441,9 @@ static void update_pcm_pointers(struct amdtp_stream *s, } } -static void pcm_period_tasklet(unsigned long data) +static void pcm_period_tasklet(struct tasklet_struct *t) { - struct amdtp_stream *s = (void *)data; + struct amdtp_stream *s = from_tasklet(s, t, period_tasklet); struct snd_pcm_substream *pcm = READ_ONCE(s->pcm); if (pcm) -- 2.17.1
[PATCH 01/10] sound: core: convert tasklets to use new tasklet_setup() API
From: Allen Pais In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- sound/core/timer.c | 7 +++ 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sound/core/timer.c b/sound/core/timer.c index d9f85f2d66a3..6e27d87b18ed 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -816,9 +816,9 @@ static void snd_timer_clear_callbacks(struct snd_timer *timer, * timer tasklet * */ -static void snd_timer_tasklet(unsigned long arg) +static void snd_timer_tasklet(struct tasklet_struct *t) { - struct snd_timer *timer = (struct snd_timer *) arg; + struct snd_timer *timer = from_tasklet(timer, t, task_queue); unsigned long flags; if (timer->card && timer->card->shutdown) { @@ -967,8 +967,7 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid, INIT_LIST_HEAD(&timer->ack_list_head); INIT_LIST_HEAD(&timer->sack_list_head); spin_lock_init(&timer->lock); - tasklet_init(&timer->task_queue, snd_timer_tasklet, -(unsigned long)timer); + tasklet_setup(&timer->task_queue, snd_timer_tasklet); timer->max_instances = 1000; /* default limit per timer */ if (card != NULL) { timer->module = card->module; -- 2.17.1
[PATCH 00/10] sound: convert tasklets to use new tasklet_setup()
From: Allen Pais Commit 12cc923f1ccc ("tasklet: Introduce new initialization API")' introduced a new tasklet initialization API. This series converts all the sound drivers to use the new tasklet_setup() API Allen Pais (10): sound: core: convert tasklets to use new tasklet_setup() API sound: firewire: convert tasklets to use new tasklet_setup() API sound: asihpi: convert tasklets to use new tasklet_setup() API sound: riptide: convert tasklets to use new tasklet_setup() API sound: rm9652: convert tasklets to use new tasklet_setup() API sound/soc: fsl_esai: convert tasklets to use new tasklet_setup() API sound/soc: sh: convert tasklets to use new tasklet_setup() API sound/soc: txx9: convert tasklets to use new tasklet_setup() API sound: midi: convert tasklets to use new tasklet_setup() API sound: ua101: convert tasklets to use new tasklet_setup() API sound/core/timer.c| 7 +++ sound/firewire/amdtp-stream.c | 8 sound/pci/asihpi/asihpi.c | 9 - sound/pci/riptide/riptide.c | 6 +++--- sound/pci/rme9652/hdsp.c | 6 +++--- sound/pci/rme9652/hdspm.c | 7 +++ sound/soc/fsl/fsl_esai.c | 7 +++ sound/soc/sh/siu_pcm.c| 10 -- sound/soc/txx9/txx9aclc.c | 7 +++ sound/usb/midi.c | 7 +++ sound/usb/misc/ua101.c| 7 +++ 11 files changed, 36 insertions(+), 45 deletions(-) -- 2.17.1
[PATCH 8/8] scsi: pmcraid: convert tasklets to use new tasklet_setup() API
From: Allen Pais In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/scsi/pmcraid.c | 29 +++-- drivers/scsi/pmcraid.h | 9 +++-- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index aa9ae2ae8579..b7bbefcbb11d 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c @@ -4198,7 +4198,7 @@ static irqreturn_t pmcraid_isr_msix(int irq, void *dev_id) } } - tasklet_schedule(&(pinstance->isr_tasklet[hrrq_id])); + tasklet_schedule(&(pinstance->isr_tasklet[hrrq_id]).tasklet); return IRQ_HANDLED; } @@ -4267,7 +4267,7 @@ static irqreturn_t pmcraid_isr(int irq, void *dev_id) pinstance->int_regs.ioa_host_interrupt_clr_reg); tasklet_schedule( - &(pinstance->isr_tasklet[hrrq_id])); + &(pinstance->isr_tasklet[hrrq_id].tasklet)); } } @@ -4380,20 +4380,20 @@ static void pmcraid_worker_function(struct work_struct *workp) * Return Value * None */ -static void pmcraid_tasklet_function(unsigned long instance) +static void pmcraid_tasklet_function(struct tasklet_struct *t) { - struct pmcraid_isr_param *hrrq_vector; - struct pmcraid_instance *pinstance; + struct pmcraid_tsk_param *tsk_param = from_tasklet(tsk_param, t, + tasklet); + int id = tsk_param->isr_tasklet_id; + struct pmcraid_instance *pinstance = container_of(tsk_param, + typeof(*pinstance), + isr_tasklet[id]); unsigned long hrrq_lock_flags; unsigned long pending_lock_flags; unsigned long host_lock_flags; spinlock_t *lockp; /* hrrq buffer lock */ - int id; u32 resp; - hrrq_vector = (struct pmcraid_isr_param *)instance; - pinstance = hrrq_vector->drv_inst; - id = hrrq_vector->hrrq_id; lockp = &(pinstance->hrrq_lock[id]); /* loop through each of the commands responded by IOA. Each HRRQ buf is @@ -4882,10 +4882,11 @@ static int pmcraid_allocate_config_buffers(struct pmcraid_instance *pinstance) static void pmcraid_init_tasklets(struct pmcraid_instance *pinstance) { int i; - for (i = 0; i < pinstance->num_hrrq; i++) - tasklet_init(&pinstance->isr_tasklet[i], -pmcraid_tasklet_function, -(unsigned long)&pinstance->hrrq_vector[i]); + for (i = 0; i < pinstance->num_hrrq; i++) { + pinstance->isr_tasklet[i].isr_tasklet_id = i; + tasklet_setup(&pinstance->isr_tasklet[i].tasklet, +pmcraid_tasklet_function); + } } /** @@ -4900,7 +4901,7 @@ static void pmcraid_kill_tasklets(struct pmcraid_instance *pinstance) { int i; for (i = 0; i < pinstance->num_hrrq; i++) - tasklet_kill(&pinstance->isr_tasklet[i]); + tasklet_kill(&pinstance->isr_tasklet[i].tasklet); } /** diff --git a/drivers/scsi/pmcraid.h b/drivers/scsi/pmcraid.h index 15c962108075..68dab849d4c1 100644 --- a/drivers/scsi/pmcraid.h +++ b/drivers/scsi/pmcraid.h @@ -617,6 +617,11 @@ struct pmcraid_isr_param { u8 hrrq_id; /* hrrq entry index */ }; +/* Tasklet parameters (one for each enabled tasklet) */ +struct pmcraid_tsk_param { + struct tasklet_struct tasklet; + u8 isr_tasklet_id; /* isr_tasklet entry index */ +}; /* AEN message header sent as part of event data to applications */ struct pmcraid_aen_msg { @@ -752,8 +757,8 @@ struct pmcraid_instance { spinlock_t free_pool_lock; /* free pool lock */ spinlock_t pending_pool_lock; /* pending pool lock */ - /* Tasklet to handle deferred processing */ - struct tasklet_struct isr_tasklet[PMCRAID_NUM_MSIX_VECTORS]; + /* Tasklet parameters and tasklets to handle deferred processing */ + struct pmcraid_tsk_param isr_tasklet[PMCRAID_NUM_MSIX_VECTORS]; /* Work-queue (Shared) for deferred reset processing */ struct work_struct worker_q; -- 2.17.1
[PATCH 7/8] scsi: pm8001: convert tasklets to use new tasklet_setup() API
From: Allen Pais In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/scsi/pm8001/pm8001_init.c | 55 ++- drivers/scsi/pm8001/pm8001_sas.h | 6 +++- 2 files changed, 37 insertions(+), 24 deletions(-) diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index 20fa96cbc9d3..818816c8b295 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -187,12 +187,15 @@ static void pm8001_free(struct pm8001_hba_info *pm8001_ha) * @opaque: the passed general host adapter struct * Note: pm8001_tasklet is common for pm8001 & pm80xx */ -static void pm8001_tasklet(unsigned long opaque) +static void pm8001_tasklet(struct tasklet_struct *t) { - struct pm8001_hba_info *pm8001_ha; + struct tsk_param *tsk_param = from_tasklet(tsk_param, t, tasklet); + struct pm8001_hba_info *pm8001_ha = container_of(tsk_param, + typeof(*pm8001_ha), + tasklet[tsk_param->irq_id]); struct isr_param *irq_vector; - irq_vector = (struct isr_param *)opaque; + irq_vector = &pm8001_ha->irq_vector[tsk_param->irq_id]; pm8001_ha = irq_vector->drv_inst; if (unlikely(!pm8001_ha)) BUG_ON(1); @@ -221,7 +224,7 @@ static irqreturn_t pm8001_interrupt_handler_msix(int irq, void *opaque) if (!PM8001_CHIP_DISP->is_our_interrupt(pm8001_ha)) return IRQ_NONE; #ifdef PM8001_USE_TASKLET - tasklet_schedule(&pm8001_ha->tasklet[irq_vector->irq_id]); + tasklet_schedule(&pm8001_ha->tasklet[irq_vector->irq_id].tasklet); #else ret = PM8001_CHIP_DISP->isr(pm8001_ha, irq_vector->irq_id); #endif @@ -246,7 +249,7 @@ static irqreturn_t pm8001_interrupt_handler_intx(int irq, void *dev_id) return IRQ_NONE; #ifdef PM8001_USE_TASKLET - tasklet_schedule(&pm8001_ha->tasklet[0]); + tasklet_schedule(&pm8001_ha->tasklet[0].tasklet); #else ret = PM8001_CHIP_DISP->isr(pm8001_ha, 0); #endif @@ -507,13 +510,16 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev, #ifdef PM8001_USE_TASKLET /* Tasklet for non msi-x interrupt handler */ if ((!pdev->msix_cap || !pci_msi_enabled()) - || (pm8001_ha->chip_id == chip_8001)) - tasklet_init(&pm8001_ha->tasklet[0], pm8001_tasklet, - (unsigned long)&(pm8001_ha->irq_vector[0])); - else - for (j = 0; j < PM8001_MAX_MSIX_VEC; j++) - tasklet_init(&pm8001_ha->tasklet[j], pm8001_tasklet, - (unsigned long)&(pm8001_ha->irq_vector[j])); + || (pm8001_ha->chip_id == chip_8001)) { + pm8001_ha->tasklet[0].irq_id = 0; + tasklet_setup(&pm8001_ha->tasklet[0].tasklet, pm8001_tasklet); + } else { + for (j = 0; j < PM8001_MAX_MSIX_VEC; j++) { + pm8001_ha->tasklet[j].irq_id = j; + tasklet_setup(&pm8001_ha->tasklet[j].tasklet, + pm8001_tasklet); + } + } #endif pm8001_ioremap(pm8001_ha); if (!pm8001_alloc(pm8001_ha, ent)) @@ -1162,10 +1168,10 @@ static void pm8001_pci_remove(struct pci_dev *pdev) /* For non-msix and msix interrupts */ if ((!pdev->msix_cap || !pci_msi_enabled()) || (pm8001_ha->chip_id == chip_8001)) - tasklet_kill(&pm8001_ha->tasklet[0]); + tasklet_kill(&pm8001_ha->tasklet[0].tasklet); else for (j = 0; j < PM8001_MAX_MSIX_VEC; j++) - tasklet_kill(&pm8001_ha->tasklet[j]); + tasklet_kill(&pm8001_ha->tasklet[j].tasklet); #endif scsi_host_put(pm8001_ha->shost); pm8001_free(pm8001_ha); @@ -1212,10 +1218,10 @@ static int pm8001_pci_suspend(struct pci_dev *pdev, pm_message_t state) /* For non-msix and msix interrupts */ if ((!pdev->msix_cap || !pci_msi_enabled()) || (pm8001_ha->chip_id == chip_8001)) - tasklet_kill(&pm8001_ha->tasklet[0]); + tasklet_kill(&pm8001_ha->tasklet[0].tasklet); else for (j = 0; j < PM8001_MAX_MSIX_VEC; j++) - tasklet_kill(&pm8001_ha->tasklet[j]); + tasklet_kill(&pm8001_ha->tasklet[j].tasklet); #endif device_state = pci_choose_state(pdev, state); pm8001_printk("pdev=
[PATCH 6/8] scsi: mvsas: convert tasklets to use new tasklet_setup() API
From: Allen Pais In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/scsi/mvsas/mv_init.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c index 978f5283c883..53b2d463fa13 100644 --- a/drivers/scsi/mvsas/mv_init.c +++ b/drivers/scsi/mvsas/mv_init.c @@ -147,13 +147,14 @@ static void mvs_free(struct mvs_info *mvi) } #ifdef CONFIG_SCSI_MVSAS_TASKLET -static void mvs_tasklet(unsigned long opaque) +static void mvs_tasklet(struct tasklet_struct *t) { u32 stat; u16 core_nr, i = 0; struct mvs_info *mvi; - struct sas_ha_struct *sha = (struct sas_ha_struct *)opaque; + struct mvs_prv_info *mpi = from_tasklet(mpi, t, mv_tasklet); + struct sas_ha_struct *sha = pci_get_drvdata(mpi->mvi[0]->pdev); core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host; mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[0]; @@ -564,8 +565,7 @@ static int mvs_pci_init(struct pci_dev *pdev, const struct pci_device_id *ent) } while (nhost < chip->n_host); mpi = (struct mvs_prv_info *)(SHOST_TO_SAS_HA(shost)->lldd_ha); #ifdef CONFIG_SCSI_MVSAS_TASKLET - tasklet_init(&(mpi->mv_tasklet), mvs_tasklet, -(unsigned long)SHOST_TO_SAS_HA(shost)); + tasklet_setup(&(mpi->mv_tasklet), mvs_tasklet); #endif mvs_post_sas_ha_init(shost, chip); -- 2.17.1
[PATCH 5/8] scsi: megaraid: convert tasklets to use new tasklet_setup() API
From: Allen Pais In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/scsi/megaraid/megaraid_mbox.c | 9 - drivers/scsi/megaraid/megaraid_sas.h| 2 +- drivers/scsi/megaraid/megaraid_sas_base.c | 16 +++- drivers/scsi/megaraid/megaraid_sas_fusion.c | 14 +++--- 4 files changed, 19 insertions(+), 22 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index 19469a2c0ea3..47b2d8045c9d 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c @@ -119,7 +119,7 @@ static void megaraid_mbox_prepare_epthru(adapter_t *, scb_t *, static irqreturn_t megaraid_isr(int, void *); -static void megaraid_mbox_dpc(unsigned long); +static void megaraid_mbox_dpc(struct tasklet_struct *t); static ssize_t megaraid_sysfs_show_app_hndl(struct device *, struct device_attribute *attr, char *); static ssize_t megaraid_sysfs_show_ldnum(struct device *, struct device_attribute *attr, char *); @@ -878,8 +878,7 @@ megaraid_init_mbox(adapter_t *adapter) } // setup tasklet for DPC - tasklet_init(&adapter->dpc_h, megaraid_mbox_dpc, - (unsigned long)adapter); + tasklet_setup(&adapter->dpc_h, megaraid_mbox_dpc); con_log(CL_DLEVEL1, (KERN_INFO "megaraid mbox hba successfully initialized\n")); @@ -2168,9 +2167,9 @@ megaraid_isr(int irq, void *devp) * it is being called. */ static void -megaraid_mbox_dpc(unsigned long devp) +megaraid_mbox_dpc(struct tasklet_struct *t) { - adapter_t *adapter = (adapter_t *)devp; + adapter_t *adapter = from_tasklet(adapter, t, dpc_h); mraid_device_t *raid_dev; struct list_headclist; struct scatterlist *sgl; diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 5e4137f10e0e..ce361b2b9f14 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -2531,7 +2531,7 @@ struct megasas_instance_template { int (*check_reset)(struct megasas_instance *, \ struct megasas_register_set __iomem *); irqreturn_t (*service_isr)(int irq, void *devp); - void (*tasklet)(unsigned long); + void (*tasklet)(struct tasklet_struct *t); u32 (*init_adapter)(struct megasas_instance *); u32 (*build_and_issue_cmd) (struct megasas_instance *, struct scsi_cmnd *); diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 861f7140f52e..dba60cc1cf41 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -217,7 +217,7 @@ megasas_init_adapter_mfi(struct megasas_instance *instance); u32 megasas_build_and_issue_cmd(struct megasas_instance *instance, struct scsi_cmnd *scmd); -static void megasas_complete_cmd_dpc(unsigned long instance_addr); +static void megasas_complete_cmd_dpc(struct tasklet_struct *t); int wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd, int seconds); @@ -2217,14 +2217,14 @@ megasas_check_and_restore_queue_depth(struct megasas_instance *instance) * * Tasklet to complete cmds */ -static void megasas_complete_cmd_dpc(unsigned long instance_addr) +static void megasas_complete_cmd_dpc(struct tasklet_struct *t) { u32 producer; u32 consumer; u32 context; struct megasas_cmd *cmd; - struct megasas_instance *instance = - (struct megasas_instance *)instance_addr; + struct megasas_instance *instance = from_tasklet(instance, t, +isr_tasklet); unsigned long flags; /* If we have already declared adapter dead, donot complete cmds */ @@ -2769,7 +2769,7 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance) * Call cmd completion routine. Cmd to be * be completed directly without depending on isr. */ - megasas_complete_cmd_dpc((unsigned long)instance); + megasas_complete_cmd_dpc(&instance->isr_tasklet); } msleep(1000); @@ -6180,8 +6180,7 @@ static int megasas_init_fw(struct megasas_instance *instance) dev_info(&instance->pdev->dev, "RDPQ mode\t: (%s)\n", instance->is_rdpq ? "enabled" : "disabled"); - tasklet_init(&instance->isr_tasklet, instance->
[PATCH 4/8] scsi: isci: convert tasklets to use new tasklet_setup() API
From: Allen Pais In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/scsi/isci/host.c | 4 ++-- drivers/scsi/isci/host.h | 2 +- drivers/scsi/isci/init.c | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 7b5deae68d33..599adebd039e 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -1113,9 +1113,9 @@ void ireq_done(struct isci_host *ihost, struct isci_request *ireq, struct sas_ta * @data: This parameter specifies the ISCI host object * */ -void isci_host_completion_routine(unsigned long data) +void isci_host_completion_routine(struct tasklet_struct *t) { - struct isci_host *ihost = (struct isci_host *)data; + struct isci_host *ihost = from_tasklet(ihost, t, completion_tasklet); u16 active; spin_lock_irq(&ihost->scic_lock); diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 6bc3f022630a..6abe23682d9b 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -478,7 +478,7 @@ void isci_tci_free(struct isci_host *ihost, u16 tci); void ireq_done(struct isci_host *ihost, struct isci_request *ireq, struct sas_task *task); int isci_host_init(struct isci_host *); -void isci_host_completion_routine(unsigned long data); +void isci_host_completion_routine(struct tasklet_struct *t); void isci_host_deinit(struct isci_host *); void sci_controller_disable_interrupts(struct isci_host *ihost); bool sci_controller_has_remote_devices_stopping(struct isci_host *ihost); diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 085e285f427d..32a0117b5ff4 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -511,8 +511,7 @@ static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id) init_waitqueue_head(&ihost->eventq); ihost->sas_ha.dev = &ihost->pdev->dev; ihost->sas_ha.lldd_ha = ihost; - tasklet_init(&ihost->completion_tasklet, -isci_host_completion_routine, (unsigned long)ihost); + tasklet_setup(&ihost->completion_tasklet, isci_host_completion_routine); /* validate module parameters */ /* TODO: kill struct sci_user_parameters and reference directly */ -- 2.17.1
[PATCH 3/8] scsi: ibmvscsi: convert tasklets to use new tasklet_setup() API
From: Allen Pais In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/scsi/ibmvscsi/ibmvfc.c | 6 +++--- drivers/scsi/ibmvscsi/ibmvscsi.c | 8 drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c | 7 +++ 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index 77f4d37d5bd6..50f025cdabbd 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -3204,9 +3204,9 @@ static irqreturn_t ibmvfc_interrupt(int irq, void *dev_instance) * Returns: * Nothing **/ -static void ibmvfc_tasklet(void *data) +static void ibmvfc_tasklet(struct tasklet_struct *t) { - struct ibmvfc_host *vhost = data; + struct ibmvfc_host *vhost = from_tasklet(vhost, t, tasklet); struct vio_dev *vdev = to_vio_dev(vhost->dev); struct ibmvfc_crq *crq; struct ibmvfc_async_crq *async; @@ -4676,7 +4676,7 @@ static int ibmvfc_init_crq(struct ibmvfc_host *vhost) retrc = 0; - tasklet_init(&vhost->tasklet, (void *)ibmvfc_tasklet, (unsigned long)vhost); + tasklet_setup(&vhost->tasklet, (void *)ibmvfc_tasklet); if ((rc = request_irq(vdev->irq, ibmvfc_interrupt, 0, IBMVFC_NAME, vhost))) { dev_err(dev, "Couldn't register irq 0x%x. rc=%d\n", vdev->irq, rc); diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index b1f3017b6547..46b818daa957 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -208,9 +208,10 @@ static int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, * ibmvscsi_task: - Process srps asynchronously * @data: ibmvscsi_host_data of host */ -static void ibmvscsi_task(void *data) +static void ibmvscsi_task(struct tasklet_struct *t) { - struct ibmvscsi_host_data *hostdata = (struct ibmvscsi_host_data *)data; + struct ibmvscsi_host_data *hostdata = from_tasklet(hostdata, t, + srp_task); struct vio_dev *vdev = to_vio_dev(hostdata->dev); struct viosrp_crq *crq; int done = 0; @@ -366,8 +367,7 @@ static int ibmvscsi_init_crq_queue(struct crq_queue *queue, queue->cur = 0; spin_lock_init(&queue->lock); - tasklet_init(&hostdata->srp_task, (void *)ibmvscsi_task, -(unsigned long)hostdata); + tasklet_setup(&hostdata->srp_task, ibmvscsi_task); if (request_irq(vdev->irq, ibmvscsi_handle_event, diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c index d9e94e81da01..e62fd6c67001 100644 --- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c +++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c @@ -3328,9 +3328,9 @@ static int ibmvscsis_rdma(struct ibmvscsis_cmd *cmd, struct scatterlist *sg, * * Note: this is an edge triggered interrupt. It can not be shared. */ -static void ibmvscsis_handle_crq(unsigned long data) +static void ibmvscsis_handle_crq(struct tasklet_struct *t) { - struct scsi_info *vscsi = (struct scsi_info *)data; + struct scsi_info *vscsi = from_tasklet(vscsi, t, work_task); struct viosrp_crq *crq; long rc; bool ack = true; @@ -3541,8 +3541,7 @@ static int ibmvscsis_probe(struct vio_dev *vdev, dev_dbg(&vscsi->dev, "probe hrc %ld, client partition num %d\n", hrc, vscsi->client_data.partition_number); - tasklet_init(&vscsi->work_task, ibmvscsis_handle_crq, -(unsigned long)vscsi); + tasklet_setup(&vscsi->work_task, ibmvscsis_handle_crq); init_completion(&vscsi->wait_idle); init_completion(&vscsi->unconfig); -- 2.17.1
[PATCH 2/8] scsi: esas2r: convert tasklets to use new tasklet_setup() API
From: Allen Pais In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/scsi/esas2r/esas2r.h | 2 +- drivers/scsi/esas2r/esas2r_init.c | 4 +--- drivers/scsi/esas2r/esas2r_main.c | 4 ++-- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/esas2r/esas2r.h b/drivers/scsi/esas2r/esas2r.h index e30d2f1f5368..b99434e24868 100644 --- a/drivers/scsi/esas2r/esas2r.h +++ b/drivers/scsi/esas2r/esas2r.h @@ -992,7 +992,7 @@ int esas2r_write_vda(struct esas2r_adapter *a, const char *buf, long off, int esas2r_read_fs(struct esas2r_adapter *a, char *buf, long off, int count); int esas2r_write_fs(struct esas2r_adapter *a, const char *buf, long off, int count); -void esas2r_adapter_tasklet(unsigned long context); +void esas2r_adapter_tasklet(struct tasklet_struct *t); irqreturn_t esas2r_interrupt(int irq, void *dev_id); irqreturn_t esas2r_msi_interrupt(int irq, void *dev_id); void esas2r_kickoff_timer(struct esas2r_adapter *a); diff --git a/drivers/scsi/esas2r/esas2r_init.c b/drivers/scsi/esas2r/esas2r_init.c index eb7d139ffc00..55387c14fb8d 100644 --- a/drivers/scsi/esas2r/esas2r_init.c +++ b/drivers/scsi/esas2r/esas2r_init.c @@ -401,9 +401,7 @@ int esas2r_init_adapter(struct Scsi_Host *host, struct pci_dev *pcid, return 0; } - tasklet_init(&a->tasklet, -esas2r_adapter_tasklet, -(unsigned long)a); + tasklet_setup(&a->tasklet, esas2r_adapter_tasklet); /* * Disable chip interrupts to prevent spurious interrupts diff --git a/drivers/scsi/esas2r/esas2r_main.c b/drivers/scsi/esas2r/esas2r_main.c index 7b49e2e9fcde..7ffa9406ab4d 100644 --- a/drivers/scsi/esas2r/esas2r_main.c +++ b/drivers/scsi/esas2r/esas2r_main.c @@ -1546,9 +1546,9 @@ void esas2r_complete_request_cb(struct esas2r_adapter *a, } /* Run tasklet to handle stuff outside of interrupt context. */ -void esas2r_adapter_tasklet(unsigned long context) +void esas2r_adapter_tasklet(struct tasklet_struct *t) { - struct esas2r_adapter *a = (struct esas2r_adapter *)context; + struct esas2r_adapter *a = from_tasklet(a, t, tasklet); if (unlikely(test_bit(AF2_TIMER_TICK, &a->flags2))) { clear_bit(AF2_TIMER_TICK, &a->flags2); -- 2.17.1
[PATCH 0/8] scsi: convert tasklets to use new tasklet_setup()
From: Allen Pais Commit 12cc923f1ccc ("tasklet: Introduce new initialization API")' introduced a new tasklet initialization API. This series converts all the scsi drivers to use the new tasklet_setup() API Allen Pais (8): scsi: aic94xx: convert tasklets to use new tasklet_setup() API scsi: esas2r: convert tasklets to use new tasklet_setup() API scsi: ibmvscsi: convert tasklets to use new tasklet_setup() API scsi: isci: convert tasklets to use new tasklet_setup() API scsi: megaraid: convert tasklets to use new tasklet_setup() API scsi: mvsas: convert tasklets to use new tasklet_setup() API scsi: pm8001: convert tasklets to use new tasklet_setup() API scsi: pmcraid: convert tasklets to use new tasklet_setup() API drivers/scsi/aic94xx/aic94xx_hwi.c | 9 ++-- drivers/scsi/esas2r/esas2r.h| 2 +- drivers/scsi/esas2r/esas2r_init.c | 4 +- drivers/scsi/esas2r/esas2r_main.c | 4 +- drivers/scsi/ibmvscsi/ibmvfc.c | 6 +-- drivers/scsi/ibmvscsi/ibmvscsi.c| 8 +-- drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c| 7 ++- drivers/scsi/isci/host.c| 4 +- drivers/scsi/isci/host.h| 2 +- drivers/scsi/isci/init.c| 3 +- drivers/scsi/megaraid/megaraid_mbox.c | 9 ++-- drivers/scsi/megaraid/megaraid_sas.h| 2 +- drivers/scsi/megaraid/megaraid_sas_base.c | 16 +++--- drivers/scsi/megaraid/megaraid_sas_fusion.c | 14 +++--- drivers/scsi/mvsas/mv_init.c| 8 +-- drivers/scsi/pm8001/pm8001_init.c | 55 - drivers/scsi/pm8001/pm8001_sas.h| 6 ++- drivers/scsi/pmcraid.c | 29 +-- drivers/scsi/pmcraid.h | 9 +++- 19 files changed, 104 insertions(+), 93 deletions(-) -- 2.17.1
[PATCH 1/8] scsi: aic94xx: convert tasklets to use new tasklet_setup() API
From: Allen Pais In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/scsi/aic94xx/aic94xx_hwi.c | 9 - 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.c b/drivers/scsi/aic94xx/aic94xx_hwi.c index 9256ab7b2522..1e4d32246cb9 100644 --- a/drivers/scsi/aic94xx/aic94xx_hwi.c +++ b/drivers/scsi/aic94xx/aic94xx_hwi.c @@ -248,7 +248,7 @@ static void asd_get_max_scb_ddb(struct asd_ha_struct *asd_ha) /* -- Done List initialization -- */ -static void asd_dl_tasklet_handler(unsigned long); +static void asd_dl_tasklet_handler(struct tasklet_struct *t); static int asd_init_dl(struct asd_ha_struct *asd_ha) { @@ -261,8 +261,7 @@ static int asd_init_dl(struct asd_ha_struct *asd_ha) asd_ha->seq.dl = asd_ha->seq.actual_dl->vaddr; asd_ha->seq.dl_toggle = ASD_DEF_DL_TOGGLE; asd_ha->seq.dl_next = 0; - tasklet_init(&asd_ha->seq.dl_tasklet, asd_dl_tasklet_handler, -(unsigned long) asd_ha); + tasklet_setup(&asd_ha->seq.dl_tasklet, asd_dl_tasklet_handler); return 0; } @@ -711,9 +710,9 @@ static void asd_chip_reset(struct asd_ha_struct *asd_ha) /* -- Done List Routines -- */ -static void asd_dl_tasklet_handler(unsigned long data) +static void asd_dl_tasklet_handler(struct tasklet_struct *t) { - struct asd_ha_struct *asd_ha = (struct asd_ha_struct *) data; + struct asd_ha_struct *asd_ha = from_tasklet(asd_ha, t, seq.dl_tasklet); struct asd_seq_data *seq = &asd_ha->seq; unsigned long flags; -- 2.17.1
[PATCH 20/20] ethernet: smsc: convert tasklets to use new tasklet_setup() API
In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/net/ethernet/smsc/smc91x.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c index 1c4fea9c3ec4..7e585aa3031c 100644 --- a/drivers/net/ethernet/smsc/smc91x.c +++ b/drivers/net/ethernet/smsc/smc91x.c @@ -535,10 +535,10 @@ static inline void smc_rcv(struct net_device *dev) /* * This is called to actually send a packet to the chip. */ -static void smc_hardware_send_pkt(unsigned long data) +static void smc_hardware_send_pkt(struct tasklet_struct *t) { - struct net_device *dev = (struct net_device *)data; - struct smc_local *lp = netdev_priv(dev); + struct smc_local *lp = from_tasklet(lp, t, tx_task); + struct net_device *dev = lp->dev; void __iomem *ioaddr = lp->base; struct sk_buff *skb; unsigned int packet_no, len; @@ -688,7 +688,7 @@ smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) * Allocation succeeded: push packet to the chip's own memory * immediately. */ - smc_hardware_send_pkt((unsigned long)dev); + smc_hardware_send_pkt(&lp->tx_task); } return NETDEV_TX_OK; @@ -1965,7 +1965,7 @@ static int smc_probe(struct net_device *dev, void __iomem *ioaddr, dev->netdev_ops = &smc_netdev_ops; dev->ethtool_ops = &smc_ethtool_ops; - tasklet_init(&lp->tx_task, smc_hardware_send_pkt, (unsigned long)dev); + tasklet_setup(&lp->tx_task, smc_hardware_send_pkt); INIT_WORK(&lp->phy_configure, smc_phy_configure); lp->dev = dev; lp->mii.phy_id_mask = 0x1f; -- 2.17.1
[PATCH 19/20] ethernet: silan: convert tasklets to use new tasklet_setup() API
In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/net/ethernet/silan/sc92031.c | 11 ++- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/silan/sc92031.c b/drivers/net/ethernet/silan/sc92031.c index f94078f8ebe5..8d56eca5be17 100644 --- a/drivers/net/ethernet/silan/sc92031.c +++ b/drivers/net/ethernet/silan/sc92031.c @@ -829,10 +829,11 @@ static void _sc92031_link_tasklet(struct net_device *dev) } } -static void sc92031_tasklet(unsigned long data) +static void sc92031_tasklet(struct tasklet_struct *t) { - struct net_device *dev = (struct net_device *)data; - struct sc92031_priv *priv = netdev_priv(dev); + struct sc92031_priv *priv = from_tasklet(priv, t, tasklet); + struct net_device *dev = (struct net_device *)((char *)priv - + ALIGN(sizeof(struct net_device), NETDEV_ALIGN)); void __iomem *port_base = priv->port_base; u32 intr_status, intr_mask; @@ -1108,7 +1109,7 @@ static void sc92031_poll_controller(struct net_device *dev) disable_irq(irq); if (sc92031_interrupt(irq, dev) != IRQ_NONE) - sc92031_tasklet((unsigned long)dev); + sc92031_tasklet(&priv->tasklet); enable_irq(irq); } #endif @@ -1446,7 +1447,7 @@ static int sc92031_probe(struct pci_dev *pdev, const struct pci_device_id *id) spin_lock_init(&priv->lock); priv->port_base = port_base; priv->pdev = pdev; - tasklet_init(&priv->tasklet, sc92031_tasklet, (unsigned long)dev); + tasklet_setup(&priv->tasklet, sc92031_tasklet); /* Fudge tasklet count so the call to sc92031_enable_interrupts at * sc92031_open will work correctly */ tasklet_disable_nosync(&priv->tasklet); -- 2.17.1
[PATCH 18/20] ethernet: qlogic: convert tasklets to use new tasklet_setup() API
In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/net/ethernet/qlogic/qed/qed.h | 2 +- drivers/net/ethernet/qlogic/qed/qed_int.c | 27 +++--- drivers/net/ethernet/qlogic/qed/qed_int.h | 2 +- drivers/net/ethernet/qlogic/qed/qed_main.c | 14 +-- 4 files changed, 12 insertions(+), 33 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h index b2a7b53ee760..22bc4ec7859a 100644 --- a/drivers/net/ethernet/qlogic/qed/qed.h +++ b/drivers/net/ethernet/qlogic/qed/qed.h @@ -572,7 +572,7 @@ struct qed_hwfn { struct qed_consq*p_consq; /* Slow-Path definitions */ - struct tasklet_struct *sp_dpc; + struct tasklet_struct sp_dpc; boolb_sp_dpc_enabled; struct qed_ptt *p_main_ptt; diff --git a/drivers/net/ethernet/qlogic/qed/qed_int.c b/drivers/net/ethernet/qlogic/qed/qed_int.c index f8c5a864812d..578935f643b8 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_int.c +++ b/drivers/net/ethernet/qlogic/qed/qed_int.c @@ -1216,9 +1216,9 @@ static void qed_sb_ack_attn(struct qed_hwfn *p_hwfn, barrier(); } -void qed_int_sp_dpc(unsigned long hwfn_cookie) +void qed_int_sp_dpc(struct tasklet_struct *t) { - struct qed_hwfn *p_hwfn = (struct qed_hwfn *)hwfn_cookie; + struct qed_hwfn *p_hwfn = from_tasklet(p_hwfn, t, sp_dpc); struct qed_pi_info *pi_info = NULL; struct qed_sb_attn_info *sb_attn; struct qed_sb_info *sb_info; @@ -2285,34 +2285,14 @@ u64 qed_int_igu_read_sisr_reg(struct qed_hwfn *p_hwfn) static void qed_int_sp_dpc_setup(struct qed_hwfn *p_hwfn) { - tasklet_init(p_hwfn->sp_dpc, -qed_int_sp_dpc, (unsigned long)p_hwfn); + tasklet_setup(&p_hwfn->sp_dpc, qed_int_sp_dpc); p_hwfn->b_sp_dpc_enabled = true; } -static int qed_int_sp_dpc_alloc(struct qed_hwfn *p_hwfn) -{ - p_hwfn->sp_dpc = kmalloc(sizeof(*p_hwfn->sp_dpc), GFP_KERNEL); - if (!p_hwfn->sp_dpc) - return -ENOMEM; - - return 0; -} - -static void qed_int_sp_dpc_free(struct qed_hwfn *p_hwfn) -{ - kfree(p_hwfn->sp_dpc); - p_hwfn->sp_dpc = NULL; -} - int qed_int_alloc(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) { int rc = 0; - rc = qed_int_sp_dpc_alloc(p_hwfn); - if (rc) - return rc; - rc = qed_int_sp_sb_alloc(p_hwfn, p_ptt); if (rc) return rc; @@ -2326,7 +2306,6 @@ void qed_int_free(struct qed_hwfn *p_hwfn) { qed_int_sp_sb_free(p_hwfn); qed_int_sb_attn_free(p_hwfn); - qed_int_sp_dpc_free(p_hwfn); } void qed_int_setup(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) diff --git a/drivers/net/ethernet/qlogic/qed/qed_int.h b/drivers/net/ethernet/qlogic/qed/qed_int.h index 86809d7bc2de..c5550e96bbe1 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_int.h +++ b/drivers/net/ethernet/qlogic/qed/qed_int.h @@ -140,7 +140,7 @@ int qed_int_sb_release(struct qed_hwfn *p_hwfn, * @param p_hwfn - pointer to hwfn * */ -void qed_int_sp_dpc(unsigned long hwfn_cookie); +void qed_int_sp_dpc(struct tasklet_struct *t); /** * @brief qed_int_get_num_sbs - get the number of status diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c index 2558cb680db3..4c4dd4e88fb1 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_main.c +++ b/drivers/net/ethernet/qlogic/qed/qed_main.c @@ -841,7 +841,7 @@ static irqreturn_t qed_single_int(int irq, void *dev_instance) /* Slowpath interrupt */ if (unlikely(status & 0x1)) { - tasklet_schedule(hwfn->sp_dpc); + tasklet_schedule(&hwfn->sp_dpc); status &= ~0x1; rc = IRQ_HANDLED; } @@ -887,7 +887,7 @@ int qed_slowpath_irq_req(struct qed_hwfn *hwfn) id, cdev->pdev->bus->number, PCI_SLOT(cdev->pdev->devfn), hwfn->abs_pf_id); rc = request_irq(cdev->int_params.msix_table[id].vector, -qed_msix_sp_int, 0, hwfn->name, hwfn->sp_dpc); +qed_msix_sp_int, 0, hwfn->name, &hwfn->sp_dpc); } else { unsigned long flags = 0; @@ -919,8 +919,8 @@ static void qed_slowpath_tasklet_flush(struct qed_hwfn *p_hwfn) * enable function makes this sequence a flush-like operation. */ if (p_hwfn->b_sp_dpc_enabled) { - tasklet_disable(p_hwfn->sp_dpc); -
[PATCH 17/20] ethernet: ni: convert tasklets to use new tasklet_setup() API
In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/net/ethernet/ni/nixge.c | 7 +++ 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/ni/nixge.c b/drivers/net/ethernet/ni/nixge.c index 4075f5e59955..a6861df9904f 100644 --- a/drivers/net/ethernet/ni/nixge.c +++ b/drivers/net/ethernet/ni/nixge.c @@ -787,9 +787,9 @@ static irqreturn_t nixge_rx_irq(int irq, void *_ndev) return IRQ_HANDLED; } -static void nixge_dma_err_handler(unsigned long data) +static void nixge_dma_err_handler(struct tasklet_struct *t) { - struct nixge_priv *lp = (struct nixge_priv *)data; + struct nixge_priv *lp = from_tasklet(lp, t, dma_err_tasklet); struct nixge_hw_dma_bd *cur_p; struct nixge_tx_skb *tx_skb; u32 cr, i; @@ -879,8 +879,7 @@ static int nixge_open(struct net_device *ndev) phy_start(phy); /* Enable tasklets for Axi DMA error handling */ - tasklet_init(&priv->dma_err_tasklet, nixge_dma_err_handler, -(unsigned long)priv); + tasklet_setup(&priv->dma_err_tasklet, nixge_dma_err_handler); napi_enable(&priv->napi); -- 2.17.1
[PATCH 16/20] ethernet: netronome: convert tasklets to use new tasklet_setup() API
In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 7 +++ 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 39ee23e8c0bf..1dcd24d899f5 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -2287,9 +2287,9 @@ static bool nfp_ctrl_rx(struct nfp_net_r_vector *r_vec) return budget; } -static void nfp_ctrl_poll(unsigned long arg) +static void nfp_ctrl_poll(struct tasklet_struct *t) { - struct nfp_net_r_vector *r_vec = (void *)arg; + struct nfp_net_r_vector *r_vec = from_tasklet(r_vec, t, tasklet); spin_lock(&r_vec->lock); nfp_net_tx_complete(r_vec->tx_ring, 0); @@ -2337,8 +2337,7 @@ static void nfp_net_vecs_init(struct nfp_net *nn) __skb_queue_head_init(&r_vec->queue); spin_lock_init(&r_vec->lock); - tasklet_init(&r_vec->tasklet, nfp_ctrl_poll, -(unsigned long)r_vec); + tasklet_setup(&r_vec->tasklet, nfp_ctrl_poll); tasklet_disable(&r_vec->tasklet); } -- 2.17.1
[PATCH 15/20] ethernet: natsemi: convert tasklets to use new tasklet_setup() API
In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/net/ethernet/natsemi/ns83820.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/natsemi/ns83820.c b/drivers/net/ethernet/natsemi/ns83820.c index 8e24c7acf79b..9157c1bffc79 100644 --- a/drivers/net/ethernet/natsemi/ns83820.c +++ b/drivers/net/ethernet/natsemi/ns83820.c @@ -923,10 +923,10 @@ static void rx_irq(struct net_device *ndev) spin_unlock_irqrestore(&info->lock, flags); } -static void rx_action(unsigned long _dev) +static void rx_action(struct tasklet_struct *t) { - struct net_device *ndev = (void *)_dev; - struct ns83820 *dev = PRIV(ndev); + struct ns83820 *dev = from_tasklet(dev, t, rx_tasklet); + struct net_device *ndev = dev->ndev; rx_irq(ndev); writel(ihr, dev->base + IHR); @@ -1927,7 +1927,7 @@ static int ns83820_init_one(struct pci_dev *pci_dev, SET_NETDEV_DEV(ndev, &pci_dev->dev); INIT_WORK(&dev->tq_refill, queue_refill); - tasklet_init(&dev->rx_tasklet, rx_action, (unsigned long)ndev); + tasklet_setup(&dev->rx_tasklet, rx_action); err = pci_enable_device(pci_dev); if (err) { -- 2.17.1
[PATCH 14/20] ethernet: micrel: convert tasklets to use new tasklet_setup() API
In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/net/ethernet/micrel/ks8842.c | 19 ++- drivers/net/ethernet/micrel/ksz884x.c | 14 ++ 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/drivers/net/ethernet/micrel/ks8842.c b/drivers/net/ethernet/micrel/ks8842.c index f3f6dfe3eddc..8fd32f98c494 100644 --- a/drivers/net/ethernet/micrel/ks8842.c +++ b/drivers/net/ethernet/micrel/ks8842.c @@ -587,10 +587,11 @@ static int __ks8842_start_new_rx_dma(struct net_device *netdev) return err; } -static void ks8842_rx_frame_dma_tasklet(unsigned long arg) +static void ks8842_rx_frame_dma_tasklet(struct tasklet_struct *t) { - struct net_device *netdev = (struct net_device *)arg; - struct ks8842_adapter *adapter = netdev_priv(netdev); + struct ks8842_adapter *adapter = from_tasklet(adapter, t, dma_rx.tasklet); + struct net_device *netdev = (struct net_device *)((char *)adapter - + ALIGN(sizeof(struct net_device), NETDEV_ALIGN)); struct ks8842_rx_dma_ctl *ctl = &adapter->dma_rx; struct sk_buff *skb = ctl->skb; dma_addr_t addr = sg_dma_address(&ctl->sg); @@ -720,10 +721,11 @@ static void ks8842_handle_rx_overrun(struct net_device *netdev, netdev->stats.rx_fifo_errors++; } -static void ks8842_tasklet(unsigned long arg) +static void ks8842_tasklet(struct tasklet_struct *t) { - struct net_device *netdev = (struct net_device *)arg; - struct ks8842_adapter *adapter = netdev_priv(netdev); + struct ks8842_adapter *adapter = from_tasklet(adapter, t, tasklet); + struct net_device *netdev = (struct net_device *)((char *)adapter - + ALIGN(sizeof(struct net_device), NETDEV_ALIGN)); u16 isr; unsigned long flags; u16 entry_bank; @@ -953,8 +955,7 @@ static int ks8842_alloc_dma_bufs(struct net_device *netdev) goto err; } - tasklet_init(&rx_ctl->tasklet, ks8842_rx_frame_dma_tasklet, - (unsigned long)netdev); + tasklet_setup(&rx_ctl->tasklet, ks8842_rx_frame_dma_tasklet); return 0; err: @@ -1173,7 +1174,7 @@ static int ks8842_probe(struct platform_device *pdev) adapter->dma_tx.channel = -1; } - tasklet_init(&adapter->tasklet, ks8842_tasklet, (unsigned long)netdev); + tasklet_setup(&adapter->tasklet, ks8842_tasklet); spin_lock_init(&adapter->lock); netdev->netdev_ops = &ks8842_netdev_ops; diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c index bb646b65cc95..5130507bbf54 100644 --- a/drivers/net/ethernet/micrel/ksz884x.c +++ b/drivers/net/ethernet/micrel/ksz884x.c @@ -5159,9 +5159,9 @@ static int dev_rcv_special(struct dev_info *hw_priv) return received; } -static void rx_proc_task(unsigned long data) +static void rx_proc_task(struct tasklet_struct *t) { - struct dev_info *hw_priv = (struct dev_info *) data; + struct dev_info *hw_priv = from_tasklet(hw_priv, t, rx_tasklet); struct ksz_hw *hw = &hw_priv->hw; if (!hw->enabled) @@ -5181,9 +5181,9 @@ static void rx_proc_task(unsigned long data) } } -static void tx_proc_task(unsigned long data) +static void tx_proc_task(struct tasklet_struct *t) { - struct dev_info *hw_priv = (struct dev_info *) data; + struct dev_info *hw_priv = from_tasklet(hw_priv, t, tx_tasklet); struct ksz_hw *hw = &hw_priv->hw; hw_ack_intr(hw, KS884X_INT_TX_MASK); @@ -5436,10 +5436,8 @@ static int prepare_hardware(struct net_device *dev) rc = request_irq(dev->irq, netdev_intr, IRQF_SHARED, dev->name, dev); if (rc) return rc; - tasklet_init(&hw_priv->rx_tasklet, rx_proc_task, -(unsigned long) hw_priv); - tasklet_init(&hw_priv->tx_tasklet, tx_proc_task, -(unsigned long) hw_priv); + tasklet_setup(&hw_priv->rx_tasklet, rx_proc_task); + tasklet_setup(&hw_priv->tx_tasklet, tx_proc_task); hw->promiscuous = 0; hw->all_multi = 0; -- 2.17.1
[PATCH 13/20] ethernet: mellanox: convert tasklets to use new tasklet_setup() API
In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/net/ethernet/mellanox/mlx4/cq.c | 4 ++-- drivers/net/ethernet/mellanox/mlx4/eq.c | 3 +-- drivers/net/ethernet/mellanox/mlx4/mlx4.h | 2 +- drivers/net/ethernet/mellanox/mlx5/core/cq.c| 4 ++-- drivers/net/ethernet/mellanox/mlx5/core/eq.c| 3 +-- drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c | 7 +++ drivers/net/ethernet/mellanox/mlx5/core/lib/eq.h| 2 +- drivers/net/ethernet/mellanox/mlxsw/pci.c | 12 ++-- 8 files changed, 17 insertions(+), 20 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/cq.c b/drivers/net/ethernet/mellanox/mlx4/cq.c index 65f8a4b6ed0c..3b8576b9c2f9 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cq.c +++ b/drivers/net/ethernet/mellanox/mlx4/cq.c @@ -55,11 +55,11 @@ #define TASKLET_MAX_TIME 2 #define TASKLET_MAX_TIME_JIFFIES msecs_to_jiffies(TASKLET_MAX_TIME) -void mlx4_cq_tasklet_cb(unsigned long data) +void mlx4_cq_tasklet_cb(struct tasklet_struct *t) { unsigned long flags; unsigned long end = jiffies + TASKLET_MAX_TIME_JIFFIES; - struct mlx4_eq_tasklet *ctx = (struct mlx4_eq_tasklet *)data; + struct mlx4_eq_tasklet *ctx = from_tasklet(ctx, t, task); struct mlx4_cq *mcq, *temp; spin_lock_irqsave(&ctx->lock, flags); diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c index ae305c2e9225..9e48509ed3b2 100644 --- a/drivers/net/ethernet/mellanox/mlx4/eq.c +++ b/drivers/net/ethernet/mellanox/mlx4/eq.c @@ -1057,8 +1057,7 @@ static int mlx4_create_eq(struct mlx4_dev *dev, int nent, INIT_LIST_HEAD(&eq->tasklet_ctx.list); INIT_LIST_HEAD(&eq->tasklet_ctx.process_list); spin_lock_init(&eq->tasklet_ctx.lock); - tasklet_init(&eq->tasklet_ctx.task, mlx4_cq_tasklet_cb, -(unsigned long)&eq->tasklet_ctx); + tasklet_setup(&eq->tasklet_ctx.task, mlx4_cq_tasklet_cb); return err; diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index 527b52e48276..64bed7ac3836 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h @@ -1217,7 +1217,7 @@ void mlx4_cmd_use_polling(struct mlx4_dev *dev); int mlx4_comm_cmd(struct mlx4_dev *dev, u8 cmd, u16 param, u16 op, unsigned long timeout); -void mlx4_cq_tasklet_cb(unsigned long data); +void mlx4_cq_tasklet_cb(struct tasklet_struct *t); void mlx4_cq_completion(struct mlx4_dev *dev, u32 cqn); void mlx4_cq_event(struct mlx4_dev *dev, u32 cqn, int event_type); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cq.c b/drivers/net/ethernet/mellanox/mlx5/core/cq.c index 8379b24cb838..df3e4938ecdd 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cq.c @@ -42,11 +42,11 @@ #define TASKLET_MAX_TIME 2 #define TASKLET_MAX_TIME_JIFFIES msecs_to_jiffies(TASKLET_MAX_TIME) -void mlx5_cq_tasklet_cb(unsigned long data) +void mlx5_cq_tasklet_cb(struct tasklet_struct *t) { unsigned long flags; unsigned long end = jiffies + TASKLET_MAX_TIME_JIFFIES; - struct mlx5_eq_tasklet *ctx = (struct mlx5_eq_tasklet *)data; + struct mlx5_eq_tasklet *ctx = from_tasklet(ctx, t, task); struct mlx5_core_cq *mcq; struct mlx5_core_cq *temp; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c index 31ef9f8420c8..ec38405d467f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c @@ -788,8 +788,7 @@ static int create_comp_eqs(struct mlx5_core_dev *dev) INIT_LIST_HEAD(&eq->tasklet_ctx.list); INIT_LIST_HEAD(&eq->tasklet_ctx.process_list); spin_lock_init(&eq->tasklet_ctx.lock); - tasklet_init(&eq->tasklet_ctx.task, mlx5_cq_tasklet_cb, -(unsigned long)&eq->tasklet_ctx); + tasklet_setup(&eq->tasklet_ctx.task, mlx5_cq_tasklet_cb); eq->irq_nb.notifier_call = mlx5_eq_comp_int; param = (struct mlx5_eq_param) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c b/drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c index 831d2c39e153..9f6d97eae0ae 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c @@ -388,9 +388,9 @@ static inline void mlx5_fpga_conn_cqes(struct mlx5_fpga_conn *conn, mlx5_fpga_conn_arm_cq(conn); } -static vo
[PATCH 12/20] ethernet: marvell: convert tasklets to use new tasklet_setup() API
In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/net/ethernet/marvell/skge.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c index b792f6306a64..55fe901d3562 100644 --- a/drivers/net/ethernet/marvell/skge.c +++ b/drivers/net/ethernet/marvell/skge.c @@ -3338,9 +3338,9 @@ static void skge_error_irq(struct skge_hw *hw) * because accessing phy registers requires spin wait which might * cause excess interrupt latency. */ -static void skge_extirq(unsigned long arg) +static void skge_extirq(struct tasklet_struct *t) { - struct skge_hw *hw = (struct skge_hw *) arg; + struct skge_hw *hw = from_tasklet(hw, t, phy_task); int port; for (port = 0; port < hw->ports; port++) { @@ -3927,7 +3927,7 @@ static int skge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) hw->pdev = pdev; spin_lock_init(&hw->hw_lock); spin_lock_init(&hw->phy_lock); - tasklet_init(&hw->phy_task, skge_extirq, (unsigned long) hw); + tasklet_setup(&hw->phy_task, skge_extirq); hw->regs = ioremap(pci_resource_start(pdev, 0), 0x4000); if (!hw->regs) { -- 2.17.1
[PATCH 11/20] ethernet: jme: convert tasklets to use new tasklet_setup() API
In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/net/ethernet/jme.c | 40 +++--- 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c index ddc757680089..e9efe074edc1 100644 --- a/drivers/net/ethernet/jme.c +++ b/drivers/net/ethernet/jme.c @@ -1187,9 +1187,9 @@ jme_shutdown_nic(struct jme_adapter *jme) } static void -jme_pcc_tasklet(unsigned long arg) +jme_pcc_tasklet(struct tasklet_struct *t) { - struct jme_adapter *jme = (struct jme_adapter *)arg; + struct jme_adapter *jme = from_tasklet(jme, t, pcc_task); struct net_device *netdev = jme->dev; if (unlikely(test_bit(JME_FLAG_SHUTDOWN, &jme->flags))) { @@ -1265,10 +1265,9 @@ jme_stop_shutdown_timer(struct jme_adapter *jme) jwrite32f(jme, JME_APMC, apmc); } -static void -jme_link_change_tasklet(unsigned long arg) +static void jme_link_change_tasklet(struct tasklet_struct *t) { - struct jme_adapter *jme = (struct jme_adapter *)arg; + struct jme_adapter *jme = from_tasklet(jme, t, linkch_task); struct net_device *netdev = jme->dev; int rc; @@ -1345,9 +1344,9 @@ jme_link_change_tasklet(unsigned long arg) } static void -jme_rx_clean_tasklet(unsigned long arg) +jme_rx_clean_tasklet(struct tasklet_struct *t) { - struct jme_adapter *jme = (struct jme_adapter *)arg; + struct jme_adapter *jme = from_tasklet(jme, t, rxclean_task); struct dynpcc_info *dpi = &(jme->dpi); jme_process_receive(jme, jme->rx_ring_size); @@ -1380,9 +1379,9 @@ jme_poll(JME_NAPI_HOLDER(holder), JME_NAPI_WEIGHT(budget)) } static void -jme_rx_empty_tasklet(unsigned long arg) +jme_rx_empty_tasklet(struct tasklet_struct *t) { - struct jme_adapter *jme = (struct jme_adapter *)arg; + struct jme_adapter *jme = from_tasklet(jme, t, rxempty_task); if (unlikely(atomic_read(&jme->link_changing) != 1)) return; @@ -1392,7 +1391,7 @@ jme_rx_empty_tasklet(unsigned long arg) netif_info(jme, rx_status, jme->dev, "RX Queue Full!\n"); - jme_rx_clean_tasklet(arg); + jme_rx_clean_tasklet(&jme->rxclean_task); while (atomic_read(&jme->rx_empty) > 0) { atomic_dec(&jme->rx_empty); @@ -1416,10 +1415,9 @@ jme_wake_queue_if_stopped(struct jme_adapter *jme) } -static void -jme_tx_clean_tasklet(unsigned long arg) +static void jme_tx_clean_tasklet(struct tasklet_struct *t) { - struct jme_adapter *jme = (struct jme_adapter *)arg; + struct jme_adapter *jme = from_tasklet(jme, t, txclean_task); struct jme_ring *txring = &(jme->txring[0]); struct txdesc *txdesc = txring->desc; struct jme_buffer_info *txbi = txring->bufinf, *ctxbi, *ttxbi; @@ -1834,14 +1832,10 @@ jme_open(struct net_device *netdev) jme_clear_pm_disable_wol(jme); JME_NAPI_ENABLE(jme); - tasklet_init(&jme->linkch_task, jme_link_change_tasklet, -(unsigned long) jme); - tasklet_init(&jme->txclean_task, jme_tx_clean_tasklet, -(unsigned long) jme); - tasklet_init(&jme->rxclean_task, jme_rx_clean_tasklet, -(unsigned long) jme); - tasklet_init(&jme->rxempty_task, jme_rx_empty_tasklet, -(unsigned long) jme); + tasklet_setup(&jme->linkch_task, jme_link_change_tasklet); + tasklet_setup(&jme->txclean_task, jme_tx_clean_tasklet); + tasklet_setup(&jme->rxclean_task, jme_rx_clean_tasklet); + tasklet_setup(&jme->rxempty_task, jme_rx_empty_tasklet); rc = jme_request_irq(jme); if (rc) @@ -3040,9 +3034,7 @@ jme_init_one(struct pci_dev *pdev, atomic_set(&jme->tx_cleaning, 1); atomic_set(&jme->rx_empty, 1); - tasklet_init(&jme->pcc_task, -jme_pcc_tasklet, -(unsigned long) jme); + tasklet_setup(&jme->pcc_task, jme_pcc_tasklet); jme->dpi.cur = PCC_P1; jme->reg_ghc = 0; -- 2.17.1
[PATCH 10/20] ethernet: ibmvnic: convert tasklets to use new tasklet_setup() API
In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/net/ethernet/ibm/ibmvnic.c | 7 +++ 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 5afb3c9c52d2..7c565e167521 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -4797,9 +4797,9 @@ static irqreturn_t ibmvnic_interrupt(int irq, void *instance) return IRQ_HANDLED; } -static void ibmvnic_tasklet(void *data) +static void ibmvnic_tasklet(struct tasklet_struct *t) { - struct ibmvnic_adapter *adapter = data; + struct ibmvnic_adapter *adapter = from_tasklet(adapter, t, tasklet); struct ibmvnic_crq_queue *queue = &adapter->crq; union ibmvnic_crq *crq; unsigned long flags; @@ -4934,8 +4934,7 @@ static int init_crq_queue(struct ibmvnic_adapter *adapter) retrc = 0; - tasklet_init(&adapter->tasklet, (void *)ibmvnic_tasklet, -(unsigned long)adapter); + tasklet_setup(&adapter->tasklet, (void *)ibmvnic_tasklet); netdev_dbg(adapter->netdev, "registering irq 0x%x\n", vdev->irq); snprintf(crq->name, sizeof(crq->name), "ibmvnic-%x", -- 2.17.1
[PATCH 09/20] ethernet: ehea: convert tasklets to use new tasklet_setup() API
In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/net/ethernet/ibm/ehea/ehea_main.c | 7 +++ 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c index 0273fb7a9d01..f3d104fec7e9 100644 --- a/drivers/net/ethernet/ibm/ehea/ehea_main.c +++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c @@ -1212,9 +1212,9 @@ static void ehea_parse_eqe(struct ehea_adapter *adapter, u64 eqe) } } -static void ehea_neq_tasklet(unsigned long data) +static void ehea_neq_tasklet(struct tasklet_struct *t) { - struct ehea_adapter *adapter = (struct ehea_adapter *)data; + struct ehea_adapter *adapter = from_tasklet(adapter, t, neq_tasklet); struct ehea_eqe *eqe; u64 event_mask; @@ -3417,8 +3417,7 @@ static int ehea_probe_adapter(struct platform_device *dev) goto out_free_ad; } - tasklet_init(&adapter->neq_tasklet, ehea_neq_tasklet, -(unsigned long)adapter); + tasklet_setup(&adapter->neq_tasklet, ehea_neq_tasklet); ret = ehea_create_device_sysfs(dev); if (ret) -- 2.17.1
[PATCH 08/20] ethernet: hinic: convert tasklets to use new tasklet_setup() API
In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c | 7 +++ 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c index ca8cb68a8d20..f304a5b16d75 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c @@ -370,9 +370,9 @@ static void eq_irq_work(struct work_struct *work) * ceq_tasklet - the tasklet of the EQ that received the event * @ceq_data: the eq **/ -static void ceq_tasklet(unsigned long ceq_data) +static void ceq_tasklet(struct tasklet_struct *t) { - struct hinic_eq *ceq = (struct hinic_eq *)ceq_data; + struct hinic_eq *ceq = from_tasklet(ceq, t, ceq_tasklet); eq_irq_handler(ceq); } @@ -782,8 +782,7 @@ static int init_eq(struct hinic_eq *eq, struct hinic_hwif *hwif, INIT_WORK(&aeq_work->work, eq_irq_work); } else if (type == HINIC_CEQ) { - tasklet_init(&eq->ceq_tasklet, ceq_tasklet, -(unsigned long)eq); + tasklet_setup(&eq->ceq_tasklet, ceq_tasklet); } /* set the attributes of the msix entry */ -- 2.17.1
[PATCH 07/20] ethernet: dlink: convert tasklets to use new tasklet_setup() API
In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/net/ethernet/dlink/sundance.c | 20 ++-- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/dlink/sundance.c b/drivers/net/ethernet/dlink/sundance.c index b3f8597e77aa..58022396b053 100644 --- a/drivers/net/ethernet/dlink/sundance.c +++ b/drivers/net/ethernet/dlink/sundance.c @@ -429,8 +429,8 @@ static void init_ring(struct net_device *dev); static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev); static int reset_tx (struct net_device *dev); static irqreturn_t intr_handler(int irq, void *dev_instance); -static void rx_poll(unsigned long data); -static void tx_poll(unsigned long data); +static void rx_poll(struct tasklet_struct *t); +static void tx_poll(struct tasklet_struct *t); static void refill_rx (struct net_device *dev); static void netdev_error(struct net_device *dev, int intr_status); static void netdev_error(struct net_device *dev, int intr_status); @@ -537,8 +537,8 @@ static int sundance_probe1(struct pci_dev *pdev, np->msg_enable = (1 << debug) - 1; spin_lock_init(&np->lock); spin_lock_init(&np->statlock); - tasklet_init(&np->rx_tasklet, rx_poll, (unsigned long)dev); - tasklet_init(&np->tx_tasklet, tx_poll, (unsigned long)dev); + tasklet_setup(&np->rx_tasklet, rx_poll); + tasklet_setup(&np->tx_tasklet, tx_poll); ring_space = dma_alloc_coherent(&pdev->dev, TX_TOTAL_SIZE, &ring_dma, GFP_KERNEL); @@ -1054,10 +1054,9 @@ static void init_ring(struct net_device *dev) } } -static void tx_poll (unsigned long data) +static void tx_poll(struct tasklet_struct *t) { - struct net_device *dev = (struct net_device *)data; - struct netdev_private *np = netdev_priv(dev); + struct netdev_private *np = from_tasklet(np, t, tx_tasklet); unsigned head = np->cur_task % TX_RING_SIZE; struct netdev_desc *txdesc = &np->tx_ring[(np->cur_tx - 1) % TX_RING_SIZE]; @@ -1312,10 +1311,11 @@ static irqreturn_t intr_handler(int irq, void *dev_instance) return IRQ_RETVAL(handled); } -static void rx_poll(unsigned long data) +static void rx_poll(struct tasklet_struct *t) { - struct net_device *dev = (struct net_device *)data; - struct netdev_private *np = netdev_priv(dev); + struct netdev_private *np = from_tasklet(np, t, rx_tasklet); + struct net_device *dev = (struct net_device *)((char *)np - + ALIGN(sizeof(struct net_device), NETDEV_ALIGN)); int entry = np->cur_rx % RX_RING_SIZE; int boguscnt = np->budget; void __iomem *ioaddr = np->base; -- 2.17.1
[PATCH 06/20] ethernet: chelsio: convert tasklets to use new tasklet_setup() API
In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/net/ethernet/chelsio/cxgb/sge.c | 12 drivers/net/ethernet/chelsio/cxgb3/sge.c | 14 ++ drivers/net/ethernet/chelsio/cxgb4/sge.c | 12 ++-- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb/sge.c b/drivers/net/ethernet/chelsio/cxgb/sge.c index 47b5c8e2104b..5f999187038c 100644 --- a/drivers/net/ethernet/chelsio/cxgb/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb/sge.c @@ -239,8 +239,10 @@ struct sched { unsigned intnum;/* num skbs in per port queues */ struct sched_port p[MAX_NPORTS]; struct tasklet_struct sched_tsk;/* tasklet used to run scheduler */ + struct sge *sge; }; -static void restart_sched(unsigned long); + +static void restart_sched(struct tasklet_struct *t); /* @@ -378,7 +380,8 @@ static int tx_sched_init(struct sge *sge) return -ENOMEM; pr_debug("tx_sched_init\n"); - tasklet_init(&s->sched_tsk, restart_sched, (unsigned long) sge); + tasklet_setup(&s->sched_tsk, restart_sched); + s->sge = sge; sge->tx_sched = s; for (i = 0; i < MAX_NPORTS; i++) { @@ -1301,9 +1304,10 @@ static inline void reclaim_completed_tx(struct sge *sge, struct cmdQ *q) * Called from tasklet. Checks the scheduler for any * pending skbs that can be sent. */ -static void restart_sched(unsigned long arg) +static void restart_sched(struct tasklet_struct *t) { - struct sge *sge = (struct sge *) arg; + struct sched *s = from_tasklet(s, t, sched_tsk); + struct sge *sge = s->sge; struct adapter *adapter = sge->adapter; struct cmdQ *q = &sge->cmdQ[0]; struct sk_buff *skb; diff --git a/drivers/net/ethernet/chelsio/cxgb3/sge.c b/drivers/net/ethernet/chelsio/cxgb3/sge.c index 6dabbf1502c7..f2c5da465db5 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c @@ -1520,10 +1520,10 @@ static int ctrl_xmit(struct adapter *adap, struct sge_txq *q, * * Resumes transmission on a suspended Tx control queue. */ -static void restart_ctrlq(unsigned long data) +static void restart_ctrlq(struct tasklet_struct *t) { struct sk_buff *skb; - struct sge_qset *qs = (struct sge_qset *)data; + struct sge_qset *qs = from_tasklet(qs, t, txq[TXQ_CTRL].qresume_tsk); struct sge_txq *q = &qs->txq[TXQ_CTRL]; spin_lock(&q->lock); @@ -1737,10 +1737,10 @@ again: reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK); * * Resumes transmission on a suspended Tx offload queue. */ -static void restart_offloadq(unsigned long data) +static void restart_offloadq(struct tasklet_struct *t) { struct sk_buff *skb; - struct sge_qset *qs = (struct sge_qset *)data; + struct sge_qset *qs = from_tasklet(qs, t, txq[TXQ_OFLD].qresume_tsk); struct sge_txq *q = &qs->txq[TXQ_OFLD]; const struct port_info *pi = netdev_priv(qs->netdev); struct adapter *adap = pi->adapter; @@ -3084,10 +3084,8 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, skb_queue_head_init(&q->txq[i].sendq); } - tasklet_init(&q->txq[TXQ_OFLD].qresume_tsk, restart_offloadq, -(unsigned long)q); - tasklet_init(&q->txq[TXQ_CTRL].qresume_tsk, restart_ctrlq, -(unsigned long)q); + tasklet_setup(&q->txq[TXQ_OFLD].qresume_tsk, restart_offloadq); + tasklet_setup(&q->txq[TXQ_CTRL].qresume_tsk, restart_ctrlq); q->fl[0].gen = q->fl[1].gen = 1; q->fl[0].size = p->fl_size; diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c index d2b587d1670a..e668e17711c8 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c @@ -2660,11 +2660,11 @@ static int ctrl_xmit(struct sge_ctrl_txq *q, struct sk_buff *skb) * * Resumes transmission on a suspended Tx control queue. */ -static void restart_ctrlq(unsigned long data) +static void restart_ctrlq(struct tasklet_struct *t) { struct sk_buff *skb; unsigned int written = 0; - struct sge_ctrl_txq *q = (struct sge_ctrl_txq *)data; + struct sge_ctrl_txq *q = from_tasklet(q, t, qresume_tsk); spin_lock(&q->sendq.lock); reclaim_completed_tx_imm(&q->q); @@ -2961,9 +2961,9 @@ static int ofld_xmit(struct sge_uld_txq *q, struct sk_buff *skb) * * Resumes transmission on a suspended Tx offload queue. */ -static void restart_ofldq(
[PATCH 05/20] ethernet: cavium: convert tasklets to use new tasklet_setup() API
In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/net/ethernet/cavium/liquidio/lio_main.c| 12 ++-- drivers/net/ethernet/cavium/liquidio/octeon_main.h | 1 + drivers/net/ethernet/cavium/octeon/octeon_mgmt.c | 8 drivers/net/ethernet/cavium/thunder/nicvf_main.c | 10 -- drivers/net/ethernet/cavium/thunder/nicvf_queues.c | 4 ++-- drivers/net/ethernet/cavium/thunder/nicvf_queues.h | 2 +- 6 files changed, 18 insertions(+), 19 deletions(-) diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c index e73bc211779a..41c5f4c6ca22 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_main.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c @@ -161,13 +161,13 @@ static int liquidio_set_vf_link_state(struct net_device *netdev, int vfidx, static struct handshake handshake[MAX_OCTEON_DEVICES]; static struct completion first_stage; -static void octeon_droq_bh(unsigned long pdev) +static void octeon_droq_bh(struct tasklet_struct *t) { int q_no; int reschedule = 0; - struct octeon_device *oct = (struct octeon_device *)pdev; - struct octeon_device_priv *oct_priv = - (struct octeon_device_priv *)oct->priv; + struct octeon_device_priv *oct_priv = from_tasklet(oct_priv, t, + droq_tasklet); + struct octeon_device *oct = oct_priv->dev; for (q_no = 0; q_no < MAX_OCTEON_OUTPUT_QUEUES(oct); q_no++) { if (!(oct->io_qmask.oq & BIT_ULL(q_no))) @@ -4194,8 +4194,7 @@ static int octeon_device_init(struct octeon_device *octeon_dev) /* Initialize the tasklet that handles output queue packet processing.*/ dev_dbg(&octeon_dev->pci_dev->dev, "Initializing droq tasklet\n"); - tasklet_init(&oct_priv->droq_tasklet, octeon_droq_bh, -(unsigned long)octeon_dev); + tasklet_setup(&oct_priv->droq_tasklet, octeon_droq_bh); /* Setup the interrupt handler and record the INT SUM register address */ @@ -4299,6 +4298,7 @@ static int octeon_device_init(struct octeon_device *octeon_dev) complete(&handshake[octeon_dev->octeon_id].init); atomic_set(&octeon_dev->status, OCT_DEV_HOST_OK); + oct_priv->dev = octeon_dev; return 0; } diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_main.h b/drivers/net/ethernet/cavium/liquidio/octeon_main.h index 073d0647b439..5b4cb725f60f 100644 --- a/drivers/net/ethernet/cavium/liquidio/octeon_main.h +++ b/drivers/net/ethernet/cavium/liquidio/octeon_main.h @@ -39,6 +39,7 @@ struct octeon_device_priv { /** Tasklet structures for this device. */ struct tasklet_struct droq_tasklet; unsigned long napi_mask; + struct octeon_device *dev; }; /** This structure is used by NIC driver to store information required diff --git a/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c b/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c index 3e17ce0d2314..c745ace07fc3 100644 --- a/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c +++ b/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c @@ -315,9 +315,9 @@ static void octeon_mgmt_clean_tx_buffers(struct octeon_mgmt *p) netif_wake_queue(p->netdev); } -static void octeon_mgmt_clean_tx_tasklet(unsigned long arg) +static void octeon_mgmt_clean_tx_tasklet(struct tasklet_struct *t) { - struct octeon_mgmt *p = (struct octeon_mgmt *)arg; + struct octeon_mgmt *p = from_tasklet(p, t, tx_clean_tasklet); octeon_mgmt_clean_tx_buffers(p); octeon_mgmt_enable_tx_irq(p); } @@ -1489,8 +1489,8 @@ static int octeon_mgmt_probe(struct platform_device *pdev) skb_queue_head_init(&p->tx_list); skb_queue_head_init(&p->rx_list); - tasklet_init(&p->tx_clean_tasklet, -octeon_mgmt_clean_tx_tasklet, (unsigned long)p); + tasklet_setup(&p->tx_clean_tasklet, +octeon_mgmt_clean_tx_tasklet); netdev->priv_flags |= IFF_UNICAST_FLT; diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c index c1378b5c780c..2b58c88f 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c @@ -985,9 +985,9 @@ static int nicvf_poll(struct napi_struct *napi, int budget) * * As of now only CQ errors are handled */ -static void nicvf_handle_qs_err(unsigned long data) +static void nicvf_handle_qs_err(struct tasklet_struct *t) { - struct nicvf *nic = (struct nicvf *)data; + struct nic
[PATCH 04/20] ethernet: cadence: convert tasklets to use new tasklet_setup() API
In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/net/ethernet/cadence/macb_main.c | 7 +++ 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index 6761f404b8aa..830c537bc08c 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -1466,9 +1466,9 @@ static int macb_poll(struct napi_struct *napi, int budget) return work_done; } -static void macb_hresp_error_task(unsigned long data) +static void macb_hresp_error_task(struct tasklet_struct *t) { - struct macb *bp = (struct macb *)data; + struct macb *bp = from_tasklet(bp, t, hresp_err_tasklet); struct net_device *dev = bp->dev; struct macb_queue *queue; unsigned int q; @@ -4560,8 +4560,7 @@ static int macb_probe(struct platform_device *pdev) goto err_out_unregister_mdio; } - tasklet_init(&bp->hresp_err_tasklet, macb_hresp_error_task, -(unsigned long)bp); + tasklet_setup(&bp->hresp_err_tasklet, macb_hresp_error_task); netdev_info(dev, "Cadence %s rev 0x%08x at 0x%08lx irq %d (%pM)\n", macb_is_gem(bp) ? "GEM" : "MACB", macb_readl(bp, MID), -- 2.17.1
[PATCH 03/20] broadcom: cnic: convert tasklets to use new tasklet_setup() API
In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/net/ethernet/broadcom/cnic.c | 18 -- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/broadcom/cnic.c b/drivers/net/ethernet/broadcom/cnic.c index c5cca63b8571..e1e8c012d501 100644 --- a/drivers/net/ethernet/broadcom/cnic.c +++ b/drivers/net/ethernet/broadcom/cnic.c @@ -3009,10 +3009,10 @@ static int cnic_service_bnx2(void *data, void *status_blk) return cnic_service_bnx2_queues(dev); } -static void cnic_service_bnx2_msix(unsigned long data) +static void cnic_service_bnx2_msix(struct tasklet_struct *t) { - struct cnic_dev *dev = (struct cnic_dev *) data; - struct cnic_local *cp = dev->cnic_priv; + struct cnic_local *cp = from_tasklet(cp, t, cnic_irq_task); + struct cnic_dev *dev = cp->dev; cp->last_status_idx = cnic_service_bnx2_queues(dev); @@ -3134,10 +3134,10 @@ static u32 cnic_service_bnx2x_kcq(struct cnic_dev *dev, struct kcq_info *info) return last_status; } -static void cnic_service_bnx2x_bh(unsigned long data) +static void cnic_service_bnx2x_bh(struct tasklet_struct *t) { - struct cnic_dev *dev = (struct cnic_dev *) data; - struct cnic_local *cp = dev->cnic_priv; + struct cnic_local *cp = from_tasklet(cp, t, cnic_irq_task); + struct cnic_dev *dev = cp->dev; struct bnx2x *bp = netdev_priv(dev->netdev); u32 status_idx, new_status_idx; @@ -4458,8 +4458,7 @@ static int cnic_init_bnx2_irq(struct cnic_dev *dev) CNIC_WR(dev, base + BNX2_HC_CMD_TICKS_OFF, (64 << 16) | 220); cp->last_status_idx = cp->status_blk.bnx2->status_idx; - tasklet_init(&cp->cnic_irq_task, cnic_service_bnx2_msix, -(unsigned long) dev); + tasklet_setup(&cp->cnic_irq_task, cnic_service_bnx2_msix); err = cnic_request_irq(dev); if (err) return err; @@ -4868,8 +4867,7 @@ static int cnic_init_bnx2x_irq(struct cnic_dev *dev) struct cnic_eth_dev *ethdev = cp->ethdev; int err = 0; - tasklet_init(&cp->cnic_irq_task, cnic_service_bnx2x_bh, -(unsigned long) dev); + tasklet_setup(&cp->cnic_irq_task, cnic_service_bnx2x_bh); if (ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX) err = cnic_request_irq(dev); -- 2.17.1
[PATCH 02/20] ethernet: amd: convert tasklets to use new tasklet_setup() API
In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 19 +-- drivers/net/ethernet/amd/xgbe/xgbe-i2c.c | 11 +-- drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 11 +-- 3 files changed, 19 insertions(+), 22 deletions(-) diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index 43294a148f8a..cc56086b7c51 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c @@ -403,9 +403,9 @@ static bool xgbe_ecc_ded(struct xgbe_prv_data *pdata, unsigned long *period, return false; } -static void xgbe_ecc_isr_task(unsigned long data) +static void xgbe_ecc_isr_task(struct tasklet_struct *t) { - struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data; + struct xgbe_prv_data *pdata = from_tasklet(pdata, t, tasklet_ecc); unsigned int ecc_isr; bool stop = false; @@ -468,14 +468,14 @@ static irqreturn_t xgbe_ecc_isr(int irq, void *data) if (pdata->isr_as_tasklet) tasklet_schedule(&pdata->tasklet_ecc); else - xgbe_ecc_isr_task((unsigned long)pdata); + xgbe_ecc_isr_task(&pdata->tasklet_ecc); return IRQ_HANDLED; } -static void xgbe_isr_task(unsigned long data) +static void xgbe_isr_task(struct tasklet_struct *t) { - struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data; + struct xgbe_prv_data *pdata = from_tasklet(pdata, t, tasklet_dev); struct xgbe_hw_if *hw_if = &pdata->hw_if; struct xgbe_channel *channel; unsigned int dma_isr, dma_ch_isr; @@ -582,7 +582,7 @@ static void xgbe_isr_task(unsigned long data) /* If there is not a separate ECC irq, handle it here */ if (pdata->vdata->ecc_support && (pdata->dev_irq == pdata->ecc_irq)) - xgbe_ecc_isr_task((unsigned long)pdata); + xgbe_ecc_isr_task(&pdata->tasklet_ecc); /* If there is not a separate I2C irq, handle it here */ if (pdata->vdata->i2c_support && (pdata->dev_irq == pdata->i2c_irq)) @@ -607,7 +607,7 @@ static irqreturn_t xgbe_isr(int irq, void *data) if (pdata->isr_as_tasklet) tasklet_schedule(&pdata->tasklet_dev); else - xgbe_isr_task((unsigned long)pdata); + xgbe_isr_task(&pdata->tasklet_dev); return IRQ_HANDLED; } @@ -991,9 +991,8 @@ static int xgbe_request_irqs(struct xgbe_prv_data *pdata) unsigned int i; int ret; - tasklet_init(&pdata->tasklet_dev, xgbe_isr_task, (unsigned long)pdata); - tasklet_init(&pdata->tasklet_ecc, xgbe_ecc_isr_task, -(unsigned long)pdata); + tasklet_setup(&pdata->tasklet_dev, xgbe_isr_task); + tasklet_setup(&pdata->tasklet_ecc, xgbe_ecc_isr_task); ret = devm_request_irq(pdata->dev, pdata->dev_irq, xgbe_isr, 0, netdev_name(netdev), pdata); diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c b/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c index 4d9062d35930..22d4fc547a0a 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c @@ -274,9 +274,9 @@ static void xgbe_i2c_clear_isr_interrupts(struct xgbe_prv_data *pdata, XI2C_IOREAD(pdata, IC_CLR_STOP_DET); } -static void xgbe_i2c_isr_task(unsigned long data) +static void xgbe_i2c_isr_task(struct tasklet_struct *t) { - struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data; + struct xgbe_prv_data *pdata = from_tasklet(pdata, t, tasklet_i2c); struct xgbe_i2c_op_state *state = &pdata->i2c.op_state; unsigned int isr; @@ -324,7 +324,7 @@ static irqreturn_t xgbe_i2c_isr(int irq, void *data) if (pdata->isr_as_tasklet) tasklet_schedule(&pdata->tasklet_i2c); else - xgbe_i2c_isr_task((unsigned long)pdata); + xgbe_i2c_isr_task(&pdata->tasklet_i2c); return IRQ_HANDLED; } @@ -369,7 +369,7 @@ static void xgbe_i2c_set_target(struct xgbe_prv_data *pdata, unsigned int addr) static irqreturn_t xgbe_i2c_combined_isr(struct xgbe_prv_data *pdata) { - xgbe_i2c_isr_task((unsigned long)pdata); + xgbe_i2c_isr_task(&pdata->tasklet_i2c); return IRQ_HANDLED; } @@ -462,8 +462,7 @@ static int xgbe_i2c_start(struct xgbe_prv_data *pdata) /* If we have a separate I2C irq, enable it */ if (pdata->dev_irq != pdata->i2c_irq) { - tasklet_init(&pdata->tasklet_i2c, xgbe_i2c_isr_task, -
[PATCH] ethernet: cxgb4: convert tasklets to use new tasklet_setup() API
In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 2 +- drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c | 3 +-- drivers/net/ethernet/chelsio/cxgb4/sge.c | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index 9cb8b229c1b3..84fa9b8a9087 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h @@ -2100,7 +2100,7 @@ void free_tx_desc(struct adapter *adap, struct sge_txq *q, void cxgb4_eosw_txq_free_desc(struct adapter *adap, struct sge_eosw_txq *txq, u32 ndesc); int cxgb4_ethofld_send_flowc(struct net_device *dev, u32 eotid, u32 tc); -void cxgb4_ethofld_restart(unsigned long data); +void cxgb4_ethofld_restart(struct tasklet_struct *t); int cxgb4_ethofld_rx_handler(struct sge_rspq *q, const __be64 *rsp, const struct pkt_gl *si); void free_txq(struct adapter *adap, struct sge_txq *q); diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c index ae7123a9de8e..6c259de96f96 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c @@ -114,8 +114,7 @@ static int cxgb4_init_eosw_txq(struct net_device *dev, eosw_txq->cred = adap->params.ofldq_wr_cred; eosw_txq->hwqid = hwqid; eosw_txq->netdev = dev; - tasklet_init(&eosw_txq->qresume_tsk, cxgb4_ethofld_restart, -(unsigned long)eosw_txq); + tasklet_setup(&eosw_txq->qresume_tsk, cxgb4_ethofld_restart); return 0; } diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c index e668e17711c8..482b2bd602e6 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c @@ -3883,9 +3883,9 @@ static int napi_rx_handler(struct napi_struct *napi, int budget) return work_done; } -void cxgb4_ethofld_restart(unsigned long data) +void cxgb4_ethofld_restart(struct tasklet_struct *t) { - struct sge_eosw_txq *eosw_txq = (struct sge_eosw_txq *)data; + struct sge_eosw_txq *eosw_txq = from_tasklet(eosw_txq, t, qresume_tsk); int pktcount; spin_lock(&eosw_txq->lock); -- 2.17.1
[PATCH 01/20] ethernet: alteon: convert tasklets to use new tasklet_setup() API
In preparation for unconditionally passing the struct tasklet_struct pointer to all tasklet callbacks, switch to using the new tasklet_setup() and from_tasklet() to pass the tasklet pointer explicitly. Signed-off-by: Romain Perier Signed-off-by: Allen Pais --- drivers/net/ethernet/alteon/acenic.c | 9 + drivers/net/ethernet/alteon/acenic.h | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/alteon/acenic.c b/drivers/net/ethernet/alteon/acenic.c index ac86fcae1582..8a4c2319953d 100644 --- a/drivers/net/ethernet/alteon/acenic.c +++ b/drivers/net/ethernet/alteon/acenic.c @@ -1562,10 +1562,11 @@ static void ace_watchdog(struct net_device *data, unsigned int txqueue) } -static void ace_tasklet(unsigned long arg) +static void ace_tasklet(struct tasklet_struct *t) { - struct net_device *dev = (struct net_device *) arg; - struct ace_private *ap = netdev_priv(dev); + struct ace_private *ap = from_tasklet(ap, t, ace_tasklet); + struct net_device *dev = (struct net_device *)((char *)ap - + ALIGN(sizeof(struct net_device), NETDEV_ALIGN)); int cur_size; cur_size = atomic_read(&ap->cur_rx_bufs); @@ -2269,7 +2270,7 @@ static int ace_open(struct net_device *dev) /* * Setup the bottom half rx ring refill handler */ - tasklet_init(&ap->ace_tasklet, ace_tasklet, (unsigned long)dev); + tasklet_setup(&ap->ace_tasklet, ace_tasklet); return 0; } diff --git a/drivers/net/ethernet/alteon/acenic.h b/drivers/net/ethernet/alteon/acenic.h index c670067b1541..4b02c705859c 100644 --- a/drivers/net/ethernet/alteon/acenic.h +++ b/drivers/net/ethernet/alteon/acenic.h @@ -776,7 +776,7 @@ static int ace_open(struct net_device *dev); static netdev_tx_t ace_start_xmit(struct sk_buff *skb, struct net_device *dev); static int ace_close(struct net_device *dev); -static void ace_tasklet(unsigned long dev); +static void ace_tasklet(struct tasklet_struct *t); static void ace_dump_trace(struct ace_private *ap); static void ace_set_multicast_list(struct net_device *dev); static int ace_change_mtu(struct net_device *dev, int new_mtu); -- 2.17.1
[PATCH 00/20] ethernet: convert tasklets to use new tasklet_setup() API
Commit 12cc923f1ccc ("tasklet: Introduce new initialization API")' introduced a new tasklet initialization API. This series converts all the crypto modules to use the new tasklet_setup() API Allen Pais (20): ethernet: alteon: convert tasklets to use new tasklet_setup() API ethernet: amd: convert tasklets to use new tasklet_setup() API broadcom: cnic: convert tasklets to use new tasklet_setup() API ethernet: cadence: convert tasklets to use new tasklet_setup() API ethernet: cavium: convert tasklets to use new tasklet_setup() API ethernet: chelsio: convert tasklets to use new tasklet_setup() API ethernet: dlink: convert tasklets to use new tasklet_setup() API ethernet: hinic: convert tasklets to use new tasklet_setup() API ethernet: ehea: convert tasklets to use new tasklet_setup() API ethernet: ibmvnic: convert tasklets to use new tasklet_setup() API ethernet: jme: convert tasklets to use new tasklet_setup() API ethernet: marvell: convert tasklets to use new tasklet_setup() API ethernet: mellanox: convert tasklets to use new tasklet_setup() API ethernet: micrel: convert tasklets to use new tasklet_setup() API ethernet: natsemi: convert tasklets to use new tasklet_setup() API ethernet: netronome: convert tasklets to use new tasklet_setup() API ethernet: ni: convert tasklets to use new tasklet_setup() API ethernet: qlogic: convert tasklets to use new tasklet_setup() API ethernet: silan: convert tasklets to use new tasklet_setup() API ethernet: smsc: convert tasklets to use new tasklet_setup() API drivers/net/ethernet/alteon/acenic.c | 9 +++-- drivers/net/ethernet/alteon/acenic.h | 2 +- drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 19 + drivers/net/ethernet/amd/xgbe/xgbe-i2c.c | 11 +++-- drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 11 +++-- drivers/net/ethernet/broadcom/cnic.c | 18 - drivers/net/ethernet/cadence/macb_main.c | 7 ++-- .../net/ethernet/cavium/liquidio/lio_main.c | 12 +++--- .../ethernet/cavium/liquidio/octeon_main.h| 1 + .../net/ethernet/cavium/octeon/octeon_mgmt.c | 8 ++-- .../net/ethernet/cavium/thunder/nicvf_main.c | 10 ++--- .../ethernet/cavium/thunder/nicvf_queues.c| 4 +- .../ethernet/cavium/thunder/nicvf_queues.h| 2 +- drivers/net/ethernet/chelsio/cxgb/sge.c | 12 -- drivers/net/ethernet/chelsio/cxgb3/sge.c | 14 +++ drivers/net/ethernet/chelsio/cxgb4/sge.c | 12 +++--- drivers/net/ethernet/dlink/sundance.c | 20 +- .../net/ethernet/huawei/hinic/hinic_hw_eqs.c | 7 ++-- drivers/net/ethernet/ibm/ehea/ehea_main.c | 7 ++-- drivers/net/ethernet/ibm/ibmvnic.c| 7 ++-- drivers/net/ethernet/jme.c| 40 --- drivers/net/ethernet/marvell/skge.c | 6 +-- drivers/net/ethernet/mellanox/mlx4/cq.c | 4 +- drivers/net/ethernet/mellanox/mlx4/eq.c | 3 +- drivers/net/ethernet/mellanox/mlx4/mlx4.h | 2 +- drivers/net/ethernet/mellanox/mlx5/core/cq.c | 4 +- drivers/net/ethernet/mellanox/mlx5/core/eq.c | 3 +- .../ethernet/mellanox/mlx5/core/fpga/conn.c | 7 ++-- .../net/ethernet/mellanox/mlx5/core/lib/eq.h | 2 +- drivers/net/ethernet/mellanox/mlxsw/pci.c | 12 +++--- drivers/net/ethernet/micrel/ks8842.c | 19 - drivers/net/ethernet/micrel/ksz884x.c | 14 +++ drivers/net/ethernet/natsemi/ns83820.c| 8 ++-- .../ethernet/netronome/nfp/nfp_net_common.c | 7 ++-- drivers/net/ethernet/ni/nixge.c | 7 ++-- drivers/net/ethernet/qlogic/qed/qed.h | 2 +- drivers/net/ethernet/qlogic/qed/qed_int.c | 27 ++--- drivers/net/ethernet/qlogic/qed/qed_int.h | 2 +- drivers/net/ethernet/qlogic/qed/qed_main.c| 14 +++ drivers/net/ethernet/silan/sc92031.c | 11 ++--- drivers/net/ethernet/smsc/smc91x.c| 10 ++--- 41 files changed, 178 insertions(+), 219 deletions(-) -- 2.17.1
[PATCH v3 1/2] powerpc/pseries: Avoid blocking rtas polling handling multiple PRRN events
When a PRRN event is being handled and another PRRN event comes in, the second event will block rtas polling waiting on the first to complete, preventing any further rtas events from being handled. This can be especially problematic in case that PRRN events are continuously being queued in which case rtas polling gets indefinitely blocked completely. This patch removes the blocking call to flush_work and allows the default workqueue behavior to handle duplicate events. Signed-off-by: John Allen --- v3: -Scrap the mutex as it only replicates existing workqueue behavior. v2: -Unlock prrn_lock when PRRN operations are complete, not after handler is scheduled. -Remove call to flush_work, the previous broken method of serializing PRRN events. --- arch/powerpc/kernel/rtasd.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/powerpc/kernel/rtasd.c b/arch/powerpc/kernel/rtasd.c index 44d66c33d59d..2017934e5985 100644 --- a/arch/powerpc/kernel/rtasd.c +++ b/arch/powerpc/kernel/rtasd.c @@ -290,7 +290,6 @@ static DECLARE_WORK(prrn_work, prrn_work_fn); static void prrn_schedule_update(u32 scope) { - flush_work(&prrn_work); prrn_update_scope = scope; schedule_work(&prrn_work); } -- 2.17.1
[PATCH v3 2/2] powerpc/pseries: Wait for completion of hotplug events during PRRN handling
While handling PRRN events, the time to handle the actual hotplug events dwarfs the time it takes to perform the device tree updates and queue the hotplug events. In the case that PRRN events are being queued continuously, hotplug events have been observed to be queued faster than the kernel can actually handle them. This patch avoids the problem by waiting for a hotplug request to complete before queueing more hotplug events. Signed-off-by: John Allen --- arch/powerpc/platforms/pseries/mobility.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c index 8a8033a249c7..49930848fa78 100644 --- a/arch/powerpc/platforms/pseries/mobility.c +++ b/arch/powerpc/platforms/pseries/mobility.c @@ -242,6 +242,7 @@ static int add_dt_node(__be32 parent_phandle, __be32 drc_index) static void prrn_update_node(__be32 phandle) { struct pseries_hp_errorlog *hp_elog; + struct completion hotplug_done; struct device_node *dn; /* @@ -263,7 +264,9 @@ static void prrn_update_node(__be32 phandle) hp_elog->id_type = PSERIES_HP_ELOG_ID_DRC_INDEX; hp_elog->_drc_u.drc_index = phandle; - queue_hotplug_event(hp_elog, NULL, NULL); + init_completion(&hotplug_done); + queue_hotplug_event(hp_elog, &hotplug_done, NULL); + wait_for_completion(&hotplug_done); kfree(hp_elog); } -- 2.17.1
[PATCH v3 0/2] powerpc/pseries: Improve serialization of PRRN events
Stress testing has uncovered issues with handling continuously queued PRRN events. Running PRRN events in this way can seriously load the system given the sheer volume of dlpar being handled. This patchset ensures that PRRN events are handled more synchronously, only allowing the PRRN handler to queue a single dlpar event at any given time. Additionally, it ensures that rtas polling continues normally when multiple PRRN events are queued simultaneously. v3: -Scrap the PRRN mutex as it only replicates existing workqueue behavior. v2: -Unlock prrn_lock when PRRN operations are complete, not after handler is scheduled. -Remove call to flush_work, the previous broken method of serializing PRRN events. John Allen (2): powerpc/pseries: Avoid blocking rtas polling handling multiple PRRN events powerpc/pseries: Wait for completion of hotplug events during PRRN handling arch/powerpc/kernel/rtasd.c | 10 +++--- arch/powerpc/platforms/pseries/mobility.c | 5 - 2 files changed, 11 insertions(+), 4 deletions(-) -- 2.17.1
Re: [PATCH v2 2/2] powerpc/pseries: Wait for completion of hotplug events during PRRN handling
On Wed, Aug 01, 2018 at 11:16:22PM +1000, Michael Ellerman wrote: John Allen writes: On Mon, Jul 23, 2018 at 11:41:24PM +1000, Michael Ellerman wrote: John Allen writes: While handling PRRN events, the time to handle the actual hotplug events dwarfs the time it takes to perform the device tree updates and queue the hotplug events. In the case that PRRN events are being queued continuously, hotplug events have been observed to be queued faster than the kernel can actually handle them. This patch avoids the problem by waiting for a hotplug request to complete before queueing more hotplug events. Have you tested this patch in isolation, ie. not with patch 1? While I was away on vacation, I believe a build was tested with just this patch and not the first and it has been running with no problems. However, I think they've had problems recreating the problem in general so it may just be that the environment is not setup properly to recreate the issue. So do we need the hotplug work queue at all? Can we just call handle_dlpar_errorlog() directly? Or are we using the work queue to serialise things? And if so would a mutex be better? Right, the workqueue is meant to serialize all hotplug events and it gets used for more than just PRRN events. I believe the motivation for using the workqueue over a mutex is that KVM guests initiate hotplug events through the hotplug interrupt and can queue fairly large requests meaning that in this scenario, waiting for a lock would block interrupts for a while. OK, but that just means that path needs to schedule work to run later. Using the workqueue allows us to serialize hotplug events from different sources in the same way without worrying about the context in which the event is generated. A lock would be so much simpler. It looks like we have three callers of queue_hotplug_event(), the dlpar code, the mobility code and the ras interrupt. The dlpar code already waits synchronously: init_completion(&hotplug_done); queue_hotplug_event(hp_elog, &hotplug_done, &rc); wait_for_completion(&hotplug_done); You're changing mobility to do the same (this patch), leaving only the ras interrupt that actually queues work and returns. So it really seems like a mutex would do the trick, and the ras interrupt would be the only case that needs to schedule work for later. I think you may be right, but I would need some feedback from Nathan Fontenot before I redesign the queue. He's been thinking about that design for longer than I have and may know something that I don't regarding the reason we're using a workqueue rather than a mutex. Given that the bug this is meant to address is pretty high priority, would you consider the wait_for_completion an acceptable stopgap while a more substantial redesign of this code is discussed? -John
Re: [PATCH v2 1/2] powerpc/pseries: Avoid blocking rtas polling handling multiple PRRN events
On Wed, Aug 01, 2018 at 11:02:59PM +1000, Michael Ellerman wrote: Hi John, I'm still not sure about this one. John Allen writes: On Mon, Jul 23, 2018 at 11:27:56PM +1000, Michael Ellerman wrote: Hi John, I'm a bit puzzled by this one. John Allen writes: When a PRRN event is being handled and another PRRN event comes in, the second event will block rtas polling waiting on the first to complete, preventing any further rtas events from being handled. This can be especially problematic in case that PRRN events are continuously being queued in which case rtas polling gets indefinitely blocked completely. This patch introduces a mutex that prevents any subsequent PRRN events from running while there is a prrn event being handled, allowing rtas polling to continue normally. Signed-off-by: John Allen --- v2: -Unlock prrn_lock when PRRN operations are complete, not after handler is scheduled. -Remove call to flush_work, the previous broken method of serializing PRRN events. --- arch/powerpc/kernel/rtasd.c | 10 +++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/kernel/rtasd.c b/arch/powerpc/kernel/rtasd.c index 44d66c33d59d..845fc5aec178 100644 --- a/arch/powerpc/kernel/rtasd.c +++ b/arch/powerpc/kernel/rtasd.c @@ -284,15 +286,17 @@ static void prrn_work_fn(struct work_struct *work) */ pseries_devicetree_update(-prrn_update_scope); numa_update_cpu_topology(false); + mutex_unlock(&prrn_lock); } static DECLARE_WORK(prrn_work, prrn_work_fn); static void prrn_schedule_update(u32 scope) { - flush_work(&prrn_work); This seems like it's actually the core of the change. Previously we were basically blocking on the flush before continuing. The idea here is to replace the blocking flush_work with a non-blocking mutex. So rather than waiting on the running PRRN event to complete, we bail out since a PRRN event is already running. OK, but why is it OK to bail out? The firmware sent you an error log asking you to do something, with a scope value that has some meaning, and now you're just going to drop that on the floor? Maybe it is OK to just drop these events? Or maybe you're saying that because the system is crashing under the load of too many events it's OK to drop the events in this case. I think I see your point. If a PRRN event comes in while another is currently running, the new one may contain a different list of LMBs/CPUs and the old list becomes outdated. With the mutex, the only event that gets handled is the oldest and we will lose any additional changes beyond the initial event. Therefore, as you mentioned in your previous message, the behavior of the global workqueue should work just fine once we remove the call to flush_work. While a prrn event is running, only one will remain on the workqueue, then when the first one completes, the newly scheduled work function should grab the latest PRRN list. I will send a new version of the patch with just the call to flush_work removed. -John The situation this is meant to address is flooding the workqueue with PRRN events, which like the situation in patch 2/2, these can be queued up faster than they can actually be handled. I'm not really sure why this is a problem though. The current code synchronously processes the events, so there should only ever be one in flight. I guess the issue is that each one can queue multiple events on the hotplug work queue? But still, we have terabytes of RAM, we should be able to queue a lot of events before it becomes a problem. So what exactly is getting flooded, what's the symptom? If the queuing of the hotplug events is the problem, then why don't we stop doing that? We could just process them synchronously from the PRRN update, that would naturally throttle them. cheers
Re: Infinite looping observed in __offline_pages
On Wed, Jul 25, 2018 at 10:03:36PM +0200, Michal Hocko wrote: On Wed 25-07-18 13:11:15, John Allen wrote: [...] Does a failure in do_migrate_range indicate that the range is unmigratable and the loop in __offline_pages should terminate and goto failed_removal? Or should we allow a certain number of retrys before we give up on migrating the range? Unfortunatelly not. Migration code doesn't tell a difference between ephemeral and permanent failures. We are relying on start_isolate_page_range to tell us this. So the question is, what kind of page is not migratable and for what reason. Are you able to add some debugging to give us more information. The current debugging code in the hotplug/migration sucks... After reproducing the problem a couple times, it seems that it can occur for different types of pages. Running page-types on the offending page over two separate instances produced the following: # tools/vm/page-types -a 307968-308224 flags page-count MB symbolic-flags long-symbolic-flags 0x0400 10 __Bbuddy total 10 And the following on a separate run: # tools/vm/page-types -a 313088-313344 flags page-count MB symbolic-flags long-symbolic-flags 0x006c 10 __RU_lA referenced,uptodate,lru,active total10 The source of the failure in migrate_pages actually doesn't seem to be that we're hitting the case of the permanent failure, but instead the -EAGAIN case. I traced the EAGAIN return back to migrate_page_move_mapping which I've seen return EAGAIN in two places: mm/migrate.c:453 if (!mapping) { /* Anonymous page without mapping */ if (page_count(page) != expected_count) return -EAGAIN; mm/migrate.c:476 if (page_count(page) != expected_count || radix_tree_deref_slot_protected(pslot, &mapping->i_pages.xa_lock) != page) { xa_unlock_irq(&mapping->i_pages); return -EAGAIN; } So it seems in each case, the actual reference count for the page is not what it is expected to be.
Infinite looping observed in __offline_pages
Hi All, Under heavy stress and constant memory hot add/remove, I have observed the following loop to occasionally loop infinitely: mm/memory_hotplug.c:__offline_pages repeat: /* start memory hot removal */ ret = -EINTR; if (signal_pending(current)) goto failed_removal; cond_resched(); lru_add_drain_all(); drain_all_pages(zone); pfn = scan_movable_pages(start_pfn, end_pfn); if (pfn) { /* We have movable pages */ ret = do_migrate_range(pfn, end_pfn); goto repeat; } What appears to be happening in this case is that do_migrate_range returns a failure code which is being ignored. The failure is stemming from migrate_pages returning "1" which I'm guessing is the result of us hitting the following case: mm/migrate.c: migrate_pages default: /* * Permanent failure (-EBUSY, -ENOSYS, etc.): * unlike -EAGAIN case, the failed page is * removed from migration page list and not * retried in the next outer loop. */ nr_failed++; break; } Does a failure in do_migrate_range indicate that the range is unmigratable and the loop in __offline_pages should terminate and goto failed_removal? Or should we allow a certain number of retrys before we give up on migrating the range? This issue was observed on a ppc64le lpar on a 4.18-rc6 kernel. -John
Re: [PATCH v07 2/9] hotplug/cpu: Add operation queuing function
On Fri, Jul 13, 2018 at 03:18:01PM -0500, Michael Bringmann wrote: migration/dlpar: This patch adds function dlpar_queue_action() which will queued up information about a CPU/Memory 'readd' operation according to resource type, action code, and DRC index. At a subsequent point, the list of operations can be run/played in series. Examples of such oprations include 'readd' of CPU and Memory blocks identified as having changed their associativity during an LPAR migration event. Signed-off-by: Michael Bringmann --- Changes in patch: -- Correct drc_index before adding to pseries_hp_errorlog struct -- Correct text of notice -- Revise queuing model to save up all of the DLPAR actions for later execution. -- Restore list init statement missing from patch -- Move call to apply queued operations into 'mobility.c' -- Compress some code -- Rename some of queueing function APIs -- Revise implementation to push execution of queued operations to a workqueue task. -- Cleanup reference to outdated queuing operation. --- arch/powerpc/include/asm/rtas.h |2 + arch/powerpc/platforms/pseries/dlpar.c| 61 + arch/powerpc/platforms/pseries/mobility.c |4 ++ arch/powerpc/platforms/pseries/pseries.h |2 + 4 files changed, 69 insertions(+) diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h index 71e393c..4f601c7 100644 --- a/arch/powerpc/include/asm/rtas.h +++ b/arch/powerpc/include/asm/rtas.h @@ -310,12 +310,14 @@ struct pseries_hp_errorlog { struct { __be32 count, index; } ic; chardrc_name[1]; } _drc_u; + struct list_head list; }; #define PSERIES_HP_ELOG_RESOURCE_CPU1 #define PSERIES_HP_ELOG_RESOURCE_MEM2 #define PSERIES_HP_ELOG_RESOURCE_SLOT 3 #define PSERIES_HP_ELOG_RESOURCE_PHB4 +#define PSERIES_HP_ELOG_RESOURCE_PMT 5 #define PSERIES_HP_ELOG_ACTION_ADD 1 #define PSERIES_HP_ELOG_ACTION_REMOVE 2 diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index a0b20c0..7264b8e 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c @@ -25,6 +25,7 @@ #include #include #include +#include #include static struct workqueue_struct *pseries_hp_wq; @@ -329,6 +330,8 @@ int dlpar_release_drc(u32 drc_index) return 0; } +static int dlpar_pmt(struct pseries_hp_errorlog *work); + static int handle_dlpar_errorlog(struct pseries_hp_errorlog *hp_elog) { int rc; @@ -357,6 +360,9 @@ static int handle_dlpar_errorlog(struct pseries_hp_errorlog *hp_elog) case PSERIES_HP_ELOG_RESOURCE_CPU: rc = dlpar_cpu(hp_elog); break; + case PSERIES_HP_ELOG_RESOURCE_PMT: + rc = dlpar_pmt(hp_elog); + break; default: pr_warn_ratelimited("Invalid resource (%d) specified\n", hp_elog->resource); @@ -407,6 +413,61 @@ void queue_hotplug_event(struct pseries_hp_errorlog *hp_errlog, } } +LIST_HEAD(dlpar_delayed_list); + +int dlpar_queue_action(int resource, int action, u32 drc_index) +{ + struct pseries_hp_errorlog *hp_errlog; + + hp_errlog = kmalloc(sizeof(struct pseries_hp_errorlog), GFP_KERNEL); + if (!hp_errlog) + return -ENOMEM; + + hp_errlog->resource = resource; + hp_errlog->action = action; + hp_errlog->id_type = PSERIES_HP_ELOG_ID_DRC_INDEX; + hp_errlog->_drc_u.drc_index = cpu_to_be32(drc_index); + + list_add_tail(&hp_errlog->list, &dlpar_delayed_list); + + return 0; +} + +static int dlpar_pmt(struct pseries_hp_errorlog *work) +{ + struct list_head *pos, *q; + + ssleep(15); Why do we need to sleep for so long here? -John + + list_for_each_safe(pos, q, &dlpar_delayed_list) { + struct pseries_hp_errorlog *tmp; + + tmp = list_entry(pos, struct pseries_hp_errorlog, list); + handle_dlpar_errorlog(tmp); + + list_del(pos); + kfree(tmp); + + ssleep(10); + } + + return 0; +} + +int dlpar_queued_actions_run(void) +{ + if (!list_empty(&dlpar_delayed_list)) { + struct pseries_hp_errorlog hp_errlog; + + hp_errlog.resource = PSERIES_HP_ELOG_RESOURCE_PMT; + hp_errlog.action = 0; + hp_errlog.id_type = 0; + + queue_hotplug_event(&hp_errlog, 0, 0); + } + return 0; +} + static int dlpar_parse_resource(char **cmd, struct pseries_hp_errorlog *hp_elog) { char *arg; diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c index f6364d9..d0d1cae 100644 --- a/arch/powerpc/platforms/pseries/mobility.c +++ b/arch/powerpc/platforms/pseries/mobility.c @@ -378,6 +378,10 @@ static ssize_t migration_store(struct class *class, return rc; po
Re: [PATCH v2 2/2] powerpc/pseries: Wait for completion of hotplug events during PRRN handling
On Mon, Jul 23, 2018 at 11:41:24PM +1000, Michael Ellerman wrote: John Allen writes: While handling PRRN events, the time to handle the actual hotplug events dwarfs the time it takes to perform the device tree updates and queue the hotplug events. In the case that PRRN events are being queued continuously, hotplug events have been observed to be queued faster than the kernel can actually handle them. This patch avoids the problem by waiting for a hotplug request to complete before queueing more hotplug events. So do we need the hotplug work queue at all? Can we just call handle_dlpar_errorlog() directly? Or are we using the work queue to serialise things? And if so would a mutex be better? Right, the workqueue is meant to serialize all hotplug events and it gets used for more than just PRRN events. I believe the motivation for using the workqueue over a mutex is that KVM guests initiate hotplug events through the hotplug interrupt and can queue fairly large requests meaning that in this scenario, waiting for a lock would block interrupts for a while. Using the workqueue allows us to serialize hotplug events from different sources in the same way without worrying about the context in which the event is generated. It looks like prrn_update_node() is called via at least, prrn_work_fn() and post_mobility_fixup(). The latter is called from migration_store(), which seems like it would be harmless. But also from pseries_suspend_enable_irqs() which I'm less clear on. Yeah, that doesn't seem to make sense based on the function name. Odd that prrn_update_node is being called from anywhere outside of handling PRRN events. Perhaps if other code paths are using the function, it needs a more generic name. -John cheers diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c index 8a8033a249c7..49930848fa78 100644 --- a/arch/powerpc/platforms/pseries/mobility.c +++ b/arch/powerpc/platforms/pseries/mobility.c @@ -242,6 +242,7 @@ static int add_dt_node(__be32 parent_phandle, __be32 drc_index) static void prrn_update_node(__be32 phandle) { struct pseries_hp_errorlog *hp_elog; + struct completion hotplug_done; struct device_node *dn; /* @@ -263,7 +264,9 @@ static void prrn_update_node(__be32 phandle) hp_elog->id_type = PSERIES_HP_ELOG_ID_DRC_INDEX; hp_elog->_drc_u.drc_index = phandle; - queue_hotplug_event(hp_elog, NULL, NULL); + init_completion(&hotplug_done); + queue_hotplug_event(hp_elog, &hotplug_done, NULL); + wait_for_completion(&hotplug_done); kfree(hp_elog); } -- 2.17.1
Re: [PATCH v2 1/2] powerpc/pseries: Avoid blocking rtas polling handling multiple PRRN events
On Mon, Jul 23, 2018 at 11:27:56PM +1000, Michael Ellerman wrote: Hi John, I'm a bit puzzled by this one. John Allen writes: When a PRRN event is being handled and another PRRN event comes in, the second event will block rtas polling waiting on the first to complete, preventing any further rtas events from being handled. This can be especially problematic in case that PRRN events are continuously being queued in which case rtas polling gets indefinitely blocked completely. This patch introduces a mutex that prevents any subsequent PRRN events from running while there is a prrn event being handled, allowing rtas polling to continue normally. Signed-off-by: John Allen --- v2: -Unlock prrn_lock when PRRN operations are complete, not after handler is scheduled. -Remove call to flush_work, the previous broken method of serializing PRRN events. --- arch/powerpc/kernel/rtasd.c | 10 +++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/kernel/rtasd.c b/arch/powerpc/kernel/rtasd.c index 44d66c33d59d..845fc5aec178 100644 --- a/arch/powerpc/kernel/rtasd.c +++ b/arch/powerpc/kernel/rtasd.c @@ -284,15 +286,17 @@ static void prrn_work_fn(struct work_struct *work) */ pseries_devicetree_update(-prrn_update_scope); numa_update_cpu_topology(false); + mutex_unlock(&prrn_lock); } static DECLARE_WORK(prrn_work, prrn_work_fn); static void prrn_schedule_update(u32 scope) { - flush_work(&prrn_work); This seems like it's actually the core of the change. Previously we were basically blocking on the flush before continuing. The idea here is to replace the blocking flush_work with a non-blocking mutex. So rather than waiting on the running PRRN event to complete, we bail out since a PRRN event is already running. The situation this is meant to address is flooding the workqueue with PRRN events, which like the situation in patch 2/2, these can be queued up faster than they can actually be handled. - prrn_update_scope = scope; I don't really understand the scope. With the old code we always ran the work function once for call, now we potentially throw away the scope value (if the try lock fails). So anytime we actually want to run with the scope (in the event the trylock succeeds), we schedule the work with the scope value set accordingly as seen in the code below. In the case that we actually don't want to run a PRRN event (if one is already running) we do throw away the scope and ignore the request entirely. - schedule_work(&prrn_work); + if (mutex_trylock(&prrn_lock)) { + prrn_update_scope = scope; + schedule_work(&prrn_work); + } Ignoring the scope, the addition of the mutex should not actually make any difference. If you see the doco for schedule_work() it says: * This puts a job in the kernel-global workqueue if it was not already * queued and leaves it in the same position on the kernel-global * workqueue otherwise. So the mutex basically implements that existing behaviour. But maybe the scope is the issue? Like I said I don't really understand the scope value. So I guess I'm wondering if we just need to drop the flush_work() and the rest is not required? To sum up the above, the behavior without the mutex is not the same as with the mutex. Without the mutex, that means that anytime we get a PRRN event, it will get queued on the workqueue which can get flooded if PRRN events are queued continuously. With the mutex, only one PRRN event can be queued for handling at once. Hope that clears things up! -John cheers
[PATCH v2 1/2] powerpc/pseries: Avoid blocking rtas polling handling multiple PRRN events
When a PRRN event is being handled and another PRRN event comes in, the second event will block rtas polling waiting on the first to complete, preventing any further rtas events from being handled. This can be especially problematic in case that PRRN events are continuously being queued in which case rtas polling gets indefinitely blocked completely. This patch introduces a mutex that prevents any subsequent PRRN events from running while there is a prrn event being handled, allowing rtas polling to continue normally. Signed-off-by: John Allen --- v2: -Unlock prrn_lock when PRRN operations are complete, not after handler is scheduled. -Remove call to flush_work, the previous broken method of serializing PRRN events. --- arch/powerpc/kernel/rtasd.c | 10 +++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/kernel/rtasd.c b/arch/powerpc/kernel/rtasd.c index 44d66c33d59d..845fc5aec178 100644 --- a/arch/powerpc/kernel/rtasd.c +++ b/arch/powerpc/kernel/rtasd.c @@ -35,6 +35,8 @@ static DEFINE_SPINLOCK(rtasd_log_lock); +static DEFINE_MUTEX(prrn_lock); + static DECLARE_WAIT_QUEUE_HEAD(rtas_log_wait); static char *rtas_log_buf; @@ -284,15 +286,17 @@ static void prrn_work_fn(struct work_struct *work) */ pseries_devicetree_update(-prrn_update_scope); numa_update_cpu_topology(false); + mutex_unlock(&prrn_lock); } static DECLARE_WORK(prrn_work, prrn_work_fn); static void prrn_schedule_update(u32 scope) { - flush_work(&prrn_work); - prrn_update_scope = scope; - schedule_work(&prrn_work); + if (mutex_trylock(&prrn_lock)) { + prrn_update_scope = scope; + schedule_work(&prrn_work); + } } static void handle_rtas_event(const struct rtas_error_log *log) -- 2.17.1