Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.29-rc4 299 lines 9.4 kB view raw
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 This routine creates an event queue based on the client completion 21 queue configuration information. 22 23 FunctionObject - Handle to a function object 24 EqBaseVa - Base VA for a the EQ ring 25 SizeEncoding - The encoded size for the EQ entries. This value is 26 either CEV_EQ_SIZE_4 or CEV_EQ_SIZE_16 27 NumEntries - CEV_CQ_CNT_* values. 28 Watermark - Enables watermark based coalescing. This parameter 29 must be of the type CEV_WMARK_* if watermarks 30 are enabled. If watermarks to to be disabled 31 this value should be-1. 32 TimerDelay - If a timer delay is enabled this value should be the 33 time of the delay in 8 microsecond units. If 34 delays are not used this parameter should be 35 set to -1. 36 ppEqObject - Internal EQ Handle returned. 37 38 Returns BE_SUCCESS if successfull,, otherwise a useful error code 39 is returned. 40 41 IRQL < DISPATCH_LEVEL 42*/ 43int 44be_eq_create(struct be_function_object *pfob, 45 struct ring_desc *rd, u32 eqe_size, u32 num_entries, 46 u32 watermark, /* CEV_WMARK_* or -1 */ 47 u32 timer_delay, /* in 8us units, or -1 */ 48 struct be_eq_object *eq_object) 49{ 50 int status = BE_SUCCESS; 51 u32 num_entries_encoding, eqe_size_encoding, length; 52 struct FWCMD_COMMON_EQ_CREATE *fwcmd = NULL; 53 struct MCC_WRB_AMAP *wrb = NULL; 54 u32 n; 55 unsigned long irql; 56 57 ASSERT(rd); 58 ASSERT(eq_object); 59 60 switch (num_entries) { 61 case 256: 62 num_entries_encoding = CEV_EQ_CNT_256; 63 break; 64 case 512: 65 num_entries_encoding = CEV_EQ_CNT_512; 66 break; 67 case 1024: 68 num_entries_encoding = CEV_EQ_CNT_1024; 69 break; 70 case 2048: 71 num_entries_encoding = CEV_EQ_CNT_2048; 72 break; 73 case 4096: 74 num_entries_encoding = CEV_EQ_CNT_4096; 75 break; 76 default: 77 ASSERT(0); 78 return BE_STATUS_INVALID_PARAMETER; 79 } 80 81 switch (eqe_size) { 82 case 4: 83 eqe_size_encoding = CEV_EQ_SIZE_4; 84 break; 85 case 16: 86 eqe_size_encoding = CEV_EQ_SIZE_16; 87 break; 88 default: 89 ASSERT(0); 90 return BE_STATUS_INVALID_PARAMETER; 91 } 92 93 if ((eqe_size == 4 && num_entries < 1024) || 94 (eqe_size == 16 && num_entries == 4096)) { 95 TRACE(DL_ERR, "Bad EQ size. eqe_size:%d num_entries:%d", 96 eqe_size, num_entries); 97 ASSERT(0); 98 return BE_STATUS_INVALID_PARAMETER; 99 } 100 101 memset(eq_object, 0, sizeof(*eq_object)); 102 103 atomic_set(&eq_object->ref_count, 0); 104 eq_object->parent_function = pfob; 105 eq_object->eq_id = 0xFFFFFFFF; 106 107 INIT_LIST_HEAD(&eq_object->cq_list_head); 108 109 length = num_entries * eqe_size; 110 111 spin_lock_irqsave(&pfob->post_lock, irql); 112 113 wrb = be_function_peek_mcc_wrb(pfob); 114 if (!wrb) { 115 ASSERT(wrb); 116 TRACE(DL_ERR, "No free MCC WRBs in create EQ."); 117 status = BE_STATUS_NO_MCC_WRB; 118 goto Error; 119 } 120 /* Prepares an embedded fwcmd, including request/response sizes. */ 121 fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_EQ_CREATE); 122 123 fwcmd->params.request.num_pages = PAGES_SPANNED(OFFSET_IN_PAGE(rd->va), 124 length); 125 n = pfob->pci_function_number; 126 AMAP_SET_BITS_PTR(EQ_CONTEXT, Func, &fwcmd->params.request.context, n); 127 128 AMAP_SET_BITS_PTR(EQ_CONTEXT, valid, &fwcmd->params.request.context, 1); 129 130 AMAP_SET_BITS_PTR(EQ_CONTEXT, Size, 131 &fwcmd->params.request.context, eqe_size_encoding); 132 133 n = 0; /* Protection Domain is always 0 in Linux driver */ 134 AMAP_SET_BITS_PTR(EQ_CONTEXT, PD, &fwcmd->params.request.context, n); 135 136 /* Let the caller ARM the EQ with the doorbell. */ 137 AMAP_SET_BITS_PTR(EQ_CONTEXT, Armed, &fwcmd->params.request.context, 0); 138 139 AMAP_SET_BITS_PTR(EQ_CONTEXT, Count, &fwcmd->params.request.context, 140 num_entries_encoding); 141 142 n = pfob->pci_function_number * 32; 143 AMAP_SET_BITS_PTR(EQ_CONTEXT, EventVect, 144 &fwcmd->params.request.context, n); 145 if (watermark != -1) { 146 AMAP_SET_BITS_PTR(EQ_CONTEXT, WME, 147 &fwcmd->params.request.context, 1); 148 AMAP_SET_BITS_PTR(EQ_CONTEXT, Watermark, 149 &fwcmd->params.request.context, watermark); 150 ASSERT(watermark <= CEV_WMARK_240); 151 } else 152 AMAP_SET_BITS_PTR(EQ_CONTEXT, WME, 153 &fwcmd->params.request.context, 0); 154 if (timer_delay != -1) { 155 AMAP_SET_BITS_PTR(EQ_CONTEXT, TMR, 156 &fwcmd->params.request.context, 1); 157 158 ASSERT(timer_delay <= 250); /* max value according to EAS */ 159 timer_delay = min(timer_delay, (u32)250); 160 161 AMAP_SET_BITS_PTR(EQ_CONTEXT, Delay, 162 &fwcmd->params.request.context, timer_delay); 163 } else { 164 AMAP_SET_BITS_PTR(EQ_CONTEXT, TMR, 165 &fwcmd->params.request.context, 0); 166 } 167 /* Create a page list for the FWCMD. */ 168 be_rd_to_pa_list(rd, fwcmd->params.request.pages, 169 ARRAY_SIZE(fwcmd->params.request.pages)); 170 171 status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, 172 NULL, NULL, fwcmd, NULL); 173 if (status != BE_SUCCESS) { 174 TRACE(DL_ERR, "MCC to create EQ failed."); 175 goto Error; 176 } 177 /* Get the EQ id. The MPU allocates the IDs. */ 178 eq_object->eq_id = fwcmd->params.response.eq_id; 179 180Error: 181 spin_unlock_irqrestore(&pfob->post_lock, irql); 182 183 if (pfob->pend_queue_driving && pfob->mcc) { 184 pfob->pend_queue_driving = 0; 185 be_drive_mcc_wrb_queue(pfob->mcc); 186 } 187 return status; 188} 189 190/* 191 Deferences the given object. Once the object's reference count drops to 192 zero, the object is destroyed and all resources that are held by this 193 object are released. The on-chip context is also destroyed along with 194 the queue ID, and any mappings made into the UT. 195 196 eq_object - EQ handle returned from eq_object_create. 197 198 Returns BE_SUCCESS if successfull, otherwise a useful error code 199 is returned. 200 201 IRQL: IRQL < DISPATCH_LEVEL 202*/ 203int be_eq_destroy(struct be_eq_object *eq_object) 204{ 205 int status = 0; 206 207 ASSERT(atomic_read(&eq_object->ref_count) == 0); 208 /* no CQs should reference this EQ now */ 209 ASSERT(list_empty(&eq_object->cq_list_head)); 210 211 /* Send fwcmd to destroy the EQ. */ 212 status = be_function_ring_destroy(eq_object->parent_function, 213 eq_object->eq_id, FWCMD_RING_TYPE_EQ, 214 NULL, NULL, NULL, NULL); 215 ASSERT(status == 0); 216 217 return BE_SUCCESS; 218} 219/* 220 *--------------------------------------------------------------------------- 221 * Function: be_eq_modify_delay 222 * Changes the EQ delay for a group of EQs. 223 * num_eq - The number of EQs in the eq_array to adjust. 224 * This also is the number of delay values in 225 * the eq_delay_array. 226 * eq_array - Array of struct be_eq_object pointers to adjust. 227 * eq_delay_array - Array of "num_eq" timer delays in units 228 * of microseconds. The be_eq_query_delay_range 229 * fwcmd returns the resolution and range of 230 * legal EQ delays. 231 * cb - 232 * cb_context - 233 * q_ctxt - Optional. Pointer to a previously allocated 234 * struct. If the MCC WRB ring is full, this 235 * structure is used to queue the operation. It 236 * will be posted to the MCC ring when space 237 * becomes available. All queued commands will 238 * be posted to the ring in the order they are 239 * received. It is always valid to pass a pointer to 240 * a generic be_generic_q_cntxt. However, 241 * the specific context structs 242 * are generally smaller than the generic struct. 243 * return pend_status - BE_SUCCESS (0) on success. 244 * BE_PENDING (postive value) if the FWCMD 245 * completion is pending. Negative error code on failure. 246 *------------------------------------------------------------------------- 247 */ 248int 249be_eq_modify_delay(struct be_function_object *pfob, 250 u32 num_eq, struct be_eq_object **eq_array, 251 u32 *eq_delay_array, mcc_wrb_cqe_callback cb, 252 void *cb_context, struct be_eq_modify_delay_q_ctxt *q_ctxt) 253{ 254 struct FWCMD_COMMON_MODIFY_EQ_DELAY *fwcmd = NULL; 255 struct MCC_WRB_AMAP *wrb = NULL; 256 int status = 0; 257 struct be_generic_q_ctxt *gen_ctxt = NULL; 258 u32 i; 259 unsigned long irql; 260 261 spin_lock_irqsave(&pfob->post_lock, irql); 262 263 wrb = be_function_peek_mcc_wrb(pfob); 264 if (!wrb) { 265 if (q_ctxt && cb) { 266 wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header; 267 gen_ctxt = (struct be_generic_q_ctxt *) q_ctxt; 268 gen_ctxt->context.bytes = sizeof(*q_ctxt); 269 } else { 270 status = BE_STATUS_NO_MCC_WRB; 271 goto Error; 272 } 273 } 274 /* Prepares an embedded fwcmd, including request/response sizes. */ 275 fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_MODIFY_EQ_DELAY); 276 277 ASSERT(num_eq > 0); 278 ASSERT(num_eq <= ARRAY_SIZE(fwcmd->params.request.delay)); 279 fwcmd->params.request.num_eq = num_eq; 280 for (i = 0; i < num_eq; i++) { 281 fwcmd->params.request.delay[i].eq_id = eq_array[i]->eq_id; 282 fwcmd->params.request.delay[i].delay_in_microseconds = 283 eq_delay_array[i]; 284 } 285 286 /* Post the f/w command */ 287 status = be_function_post_mcc_wrb(pfob, wrb, gen_ctxt, 288 cb, cb_context, NULL, NULL, fwcmd, NULL); 289 290Error: 291 spin_unlock_irqrestore(&pfob->post_lock, irql); 292 293 if (pfob->pend_queue_driving && pfob->mcc) { 294 pfob->pend_queue_driving = 0; 295 be_drive_mcc_wrb_queue(pfob->mcc); 296 } 297 return status; 298} 299