5019 want open source bnxe
[illumos-gate.git] / usr / src / uts / common / io / bnxe / bnxe_workq.c
blob2be064c090a4fddbeaf6b181bf4993c047c3d6f6
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2014 QLogic Corporation
24 * The contents of this file are subject to the terms of the
25 * QLogic End User License (the "License").
26 * You may not use this file except in compliance with the License.
28 * You can obtain a copy of the License at
29 * http://www.qlogic.com/Resources/Documents/DriverDownloadHelp/
30 * QLogic_End_User_Software_License.txt
31 * See the License for the specific language governing permissions
32 * and limitations under the License.
35 #include "bnxe.h"
38 typedef struct _BnxeWorkItem
40 s_list_entry_t link;
41 void * pWorkData;
42 u32_t workDataLen;
43 u32_t delayMs;
44 void (*pWorkCbkCopy)(um_device_t *, void *, u32_t);
45 void (*pWorkCbkNoCopy)(um_device_t *, void *);
46 void (*pWorkCbkGeneric)(um_device_t *);
47 } BnxeWorkItem;
50 static void BnxeWorkQueueInstanceWaitAndDestroy(BnxeWorkQueueInstance * pWorkq)
52 if (pWorkq->pTaskq)
54 ddi_taskq_wait(pWorkq->pTaskq);
55 ddi_taskq_destroy(pWorkq->pTaskq);
56 mutex_destroy(&pWorkq->workQueueMutex);
59 memset(pWorkq, 0, sizeof(BnxeWorkQueueInstance));
63 boolean_t BnxeWorkQueueInit(um_device_t * pUM)
65 pUM->workqs.instq.pUM = pUM;
67 strcpy(pUM->workqs.instq.taskqName, pUM->devName);
68 strcat(pUM->workqs.instq.taskqName, "_inst_q");
70 mutex_init(&pUM->workqs.instq.workQueueMutex, NULL,
71 MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
73 if ((pUM->workqs.instq.pTaskq =
74 ddi_taskq_create(pUM->pDev,
75 pUM->workqs.instq.taskqName,
77 TASKQ_DEFAULTPRI,
78 0)) == NULL)
80 BnxeLogWarn(pUM, "Failed to create the workqs instq");
81 return B_FALSE;
84 pUM->workqs.instq.pUM = pUM;
86 strcpy(pUM->workqs.delayq.taskqName, pUM->devName);
87 strcat(pUM->workqs.delayq.taskqName, "_delay_q");
89 mutex_init(&pUM->workqs.delayq.workQueueMutex, NULL,
90 MUTEX_DRIVER, DDI_INTR_PRI(pUM->intrPriority));
92 if ((pUM->workqs.delayq.pTaskq =
93 ddi_taskq_create(pUM->pDev,
94 pUM->workqs.delayq.taskqName,
95 16, /* XXX Is this enough? */
96 TASKQ_DEFAULTPRI,
97 0)) == NULL)
99 BnxeLogWarn(pUM, "Failed to create the workqs delayq");
100 BnxeWorkQueueInstanceWaitAndDestroy(&pUM->workqs.instq);
101 return B_FALSE;
104 pUM->workqs.delayq.pUM = pUM;
106 return B_TRUE;
110 void BnxeWorkQueueWaitAndDestroy(um_device_t * pUM)
112 BnxeWorkQueueInstanceWaitAndDestroy(&pUM->workqs.instq);
113 BnxeWorkQueueInstanceWaitAndDestroy(&pUM->workqs.delayq);
117 static void BnxeWorkQueueDispatch(void * pArg)
119 BnxeWorkQueueInstance * pWorkq = (BnxeWorkQueueInstance *)pArg;
120 um_device_t * pUM = (um_device_t *)pWorkq->pUM;
121 BnxeWorkItem * pWorkItem;
123 mutex_enter(&pWorkq->workQueueMutex);
124 pWorkItem = (BnxeWorkItem *)s_list_pop_head(&pWorkq->workQueue);
125 mutex_exit(&pWorkq->workQueueMutex);
127 if (pWorkItem == NULL)
129 BnxeLogWarn(pUM, "Work item is NULL!");
130 pWorkq->workItemError++;
131 return;
134 if ((pWorkItem->pWorkCbkCopy == NULL) &&
135 (pWorkItem->pWorkCbkNoCopy == NULL) &&
136 (pWorkItem->pWorkCbkGeneric == NULL))
138 BnxeLogWarn(pUM, "Work item callback is NULL!");
139 pWorkq->workItemError++;
140 goto BnxeWorkQueueDispatch_done;
143 if (pWorkItem->delayMs > 0)
145 /* this only occurs when processing the delayq */
146 drv_usecwait(pWorkItem->delayMs * 1000);
149 if (pWorkItem->pWorkCbkCopy)
151 pWorkItem->pWorkCbkCopy(pUM,
152 pWorkItem->pWorkData,
153 pWorkItem->workDataLen);
155 else if (pWorkItem->pWorkCbkNoCopy)
157 pWorkItem->pWorkCbkNoCopy(pUM,
158 pWorkItem->pWorkData);
160 else /* (pWorkItem->pWorkCbkGeneric) */
162 pWorkItem->pWorkCbkGeneric(pUM);
165 pWorkq->workItemComplete++;
167 BnxeWorkQueueDispatch_done:
169 kmem_free(pWorkItem, (sizeof(BnxeWorkItem) + pWorkItem->workDataLen));
173 static void BnxeWorkQueueTrigger(um_device_t * pUM,
174 BnxeWorkQueueInstance * pWorkq)
176 if (pUM->chipStarted)
178 ddi_taskq_dispatch(pWorkq->pTaskq,
179 BnxeWorkQueueDispatch,
180 (void *)pWorkq,
181 DDI_NOSLEEP);
183 else
185 BnxeLogInfo(pUM, "Delaying WorkQ item since chip not yet started.");
190 void BnxeWorkQueueStartPending(um_device_t * pUM)
192 u32_t cnt;
194 if (!pUM->chipStarted)
196 BnxeLogWarn(pUM, "Triggering WorkQs and chip not started!");
197 return;
200 mutex_enter(&pUM->workqs.instq.workQueueMutex);
201 cnt = s_list_entry_cnt(&pUM->workqs.instq.workQueue);
202 mutex_exit(&pUM->workqs.instq.workQueueMutex);
204 if (cnt)
206 BnxeWorkQueueTrigger(pUM, &pUM->workqs.instq);
209 mutex_enter(&pUM->workqs.delayq.workQueueMutex);
210 cnt = s_list_entry_cnt(&pUM->workqs.delayq.workQueue);
211 mutex_exit(&pUM->workqs.delayq.workQueueMutex);
213 if (cnt)
215 BnxeWorkQueueTrigger(pUM, &pUM->workqs.delayq);
220 boolean_t BnxeWorkQueueAdd(um_device_t * pUM,
221 void (*pWorkCbkCopy)(um_device_t *, void *, u32_t),
222 void * pWorkData,
223 u32_t workDataLen)
225 BnxeWorkItem * pWorkItem;
227 if ((pWorkItem = kmem_zalloc((sizeof(BnxeWorkItem) + workDataLen),
228 KM_NOSLEEP)) == NULL)
230 BnxeLogWarn(pUM, "Failed to allocate memory for work item!");
231 return B_FALSE;
234 pWorkItem->pWorkData = (pWorkItem + 1);
235 pWorkItem->workDataLen = workDataLen;
236 pWorkItem->pWorkCbkCopy = pWorkCbkCopy;
237 pWorkItem->pWorkCbkNoCopy = NULL;
238 pWorkItem->pWorkCbkGeneric = NULL;
239 pWorkItem->delayMs = 0;
241 memcpy(pWorkItem->pWorkData, pWorkData, workDataLen);
243 mutex_enter(&pUM->workqs.instq.workQueueMutex);
245 s_list_push_tail(&pUM->workqs.instq.workQueue, &pWorkItem->link);
246 pUM->workqs.instq.workItemQueued++;
247 if (s_list_entry_cnt(&pUM->workqs.instq.workQueue) >
248 pUM->workqs.instq.highWater)
250 pUM->workqs.instq.highWater =
251 s_list_entry_cnt(&pUM->workqs.instq.workQueue);
254 mutex_exit(&pUM->workqs.instq.workQueueMutex);
256 BnxeWorkQueueTrigger(pUM, &pUM->workqs.instq);
258 return B_TRUE;
262 boolean_t BnxeWorkQueueAddNoCopy(um_device_t * pUM,
263 void (*pWorkCbkNoCopy)(um_device_t *, void *),
264 void * pWorkData)
266 BnxeWorkItem * pWorkItem;
268 if ((pWorkItem = kmem_zalloc(sizeof(BnxeWorkItem), KM_NOSLEEP)) == NULL)
270 BnxeLogWarn(pUM, "Failed to allocate memory for work item!");
271 return B_FALSE;
274 pWorkItem->pWorkData = pWorkData;
275 pWorkItem->workDataLen = 0;
276 pWorkItem->pWorkCbkCopy = NULL;
277 pWorkItem->pWorkCbkNoCopy = pWorkCbkNoCopy;
278 pWorkItem->pWorkCbkGeneric = NULL;
279 pWorkItem->delayMs = 0;
281 mutex_enter(&pUM->workqs.instq.workQueueMutex);
283 s_list_push_tail(&pUM->workqs.instq.workQueue, &pWorkItem->link);
284 pUM->workqs.instq.workItemQueued++;
285 if (s_list_entry_cnt(&pUM->workqs.instq.workQueue) >
286 pUM->workqs.instq.highWater)
288 pUM->workqs.instq.highWater =
289 s_list_entry_cnt(&pUM->workqs.instq.workQueue);
292 mutex_exit(&pUM->workqs.instq.workQueueMutex);
294 BnxeWorkQueueTrigger(pUM, &pUM->workqs.instq);
296 return B_TRUE;
300 boolean_t BnxeWorkQueueAddGeneric(um_device_t * pUM,
301 void (*pWorkCbkGeneric)(um_device_t *))
303 BnxeWorkItem * pWorkItem;
305 if ((pWorkItem = kmem_zalloc(sizeof(BnxeWorkItem), KM_NOSLEEP)) == NULL)
307 BnxeLogWarn(pUM, "Failed to allocate memory for work item!");
308 return B_FALSE;
311 pWorkItem->pWorkData = NULL;
312 pWorkItem->workDataLen = 0;
313 pWorkItem->pWorkCbkCopy = NULL;
314 pWorkItem->pWorkCbkNoCopy = NULL;
315 pWorkItem->pWorkCbkGeneric = pWorkCbkGeneric;
316 pWorkItem->delayMs = 0;
318 mutex_enter(&pUM->workqs.instq.workQueueMutex);
320 s_list_push_tail(&pUM->workqs.instq.workQueue, &pWorkItem->link);
321 pUM->workqs.instq.workItemQueued++;
322 if (s_list_entry_cnt(&pUM->workqs.instq.workQueue) >
323 pUM->workqs.instq.highWater)
325 pUM->workqs.instq.highWater =
326 s_list_entry_cnt(&pUM->workqs.instq.workQueue);
329 mutex_exit(&pUM->workqs.instq.workQueueMutex);
331 BnxeWorkQueueTrigger(pUM, &pUM->workqs.instq);
333 return B_TRUE;
337 boolean_t BnxeWorkQueueAddDelay(um_device_t * pUM,
338 void (*pWorkCbkCopy)(um_device_t *, void *, u32_t),
339 void * pWorkData,
340 u32_t workDataLen,
341 u32_t delayMs)
343 BnxeWorkItem * pWorkItem;
345 if ((pWorkItem = kmem_zalloc((sizeof(BnxeWorkItem) + workDataLen),
346 KM_NOSLEEP)) == NULL)
348 BnxeLogWarn(pUM, "Failed to allocate memory for work item!");
349 return B_FALSE;
352 pWorkItem->pWorkData = (pWorkItem + 1);
353 pWorkItem->workDataLen = workDataLen;
354 pWorkItem->pWorkCbkCopy = pWorkCbkCopy;
355 pWorkItem->pWorkCbkNoCopy = NULL;
356 pWorkItem->pWorkCbkGeneric = NULL;
357 pWorkItem->delayMs = delayMs;
359 memcpy(pWorkItem->pWorkData, pWorkData, workDataLen);
361 mutex_enter(&pUM->workqs.delayq.workQueueMutex);
363 s_list_push_tail(&pUM->workqs.delayq.workQueue, &pWorkItem->link);
364 pUM->workqs.delayq.workItemQueued++;
365 if (s_list_entry_cnt(&pUM->workqs.delayq.workQueue) >
366 pUM->workqs.delayq.highWater)
368 pUM->workqs.delayq.highWater =
369 s_list_entry_cnt(&pUM->workqs.delayq.workQueue);
372 mutex_exit(&pUM->workqs.delayq.workQueueMutex);
374 BnxeWorkQueueTrigger(pUM, &pUM->workqs.delayq);
376 return B_TRUE;
380 boolean_t BnxeWorkQueueAddDelayNoCopy(um_device_t * pUM,
381 void (*pWorkCbkNoCopy)(um_device_t *, void *),
382 void * pWorkData,
383 u32_t delayMs)
385 BnxeWorkItem * pWorkItem;
387 if ((pWorkItem = kmem_zalloc(sizeof(BnxeWorkItem), KM_NOSLEEP)) == NULL)
389 BnxeLogWarn(pUM, "Failed to allocate memory for work item!");
390 return B_FALSE;
393 pWorkItem->pWorkData = pWorkData;
394 pWorkItem->workDataLen = 0;
395 pWorkItem->pWorkCbkCopy = NULL;
396 pWorkItem->pWorkCbkNoCopy = pWorkCbkNoCopy;
397 pWorkItem->pWorkCbkGeneric = NULL;
398 pWorkItem->delayMs = delayMs;
400 mutex_enter(&pUM->workqs.delayq.workQueueMutex);
402 s_list_push_tail(&pUM->workqs.delayq.workQueue, &pWorkItem->link);
403 pUM->workqs.delayq.workItemQueued++;
404 if (s_list_entry_cnt(&pUM->workqs.delayq.workQueue) >
405 pUM->workqs.delayq.highWater)
407 pUM->workqs.delayq.highWater =
408 s_list_entry_cnt(&pUM->workqs.delayq.workQueue);
411 mutex_exit(&pUM->workqs.delayq.workQueueMutex);
413 BnxeWorkQueueTrigger(pUM, &pUM->workqs.delayq);
415 return B_TRUE;
419 boolean_t BnxeWorkQueueAddDelayGeneric(um_device_t * pUM,
420 void (*pWorkCbkGeneric)(um_device_t *),
421 u32_t delayMs)
423 BnxeWorkItem * pWorkItem;
425 if ((pWorkItem = kmem_zalloc(sizeof(BnxeWorkItem), KM_NOSLEEP)) == NULL)
427 BnxeLogWarn(pUM, "Failed to allocate memory for work item!");
428 return B_FALSE;
431 pWorkItem->pWorkData = NULL;
432 pWorkItem->workDataLen = 0;
433 pWorkItem->pWorkCbkCopy = NULL;
434 pWorkItem->pWorkCbkNoCopy = NULL;
435 pWorkItem->pWorkCbkGeneric = pWorkCbkGeneric;
436 pWorkItem->delayMs = delayMs;
438 mutex_enter(&pUM->workqs.delayq.workQueueMutex);
440 s_list_push_tail(&pUM->workqs.delayq.workQueue, &pWorkItem->link);
441 pUM->workqs.delayq.workItemQueued++;
442 if (s_list_entry_cnt(&pUM->workqs.delayq.workQueue) >
443 pUM->workqs.delayq.highWater)
445 pUM->workqs.delayq.highWater =
446 s_list_entry_cnt(&pUM->workqs.delayq.workQueue);
449 mutex_exit(&pUM->workqs.delayq.workQueueMutex);
451 BnxeWorkQueueTrigger(pUM, &pUM->workqs.delayq);
453 return B_TRUE;