root/drivers/hid/intel-ish-hid/ishtp/client-buffers.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ishtp_cl_alloc_rx_ring
  2. ishtp_cl_alloc_tx_ring
  3. ishtp_cl_free_rx_ring
  4. ishtp_cl_free_tx_ring
  5. ishtp_io_rb_free
  6. ishtp_io_rb_init
  7. ishtp_io_rb_alloc_buf
  8. ishtp_cl_io_rb_recycle
  9. ishtp_cl_tx_empty
  10. ishtp_cl_rx_get_rb

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * ISHTP Ring Buffers
   4  *
   5  * Copyright (c) 2003-2016, Intel Corporation.
   6  */
   7 
   8 #include <linux/slab.h>
   9 #include "client.h"
  10 
  11 /**
  12  * ishtp_cl_alloc_rx_ring() - Allocate RX ring buffers
  13  * @cl: client device instance
  14  *
  15  * Allocate and initialize RX ring buffers
  16  *
  17  * Return: 0 on success else -ENOMEM
  18  */
  19 int ishtp_cl_alloc_rx_ring(struct ishtp_cl *cl)
  20 {
  21         size_t  len = cl->device->fw_client->props.max_msg_length;
  22         int     j;
  23         struct ishtp_cl_rb *rb;
  24         int     ret = 0;
  25         unsigned long   flags;
  26 
  27         for (j = 0; j < cl->rx_ring_size; ++j) {
  28                 rb = ishtp_io_rb_init(cl);
  29                 if (!rb) {
  30                         ret = -ENOMEM;
  31                         goto out;
  32                 }
  33                 ret = ishtp_io_rb_alloc_buf(rb, len);
  34                 if (ret)
  35                         goto out;
  36                 spin_lock_irqsave(&cl->free_list_spinlock, flags);
  37                 list_add_tail(&rb->list, &cl->free_rb_list.list);
  38                 spin_unlock_irqrestore(&cl->free_list_spinlock, flags);
  39         }
  40 
  41         return  0;
  42 
  43 out:
  44         dev_err(&cl->device->dev, "error in allocating Rx buffers\n");
  45         ishtp_cl_free_rx_ring(cl);
  46         return  ret;
  47 }
  48 
  49 /**
  50  * ishtp_cl_alloc_tx_ring() - Allocate TX ring buffers
  51  * @cl: client device instance
  52  *
  53  * Allocate and initialize TX ring buffers
  54  *
  55  * Return: 0 on success else -ENOMEM
  56  */
  57 int ishtp_cl_alloc_tx_ring(struct ishtp_cl *cl)
  58 {
  59         size_t  len = cl->device->fw_client->props.max_msg_length;
  60         int     j;
  61         unsigned long   flags;
  62 
  63         cl->tx_ring_free_size = 0;
  64 
  65         /* Allocate pool to free Tx bufs */
  66         for (j = 0; j < cl->tx_ring_size; ++j) {
  67                 struct ishtp_cl_tx_ring *tx_buf;
  68 
  69                 tx_buf = kzalloc(sizeof(struct ishtp_cl_tx_ring), GFP_KERNEL);
  70                 if (!tx_buf)
  71                         goto    out;
  72 
  73                 tx_buf->send_buf.data = kmalloc(len, GFP_KERNEL);
  74                 if (!tx_buf->send_buf.data) {
  75                         kfree(tx_buf);
  76                         goto    out;
  77                 }
  78 
  79                 spin_lock_irqsave(&cl->tx_free_list_spinlock, flags);
  80                 list_add_tail(&tx_buf->list, &cl->tx_free_list.list);
  81                 ++cl->tx_ring_free_size;
  82                 spin_unlock_irqrestore(&cl->tx_free_list_spinlock, flags);
  83         }
  84         return  0;
  85 out:
  86         dev_err(&cl->device->dev, "error in allocating Tx pool\n");
  87         ishtp_cl_free_tx_ring(cl);
  88         return  -ENOMEM;
  89 }
  90 
  91 /**
  92  * ishtp_cl_free_rx_ring() - Free RX ring buffers
  93  * @cl: client device instance
  94  *
  95  * Free RX ring buffers
  96  */
  97 void ishtp_cl_free_rx_ring(struct ishtp_cl *cl)
  98 {
  99         struct ishtp_cl_rb *rb;
 100         unsigned long   flags;
 101 
 102         /* release allocated memory - pass over free_rb_list */
 103         spin_lock_irqsave(&cl->free_list_spinlock, flags);
 104         while (!list_empty(&cl->free_rb_list.list)) {
 105                 rb = list_entry(cl->free_rb_list.list.next, struct ishtp_cl_rb,
 106                                 list);
 107                 list_del(&rb->list);
 108                 kfree(rb->buffer.data);
 109                 kfree(rb);
 110         }
 111         spin_unlock_irqrestore(&cl->free_list_spinlock, flags);
 112         /* release allocated memory - pass over in_process_list */
 113         spin_lock_irqsave(&cl->in_process_spinlock, flags);
 114         while (!list_empty(&cl->in_process_list.list)) {
 115                 rb = list_entry(cl->in_process_list.list.next,
 116                                 struct ishtp_cl_rb, list);
 117                 list_del(&rb->list);
 118                 kfree(rb->buffer.data);
 119                 kfree(rb);
 120         }
 121         spin_unlock_irqrestore(&cl->in_process_spinlock, flags);
 122 }
 123 
 124 /**
 125  * ishtp_cl_free_tx_ring() - Free TX ring buffers
 126  * @cl: client device instance
 127  *
 128  * Free TX ring buffers
 129  */
 130 void ishtp_cl_free_tx_ring(struct ishtp_cl *cl)
 131 {
 132         struct ishtp_cl_tx_ring *tx_buf;
 133         unsigned long   flags;
 134 
 135         spin_lock_irqsave(&cl->tx_free_list_spinlock, flags);
 136         /* release allocated memory - pass over tx_free_list */
 137         while (!list_empty(&cl->tx_free_list.list)) {
 138                 tx_buf = list_entry(cl->tx_free_list.list.next,
 139                                     struct ishtp_cl_tx_ring, list);
 140                 list_del(&tx_buf->list);
 141                 --cl->tx_ring_free_size;
 142                 kfree(tx_buf->send_buf.data);
 143                 kfree(tx_buf);
 144         }
 145         spin_unlock_irqrestore(&cl->tx_free_list_spinlock, flags);
 146 
 147         spin_lock_irqsave(&cl->tx_list_spinlock, flags);
 148         /* release allocated memory - pass over tx_list */
 149         while (!list_empty(&cl->tx_list.list)) {
 150                 tx_buf = list_entry(cl->tx_list.list.next,
 151                                     struct ishtp_cl_tx_ring, list);
 152                 list_del(&tx_buf->list);
 153                 kfree(tx_buf->send_buf.data);
 154                 kfree(tx_buf);
 155         }
 156         spin_unlock_irqrestore(&cl->tx_list_spinlock, flags);
 157 }
 158 
 159 /**
 160  * ishtp_io_rb_free() - Free IO request block
 161  * @rb: IO request block
 162  *
 163  * Free io request block memory
 164  */
 165 void ishtp_io_rb_free(struct ishtp_cl_rb *rb)
 166 {
 167         if (rb == NULL)
 168                 return;
 169 
 170         kfree(rb->buffer.data);
 171         kfree(rb);
 172 }
 173 
 174 /**
 175  * ishtp_io_rb_init() - Allocate and init IO request block
 176  * @cl: client device instance
 177  *
 178  * Allocate and initialize request block
 179  *
 180  * Return: Allocted IO request block pointer
 181  */
 182 struct ishtp_cl_rb *ishtp_io_rb_init(struct ishtp_cl *cl)
 183 {
 184         struct ishtp_cl_rb *rb;
 185 
 186         rb = kzalloc(sizeof(struct ishtp_cl_rb), GFP_KERNEL);
 187         if (!rb)
 188                 return NULL;
 189 
 190         INIT_LIST_HEAD(&rb->list);
 191         rb->cl = cl;
 192         rb->buf_idx = 0;
 193         return rb;
 194 }
 195 
 196 /**
 197  * ishtp_io_rb_alloc_buf() - Allocate and init response buffer
 198  * @rb: IO request block
 199  * @length: length of response buffer
 200  *
 201  * Allocate respose buffer
 202  *
 203  * Return: 0 on success else -ENOMEM
 204  */
 205 int ishtp_io_rb_alloc_buf(struct ishtp_cl_rb *rb, size_t length)
 206 {
 207         if (!rb)
 208                 return -EINVAL;
 209 
 210         if (length == 0)
 211                 return 0;
 212 
 213         rb->buffer.data = kmalloc(length, GFP_KERNEL);
 214         if (!rb->buffer.data)
 215                 return -ENOMEM;
 216 
 217         rb->buffer.size = length;
 218         return 0;
 219 }
 220 
 221 /**
 222  * ishtp_cl_io_rb_recycle() - Recycle IO request blocks
 223  * @rb: IO request block
 224  *
 225  * Re-append rb to its client's free list and send flow control if needed
 226  *
 227  * Return: 0 on success else -EFAULT
 228  */
 229 int ishtp_cl_io_rb_recycle(struct ishtp_cl_rb *rb)
 230 {
 231         struct ishtp_cl *cl;
 232         int     rets = 0;
 233         unsigned long   flags;
 234 
 235         if (!rb || !rb->cl)
 236                 return  -EFAULT;
 237 
 238         cl = rb->cl;
 239         spin_lock_irqsave(&cl->free_list_spinlock, flags);
 240         list_add_tail(&rb->list, &cl->free_rb_list.list);
 241         spin_unlock_irqrestore(&cl->free_list_spinlock, flags);
 242 
 243         /*
 244          * If we returned the first buffer to empty 'free' list,
 245          * send flow control
 246          */
 247         if (!cl->out_flow_ctrl_creds)
 248                 rets = ishtp_cl_read_start(cl);
 249 
 250         return  rets;
 251 }
 252 EXPORT_SYMBOL(ishtp_cl_io_rb_recycle);
 253 
 254 /**
 255  * ishtp_cl_tx_empty() -test whether client device tx buffer is empty
 256  * @cl: Pointer to client device instance
 257  *
 258  * Look client device tx buffer list, and check whether this list is empty
 259  *
 260  * Return: true if client tx buffer list is empty else false
 261  */
 262 bool ishtp_cl_tx_empty(struct ishtp_cl *cl)
 263 {
 264         int tx_list_empty;
 265         unsigned long tx_flags;
 266 
 267         spin_lock_irqsave(&cl->tx_list_spinlock, tx_flags);
 268         tx_list_empty = list_empty(&cl->tx_list.list);
 269         spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags);
 270 
 271         return !!tx_list_empty;
 272 }
 273 EXPORT_SYMBOL(ishtp_cl_tx_empty);
 274 
 275 /**
 276  * ishtp_cl_rx_get_rb() -Get a rb from client device rx buffer list
 277  * @cl: Pointer to client device instance
 278  *
 279  * Check client device in-processing buffer list and get a rb from it.
 280  *
 281  * Return: rb pointer if buffer list isn't empty else NULL
 282  */
 283 struct ishtp_cl_rb *ishtp_cl_rx_get_rb(struct ishtp_cl *cl)
 284 {
 285         unsigned long rx_flags;
 286         struct ishtp_cl_rb *rb;
 287 
 288         spin_lock_irqsave(&cl->in_process_spinlock, rx_flags);
 289         rb = list_first_entry_or_null(&cl->in_process_list.list,
 290                                 struct ishtp_cl_rb, list);
 291         if (rb)
 292                 list_del_init(&rb->list);
 293         spin_unlock_irqrestore(&cl->in_process_spinlock, rx_flags);
 294 
 295         return rb;
 296 }
 297 EXPORT_SYMBOL(ishtp_cl_rx_get_rb);

/* [<][>][^][v][top][bottom][index][help] */