~ubuntu-branches/debian/wheezy/linux-2.6/wheezy

« back to all changes in this revision

Viewing changes to drivers/staging/tidspbridge/core/msg_sm.c

  • Committer: Bazaar Package Importer
  • Author(s): Ben Hutchings, Ben Hutchings, Aurelien Jarno
  • Date: 2011-06-07 12:14:05 UTC
  • mfrom: (43.1.9 sid)
  • Revision ID: james.westby@ubuntu.com-20110607121405-i3h1rd7nrnd2b73h
Tags: 2.6.39-2
[ Ben Hutchings ]
* [x86] Enable BACKLIGHT_APPLE, replacing BACKLIGHT_MBP_NVIDIA
  (Closes: #627492)
* cgroups: Disable memory resource controller by default. Allow it
  to be enabled using kernel parameter 'cgroup_enable=memory'.
* rt2800usb: Enable support for more USB devices including
  Linksys WUSB600N (Closes: #596626) (this change was accidentally
  omitted from 2.6.39-1)
* [x86] Remove Celeron from list of processors supporting PAE. Most
  'Celeron M' models do not.
* Update debconf template translations:
  - Swedish (Martin Bagge) (Closes: #628932)
  - French (David Prévot) (Closes: #628191)
* aufs: Update for 2.6.39 (Closes: #627837)
* Add stable 2.6.39.1, including:
  - ext4: dont set PageUptodate in ext4_end_bio()
  - pata_cmd64x: fix boot crash on parisc (Closes: #622997, #622745)
  - ext3: Fix fs corruption when make_indexed_dir() fails
  - netfilter: nf_ct_sip: validate Content-Length in TCP SIP messages
  - sctp: fix race between sctp_bind_addr_free() and
    sctp_bind_addr_conflict()
  - sctp: fix memory leak of the ASCONF queue when free asoc
  - md/bitmap: fix saving of events_cleared and other state
  - cdc_acm: Fix oops when Droids MuIn LCD is connected
  - cx88: Fix conversion from BKL to fine-grained locks (Closes: #619827)
  - keys: Set cred->user_ns in key_replace_session_keyring (CVE-2011-2184)
  - tmpfs: fix race between truncate and writepage
  - nfs41: Correct offset for LAYOUTCOMMIT
  - xen/mmu: fix a race window causing leave_mm BUG()
  - ext4: fix possible use-after-free in ext4_remove_li_request()
  For the complete list of changes, see:
   http://www.kernel.org/pub/linux/kernel/v2.6/ChangeLog-2.6.39.1
* Bump ABI to 2
* netfilter: Enable IP_SET, IP_SET_BITMAP_IP, IP_SET_BITMAP_IPMAC,
  IP_SET_BITMAP_PORT, IP_SET_HASH_IP, IP_SET_HASH_IPPORT,
  IP_SET_HASH_IPPORTIP, IP_SET_HASH_IPPORTNET, IP_SET_HASH_NET,
  IP_SET_HASH_NETPORT, IP_SET_LIST_SET, NETFILTER_XT_SET as modules
  (Closes: #629401)

[ Aurelien Jarno ]
* [mipsel/loongson-2f] Disable_SCSI_LPFC to workaround GCC ICE.

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
#include <dspbridge/dbc.h>
25
25
 
26
26
/*  ----------------------------------- OS Adaptation Layer */
27
 
#include <dspbridge/list.h>
28
27
#include <dspbridge/sync.h>
29
28
 
30
29
/*  ----------------------------------- Platform Manager */
38
37
#include <dspbridge/dspmsg.h>
39
38
 
40
39
/*  ----------------------------------- Function Prototypes */
41
 
static int add_new_msg(struct lst_list *msg_list);
 
40
static int add_new_msg(struct list_head *msg_list);
42
41
static void delete_msg_mgr(struct msg_mgr *hmsg_mgr);
43
42
static void delete_msg_queue(struct msg_queue *msg_queue_obj, u32 num_to_dsp);
44
 
static void free_msg_list(struct lst_list *msg_list);
 
43
static void free_msg_list(struct list_head *msg_list);
45
44
 
46
45
/*
47
46
 *  ======== bridge_msg_create ========
56
55
        struct io_mgr *hio_mgr;
57
56
        int status = 0;
58
57
 
59
 
        if (!msg_man || !msg_callback || !hdev_obj) {
60
 
                status = -EFAULT;
61
 
                goto func_end;
62
 
        }
 
58
        if (!msg_man || !msg_callback || !hdev_obj)
 
59
                return -EFAULT;
 
60
 
63
61
        dev_get_io_mgr(hdev_obj, &hio_mgr);
64
 
        if (!hio_mgr) {
65
 
                status = -EFAULT;
66
 
                goto func_end;
67
 
        }
 
62
        if (!hio_mgr)
 
63
                return -EFAULT;
 
64
 
68
65
        *msg_man = NULL;
69
66
        /* Allocate msg_ctrl manager object */
70
67
        msg_mgr_obj = kzalloc(sizeof(struct msg_mgr), GFP_KERNEL);
71
 
 
72
 
        if (msg_mgr_obj) {
73
 
                msg_mgr_obj->on_exit = msg_callback;
74
 
                msg_mgr_obj->hio_mgr = hio_mgr;
75
 
                /* List of MSG_QUEUEs */
76
 
                msg_mgr_obj->queue_list = kzalloc(sizeof(struct lst_list),
77
 
                                                        GFP_KERNEL);
78
 
                /*  Queues of message frames for messages to the DSP. Message
79
 
                 * frames will only be added to the free queue when a
80
 
                 * msg_queue object is created. */
81
 
                msg_mgr_obj->msg_free_list = kzalloc(sizeof(struct lst_list),
82
 
                                                        GFP_KERNEL);
83
 
                msg_mgr_obj->msg_used_list = kzalloc(sizeof(struct lst_list),
84
 
                                                        GFP_KERNEL);
85
 
                if (msg_mgr_obj->queue_list == NULL ||
86
 
                    msg_mgr_obj->msg_free_list == NULL ||
87
 
                    msg_mgr_obj->msg_used_list == NULL) {
88
 
                        status = -ENOMEM;
89
 
                } else {
90
 
                        INIT_LIST_HEAD(&msg_mgr_obj->queue_list->head);
91
 
                        INIT_LIST_HEAD(&msg_mgr_obj->msg_free_list->head);
92
 
                        INIT_LIST_HEAD(&msg_mgr_obj->msg_used_list->head);
93
 
                        spin_lock_init(&msg_mgr_obj->msg_mgr_lock);
94
 
                }
95
 
 
96
 
                /*  Create an event to be used by bridge_msg_put() in waiting
97
 
                 *  for an available free frame from the message manager. */
98
 
                msg_mgr_obj->sync_event =
99
 
                                kzalloc(sizeof(struct sync_object), GFP_KERNEL);
100
 
                if (!msg_mgr_obj->sync_event)
101
 
                        status = -ENOMEM;
102
 
                else
103
 
                        sync_init_event(msg_mgr_obj->sync_event);
104
 
 
105
 
                if (!status)
106
 
                        *msg_man = msg_mgr_obj;
107
 
                else
108
 
                        delete_msg_mgr(msg_mgr_obj);
109
 
 
110
 
        } else {
111
 
                status = -ENOMEM;
 
68
        if (!msg_mgr_obj)
 
69
                return -ENOMEM;
 
70
 
 
71
        msg_mgr_obj->on_exit = msg_callback;
 
72
        msg_mgr_obj->iomgr = hio_mgr;
 
73
        /* List of MSG_QUEUEs */
 
74
        INIT_LIST_HEAD(&msg_mgr_obj->queue_list);
 
75
        /*
 
76
         * Queues of message frames for messages to the DSP. Message
 
77
         * frames will only be added to the free queue when a
 
78
         * msg_queue object is created.
 
79
         */
 
80
        INIT_LIST_HEAD(&msg_mgr_obj->msg_free_list);
 
81
        INIT_LIST_HEAD(&msg_mgr_obj->msg_used_list);
 
82
        spin_lock_init(&msg_mgr_obj->msg_mgr_lock);
 
83
 
 
84
        /*
 
85
         * Create an event to be used by bridge_msg_put() in waiting
 
86
         * for an available free frame from the message manager.
 
87
         */
 
88
        msg_mgr_obj->sync_event =
 
89
                kzalloc(sizeof(struct sync_object), GFP_KERNEL);
 
90
        if (!msg_mgr_obj->sync_event) {
 
91
                kfree(msg_mgr_obj);
 
92
                return -ENOMEM;
112
93
        }
113
 
func_end:
 
94
        sync_init_event(msg_mgr_obj->sync_event);
 
95
 
 
96
        *msg_man = msg_mgr_obj;
 
97
 
114
98
        return status;
115
99
}
116
100
 
119
103
 *      Create a msg_queue for sending/receiving messages to/from a node
120
104
 *      on the DSP.
121
105
 */
122
 
int bridge_msg_create_queue(struct msg_mgr *hmsg_mgr,
123
 
                                struct msg_queue **msgq,
 
106
int bridge_msg_create_queue(struct msg_mgr *hmsg_mgr, struct msg_queue **msgq,
124
107
                                u32 msgq_id, u32 max_msgs, void *arg)
125
108
{
126
109
        u32 i;
128
111
        struct msg_queue *msg_q;
129
112
        int status = 0;
130
113
 
131
 
        if (!hmsg_mgr || msgq == NULL || !hmsg_mgr->msg_free_list) {
132
 
                status = -EFAULT;
133
 
                goto func_end;
134
 
        }
 
114
        if (!hmsg_mgr || msgq == NULL)
 
115
                return -EFAULT;
135
116
 
136
117
        *msgq = NULL;
137
118
        /* Allocate msg_queue object */
138
119
        msg_q = kzalloc(sizeof(struct msg_queue), GFP_KERNEL);
139
 
        if (!msg_q) {
140
 
                status = -ENOMEM;
141
 
                goto func_end;
142
 
        }
143
 
        lst_init_elem((struct list_head *)msg_q);
 
120
        if (!msg_q)
 
121
                return -ENOMEM;
 
122
 
144
123
        msg_q->max_msgs = max_msgs;
145
 
        msg_q->hmsg_mgr = hmsg_mgr;
 
124
        msg_q->msg_mgr = hmsg_mgr;
146
125
        msg_q->arg = arg;       /* Node handle */
147
126
        msg_q->msgq_id = msgq_id;       /* Node env (not valid yet) */
148
127
        /* Queues of Message frames for messages from the DSP */
149
 
        msg_q->msg_free_list = kzalloc(sizeof(struct lst_list), GFP_KERNEL);
150
 
        msg_q->msg_used_list = kzalloc(sizeof(struct lst_list), GFP_KERNEL);
151
 
        if (msg_q->msg_free_list == NULL || msg_q->msg_used_list == NULL)
152
 
                status = -ENOMEM;
153
 
        else {
154
 
                INIT_LIST_HEAD(&msg_q->msg_free_list->head);
155
 
                INIT_LIST_HEAD(&msg_q->msg_used_list->head);
156
 
        }
 
128
        INIT_LIST_HEAD(&msg_q->msg_free_list);
 
129
        INIT_LIST_HEAD(&msg_q->msg_used_list);
157
130
 
158
131
        /*  Create event that will be signalled when a message from
159
132
         *  the DSP is available. */
160
 
        if (!status) {
161
 
                msg_q->sync_event = kzalloc(sizeof(struct sync_object),
162
 
                                                        GFP_KERNEL);
163
 
                if (msg_q->sync_event)
164
 
                        sync_init_event(msg_q->sync_event);
165
 
                else
166
 
                        status = -ENOMEM;
 
133
        msg_q->sync_event = kzalloc(sizeof(struct sync_object), GFP_KERNEL);
 
134
        if (!msg_q->sync_event) {
 
135
                status = -ENOMEM;
 
136
                goto out_err;
 
137
 
167
138
        }
 
139
        sync_init_event(msg_q->sync_event);
168
140
 
169
141
        /* Create a notification list for message ready notification. */
170
 
        if (!status) {
171
 
                msg_q->ntfy_obj = kmalloc(sizeof(struct ntfy_object),
172
 
                                                        GFP_KERNEL);
173
 
                if (msg_q->ntfy_obj)
174
 
                        ntfy_init(msg_q->ntfy_obj);
175
 
                else
176
 
                        status = -ENOMEM;
 
142
        msg_q->ntfy_obj = kmalloc(sizeof(struct ntfy_object), GFP_KERNEL);
 
143
        if (!msg_q->ntfy_obj) {
 
144
                status = -ENOMEM;
 
145
                goto out_err;
177
146
        }
 
147
        ntfy_init(msg_q->ntfy_obj);
178
148
 
179
149
        /*  Create events that will be used to synchronize cleanup
180
150
         *  when the object is deleted. sync_done will be set to
181
151
         *  unblock threads in MSG_Put() or MSG_Get(). sync_done_ack
182
152
         *  will be set by the unblocked thread to signal that it
183
153
         *  is unblocked and will no longer reference the object. */
184
 
        if (!status) {
185
 
                msg_q->sync_done = kzalloc(sizeof(struct sync_object),
186
 
                                                        GFP_KERNEL);
187
 
                if (msg_q->sync_done)
188
 
                        sync_init_event(msg_q->sync_done);
189
 
                else
190
 
                        status = -ENOMEM;
191
 
        }
192
 
 
193
 
        if (!status) {
194
 
                msg_q->sync_done_ack = kzalloc(sizeof(struct sync_object),
195
 
                                                        GFP_KERNEL);
196
 
                if (msg_q->sync_done_ack)
197
 
                        sync_init_event(msg_q->sync_done_ack);
198
 
                else
199
 
                        status = -ENOMEM;
200
 
        }
201
 
 
202
 
        if (!status) {
203
 
                /* Enter critical section */
204
 
                spin_lock_bh(&hmsg_mgr->msg_mgr_lock);
205
 
                /* Initialize message frames and put in appropriate queues */
206
 
                for (i = 0; i < max_msgs && !status; i++) {
207
 
                        status = add_new_msg(hmsg_mgr->msg_free_list);
208
 
                        if (!status) {
209
 
                                num_allocated++;
210
 
                                status = add_new_msg(msg_q->msg_free_list);
211
 
                        }
212
 
                }
213
 
                if (status) {
214
 
                        /*  Stay inside CS to prevent others from taking any
215
 
                         *  of the newly allocated message frames. */
216
 
                        delete_msg_queue(msg_q, num_allocated);
217
 
                } else {
218
 
                        lst_put_tail(hmsg_mgr->queue_list,
219
 
                                     (struct list_head *)msg_q);
220
 
                        *msgq = msg_q;
221
 
                        /* Signal that free frames are now available */
222
 
                        if (!LST_IS_EMPTY(hmsg_mgr->msg_free_list))
223
 
                                sync_set_event(hmsg_mgr->sync_event);
224
 
 
225
 
                }
226
 
                /* Exit critical section */
 
154
        msg_q->sync_done = kzalloc(sizeof(struct sync_object), GFP_KERNEL);
 
155
        if (!msg_q->sync_done) {
 
156
                status = -ENOMEM;
 
157
                goto out_err;
 
158
        }
 
159
        sync_init_event(msg_q->sync_done);
 
160
 
 
161
        msg_q->sync_done_ack = kzalloc(sizeof(struct sync_object), GFP_KERNEL);
 
162
        if (!msg_q->sync_done_ack) {
 
163
                status = -ENOMEM;
 
164
                goto out_err;
 
165
        }
 
166
        sync_init_event(msg_q->sync_done_ack);
 
167
 
 
168
        /* Enter critical section */
 
169
        spin_lock_bh(&hmsg_mgr->msg_mgr_lock);
 
170
        /* Initialize message frames and put in appropriate queues */
 
171
        for (i = 0; i < max_msgs && !status; i++) {
 
172
                status = add_new_msg(&hmsg_mgr->msg_free_list);
 
173
                if (!status) {
 
174
                        num_allocated++;
 
175
                        status = add_new_msg(&msg_q->msg_free_list);
 
176
                }
 
177
        }
 
178
        if (status) {
227
179
                spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
228
 
        } else {
229
 
                delete_msg_queue(msg_q, 0);
 
180
                goto out_err;
230
181
        }
231
 
func_end:
 
182
 
 
183
        list_add_tail(&msg_q->list_elem, &hmsg_mgr->queue_list);
 
184
        *msgq = msg_q;
 
185
        /* Signal that free frames are now available */
 
186
        if (!list_empty(&hmsg_mgr->msg_free_list))
 
187
                sync_set_event(hmsg_mgr->sync_event);
 
188
 
 
189
        /* Exit critical section */
 
190
        spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
 
191
 
 
192
        return 0;
 
193
out_err:
 
194
        delete_msg_queue(msg_q, num_allocated);
232
195
        return status;
233
196
}
234
197
 
251
214
        struct msg_mgr *hmsg_mgr;
252
215
        u32 io_msg_pend;
253
216
 
254
 
        if (!msg_queue_obj || !msg_queue_obj->hmsg_mgr)
255
 
                goto func_end;
 
217
        if (!msg_queue_obj || !msg_queue_obj->msg_mgr)
 
218
                return;
256
219
 
257
 
        hmsg_mgr = msg_queue_obj->hmsg_mgr;
 
220
        hmsg_mgr = msg_queue_obj->msg_mgr;
258
221
        msg_queue_obj->done = true;
259
222
        /*  Unblock all threads blocked in MSG_Get() or MSG_Put(). */
260
223
        io_msg_pend = msg_queue_obj->io_msg_pend;
267
230
        }
268
231
        /* Remove message queue from hmsg_mgr->queue_list */
269
232
        spin_lock_bh(&hmsg_mgr->msg_mgr_lock);
270
 
        lst_remove_elem(hmsg_mgr->queue_list,
271
 
                        (struct list_head *)msg_queue_obj);
 
233
        list_del(&msg_queue_obj->list_elem);
272
234
        /* Free the message queue object */
273
235
        delete_msg_queue(msg_queue_obj, msg_queue_obj->max_msgs);
274
 
        if (!hmsg_mgr->msg_free_list)
275
 
                goto func_cont;
276
 
        if (LST_IS_EMPTY(hmsg_mgr->msg_free_list))
 
236
        if (list_empty(&hmsg_mgr->msg_free_list))
277
237
                sync_reset_event(hmsg_mgr->sync_event);
278
 
func_cont:
279
238
        spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
280
 
func_end:
281
 
        return;
282
239
}
283
240
 
284
241
/*
290
247
{
291
248
        struct msg_frame *msg_frame_obj;
292
249
        struct msg_mgr *hmsg_mgr;
293
 
        bool got_msg = false;
294
250
        struct sync_object *syncs[2];
295
251
        u32 index;
296
252
        int status = 0;
297
253
 
298
 
        if (!msg_queue_obj || pmsg == NULL) {
299
 
                status = -ENOMEM;
300
 
                goto func_end;
301
 
        }
302
 
 
303
 
        hmsg_mgr = msg_queue_obj->hmsg_mgr;
304
 
        if (!msg_queue_obj->msg_used_list) {
305
 
                status = -EFAULT;
306
 
                goto func_end;
307
 
        }
308
 
 
309
 
        /* Enter critical section */
 
254
        if (!msg_queue_obj || pmsg == NULL)
 
255
                return -ENOMEM;
 
256
 
 
257
        hmsg_mgr = msg_queue_obj->msg_mgr;
 
258
 
310
259
        spin_lock_bh(&hmsg_mgr->msg_mgr_lock);
311
260
        /* If a message is already there, get it */
312
 
        if (!LST_IS_EMPTY(msg_queue_obj->msg_used_list)) {
313
 
                msg_frame_obj = (struct msg_frame *)
314
 
                    lst_get_head(msg_queue_obj->msg_used_list);
315
 
                if (msg_frame_obj != NULL) {
316
 
                        *pmsg = msg_frame_obj->msg_data.msg;
317
 
                        lst_put_tail(msg_queue_obj->msg_free_list,
318
 
                                     (struct list_head *)msg_frame_obj);
319
 
                        if (LST_IS_EMPTY(msg_queue_obj->msg_used_list))
320
 
                                sync_reset_event(msg_queue_obj->sync_event);
321
 
 
322
 
                        got_msg = true;
323
 
                }
324
 
        } else {
325
 
                if (msg_queue_obj->done)
326
 
                        status = -EPERM;
327
 
                else
328
 
                        msg_queue_obj->io_msg_pend++;
329
 
 
330
 
        }
331
 
        /* Exit critical section */
332
 
        spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
333
 
        if (!status && !got_msg) {
334
 
                /*  Wait til message is available, timeout, or done. We don't
335
 
                 *  have to schedule the DPC, since the DSP will send messages
336
 
                 *  when they are available. */
337
 
                syncs[0] = msg_queue_obj->sync_event;
338
 
                syncs[1] = msg_queue_obj->sync_done;
339
 
                status = sync_wait_on_multiple_events(syncs, 2, utimeout,
340
 
                                                      &index);
341
 
                /* Enter critical section */
342
 
                spin_lock_bh(&hmsg_mgr->msg_mgr_lock);
343
 
                if (msg_queue_obj->done) {
344
 
                        msg_queue_obj->io_msg_pend--;
345
 
                        /* Exit critical section */
346
 
                        spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
347
 
                        /*  Signal that we're not going to access msg_queue_obj
348
 
                         *  anymore, so it can be deleted. */
349
 
                        (void)sync_set_event(msg_queue_obj->sync_done_ack);
350
 
                        status = -EPERM;
351
 
                } else {
352
 
                        if (!status) {
353
 
                                DBC_ASSERT(!LST_IS_EMPTY
354
 
                                           (msg_queue_obj->msg_used_list));
355
 
                                /* Get msg from used list */
356
 
                                msg_frame_obj = (struct msg_frame *)
357
 
                                    lst_get_head(msg_queue_obj->msg_used_list);
358
 
                                /* Copy message into pmsg and put frame on the
359
 
                                 * free list */
360
 
                                if (msg_frame_obj != NULL) {
361
 
                                        *pmsg = msg_frame_obj->msg_data.msg;
362
 
                                        lst_put_tail
363
 
                                            (msg_queue_obj->msg_free_list,
364
 
                                             (struct list_head *)
365
 
                                             msg_frame_obj);
366
 
                                }
367
 
                        }
368
 
                        msg_queue_obj->io_msg_pend--;
369
 
                        /* Reset the event if there are still queued messages */
370
 
                        if (!LST_IS_EMPTY(msg_queue_obj->msg_used_list))
371
 
                                sync_set_event(msg_queue_obj->sync_event);
372
 
 
373
 
                        /* Exit critical section */
374
 
                        spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
375
 
                }
376
 
        }
377
 
func_end:
 
261
        if (!list_empty(&msg_queue_obj->msg_used_list)) {
 
262
                msg_frame_obj = list_first_entry(&msg_queue_obj->msg_used_list,
 
263
                                struct msg_frame, list_elem);
 
264
                list_del(&msg_frame_obj->list_elem);
 
265
                *pmsg = msg_frame_obj->msg_data.msg;
 
266
                list_add_tail(&msg_frame_obj->list_elem,
 
267
                                &msg_queue_obj->msg_free_list);
 
268
                if (list_empty(&msg_queue_obj->msg_used_list))
 
269
                        sync_reset_event(msg_queue_obj->sync_event);
 
270
                spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
 
271
                return 0;
 
272
        }
 
273
 
 
274
        if (msg_queue_obj->done) {
 
275
                spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
 
276
                return -EPERM;
 
277
        }
 
278
        msg_queue_obj->io_msg_pend++;
 
279
        spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
 
280
 
 
281
        /*
 
282
         * Wait til message is available, timeout, or done. We don't
 
283
         * have to schedule the DPC, since the DSP will send messages
 
284
         * when they are available.
 
285
         */
 
286
        syncs[0] = msg_queue_obj->sync_event;
 
287
        syncs[1] = msg_queue_obj->sync_done;
 
288
        status = sync_wait_on_multiple_events(syncs, 2, utimeout, &index);
 
289
 
 
290
        spin_lock_bh(&hmsg_mgr->msg_mgr_lock);
 
291
        if (msg_queue_obj->done) {
 
292
                msg_queue_obj->io_msg_pend--;
 
293
                spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
 
294
                /*
 
295
                 * Signal that we're not going to access msg_queue_obj
 
296
                 * anymore, so it can be deleted.
 
297
                 */
 
298
                sync_set_event(msg_queue_obj->sync_done_ack);
 
299
                return -EPERM;
 
300
        }
 
301
        if (!status && !list_empty(&msg_queue_obj->msg_used_list)) {
 
302
                /* Get msg from used list */
 
303
                msg_frame_obj = list_first_entry(&msg_queue_obj->msg_used_list,
 
304
                                struct msg_frame, list_elem);
 
305
                list_del(&msg_frame_obj->list_elem);
 
306
                /* Copy message into pmsg and put frame on the free list */
 
307
                *pmsg = msg_frame_obj->msg_data.msg;
 
308
                list_add_tail(&msg_frame_obj->list_elem,
 
309
                                &msg_queue_obj->msg_free_list);
 
310
        }
 
311
        msg_queue_obj->io_msg_pend--;
 
312
        /* Reset the event if there are still queued messages */
 
313
        if (!list_empty(&msg_queue_obj->msg_used_list))
 
314
                sync_set_event(msg_queue_obj->sync_event);
 
315
 
 
316
        spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
 
317
 
378
318
        return status;
379
319
}
380
320
 
387
327
{
388
328
        struct msg_frame *msg_frame_obj;
389
329
        struct msg_mgr *hmsg_mgr;
390
 
        bool put_msg = false;
391
330
        struct sync_object *syncs[2];
392
331
        u32 index;
393
 
        int status = 0;
394
 
 
395
 
        if (!msg_queue_obj || !pmsg || !msg_queue_obj->hmsg_mgr) {
396
 
                status = -ENOMEM;
397
 
                goto func_end;
398
 
        }
399
 
        hmsg_mgr = msg_queue_obj->hmsg_mgr;
400
 
        if (!hmsg_mgr->msg_free_list) {
401
 
                status = -EFAULT;
402
 
                goto func_end;
403
 
        }
 
332
        int status;
 
333
 
 
334
        if (!msg_queue_obj || !pmsg || !msg_queue_obj->msg_mgr)
 
335
                return -EFAULT;
 
336
 
 
337
        hmsg_mgr = msg_queue_obj->msg_mgr;
404
338
 
405
339
        spin_lock_bh(&hmsg_mgr->msg_mgr_lock);
406
340
 
407
341
        /* If a message frame is available, use it */
408
 
        if (!LST_IS_EMPTY(hmsg_mgr->msg_free_list)) {
409
 
                msg_frame_obj =
410
 
                    (struct msg_frame *)lst_get_head(hmsg_mgr->msg_free_list);
411
 
                if (msg_frame_obj != NULL) {
412
 
                        msg_frame_obj->msg_data.msg = *pmsg;
413
 
                        msg_frame_obj->msg_data.msgq_id =
414
 
                            msg_queue_obj->msgq_id;
415
 
                        lst_put_tail(hmsg_mgr->msg_used_list,
416
 
                                     (struct list_head *)msg_frame_obj);
417
 
                        hmsg_mgr->msgs_pending++;
418
 
                        put_msg = true;
419
 
                }
420
 
                if (LST_IS_EMPTY(hmsg_mgr->msg_free_list))
 
342
        if (!list_empty(&hmsg_mgr->msg_free_list)) {
 
343
                msg_frame_obj = list_first_entry(&hmsg_mgr->msg_free_list,
 
344
                                struct msg_frame, list_elem);
 
345
                list_del(&msg_frame_obj->list_elem);
 
346
                msg_frame_obj->msg_data.msg = *pmsg;
 
347
                msg_frame_obj->msg_data.msgq_id =
 
348
                        msg_queue_obj->msgq_id;
 
349
                list_add_tail(&msg_frame_obj->list_elem,
 
350
                                &hmsg_mgr->msg_used_list);
 
351
                hmsg_mgr->msgs_pending++;
 
352
 
 
353
                if (list_empty(&hmsg_mgr->msg_free_list))
421
354
                        sync_reset_event(hmsg_mgr->sync_event);
422
355
 
423
356
                /* Release critical section before scheduling DPC */
424
357
                spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
425
358
                /* Schedule a DPC, to do the actual data transfer: */
426
 
                iosm_schedule(hmsg_mgr->hio_mgr);
427
 
        } else {
428
 
                if (msg_queue_obj->done)
429
 
                        status = -EPERM;
430
 
                else
431
 
                        msg_queue_obj->io_msg_pend++;
432
 
 
433
 
                spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
434
 
        }
435
 
        if (!status && !put_msg) {
436
 
                /* Wait til a free message frame is available, timeout,
437
 
                 * or done */
438
 
                syncs[0] = hmsg_mgr->sync_event;
439
 
                syncs[1] = msg_queue_obj->sync_done;
440
 
                status = sync_wait_on_multiple_events(syncs, 2, utimeout,
441
 
                                                      &index);
442
 
                if (status)
443
 
                        goto func_end;
444
 
                /* Enter critical section */
445
 
                spin_lock_bh(&hmsg_mgr->msg_mgr_lock);
446
 
                if (msg_queue_obj->done) {
447
 
                        msg_queue_obj->io_msg_pend--;
448
 
                        /* Exit critical section */
449
 
                        spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
450
 
                        /*  Signal that we're not going to access msg_queue_obj
451
 
                         *  anymore, so it can be deleted. */
452
 
                        (void)sync_set_event(msg_queue_obj->sync_done_ack);
453
 
                        status = -EPERM;
454
 
                } else {
455
 
                        if (LST_IS_EMPTY(hmsg_mgr->msg_free_list)) {
456
 
                                status = -EFAULT;
457
 
                                goto func_cont;
458
 
                        }
459
 
                        /* Get msg from free list */
460
 
                        msg_frame_obj = (struct msg_frame *)
461
 
                            lst_get_head(hmsg_mgr->msg_free_list);
462
 
                        /*
463
 
                         * Copy message into pmsg and put frame on the
464
 
                         * used list.
465
 
                         */
466
 
                        if (msg_frame_obj) {
467
 
                                msg_frame_obj->msg_data.msg = *pmsg;
468
 
                                msg_frame_obj->msg_data.msgq_id =
469
 
                                    msg_queue_obj->msgq_id;
470
 
                                lst_put_tail(hmsg_mgr->msg_used_list,
471
 
                                             (struct list_head *)msg_frame_obj);
472
 
                                hmsg_mgr->msgs_pending++;
473
 
                                /*
474
 
                                 * Schedule a DPC, to do the actual
475
 
                                 * data transfer.
476
 
                                 */
477
 
                                iosm_schedule(hmsg_mgr->hio_mgr);
478
 
                        }
479
 
 
480
 
                        msg_queue_obj->io_msg_pend--;
481
 
                        /* Reset event if there are still frames available */
482
 
                        if (!LST_IS_EMPTY(hmsg_mgr->msg_free_list))
483
 
                                sync_set_event(hmsg_mgr->sync_event);
484
 
func_cont:
485
 
                        /* Exit critical section */
486
 
                        spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
487
 
                }
488
 
        }
489
 
func_end:
490
 
        return status;
 
359
                iosm_schedule(hmsg_mgr->iomgr);
 
360
                return 0;
 
361
        }
 
362
 
 
363
        if (msg_queue_obj->done) {
 
364
                spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
 
365
                return -EPERM;
 
366
        }
 
367
        msg_queue_obj->io_msg_pend++;
 
368
 
 
369
        spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
 
370
 
 
371
        /* Wait til a free message frame is available, timeout, or done */
 
372
        syncs[0] = hmsg_mgr->sync_event;
 
373
        syncs[1] = msg_queue_obj->sync_done;
 
374
        status = sync_wait_on_multiple_events(syncs, 2, utimeout, &index);
 
375
        if (status)
 
376
                return status;
 
377
 
 
378
        /* Enter critical section */
 
379
        spin_lock_bh(&hmsg_mgr->msg_mgr_lock);
 
380
        if (msg_queue_obj->done) {
 
381
                msg_queue_obj->io_msg_pend--;
 
382
                /* Exit critical section */
 
383
                spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
 
384
                /*
 
385
                 * Signal that we're not going to access msg_queue_obj
 
386
                 * anymore, so it can be deleted.
 
387
                 */
 
388
                sync_set_event(msg_queue_obj->sync_done_ack);
 
389
                return -EPERM;
 
390
        }
 
391
 
 
392
        if (list_empty(&hmsg_mgr->msg_free_list)) {
 
393
                spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
 
394
                return -EFAULT;
 
395
        }
 
396
 
 
397
        /* Get msg from free list */
 
398
        msg_frame_obj = list_first_entry(&hmsg_mgr->msg_free_list,
 
399
                        struct msg_frame, list_elem);
 
400
        /*
 
401
         * Copy message into pmsg and put frame on the
 
402
         * used list.
 
403
         */
 
404
        list_del(&msg_frame_obj->list_elem);
 
405
        msg_frame_obj->msg_data.msg = *pmsg;
 
406
        msg_frame_obj->msg_data.msgq_id = msg_queue_obj->msgq_id;
 
407
        list_add_tail(&msg_frame_obj->list_elem, &hmsg_mgr->msg_used_list);
 
408
        hmsg_mgr->msgs_pending++;
 
409
        /*
 
410
         * Schedule a DPC, to do the actual
 
411
         * data transfer.
 
412
         */
 
413
        iosm_schedule(hmsg_mgr->iomgr);
 
414
 
 
415
        msg_queue_obj->io_msg_pend--;
 
416
        /* Reset event if there are still frames available */
 
417
        if (!list_empty(&hmsg_mgr->msg_free_list))
 
418
                sync_set_event(hmsg_mgr->sync_event);
 
419
 
 
420
        /* Exit critical section */
 
421
        spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
 
422
 
 
423
        return 0;
491
424
}
492
425
 
493
426
/*
551
484
 *  ======== add_new_msg ========
552
485
 *      Must be called in message manager critical section.
553
486
 */
554
 
static int add_new_msg(struct lst_list *msg_list)
 
487
static int add_new_msg(struct list_head *msg_list)
555
488
{
556
489
        struct msg_frame *pmsg;
557
 
        int status = 0;
558
490
 
559
491
        pmsg = kzalloc(sizeof(struct msg_frame), GFP_ATOMIC);
560
 
        if (pmsg != NULL) {
561
 
                lst_init_elem((struct list_head *)pmsg);
562
 
                lst_put_tail(msg_list, (struct list_head *)pmsg);
563
 
        } else {
564
 
                status = -ENOMEM;
565
 
        }
566
 
 
567
 
        return status;
 
492
        if (!pmsg)
 
493
                return -ENOMEM;
 
494
 
 
495
        list_add_tail(&pmsg->list_elem, msg_list);
 
496
 
 
497
        return 0;
568
498
}
569
499
 
570
500
/*
573
503
static void delete_msg_mgr(struct msg_mgr *hmsg_mgr)
574
504
{
575
505
        if (!hmsg_mgr)
576
 
                goto func_end;
577
 
 
578
 
        if (hmsg_mgr->queue_list) {
579
 
                if (LST_IS_EMPTY(hmsg_mgr->queue_list)) {
580
 
                        kfree(hmsg_mgr->queue_list);
581
 
                        hmsg_mgr->queue_list = NULL;
582
 
                }
583
 
        }
584
 
 
585
 
        if (hmsg_mgr->msg_free_list) {
586
 
                free_msg_list(hmsg_mgr->msg_free_list);
587
 
                hmsg_mgr->msg_free_list = NULL;
588
 
        }
589
 
 
590
 
        if (hmsg_mgr->msg_used_list) {
591
 
                free_msg_list(hmsg_mgr->msg_used_list);
592
 
                hmsg_mgr->msg_used_list = NULL;
593
 
        }
594
 
 
 
506
                return;
 
507
 
 
508
        /* FIXME: free elements from queue_list? */
 
509
        free_msg_list(&hmsg_mgr->msg_free_list);
 
510
        free_msg_list(&hmsg_mgr->msg_used_list);
595
511
        kfree(hmsg_mgr->sync_event);
596
 
 
597
512
        kfree(hmsg_mgr);
598
 
func_end:
599
 
        return;
600
513
}
601
514
 
602
515
/*
605
518
static void delete_msg_queue(struct msg_queue *msg_queue_obj, u32 num_to_dsp)
606
519
{
607
520
        struct msg_mgr *hmsg_mgr;
608
 
        struct msg_frame *pmsg;
 
521
        struct msg_frame *pmsg, *tmp;
609
522
        u32 i;
610
523
 
611
 
        if (!msg_queue_obj ||
612
 
            !msg_queue_obj->hmsg_mgr || !msg_queue_obj->hmsg_mgr->msg_free_list)
613
 
                goto func_end;
 
524
        if (!msg_queue_obj || !msg_queue_obj->msg_mgr)
 
525
                return;
614
526
 
615
 
        hmsg_mgr = msg_queue_obj->hmsg_mgr;
 
527
        hmsg_mgr = msg_queue_obj->msg_mgr;
616
528
 
617
529
        /* Pull off num_to_dsp message frames from Msg manager and free */
618
 
        for (i = 0; i < num_to_dsp; i++) {
619
 
 
620
 
                if (!LST_IS_EMPTY(hmsg_mgr->msg_free_list)) {
621
 
                        pmsg = (struct msg_frame *)
622
 
                            lst_get_head(hmsg_mgr->msg_free_list);
623
 
                        kfree(pmsg);
624
 
                } else {
625
 
                        /* Cannot free all of the message frames */
 
530
        i = 0;
 
531
        list_for_each_entry_safe(pmsg, tmp, &hmsg_mgr->msg_free_list,
 
532
                        list_elem) {
 
533
                list_del(&pmsg->list_elem);
 
534
                kfree(pmsg);
 
535
                if (i++ >= num_to_dsp)
626
536
                        break;
627
 
                }
628
 
        }
629
 
 
630
 
        if (msg_queue_obj->msg_free_list) {
631
 
                free_msg_list(msg_queue_obj->msg_free_list);
632
 
                msg_queue_obj->msg_free_list = NULL;
633
 
        }
634
 
 
635
 
        if (msg_queue_obj->msg_used_list) {
636
 
                free_msg_list(msg_queue_obj->msg_used_list);
637
 
                msg_queue_obj->msg_used_list = NULL;
638
 
        }
 
537
        }
 
538
 
 
539
        free_msg_list(&msg_queue_obj->msg_free_list);
 
540
        free_msg_list(&msg_queue_obj->msg_used_list);
639
541
 
640
542
        if (msg_queue_obj->ntfy_obj) {
641
543
                ntfy_delete(msg_queue_obj->ntfy_obj);
647
549
        kfree(msg_queue_obj->sync_done_ack);
648
550
 
649
551
        kfree(msg_queue_obj);
650
 
func_end:
651
 
        return;
652
 
 
653
552
}
654
553
 
655
554
/*
656
555
 *  ======== free_msg_list ========
657
556
 */
658
 
static void free_msg_list(struct lst_list *msg_list)
 
557
static void free_msg_list(struct list_head *msg_list)
659
558
{
660
 
        struct msg_frame *pmsg;
 
559
        struct msg_frame *pmsg, *tmp;
661
560
 
662
561
        if (!msg_list)
663
 
                goto func_end;
 
562
                return;
664
563
 
665
 
        while ((pmsg = (struct msg_frame *)lst_get_head(msg_list)) != NULL)
 
564
        list_for_each_entry_safe(pmsg, tmp, msg_list, list_elem) {
 
565
                list_del(&pmsg->list_elem);
666
566
                kfree(pmsg);
667
 
 
668
 
        DBC_ASSERT(LST_IS_EMPTY(msg_list));
669
 
 
670
 
        kfree(msg_list);
671
 
func_end:
672
 
        return;
 
567
        }
673
568
}