Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2015-2021, Linaro Limited
0004  */
0005 
0006 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0007 
0008 #include <linux/arm-smccc.h>
0009 #include <linux/errno.h>
0010 #include <linux/slab.h>
0011 #include <linux/spinlock.h>
0012 #include <linux/tee_drv.h>
0013 #include "optee_private.h"
0014 
0015 struct notif_entry {
0016     struct list_head link;
0017     struct completion c;
0018     u_int key;
0019 };
0020 
0021 static bool have_key(struct optee *optee, u_int key)
0022 {
0023     struct notif_entry *entry;
0024 
0025     list_for_each_entry(entry, &optee->notif.db, link)
0026         if (entry->key == key)
0027             return true;
0028 
0029     return false;
0030 }
0031 
0032 int optee_notif_wait(struct optee *optee, u_int key)
0033 {
0034     unsigned long flags;
0035     struct notif_entry *entry;
0036     int rc = 0;
0037 
0038     if (key > optee->notif.max_key)
0039         return -EINVAL;
0040 
0041     entry = kmalloc(sizeof(*entry), GFP_KERNEL);
0042     if (!entry)
0043         return -ENOMEM;
0044     init_completion(&entry->c);
0045     entry->key = key;
0046 
0047     spin_lock_irqsave(&optee->notif.lock, flags);
0048 
0049     /*
0050      * If the bit is already set it means that the key has already
0051      * been posted and we must not wait.
0052      */
0053     if (test_bit(key, optee->notif.bitmap)) {
0054         clear_bit(key, optee->notif.bitmap);
0055         goto out;
0056     }
0057 
0058     /*
0059      * Check if someone is already waiting for this key. If there is
0060      * it's a programming error.
0061      */
0062     if (have_key(optee, key)) {
0063         rc = -EBUSY;
0064         goto out;
0065     }
0066 
0067     list_add_tail(&entry->link, &optee->notif.db);
0068 
0069     /*
0070      * Unlock temporarily and wait for completion.
0071      */
0072     spin_unlock_irqrestore(&optee->notif.lock, flags);
0073     wait_for_completion(&entry->c);
0074     spin_lock_irqsave(&optee->notif.lock, flags);
0075 
0076     list_del(&entry->link);
0077 out:
0078     spin_unlock_irqrestore(&optee->notif.lock, flags);
0079 
0080     kfree(entry);
0081 
0082     return rc;
0083 }
0084 
0085 int optee_notif_send(struct optee *optee, u_int key)
0086 {
0087     unsigned long flags;
0088     struct notif_entry *entry;
0089 
0090     if (key > optee->notif.max_key)
0091         return -EINVAL;
0092 
0093     spin_lock_irqsave(&optee->notif.lock, flags);
0094 
0095     list_for_each_entry(entry, &optee->notif.db, link)
0096         if (entry->key == key) {
0097             complete(&entry->c);
0098             goto out;
0099         }
0100 
0101     /* Only set the bit in case there where nobody waiting */
0102     set_bit(key, optee->notif.bitmap);
0103 out:
0104     spin_unlock_irqrestore(&optee->notif.lock, flags);
0105 
0106     return 0;
0107 }
0108 
0109 int optee_notif_init(struct optee *optee, u_int max_key)
0110 {
0111     spin_lock_init(&optee->notif.lock);
0112     INIT_LIST_HEAD(&optee->notif.db);
0113     optee->notif.bitmap = bitmap_zalloc(max_key, GFP_KERNEL);
0114     if (!optee->notif.bitmap)
0115         return -ENOMEM;
0116 
0117     optee->notif.max_key = max_key;
0118 
0119     return 0;
0120 }
0121 
0122 void optee_notif_uninit(struct optee *optee)
0123 {
0124     bitmap_free(optee->notif.bitmap);
0125 }