]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/staging/benet/cq.c
thermal: support forcing support for passive cooling
[linux-2.6-omap-h63xx.git] / drivers / staging / benet / cq.c
1 /*
2  * Copyright (C) 2005 - 2008 ServerEngines
3  * All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License version 2
7  * as published by the Free Software Foundation.  The full GNU General
8  * Public License is included in this distribution in the file called COPYING.
9  *
10  * Contact Information:
11  * linux-drivers@serverengines.com
12  *
13  * ServerEngines
14  * 209 N. Fair Oaks Ave
15  * Sunnyvale, CA 94085
16  */
17 #include "hwlib.h"
18 #include "bestatus.h"
19
20 /*
21  * Completion Queue Objects
22  */
23 /*
24  *============================================================================
25  *                  P U B L I C  R O U T I N E S
26  *============================================================================
27  */
28
29 /*
30     This routine creates a completion queue based on the client completion
31     queue configuration information.
32
33
34     FunctionObject      - Handle to a function object
35     CqBaseVa            - Base VA for a the CQ ring
36     NumEntries          - CEV_CQ_CNT_* values
37     solEventEnable      - 0 = All CQEs can generate Events if CQ is eventable
38                         1 = only CQEs with solicited bit set are eventable
39     eventable           - Eventable CQ, generates interrupts.
40     nodelay             - 1 = Force interrupt, relevent if CQ eventable.
41                         Interrupt is asserted immediately after EQE
42                         write is confirmed, regardless of EQ Timer
43                         or watermark settings.
44     wme                 - Enable watermark based coalescing
45     wmThresh            - High watermark(CQ fullness at which event
46                         or interrupt should be asserted).  These are the
47                         CEV_WATERMARK encoded values.
48     EqObject            - EQ Handle to assign to this CQ
49     ppCqObject          - Internal CQ Handle returned.
50
51     Returns BE_SUCCESS if successfull, otherwise a useful error code is
52         returned.
53
54     IRQL < DISPATCH_LEVEL
55
56 */
57 int be_cq_create(struct be_function_object *pfob,
58         struct ring_desc *rd, u32 length, bool solicited_eventable,
59         bool no_delay, u32 wm_thresh,
60         struct be_eq_object *eq_object, struct be_cq_object *cq_object)
61 {
62         int status = BE_SUCCESS;
63         u32 num_entries_encoding;
64         u32 num_entries = length / sizeof(struct MCC_CQ_ENTRY_AMAP);
65         struct FWCMD_COMMON_CQ_CREATE *fwcmd = NULL;
66         struct MCC_WRB_AMAP *wrb = NULL;
67         u32 n;
68         unsigned long irql;
69
70         ASSERT(rd);
71         ASSERT(cq_object);
72         ASSERT(length % sizeof(struct MCC_CQ_ENTRY_AMAP) == 0);
73
74         switch (num_entries) {
75         case 256:
76                 num_entries_encoding = CEV_CQ_CNT_256;
77                 break;
78         case 512:
79                 num_entries_encoding = CEV_CQ_CNT_512;
80                 break;
81         case 1024:
82                 num_entries_encoding = CEV_CQ_CNT_1024;
83                 break;
84         default:
85                 ASSERT(0);
86                 return BE_STATUS_INVALID_PARAMETER;
87         }
88
89         /*
90          * All cq entries all the same size.  Use iSCSI version
91          * as a test for the proper rd length.
92          */
93         memset(cq_object, 0, sizeof(*cq_object));
94
95         atomic_set(&cq_object->ref_count, 0);
96         cq_object->parent_function = pfob;
97         cq_object->eq_object = eq_object;
98         cq_object->num_entries = num_entries;
99         /* save for MCC cq processing */
100         cq_object->va = rd->va;
101
102         /* map into UT. */
103         length = num_entries * sizeof(struct MCC_CQ_ENTRY_AMAP);
104
105         spin_lock_irqsave(&pfob->post_lock, irql);
106
107         wrb = be_function_peek_mcc_wrb(pfob);
108         if (!wrb) {
109                 ASSERT(wrb);
110                 TRACE(DL_ERR, "No free MCC WRBs in create EQ.");
111                 status = BE_STATUS_NO_MCC_WRB;
112                 goto Error;
113         }
114         /* Prepares an embedded fwcmd, including request/response sizes. */
115         fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_CQ_CREATE);
116
117         fwcmd->params.request.num_pages = PAGES_SPANNED(OFFSET_IN_PAGE(rd->va),
118                                                                         length);
119
120         AMAP_SET_BITS_PTR(CQ_CONTEXT, valid, &fwcmd->params.request.context, 1);
121         n = pfob->pci_function_number;
122         AMAP_SET_BITS_PTR(CQ_CONTEXT, Func, &fwcmd->params.request.context, n);
123
124         n = (eq_object != NULL);
125         AMAP_SET_BITS_PTR(CQ_CONTEXT, Eventable,
126                                 &fwcmd->params.request.context, n);
127         AMAP_SET_BITS_PTR(CQ_CONTEXT, Armed, &fwcmd->params.request.context, 1);
128
129         n = eq_object ? eq_object->eq_id : 0;
130         AMAP_SET_BITS_PTR(CQ_CONTEXT, EQID, &fwcmd->params.request.context, n);
131         AMAP_SET_BITS_PTR(CQ_CONTEXT, Count,
132                         &fwcmd->params.request.context, num_entries_encoding);
133
134         n = 0; /* Protection Domain is always 0 in  Linux  driver */
135         AMAP_SET_BITS_PTR(CQ_CONTEXT, PD, &fwcmd->params.request.context, n);
136         AMAP_SET_BITS_PTR(CQ_CONTEXT, NoDelay,
137                                 &fwcmd->params.request.context, no_delay);
138         AMAP_SET_BITS_PTR(CQ_CONTEXT, SolEvent,
139                         &fwcmd->params.request.context, solicited_eventable);
140
141         n = (wm_thresh != 0xFFFFFFFF);
142         AMAP_SET_BITS_PTR(CQ_CONTEXT, WME, &fwcmd->params.request.context, n);
143
144         n = (n ? wm_thresh : 0);
145         AMAP_SET_BITS_PTR(CQ_CONTEXT, Watermark,
146                                 &fwcmd->params.request.context, n);
147         /* Create a page list for the FWCMD. */
148         be_rd_to_pa_list(rd, fwcmd->params.request.pages,
149                           ARRAY_SIZE(fwcmd->params.request.pages));
150
151         /* Post the f/w command */
152         status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL,
153                         NULL, NULL, fwcmd, NULL);
154         if (status != BE_SUCCESS) {
155                 TRACE(DL_ERR, "MCC to create CQ failed.");
156                 goto Error;
157         }
158         /* Remember the CQ id. */
159         cq_object->cq_id = fwcmd->params.response.cq_id;
160
161         /* insert this cq into eq_object reference */
162         if (eq_object) {
163                 atomic_inc(&eq_object->ref_count);
164                 list_add_tail(&cq_object->cqlist_for_eq,
165                                         &eq_object->cq_list_head);
166         }
167
168 Error:
169         spin_unlock_irqrestore(&pfob->post_lock, irql);
170
171         if (pfob->pend_queue_driving && pfob->mcc) {
172                 pfob->pend_queue_driving = 0;
173                 be_drive_mcc_wrb_queue(pfob->mcc);
174         }
175         return status;
176 }
177
178 /*
179
180     Deferences the given object. Once the object's reference count drops to
181     zero, the object is destroyed and all resources that are held by this object
182     are released.  The on-chip context is also destroyed along with the queue
183     ID, and any mappings made into the UT.
184
185     cq_object            - CQ handle returned from cq_object_create.
186
187     returns the current reference count on the object
188
189     IRQL: IRQL < DISPATCH_LEVEL
190 */
191 int be_cq_destroy(struct be_cq_object *cq_object)
192 {
193         int status = 0;
194
195         /* Nothing should reference this CQ at this point. */
196         ASSERT(atomic_read(&cq_object->ref_count) == 0);
197
198         /* Send fwcmd to destroy the CQ. */
199         status = be_function_ring_destroy(cq_object->parent_function,
200                      cq_object->cq_id, FWCMD_RING_TYPE_CQ,
201                                         NULL, NULL, NULL, NULL);
202         ASSERT(status == 0);
203
204         /* Remove reference if this is an eventable CQ. */
205         if (cq_object->eq_object) {
206                 atomic_dec(&cq_object->eq_object->ref_count);
207                 list_del(&cq_object->cqlist_for_eq);
208         }
209         return BE_SUCCESS;
210 }
211