GNU Linux-libre 5.10.215-gnu1
[releases.git] / drivers / staging / rtl8723bs / core / rtw_sta_mgt.c
1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  *
4  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
5  *
6  ******************************************************************************/
7 #define _RTW_STA_MGT_C_
8
9 #include <drv_types.h>
10 #include <rtw_debug.h>
11
12 void _rtw_init_stainfo(struct sta_info *psta);
13 void _rtw_init_stainfo(struct sta_info *psta)
14 {
15         memset((u8 *)psta, 0, sizeof(struct sta_info));
16
17         spin_lock_init(&psta->lock);
18         INIT_LIST_HEAD(&psta->list);
19         INIT_LIST_HEAD(&psta->hash_list);
20         /* INIT_LIST_HEAD(&psta->asoc_list); */
21         /* INIT_LIST_HEAD(&psta->sleep_list); */
22         /* INIT_LIST_HEAD(&psta->wakeup_list); */
23
24         _rtw_init_queue(&psta->sleep_q);
25         psta->sleepq_len = 0;
26
27         _rtw_init_sta_xmit_priv(&psta->sta_xmitpriv);
28         _rtw_init_sta_recv_priv(&psta->sta_recvpriv);
29
30         INIT_LIST_HEAD(&psta->asoc_list);
31
32         INIT_LIST_HEAD(&psta->auth_list);
33
34         psta->expire_to = 0;
35
36         psta->flags = 0;
37
38         psta->capability = 0;
39
40         psta->bpairwise_key_installed = false;
41
42         psta->nonerp_set = 0;
43         psta->no_short_slot_time_set = 0;
44         psta->no_short_preamble_set = 0;
45         psta->no_ht_gf_set = 0;
46         psta->no_ht_set = 0;
47         psta->ht_20mhz_set = 0;
48
49         psta->under_exist_checking = 0;
50
51         psta->keep_alive_trycnt = 0;
52 }
53
54 u32 _rtw_init_sta_priv(struct   sta_priv *pstapriv)
55 {
56         struct sta_info *psta;
57         s32 i;
58
59         pstapriv->pallocated_stainfo_buf = vzalloc(sizeof(struct sta_info) * NUM_STA+4);
60
61         if (!pstapriv->pallocated_stainfo_buf)
62                 return _FAIL;
63
64         pstapriv->pstainfo_buf = pstapriv->pallocated_stainfo_buf + 4 -
65                 ((SIZE_PTR)(pstapriv->pallocated_stainfo_buf) & 3);
66
67         _rtw_init_queue(&pstapriv->free_sta_queue);
68
69         spin_lock_init(&pstapriv->sta_hash_lock);
70
71         /* _rtw_init_queue(&pstapriv->asoc_q); */
72         pstapriv->asoc_sta_count = 0;
73         _rtw_init_queue(&pstapriv->sleep_q);
74         _rtw_init_queue(&pstapriv->wakeup_q);
75
76         psta = (struct sta_info *)(pstapriv->pstainfo_buf);
77
78         for (i = 0; i < NUM_STA; i++) {
79                 _rtw_init_stainfo(psta);
80
81                 INIT_LIST_HEAD(&(pstapriv->sta_hash[i]));
82
83                 list_add_tail(&psta->list, get_list_head(&pstapriv->free_sta_queue));
84
85                 psta++;
86         }
87
88         pstapriv->sta_dz_bitmap = 0;
89         pstapriv->tim_bitmap = 0;
90
91         INIT_LIST_HEAD(&pstapriv->asoc_list);
92         INIT_LIST_HEAD(&pstapriv->auth_list);
93         spin_lock_init(&pstapriv->asoc_list_lock);
94         spin_lock_init(&pstapriv->auth_list_lock);
95         pstapriv->asoc_list_cnt = 0;
96         pstapriv->auth_list_cnt = 0;
97
98         pstapriv->auth_to = 3; /*  3*2 = 6 sec */
99         pstapriv->assoc_to = 3;
100         pstapriv->expire_to = 3; /*  3*2 = 6 sec */
101         pstapriv->max_num_sta = NUM_STA;
102         return _SUCCESS;
103 }
104
105 inline int rtw_stainfo_offset(struct sta_priv *stapriv, struct sta_info *sta)
106 {
107         int offset = (((u8 *)sta) - stapriv->pstainfo_buf)/sizeof(struct sta_info);
108
109         if (!stainfo_offset_valid(offset))
110                 DBG_871X("%s invalid offset(%d), out of range!!!", __func__, offset);
111
112         return offset;
113 }
114
115 inline struct sta_info *rtw_get_stainfo_by_offset(struct sta_priv *stapriv, int offset)
116 {
117         if (!stainfo_offset_valid(offset))
118                 DBG_871X("%s invalid offset(%d), out of range!!!", __func__, offset);
119
120         return (struct sta_info *)(stapriv->pstainfo_buf + offset * sizeof(struct sta_info));
121 }
122
123 /*  this function is used to free the memory of lock || sema for all stainfos */
124 void kfree_all_stainfo(struct sta_priv *pstapriv);
125 void kfree_all_stainfo(struct sta_priv *pstapriv)
126 {
127         struct list_head        *plist, *phead;
128         struct sta_info *psta = NULL;
129
130         spin_lock_bh(&pstapriv->sta_hash_lock);
131
132         phead = get_list_head(&pstapriv->free_sta_queue);
133         plist = get_next(phead);
134
135         while (phead != plist) {
136                 psta = LIST_CONTAINOR(plist, struct sta_info, list);
137                 plist = get_next(plist);
138         }
139
140         spin_unlock_bh(&pstapriv->sta_hash_lock);
141 }
142
143 void kfree_sta_priv_lock(struct sta_priv *pstapriv);
144 void kfree_sta_priv_lock(struct sta_priv *pstapriv)
145 {
146          kfree_all_stainfo(pstapriv); /* be done before free sta_hash_lock */
147 }
148
149 u32 _rtw_free_sta_priv(struct   sta_priv *pstapriv)
150 {
151         struct list_head        *phead, *plist;
152         struct sta_info *psta = NULL;
153         struct recv_reorder_ctrl *preorder_ctrl;
154         int     index;
155
156         if (pstapriv) {
157
158                 /*delete all reordering_ctrl_timer              */
159                 spin_lock_bh(&pstapriv->sta_hash_lock);
160                 for (index = 0; index < NUM_STA; index++) {
161                         phead = &(pstapriv->sta_hash[index]);
162                         plist = get_next(phead);
163
164                         while (phead != plist) {
165                                 int i;
166                                 psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
167                                 plist = get_next(plist);
168
169                                 for (i = 0; i < 16 ; i++) {
170                                         preorder_ctrl = &psta->recvreorder_ctrl[i];
171                                         del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
172                                 }
173                         }
174                 }
175                 spin_unlock_bh(&pstapriv->sta_hash_lock);
176                 /*===============================*/
177
178                 kfree_sta_priv_lock(pstapriv);
179
180                 if (pstapriv->pallocated_stainfo_buf)
181                         vfree(pstapriv->pallocated_stainfo_buf);
182
183         }
184         return _SUCCESS;
185 }
186
187 /* struct       sta_info *rtw_alloc_stainfo(_queue *pfree_sta_queue, unsigned char *hwaddr) */
188 struct  sta_info *rtw_alloc_stainfo(struct      sta_priv *pstapriv, u8 *hwaddr)
189 {
190         s32     index;
191         struct list_head        *phash_list;
192         struct sta_info *psta;
193         struct __queue *pfree_sta_queue;
194         struct recv_reorder_ctrl *preorder_ctrl;
195         int i = 0;
196         u16  wRxSeqInitialValue = 0xffff;
197
198         pfree_sta_queue = &pstapriv->free_sta_queue;
199
200         /* spin_lock_bh(&(pfree_sta_queue->lock)); */
201         spin_lock_bh(&(pstapriv->sta_hash_lock));
202         if (list_empty(&pfree_sta_queue->queue)) {
203                 /* spin_unlock_bh(&(pfree_sta_queue->lock)); */
204                 spin_unlock_bh(&(pstapriv->sta_hash_lock));
205                 return NULL;
206         } else {
207                 psta = LIST_CONTAINOR(get_next(&pfree_sta_queue->queue), struct sta_info, list);
208
209                 list_del_init(&(psta->list));
210
211                 /* spin_unlock_bh(&(pfree_sta_queue->lock)); */
212
213                 _rtw_init_stainfo(psta);
214
215                 psta->padapter = pstapriv->padapter;
216
217                 memcpy(psta->hwaddr, hwaddr, ETH_ALEN);
218
219                 index = wifi_mac_hash(hwaddr);
220
221                 RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_, ("rtw_alloc_stainfo: index  = %x", index));
222
223                 if (index >= NUM_STA) {
224                         RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, ("ERROR => rtw_alloc_stainfo: index >= NUM_STA"));
225                         spin_unlock_bh(&(pstapriv->sta_hash_lock));
226                         psta = NULL;
227                         goto exit;
228                 }
229                 phash_list = &(pstapriv->sta_hash[index]);
230
231                 /* spin_lock_bh(&(pstapriv->sta_hash_lock)); */
232
233                 list_add_tail(&psta->hash_list, phash_list);
234
235                 pstapriv->asoc_sta_count++;
236
237                 /* spin_unlock_bh(&(pstapriv->sta_hash_lock)); */
238
239 /*  Commented by Albert 2009/08/13 */
240 /*  For the SMC router, the sequence number of first packet of WPS handshake will be 0. */
241 /*  In this case, this packet will be dropped by recv_decache function if we use the 0x00 as the default value for tid_rxseq variable. */
242 /*  So, we initialize the tid_rxseq variable as the 0xffff. */
243
244                 for (i = 0; i < 16; i++) {
245                         memcpy(&psta->sta_recvpriv.rxcache.tid_rxseq[i], &wRxSeqInitialValue, 2);
246                 }
247
248                 RT_TRACE(
249                         _module_rtl871x_sta_mgt_c_,
250                         _drv_info_, (
251                                 "alloc number_%d stainfo  with hwaddr = %x %x %x %x %x %x \n",
252                                 pstapriv->asoc_sta_count,
253                                 hwaddr[0],
254                                 hwaddr[1],
255                                 hwaddr[2],
256                                 hwaddr[3],
257                                 hwaddr[4],
258                                 hwaddr[5]
259                         )
260                 );
261
262                 init_addba_retry_timer(pstapriv->padapter, psta);
263
264                 /* for A-MPDU Rx reordering buffer control */
265                 for (i = 0; i < 16 ; i++) {
266                         preorder_ctrl = &psta->recvreorder_ctrl[i];
267
268                         preorder_ctrl->padapter = pstapriv->padapter;
269
270                         preorder_ctrl->enable = false;
271
272                         preorder_ctrl->indicate_seq = 0xffff;
273                         #ifdef DBG_RX_SEQ
274                         DBG_871X("DBG_RX_SEQ %s:%d IndicateSeq: %d\n", __func__, __LINE__,
275                                 preorder_ctrl->indicate_seq);
276                         #endif
277                         preorder_ctrl->wend_b = 0xffff;
278                         /* preorder_ctrl->wsize_b = (NR_RECVBUFF-2); */
279                         preorder_ctrl->wsize_b = 64;/* 64; */
280
281                         _rtw_init_queue(&preorder_ctrl->pending_recvframe_queue);
282
283                         rtw_init_recv_timer(preorder_ctrl);
284                 }
285
286
287                 /* init for DM */
288                 psta->rssi_stat.UndecoratedSmoothedPWDB = (-1);
289                 psta->rssi_stat.UndecoratedSmoothedCCK = (-1);
290
291                 /* init for the sequence number of received management frame */
292                 psta->RxMgmtFrameSeqNum = 0xffff;
293                 spin_unlock_bh(&(pstapriv->sta_hash_lock));
294                 /* alloc mac id for non-bc/mc station, */
295                 rtw_alloc_macid(pstapriv->padapter, psta);
296
297         }
298
299 exit:
300
301
302         return psta;
303 }
304
305 /*  using pstapriv->sta_hash_lock to protect */
306 u32 rtw_free_stainfo(struct adapter *padapter, struct sta_info *psta)
307 {
308         int i;
309         struct __queue *pfree_sta_queue;
310         struct recv_reorder_ctrl *preorder_ctrl;
311         struct  sta_xmit_priv *pstaxmitpriv;
312         struct  xmit_priv *pxmitpriv = &padapter->xmitpriv;
313         struct  sta_priv *pstapriv = &padapter->stapriv;
314         struct hw_xmit *phwxmit;
315
316         if (!psta)
317                 goto exit;
318
319
320         spin_lock_bh(&psta->lock);
321         psta->state &= ~_FW_LINKED;
322         spin_unlock_bh(&psta->lock);
323
324         pfree_sta_queue = &pstapriv->free_sta_queue;
325
326
327         pstaxmitpriv = &psta->sta_xmitpriv;
328
329         /* list_del_init(&psta->sleep_list); */
330
331         /* list_del_init(&psta->wakeup_list); */
332
333         spin_lock_bh(&pxmitpriv->lock);
334
335         rtw_free_xmitframe_queue(pxmitpriv, &psta->sleep_q);
336         psta->sleepq_len = 0;
337
338         /* vo */
339         /* spin_lock_bh(&(pxmitpriv->vo_pending.lock)); */
340         rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vo_q.sta_pending);
341         list_del_init(&(pstaxmitpriv->vo_q.tx_pending));
342         phwxmit = pxmitpriv->hwxmits;
343         phwxmit->accnt -= pstaxmitpriv->vo_q.qcnt;
344         pstaxmitpriv->vo_q.qcnt = 0;
345         /* spin_unlock_bh(&(pxmitpriv->vo_pending.lock)); */
346
347         /* vi */
348         /* spin_lock_bh(&(pxmitpriv->vi_pending.lock)); */
349         rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vi_q.sta_pending);
350         list_del_init(&(pstaxmitpriv->vi_q.tx_pending));
351         phwxmit = pxmitpriv->hwxmits+1;
352         phwxmit->accnt -= pstaxmitpriv->vi_q.qcnt;
353         pstaxmitpriv->vi_q.qcnt = 0;
354         /* spin_unlock_bh(&(pxmitpriv->vi_pending.lock)); */
355
356         /* be */
357         /* spin_lock_bh(&(pxmitpriv->be_pending.lock)); */
358         rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->be_q.sta_pending);
359         list_del_init(&(pstaxmitpriv->be_q.tx_pending));
360         phwxmit = pxmitpriv->hwxmits+2;
361         phwxmit->accnt -= pstaxmitpriv->be_q.qcnt;
362         pstaxmitpriv->be_q.qcnt = 0;
363         /* spin_unlock_bh(&(pxmitpriv->be_pending.lock)); */
364
365         /* bk */
366         /* spin_lock_bh(&(pxmitpriv->bk_pending.lock)); */
367         rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->bk_q.sta_pending);
368         list_del_init(&(pstaxmitpriv->bk_q.tx_pending));
369         phwxmit = pxmitpriv->hwxmits+3;
370         phwxmit->accnt -= pstaxmitpriv->bk_q.qcnt;
371         pstaxmitpriv->bk_q.qcnt = 0;
372         /* spin_unlock_bh(&(pxmitpriv->bk_pending.lock)); */
373
374         spin_unlock_bh(&pxmitpriv->lock);
375
376         list_del_init(&psta->hash_list);
377         RT_TRACE(
378                 _module_rtl871x_sta_mgt_c_,
379                 _drv_err_, (
380                         "\n free number_%d stainfo  with hwaddr = 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x \n",
381                         pstapriv->asoc_sta_count,
382                         psta->hwaddr[0],
383                         psta->hwaddr[1],
384                         psta->hwaddr[2],
385                         psta->hwaddr[3],
386                         psta->hwaddr[4],
387                         psta->hwaddr[5]
388                 )
389         );
390         pstapriv->asoc_sta_count--;
391
392         /*  re-init sta_info; 20061114 will be init in alloc_stainfo */
393         /* _rtw_init_sta_xmit_priv(&psta->sta_xmitpriv); */
394         /* _rtw_init_sta_recv_priv(&psta->sta_recvpriv); */
395
396         del_timer_sync(&psta->addba_retry_timer);
397
398         /* for A-MPDU Rx reordering buffer control, cancel reordering_ctrl_timer */
399         for (i = 0; i < 16 ; i++) {
400                 struct list_head        *phead, *plist;
401                 union recv_frame *prframe;
402                 struct __queue *ppending_recvframe_queue;
403                 struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
404
405                 preorder_ctrl = &psta->recvreorder_ctrl[i];
406
407                 del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
408
409
410                 ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
411
412                 spin_lock_bh(&ppending_recvframe_queue->lock);
413
414                 phead =         get_list_head(ppending_recvframe_queue);
415                 plist = get_next(phead);
416
417                 while (!list_empty(phead)) {
418                         prframe = (union recv_frame *)plist;
419
420                         plist = get_next(plist);
421
422                         list_del_init(&(prframe->u.hdr.list));
423
424                         rtw_free_recvframe(prframe, pfree_recv_queue);
425                 }
426
427                 spin_unlock_bh(&ppending_recvframe_queue->lock);
428
429         }
430
431         if (!(psta->state & WIFI_AP_STATE))
432                 rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, false);
433
434         /* release mac id for non-bc/mc station, */
435         rtw_release_macid(pstapriv->padapter, psta);
436
437 /*
438         spin_lock_bh(&pstapriv->asoc_list_lock);
439         list_del_init(&psta->asoc_list);
440         spin_unlock_bh(&pstapriv->asoc_list_lock);
441 */
442         spin_lock_bh(&pstapriv->auth_list_lock);
443         if (!list_empty(&psta->auth_list)) {
444                 list_del_init(&psta->auth_list);
445                 pstapriv->auth_list_cnt--;
446         }
447         spin_unlock_bh(&pstapriv->auth_list_lock);
448
449         psta->expire_to = 0;
450         psta->sleepq_ac_len = 0;
451         psta->qos_info = 0;
452
453         psta->max_sp_len = 0;
454         psta->uapsd_bk = 0;
455         psta->uapsd_be = 0;
456         psta->uapsd_vi = 0;
457         psta->uapsd_vo = 0;
458
459         psta->has_legacy_ac = 0;
460
461         pstapriv->sta_dz_bitmap &= ~BIT(psta->aid);
462         pstapriv->tim_bitmap &= ~BIT(psta->aid);
463
464         if ((psta->aid > 0) && (pstapriv->sta_aid[psta->aid - 1] == psta)) {
465                 pstapriv->sta_aid[psta->aid - 1] = NULL;
466                 psta->aid = 0;
467         }
468
469         psta->under_exist_checking = 0;
470
471         /* spin_lock_bh(&(pfree_sta_queue->lock)); */
472         list_add_tail(&psta->list, get_list_head(pfree_sta_queue));
473         /* spin_unlock_bh(&(pfree_sta_queue->lock)); */
474
475 exit:
476         return _SUCCESS;
477 }
478
479 /*  free all stainfo which in sta_hash[all] */
480 void rtw_free_all_stainfo(struct adapter *padapter)
481 {
482         struct list_head        *plist, *phead;
483         s32     index;
484         struct sta_info *psta = NULL;
485         struct  sta_priv *pstapriv = &padapter->stapriv;
486         struct sta_info *pbcmc_stainfo = rtw_get_bcmc_stainfo(padapter);
487
488         if (pstapriv->asoc_sta_count == 1)
489                 return;
490
491         spin_lock_bh(&pstapriv->sta_hash_lock);
492
493         for (index = 0; index < NUM_STA; index++) {
494                 phead = &(pstapriv->sta_hash[index]);
495                 plist = get_next(phead);
496
497                 while (phead != plist) {
498                         psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
499
500                         plist = get_next(plist);
501
502                         if (pbcmc_stainfo != psta)
503                                 rtw_free_stainfo(padapter, psta);
504
505                 }
506         }
507
508         spin_unlock_bh(&pstapriv->sta_hash_lock);
509 }
510
511 /* any station allocated can be searched by hash list */
512 struct sta_info *rtw_get_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
513 {
514         struct list_head        *plist, *phead;
515         struct sta_info *psta = NULL;
516         u32 index;
517         u8 *addr;
518         u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
519
520         if (!hwaddr)
521                 return NULL;
522
523         if (IS_MCAST(hwaddr))
524                 addr = bc_addr;
525         else
526                 addr = hwaddr;
527
528         index = wifi_mac_hash(addr);
529
530         spin_lock_bh(&pstapriv->sta_hash_lock);
531
532         phead = &(pstapriv->sta_hash[index]);
533         plist = get_next(phead);
534
535
536         while (phead != plist) {
537
538                 psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
539
540                 if ((!memcmp(psta->hwaddr, addr, ETH_ALEN)))
541                  /*  if found the matched address */
542                         break;
543
544                 psta = NULL;
545                 plist = get_next(plist);
546         }
547
548         spin_unlock_bh(&pstapriv->sta_hash_lock);
549         return psta;
550 }
551
552 u32 rtw_init_bcmc_stainfo(struct adapter *padapter)
553 {
554
555         struct sta_info *psta;
556         u32 res = _SUCCESS;
557         NDIS_802_11_MAC_ADDRESS bcast_addr = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
558
559         struct  sta_priv *pstapriv = &padapter->stapriv;
560         /* struct __queue       *pstapending = &padapter->xmitpriv.bm_pending; */
561
562         psta = rtw_alloc_stainfo(pstapriv, bcast_addr);
563
564         if (!psta) {
565                 res = _FAIL;
566                 RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, ("rtw_alloc_stainfo fail"));
567                 goto exit;
568         }
569
570         /*  default broadcast & multicast use macid 1 */
571         psta->mac_id = 1;
572
573 exit:
574         return _SUCCESS;
575 }
576
577 struct sta_info *rtw_get_bcmc_stainfo(struct adapter *padapter)
578 {
579         struct sta_priv *pstapriv = &padapter->stapriv;
580         u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
581
582         return rtw_get_stainfo(pstapriv, bc_addr);
583 }
584
585 u8 rtw_access_ctrl(struct adapter *padapter, u8 *mac_addr)
586 {
587         bool res = true;
588         struct list_head        *plist, *phead;
589         struct rtw_wlan_acl_node *paclnode;
590         bool match = false;
591         struct sta_priv *pstapriv = &padapter->stapriv;
592         struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
593         struct __queue  *pacl_node_q = &pacl_list->acl_node_q;
594
595         spin_lock_bh(&(pacl_node_q->lock));
596         phead = get_list_head(pacl_node_q);
597         plist = get_next(phead);
598         while (phead != plist) {
599                 paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);
600                 plist = get_next(plist);
601
602                 if (!memcmp(paclnode->addr, mac_addr, ETH_ALEN))
603                         if (paclnode->valid == true) {
604                                 match = true;
605                                 break;
606                         }
607
608         }
609         spin_unlock_bh(&(pacl_node_q->lock));
610
611         if (pacl_list->mode == 1) /* accept unless in deny list */
612                 res = !match;
613
614         else if (pacl_list->mode == 2)/* deny unless in accept list */
615                 res = match;
616         else
617                  res = true;
618
619         return res;
620 }