xgehal-channel.c revision 173139
1/*-
2 * Copyright (c) 2002-2007 Neterion, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/sys/dev/nxge/xgehal/xgehal-channel.c 173139 2007-10-29 14:19:32Z rwatson $
27 */
28
29#include <dev/nxge/include/xgehal-channel.h>
30#include <dev/nxge/include/xgehal-fifo.h>
31#include <dev/nxge/include/xgehal-ring.h>
32#include <dev/nxge/include/xgehal-device.h>
33#include <dev/nxge/include/xgehal-regs.h>
34
35/*
36 * __hal_channel_dtr_next_reservelist
37 *
38 * Walking through the all available DTRs.
39 */
40static xge_hal_status_e
41__hal_channel_dtr_next_reservelist(xge_hal_channel_h channelh,
42	    xge_hal_dtr_h *dtrh)
43{
44	xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
45
46	if (channel->reserve_top >= channel->reserve_length) {
47	    return XGE_HAL_INF_NO_MORE_FREED_DESCRIPTORS;
48	}
49
50	*dtrh = channel->reserve_arr[channel->reserve_top++];
51
52	return XGE_HAL_OK;
53}
54
55/*
56 * __hal_channel_dtr_next_freelist
57 *
58 * Walking through the "freed" DTRs.
59 */
60static xge_hal_status_e
61__hal_channel_dtr_next_freelist(xge_hal_channel_h channelh, xge_hal_dtr_h *dtrh)
62{
63	xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
64
65	if (channel->reserve_initial == channel->free_length) {
66	    return XGE_HAL_INF_NO_MORE_FREED_DESCRIPTORS;
67	}
68
69	*dtrh = channel->free_arr[channel->free_length++];
70
71	return XGE_HAL_OK;
72}
73
74/*
75 * __hal_channel_dtr_next_not_completed - Get the _next_ posted but
76 *                                     not completed descriptor.
77 *
78 * Walking through the "not completed" DTRs.
79 */
80static xge_hal_status_e
81__hal_channel_dtr_next_not_completed(xge_hal_channel_h channelh,
82	    xge_hal_dtr_h *dtrh)
83{
84	xge_hal_ring_rxd_1_t *rxdp; /* doesn't matter 1, 3 or 5... */
85	__hal_channel_dtr_try_complete(channelh, dtrh);
86	if (*dtrh == NULL) {
87	    return XGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS;
88	}
89
90	rxdp = (xge_hal_ring_rxd_1_t *)*dtrh;
91	xge_assert(rxdp->host_control!=0);
92
93	__hal_channel_dtr_complete(channelh);
94
95	return XGE_HAL_OK;
96}
97
98xge_hal_channel_t*
99__hal_channel_allocate(xge_hal_device_h devh, int post_qid,
100	    xge_hal_channel_type_e type)
101{
102	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
103	xge_hal_channel_t *channel;
104	int size = 0;
105
106	switch(type) {
107	    case XGE_HAL_CHANNEL_TYPE_FIFO:
108	        xge_assert(post_qid + 1 >= XGE_HAL_MIN_FIFO_NUM &&
109	             post_qid + 1 <= XGE_HAL_MAX_FIFO_NUM);
110	        size = sizeof(xge_hal_fifo_t);
111	        break;
112	    case XGE_HAL_CHANNEL_TYPE_RING:
113	        xge_assert(post_qid + 1 >= XGE_HAL_MIN_RING_NUM &&
114	            post_qid + 1 <= XGE_HAL_MAX_RING_NUM);
115	        size = sizeof(xge_hal_ring_t);
116	        break;
117	    default :
118	        xge_assert(size);
119	        break;
120
121	}
122
123
124	/* allocate FIFO channel */
125	channel = (xge_hal_channel_t *) xge_os_malloc(hldev->pdev, size);
126	if (channel == NULL) {
127	    return NULL;
128	}
129	xge_os_memzero(channel, size);
130
131	channel->pdev       = hldev->pdev;
132	channel->regh0      = hldev->regh0;
133	channel->regh1      = hldev->regh1;
134	channel->type       = type;
135	channel->devh       = devh;
136	channel->post_qid   = post_qid;
137	channel->compl_qid  = 0;
138
139	return channel;
140}
141
142void __hal_channel_free(xge_hal_channel_t *channel)
143{
144	int size = 0;
145
146	xge_assert(channel->pdev);
147
148	switch(channel->type) {
149	    case XGE_HAL_CHANNEL_TYPE_FIFO:
150	        size = sizeof(xge_hal_fifo_t);
151	        break;
152	    case XGE_HAL_CHANNEL_TYPE_RING:
153	        size = sizeof(xge_hal_ring_t);
154	        break;
155	    case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE:
156	    case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE:
157	    case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE:
158	    case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE:
159	    case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE:
160	        xge_assert(size);
161	        break;
162	    default:
163	        break;
164	}
165
166	xge_os_free(channel->pdev, channel, size);
167}
168
169xge_hal_status_e
170__hal_channel_initialize (xge_hal_channel_h channelh,
171	    xge_hal_channel_attr_t *attr, void **reserve_arr,
172	    int reserve_initial, int reserve_max, int reserve_threshold)
173{
174	xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
175	xge_hal_device_t *hldev;
176
177	hldev = (xge_hal_device_t *)channel->devh;
178
179	channel->dtr_term = attr->dtr_term;
180	channel->dtr_init = attr->dtr_init;
181	channel->callback = attr->callback;
182	channel->userdata = attr->userdata;
183	channel->flags = attr->flags;
184	channel->per_dtr_space = attr->per_dtr_space;
185
186	channel->reserve_arr = reserve_arr;
187	channel->reserve_initial = reserve_initial;
188	channel->reserve_max = reserve_max;
189	channel->reserve_length = channel->reserve_initial;
190	channel->reserve_threshold = reserve_threshold;
191	channel->reserve_top = 0;
192	channel->saved_arr = (void **) xge_os_malloc(hldev->pdev,
193	                   sizeof(void*)*channel->reserve_max);
194	if (channel->saved_arr == NULL) {
195	    return XGE_HAL_ERR_OUT_OF_MEMORY;
196	}
197	xge_os_memzero(channel->saved_arr, sizeof(void*)*channel->reserve_max);
198	channel->free_arr = channel->saved_arr;
199	channel->free_length = channel->reserve_initial;
200	channel->work_arr = (void **) xge_os_malloc(hldev->pdev,
201	              sizeof(void*)*channel->reserve_max);
202	if (channel->work_arr == NULL) {
203	    return XGE_HAL_ERR_OUT_OF_MEMORY;
204	}
205	xge_os_memzero(channel->work_arr,
206	                   sizeof(void*)*channel->reserve_max);
207	channel->post_index = 0;
208	channel->compl_index = 0;
209	channel->length = channel->reserve_initial;
210
211	channel->orig_arr = (void **) xge_os_malloc(hldev->pdev,
212	                    sizeof(void*)*channel->reserve_max);
213	if (channel->orig_arr == NULL)
214	    return XGE_HAL_ERR_OUT_OF_MEMORY;
215
216	xge_os_memzero(channel->orig_arr, sizeof(void*)*channel->reserve_max);
217
218#if defined(XGE_HAL_RX_MULTI_FREE_IRQ) || defined(XGE_HAL_TX_MULTI_FREE_IRQ)
219	xge_os_spin_lock_init_irq(&channel->free_lock, hldev->irqh);
220#elif defined(XGE_HAL_RX_MULTI_FREE) || defined(XGE_HAL_TX_MULTI_FREE)
221	xge_os_spin_lock_init(&channel->free_lock, hldev->pdev);
222#endif
223
224	return XGE_HAL_OK;
225}
226
227void __hal_channel_terminate(xge_hal_channel_h channelh)
228{
229	xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
230	xge_hal_device_t *hldev;
231
232	hldev = (xge_hal_device_t *)channel->devh;
233
234	xge_assert(channel->pdev);
235	/* undo changes made at channel_initialize() */
236	if (channel->work_arr) {
237	    xge_os_free(channel->pdev, channel->work_arr,
238	              sizeof(void*)*channel->reserve_max);
239	    channel->work_arr = NULL;
240	}
241
242	if (channel->saved_arr) {
243	    xge_os_free(channel->pdev, channel->saved_arr,
244	              sizeof(void*)*channel->reserve_max);
245	    channel->saved_arr = NULL;
246	}
247
248	if (channel->orig_arr) {
249	    xge_os_free(channel->pdev, channel->orig_arr,
250	              sizeof(void*)*channel->reserve_max);
251	    channel->orig_arr = NULL;
252	}
253
254#if defined(XGE_HAL_RX_MULTI_FREE_IRQ) || defined(XGE_HAL_TX_MULTI_FREE_IRQ)
255	xge_os_spin_lock_destroy_irq(&channel->free_lock, hldev->irqh);
256#elif defined(XGE_HAL_RX_MULTI_FREE) || defined(XGE_HAL_TX_MULTI_FREE)
257	xge_os_spin_lock_destroy(&channel->free_lock, hldev->pdev);
258#endif
259}
260
261/**
262 * xge_hal_channel_open - Open communication channel.
263 * @devh: HAL device, pointer to xge_hal_device_t structure.
264 * @attr: Contains attributes required to open
265 *        the channel.
266 * @channelh:  The channel handle. On success (XGE_HAL_OK) HAL fills
267 * this "out" parameter with a valid channel handle.
268 * @reopen: See  xge_hal_channel_reopen_e{}.
269 *
270 * Open communication channel with the device.
271 *
272 * HAL uses (persistent) channel configuration to allocate both channel
273 * and Xframe Tx and Rx descriptors.
274 * Notes:
275 *     1) The channel config data is fed into HAL prior to
276 *        xge_hal_channel_open().
277 *
278 *     2) The corresponding hardware queues must be already configured and
279 *        enabled.
280 *
281 *     3) Either down or up queue may be omitted, in which case the channel
282 *        is treated as _unidirectional_.
283 *
284 *     4) Post and completion queue may be the same, in which case the channel
285 *        is said to have "in-band completions".
286 *
287 * Note that free_channels list is not protected. i.e. caller must provide
288 * safe context.
289 *
290 * Returns: XGE_HAL_OK  - success.
291 * XGE_HAL_ERR_CHANNEL_NOT_FOUND - Unable to locate the channel.
292 * XGE_HAL_ERR_OUT_OF_MEMORY - Memory allocation failed.
293 *
294 * See also: xge_hal_channel_attr_t{}.
295 * Usage: See ex_open{}.
296 */
297xge_hal_status_e
298xge_hal_channel_open(xge_hal_device_h devh,
299	         xge_hal_channel_attr_t *attr,
300	         xge_hal_channel_h *channelh,
301	         xge_hal_channel_reopen_e reopen)
302{
303	xge_list_t *item;
304	int i;
305	xge_hal_status_e status = XGE_HAL_OK;
306	xge_hal_channel_t *channel = NULL;
307	xge_hal_device_t *device = (xge_hal_device_t *)devh;
308
309	xge_assert(device);
310	xge_assert(attr);
311
312	*channelh = NULL;
313
314	/* find channel */
315	xge_list_for_each(item, &device->free_channels) {
316	    xge_hal_channel_t *tmp;
317
318	    tmp = xge_container_of(item, xge_hal_channel_t, item);
319	    if (tmp->type == attr->type &&
320	    tmp->post_qid == attr->post_qid &&
321	    tmp->compl_qid == attr->compl_qid) {
322	        channel = tmp;
323	        break;
324	    }
325	}
326
327	if (channel == NULL) {
328	    return XGE_HAL_ERR_CHANNEL_NOT_FOUND;
329	}
330
331	xge_assert((channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) ||
332	    (channel->type == XGE_HAL_CHANNEL_TYPE_RING));
333
334	if (reopen == XGE_HAL_CHANNEL_OC_NORMAL) {
335	    /* allocate memory, initialize pointers, etc */
336	    switch(channel->type) {
337	        case XGE_HAL_CHANNEL_TYPE_FIFO:
338	            status = __hal_fifo_open(channel, attr);
339	            break;
340	        case XGE_HAL_CHANNEL_TYPE_RING:
341	            status = __hal_ring_open(channel, attr);
342	            break;
343	        case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE:
344	        case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE:
345	        case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE:
346	        case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE:
347	        case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE:
348	            status = XGE_HAL_FAIL;
349	            break;
350	        default:
351	            break;
352	    }
353
354	    if (status == XGE_HAL_OK) {
355	        for (i = 0; i < channel->reserve_initial; i++) {
356	            channel->orig_arr[i] =
357	                channel->reserve_arr[i];
358	        }
359	    }
360	    else
361	        return status;
362	} else {
363	        xge_assert(reopen == XGE_HAL_CHANNEL_RESET_ONLY);
364
365	    for (i = 0; i < channel->reserve_initial; i++) {
366	        channel->reserve_arr[i] = channel->orig_arr[i];
367	        channel->free_arr[i] = NULL;
368	    }
369	    channel->free_length = channel->reserve_initial;
370	    channel->reserve_length = channel->reserve_initial;
371	    channel->reserve_top = 0;
372	    channel->post_index = 0;
373	    channel->compl_index = 0;
374	            if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) {
375	        status = __hal_ring_initial_replenish(channel,
376	                              reopen);
377	                    if (status != XGE_HAL_OK)
378	                            return status;
379	    }
380	}
381
382	/* move channel to the open state list */
383
384	switch(channel->type) {
385	    case XGE_HAL_CHANNEL_TYPE_FIFO:
386	        xge_list_remove(&channel->item);
387	        xge_list_insert(&channel->item, &device->fifo_channels);
388	        break;
389	    case XGE_HAL_CHANNEL_TYPE_RING:
390	        xge_list_remove(&channel->item);
391	        xge_list_insert(&channel->item, &device->ring_channels);
392	        break;
393	    case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE:
394	    case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE:
395	    case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE:
396	    case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE:
397	    case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE:
398	        xge_assert(channel->type == XGE_HAL_CHANNEL_TYPE_FIFO ||
399	               channel->type == XGE_HAL_CHANNEL_TYPE_RING);
400	        break;
401	    default:
402	        break;
403	}
404	channel->is_open = 1;
405	channel->terminating = 0;
406	/*
407	 * The magic check the argument validity, has to be
408	 * removed before 03/01/2005.
409	 */
410	channel->magic = XGE_HAL_MAGIC;
411
412	*channelh = channel;
413
414	return XGE_HAL_OK;
415}
416
417/**
418 * xge_hal_channel_abort - Abort the channel.
419 * @channelh: Channel handle.
420 * @reopen: See  xge_hal_channel_reopen_e{}.
421 *
422 * Terminate (via xge_hal_channel_dtr_term_f{}) all channel descriptors.
423 * Currently used internally only by HAL, as part of its
424 * xge_hal_channel_close() and xge_hal_channel_open() in case
425 * of fatal error.
426 *
427 * See also: xge_hal_channel_dtr_term_f{}.
428 */
429void xge_hal_channel_abort(xge_hal_channel_h channelh,
430	                       xge_hal_channel_reopen_e reopen)
431{
432	xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
433	xge_hal_dtr_h dtr;
434#ifdef XGE_OS_MEMORY_CHECK
435	int check_cnt = 0;
436#endif
437	int free_length_sav;
438	int reserve_top_sav;
439
440	if (channel->dtr_term == NULL) {
441	    return;
442	}
443
444	free_length_sav = channel->free_length;
445	while (__hal_channel_dtr_next_freelist(channelh, &dtr) == XGE_HAL_OK) {
446#ifdef XGE_OS_MEMORY_CHECK
447#ifdef XGE_DEBUG_ASSERT
448	    if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) {
449	        xge_assert(!__hal_fifo_txdl_priv(dtr)->allocated);
450	    } else {
451	        if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) {
452	            xge_assert(!__hal_ring_rxd_priv((xge_hal_ring_t * ) channelh, dtr)->allocated);
453	        }
454	    }
455#endif
456	    check_cnt++;
457#endif
458	    channel->dtr_term(channel, dtr, XGE_HAL_DTR_STATE_FREED,
459	              channel->userdata, reopen);
460	}
461	channel->free_length = free_length_sav;
462
463	while (__hal_channel_dtr_next_not_completed(channelh, &dtr) ==
464	       XGE_HAL_OK) {
465#ifdef XGE_OS_MEMORY_CHECK
466#ifdef XGE_DEBUG_ASSERT
467	    if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) {
468	        xge_assert(__hal_fifo_txdl_priv(dtr)->allocated);
469	    } else {
470	        if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) {
471	        xge_assert(__hal_ring_rxd_priv((xge_hal_ring_t * ) channelh, dtr)
472	               ->allocated);
473	        }
474	    }
475#endif
476	    check_cnt++;
477#endif
478	    channel->dtr_term(channel, dtr, XGE_HAL_DTR_STATE_POSTED,
479	              channel->userdata, reopen);
480
481	}
482
483	reserve_top_sav = channel->reserve_top;
484	while (__hal_channel_dtr_next_reservelist(channelh, &dtr) ==
485	                        XGE_HAL_OK) {
486#ifdef XGE_OS_MEMORY_CHECK
487#ifdef XGE_DEBUG_ASSERT
488	    if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) {
489	        xge_assert(!__hal_fifo_txdl_priv(dtr)->allocated);
490	    } else {
491	        if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) {
492	        xge_assert(!__hal_ring_rxd_priv((xge_hal_ring_t * ) channelh, dtr)->allocated);
493	        }
494	    }
495#endif
496	    check_cnt++;
497#endif
498	    channel->dtr_term(channel, dtr, XGE_HAL_DTR_STATE_AVAIL,
499	              channel->userdata, reopen);
500	}
501	channel->reserve_top = reserve_top_sav;
502
503	xge_assert(channel->reserve_length ==
504	            (channel->free_length + channel->reserve_top));
505
506#ifdef XGE_OS_MEMORY_CHECK
507	xge_assert(check_cnt == channel->reserve_initial);
508#endif
509
510}
511
512/**
513 * xge_hal_channel_close - Close communication channel.
514 * @channelh: The channel handle.
515 * @reopen: See  xge_hal_channel_reopen_e{}.
516 *
517 * Will close previously opened channel and deallocate associated resources.
518 * Channel must be opened otherwise assert will be generated.
519 * Note that free_channels list is not protected. i.e. caller must provide
520 * safe context.
521 */
522void xge_hal_channel_close(xge_hal_channel_h channelh,
523	                       xge_hal_channel_reopen_e reopen)
524{
525	xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
526	xge_hal_device_t *hldev;
527	xge_list_t *item;
528	xge_assert(channel);
529	xge_assert(channel->type < XGE_HAL_CHANNEL_TYPE_MAX);
530
531	hldev = (xge_hal_device_t *)channel->devh;
532	channel->is_open = 0;
533	channel->magic = XGE_HAL_DEAD;
534
535	/* sanity check: make sure channel is not in free list */
536	xge_list_for_each(item, &hldev->free_channels) {
537	    xge_hal_channel_t *tmp;
538
539	    tmp = xge_container_of(item, xge_hal_channel_t, item);
540	    xge_assert(!tmp->is_open);
541	    if (channel == tmp) {
542	        return;
543	    }
544	}
545
546	xge_hal_channel_abort(channel, reopen);
547
548	xge_assert((channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) ||
549	       (channel->type == XGE_HAL_CHANNEL_TYPE_RING));
550
551	if (reopen == XGE_HAL_CHANNEL_OC_NORMAL) {
552	    /* de-allocate */
553	    switch(channel->type) {
554	        case XGE_HAL_CHANNEL_TYPE_FIFO:
555	            __hal_fifo_close(channelh);
556	            break;
557	        case XGE_HAL_CHANNEL_TYPE_RING:
558	            __hal_ring_close(channelh);
559	            break;
560	        case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE:
561	        case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE:
562	        case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE:
563	        case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE:
564	        case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE:
565	            xge_assert(channel->type == XGE_HAL_CHANNEL_TYPE_FIFO ||
566	                   channel->type == XGE_HAL_CHANNEL_TYPE_RING);
567	            break;
568	        default:
569	            break;
570	    }
571	}
572	else
573	        xge_assert(reopen == XGE_HAL_CHANNEL_RESET_ONLY);
574
575	/* move channel back to free state list */
576	xge_list_remove(&channel->item);
577	xge_list_insert(&channel->item, &hldev->free_channels);
578
579	if (xge_list_is_empty(&hldev->fifo_channels) &&
580	    xge_list_is_empty(&hldev->ring_channels)) {
581	    /* clear msix_idx in case of following HW reset */
582	    hldev->reset_needed_after_close = 1;
583	}
584}
585