1266b0663SKrzysztof Zdziarski /* SPDX-License-Identifier: BSD-3-Clause */ 2266b0663SKrzysztof Zdziarski /* Copyright(c) 2007-2022 Intel Corporation */ 3266b0663SKrzysztof Zdziarski 4266b0663SKrzysztof Zdziarski #include "qat_freebsd.h" 5266b0663SKrzysztof Zdziarski #include "adf_cfg.h" 6266b0663SKrzysztof Zdziarski #include "adf_common_drv.h" 7266b0663SKrzysztof Zdziarski #include "adf_accel_devices.h" 8266b0663SKrzysztof Zdziarski #include "icp_qat_uclo.h" 9266b0663SKrzysztof Zdziarski #include "icp_qat_fw.h" 10266b0663SKrzysztof Zdziarski #include "icp_qat_fw_init_admin.h" 11266b0663SKrzysztof Zdziarski #include "adf_cfg_strings.h" 12266b0663SKrzysztof Zdziarski #include "adf_uio_control.h" 13266b0663SKrzysztof Zdziarski #include "adf_uio_cleanup.h" 14266b0663SKrzysztof Zdziarski #include "adf_uio.h" 15266b0663SKrzysztof Zdziarski #include "adf_transport_access_macros.h" 16266b0663SKrzysztof Zdziarski #include "adf_transport_internal.h" 17266b0663SKrzysztof Zdziarski 18266b0663SKrzysztof Zdziarski #define ADF_DEV_PROCESSES_NAME "qat_dev_processes" 19266b0663SKrzysztof Zdziarski #define ADF_DEV_STATE_NAME "qat_dev_state" 20266b0663SKrzysztof Zdziarski 21266b0663SKrzysztof Zdziarski #define ADF_STATE_CALLOUT_TIME 10 22266b0663SKrzysztof Zdziarski 2322cf89c9SPiotr Kasierski static const char *mtx_name = "state_mtx"; 2422cf89c9SPiotr Kasierski static const char *mtx_callout_name = "callout_mtx"; 25266b0663SKrzysztof Zdziarski 26266b0663SKrzysztof Zdziarski static d_open_t adf_processes_open; 27266b0663SKrzysztof Zdziarski static void adf_processes_release(void *data); 28266b0663SKrzysztof Zdziarski static d_read_t adf_processes_read; 29266b0663SKrzysztof Zdziarski static d_write_t adf_processes_write; 30266b0663SKrzysztof Zdziarski 31266b0663SKrzysztof Zdziarski static d_open_t adf_state_open; 32266b0663SKrzysztof Zdziarski static void adf_state_release(void *data); 33266b0663SKrzysztof Zdziarski static d_read_t adf_state_read; 34266b0663SKrzysztof Zdziarski static int adf_state_kqfilter(struct cdev *dev, struct knote *kn); 35266b0663SKrzysztof Zdziarski static int adf_state_kqread_event(struct knote *kn, long hint); 36266b0663SKrzysztof Zdziarski static void adf_state_kqread_detach(struct knote *kn); 37266b0663SKrzysztof Zdziarski 38266b0663SKrzysztof Zdziarski static struct callout callout; 39266b0663SKrzysztof Zdziarski static struct mtx mtx; 4022cf89c9SPiotr Kasierski static struct mtx callout_mtx; 41266b0663SKrzysztof Zdziarski static struct service_hndl adf_state_hndl; 42266b0663SKrzysztof Zdziarski 43266b0663SKrzysztof Zdziarski struct entry_proc_events { 44266b0663SKrzysztof Zdziarski struct adf_state_priv_data *proc_events; 45266b0663SKrzysztof Zdziarski 46266b0663SKrzysztof Zdziarski SLIST_ENTRY(entry_proc_events) entries_proc_events; 47266b0663SKrzysztof Zdziarski }; 48266b0663SKrzysztof Zdziarski 49266b0663SKrzysztof Zdziarski struct entry_state { 50266b0663SKrzysztof Zdziarski struct adf_state state; 51266b0663SKrzysztof Zdziarski 52266b0663SKrzysztof Zdziarski STAILQ_ENTRY(entry_state) entries_state; 53266b0663SKrzysztof Zdziarski }; 54266b0663SKrzysztof Zdziarski 55266b0663SKrzysztof Zdziarski SLIST_HEAD(proc_events_head, entry_proc_events); 56266b0663SKrzysztof Zdziarski STAILQ_HEAD(state_head, entry_state); 57266b0663SKrzysztof Zdziarski 58266b0663SKrzysztof Zdziarski static struct proc_events_head proc_events_head; 59266b0663SKrzysztof Zdziarski 60266b0663SKrzysztof Zdziarski struct adf_processes_priv_data { 61266b0663SKrzysztof Zdziarski char name[ADF_CFG_MAX_SECTION_LEN_IN_BYTES]; 62266b0663SKrzysztof Zdziarski int read_flag; 63266b0663SKrzysztof Zdziarski struct list_head list; 64266b0663SKrzysztof Zdziarski }; 65266b0663SKrzysztof Zdziarski 66266b0663SKrzysztof Zdziarski struct adf_state_priv_data { 67266b0663SKrzysztof Zdziarski struct cdev *cdev; 68266b0663SKrzysztof Zdziarski struct selinfo rsel; 69266b0663SKrzysztof Zdziarski struct state_head state_head; 70266b0663SKrzysztof Zdziarski }; 71266b0663SKrzysztof Zdziarski 72266b0663SKrzysztof Zdziarski static struct cdevsw adf_processes_cdevsw = { 73266b0663SKrzysztof Zdziarski .d_version = D_VERSION, 74266b0663SKrzysztof Zdziarski .d_open = adf_processes_open, 75266b0663SKrzysztof Zdziarski .d_read = adf_processes_read, 76266b0663SKrzysztof Zdziarski .d_write = adf_processes_write, 77266b0663SKrzysztof Zdziarski .d_name = ADF_DEV_PROCESSES_NAME, 78266b0663SKrzysztof Zdziarski }; 79266b0663SKrzysztof Zdziarski 80266b0663SKrzysztof Zdziarski static struct cdevsw adf_state_cdevsw = { 81266b0663SKrzysztof Zdziarski .d_version = D_VERSION, 82266b0663SKrzysztof Zdziarski .d_open = adf_state_open, 83266b0663SKrzysztof Zdziarski .d_read = adf_state_read, 84266b0663SKrzysztof Zdziarski .d_kqfilter = adf_state_kqfilter, 85266b0663SKrzysztof Zdziarski .d_name = ADF_DEV_STATE_NAME, 86266b0663SKrzysztof Zdziarski }; 87266b0663SKrzysztof Zdziarski 88*ef9ffb85SMark Johnston static const struct filterops adf_state_read_filterops = { 89266b0663SKrzysztof Zdziarski .f_isfd = 1, 90266b0663SKrzysztof Zdziarski .f_attach = NULL, 91266b0663SKrzysztof Zdziarski .f_detach = adf_state_kqread_detach, 92266b0663SKrzysztof Zdziarski .f_event = adf_state_kqread_event, 93266b0663SKrzysztof Zdziarski }; 94266b0663SKrzysztof Zdziarski 95266b0663SKrzysztof Zdziarski static struct cdev *adf_processes_dev; 96266b0663SKrzysztof Zdziarski static struct cdev *adf_state_dev; 97266b0663SKrzysztof Zdziarski 98266b0663SKrzysztof Zdziarski static LINUX_LIST_HEAD(processes_list); 99266b0663SKrzysztof Zdziarski 100266b0663SKrzysztof Zdziarski struct sx processes_list_sema; 101266b0663SKrzysztof Zdziarski SX_SYSINIT(processes_list_sema, &processes_list_sema, "adf proc list"); 102266b0663SKrzysztof Zdziarski 103266b0663SKrzysztof Zdziarski static void 104266b0663SKrzysztof Zdziarski adf_chr_drv_destroy(void) 105266b0663SKrzysztof Zdziarski { 106266b0663SKrzysztof Zdziarski destroy_dev(adf_processes_dev); 107266b0663SKrzysztof Zdziarski } 108266b0663SKrzysztof Zdziarski 109266b0663SKrzysztof Zdziarski static int 110266b0663SKrzysztof Zdziarski adf_chr_drv_create(void) 111266b0663SKrzysztof Zdziarski { 112266b0663SKrzysztof Zdziarski 113266b0663SKrzysztof Zdziarski adf_processes_dev = make_dev(&adf_processes_cdevsw, 114266b0663SKrzysztof Zdziarski 0, 115266b0663SKrzysztof Zdziarski UID_ROOT, 116266b0663SKrzysztof Zdziarski GID_WHEEL, 117266b0663SKrzysztof Zdziarski 0600, 118266b0663SKrzysztof Zdziarski ADF_DEV_PROCESSES_NAME); 119266b0663SKrzysztof Zdziarski if (adf_processes_dev == NULL) { 120266b0663SKrzysztof Zdziarski printf("QAT: failed to create device\n"); 121266b0663SKrzysztof Zdziarski goto err_cdev_del; 122266b0663SKrzysztof Zdziarski } 123266b0663SKrzysztof Zdziarski return 0; 124266b0663SKrzysztof Zdziarski err_cdev_del: 125266b0663SKrzysztof Zdziarski return EFAULT; 126266b0663SKrzysztof Zdziarski } 127266b0663SKrzysztof Zdziarski 128266b0663SKrzysztof Zdziarski static int 129266b0663SKrzysztof Zdziarski adf_processes_open(struct cdev *dev, int oflags, int devtype, struct thread *td) 130266b0663SKrzysztof Zdziarski { 131266b0663SKrzysztof Zdziarski int i = 0, devices = 0; 132266b0663SKrzysztof Zdziarski struct adf_accel_dev *accel_dev = NULL; 133266b0663SKrzysztof Zdziarski struct adf_processes_priv_data *prv_data = NULL; 134266b0663SKrzysztof Zdziarski int error = 0; 135266b0663SKrzysztof Zdziarski 136266b0663SKrzysztof Zdziarski for (i = 0; i < ADF_MAX_DEVICES; i++) { 137266b0663SKrzysztof Zdziarski accel_dev = adf_devmgr_get_dev_by_id(i); 138266b0663SKrzysztof Zdziarski if (!accel_dev) 139266b0663SKrzysztof Zdziarski continue; 140266b0663SKrzysztof Zdziarski if (!adf_dev_started(accel_dev)) 141266b0663SKrzysztof Zdziarski continue; 142266b0663SKrzysztof Zdziarski devices++; 143266b0663SKrzysztof Zdziarski } 144266b0663SKrzysztof Zdziarski if (!devices) { 145266b0663SKrzysztof Zdziarski printf("QAT: No active devices found.\n"); 146266b0663SKrzysztof Zdziarski return ENXIO; 147266b0663SKrzysztof Zdziarski } 148266b0663SKrzysztof Zdziarski prv_data = malloc(sizeof(*prv_data), M_QAT, M_WAITOK | M_ZERO); 149266b0663SKrzysztof Zdziarski INIT_LIST_HEAD(&prv_data->list); 150266b0663SKrzysztof Zdziarski error = devfs_set_cdevpriv(prv_data, adf_processes_release); 151266b0663SKrzysztof Zdziarski if (error) { 152266b0663SKrzysztof Zdziarski free(prv_data, M_QAT); 153266b0663SKrzysztof Zdziarski return error; 154266b0663SKrzysztof Zdziarski } 155266b0663SKrzysztof Zdziarski 156266b0663SKrzysztof Zdziarski return 0; 157266b0663SKrzysztof Zdziarski } 158266b0663SKrzysztof Zdziarski 159266b0663SKrzysztof Zdziarski static int 160266b0663SKrzysztof Zdziarski adf_get_first_started_dev(void) 161266b0663SKrzysztof Zdziarski { 162266b0663SKrzysztof Zdziarski int i = 0; 163266b0663SKrzysztof Zdziarski struct adf_accel_dev *accel_dev = NULL; 164266b0663SKrzysztof Zdziarski 165266b0663SKrzysztof Zdziarski for (i = 0; i < ADF_MAX_DEVICES; i++) { 166266b0663SKrzysztof Zdziarski accel_dev = adf_devmgr_get_dev_by_id(i); 167266b0663SKrzysztof Zdziarski if (!accel_dev) 168266b0663SKrzysztof Zdziarski continue; 169266b0663SKrzysztof Zdziarski if (adf_dev_started(accel_dev)) 170266b0663SKrzysztof Zdziarski return i; 171266b0663SKrzysztof Zdziarski } 172266b0663SKrzysztof Zdziarski 173266b0663SKrzysztof Zdziarski return -1; 174266b0663SKrzysztof Zdziarski } 175266b0663SKrzysztof Zdziarski 176266b0663SKrzysztof Zdziarski static int 177266b0663SKrzysztof Zdziarski adf_processes_write(struct cdev *dev, struct uio *uio, int ioflag) 178266b0663SKrzysztof Zdziarski { 179266b0663SKrzysztof Zdziarski struct adf_processes_priv_data *prv_data = NULL; 180266b0663SKrzysztof Zdziarski struct adf_processes_priv_data *pdata = NULL; 181266b0663SKrzysztof Zdziarski int dev_num = 0, pr_num = 0; 182266b0663SKrzysztof Zdziarski struct list_head *lpos = NULL; 183266b0663SKrzysztof Zdziarski char usr_name[ADF_CFG_MAX_SECTION_LEN_IN_BYTES] = { 0 }; 184266b0663SKrzysztof Zdziarski struct adf_accel_dev *accel_dev = NULL; 185266b0663SKrzysztof Zdziarski struct adf_cfg_section *section_ptr = NULL; 186266b0663SKrzysztof Zdziarski bool pr_name_available = 1; 187266b0663SKrzysztof Zdziarski uint32_t num_accel_devs = 0; 188266b0663SKrzysztof Zdziarski int error = 0; 189266b0663SKrzysztof Zdziarski ssize_t count; 190266b0663SKrzysztof Zdziarski int dev_id; 191266b0663SKrzysztof Zdziarski 192266b0663SKrzysztof Zdziarski error = devfs_get_cdevpriv((void **)&prv_data); 193266b0663SKrzysztof Zdziarski if (error) { 194266b0663SKrzysztof Zdziarski printf("QAT: invalid file descriptor\n"); 195266b0663SKrzysztof Zdziarski return error; 196266b0663SKrzysztof Zdziarski } 197266b0663SKrzysztof Zdziarski 198266b0663SKrzysztof Zdziarski if (prv_data->read_flag == 1) { 199266b0663SKrzysztof Zdziarski printf("QAT: can only write once\n"); 200266b0663SKrzysztof Zdziarski return EBADF; 201266b0663SKrzysztof Zdziarski } 202266b0663SKrzysztof Zdziarski count = uio->uio_resid; 203266b0663SKrzysztof Zdziarski if ((count <= 0) || (count > ADF_CFG_MAX_SECTION_LEN_IN_BYTES)) { 204266b0663SKrzysztof Zdziarski printf("QAT: wrong size %d\n", (int)count); 205266b0663SKrzysztof Zdziarski return EIO; 206266b0663SKrzysztof Zdziarski } 207266b0663SKrzysztof Zdziarski 208266b0663SKrzysztof Zdziarski error = uiomove(usr_name, count, uio); 209266b0663SKrzysztof Zdziarski if (error) { 210266b0663SKrzysztof Zdziarski printf("QAT: can't copy data\n"); 211266b0663SKrzysztof Zdziarski return error; 212266b0663SKrzysztof Zdziarski } 213266b0663SKrzysztof Zdziarski 214266b0663SKrzysztof Zdziarski /* Lock other processes and try to find out the process name */ 215266b0663SKrzysztof Zdziarski if (sx_xlock_sig(&processes_list_sema)) { 216266b0663SKrzysztof Zdziarski printf("QAT: can't aquire process info lock\n"); 217266b0663SKrzysztof Zdziarski return EBADF; 218266b0663SKrzysztof Zdziarski } 219266b0663SKrzysztof Zdziarski 220266b0663SKrzysztof Zdziarski dev_id = adf_get_first_started_dev(); 221266b0663SKrzysztof Zdziarski if (-1 == dev_id) { 222266b0663SKrzysztof Zdziarski pr_err("QAT: could not find started device\n"); 223266b0663SKrzysztof Zdziarski sx_xunlock(&processes_list_sema); 224266b0663SKrzysztof Zdziarski return -EIO; 225266b0663SKrzysztof Zdziarski } 226266b0663SKrzysztof Zdziarski 227266b0663SKrzysztof Zdziarski accel_dev = adf_devmgr_get_dev_by_id(dev_id); 228266b0663SKrzysztof Zdziarski if (!accel_dev) { 229266b0663SKrzysztof Zdziarski pr_err("QAT: could not find started device\n"); 230266b0663SKrzysztof Zdziarski sx_xunlock(&processes_list_sema); 231266b0663SKrzysztof Zdziarski return -EIO; 232266b0663SKrzysztof Zdziarski } 233266b0663SKrzysztof Zdziarski 234266b0663SKrzysztof Zdziarski /* If there is nothing there then take the first name and return */ 235266b0663SKrzysztof Zdziarski if (list_empty(&processes_list)) { 236266b0663SKrzysztof Zdziarski snprintf(prv_data->name, 237266b0663SKrzysztof Zdziarski ADF_CFG_MAX_SECTION_LEN_IN_BYTES, 238266b0663SKrzysztof Zdziarski "%s" ADF_INTERNAL_USERSPACE_SEC_SUFF "%d", 239266b0663SKrzysztof Zdziarski usr_name, 240266b0663SKrzysztof Zdziarski 0); 241266b0663SKrzysztof Zdziarski list_add(&prv_data->list, &processes_list); 242266b0663SKrzysztof Zdziarski sx_xunlock(&processes_list_sema); 243266b0663SKrzysztof Zdziarski prv_data->read_flag = 1; 244266b0663SKrzysztof Zdziarski return 0; 245266b0663SKrzysztof Zdziarski } 246266b0663SKrzysztof Zdziarski 247266b0663SKrzysztof Zdziarski /* If there are processes running then search for a first free name */ 248266b0663SKrzysztof Zdziarski adf_devmgr_get_num_dev(&num_accel_devs); 249266b0663SKrzysztof Zdziarski for (dev_num = 0; dev_num < num_accel_devs; dev_num++) { 250266b0663SKrzysztof Zdziarski accel_dev = adf_devmgr_get_dev_by_id(dev_num); 251266b0663SKrzysztof Zdziarski if (!accel_dev) 252266b0663SKrzysztof Zdziarski continue; 253266b0663SKrzysztof Zdziarski 254266b0663SKrzysztof Zdziarski if (!adf_dev_started(accel_dev)) 255266b0663SKrzysztof Zdziarski continue; /* to next device */ 256266b0663SKrzysztof Zdziarski 257266b0663SKrzysztof Zdziarski for (pr_num = 0; pr_num < GET_MAX_PROCESSES(accel_dev); 258266b0663SKrzysztof Zdziarski pr_num++) { 259266b0663SKrzysztof Zdziarski snprintf(prv_data->name, 260266b0663SKrzysztof Zdziarski ADF_CFG_MAX_SECTION_LEN_IN_BYTES, 261266b0663SKrzysztof Zdziarski "%s" ADF_INTERNAL_USERSPACE_SEC_SUFF "%d", 262266b0663SKrzysztof Zdziarski usr_name, 263266b0663SKrzysztof Zdziarski pr_num); 264266b0663SKrzysztof Zdziarski pr_name_available = 1; 265266b0663SKrzysztof Zdziarski /* Figure out if section exists in the config table */ 266266b0663SKrzysztof Zdziarski section_ptr = 267266b0663SKrzysztof Zdziarski adf_cfg_sec_find(accel_dev, prv_data->name); 268266b0663SKrzysztof Zdziarski if (NULL == section_ptr) { 269266b0663SKrzysztof Zdziarski /* This section name doesn't exist */ 270266b0663SKrzysztof Zdziarski pr_name_available = 0; 271266b0663SKrzysztof Zdziarski /* As process_num enumerates from 0, once we get 272266b0663SKrzysztof Zdziarski * to one which doesn't exist no further ones 273266b0663SKrzysztof Zdziarski * will exist. On to next device 274266b0663SKrzysztof Zdziarski */ 275266b0663SKrzysztof Zdziarski break; 276266b0663SKrzysztof Zdziarski } 277266b0663SKrzysztof Zdziarski /* Figure out if it's been taken already */ 278266b0663SKrzysztof Zdziarski list_for_each(lpos, &processes_list) 279266b0663SKrzysztof Zdziarski { 280266b0663SKrzysztof Zdziarski pdata = 281266b0663SKrzysztof Zdziarski list_entry(lpos, 282266b0663SKrzysztof Zdziarski struct adf_processes_priv_data, 283266b0663SKrzysztof Zdziarski list); 284266b0663SKrzysztof Zdziarski if (!strncmp( 285266b0663SKrzysztof Zdziarski pdata->name, 286266b0663SKrzysztof Zdziarski prv_data->name, 287266b0663SKrzysztof Zdziarski ADF_CFG_MAX_SECTION_LEN_IN_BYTES)) { 288266b0663SKrzysztof Zdziarski pr_name_available = 0; 289266b0663SKrzysztof Zdziarski break; 290266b0663SKrzysztof Zdziarski } 291266b0663SKrzysztof Zdziarski } 292266b0663SKrzysztof Zdziarski if (pr_name_available) 293266b0663SKrzysztof Zdziarski break; 294266b0663SKrzysztof Zdziarski } 295266b0663SKrzysztof Zdziarski if (pr_name_available) 296266b0663SKrzysztof Zdziarski break; 297266b0663SKrzysztof Zdziarski } 298266b0663SKrzysztof Zdziarski /* 299266b0663SKrzysztof Zdziarski * If we have a valid name that is not on 300266b0663SKrzysztof Zdziarski * the list take it and add to the list 301266b0663SKrzysztof Zdziarski */ 302266b0663SKrzysztof Zdziarski if (pr_name_available) { 303266b0663SKrzysztof Zdziarski list_add(&prv_data->list, &processes_list); 304266b0663SKrzysztof Zdziarski sx_xunlock(&processes_list_sema); 305266b0663SKrzysztof Zdziarski prv_data->read_flag = 1; 306266b0663SKrzysztof Zdziarski return 0; 307266b0663SKrzysztof Zdziarski } 308266b0663SKrzysztof Zdziarski /* If not then the process needs to wait */ 309266b0663SKrzysztof Zdziarski sx_xunlock(&processes_list_sema); 310266b0663SKrzysztof Zdziarski explicit_bzero(prv_data->name, ADF_CFG_MAX_SECTION_LEN_IN_BYTES); 311266b0663SKrzysztof Zdziarski prv_data->read_flag = 0; 312266b0663SKrzysztof Zdziarski return 1; 313266b0663SKrzysztof Zdziarski } 314266b0663SKrzysztof Zdziarski 315266b0663SKrzysztof Zdziarski static int 316266b0663SKrzysztof Zdziarski adf_processes_read(struct cdev *dev, struct uio *uio, int ioflag) 317266b0663SKrzysztof Zdziarski { 318266b0663SKrzysztof Zdziarski struct adf_processes_priv_data *prv_data = NULL; 319266b0663SKrzysztof Zdziarski int error = 0; 320266b0663SKrzysztof Zdziarski 321266b0663SKrzysztof Zdziarski error = devfs_get_cdevpriv((void **)&prv_data); 322266b0663SKrzysztof Zdziarski if (error) { 323266b0663SKrzysztof Zdziarski printf("QAT: invalid file descriptor\n"); 324266b0663SKrzysztof Zdziarski return error; 325266b0663SKrzysztof Zdziarski } 326266b0663SKrzysztof Zdziarski 327266b0663SKrzysztof Zdziarski /* 328266b0663SKrzysztof Zdziarski * If there is a name that the process can use then give it 329266b0663SKrzysztof Zdziarski * to the proocess. 330266b0663SKrzysztof Zdziarski */ 331266b0663SKrzysztof Zdziarski if (prv_data->read_flag) { 332266b0663SKrzysztof Zdziarski error = uiomove(prv_data->name, 333266b0663SKrzysztof Zdziarski strnlen(prv_data->name, 334266b0663SKrzysztof Zdziarski ADF_CFG_MAX_SECTION_LEN_IN_BYTES), 335266b0663SKrzysztof Zdziarski uio); 336266b0663SKrzysztof Zdziarski if (error) { 337266b0663SKrzysztof Zdziarski printf("QAT: failed to copy data to user\n"); 338266b0663SKrzysztof Zdziarski return error; 339266b0663SKrzysztof Zdziarski } 340266b0663SKrzysztof Zdziarski return 0; 341266b0663SKrzysztof Zdziarski } 342266b0663SKrzysztof Zdziarski 343266b0663SKrzysztof Zdziarski return EIO; 344266b0663SKrzysztof Zdziarski } 345266b0663SKrzysztof Zdziarski 346266b0663SKrzysztof Zdziarski static void 347266b0663SKrzysztof Zdziarski adf_processes_release(void *data) 348266b0663SKrzysztof Zdziarski { 349266b0663SKrzysztof Zdziarski struct adf_processes_priv_data *prv_data = NULL; 350266b0663SKrzysztof Zdziarski 351266b0663SKrzysztof Zdziarski prv_data = (struct adf_processes_priv_data *)data; 352266b0663SKrzysztof Zdziarski sx_xlock(&processes_list_sema); 353266b0663SKrzysztof Zdziarski list_del(&prv_data->list); 354266b0663SKrzysztof Zdziarski sx_xunlock(&processes_list_sema); 355266b0663SKrzysztof Zdziarski free(prv_data, M_QAT); 356266b0663SKrzysztof Zdziarski } 357266b0663SKrzysztof Zdziarski 358266b0663SKrzysztof Zdziarski int 359266b0663SKrzysztof Zdziarski adf_processes_dev_register(void) 360266b0663SKrzysztof Zdziarski { 361266b0663SKrzysztof Zdziarski return adf_chr_drv_create(); 362266b0663SKrzysztof Zdziarski } 363266b0663SKrzysztof Zdziarski 364266b0663SKrzysztof Zdziarski void 365266b0663SKrzysztof Zdziarski adf_processes_dev_unregister(void) 366266b0663SKrzysztof Zdziarski { 367266b0663SKrzysztof Zdziarski adf_chr_drv_destroy(); 368266b0663SKrzysztof Zdziarski } 369266b0663SKrzysztof Zdziarski 370266b0663SKrzysztof Zdziarski static void 371266b0663SKrzysztof Zdziarski adf_state_callout_notify_ev(void *arg) 372266b0663SKrzysztof Zdziarski { 373266b0663SKrzysztof Zdziarski int notified = 0; 374266b0663SKrzysztof Zdziarski struct adf_state_priv_data *priv = NULL; 375266b0663SKrzysztof Zdziarski struct entry_proc_events *proc_events = NULL; 376266b0663SKrzysztof Zdziarski 377266b0663SKrzysztof Zdziarski SLIST_FOREACH (proc_events, &proc_events_head, entries_proc_events) { 378266b0663SKrzysztof Zdziarski if (!STAILQ_EMPTY(&proc_events->proc_events->state_head)) { 379266b0663SKrzysztof Zdziarski notified = 1; 380266b0663SKrzysztof Zdziarski priv = proc_events->proc_events; 381266b0663SKrzysztof Zdziarski wakeup(priv); 382266b0663SKrzysztof Zdziarski selwakeup(&priv->rsel); 383266b0663SKrzysztof Zdziarski KNOTE_UNLOCKED(&priv->rsel.si_note, 0); 384266b0663SKrzysztof Zdziarski } 385266b0663SKrzysztof Zdziarski } 386266b0663SKrzysztof Zdziarski if (notified) 387266b0663SKrzysztof Zdziarski callout_schedule(&callout, ADF_STATE_CALLOUT_TIME); 388266b0663SKrzysztof Zdziarski } 389266b0663SKrzysztof Zdziarski 390266b0663SKrzysztof Zdziarski static void 391266b0663SKrzysztof Zdziarski adf_state_set(int dev, enum adf_event event) 392266b0663SKrzysztof Zdziarski { 393266b0663SKrzysztof Zdziarski struct adf_accel_dev *accel_dev = NULL; 394266b0663SKrzysztof Zdziarski struct state_head *head = NULL; 395266b0663SKrzysztof Zdziarski struct entry_proc_events *proc_events = NULL; 396266b0663SKrzysztof Zdziarski struct entry_state *state = NULL; 397266b0663SKrzysztof Zdziarski 398266b0663SKrzysztof Zdziarski accel_dev = adf_devmgr_get_dev_by_id(dev); 399266b0663SKrzysztof Zdziarski if (!accel_dev) 400266b0663SKrzysztof Zdziarski return; 401266b0663SKrzysztof Zdziarski mtx_lock(&mtx); 402266b0663SKrzysztof Zdziarski SLIST_FOREACH (proc_events, &proc_events_head, entries_proc_events) { 403266b0663SKrzysztof Zdziarski state = NULL; 404266b0663SKrzysztof Zdziarski head = &proc_events->proc_events->state_head; 405266b0663SKrzysztof Zdziarski state = malloc(sizeof(struct entry_state), 406266b0663SKrzysztof Zdziarski M_QAT, 407266b0663SKrzysztof Zdziarski M_NOWAIT | M_ZERO); 408266b0663SKrzysztof Zdziarski if (!state) 409266b0663SKrzysztof Zdziarski continue; 410266b0663SKrzysztof Zdziarski state->state.dev_state = event; 411266b0663SKrzysztof Zdziarski state->state.dev_id = dev; 412266b0663SKrzysztof Zdziarski STAILQ_INSERT_TAIL(head, state, entries_state); 413266b0663SKrzysztof Zdziarski if (event == ADF_EVENT_STOP) { 414266b0663SKrzysztof Zdziarski state = NULL; 415266b0663SKrzysztof Zdziarski state = malloc(sizeof(struct entry_state), 416266b0663SKrzysztof Zdziarski M_QAT, 417266b0663SKrzysztof Zdziarski M_NOWAIT | M_ZERO); 418266b0663SKrzysztof Zdziarski if (!state) 419266b0663SKrzysztof Zdziarski continue; 420266b0663SKrzysztof Zdziarski state->state.dev_state = ADF_EVENT_SHUTDOWN; 421266b0663SKrzysztof Zdziarski state->state.dev_id = dev; 422266b0663SKrzysztof Zdziarski STAILQ_INSERT_TAIL(head, state, entries_state); 423266b0663SKrzysztof Zdziarski } 424266b0663SKrzysztof Zdziarski } 425266b0663SKrzysztof Zdziarski mtx_unlock(&mtx); 42622cf89c9SPiotr Kasierski callout_schedule(&callout, ADF_STATE_CALLOUT_TIME); 427266b0663SKrzysztof Zdziarski } 428266b0663SKrzysztof Zdziarski 429266b0663SKrzysztof Zdziarski static int 430266b0663SKrzysztof Zdziarski adf_state_event_handler(struct adf_accel_dev *accel_dev, enum adf_event event) 431266b0663SKrzysztof Zdziarski { 432266b0663SKrzysztof Zdziarski int ret = 0; 433266b0663SKrzysztof Zdziarski 434266b0663SKrzysztof Zdziarski #if defined(QAT_UIO) && defined(QAT_DBG) 435266b0663SKrzysztof Zdziarski if (event > ADF_EVENT_DBG_SHUTDOWN) 436266b0663SKrzysztof Zdziarski return -EINVAL; 437266b0663SKrzysztof Zdziarski #else 438266b0663SKrzysztof Zdziarski if (event > ADF_EVENT_ERROR) 439266b0663SKrzysztof Zdziarski return -EINVAL; 440266b0663SKrzysztof Zdziarski #endif /* defined(QAT_UIO) && defined(QAT_DBG) */ 441266b0663SKrzysztof Zdziarski 442266b0663SKrzysztof Zdziarski switch (event) { 443266b0663SKrzysztof Zdziarski case ADF_EVENT_INIT: 444266b0663SKrzysztof Zdziarski return ret; 445266b0663SKrzysztof Zdziarski case ADF_EVENT_SHUTDOWN: 446266b0663SKrzysztof Zdziarski return ret; 447266b0663SKrzysztof Zdziarski case ADF_EVENT_RESTARTING: 448266b0663SKrzysztof Zdziarski break; 449266b0663SKrzysztof Zdziarski case ADF_EVENT_RESTARTED: 450266b0663SKrzysztof Zdziarski break; 451266b0663SKrzysztof Zdziarski case ADF_EVENT_START: 452266b0663SKrzysztof Zdziarski return ret; 453266b0663SKrzysztof Zdziarski case ADF_EVENT_STOP: 454266b0663SKrzysztof Zdziarski break; 455266b0663SKrzysztof Zdziarski case ADF_EVENT_ERROR: 456266b0663SKrzysztof Zdziarski break; 457266b0663SKrzysztof Zdziarski #if defined(QAT_UIO) && defined(QAT_DBG) 458266b0663SKrzysztof Zdziarski case ADF_EVENT_PROC_CRASH: 459266b0663SKrzysztof Zdziarski break; 460266b0663SKrzysztof Zdziarski case ADF_EVENT_MANUAL_DUMP: 461266b0663SKrzysztof Zdziarski break; 462266b0663SKrzysztof Zdziarski case ADF_EVENT_SLICE_HANG: 463266b0663SKrzysztof Zdziarski break; 464266b0663SKrzysztof Zdziarski case ADF_EVENT_DBG_SHUTDOWN: 465266b0663SKrzysztof Zdziarski break; 466266b0663SKrzysztof Zdziarski #endif /* defined(QAT_UIO) && defined(QAT_DBG) */ 467266b0663SKrzysztof Zdziarski default: 468266b0663SKrzysztof Zdziarski return -1; 469266b0663SKrzysztof Zdziarski } 470266b0663SKrzysztof Zdziarski 471266b0663SKrzysztof Zdziarski adf_state_set(accel_dev->accel_id, event); 472266b0663SKrzysztof Zdziarski 473266b0663SKrzysztof Zdziarski return 0; 474266b0663SKrzysztof Zdziarski } 475266b0663SKrzysztof Zdziarski 476266b0663SKrzysztof Zdziarski static int 477266b0663SKrzysztof Zdziarski adf_state_kqfilter(struct cdev *dev, struct knote *kn) 478266b0663SKrzysztof Zdziarski { 479266b0663SKrzysztof Zdziarski struct adf_state_priv_data *priv; 480266b0663SKrzysztof Zdziarski 481266b0663SKrzysztof Zdziarski mtx_lock(&mtx); 482266b0663SKrzysztof Zdziarski priv = dev->si_drv1; 483266b0663SKrzysztof Zdziarski switch (kn->kn_filter) { 484266b0663SKrzysztof Zdziarski case EVFILT_READ: 485266b0663SKrzysztof Zdziarski kn->kn_fop = &adf_state_read_filterops; 486266b0663SKrzysztof Zdziarski kn->kn_hook = priv; 48722cf89c9SPiotr Kasierski knlist_add(&priv->rsel.si_note, kn, 1); 488266b0663SKrzysztof Zdziarski mtx_unlock(&mtx); 489266b0663SKrzysztof Zdziarski return 0; 490266b0663SKrzysztof Zdziarski default: 491266b0663SKrzysztof Zdziarski mtx_unlock(&mtx); 492266b0663SKrzysztof Zdziarski return -EINVAL; 493266b0663SKrzysztof Zdziarski } 494266b0663SKrzysztof Zdziarski } 495266b0663SKrzysztof Zdziarski 496266b0663SKrzysztof Zdziarski static int 497266b0663SKrzysztof Zdziarski adf_state_kqread_event(struct knote *kn, long hint) 498266b0663SKrzysztof Zdziarski { 499266b0663SKrzysztof Zdziarski return 1; 500266b0663SKrzysztof Zdziarski } 501266b0663SKrzysztof Zdziarski 502266b0663SKrzysztof Zdziarski static void 503266b0663SKrzysztof Zdziarski adf_state_kqread_detach(struct knote *kn) 504266b0663SKrzysztof Zdziarski { 505266b0663SKrzysztof Zdziarski struct adf_state_priv_data *priv = NULL; 506266b0663SKrzysztof Zdziarski 507266b0663SKrzysztof Zdziarski mtx_lock(&mtx); 508266b0663SKrzysztof Zdziarski if (!kn) { 509266b0663SKrzysztof Zdziarski mtx_unlock(&mtx); 510266b0663SKrzysztof Zdziarski return; 511266b0663SKrzysztof Zdziarski } 512266b0663SKrzysztof Zdziarski priv = kn->kn_hook; 513266b0663SKrzysztof Zdziarski if (!priv) { 514266b0663SKrzysztof Zdziarski mtx_unlock(&mtx); 515266b0663SKrzysztof Zdziarski return; 516266b0663SKrzysztof Zdziarski } 517266b0663SKrzysztof Zdziarski knlist_remove(&priv->rsel.si_note, kn, 1); 518266b0663SKrzysztof Zdziarski mtx_unlock(&mtx); 519266b0663SKrzysztof Zdziarski } 520266b0663SKrzysztof Zdziarski 521266b0663SKrzysztof Zdziarski void 522266b0663SKrzysztof Zdziarski adf_state_init(void) 523266b0663SKrzysztof Zdziarski { 524266b0663SKrzysztof Zdziarski adf_state_dev = make_dev(&adf_state_cdevsw, 525266b0663SKrzysztof Zdziarski 0, 526266b0663SKrzysztof Zdziarski UID_ROOT, 527266b0663SKrzysztof Zdziarski GID_WHEEL, 528266b0663SKrzysztof Zdziarski 0600, 529266b0663SKrzysztof Zdziarski "%s", 530266b0663SKrzysztof Zdziarski ADF_DEV_STATE_NAME); 531266b0663SKrzysztof Zdziarski SLIST_INIT(&proc_events_head); 532266b0663SKrzysztof Zdziarski mtx_init(&mtx, mtx_name, NULL, MTX_DEF); 53322cf89c9SPiotr Kasierski mtx_init(&callout_mtx, mtx_callout_name, NULL, MTX_DEF); 53422cf89c9SPiotr Kasierski callout_init_mtx(&callout, &callout_mtx, 0); 535266b0663SKrzysztof Zdziarski explicit_bzero(&adf_state_hndl, sizeof(adf_state_hndl)); 536266b0663SKrzysztof Zdziarski adf_state_hndl.event_hld = adf_state_event_handler; 537266b0663SKrzysztof Zdziarski adf_state_hndl.name = "adf_state_event_handler"; 538266b0663SKrzysztof Zdziarski adf_service_register(&adf_state_hndl); 539266b0663SKrzysztof Zdziarski callout_reset(&callout, 540266b0663SKrzysztof Zdziarski ADF_STATE_CALLOUT_TIME, 541266b0663SKrzysztof Zdziarski adf_state_callout_notify_ev, 542266b0663SKrzysztof Zdziarski NULL); 543266b0663SKrzysztof Zdziarski } 544266b0663SKrzysztof Zdziarski 545266b0663SKrzysztof Zdziarski void 546266b0663SKrzysztof Zdziarski adf_state_destroy(void) 547266b0663SKrzysztof Zdziarski { 548266b0663SKrzysztof Zdziarski struct entry_proc_events *proc_events = NULL; 549266b0663SKrzysztof Zdziarski 550266b0663SKrzysztof Zdziarski adf_service_unregister(&adf_state_hndl); 55122cf89c9SPiotr Kasierski mtx_lock(&callout_mtx); 552266b0663SKrzysztof Zdziarski callout_stop(&callout); 55322cf89c9SPiotr Kasierski mtx_unlock(&callout_mtx); 55422cf89c9SPiotr Kasierski mtx_destroy(&callout_mtx); 55522cf89c9SPiotr Kasierski mtx_lock(&mtx); 556266b0663SKrzysztof Zdziarski while (!SLIST_EMPTY(&proc_events_head)) { 557266b0663SKrzysztof Zdziarski proc_events = SLIST_FIRST(&proc_events_head); 558266b0663SKrzysztof Zdziarski SLIST_REMOVE_HEAD(&proc_events_head, entries_proc_events); 559266b0663SKrzysztof Zdziarski free(proc_events, M_QAT); 560266b0663SKrzysztof Zdziarski } 561266b0663SKrzysztof Zdziarski mtx_unlock(&mtx); 562266b0663SKrzysztof Zdziarski mtx_destroy(&mtx); 56322cf89c9SPiotr Kasierski destroy_dev(adf_state_dev); 564266b0663SKrzysztof Zdziarski } 565266b0663SKrzysztof Zdziarski 566266b0663SKrzysztof Zdziarski static int 567266b0663SKrzysztof Zdziarski adf_state_open(struct cdev *dev, int oflags, int devtype, struct thread *td) 568266b0663SKrzysztof Zdziarski { 569266b0663SKrzysztof Zdziarski struct adf_state_priv_data *prv_data = NULL; 570266b0663SKrzysztof Zdziarski struct entry_proc_events *entry_proc_events = NULL; 571266b0663SKrzysztof Zdziarski int ret = 0; 572266b0663SKrzysztof Zdziarski 573266b0663SKrzysztof Zdziarski prv_data = malloc(sizeof(*prv_data), M_QAT, M_WAITOK | M_ZERO); 574266b0663SKrzysztof Zdziarski entry_proc_events = 575266b0663SKrzysztof Zdziarski malloc(sizeof(struct entry_proc_events), M_QAT, M_WAITOK | M_ZERO); 576266b0663SKrzysztof Zdziarski mtx_lock(&mtx); 577266b0663SKrzysztof Zdziarski prv_data->cdev = dev; 578266b0663SKrzysztof Zdziarski prv_data->cdev->si_drv1 = prv_data; 579266b0663SKrzysztof Zdziarski knlist_init_mtx(&prv_data->rsel.si_note, &mtx); 580266b0663SKrzysztof Zdziarski STAILQ_INIT(&prv_data->state_head); 581266b0663SKrzysztof Zdziarski entry_proc_events->proc_events = prv_data; 582266b0663SKrzysztof Zdziarski SLIST_INSERT_HEAD(&proc_events_head, 583266b0663SKrzysztof Zdziarski entry_proc_events, 584266b0663SKrzysztof Zdziarski entries_proc_events); 58522cf89c9SPiotr Kasierski mtx_unlock(&mtx); 586266b0663SKrzysztof Zdziarski ret = devfs_set_cdevpriv(prv_data, adf_state_release); 587266b0663SKrzysztof Zdziarski if (ret) { 588266b0663SKrzysztof Zdziarski SLIST_REMOVE(&proc_events_head, 589266b0663SKrzysztof Zdziarski entry_proc_events, 590266b0663SKrzysztof Zdziarski entry_proc_events, 591266b0663SKrzysztof Zdziarski entries_proc_events); 592266b0663SKrzysztof Zdziarski free(entry_proc_events, M_QAT); 593266b0663SKrzysztof Zdziarski free(prv_data, M_QAT); 594266b0663SKrzysztof Zdziarski } 595266b0663SKrzysztof Zdziarski callout_schedule(&callout, ADF_STATE_CALLOUT_TIME); 596266b0663SKrzysztof Zdziarski return ret; 597266b0663SKrzysztof Zdziarski } 598266b0663SKrzysztof Zdziarski 599266b0663SKrzysztof Zdziarski static int 600266b0663SKrzysztof Zdziarski adf_state_read(struct cdev *dev, struct uio *uio, int ioflag) 601266b0663SKrzysztof Zdziarski { 602266b0663SKrzysztof Zdziarski int ret = 0; 603266b0663SKrzysztof Zdziarski struct adf_state_priv_data *prv_data = NULL; 604266b0663SKrzysztof Zdziarski struct state_head *state_head = NULL; 605266b0663SKrzysztof Zdziarski struct entry_state *entry_state = NULL; 606266b0663SKrzysztof Zdziarski struct adf_state *state = NULL; 607266b0663SKrzysztof Zdziarski struct entry_proc_events *proc_events = NULL; 608266b0663SKrzysztof Zdziarski 609266b0663SKrzysztof Zdziarski mtx_lock(&mtx); 610266b0663SKrzysztof Zdziarski ret = devfs_get_cdevpriv((void **)&prv_data); 611266b0663SKrzysztof Zdziarski if (ret) { 612266b0663SKrzysztof Zdziarski mtx_unlock(&mtx); 613266b0663SKrzysztof Zdziarski return 0; 614266b0663SKrzysztof Zdziarski } 615266b0663SKrzysztof Zdziarski state_head = &prv_data->state_head; 616266b0663SKrzysztof Zdziarski if (STAILQ_EMPTY(state_head)) { 617266b0663SKrzysztof Zdziarski mtx_unlock(&mtx); 618266b0663SKrzysztof Zdziarski return 0; 619266b0663SKrzysztof Zdziarski } 620266b0663SKrzysztof Zdziarski entry_state = STAILQ_FIRST(state_head); 621266b0663SKrzysztof Zdziarski state = &entry_state->state; 622266b0663SKrzysztof Zdziarski ret = uiomove(state, sizeof(struct adf_state), uio); 623266b0663SKrzysztof Zdziarski if (!ret && !STAILQ_EMPTY(state_head)) { 624266b0663SKrzysztof Zdziarski STAILQ_REMOVE_HEAD(state_head, entries_state); 625266b0663SKrzysztof Zdziarski free(entry_state, M_QAT); 626266b0663SKrzysztof Zdziarski } 627266b0663SKrzysztof Zdziarski SLIST_FOREACH (proc_events, &proc_events_head, entries_proc_events) { 628266b0663SKrzysztof Zdziarski if (!STAILQ_EMPTY(&proc_events->proc_events->state_head)) { 629266b0663SKrzysztof Zdziarski prv_data = proc_events->proc_events; 630266b0663SKrzysztof Zdziarski wakeup(prv_data); 631266b0663SKrzysztof Zdziarski selwakeup(&prv_data->rsel); 632266b0663SKrzysztof Zdziarski KNOTE_UNLOCKED(&prv_data->rsel.si_note, 0); 633266b0663SKrzysztof Zdziarski } 634266b0663SKrzysztof Zdziarski } 635266b0663SKrzysztof Zdziarski mtx_unlock(&mtx); 63622cf89c9SPiotr Kasierski callout_schedule(&callout, ADF_STATE_CALLOUT_TIME); 637266b0663SKrzysztof Zdziarski return ret; 638266b0663SKrzysztof Zdziarski } 639266b0663SKrzysztof Zdziarski 640266b0663SKrzysztof Zdziarski static void 641266b0663SKrzysztof Zdziarski adf_state_release(void *data) 642266b0663SKrzysztof Zdziarski { 643266b0663SKrzysztof Zdziarski struct adf_state_priv_data *prv_data = NULL; 644266b0663SKrzysztof Zdziarski struct entry_state *entry_state = NULL; 645266b0663SKrzysztof Zdziarski struct entry_proc_events *entry_proc_events = NULL; 646266b0663SKrzysztof Zdziarski struct entry_proc_events *tmp = NULL; 647266b0663SKrzysztof Zdziarski 648266b0663SKrzysztof Zdziarski mtx_lock(&mtx); 649266b0663SKrzysztof Zdziarski prv_data = (struct adf_state_priv_data *)data; 650266b0663SKrzysztof Zdziarski knlist_delete(&prv_data->rsel.si_note, curthread, 1); 651266b0663SKrzysztof Zdziarski knlist_destroy(&prv_data->rsel.si_note); 652266b0663SKrzysztof Zdziarski seldrain(&prv_data->rsel); 653266b0663SKrzysztof Zdziarski while (!STAILQ_EMPTY(&prv_data->state_head)) { 654266b0663SKrzysztof Zdziarski entry_state = STAILQ_FIRST(&prv_data->state_head); 655266b0663SKrzysztof Zdziarski STAILQ_REMOVE_HEAD(&prv_data->state_head, entries_state); 656266b0663SKrzysztof Zdziarski free(entry_state, M_QAT); 657266b0663SKrzysztof Zdziarski } 658266b0663SKrzysztof Zdziarski SLIST_FOREACH_SAFE (entry_proc_events, 659266b0663SKrzysztof Zdziarski &proc_events_head, 660266b0663SKrzysztof Zdziarski entries_proc_events, 661266b0663SKrzysztof Zdziarski tmp) { 662266b0663SKrzysztof Zdziarski if (entry_proc_events->proc_events == prv_data) { 663266b0663SKrzysztof Zdziarski SLIST_REMOVE(&proc_events_head, 664266b0663SKrzysztof Zdziarski entry_proc_events, 665266b0663SKrzysztof Zdziarski entry_proc_events, 666266b0663SKrzysztof Zdziarski entries_proc_events); 667266b0663SKrzysztof Zdziarski free(entry_proc_events, M_QAT); 668266b0663SKrzysztof Zdziarski } 669266b0663SKrzysztof Zdziarski } 670266b0663SKrzysztof Zdziarski free(prv_data, M_QAT); 671266b0663SKrzysztof Zdziarski mtx_unlock(&mtx); 672266b0663SKrzysztof Zdziarski } 673