root/fs/smb/smbdirect/internal.h
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 *   Copyright (c) 2025, Stefan Metzmacher
 */

#ifndef __FS_SMB_COMMON_SMBDIRECT_INTERNAL_H__
#define __FS_SMB_COMMON_SMBDIRECT_INTERNAL_H__

#define DEFAULT_SYMBOL_NAMESPACE "SMBDIRECT"
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/smbdirect.h>
#include "pdu.h"

#include <linux/mutex.h>

struct smbdirect_module_state {
        struct mutex mutex;

        struct {
                struct workqueue_struct *accept;
                struct workqueue_struct *connect;
                struct workqueue_struct *idle;
                struct workqueue_struct *refill;
                struct workqueue_struct *immediate;
                struct workqueue_struct *cleanup;
        } workqueues;

        struct {
                rwlock_t lock;
                struct list_head list;
        } devices;
};

extern struct smbdirect_module_state smbdirect_globals;

#include "socket.h"

struct smbdirect_device {
        struct list_head list;
        struct ib_device *ib_dev;
        /*
         * copy of ib_dev->name,
         * in order to print renames
         */
        char ib_name[IB_DEVICE_NAME_MAX];
};

int smbdirect_socket_init_new(struct net *net, struct smbdirect_socket *sc);

int smbdirect_socket_init_accepting(struct rdma_cm_id *id, struct smbdirect_socket *sc);

void __smbdirect_socket_schedule_cleanup(struct smbdirect_socket *sc,
                                         const char *macro_name,
                                         unsigned int lvl,
                                         const char *func,
                                         unsigned int line,
                                         int error,
                                         enum smbdirect_socket_status *force_status);
#define smbdirect_socket_schedule_cleanup(__sc, __error) \
        __smbdirect_socket_schedule_cleanup(__sc, \
                "smbdirect_socket_schedule_cleanup", SMBDIRECT_LOG_ERR, \
                __func__, __LINE__, __error, NULL)
#define smbdirect_socket_schedule_cleanup_lvl(__sc, __lvl, __error) \
        __smbdirect_socket_schedule_cleanup(__sc, \
                "smbdirect_socket_schedule_cleanup_lvl", __lvl, \
                __func__, __LINE__, __error, NULL)
#define smbdirect_socket_schedule_cleanup_status(__sc, __lvl, __error, __status) do { \
        enum smbdirect_socket_status __force_status = __status; \
        __smbdirect_socket_schedule_cleanup(__sc, \
                "smbdirect_socket_schedule_cleanup_status", __lvl, \
                __func__, __LINE__, __error, &__force_status); \
} while (0)

void smbdirect_socket_destroy_sync(struct smbdirect_socket *sc);

int smbdirect_socket_wait_for_credits(struct smbdirect_socket *sc,
                                      enum smbdirect_socket_status expected_status,
                                      int unexpected_errno,
                                      wait_queue_head_t *waitq,
                                      atomic_t *total_credits,
                                      int needed);

void smbdirect_connection_rdma_established(struct smbdirect_socket *sc);

void smbdirect_connection_negotiation_done(struct smbdirect_socket *sc);

int smbdirect_connection_create_qp(struct smbdirect_socket *sc);

void smbdirect_connection_destroy_qp(struct smbdirect_socket *sc);

int smbdirect_connection_create_mem_pools(struct smbdirect_socket *sc);

void smbdirect_connection_destroy_mem_pools(struct smbdirect_socket *sc);

struct smbdirect_send_io *smbdirect_connection_alloc_send_io(struct smbdirect_socket *sc);

void smbdirect_connection_free_send_io(struct smbdirect_send_io *msg);

struct smbdirect_recv_io *smbdirect_connection_get_recv_io(struct smbdirect_socket *sc);

void smbdirect_connection_put_recv_io(struct smbdirect_recv_io *msg);

void smbdirect_connection_reassembly_append_recv_io(struct smbdirect_socket *sc,
                                                    struct smbdirect_recv_io *msg,
                                                    u32 data_length);

struct smbdirect_recv_io *
smbdirect_connection_reassembly_first_recv_io(struct smbdirect_socket *sc);

void smbdirect_connection_negotiate_rdma_resources(struct smbdirect_socket *sc,
                                                   u8 peer_initiator_depth,
                                                   u8 peer_responder_resources,
                                                   const struct rdma_conn_param *param);

void smbdirect_connection_idle_timer_work(struct work_struct *work);

u16 smbdirect_connection_grant_recv_credits(struct smbdirect_socket *sc);

int smbdirect_connection_post_send_wr(struct smbdirect_socket *sc,
                                      struct ib_send_wr *wr);

int smbdirect_connection_post_recv_io(struct smbdirect_recv_io *msg);

void smbdirect_connection_recv_io_done(struct ib_cq *cq, struct ib_wc *wc);

int smbdirect_connection_recv_io_refill(struct smbdirect_socket *sc);

int smbdirect_connection_create_mr_list(struct smbdirect_socket *sc);

void smbdirect_connection_destroy_mr_list(struct smbdirect_socket *sc);

int smbdirect_accept_connect_request(struct smbdirect_socket *sc,
                                     const struct rdma_conn_param *param);

void smbdirect_accept_negotiate_finish(struct smbdirect_socket *sc, u32 ntstatus);

__init int smbdirect_devices_init(void);
__exit void smbdirect_devices_exit(void);

#endif /* __FS_SMB_COMMON_SMBDIRECT_INTERNAL_H__ */