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]
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.
38 typedef struct _BnxeWorkItem
44 void (*pWorkCbkCopy
)(um_device_t
*, void *, u32_t
);
45 void (*pWorkCbkNoCopy
)(um_device_t
*, void *);
46 void (*pWorkCbkGeneric
)(um_device_t
*);
50 static void BnxeWorkQueueInstanceWaitAndDestroy(BnxeWorkQueueInstance
* pWorkq
)
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
,
80 BnxeLogWarn(pUM
, "Failed to create the workqs instq");
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? */
99 BnxeLogWarn(pUM
, "Failed to create the workqs delayq");
100 BnxeWorkQueueInstanceWaitAndDestroy(&pUM
->workqs
.instq
);
104 pUM
->workqs
.delayq
.pUM
= pUM
;
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
++;
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
,
185 BnxeLogInfo(pUM
, "Delaying WorkQ item since chip not yet started.");
190 void BnxeWorkQueueStartPending(um_device_t
* pUM
)
194 if (!pUM
->chipStarted
)
196 BnxeLogWarn(pUM
, "Triggering WorkQs and chip not started!");
200 mutex_enter(&pUM
->workqs
.instq
.workQueueMutex
);
201 cnt
= s_list_entry_cnt(&pUM
->workqs
.instq
.workQueue
);
202 mutex_exit(&pUM
->workqs
.instq
.workQueueMutex
);
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
);
215 BnxeWorkQueueTrigger(pUM
, &pUM
->workqs
.delayq
);
220 boolean_t
BnxeWorkQueueAdd(um_device_t
* pUM
,
221 void (*pWorkCbkCopy
)(um_device_t
*, void *, u32_t
),
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!");
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
);
262 boolean_t
BnxeWorkQueueAddNoCopy(um_device_t
* pUM
,
263 void (*pWorkCbkNoCopy
)(um_device_t
*, void *),
266 BnxeWorkItem
* pWorkItem
;
268 if ((pWorkItem
= kmem_zalloc(sizeof(BnxeWorkItem
), KM_NOSLEEP
)) == NULL
)
270 BnxeLogWarn(pUM
, "Failed to allocate memory for work item!");
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
);
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!");
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
);
337 boolean_t
BnxeWorkQueueAddDelay(um_device_t
* pUM
,
338 void (*pWorkCbkCopy
)(um_device_t
*, void *, u32_t
),
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!");
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
);
380 boolean_t
BnxeWorkQueueAddDelayNoCopy(um_device_t
* pUM
,
381 void (*pWorkCbkNoCopy
)(um_device_t
*, void *),
385 BnxeWorkItem
* pWorkItem
;
387 if ((pWorkItem
= kmem_zalloc(sizeof(BnxeWorkItem
), KM_NOSLEEP
)) == NULL
)
389 BnxeLogWarn(pUM
, "Failed to allocate memory for work item!");
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
);
419 boolean_t
BnxeWorkQueueAddDelayGeneric(um_device_t
* pUM
,
420 void (*pWorkCbkGeneric
)(um_device_t
*),
423 BnxeWorkItem
* pWorkItem
;
425 if ((pWorkItem
= kmem_zalloc(sizeof(BnxeWorkItem
), KM_NOSLEEP
)) == NULL
)
427 BnxeLogWarn(pUM
, "Failed to allocate memory for work item!");
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
);