mirror of
https://git.proxmox.com/git/mirror_ubuntu-kernels.git
synced 2025-11-22 04:48:22 +00:00
This patch is a major rewrite of the tasklet routines in rxe_task.c. The main motivation for this is the realization that the code violates the safety of the qp pointer by correct reference counting. When a tasklet is scheduled from a verbs API the calling thread has a valid reference to the qp and schedules the tasklet to run at a later time carrying a pointer to the qp. Once the calling code returns however the qp can be destroyed at any time. In order to correct this a reference to the qp must be taken when the task is scheduled and held until it finishes running. This is complicated by the tasklet library not alwys running a task that is scheduled depending on whether someone else has scheduled it. This patch moves the logic for deciding whether to run or schedule a task outside of do_task() and guarantees that there is only one copy of the task scheduled or running at a time. Secondly the separate flags controlling teardown and draining of the task are included in the task state machine and all references to the state are protected by spinlocks to avoid consistency and memory barrier issues. Link: https://lore.kernel.org/r/20230304174533.11296-9-rpearsonhpe@gmail.com Signed-off-by: Bob Pearson <rpearsonhpe@gmail.com> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
57 lines
1.2 KiB
C
57 lines
1.2 KiB
C
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
|
|
/*
|
|
* Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
|
|
* Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
|
|
*/
|
|
|
|
#ifndef RXE_TASK_H
|
|
#define RXE_TASK_H
|
|
|
|
enum {
|
|
TASK_STATE_IDLE = 0,
|
|
TASK_STATE_BUSY = 1,
|
|
TASK_STATE_ARMED = 2,
|
|
TASK_STATE_DRAINING = 3,
|
|
TASK_STATE_DRAINED = 4,
|
|
TASK_STATE_INVALID = 5,
|
|
};
|
|
|
|
/*
|
|
* data structure to describe a 'task' which is a short
|
|
* function that returns 0 as long as it needs to be
|
|
* called again.
|
|
*/
|
|
struct rxe_task {
|
|
struct tasklet_struct tasklet;
|
|
int state;
|
|
spinlock_t lock;
|
|
struct rxe_qp *qp;
|
|
int (*func)(struct rxe_qp *qp);
|
|
int ret;
|
|
long num_sched;
|
|
long num_done;
|
|
};
|
|
|
|
/*
|
|
* init rxe_task structure
|
|
* qp => parameter to pass to func
|
|
* func => function to call until it returns != 0
|
|
*/
|
|
int rxe_init_task(struct rxe_task *task, struct rxe_qp *qp,
|
|
int (*func)(struct rxe_qp *));
|
|
|
|
/* cleanup task */
|
|
void rxe_cleanup_task(struct rxe_task *task);
|
|
|
|
void rxe_run_task(struct rxe_task *task);
|
|
|
|
void rxe_sched_task(struct rxe_task *task);
|
|
|
|
/* keep a task from scheduling */
|
|
void rxe_disable_task(struct rxe_task *task);
|
|
|
|
/* allow task to run */
|
|
void rxe_enable_task(struct rxe_task *task);
|
|
|
|
#endif /* RXE_TASK_H */
|