xref: /illumos-gate/usr/src/uts/common/io/bnx/570x/driver/common/lmdev/bnx_lm_main.c (revision eef4f27b270242808b43b4b23bd161df52839361)
1 /*
2  * Copyright 2014-2017 Cavium, Inc.
3  * The contents of this file are subject to the terms of the Common Development
4  * and Distribution License, v.1,  (the "License").
5  *
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the License at available
9  * at http://opensource.org/licenses/CDDL-1.0
10  *
11  * See the License for the specific language governing permissions and
12  * limitations under the License.
13  */
14 
15 #include "lm5706.h"
16 #if !defined(LINUX) && !defined(SOLARIS)
17 #include "string.h"     // needed by some OS for memset
18 #pragma warning(disable:28718)
19 #endif
20 
21 
22 /*******************************************************************************
23  * Description:
24  *
25  * Return:
26  ******************************************************************************/
27 void
28 lm_abort(
29     lm_device_t *pdev,
30     u32_t abort_op,
31     u32_t idx)
32 {
33     if(abort_op == ABORT_OP_RX_CHAIN)
34     {
35         lm_recv_abort(pdev, idx);
36     }
37     else if(abort_op == ABORT_OP_TX_CHAIN)
38     {
39         lm_send_abort(pdev, idx);
40     }
41     else
42     {
43         DbgBreakMsg("Invalid abort.\n");
44     }
45 } /* lm_abort */
46 
47 
48 
49 /*******************************************************************************
50  * Description:
51  *
52  * Return:
53  ******************************************************************************/
54 STATIC char *
55 val_to_decimal_string(
56     char *str_buf,
57     u32_t buf_size,
58     u32_t val)
59 {
60     u32_t digit;
61 
62     if(buf_size == 0)
63     {
64         return str_buf;
65     }
66 
67     digit = val % 10;
68     val = val / 10;
69 
70     if(val)
71     {
72         buf_size--;
73         str_buf = val_to_decimal_string(str_buf, buf_size, val);
74     }
75 
76     *str_buf = '0' + digit;
77 
78     str_buf++;
79 
80     return str_buf;
81 } /* val_to_decimal_string */
82 
83 
84 
85 /*******************************************************************************
86  * Description:
87  *
88  * Return:
89  ******************************************************************************/
90 STATIC u32_t
91 build_ver_string(
92     char *str_buf,
93     u32_t buf_size,
94     u8_t major_ver,
95     u8_t minor_ver,
96     u8_t rel_num,
97     u8_t fix_num)
98 {
99     char *p;
100 
101     if(buf_size == 0)
102     {
103         return 0;
104     }
105 
106     p = str_buf;
107 
108     if(buf_size - (p - str_buf) > 1)
109     {
110         *p = 'v';
111         p++;
112     }
113 
114     if(buf_size - (p - str_buf) > 1)
115     {
116         p = val_to_decimal_string(
117             p,
118             buf_size - (u32_t) PTR_SUB(p, str_buf),
119             major_ver);
120     }
121 
122     if(buf_size - (p - str_buf) > 1)
123     {
124         *p = '.';
125         p++;
126     }
127 
128     if(buf_size - (u32_t) PTR_SUB(p, str_buf) > 1)
129     {
130         p = val_to_decimal_string(
131             p,
132             buf_size - (u32_t) PTR_SUB(p, str_buf),
133             minor_ver);
134     }
135 
136     if(buf_size - (u32_t) PTR_SUB(p, str_buf) > 1)
137     {
138         *p = '.';
139         p++;
140     }
141 
142     if(buf_size - (u32_t) PTR_SUB(p, str_buf) > 1)
143     {
144         p = val_to_decimal_string(
145             p,
146             buf_size - (u32_t) PTR_SUB(p, str_buf),
147             rel_num);
148     }
149 
150     if(buf_size - (u32_t) PTR_SUB(p, str_buf) > 1)
151     {
152         *p = '.';
153         p++;
154     }
155 
156     if(buf_size - (u32_t) PTR_SUB(p, str_buf) > 1)
157     {
158         p = val_to_decimal_string(
159             p,
160             buf_size - (u32_t) PTR_SUB(p, str_buf),
161             fix_num);
162     }
163 
164     if(buf_size - (u32_t) PTR_SUB(p, str_buf) > 1)
165     {
166         *p = '.';
167         p++;
168     }
169 
170     if(buf_size - (u32_t) PTR_SUB(p, str_buf) > 1)
171     {
172         #if DBG
173         *p = 'd';
174         #else
175         *p = 'r';
176         #endif
177 
178         p++;
179     }
180 
181     if(buf_size - (u32_t) PTR_SUB(p, str_buf) > 1)
182     {
183         #if DBG
184         *p = 'b';
185         #else
186         *p = 't';
187         #endif
188 
189         p++;
190     }
191 
192     if(buf_size - (u32_t) PTR_SUB(p, str_buf) > 1)
193     {
194         #if DBG
195         *p = 'g';
196         #else
197         *p = 'l';
198         #endif
199 
200         p++;
201     }
202 
203     *p = 0;
204     p++;
205 
206     return (u32_t) PTR_SUB(p, str_buf);
207 } /* build_ver_string */
208 
209 
210 
211 /*******************************************************************************
212  * Description:
213  *
214  * Return:
215  ******************************************************************************/
216 STATIC void
217 get_max_conns(
218     lm_device_t *pdev,
219     u32_t *max_toe_conn,
220     u32_t *max_iscsi_conn,
221     u32_t *max_iscsi_pending_tasks)
222 {
223     u32_t max_lic_conn;
224     u32_t max_res_conn;
225     u32_t res_flags;
226 
227     /* get resource reservation flag. */
228     REG_RD_IND(
229         pdev,
230         pdev->hw_info.shmem_base +
231             OFFSETOF(shmem_region_t,
232                 dev_info.port_feature_config.resource.res_cfg),
233         &res_flags);
234 
235     /* get max_lic_conn for toe. */
236     REG_RD_IND(
237         pdev,
238         pdev->hw_info.shmem_base +
239             OFFSETOF(shmem_region_t, fw_lic_key.max_toe_conn),
240         &max_lic_conn);
241 
242     max_lic_conn &= 0xffff;
243 
244     if(max_lic_conn)
245     {
246         max_lic_conn ^= FW_ENCODE_16BIT_PATTERN;
247 
248         if(max_lic_conn == 0xffff)
249         {
250             max_lic_conn = 1024;
251         }
252     }
253 
254     /* get max_res_conn for toe. */
255     if(res_flags & RES_RES_CFG_VALID)
256     {
257         if(res_flags & RES_RES_CFG_L2)
258         {
259             REG_RD_IND(
260                 pdev,
261                 pdev->hw_info.shmem_base +
262                     OFFSETOF(shmem_region_t,
263                         dev_info.port_feature_config.resource.conn_resource1),
264                 &max_res_conn);
265             /*
266              * if(max_res_conn == 0 || !(res_flags & RES_RES_CFG_FCFS_DISABLED))
267              * CQ#42214 HH, SK and HYF all agreed on removing the test
268              * for max_res_conn == 0
269              */
270             if (!(res_flags & RES_RES_CFG_FCFS_DISABLED))
271             {
272                 max_res_conn = 1024;
273             }
274         }
275         else
276         {
277             max_res_conn = 0;
278         }
279     }
280     else
281     {
282         max_res_conn = 1024;
283     }
284 
285     *max_toe_conn = (max_lic_conn < max_res_conn) ? max_lic_conn: max_res_conn;
286 
287     /* get iscsi pending tasks. */
288     if((res_flags & RES_RES_CFG_VALID) && (res_flags & RES_RES_CFG_ISCSI))
289     {
290         REG_RD_IND(
291             pdev,
292             pdev->hw_info.shmem_base +
293                 OFFSETOF(shmem_region_t,
294                     dev_info.port_feature_config.resource.conn_resource3),
295             max_iscsi_pending_tasks);
296 
297         *max_iscsi_pending_tasks &= RES_CONN_ISCSI_PTASK_MASK;
298 
299         if(*max_iscsi_pending_tasks == 0 || *max_iscsi_pending_tasks > 128)
300         {
301             *max_iscsi_pending_tasks = 128;
302         }
303     }
304     else
305     {
306         *max_iscsi_pending_tasks = 128;
307         *max_iscsi_conn = 0;
308     }
309 
310     REG_RD_IND(
311         pdev,
312         pdev->hw_info.shmem_base +
313             OFFSETOF(shmem_region_t, fw_lic_key.max_iscsi_trgt_conn),
314         &max_lic_conn);
315 
316     if(max_lic_conn)
317     {
318         max_lic_conn ^= FW_ENCODE_32BIT_PATTERN;
319         max_lic_conn >>= 16;
320     }
321 
322     *max_iscsi_conn = max_lic_conn;
323 
324     /* no license information. */
325     if(*max_toe_conn == 0)
326     {
327         if(pdev->hw_info.svid == 0x103c)        /* HP device. */
328         {
329             *max_toe_conn = 1024;
330         }
331         else if(CHIP_REV(pdev) == CHIP_REV_IKOS ||
332                 CHIP_REV(pdev) == CHIP_REV_FPGA)
333         {
334             *max_toe_conn = 32;
335         }
336     }
337 
338     /* cq#39856 - iSCSI Device Disappears from System after reboot. */
339     if(*max_iscsi_conn == 0)
340     {
341         if(pdev->hw_info.svid == 0x103c)        /* HP device. */
342         {
343             *max_iscsi_conn = 1024;
344         }
345         else if(CHIP_REV(pdev) == CHIP_REV_IKOS ||
346                 CHIP_REV(pdev) == CHIP_REV_FPGA)
347         {
348             *max_iscsi_conn = 32;
349         }
350     }
351 } /* get_max_conns */
352 
353 
354 
355 /*******************************************************************************
356  * Description:
357  *
358  * Return:
359  ******************************************************************************/
360 lm_status_t
361 lm_get_dev_info(
362     lm_device_t *pdev)
363 {
364     typedef struct _param_entry_t
365     {
366         /* Ideally, we want to save the address of the parameter here.
367          * However, some compiler will not allow us to dynamically
368          * initialize the pointer to a parameter in the table below.
369          * As an alternative, we will save the offset to the parameter
370          * from pdev device structure. */
371         u32_t offset;
372 
373         /* Parameter default value. */
374         u32_t asic_default;
375         u32_t fpga_ikos_default;
376 
377         /* Limit checking is diabled if min and max are zeros. */
378         u32_t min;
379         u32_t max;
380     } param_entry_t;
381 
382     #define _OFFSET(_name)          (OFFSETOF(lm_device_t, params._name))
383     #define PARAM_VAL(_pdev, _entry) \
384         (*((u32_t *) ((u8_t *) (_pdev) + (_entry)->offset)))
385     #define SET_PARAM_VAL(_pdev, _entry, _val) \
386         *((u32_t *) ((u8_t *) (_pdev) + (_entry)->offset)) = (_val)
387 
388     static param_entry_t param_list[] =
389     {
390         /*                                 asic     fpga/ikos
391            offset                          default  default  min     max */
392         { _OFFSET(mtu),                    1500,    1500,    1500,   9018 },
393         { _OFFSET(l2_rx_desc_cnt[0]),      200,     150,     0,      0 },
394         { _OFFSET(l2_rx_desc_cnt[1]),      0,       0,       0,      0 },
395         { _OFFSET(l2_rx_desc_cnt[2]),      0,       0,       0,      0 },
396         { _OFFSET(l2_rx_desc_cnt[3]),      0,       0,       0,      0 },
397         { _OFFSET(l2_rx_desc_cnt[4]),      0,       0,       0,      0 },
398         { _OFFSET(l2_rx_desc_cnt[5]),      0,       0,       0,      0 },
399         { _OFFSET(l2_rx_desc_cnt[6]),      0,       0,       0,      0 },
400         { _OFFSET(l2_rx_desc_cnt[7]),      0,       0,       0,      0 },
401         { _OFFSET(l2_rx_desc_cnt[8]),      0,       0,       0,      0 },
402         { _OFFSET(l2_rx_desc_cnt[9]),      0,       0,       0,      0 },
403         { _OFFSET(l2_rx_desc_cnt[10]),     0,       0,       0,      0 },
404         { _OFFSET(l2_rx_desc_cnt[11]),     0,       0,       0,      0 },
405         #if 0
406         { _OFFSET(l2_rx_desc_cnt[12]),     0,       0,       0,      0 },
407         { _OFFSET(l2_rx_desc_cnt[13]),     0,       0,       0,      0 },
408         { _OFFSET(l2_rx_desc_cnt[14]),     0,       0,       0,      0 },
409         { _OFFSET(l2_rx_desc_cnt[15]),     0,       0,       0,      0 },
410         #endif
411 
412         /* The maximum page count is chosen to prevent us from having
413          * more than 32767 pending entries at any one time. */
414         { _OFFSET(l2_tx_bd_page_cnt[0]),   2,       2,       1,      127 },
415         { _OFFSET(l2_tx_bd_page_cnt[1]),   1,       1,       1,      127 },
416         { _OFFSET(l2_tx_bd_page_cnt[2]),   1,       1,       1,      127 },
417         { _OFFSET(l2_tx_bd_page_cnt[3]),   1,       1,       1,      127 },
418         { _OFFSET(l2_tx_bd_page_cnt[4]),   1,       1,       1,      127 },
419         { _OFFSET(l2_tx_bd_page_cnt[5]),   1,       1,       1,      127 },
420         { _OFFSET(l2_tx_bd_page_cnt[6]),   1,       1,       1,      127 },
421         { _OFFSET(l2_tx_bd_page_cnt[7]),   1,       1,       1,      127 },
422         { _OFFSET(l2_tx_bd_page_cnt[8]),   1,       1,       1,      127 },
423         { _OFFSET(l2_tx_bd_page_cnt[9]),   1,       1,       1,      127 },
424         { _OFFSET(l2_tx_bd_page_cnt[10]),  1,       1,       1,      127 },
425         { _OFFSET(l2_tx_bd_page_cnt[11]),  1,       1,       1,      127 },
426 
427         { _OFFSET(l2_rx_bd_page_cnt[0]),   2,       2,       1,      127 },
428         { _OFFSET(l2_rx_bd_page_cnt[1]),   1,       1,       1,      127 },
429         { _OFFSET(l2_rx_bd_page_cnt[2]),   1,       1,       1,      127 },
430         { _OFFSET(l2_rx_bd_page_cnt[3]),   1,       1,       1,      127 },
431         { _OFFSET(l2_rx_bd_page_cnt[4]),   1,       1,       1,      127 },
432         { _OFFSET(l2_rx_bd_page_cnt[5]),   1,       1,       1,      127 },
433         { _OFFSET(l2_rx_bd_page_cnt[6]),   1,       1,       1,      127 },
434         { _OFFSET(l2_rx_bd_page_cnt[7]),   1,       1,       1,      127 },
435         { _OFFSET(l2_rx_bd_page_cnt[8]),   1,       1,       1,      127 },
436         { _OFFSET(l2_rx_bd_page_cnt[9]),   1,       1,       1,      127 },
437         { _OFFSET(l2_rx_bd_page_cnt[10]),  1,       1,       1,      127 },
438         { _OFFSET(l2_rx_bd_page_cnt[11]),  1,       1,       1,      127 },
439         #if 0
440         { _OFFSET(l2_rx_bd_page_cnt[12]),  1,       1,       1,      127 },
441         { _OFFSET(l2_rx_bd_page_cnt[13]),  1,       1,       1,      127 },
442         { _OFFSET(l2_rx_bd_page_cnt[14]),  1,       1,       1,      127 },
443         { _OFFSET(l2_rx_bd_page_cnt[15]),  1,       1,       1,      127 },
444         #endif
445 
446         { _OFFSET(l4_tx_bd_page_cnt),      1,       1,       1,      255 },
447         { _OFFSET(limit_l4_tx_bd_cnt),     0,       0,       0,      0 },
448         { _OFFSET(l4_rx_bd_page_cnt),      1,       1,       1,      255 },
449         { _OFFSET(limit_l4_rx_bd_cnt),     0,       0,       0,      0 },
450 
451         #ifndef EXCLUDE_KQE_SUPPORT
452         #if INCLUDE_OFLD_SUPPORT
453         { _OFFSET(kwq_page_cnt),           4,       2,       1,      255 },
454         { _OFFSET(kcq_page_cnt),           32,      32,      1,      255 },
455         { _OFFSET(kcq_history_size),       0x80,    0x80,    0,      0   },
456         #else
457         /* Kernel queues are used when RSS or TCP offload is enabled.
458          * When RSS is enabled, the upper module should modify the
459          * default settings for these parameters. */
460         { _OFFSET(kwq_page_cnt),           0,       0,       0,      0 },
461         { _OFFSET(kcq_page_cnt),           0,       0,       0,      0 },
462         { _OFFSET(kcq_history_size),       0,       0,       0,      0 },
463         #endif
464 
465         /* Connection kcqe/kwqe history. */
466         { _OFFSET(con_kcqe_history_size),  0,       0,       0,      0 },
467         { _OFFSET(con_kwqe_history_size),  0,       0,       0,      0 },
468         #endif
469 
470         { _OFFSET(gen_bd_page_cnt),        2,       2,       1,      127 },
471         { _OFFSET(max_gen_buf_cnt),        0x8000,  0x8000,  0,      0 },
472         { _OFFSET(gen_buf_per_alloc),      0x4,    0x4,      0,      0 },
473 
474         { _OFFSET(copy_buffered_data),     0,       0,       0,      0 },
475         { _OFFSET(rcv_buffer_offset),      0x38,    0x38,    0,      0 },
476         { _OFFSET(enable_syn_rcvq),        0,       0,       0,      0 },
477 
478         { _OFFSET(hcopy_desc_cnt),         0,       0,       0,      0 },
479         { _OFFSET(hcopy_bd_page_cnt),      2,       2,       1,      127 },
480         { _OFFSET(buffered_kcqe_cnt),      0x80,    0x80,    0,      0 },
481 
482         { _OFFSET(deferred_kcqe_cnt),      0x100,   0x100,   0,      0 },
483 
484         { _OFFSET(test_mode),              0x60,    0x60,    0,      0 },
485         { _OFFSET(ofld_cap),               0,       0,       0,      0 },
486         { _OFFSET(wol_cap),                0,       0,       0,      0 },
487         { _OFFSET(flow_ctrl_cap),          0,       0,       0,      0 },
488         { _OFFSET(req_medium),             0,       0,       0,      0xfffff },
489         { _OFFSET(selective_autoneg),      0,       0,       0,      0 },
490         { _OFFSET(wire_speed),             1,       0,       0,      0 },
491         { _OFFSET(phy_addr),               1,       0,       0,      0 },
492         { _OFFSET(phy_int_mode),           2,       2,       0,      0 },
493         { _OFFSET(link_chng_mode),         2,       2,       0,      0 },
494 
495         { _OFFSET(hc_timer_mode),          0,       0,       0,      0 },
496         { _OFFSET(ind_comp_limit),         200,     100,     0,      0 },
497         { _OFFSET(tx_quick_cons_trip_int), 3,       10,      0,      0 },
498         { _OFFSET(tx_quick_cons_trip),     3,       30,      0,      0 },
499         { _OFFSET(tx_ticks_int),           30,      10,      0,      0 },
500         { _OFFSET(tx_ticks),               60,      200,     0,      0 },
501         { _OFFSET(rx_quick_cons_trip_int), 1,       3,       0,      0 },
502         { _OFFSET(rx_quick_cons_trip),     2,       1,       0,      0 },
503         { _OFFSET(rx_ticks_int),           15,      5,       0,      0 },
504         { _OFFSET(rx_ticks),               45,      1,       0,      0 },
505         { _OFFSET(comp_prod_trip_int),     2,       3,       0,      0 },
506         { _OFFSET(comp_prod_trip),         4,       1,       0,      0 },
507         { _OFFSET(com_ticks_int),          64,      5,       0,      0 },
508         { _OFFSET(com_ticks),              220,     1,       0,      0 },
509         { _OFFSET(cmd_ticks_int),          64,      5,       0,      0 },
510         { _OFFSET(cmd_ticks),              220,     1,       0,      0 },
511         { _OFFSET(stats_ticks),            1000000, 1000000, 0,      0 },
512 
513         /* Xinan per-processor HC configuration. */
514         { _OFFSET(psb_tx_cons_trip),       0x100010,0x100010,0,      0 },
515         { _OFFSET(psb_tx_ticks),           0x100040,0x100040,0,      0 },
516         { _OFFSET(psb_rx_cons_trip),       0x100010,0x100010,0,      0 },
517         { _OFFSET(psb_rx_ticks),           0x80020, 0x80020, 0,      0 },
518         { _OFFSET(psb_comp_prod_trip),     0x80008, 0x80008, 0,      0 },
519         { _OFFSET(psb_com_ticks),          0x400040,0x400040,0,      0 },
520         { _OFFSET(psb_cmd_ticks),          0x400040,0x400040,0,      0 },
521         { _OFFSET(psb_period_ticks),       0,       0,       0,      0 },
522 
523         { _OFFSET(enable_fir),             1,       1,       0,      0 },
524         { _OFFSET(num_rchans),             5,       5,       0,      0 },
525         { _OFFSET(num_wchans),             3,       3,       0,      0 },
526 
527         /* One some system, with one_tdma disabled, we will get data
528          * corruption.  Currently this looks like a chipset bug.  The
529          * chip group will continue to look into this.  So for now, we
530          * will enable one_tdma for all chip revisions. */
531         { _OFFSET(one_tdma),               0,       0,       0,      0 },
532 
533         { _OFFSET(ping_pong_dma),          0,       0,       0,      0 },
534         { _OFFSET(tmr_reload_value1),      0x6c627970, 0,    0,      0 },
535         { _OFFSET(keep_vlan_tag),          0,       0,       0,      0 },
536 
537         { _OFFSET(enable_remote_phy),      0,       0,       0,      0 },
538         { _OFFSET(rphy_req_medium),        0,       0,       0,      0 },
539         { _OFFSET(rphy_flow_ctrl_cap),     0,       0,       0,      0 },
540         { _OFFSET(rphy_selective_autoneg), 0,       0,       0,      0 },
541         { _OFFSET(rphy_wire_speed),        1,       0,       0,      0 },
542 
543         { _OFFSET(bin_mq_mode),            0,       0,       0,      0 },
544         { _OFFSET(validate_l4_data),       0,       0,       0,      0 },
545         { _OFFSET(disable_pcie_nfr),       0,       0,       0,      0 },
546         { _OFFSET(fw_flow_control),        0,       0,       0,      0 },
547         { _OFFSET(fw_flow_control_wait),   0xffff,  0xffff,  0,      0xffff },
548         { _OFFSET(ena_large_grc_timeout),  0,       0,       0,      0 },
549         { _OFFSET(flow_control_reporting_mode),     0,       0,      0,      0 },
550         { 0,                               0,       0,       0,      0 }
551     };
552 
553     lm_status_t lm_status;
554     param_entry_t *param;
555     u32_t val;
556 
557     DbgMessage(pdev, INFORMi, "### lm_get_dev_info\n");
558 
559     /* Get PCI device and vendor id. */
560     lm_status = mm_read_pci(
561         pdev,
562         OFFSETOF(reg_space_t, pci_config.pcicfg_vendor_id),
563         &val);
564     if(lm_status != LM_STATUS_SUCCESS)
565     {
566         return lm_status;
567     }
568 
569     pdev->hw_info.vid = (u16_t) val;
570     DbgMessage1(pdev, INFORMi, "vid 0x%x\n", pdev->hw_info.vid);
571 
572     pdev->hw_info.did = (u16_t) (val >> 16);
573     DbgMessage1(pdev, INFORMi, "did 0x%x\n", pdev->hw_info.did);
574 
575     /* Get subsystem and subvendor id. */
576     lm_status = mm_read_pci(
577         pdev,
578         OFFSETOF(reg_space_t, pci_config.pcicfg_subsystem_vendor_id),
579         &val);
580     if(lm_status != LM_STATUS_SUCCESS)
581     {
582         return lm_status;
583     }
584 
585     pdev->hw_info.svid = (u16_t) val;
586     DbgMessage1(pdev, INFORMi, "svid 0x%x\n", pdev->hw_info.svid);
587 
588     pdev->hw_info.ssid = (u16_t) (val >> 16);
589     DbgMessage1(pdev, INFORMi, "ssid 0x%x\n", pdev->hw_info.ssid);
590 
591     /* Get IRQ, and interrupt pin. */
592     lm_status = mm_read_pci(
593         pdev,
594         OFFSETOF(reg_space_t, pci_config.pcicfg_int_line),
595         &val);
596     if(lm_status != LM_STATUS_SUCCESS)
597     {
598         return lm_status;
599     }
600 
601     pdev->hw_info.irq = (u8_t) val;
602     DbgMessage1(pdev, INFORMi, "IRQ 0x%x\n", pdev->hw_info.irq);
603 
604     pdev->hw_info.int_pin = (u8_t) (val >> 8);
605     DbgMessage1(pdev, INFORMi, "Int pin 0x%x\n", pdev->hw_info.int_pin);
606 
607     /* Get cache line size. */
608     lm_status = mm_read_pci(
609         pdev,
610         OFFSETOF(reg_space_t, pci_config.pcicfg_cache_line_size),
611         &val);
612     if(lm_status != LM_STATUS_SUCCESS)
613     {
614         return lm_status;
615     }
616 
617     pdev->hw_info.cache_line_size = (u8_t) val;
618     DbgMessage1(pdev, INFORMi, "Cache line size 0x%x\n", (u8_t) val);
619 
620     pdev->hw_info.latency_timer = (u8_t) (val >> 8);
621     DbgMessage1(pdev, INFORMi, "Latency timer 0x%x\n", (u8_t) (val >> 8));
622 
623     /* Get PCI revision id. */
624     lm_status = mm_read_pci(
625         pdev,
626         OFFSETOF(reg_space_t, pci_config.pcicfg_class_code),
627         &val);
628     if(lm_status != LM_STATUS_SUCCESS)
629     {
630         return lm_status;
631     }
632 
633     pdev->hw_info.rev_id = (u8_t) val;
634     DbgMessage1(pdev, INFORMi, "Revision id 0x%x\n", pdev->hw_info.rev_id);
635 
636     /* Get the base address. */
637     lm_status = mm_read_pci(
638         pdev,
639         OFFSETOF(reg_space_t, pci_config.pcicfg_bar_1),
640         &val);
641     if(lm_status != LM_STATUS_SUCCESS)
642     {
643         return lm_status;
644     }
645 
646 #ifndef CONFIG_PPC64
647     pdev->hw_info.mem_base.as_u32.low = val & 0xfffffff0;
648 #endif
649 
650     DbgMessage1(pdev, INFORMi, "Mem base low 0x%x\n", pdev->hw_info.mem_base.as_u32.low);
651 
652     val = 0;
653 
654     lm_status = mm_read_pci(
655         pdev,
656         OFFSETOF(reg_space_t, pci_config.pcicfg_bar_2),
657         &val);
658     if(lm_status != LM_STATUS_SUCCESS)
659     {
660         return lm_status;
661     }
662 
663 #ifndef CONFIG_PPC64
664     pdev->hw_info.mem_base.as_u32.high = val;
665 #endif
666 
667     DbgMessage1(pdev, INFORMi, "Mem base high 0x%x\n",
668         pdev->hw_info.mem_base.as_u32.high);
669 
670     /* Enable PCI bus master.  This is supposed to be enabled by the
671      * BIOS, however, BIOS on older systems may not set this bit. */
672     lm_status = mm_read_pci(
673         pdev,
674         OFFSETOF(reg_space_t, pci_config.pcicfg_command),
675         &val);
676     if(lm_status != LM_STATUS_SUCCESS)
677     {
678         return lm_status;
679     }
680 
681     /* Error out if memory map is NOT enabled.  This could occur if the
682      * BIOS is not able to reserve an address range for the device. */
683     if(!(val & PCICFG_COMMAND_MEM_SPACE))
684     {
685         DbgBreakMsg("MEM_SPACE not enabled.\n");
686 
687         return LM_STATUS_FAILURE;
688     }
689 
690     val |= PCICFG_COMMAND_BUS_MASTER;
691 
692     lm_status = mm_write_pci(
693         pdev,
694         OFFSETOF(reg_space_t, pci_config.pcicfg_command),
695         val);
696     if(lm_status != LM_STATUS_SUCCESS)
697     {
698         return lm_status;
699     }
700 
701     /* Configure byte swap and enable write to the reg_window registers. */
702     val = PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
703         PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP;
704     lm_status = mm_write_pci(
705         pdev,
706         OFFSETOF(reg_space_t, pci_config.pcicfg_misc_config),
707         val);
708     if(lm_status != LM_STATUS_SUCCESS)
709     {
710         return lm_status;
711     }
712 
713     /* Get the bar size at register 0x408 via PCI configuration indirect. */
714     lm_status = mm_write_pci(
715         pdev,
716         OFFSETOF(pci_config_t, pcicfg_reg_window_address),
717         OFFSETOF(reg_space_t, pci.pci_config_2));
718     if(lm_status != LM_STATUS_SUCCESS)
719     {
720         return lm_status;
721     }
722 
723     lm_status = mm_read_pci(
724         pdev,
725         OFFSETOF(pci_config_t, pcicfg_reg_window),
726         &val);
727     if(lm_status != LM_STATUS_SUCCESS)
728     {
729         return lm_status;
730     }
731 
732     val &= PCI_CONFIG_2_BAR1_SIZE;
733     if(val == PCI_CONFIG_2_BAR1_SIZE_DISABLED ||
734         val > PCI_CONFIG_2_BAR1_SIZE_1G)
735     {
736         DbgBreakMsg("Invalid bar size.\n");
737 
738         return LM_STATUS_FAILURE;
739     }
740 
741     pdev->hw_info.bar_size = 1 << (val+15);
742     DbgMessage1(pdev, INFORM, "bar_size 0x%x\n", pdev->hw_info.bar_size);
743 
744     /* Map memory base to system address space. */
745     pdev->vars.regview = (reg_space_t *) mm_map_io_base(
746         pdev,
747         pdev->hw_info.mem_base,
748         pdev->hw_info.bar_size);
749     if(pdev->vars.regview == NULL)
750     {
751         return LM_STATUS_FAILURE;
752     }
753     DbgMessage1(pdev, INFORMi, "Mapped base %p\n", pdev->vars.regview);
754 
755     #if DBG
756     /* Make sure byte swapping is properly configured. */
757     REG_RD(pdev, pci.pci_swap_diag0, &val);
758 
759     DbgBreakIf(val != 0x1020304);
760     #endif
761 
762     /* Get the chip revision id and number. */
763     REG_RD(pdev, misc.misc_id, &pdev->hw_info.chip_id);
764     DbgMessage1(pdev, INFORMi, "chip id 0x%x\n", pdev->hw_info.chip_id);
765 
766     if(CHIP_NUM(pdev) == CHIP_NUM_5709)
767     {
768         pdev->hw_info.bus_mode = BUS_MODE_PCIE;
769     }
770     else
771     {
772         /* Get bus information. */
773         REG_RD(pdev, pci_config.pcicfg_misc_status, &val);
774 
775         if(val & PCICFG_MISC_STATUS_32BIT_DET)
776         {
777             pdev->hw_info.bus_width = BUS_WIDTH_32_BIT;
778             DbgMessage(pdev, INFORM, "32bit bus width.\n");
779         }
780         else
781         {
782             pdev->hw_info.bus_width = BUS_WIDTH_64_BIT;
783             DbgMessage(pdev, INFORM, "64bit bus width.\n");
784         }
785 
786         if(val & PCICFG_MISC_STATUS_PCIX_DET)
787         {
788             pdev->hw_info.bus_mode = BUS_MODE_PCIX;
789             DbgMessage(pdev, INFORM, "PCIX bus detected.\n");
790 
791             REG_RD(pdev, pci_config.pcicfg_pci_clock_control_bits, &val);
792             switch(val & PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET)
793             {
794             case PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ:
795                 pdev->hw_info.bus_speed = BUS_SPEED_133_MHZ;
796                 DbgMessage(pdev, INFORM, "Bus speed is 133Mhz.\n");
797                 break;
798 
799             case PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ:
800                 pdev->hw_info.bus_speed = BUS_SPEED_100_MHZ;
801                 DbgMessage(pdev, INFORM, "Bus speed is 100Mhz.\n");
802                 break;
803 
804             case PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ:
805             case PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ:
806                 pdev->hw_info.bus_speed = BUS_SPEED_66_MHZ;
807                 DbgMessage(pdev, INFORM, "Bus speed is 66Mhz.\n");
808                 break;
809 
810             case PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ:
811             case PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ:
812                 pdev->hw_info.bus_speed = BUS_SPEED_50_MHZ;
813                 DbgMessage(pdev, INFORM, "Bus speed is 50Mhz.\n");
814                 break;
815 
816             case PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET:
817             case PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ:
818             case PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ:
819             default:
820                 pdev->hw_info.bus_speed = BUS_SPEED_33_MHZ;
821                 DbgMessage(pdev, INFORM, "Bus speed is 33Mhz.\n");
822                 break;
823             }
824         }
825         else
826         {
827             pdev->hw_info.bus_mode = BUS_MODE_PCI;
828             DbgMessage(pdev, INFORM, "Conventional PCI bus detected.\n");
829 
830             if(val & PCICFG_MISC_STATUS_M66EN)
831             {
832                 pdev->hw_info.bus_speed = BUS_SPEED_66_MHZ;
833                 DbgMessage(pdev, INFORM, "Bus speed is 66Mhz.\n");
834             }
835             else
836             {
837                 pdev->hw_info.bus_speed = BUS_SPEED_33_MHZ;
838                 DbgMessage(pdev, INFORM, "Bus speed is 33Mhz.\n");
839             }
840         }
841     }
842 
843     if(CHIP_ID(pdev) == CHIP_ID_5706_A0 || CHIP_ID(pdev) == CHIP_ID_5706_A1)
844     {
845         REG_RD_OFFSET(
846             pdev,
847             OFFSETOF(reg_space_t, pci_config.pcicfg_command),
848             &val);
849 
850         /* 5706A0 may falsely detect SERR and PERR. */
851         if(CHIP_ID(pdev) == CHIP_ID_5706_A0)
852         {
853             val &= ~(PCICFG_COMMAND_SERR_ENA | PCICFG_COMMAND_PERR_ENA);
854         }
855 
856         /* 5706A1 PCI 64-bit. */
857         else if(pdev->hw_info.bus_mode == BUS_MODE_PCI &&
858             pdev->hw_info.bus_width == BUS_WIDTH_64_BIT)
859         {
860             /* E4_5706A1_577: PERR IS INCORRECTLY GENERATED IN PCI 64-BIT.
861                Description: If the data on the upper AD and CBE busses
862                   do not match the parity of PAR64 during a 32-bit target
863                   access, a parity error is incorrectly generated. This
864                   happens only after a 64-bit master DMA operation has been
865                   done by the chip.
866                Scope: All PCI 64-bit systems.
867                Impact: Ability to indicate a real parity error is lost.
868                Workaround: Driver needs to clear PERR_EN. */
869             val &= ~PCICFG_COMMAND_PERR_ENA;
870         }
871 
872         REG_WR_OFFSET(
873             pdev,
874             OFFSETOF(reg_space_t, pci_config.pcicfg_command),
875             val);
876     }
877     else if(CHIP_ID(pdev) == CHIP_ID_5708_A0)
878     {
879         /* 5708A0 errata. */
880         REG_RD_OFFSET(
881             pdev,
882             OFFSETOF(reg_space_t, pci_config.pcicfg_command),
883             &val);
884 
885         val &= ~(PCICFG_COMMAND_SERR_ENA | PCICFG_COMMAND_PERR_ENA);
886 
887         REG_WR_OFFSET(
888             pdev,
889             OFFSETOF(reg_space_t, pci_config.pcicfg_command),
890             val);
891     }
892 
893     /* Get the EPB info. */
894     if(CHIP_NUM(pdev) == CHIP_NUM_5708)
895     {
896         REG_RD_IND(pdev, 0x240000+0x18, &val);
897         pdev->hw_info.pcie_bus_num = (u8_t) val;
898 
899         REG_RD_IND(pdev, 0x240000+0x6c, &val);
900         pdev->hw_info.pcie_max_width = (u8_t) ((val & 0x3f0) >> 4);
901 
902         switch(val & 0xf)
903         {
904             case 1:
905                 pdev->hw_info.pcie_max_speed = PCIE_SPEED_2_5_G;
906                 break;
907 
908             default:
909                 pdev->hw_info.pcie_max_speed = 0;
910                 break;
911         }
912 
913         REG_RD_IND(pdev, 0x240000+0x70, &val);
914         pdev->hw_info.pcie_width = (u8_t) ((val & 0x3f00000) >> 20);
915 
916         switch(val & 0xf0000)
917         {
918             case 0x10000:
919                 pdev->hw_info.pcie_speed = PCIE_SPEED_2_5_G;
920                 break;
921 
922             default:
923                 pdev->hw_info.pcie_speed = 0;
924                 break;
925         }
926     }
927     else if(CHIP_NUM(pdev) == CHIP_NUM_5709)
928     {
929         REG_RD(pdev, pci_config.pcicfg_link_capability, &val);
930         pdev->hw_info.pcie_max_width =
931             (u8_t) ((val & PCICFG_LINK_CAPABILITY_MAX_LINK_WIDTH) >> 4);
932         switch (val & PCICFG_LINK_CAPABILITY_MAX_LINK_SPEED)
933         {
934             case PCICFG_LINK_CAPABILITY_MAX_LINK_SPEED_5:
935                 pdev->hw_info.pcie_max_speed = PCIE_SPEED_5_G;
936                 break;
937             case PCICFG_LINK_CAPABILITY_MAX_LINK_SPEED_2_5:
938                 pdev->hw_info.pcie_max_speed = PCIE_SPEED_2_5_G;
939                 break;
940             default:
941                 pdev->hw_info.pcie_max_speed = 0;
942                 break;
943         }
944 
945         REG_RD(pdev, pci_config.pcicfg_link_status, &val);
946         pdev->hw_info.pcie_width =
947             (u8_t) ((val & PCICFG_LINK_STATUS_NEG_LINK_WIDTH) >> 4);
948         switch (val & PCICFG_LINK_STATUS_SPEED)
949         {
950             case PCICFG_LINK_CAPABILITY_MAX_LINK_SPEED_5:
951                 pdev->hw_info.pcie_speed = PCIE_SPEED_5_G;
952                 break;
953             case PCICFG_LINK_CAPABILITY_MAX_LINK_SPEED_2_5:
954                 pdev->hw_info.pcie_speed = PCIE_SPEED_2_5_G;
955                 break;
956             default:
957                 pdev->hw_info.pcie_speed = 0;
958                 break;
959         }
960 
961         REG_RD_IND(pdev, OFFSETOF(reg_space_t, mcp.mcp_toe_id), &val);
962         if(val & MCP_TOE_ID_FUNCTION_ID)
963         {
964             pdev->hw_info.mac_id = 1;
965         }
966     }
967 
968     /* Get firmware share memory base address. */
969     REG_RD_IND(
970         pdev,
971         MCP_SCRATCHPAD_START + OFFSETOF(shm_hdr_t, shm_hdr_signature),
972         &val);
973     if((val & SHM_ADDR_SIGN_MASK) == SHM_ADDR_SIGNATURE)
974     {
975         REG_RD_IND(
976             pdev,
977             MCP_SCRATCHPAD_START +
978                 OFFSETOF(shm_hdr_t, shm_addr[pdev->hw_info.mac_id]),
979             &pdev->hw_info.shmem_base);
980     }
981     else
982     {
983         /* Pre v1.3.2 bootcode. */
984         pdev->hw_info.shmem_base = HOST_VIEW_SHMEM_BASE;
985     }
986 
987     /* Get the hw config word. */
988     REG_RD_IND(
989         pdev,
990         pdev->hw_info.shmem_base +
991             OFFSETOF(shmem_region_t, dev_info.shared_hw_config.config),
992         &val);
993     pdev->hw_info.nvm_hw_config = val;
994 
995     get_max_conns(
996         pdev,
997         &pdev->hw_info.max_toe_conn,
998         &pdev->hw_info.max_iscsi_conn,
999         &pdev->hw_info.max_iscsi_pending_tasks);
1000 
1001     /* Get the permanent MAC address. */
1002     REG_RD_IND(
1003         pdev,
1004         pdev->hw_info.shmem_base +
1005             OFFSETOF(shmem_region_t, dev_info.port_hw_config.mac_upper),
1006         &val);
1007     pdev->hw_info.mac_addr[0] = (u8_t) (val >> 8);
1008     pdev->hw_info.mac_addr[1] = (u8_t) val;
1009 
1010     REG_RD_IND(
1011         pdev,
1012         pdev->hw_info.shmem_base +
1013             OFFSETOF(shmem_region_t, dev_info.port_hw_config.mac_lower),
1014         &val);
1015 
1016     pdev->hw_info.mac_addr[2] = (u8_t) (val >> 24);
1017     pdev->hw_info.mac_addr[3] = (u8_t) (val >> 16);
1018     pdev->hw_info.mac_addr[4] = (u8_t) (val >> 8);
1019     pdev->hw_info.mac_addr[5] = (u8_t) val;
1020 
1021     /* Get iSCSI MAC address. */
1022     REG_RD_IND(
1023         pdev,
1024         pdev->hw_info.shmem_base +
1025             OFFSETOF(
1026                 shmem_region_t,
1027                 dev_info.port_hw_config.iscsi_mac_upper),
1028          &val);
1029     pdev->hw_info.iscsi_mac_addr[0] = (u8_t) (val >> 8);
1030     pdev->hw_info.iscsi_mac_addr[1] = (u8_t) val;
1031 
1032     REG_RD_IND(
1033         pdev,
1034         pdev->hw_info.shmem_base +
1035             OFFSETOF(
1036                 shmem_region_t,
1037                 dev_info.port_hw_config.iscsi_mac_lower),
1038         &val);
1039     pdev->hw_info.iscsi_mac_addr[2] = (u8_t) (val >> 24);
1040     pdev->hw_info.iscsi_mac_addr[3] = (u8_t) (val >> 16);
1041     pdev->hw_info.iscsi_mac_addr[4] = (u8_t) (val >> 8);
1042     pdev->hw_info.iscsi_mac_addr[5] = (u8_t) val;
1043 
1044     DbgMessage6(pdev, INFORM, "mac addr: %02x %02x %02x %02x %02x %02x\n",
1045         pdev->hw_info.mac_addr[0],
1046         pdev->hw_info.mac_addr[1],
1047         pdev->hw_info.mac_addr[2],
1048         pdev->hw_info.mac_addr[3],
1049         pdev->hw_info.mac_addr[4],
1050         pdev->hw_info.mac_addr[5]);
1051 
1052     DbgBreakIf(LM_DRIVER_MAJOR_VER > 255);
1053     DbgBreakIf(LM_DRIVER_MINOR_VER > 255);
1054     DbgBreakIf(LM_DRIVER_REL_NUM > 255);
1055     DbgBreakIf(LM_DRIVER_FIX_NUM > 255);
1056 
1057     pdev->ver_num =
1058         (LM_DRIVER_MAJOR_VER << 24) |
1059         (LM_DRIVER_MINOR_VER << 16) |
1060         (LM_DRIVER_REL_NUM << 8)    |
1061         LM_DRIVER_FIX_NUM;
1062 
1063     (void) build_ver_string(
1064         (char *)pdev->ver_str,
1065         sizeof(pdev->ver_str),
1066         LM_DRIVER_MAJOR_VER,
1067         LM_DRIVER_MINOR_VER,
1068         LM_DRIVER_REL_NUM,
1069         LM_DRIVER_FIX_NUM);
1070 
1071     pdev->params.mac_addr[0] = pdev->hw_info.mac_addr[0];
1072     pdev->params.mac_addr[1] = pdev->hw_info.mac_addr[1];
1073     pdev->params.mac_addr[2] = pdev->hw_info.mac_addr[2];
1074     pdev->params.mac_addr[3] = pdev->hw_info.mac_addr[3];
1075     pdev->params.mac_addr[4] = pdev->hw_info.mac_addr[4];
1076     pdev->params.mac_addr[5] = pdev->hw_info.mac_addr[5];
1077 
1078     /* Initialize the default parameters. */
1079     param = param_list;
1080     while(param->offset)
1081     {
1082         if(CHIP_REV(pdev) == CHIP_REV_FPGA || CHIP_REV(pdev) == CHIP_REV_IKOS)
1083         {
1084             SET_PARAM_VAL(pdev, param, param->fpga_ikos_default);
1085         }
1086         else
1087         {
1088             SET_PARAM_VAL(pdev, param, param->asic_default);
1089         }
1090 
1091         param++;
1092     }
1093 
1094     if(CHIP_REV(pdev) == CHIP_REV_FPGA || CHIP_REV(pdev) == CHIP_REV_IKOS)
1095     {
1096         pdev->params.test_mode |= TEST_MODE_INIT_GEN_BUF_DATA;
1097         pdev->params.test_mode |= TEST_MODE_SAVE_DUMMY_DMA_DATA;
1098         pdev->params.test_mode |= TEST_MODE_IGNORE_SHMEM_SIGNATURE;
1099         pdev->params.test_mode |= TEST_MODE_DRIVER_PULSE_ALWAYS_ALIVE;
1100     }
1101 
1102     /* Some chipsets are not capabable of handling multiple
1103      * read requests.  Currently we will get data corrupt on
1104      * Intel 840/860 chipset when one_tdma is not enabled. */
1105     if(pdev->hw_info.bus_mode == BUS_MODE_PCI)
1106     {
1107         if((CHIP_NUM(pdev)==CHIP_NUM_5706 || CHIP_NUM(pdev)==CHIP_NUM_5708) &&
1108             (CHIP_REV(pdev)==CHIP_REV_FPGA || CHIP_REV(pdev)==CHIP_REV_IKOS))
1109         {
1110             pdev->params.ping_pong_dma = FALSE;
1111         }
1112         else
1113         {
1114             pdev->params.ping_pong_dma = TRUE;
1115         }
1116     }
1117     else
1118     {
1119         pdev->params.ping_pong_dma = FALSE;
1120     }
1121 
1122     /* Get the pre-emphasis. */
1123     REG_RD_IND(
1124         pdev,
1125         pdev->hw_info.shmem_base +
1126             OFFSETOF(shmem_region_t, dev_info.port_hw_config.config),
1127         &pdev->params.serdes_pre_emphasis);
1128     pdev->params.serdes_pre_emphasis &= PORT_HW_CFG_SERDES_TXCTL3_MASK;
1129 
1130     /* This should be fixed in A1. */
1131     if(CHIP_ID(pdev) == CHIP_ID_5706_A0)
1132     {
1133         if(pdev->hw_info.bus_mode == BUS_MODE_PCIX &&
1134             pdev->hw_info.bus_speed == BUS_SPEED_133_MHZ)
1135         {
1136             pdev->params.num_rchans = 1;
1137         }
1138     }
1139 
1140     #if defined(DBG) && !defined(EXCLUDE_KQE_SUPPORT)
1141     pdev->params.con_kcqe_history_size = 256;
1142     pdev->params.con_kwqe_history_size = 256;
1143     #endif
1144 
1145     if(CHIP_NUM(pdev) == CHIP_NUM_5708 || CHIP_NUM(pdev) == CHIP_NUM_5709)
1146     {
1147         if(lm_get_medium(pdev) == LM_MEDIUM_TYPE_FIBER)
1148         {
1149             pdev->params.phy_addr = 2;
1150         }
1151     }
1152 
1153     if(CHIP_NUM(pdev) == CHIP_NUM_5709)
1154     {
1155         pdev->params.bin_mq_mode = TRUE;
1156     }
1157 
1158     DbgBreakIf(NUM_RX_CHAIN != NUM_TX_CHAIN);
1159 
1160     pdev->rx_info.num_rxq = NUM_RX_CHAIN;
1161     pdev->tx_info.num_txq = NUM_TX_CHAIN;
1162     pdev->tx_info.cu_idx = TX_CHAIN_IDX1;
1163 
1164     /* see if remote phy is enabled. */
1165     if(CHIP_REV(pdev) != CHIP_REV_IKOS)
1166     {
1167         REG_RD_IND(
1168             pdev,
1169             pdev->hw_info.shmem_base +
1170                 OFFSETOF(shmem_region_t,
1171                     dev_info.port_feature_config.config),
1172             &val);
1173         if(val & PORT_FEATURE_RPHY_ENABLED)
1174         {
1175             pdev->params.enable_remote_phy = 1;
1176         }
1177     }
1178 
1179     if (CHIP_NUM(pdev) == CHIP_NUM_5706 ||
1180         CHIP_NUM(pdev) == CHIP_NUM_5708)
1181     {
1182         // Due to slower speed of RV2P in Teton, we need to limit max
1183         // number of BD per each end bit. Otherwise, Appscan in RV2P
1184         // would spend excessive time scanning for end bit.
1185         pdev->params.limit_l4_rx_bd_cnt = 110;
1186     }
1187 
1188     /* Override the defaults with user configurations. */
1189     lm_status = mm_get_user_config(pdev);
1190     if(lm_status != LM_STATUS_SUCCESS)
1191     {
1192         return lm_status;
1193     }
1194 
1195     /* Make sure share memory is initialized by the firmware.  If not
1196      * fail initialization.  The check here is a little late as we
1197      * have already read some share memory info above.  This is ok. */
1198     REG_RD_IND(
1199         pdev,
1200         pdev->hw_info.shmem_base +
1201             OFFSETOF(shmem_region_t, dev_info.signature),
1202         &val);
1203     if((val & DEV_INFO_SIGNATURE_MASK) != DEV_INFO_SIGNATURE)
1204     {
1205         if(!(pdev->params.test_mode & TEST_MODE_IGNORE_SHMEM_SIGNATURE))
1206         {
1207             DbgBreakMsg("Shmem signature not present.\n");
1208 
1209             return LM_STATUS_BAD_SIGNATURE;
1210         }
1211 
1212         pdev->hw_info.mac_addr[0] = 0x00;
1213         pdev->hw_info.mac_addr[1] = 0x10;
1214         pdev->hw_info.mac_addr[2] = 0x18;
1215         pdev->hw_info.mac_addr[3] = 0xff;
1216         pdev->hw_info.mac_addr[4] = 0xff;
1217         pdev->hw_info.mac_addr[5] = 0xff;
1218 
1219         pdev->hw_info.iscsi_mac_addr[0] = 0x00;
1220         pdev->hw_info.iscsi_mac_addr[1] = 0x10;
1221         pdev->hw_info.iscsi_mac_addr[2] = 0x18;
1222         pdev->hw_info.iscsi_mac_addr[3] = 0xff;
1223         pdev->hw_info.iscsi_mac_addr[4] = 0xff;
1224         pdev->hw_info.iscsi_mac_addr[5] = 0xfe;
1225     }
1226 
1227     /* Make sure the parameter values are within range. */
1228     param = param_list;
1229     while(param->offset)
1230     {
1231         if(param->min != 0 || param->max != 0)
1232         {
1233             if(PARAM_VAL(pdev, param) < param->min ||
1234                 PARAM_VAL(pdev, param) > param->max)
1235             {
1236                 if(CHIP_REV(pdev) == CHIP_REV_FPGA ||
1237                     CHIP_REV(pdev) == CHIP_REV_IKOS)
1238                 {
1239                     SET_PARAM_VAL(pdev, param, param->fpga_ikos_default);
1240                 }
1241                 else
1242                 {
1243                     SET_PARAM_VAL(pdev, param, param->asic_default);
1244                 }
1245             }
1246         }
1247 
1248         param++;
1249     }
1250 
1251     /* params.mtu read from the registry does not include the MAC header
1252      * size.  We need to add the header here. */
1253     /*
1254      * get_vbd_params does this aleady
1255      * pdev->params.mtu += ETHERNET_PACKET_HEADER_SIZE;
1256      */
1257 
1258     #ifndef EXCLUDE_KQE_SUPPORT
1259     /* The size of the kcq histroy.  This is the number entries that will
1260      * not be over written by the chip. */
1261     if(pdev->params.kcq_history_size > (LM_PAGE_SIZE/sizeof(kcqe_t)) *
1262         pdev->params.kcq_page_cnt - 1)
1263     {
1264         pdev->params.kcq_history_size = ((LM_PAGE_SIZE/sizeof(kcqe_t)) *
1265             pdev->params.kcq_page_cnt) / 2;
1266     }
1267     #endif
1268 
1269     /* XXX: Exception for Xinan, need a permanent fix. */
1270     if (CHIP_NUM(pdev) == CHIP_NUM_5709)
1271     {
1272         pdev->params.rcv_buffer_offset = 0;
1273     }
1274 
1275     /* Check for a valid mac address. */
1276     if((pdev->params.mac_addr[0] == 0 &&
1277         pdev->params.mac_addr[1] == 0 &&
1278         pdev->params.mac_addr[2] == 0 &&
1279         pdev->params.mac_addr[3] == 0 &&
1280         pdev->params.mac_addr[4] == 0 &&
1281         pdev->params.mac_addr[5] == 0) || (pdev->params.mac_addr[0] & 1))
1282     {
1283         DbgMessage(pdev, WARN, "invalid LAA.\n");
1284 
1285         pdev->params.mac_addr[0] = pdev->hw_info.mac_addr[0];
1286         pdev->params.mac_addr[1] = pdev->hw_info.mac_addr[1];
1287         pdev->params.mac_addr[2] = pdev->hw_info.mac_addr[2];
1288         pdev->params.mac_addr[3] = pdev->hw_info.mac_addr[3];
1289         pdev->params.mac_addr[4] = pdev->hw_info.mac_addr[4];
1290         pdev->params.mac_addr[5] = pdev->hw_info.mac_addr[5];
1291     }
1292 
1293     /* There is a bug in HC that will cause it to stop updating the
1294      * status block.  This has been shown on some system with L4 traffic
1295      * goinging.  To workaround this, the trip points and interrupt trip
1296      * points must be the same and the statistics DMA must be disabled. */
1297     if(CHIP_ID(pdev) == CHIP_ID_5706_A0)
1298     {
1299         pdev->params.tx_quick_cons_trip_int = pdev->params.tx_quick_cons_trip;
1300         pdev->params.tx_ticks_int = pdev->params.tx_ticks;
1301         pdev->params.rx_quick_cons_trip_int = pdev->params.rx_quick_cons_trip;
1302         pdev->params.rx_ticks_int = pdev->params.rx_ticks;
1303         pdev->params.comp_prod_trip_int = pdev->params.comp_prod_trip;
1304         pdev->params.com_ticks_int = pdev->params.com_ticks;
1305         pdev->params.cmd_ticks_int = pdev->params.cmd_ticks;
1306         pdev->params.stats_ticks = 0;
1307     }
1308 
1309     /* enable_syn_rcvd will direct all tcp segments with syn bit to rxq 1. */
1310     if(pdev->params.enable_syn_rcvq &&
1311         NUM_RX_CHAIN > 1 &&
1312         pdev->params.l2_rx_desc_cnt[1] == 0)
1313     {
1314         pdev->params.l2_rx_desc_cnt[1] = 60;
1315     }
1316 
1317     /* Timer mode is broken is 5706_A0 and 5706_A1. */
1318     if(CHIP_ID(pdev) == CHIP_ID_5706_A0 || CHIP_ID(pdev) == CHIP_ID_5706_A1)
1319     {
1320         pdev->params.hc_timer_mode = HC_COLLECT_MODE;
1321     }
1322 
1323     /* Get the current fw_wr_seq. */
1324     REG_RD_IND(
1325         pdev,
1326         pdev->hw_info.shmem_base + OFFSETOF(shmem_region_t, drv_fw_mb.fw_mb),
1327         &val);
1328     pdev->vars.fw_wr_seq = val & DRV_MSG_SEQ;
1329 
1330     /* see if firmware is remote phy capable. */
1331     if(pdev->params.enable_remote_phy)
1332     {
1333         REG_RD_IND(
1334             pdev,
1335             pdev->hw_info.shmem_base +
1336                 OFFSETOF(shmem_region_t, drv_fw_cap_mb.fw_cap_mb),
1337             &val);
1338         if((val & CAPABILITY_SIGNATURE_MASK) != FW_CAP_SIGNATURE ||
1339             (val & FW_CAP_REMOTE_PHY_CAPABLE) == 0)
1340         {
1341             pdev->params.enable_remote_phy = 0;
1342         }
1343     }
1344 
1345     return LM_STATUS_SUCCESS;
1346 } /* lm_get_dev_info */
1347 
1348 
1349 
1350 #ifndef EXCLUDE_KQE_SUPPORT
1351 /*******************************************************************************
1352  * Description:
1353  *
1354  * Return:
1355  ******************************************************************************/
1356 STATIC lm_status_t
1357 init_kwq_resc(
1358     lm_device_t *pdev)
1359 {
1360     u32_t mem_size;
1361 
1362     if(pdev->params.kwq_page_cnt == 0)
1363     {
1364         return LM_STATUS_SUCCESS;
1365     }
1366 
1367     /* Allocate memory for the page table which does not need to be
1368      * page aligned.  However the size must be multiple of page size.
1369      *
1370      * When initialized, the page table will point to the pages
1371      * used for the kernel work queue. */
1372     mem_size = pdev->params.kwq_page_cnt * sizeof(lm_address_t);
1373     mem_size = (mem_size + LM_PAGE_MASK) & ~LM_PAGE_MASK;
1374 
1375     pdev->kq_info.kwq_pgtbl_virt = mm_alloc_phys_mem(
1376         pdev,
1377         mem_size,
1378         &pdev->kq_info.kwq_pgtbl_phy,
1379         PHYS_MEM_TYPE_NONCACHED,
1380         NULL);
1381     if(pdev->kq_info.kwq_pgtbl_virt == NULL)
1382     {
1383         return LM_STATUS_RESOURCE;
1384     }
1385 
1386     DbgBreakIf(pdev->kq_info.kwq_pgtbl_phy.as_u32.low & CACHE_LINE_SIZE_MASK);
1387 
1388     /* Allocate memory for the kernel work queue.  Here we allocate
1389      * a physically continuous block of memory and then initialize the
1390      * page table to pointer to the pages in this block.
1391      *
1392      * The kernel work queue is used by the driver similiar to a
1393      * circular ring.
1394      *
1395      * The memory block must be page aligned. */
1396     mem_size = LM_PAGE_SIZE * pdev->params.kwq_page_cnt;
1397     pdev->kq_info.kwq_virt = (kwqe_t *) mm_alloc_phys_mem(
1398         pdev,
1399         mem_size,
1400         &pdev->kq_info.kwq_phy,
1401         PHYS_MEM_TYPE_NONCACHED,
1402         NULL);
1403     if(pdev->kq_info.kwq_virt == NULL)
1404     {
1405         return LM_STATUS_RESOURCE;
1406     }
1407 
1408     DbgBreakIf(pdev->kq_info.kwq_phy.as_u32.low & CACHE_LINE_SIZE_MASK);
1409     DbgBreakIf(((u8_t *) pdev->kq_info.kwq_virt - (u8_t *) 0) & LM_PAGE_MASK);
1410 
1411     return LM_STATUS_SUCCESS;
1412 } /* init_kwq_resc */
1413 
1414 
1415 
1416 /*******************************************************************************
1417  * Description:
1418  *
1419  * Return:
1420  ******************************************************************************/
1421 STATIC lm_status_t
1422 init_kcq_resc(
1423     lm_device_t *pdev)
1424 {
1425 
1426     u32_t mem_size;
1427 
1428     if(pdev->params.kcq_page_cnt == 0)
1429     {
1430         return LM_STATUS_SUCCESS;
1431     }
1432 
1433     /* Allocate memory for the page table which does not need to be
1434      * page aligned.  However the size must be multiple of page size.
1435      *
1436      * When initialized, the page table will point to the pages
1437      * used for the kernel completion queue. */
1438     mem_size = pdev->params.kcq_page_cnt * sizeof(lm_address_t);
1439     mem_size = (mem_size + LM_PAGE_MASK) & ~LM_PAGE_MASK;
1440 
1441     pdev->kq_info.kcq_pgtbl_virt = mm_alloc_phys_mem(
1442         pdev,
1443         mem_size,
1444         &pdev->kq_info.kcq_pgtbl_phy,
1445         PHYS_MEM_TYPE_NONCACHED,
1446         NULL);
1447     if(pdev->kq_info.kcq_pgtbl_virt == NULL)
1448     {
1449         return LM_STATUS_RESOURCE;
1450     }
1451 
1452     DbgBreakIf(pdev->kq_info.kcq_pgtbl_phy.as_u32.low & CACHE_LINE_SIZE_MASK);
1453 
1454     /* Allocate memory for the kernel completion queue.  Here we allocate
1455      * a physically continuous block of memory and then initialize the
1456      * page table to pointer to the pages in this block.
1457      *
1458      * The kernel completion queue is used by the driver similiar to a
1459      * circular ring.
1460      *
1461      * The memory block must be page aligned. */
1462     mem_size = LM_PAGE_SIZE * pdev->params.kcq_page_cnt;
1463 
1464     pdev->kq_info.kcq_virt = (kcqe_t *) mm_alloc_phys_mem(
1465         pdev,
1466         mem_size,
1467         &pdev->kq_info.kcq_phy,
1468         PHYS_MEM_TYPE_NONCACHED,
1469         NULL);
1470     if(pdev->kq_info.kcq_virt == NULL)
1471     {
1472         return LM_STATUS_RESOURCE;
1473     }
1474 
1475     DbgBreakIf(pdev->kq_info.kcq_phy.as_u32.low & CACHE_LINE_SIZE_MASK);
1476     DbgBreakIf(((u8_t *) pdev->kq_info.kcq_virt - (u8_t *) 0) & LM_PAGE_MASK);
1477 
1478     return LM_STATUS_SUCCESS;
1479 } /* init_kcq_resc */
1480 #endif /* EXCLUDE_KQE_SUPPORT */
1481 
1482 
1483 
1484 #if INCLUDE_OFLD_SUPPORT
1485 /*******************************************************************************
1486  * Description:
1487  *
1488  * Return:
1489  ******************************************************************************/
1490 STATIC lm_status_t
1491 init_ofld_resc(
1492     lm_device_t *pdev)
1493 {
1494     lm_offload_info_t *ofld;
1495     u32_t mem_size;
1496     u32_t idx;
1497 
1498     ofld = &pdev->ofld;
1499     ofld->pdev = pdev;
1500     ofld->pg_cid_hnd_info.max_pending_pg_oflds = 16;
1501     ofld->pg_cid_hnd_info.pending_pg_ofld_cnt = 0;
1502 
1503     s_list_init(&ofld->active_req_list, NULL, NULL, 0);
1504     s_list_init(&ofld->upload_req_list, NULL, NULL, 0);
1505 
1506     for(idx = 0; idx < STATE_BLOCK_CNT; idx++)
1507     {
1508         d_list_init(&ofld->state_blks[idx].tcp_list, NULL, NULL, 0);
1509         d_list_init(&ofld->state_blks[idx].path_list, NULL, NULL, 0);
1510         d_list_init(&ofld->state_blks[idx].neigh_list, NULL, NULL, 0);
1511 
1512         ofld->state_blks[idx].max_conn = 0xffffffff;
1513 
1514         ofld->state_blks[idx].state_block_idx = idx;
1515         ofld->state_blks[idx].ofld = ofld;
1516 
1517         ofld->state_blks[idx].params.ticks_per_second = 100;
1518         ofld->state_blks[idx].params.ack_frequency = 2;
1519         ofld->state_blks[idx].params.delayed_ack_ticks = 20;
1520         ofld->state_blks[idx].params.max_retx = 10;
1521         ofld->state_blks[idx].params.doubt_reachability_retx = 8;
1522         ofld->state_blks[idx].params.sws_prevention_ticks = 10;
1523         ofld->state_blks[idx].params.dup_ack_threshold = 3;
1524         ofld->state_blks[idx].params.push_ticks = 20;
1525         ofld->state_blks[idx].params.nce_stale_ticks = 20;
1526         ofld->state_blks[idx].params.starting_ip_id = 0x8000;
1527     }
1528 
1529     /* Allocate memory for the generic buffer chain. */
1530     mem_size = LM_PAGE_SIZE * pdev->params.gen_bd_page_cnt;
1531     ofld->gen_chain.bd_chain_virt = (rx_bd_t *) mm_alloc_phys_mem(
1532         pdev,
1533         mem_size,
1534         &ofld->gen_chain.bd_chain_phy,
1535         PHYS_MEM_TYPE_UNSPECIFIED,
1536         NULL);
1537     if(ofld->gen_chain.bd_chain_virt == NULL)
1538     {
1539         return LM_STATUS_RESOURCE;
1540     }
1541 
1542     DbgBreakIf(ofld->gen_chain.bd_chain_phy.as_u32.low & CACHE_LINE_SIZE_MASK);
1543 
1544     ofld->gen_chain.cid_addr = GET_CID_ADDR(GEN_CHAIN_CID);
1545 
1546     s_list_init(&ofld->gen_chain.block_list, NULL, NULL, 0);
1547     s_list_init(&ofld->gen_chain.free_gen_buf_list, NULL, NULL, 0);
1548     s_list_init(&ofld->gen_chain.active_gen_buf_list, NULL, NULL, 0);
1549 
1550     /* Allocate memory for the hcopy chain. */
1551     if(pdev->params.hcopy_desc_cnt)
1552     {
1553         mem_size = LM_PAGE_SIZE * pdev->params.hcopy_bd_page_cnt;
1554         ofld->hcopy_chain.bd_chain_virt =(tx_bd_t *) mm_alloc_phys_mem(
1555             pdev,
1556             mem_size,
1557             &ofld->hcopy_chain.bd_chain_phy,
1558             PHYS_MEM_TYPE_UNSPECIFIED,
1559             NULL);
1560         if(ofld->hcopy_chain.bd_chain_virt == NULL)
1561         {
1562             return LM_STATUS_RESOURCE;
1563         }
1564 
1565         DbgBreakIf(ofld->hcopy_chain.bd_chain_phy.as_u32.low &
1566             CACHE_LINE_SIZE_MASK);
1567 
1568         ofld->hcopy_chain.cid_addr = GET_CID_ADDR(HCOPY_CID);
1569         ofld->hcopy_chain.hw_con_idx_ptr =
1570             &pdev->vars.status_virt->deflt.status_rx_quick_consumer_index15;
1571 
1572         s_list_init(&ofld->hcopy_chain.pending_descq, NULL, NULL, 0);
1573         s_list_init(&ofld->hcopy_chain.active_descq, NULL, NULL, 0);
1574     }
1575 
1576     ofld->cid_to_state = (lm_state_header_t **) mm_alloc_mem(
1577         pdev,
1578         sizeof(lm_state_header_t *) * MAX_CID,
1579         NULL);
1580     if(ofld->cid_to_state == NULL)
1581     {
1582         return LM_STATUS_RESOURCE;
1583     }
1584 
1585     return LM_STATUS_SUCCESS;
1586 } /* init_ofld_resc */
1587 #endif /* INCLUDE_OFLD_SUPPORT */
1588 
1589 
1590 
1591 /*******************************************************************************
1592  * Description:
1593  *
1594  * Return:
1595  ******************************************************************************/
1596 STATIC volatile u16_t *
1597 sblk_tx_con_idx_ptr(
1598     lm_device_t *pdev,
1599     lm_tx_chain_t *txq)
1600 {
1601     volatile status_blk_combined_t *sblk;
1602     volatile u16_t *idx_ptr;
1603 
1604     sblk = pdev->vars.status_virt;
1605 
1606     if(CHIP_NUM(pdev) == CHIP_NUM_5706 || CHIP_NUM(pdev) == CHIP_NUM_5708)
1607     {
1608         switch(txq->idx)
1609         {
1610             case TX_CHAIN_IDX0:
1611                 idx_ptr = &sblk->deflt.status_tx_quick_consumer_index0;
1612                 break;
1613 
1614             case TX_CHAIN_IDX1:
1615                 idx_ptr = &sblk->deflt.status_tx_quick_consumer_index1;
1616                 break;
1617 
1618             case TX_CHAIN_IDX2:
1619                 idx_ptr = &sblk->deflt.status_tx_quick_consumer_index2;
1620                 break;
1621 
1622             case TX_CHAIN_IDX3:
1623                 idx_ptr = &sblk->deflt.status_tx_quick_consumer_index3;
1624                 break;
1625 
1626             default:
1627                 idx_ptr = NULL;
1628 
1629                 DbgBreakIf(txq->idx != pdev->tx_info.cu_idx);
1630 
1631                 if(txq->idx == pdev->tx_info.cu_idx)
1632                 {
1633                     idx_ptr = &sblk->deflt.status_rx_quick_consumer_index14;
1634                 }
1635                 break;
1636         }
1637     }
1638     else
1639     {
1640         switch(txq->idx)
1641         {
1642             case TX_CHAIN_IDX0:
1643                 idx_ptr = &sblk->deflt.status_tx_quick_consumer_index0;
1644                 break;
1645 
1646             case TX_CHAIN_IDX1:
1647                 idx_ptr = &sblk->deflt.status_tx_quick_consumer_index1;
1648                 break;
1649 
1650             case TX_CHAIN_IDX2:
1651                 idx_ptr = &sblk->deflt.status_tx_quick_consumer_index2;
1652                 break;
1653 
1654             case TX_CHAIN_IDX3:
1655                 idx_ptr = &sblk->deflt.status_tx_quick_consumer_index3;
1656                 break;
1657 
1658             case TX_CHAIN_IDX4:
1659                 idx_ptr = &sblk->proc[0].status_pcpu_tx_quick_consumer_index;
1660                 break;
1661 
1662             case TX_CHAIN_IDX5:
1663                 idx_ptr = &sblk->proc[1].status_pcpu_tx_quick_consumer_index;
1664                 break;
1665 
1666             case TX_CHAIN_IDX6:
1667                 idx_ptr = &sblk->proc[2].status_pcpu_tx_quick_consumer_index;
1668                 break;
1669 
1670             case TX_CHAIN_IDX7:
1671                 idx_ptr = &sblk->proc[3].status_pcpu_tx_quick_consumer_index;
1672                 break;
1673 
1674             case TX_CHAIN_IDX8:
1675                 idx_ptr = &sblk->proc[4].status_pcpu_tx_quick_consumer_index;
1676                 break;
1677 
1678             case TX_CHAIN_IDX9:
1679                 idx_ptr = &sblk->proc[5].status_pcpu_tx_quick_consumer_index;
1680                 break;
1681 
1682             case TX_CHAIN_IDX10:
1683                 idx_ptr = &sblk->proc[6].status_pcpu_tx_quick_consumer_index;
1684                 break;
1685 
1686             case TX_CHAIN_IDX11:
1687                 idx_ptr = &sblk->proc[7].status_pcpu_tx_quick_consumer_index;
1688                 break;
1689 
1690             default:
1691                 DbgBreakMsg("invalid xinan tx index.\n");
1692                 idx_ptr = NULL;
1693                 break;
1694         }
1695     }
1696 
1697     return idx_ptr;
1698 } /* sblk_tx_con_idx_ptr */
1699 
1700 
1701 
1702 /*******************************************************************************
1703  * Description:
1704  *
1705  * Return:
1706  ******************************************************************************/
1707 STATIC lm_status_t
1708 init_l2tx_resc(
1709     lm_device_t *pdev)
1710 {
1711     lm_tx_chain_t *txq;
1712     u32_t bd_page_cnt;
1713     u32_t mem_size;
1714     u32_t idx;
1715     u32_t num_tx_chains;
1716 
1717 #if defined(LM_NON_LEGACY_MODE_SUPPORT)
1718     num_tx_chains = MAX_TX_CHAIN;
1719     if(CHIP_NUM(pdev) == CHIP_NUM_5706 || CHIP_NUM(pdev) == CHIP_NUM_5708)
1720     {
1721         num_tx_chains = pdev->tx_info.num_txq;
1722     }
1723 #else
1724     DbgBreakIf(pdev->tx_info.num_txq > MAX_TX_CHAIN);
1725     for(idx = pdev->tx_info.num_txq; idx < MAX_TX_CHAIN; idx++)
1726     {
1727         pdev->params.l2_tx_bd_page_cnt[idx] = 0;
1728     }
1729     num_tx_chains = pdev->tx_info.num_txq;
1730 #endif
1731     for(idx = 0; idx < num_tx_chains; idx++)
1732     {
1733         txq = &pdev->tx_info.chain[idx];
1734         txq->idx = idx;
1735         txq->cid_addr = GET_CID_ADDR(L2TX_CID_BASE + 2 * txq->idx);
1736 
1737         s_list_init(&txq->active_descq, NULL, NULL, 0);
1738 
1739         if(CHIP_NUM(pdev) == CHIP_NUM_5706 || CHIP_NUM(pdev) == CHIP_NUM_5708)
1740         {
1741             DbgBreakIf(idx > 4);
1742 
1743             if(txq->idx == pdev->tx_info.cu_idx && txq->idx != TX_CHAIN_IDX1)
1744             {
1745                 DbgBreakIf(idx != 4);
1746                 txq->cid_addr = GET_CID_ADDR(30);
1747             }
1748         }
1749         else if(txq->idx >= 4)
1750         {
1751             DbgBreakIf(idx > 11);
1752 
1753             /* Xinan has to use tx1 for catchup because catchup2 uses
1754              * status_rx_quick_consumer_index14 for completion.  This
1755              * status block index is not available on Xinan. */
1756             DbgBreakIf(pdev->tx_info.cu_idx != TX_CHAIN_IDX1);
1757 
1758             if(txq->idx >= 4)
1759             {
1760                 txq->cid_addr = GET_CID_ADDR(L2TX_TSS_CID_BASE + txq->idx - 4);
1761             }
1762         }
1763 
1764         bd_page_cnt = pdev->params.l2_tx_bd_page_cnt[txq->idx];
1765         if(bd_page_cnt)
1766         {
1767             mem_size = LM_PAGE_SIZE * bd_page_cnt;
1768 
1769             txq->bd_chain_virt = (tx_bd_t *) mm_alloc_phys_mem(
1770                 pdev,
1771                 mem_size,
1772                 &txq->bd_chain_phy,
1773                 PHYS_MEM_TYPE_NONCACHED,
1774                 NULL);
1775             if(txq->bd_chain_virt == NULL)
1776             {
1777                 return LM_STATUS_RESOURCE;
1778             }
1779 
1780             DbgBreakIf(txq->bd_chain_phy.as_u32.low & CACHE_LINE_SIZE_MASK);
1781         }
1782 
1783         txq->hw_con_idx_ptr = sblk_tx_con_idx_ptr(pdev, txq);
1784     }
1785 
1786     return LM_STATUS_SUCCESS;
1787 } /* init_l2tx_resc */
1788 
1789 
1790 
1791 /*******************************************************************************
1792  * Description:
1793  *
1794  * Return:
1795  ******************************************************************************/
1796 STATIC volatile u16_t *
1797 sblk_rx_con_idx_ptr(
1798     lm_device_t *pdev,
1799     lm_rx_chain_t *rxq)
1800 {
1801     volatile status_blk_combined_t *sblk;
1802     volatile u16_t *idx_ptr;
1803 
1804     sblk = pdev->vars.status_virt;
1805 
1806     if(CHIP_NUM(pdev) == CHIP_NUM_5706 || CHIP_NUM(pdev) == CHIP_NUM_5708)
1807     {
1808         switch(rxq->idx)
1809         {
1810             case RX_CHAIN_IDX0:
1811                 idx_ptr = &sblk->deflt.status_rx_quick_consumer_index0;
1812                 break;
1813 
1814             case RX_CHAIN_IDX1:
1815                 idx_ptr = &sblk->deflt.status_rx_quick_consumer_index1;
1816                 break;
1817 
1818             case RX_CHAIN_IDX2:
1819                 idx_ptr = &sblk->deflt.status_rx_quick_consumer_index2;
1820                 break;
1821 
1822             case RX_CHAIN_IDX3:
1823                 idx_ptr = &sblk->deflt.status_rx_quick_consumer_index3;
1824                 break;
1825 
1826             case RX_CHAIN_IDX4:
1827                 idx_ptr = &sblk->deflt.status_rx_quick_consumer_index4;
1828                 break;
1829 
1830             case RX_CHAIN_IDX5:
1831                 idx_ptr = &sblk->deflt.status_rx_quick_consumer_index5;
1832                 break;
1833 
1834             case RX_CHAIN_IDX6:
1835                 idx_ptr = &sblk->deflt.status_rx_quick_consumer_index6;
1836                 break;
1837 
1838             case RX_CHAIN_IDX7:
1839                 idx_ptr = &sblk->deflt.status_rx_quick_consumer_index7;
1840                 break;
1841 
1842             case RX_CHAIN_IDX8:
1843                 idx_ptr = &sblk->deflt.status_rx_quick_consumer_index8;
1844                 break;
1845 
1846             case RX_CHAIN_IDX9:
1847                 idx_ptr = &sblk->deflt.status_rx_quick_consumer_index9;
1848                 break;
1849 
1850             case RX_CHAIN_IDX10:
1851                 idx_ptr = &sblk->deflt.status_rx_quick_consumer_index10;
1852                 break;
1853 
1854             case RX_CHAIN_IDX11:
1855                 idx_ptr = &sblk->deflt.status_rx_quick_consumer_index11;
1856                 break;
1857 
1858             case RX_CHAIN_IDX12:
1859                 idx_ptr = &sblk->deflt.status_rx_quick_consumer_index12;
1860                 break;
1861 
1862             case RX_CHAIN_IDX13:
1863                 idx_ptr = &sblk->deflt.status_rx_quick_consumer_index13;
1864                 break;
1865 
1866             case RX_CHAIN_IDX14:
1867                 idx_ptr = &sblk->deflt.status_rx_quick_consumer_index14;
1868                 break;
1869 
1870             case RX_CHAIN_IDX15:
1871                 idx_ptr = &sblk->deflt.status_rx_quick_consumer_index15;
1872                 break;
1873 
1874             default:
1875                 DbgBreakMsg("invalid teton rx index.\n");
1876                 idx_ptr = NULL;
1877                 break;
1878         }
1879     }
1880     else
1881     {
1882         switch(rxq->idx)
1883         {
1884             case RX_CHAIN_IDX0:
1885                 idx_ptr = &sblk->deflt.status_rx_quick_consumer_index0;
1886                 break;
1887 
1888             case RX_CHAIN_IDX1:
1889                 idx_ptr = &sblk->deflt.status_rx_quick_consumer_index1;
1890                 break;
1891 
1892             case RX_CHAIN_IDX2:
1893                 idx_ptr = &sblk->deflt.status_rx_quick_consumer_index2;
1894                 break;
1895 
1896             case RX_CHAIN_IDX3:
1897                 idx_ptr = &sblk->deflt.status_rx_quick_consumer_index3;
1898                 break;
1899 
1900             case RX_CHAIN_IDX4:
1901                 idx_ptr = &sblk->proc[0].status_pcpu_rx_quick_consumer_index;
1902                 break;
1903 
1904             case RX_CHAIN_IDX5:
1905                 idx_ptr = &sblk->proc[1].status_pcpu_rx_quick_consumer_index;
1906                 break;
1907 
1908             case RX_CHAIN_IDX6:
1909                 idx_ptr = &sblk->proc[2].status_pcpu_rx_quick_consumer_index;
1910                 break;
1911 
1912             case RX_CHAIN_IDX7:
1913                 idx_ptr = &sblk->proc[3].status_pcpu_rx_quick_consumer_index;
1914                 break;
1915 
1916             case RX_CHAIN_IDX8:
1917                 idx_ptr = &sblk->proc[4].status_pcpu_rx_quick_consumer_index;
1918                 break;
1919 
1920             case RX_CHAIN_IDX9:
1921                 idx_ptr = &sblk->proc[5].status_pcpu_rx_quick_consumer_index;
1922                 break;
1923 
1924             case RX_CHAIN_IDX10:
1925                 idx_ptr = &sblk->proc[6].status_pcpu_rx_quick_consumer_index;
1926                 break;
1927 
1928             case RX_CHAIN_IDX11:
1929                 idx_ptr = &sblk->proc[7].status_pcpu_rx_quick_consumer_index;
1930                 break;
1931 
1932             default:
1933                 DbgBreakMsg("invalid xinan rx index.\n");
1934                 idx_ptr = NULL;
1935                 break;
1936         }
1937     }
1938 
1939     return idx_ptr;
1940 } /* sblk_rx_con_idx_ptr */
1941 
1942 
1943 
1944 /*******************************************************************************
1945  * Description:
1946  *
1947  * Return:
1948  ******************************************************************************/
1949 STATIC lm_status_t
1950 alloc_l2rx_desc(
1951     lm_device_t *pdev,
1952     lm_rx_chain_t *rxq)
1953 {
1954     u32_t bd_page_cnt;
1955     lm_packet_t *pkt;
1956     u32_t desc_size;
1957     u32_t desc_cnt;
1958     u8_t *mem_virt;
1959     u32_t mem_size;
1960     u32_t idx;
1961 
1962     bd_page_cnt = pdev->params.l2_rx_bd_page_cnt[rxq->idx];
1963     desc_cnt = pdev->params.l2_rx_desc_cnt[rxq->idx];
1964 
1965     if(bd_page_cnt == 0 || desc_cnt == 0)
1966     {
1967         pdev->params.l2_rx_bd_page_cnt[rxq->idx] = 0;
1968         pdev->params.l2_rx_desc_cnt[rxq->idx] = 0;
1969 
1970         return LM_STATUS_SUCCESS;
1971     }
1972 
1973     mem_size = LM_PAGE_SIZE * bd_page_cnt;
1974 
1975     rxq->bd_chain_virt = (rx_bd_t *) mm_alloc_phys_mem(
1976         pdev,
1977         mem_size,
1978         &rxq->bd_chain_phy,
1979         PHYS_MEM_TYPE_NONCACHED,
1980         NULL);
1981     if(rxq->bd_chain_virt == NULL)
1982     {
1983         return LM_STATUS_RESOURCE;
1984     }
1985 
1986     DbgBreakIf(rxq->bd_chain_phy.as_u32.low & CACHE_LINE_SIZE_MASK);
1987 
1988 #ifndef LM_NON_LEGACY_MODE_SUPPORT
1989     desc_size = mm_desc_size(pdev, DESC_TYPE_L2RX_PACKET) + SIZEOF_SIG;
1990     mem_size = desc_size * desc_cnt;
1991 
1992     mem_virt = (u8_t *) mm_alloc_mem(pdev, mem_size, NULL);
1993     if(mem_virt == NULL)
1994     {
1995         return LM_STATUS_RESOURCE;
1996     }
1997 
1998     for(idx = 0; idx < desc_cnt; idx++)
1999     {
2000         pkt = (lm_packet_t *) (mem_virt + SIZEOF_SIG);
2001         mem_virt += desc_size;
2002         mem_size -= desc_size;
2003 
2004         SIG(pkt) = L2PACKET_RX_SIG;
2005         // full packet needs to hold mtu + 4-byte CRC32
2006         pkt->u1.rx.buf_size = pdev->params.mtu + 4;
2007         pkt->u1.rx.buf_size += L2RX_FRAME_HDR_LEN;
2008         pkt->u1.rx.buf_size += pdev->params.rcv_buffer_offset;
2009         pkt->u1.rx.buf_size += CACHE_LINE_SIZE_MASK + 1;
2010         pkt->u1.rx.buf_size &= ~CACHE_LINE_SIZE_MASK;
2011 
2012         s_list_push_tail(&rxq->free_descq, &pkt->link);
2013     }
2014 
2015     DbgBreakIf(mem_size);
2016     DbgBreakIf(s_list_entry_cnt(&rxq->free_descq) != desc_cnt);
2017 #endif
2018     return LM_STATUS_SUCCESS;
2019 } /* alloc_l2rx_desc */
2020 
2021 
2022 
2023 /*******************************************************************************
2024  * Description:
2025  *
2026  * Return:
2027  ******************************************************************************/
2028 STATIC lm_status_t
2029 init_l2rx_resc(
2030     lm_device_t *pdev)
2031 {
2032     lm_status_t lm_status;
2033     lm_rx_chain_t *rxq;
2034     u32_t idx;
2035 
2036 #ifndef LM_NON_LEGACY_MODE_SUPPORT
2037     DbgBreakIf(pdev->rx_info.num_rxq > MAX_RX_CHAIN);
2038 
2039     for(idx = pdev->rx_info.num_rxq; idx < MAX_RX_CHAIN; idx++)
2040     {
2041         pdev->params.l2_rx_desc_cnt[idx] = 0;
2042         pdev->params.l2_rx_bd_page_cnt[idx] = 0;
2043     }
2044 #endif
2045     for(idx = 0; idx < pdev->rx_info.num_rxq ; idx++)
2046     {
2047         rxq = &pdev->rx_info.chain[idx];
2048         rxq->idx = idx;
2049         rxq->cid_addr = GET_CID_ADDR(L2RX_CID_BASE + rxq->idx);
2050 
2051         s_list_init(&rxq->free_descq, NULL, NULL, 0);
2052         s_list_init(&rxq->active_descq, NULL, NULL, 0);
2053 
2054         lm_status = alloc_l2rx_desc(pdev, rxq);
2055         if(lm_status != LM_STATUS_SUCCESS)
2056         {
2057             return lm_status;
2058         }
2059 
2060         rxq->hw_con_idx_ptr = sblk_rx_con_idx_ptr(pdev, rxq);
2061     }
2062 
2063     return LM_STATUS_SUCCESS;
2064 } /* init_l2rx_resc */
2065 
2066 
2067 
2068 /*******************************************************************************
2069  * Description:
2070  *
2071  * Return:
2072  ******************************************************************************/
2073 STATIC lm_status_t
2074 init_context_resc_5709(
2075     lm_device_t *pdev)
2076 {
2077     phy_mem_block_t *ctx_mem;
2078     u32_t page_align_delta;
2079     lm_address_t mem_phy;
2080     u32_t ctx_in_mblk;
2081     u32_t mem_size;
2082     u8_t *mem_virt;
2083     u32_t ctx_cnt;
2084 
2085     DbgBreakIf(CHIP_NUM(pdev) != CHIP_NUM_5709);
2086     DbgBreakIf(CTX_MBLK_SIZE & LM_PAGE_MASK);
2087     DbgBreakIf(MAX_CTX > 16 * 1024);
2088     DbgBreakIf(MAX_CTX * ONE_CTX_SIZE / CTX_MBLK_SIZE != NUM_CTX_MBLKS);
2089     DbgBreakIf((MAX_CTX * ONE_CTX_SIZE) % CTX_MBLK_SIZE);
2090 
2091     ctx_mem = &pdev->vars.ctx_mem[0];
2092     ctx_cnt = 0;
2093 
2094     while(ctx_cnt < MAX_CTX)
2095     {
2096         ctx_in_mblk = CTX_MBLK_SIZE / ONE_CTX_SIZE;
2097         if(ctx_cnt + ctx_in_mblk > MAX_CTX)
2098         {
2099             ctx_in_mblk = MAX_CTX - ctx_cnt;
2100         }
2101 
2102         mem_size = ctx_in_mblk * ONE_CTX_SIZE;
2103 
2104         mem_virt = (u8_t *) mm_alloc_phys_mem(
2105             pdev,
2106             mem_size + LM_PAGE_MASK,
2107             &mem_phy,
2108             PHYS_MEM_TYPE_NONCACHED,
2109             NULL);
2110         if(mem_virt == NULL)
2111         {
2112             return LM_STATUS_RESOURCE;
2113         }
2114 
2115         page_align_delta = mem_phy.as_u32.low & LM_PAGE_MASK;
2116         if(page_align_delta)
2117         {
2118             page_align_delta = LM_PAGE_SIZE - page_align_delta;
2119         }
2120 
2121         mem_virt += page_align_delta;
2122         LM_INC64(&mem_phy, page_align_delta);
2123 
2124         ctx_mem->start_phy = mem_phy;
2125         ctx_mem->start = mem_virt;
2126         ctx_mem->size = mem_size;
2127         ctx_mem++;
2128 
2129         ctx_cnt += mem_size / ONE_CTX_SIZE;
2130     }
2131 
2132     return LM_STATUS_SUCCESS;
2133 } /* init_context_resc_5709 */
2134 
2135 
2136 
2137 /*******************************************************************************
2138  * Description:
2139  *
2140  * Return:
2141  ******************************************************************************/
2142 lm_status_t
2143 lm_init_resc(
2144     lm_device_t *pdev)
2145 {
2146     lm_status_t lm_status;
2147     lm_address_t mem_phy;
2148     u8_t *mem_virt;
2149     u32_t mem_size;
2150 
2151     #ifndef EXCLUDE_KQE_SUPPORT
2152     lm_status = init_kwq_resc(pdev);
2153     if(lm_status != LM_STATUS_SUCCESS)
2154     {
2155         return lm_status;
2156     }
2157 
2158     lm_status = init_kcq_resc(pdev);
2159     if(lm_status != LM_STATUS_SUCCESS)
2160     {
2161         return lm_status;
2162     }
2163     #endif
2164 
2165     #if INCLUDE_OFLD_SUPPORT
2166     lm_status = init_ofld_resc(pdev);
2167     if(lm_status != LM_STATUS_SUCCESS)
2168     {
2169         return lm_status;
2170     }
2171     #endif
2172 
2173     DbgBreakIf(sizeof(status_blk_combined_t) > STATUS_BLOCK_BUFFER_SIZE);
2174     DbgBreakIf(sizeof(statistics_block_t) > CHIP_STATS_BUFFER_SIZE);
2175 
2176     mem_size = STATUS_BLOCK_BUFFER_SIZE +
2177     #ifndef EXCLUDE_RSS_SUPPORT
2178         RSS_INDIRECTION_TABLE_SIZE +
2179         RSS_LOOKUP_TABLE_WA +
2180     #endif
2181         CHIP_STATS_BUFFER_SIZE;
2182 
2183     mem_virt = mm_alloc_phys_mem(
2184         pdev,
2185         mem_size,
2186         &mem_phy,
2187         PHYS_MEM_TYPE_NONCACHED,
2188         NULL);
2189     if(mem_virt == NULL)
2190     {
2191         return LM_STATUS_RESOURCE;
2192     }
2193 
2194     DbgBreakIf(mem_phy.as_u32.low & CACHE_LINE_SIZE_MASK);
2195 
2196     pdev->vars.status_virt = (status_blk_combined_t *) mem_virt;
2197     pdev->vars.status_phy = mem_phy;
2198     mem_virt += STATUS_BLOCK_BUFFER_SIZE;
2199     LM_INC64(&mem_phy, STATUS_BLOCK_BUFFER_SIZE);
2200 
2201     pdev->vars.stats_virt = (statistics_block_t *) mem_virt;
2202     pdev->vars.stats_phy = mem_phy;
2203     mem_virt += CHIP_STATS_BUFFER_SIZE;
2204     LM_INC64(&mem_phy, CHIP_STATS_BUFFER_SIZE);
2205 
2206     #ifndef EXCLUDE_RSS_SUPPORT
2207     pdev->rx_info.rss_ind_table_virt = mem_virt;
2208     pdev->rx_info.rss_ind_table_phy = mem_phy;
2209     #endif
2210 
2211     if(CHIP_NUM(pdev) == CHIP_NUM_5709)
2212     {
2213         lm_status = init_context_resc_5709(pdev);
2214         if(lm_status != LM_STATUS_SUCCESS)
2215         {
2216             return lm_status;
2217         }
2218     }
2219 
2220     lm_status = init_l2tx_resc(pdev);
2221     if(lm_status != LM_STATUS_SUCCESS)
2222     {
2223         return lm_status;
2224     }
2225 
2226     lm_status = init_l2rx_resc(pdev);
2227     if(lm_status != LM_STATUS_SUCCESS)
2228     {
2229         return lm_status;
2230     }
2231 
2232     lm_clear_nwuf(pdev);
2233 
2234     return LM_STATUS_SUCCESS;
2235 } /* lm_init_resc */
2236 
2237 
2238 
2239 /*******************************************************************************
2240  * Description:
2241  *
2242  * Return:
2243  ******************************************************************************/
2244 STATIC u32_t
2245 compute_crc32(
2246     u8_t *buf,
2247     u32_t buf_size)
2248 {
2249     u32_t reg;
2250     u32_t tmp;
2251     u32_t j;
2252     u32_t k;
2253 
2254     reg = 0xffffffff;
2255 
2256     for(j = 0; j < buf_size; j++)
2257     {
2258         reg ^= buf[j];
2259 
2260         for(k = 0; k < 8; k++)
2261         {
2262             tmp = reg & 0x01;
2263 
2264             reg >>= 1;
2265 
2266             if(tmp)
2267             {
2268                 reg ^= 0xedb88320;
2269             }
2270         }
2271     }
2272 
2273     return ~reg;
2274 } /* compute_crc32 */
2275 
2276 
2277 
2278 #define NUM_MC_HASH_REGISTERS                   8
2279 /*******************************************************************************
2280  * Description:
2281  *
2282  * Return:
2283  ******************************************************************************/
2284 STATIC void
2285 set_mc_hash_reg(
2286     lm_device_t *pdev,
2287     lm_mc_table_t *mc_table)
2288 {
2289     u32_t hash_reg[NUM_MC_HASH_REGISTERS];
2290     u32_t reg_idx;
2291     u32_t bit_pos;
2292     u32_t idx;
2293     u32_t crc32;
2294 
2295     /* Program the MC hash registers.
2296      *    The MAC hash registers are used to help discard unwanted
2297      *    multicast packets as they are received from the external
2298      *    media.  The destination address is fed into the normal CRC
2299      *    algorithm in order to generate a hash function.  The most
2300      *    significant bits of the CRC are then used without any inversion
2301      *    in reverse order to index into a hash table which is comprised
2302      *    of these MAC hash registers.  If the CRC is calculated by
2303      *    shifting right then the rightmost bits of the CRC can be
2304      *    directly used with no additional inversion or bit swapping
2305      *    required.  All four MAC hash registers are used such that
2306      *    register 1 bit-32 is the most significant hash table entry
2307      *    and register 8 bit-0 is the least significant hash table entry.
2308      *    This follows the normal big-endian ordering used throughout
2309      *    Teton.  Since there are 256 hash table entries, 8-bits are
2310      *    used from the CRC.  The hash registers are ignored if the
2311      *    receive MAC is in promiscuous mode. */
2312     for(idx = 0; idx < NUM_MC_HASH_REGISTERS; idx++)
2313     {
2314         hash_reg[idx] = 0;
2315     }
2316 
2317     for(idx = 0; idx < mc_table->entry_cnt; idx++)
2318     {
2319         crc32 = compute_crc32(
2320             mc_table->addr_arr[idx].mc_addr,
2321             ETHERNET_ADDRESS_SIZE);
2322 
2323         /* The most significant 7 bits of the CRC32 (no inversion),
2324          * are used to index into one of the possible 128 bit positions. */
2325         bit_pos = ~crc32 & 0xff;
2326 
2327         reg_idx = (bit_pos & 0xe0) >> 5;
2328 
2329         bit_pos &= 0x1f;
2330 
2331         hash_reg[reg_idx] |= (1 << bit_pos);
2332     }
2333 
2334     for(idx = 0; idx < NUM_MC_HASH_REGISTERS; idx++)
2335     {
2336         REG_WR(pdev, emac.emac_multicast_hash[idx], hash_reg[idx]);
2337     }
2338 } /* set_mc_hash_reg */
2339 
2340 
2341 
2342 /*******************************************************************************
2343  * Description:
2344  *
2345  * Return:
2346  ******************************************************************************/
2347 lm_status_t
2348 lm_set_rx_mask(
2349     lm_device_t *pdev,
2350     u32_t user_idx,
2351     lm_rx_mask_t rx_mask)
2352 {
2353     u32_t combined_rx_mask;
2354     u32_t invalid_rx_mask;
2355     u32_t sort_mode;
2356     u32_t rx_mode;
2357     u32_t val;
2358     u32_t idx;
2359 
2360     if(user_idx >= MAX_RX_FILTER_USER_CNT)
2361     {
2362         DbgBreakMsg("invalid user index.\n");
2363 
2364         return LM_STATUS_FAILURE;
2365     }
2366 
2367     combined_rx_mask = rx_mask;
2368     for(idx = 0; idx < MAX_RX_FILTER_USER_CNT; idx++)
2369     {
2370         if(idx != user_idx)
2371         {
2372             combined_rx_mask |= pdev->rx_info.mask[idx];
2373         }
2374     }
2375 
2376     /* Set up the rx_mode register. */
2377     invalid_rx_mask = combined_rx_mask;
2378     REG_RD(pdev, emac.emac_rx_mode, &rx_mode);
2379 
2380     if(invalid_rx_mask & LM_RX_MASK_ACCEPT_UNICAST)
2381     {
2382         invalid_rx_mask &= ~LM_RX_MASK_ACCEPT_UNICAST;
2383     }
2384 
2385     if(invalid_rx_mask & LM_RX_MASK_ACCEPT_MULTICAST)
2386     {
2387         invalid_rx_mask &= ~LM_RX_MASK_ACCEPT_MULTICAST;
2388     }
2389 
2390     if(invalid_rx_mask & LM_RX_MASK_ACCEPT_ALL_MULTICAST)
2391     {
2392         invalid_rx_mask &= ~LM_RX_MASK_ACCEPT_ALL_MULTICAST;
2393     }
2394 
2395     rx_mode &= ~EMAC_RX_MODE_FILT_BROADCAST;
2396     if(invalid_rx_mask & LM_RX_MASK_ACCEPT_BROADCAST)
2397     {
2398         invalid_rx_mask &= ~LM_RX_MASK_ACCEPT_BROADCAST;
2399     }
2400     else
2401     {
2402         rx_mode |= EMAC_RX_MODE_FILT_BROADCAST;
2403     }
2404 
2405     rx_mode &= ~(EMAC_RX_MODE_ACCEPT_RUNTS | EMAC_RX_MODE_ACCEPT_OVERSIZE);
2406     if(invalid_rx_mask & LM_RX_MASK_ACCEPT_ERROR_PACKET)
2407     {
2408         invalid_rx_mask &= ~LM_RX_MASK_ACCEPT_ERROR_PACKET;
2409         rx_mode |= EMAC_RX_MODE_ACCEPT_RUNTS |
2410             EMAC_RX_MODE_ACCEPT_OVERSIZE |
2411             EMAC_RX_MODE_NO_CRC_CHK;
2412     }
2413 
2414     rx_mode &= ~EMAC_RX_MODE_PROMISCUOUS;
2415     if(invalid_rx_mask & LM_RX_MASK_PROMISCUOUS_MODE)
2416     {
2417         invalid_rx_mask &= ~LM_RX_MASK_PROMISCUOUS_MODE;
2418         rx_mode |= EMAC_RX_MODE_PROMISCUOUS;
2419     }
2420 
2421     if(invalid_rx_mask)
2422     {
2423         DbgBreakMsg("Unknown rx_mask.\n");
2424 
2425         return LM_STATUS_FAILURE;
2426     }
2427 
2428     if(combined_rx_mask & LM_RX_MASK_ACCEPT_ALL_MULTICAST)
2429     {
2430         for(idx = 0; idx < NUM_MC_HASH_REGISTERS; idx++)
2431         {
2432             REG_WR(pdev, emac.emac_multicast_hash[idx], 0xffffffff);
2433         }
2434     }
2435     else if(combined_rx_mask & LM_RX_MASK_ACCEPT_MULTICAST)
2436     {
2437         set_mc_hash_reg(pdev, &pdev->mc_table);
2438     }
2439     else
2440     {
2441         for(idx = 0; idx < NUM_MC_HASH_REGISTERS; idx++)
2442         {
2443             REG_WR(pdev, emac.emac_multicast_hash[idx], 0);
2444         }
2445     }
2446 
2447     pdev->rx_info.mask[user_idx] = rx_mask;
2448 
2449     val = rx_mode | EMAC_RX_MODE_SORT_MODE;
2450     if(pdev->params.keep_vlan_tag)
2451     {
2452         val |= EMAC_RX_MODE_KEEP_VLAN_TAG;
2453     }
2454     REG_WR(pdev, emac.emac_rx_mode, val);
2455 
2456     /* Set up the sort_mode register. */
2457     sort_mode = 0;
2458 
2459     if(rx_mask & LM_RX_MASK_ACCEPT_UNICAST)
2460     {
2461         sort_mode |= 1 << user_idx;
2462     }
2463 
2464     if(rx_mask & LM_RX_MASK_ACCEPT_MULTICAST)
2465     {
2466         sort_mode |= RPM_SORT_USER0_MC_HSH_EN;
2467     }
2468 
2469     if(rx_mask & LM_RX_MASK_ACCEPT_ALL_MULTICAST)
2470     {
2471         sort_mode |= RPM_SORT_USER0_MC_EN;
2472     }
2473 
2474     if(rx_mask & LM_RX_MASK_ACCEPT_BROADCAST)
2475     {
2476         sort_mode |= RPM_SORT_USER0_BC_EN;
2477     }
2478 
2479     if(rx_mask & LM_RX_MASK_PROMISCUOUS_MODE)
2480     {
2481         sort_mode |= RPM_SORT_USER0_PROM_EN | RPM_SORT_USER0_PROM_VLAN;
2482     }
2483 
2484     switch(user_idx)
2485     {
2486         case RX_FILTER_USER_IDX0:
2487             REG_RD(pdev, rpm.rpm_sort_user0, &val);
2488 
2489             REG_WR(pdev, rpm.rpm_sort_user0, 0x00000000);
2490             REG_WR(pdev, rpm.rpm_sort_user0, sort_mode);
2491 
2492             val &= 0xffff;
2493             val &= ~(1 << user_idx);
2494 
2495             sort_mode |= val | RPM_SORT_USER0_ENA;
2496             REG_WR(pdev, rpm.rpm_sort_user0, sort_mode);
2497             break;
2498 
2499         case RX_FILTER_USER_IDX1:
2500             REG_RD(pdev, rpm.rpm_sort_user1, &val);
2501 
2502             REG_WR(pdev, rpm.rpm_sort_user1, 0x00000000);
2503             REG_WR(pdev, rpm.rpm_sort_user1, sort_mode);
2504 
2505             val &= 0xffff;
2506             val &= ~(1 << user_idx);
2507 
2508             sort_mode |= val | RPM_SORT_USER0_ENA;
2509             REG_WR(pdev, rpm.rpm_sort_user1, sort_mode);
2510             break;
2511 
2512         case RX_FILTER_USER_IDX2:
2513             REG_RD(pdev, rpm.rpm_sort_user2, &val);
2514 
2515             REG_WR(pdev, rpm.rpm_sort_user2, 0x00000000);
2516             REG_WR(pdev, rpm.rpm_sort_user2, sort_mode);
2517 
2518             val &= 0xffff;
2519             val &= ~(1 << user_idx);
2520 
2521             sort_mode |= val | RPM_SORT_USER0_ENA;
2522             REG_WR(pdev, rpm.rpm_sort_user2, sort_mode);
2523             break;
2524 
2525         case RX_FILTER_USER_IDX3:
2526             REG_RD(pdev, rpm.rpm_sort_user3, &val);
2527 
2528             REG_WR(pdev, rpm.rpm_sort_user3, 0x00000000);
2529             REG_WR(pdev, rpm.rpm_sort_user3, sort_mode);
2530 
2531             val &= 0xffff;
2532             val &= ~(1 << user_idx);
2533 
2534             sort_mode |= val | RPM_SORT_USER0_ENA;
2535             REG_WR(pdev, rpm.rpm_sort_user3, sort_mode);
2536             break;
2537 
2538         default:
2539             DbgBreakMsg("invalid user idx.\n");
2540 
2541             break;
2542     }
2543 
2544     /* Set rx_flood for L2. */
2545     REG_RD_IND(pdev, 0xe0024, &val);
2546     val &= ~(1 << user_idx);
2547 
2548     if(rx_mask & (LM_RX_MASK_ACCEPT_MULTICAST |
2549                   LM_RX_MASK_ACCEPT_ALL_MULTICAST |
2550                   LM_RX_MASK_ACCEPT_BROADCAST |
2551                   LM_RX_MASK_PROMISCUOUS_MODE))
2552     {
2553         val |= (1 << user_idx);
2554     }
2555 
2556     REG_WR_IND(pdev, 0xe0024, val);
2557 
2558     return LM_STATUS_SUCCESS;
2559 } /* lm_set_rx_mask */
2560 
2561 
2562 
2563 /*******************************************************************************
2564  * Description:
2565  *
2566  * Return:
2567  ******************************************************************************/
2568 lm_status_t
2569 lm_add_mc(
2570     lm_device_t *pdev,
2571     u8_t *mc_addr)
2572 {
2573     lm_mc_entry_t *mc_entry;
2574     u32_t cnt;
2575 
2576     DbgMessage(pdev, VERBOSE, "### lm_add_mc\n");
2577 
2578     for(cnt = 0; cnt < pdev->mc_table.entry_cnt; cnt++)
2579     {
2580         mc_entry = &pdev->mc_table.addr_arr[cnt];
2581 
2582         if(IS_ETH_ADDRESS_EQUAL(mc_entry->mc_addr, mc_addr))
2583         {
2584             mc_entry->ref_cnt++;
2585 
2586             return LM_STATUS_SUCCESS;
2587         }
2588     }
2589 
2590     if(pdev->mc_table.entry_cnt >= LM_MAX_MC_TABLE_SIZE)
2591     {
2592         DbgBreakMsg("No entry in MC table\n");
2593 
2594         return LM_STATUS_FAILURE;
2595     }
2596 
2597     mc_entry = &pdev->mc_table.addr_arr[pdev->mc_table.entry_cnt];
2598     pdev->mc_table.entry_cnt++;
2599 
2600     mc_entry->ref_cnt = 1;
2601 
2602     COPY_ETH_ADDRESS(mc_addr, mc_entry->mc_addr);
2603 
2604     (void) lm_set_rx_mask(
2605         pdev,
2606         RX_FILTER_USER_IDX0,
2607         pdev->rx_info.mask[RX_FILTER_USER_IDX0] | LM_RX_MASK_ACCEPT_MULTICAST);
2608 
2609     return LM_STATUS_SUCCESS;
2610 } /* lm_add_mc */
2611 
2612 
2613 
2614 /*******************************************************************************
2615  * Description:
2616  *
2617  * Return:
2618  ******************************************************************************/
2619 lm_status_t
2620 lm_del_mc(
2621     lm_device_t *pdev,
2622     u8_t *mc_addr)
2623 {
2624     lm_mc_entry_t *mc_entry;
2625     u32_t cnt;
2626 
2627     for(cnt = 0; cnt < pdev->mc_table.entry_cnt; cnt++)
2628     {
2629         mc_entry = &pdev->mc_table.addr_arr[cnt];
2630 
2631         if(IS_ETH_ADDRESS_EQUAL(mc_entry->mc_addr, mc_addr))
2632         {
2633             mc_entry->ref_cnt--;
2634 
2635             /* No more instance left, remove the address from the table.
2636              * Move the last entry in the table to the deleted slot. */
2637             if(mc_entry->ref_cnt == 0)
2638             {
2639                 if(pdev->mc_table.entry_cnt > 1)
2640                 {
2641                     *mc_entry = pdev->mc_table.addr_arr[pdev->mc_table.entry_cnt-1];
2642                 }
2643 
2644                 pdev->mc_table.entry_cnt--;
2645 
2646                 /* Update the receive mask if the table is empty. */
2647                 if(pdev->mc_table.entry_cnt == 0)
2648                 {
2649                     pdev->rx_info.mask[RX_FILTER_USER_IDX0] &=
2650                             ~LM_RX_MASK_ACCEPT_MULTICAST;
2651                 }
2652 
2653                 (void) lm_set_rx_mask(
2654                         pdev,
2655                         RX_FILTER_USER_IDX0,
2656                         pdev->rx_info.mask[RX_FILTER_USER_IDX0]);
2657             }
2658 
2659             return LM_STATUS_SUCCESS;
2660         }
2661     }
2662 
2663     DbgBreakMsg("Mc address not in the table\n");
2664 
2665     return LM_STATUS_FAILURE;
2666 } /* lm_del_mc */
2667 
2668 
2669 
2670 /*******************************************************************************
2671  * Description:
2672  *
2673  * Return:
2674  ******************************************************************************/
2675 void
2676 lm_clear_mc(lm_device_t *pdev)
2677 {
2678     DbgMessage(pdev, VERBOSE, "### lm_clear_mc\n");
2679 
2680     pdev->mc_table.entry_cnt = 0;
2681 
2682     (void) lm_set_rx_mask(
2683         pdev,
2684         RX_FILTER_USER_IDX0,
2685         pdev->rx_info.mask[RX_FILTER_USER_IDX0] & ~LM_RX_MASK_ACCEPT_MULTICAST);
2686 } /* lm_clear_mc */
2687 
2688 
2689 
2690 /*******************************************************************************
2691  * Description:
2692  *
2693  * Return:
2694  ******************************************************************************/
2695 lm_status_t
2696 lm_get_stats(
2697     lm_device_t *pdev,
2698     lm_stats_t stats_type,
2699     u64_t *stats_cnt)
2700 {
2701     volatile statistics_block_t *sb;
2702     lm_status_t lm_status;
2703     lm_u64_t *stats;
2704     u32_t reg_val;
2705     u32_t val;
2706 
2707     //
2708     // The fix of CQ#29454 caused CQ#30307 -
2709     // Bacs: Bogus counters on 5708 under statistics tab
2710     // So far, Windows never see CQ#29454 problem.
2711     // Remove the fix right now
2712     //
2713 
2714     /* CQ#29454 - statistics corruption. */
2715     //REG_RD(pdev, hc.hc_stats_ticks, &val);
2716     //REG_WR(pdev, hc.hc_stats_ticks, 0);
2717 
2718     REG_WR(pdev, hc.hc_command, HC_COMMAND_STATS_NOW);
2719     REG_RD(pdev, hc.hc_command, &reg_val);
2720     mm_wait(pdev, 5);
2721 
2722     lm_status = LM_STATUS_SUCCESS;
2723     sb = pdev->vars.stats_virt;
2724     stats = (lm_u64_t *) stats_cnt;
2725 
2726     switch(stats_type)
2727     {
2728         case LM_STATS_FRAMES_XMITTED_OK:
2729             stats->as_u32.low = sb->stat_IfHCOutUcastPkts_lo;
2730             stats->as_u32.high = sb->stat_IfHCOutUcastPkts_hi;
2731 
2732             LM_INC64(stats, sb->stat_IfHCOutMulticastPkts_lo);
2733             stats->as_u32.high += sb->stat_IfHCOutMulticastPkts_hi;
2734 
2735             LM_INC64(stats, sb->stat_IfHCOutBroadcastPkts_lo);
2736             stats->as_u32.high += sb->stat_IfHCOutBroadcastPkts_hi;
2737             break;
2738 
2739         case LM_STATS_FRAMES_RECEIVED_OK:
2740             stats->as_u32.low = sb->stat_IfHCInUcastPkts_lo;
2741             stats->as_u32.high = sb->stat_IfHCInUcastPkts_hi;
2742 
2743             LM_INC64(stats, sb->stat_IfHCInMulticastPkts_lo);
2744             stats->as_u32.high += sb->stat_IfHCInMulticastPkts_hi;
2745 
2746             LM_INC64(stats, sb->stat_IfHCInBroadcastPkts_lo);
2747             stats->as_u32.high += sb->stat_IfHCInBroadcastPkts_hi;
2748             REG_RD_IND(
2749                 pdev,
2750                 OFFSETOF(reg_space_t,
2751                          com.com_scratch[0])+
2752                          COM_HSI_OFFSETOFF(com_l2_iscsi_no_buffer),
2753                          &val);
2754             if((stats->as_u32.high == 0 && stats->as_u32.low) &&
2755                (stats->as_u32.low < val))
2756             {
2757                 /* due to asynchrous nature of reading the counters
2758                  * from status block and reading the counters from
2759                  * chip scratchpad mem, it is possible that the values
2760                  * are out of syn */
2761                 stats->as_u32.low = 0;
2762             }
2763             else
2764             {
2765                 LM_DEC64(stats, val);
2766             }
2767 
2768             REG_RD_IND(
2769                 pdev,
2770                 OFFSETOF(reg_space_t,
2771                          com.com_scratch[0])+
2772                          COM_HSI_OFFSETOFF(com_l2_no_buffer),
2773                          &val);
2774             if((stats->as_u32.high == 0 && stats->as_u32.low) &&
2775                (stats->as_u32.low < val))
2776             {
2777                 /* due to asynchrous nature of reading the counters
2778                  * from status block and reading the counters from
2779                  * chip scratchpad mem, it is possible that the values
2780                  * are out of syn */
2781                 stats->as_u32.low = 0;
2782             }
2783             else
2784             {
2785                 LM_DEC64(stats, val);
2786             }
2787             break;
2788 
2789         case LM_STATS_ERRORED_RECEIVE_CNT:
2790             stats->as_u32.low = pdev->rx_info.stats.err;
2791             stats->as_u32.high = 0;
2792             break;
2793 
2794         case LM_STATS_RCV_CRC_ERROR:
2795             stats->as_u32.low = sb->stat_Dot3StatsFCSErrors;
2796             stats->as_u32.high = 0;
2797             break;
2798 
2799         case LM_STATS_ALIGNMENT_ERROR:
2800             stats->as_u32.low = sb->stat_Dot3StatsAlignmentErrors;
2801             stats->as_u32.high = 0;
2802             break;
2803 
2804         case LM_STATS_SINGLE_COLLISION_FRAMES:
2805             stats->as_u32.low = sb->stat_Dot3StatsSingleCollisionFrames;
2806             stats->as_u32.high = 0;
2807             break;
2808 
2809         case LM_STATS_MULTIPLE_COLLISION_FRAMES:
2810             stats->as_u32.low = sb->stat_Dot3StatsMultipleCollisionFrames;
2811             stats->as_u32.high = 0;
2812             break;
2813 
2814         case LM_STATS_FRAMES_DEFERRED:
2815             stats->as_u32.low = sb->stat_Dot3StatsDeferredTransmissions;
2816             stats->as_u32.high = 0;
2817             break;
2818 
2819         case LM_STATS_MAX_COLLISIONS:
2820             stats->as_u32.low = sb->stat_Dot3StatsExcessiveCollisions;
2821             break;
2822 
2823         case LM_STATS_UNICAST_FRAMES_XMIT:
2824             stats->as_u32.low = sb->stat_IfHCOutUcastPkts_lo;
2825             stats->as_u32.high = sb->stat_IfHCOutUcastPkts_hi;
2826             break;
2827 
2828         case LM_STATS_MULTICAST_FRAMES_XMIT:
2829             stats->as_u32.low = sb->stat_IfHCOutMulticastPkts_lo;
2830             stats->as_u32.high = sb->stat_IfHCOutMulticastPkts_hi;
2831             break;
2832 
2833         case LM_STATS_BROADCAST_FRAMES_XMIT:
2834             stats->as_u32.low = sb->stat_IfHCOutBroadcastPkts_lo;
2835             stats->as_u32.high = sb->stat_IfHCOutBroadcastPkts_hi;
2836             break;
2837 
2838         case LM_STATS_UNICAST_FRAMES_RCV:
2839             stats->as_u32.low = sb->stat_IfHCInUcastPkts_lo;
2840             stats->as_u32.high = sb->stat_IfHCInUcastPkts_hi;
2841             REG_RD_IND(
2842                 pdev,
2843                 OFFSETOF(reg_space_t,
2844                          com.com_scratch[0])+
2845                          COM_HSI_OFFSETOFF(com_unicast_no_buffer),
2846                          &val);
2847             if((stats->as_u32.high == 0 && stats->as_u32.low) &&
2848                (stats->as_u32.low < val))
2849             {
2850                 /* due to asynchrous nature of reading the counters
2851                  * from status block and reading the counters from
2852                  * chip scratchpad mem, it is possible that the values
2853                  * are out of syn */
2854                 stats->as_u32.low = 0;
2855             }
2856             else
2857             {
2858                 LM_DEC64(stats, val);
2859             }
2860             break;
2861 
2862         case LM_STATS_MULTICAST_FRAMES_RCV:
2863             stats->as_u32.low = sb->stat_IfHCInMulticastPkts_lo;
2864             stats->as_u32.high = sb->stat_IfHCInMulticastPkts_hi;
2865             REG_RD_IND(
2866                 pdev,
2867                 OFFSETOF(reg_space_t,
2868                          com.com_scratch[0])+
2869                          COM_HSI_OFFSETOFF(com_mcast_no_buffer),
2870                          &val);
2871 
2872             if((stats->as_u32.high == 0 && stats->as_u32.low) &&
2873                (stats->as_u32.low < val))
2874             {
2875                 /* due to asynchrous nature of reading the counters
2876                  * from status block and reading the counters from
2877                  * chip scratchpad mem, it is possible that the values
2878                  * are out of syn */
2879                 stats->as_u32.low = 0;
2880             }
2881             else
2882             {
2883                 LM_DEC64(stats, val);
2884             }
2885             break;
2886 
2887         case LM_STATS_BROADCAST_FRAMES_RCV:
2888             stats->as_u32.low = sb->stat_IfHCInBroadcastPkts_lo;
2889             stats->as_u32.high = sb->stat_IfHCInBroadcastPkts_hi;
2890             REG_RD_IND(
2891                 pdev,
2892                 OFFSETOF(reg_space_t,
2893                          com.com_scratch[0])+
2894                          COM_HSI_OFFSETOFF(com_bcast_no_buffer),
2895                          &val);
2896             if((stats->as_u32.high == 0 && stats->as_u32.low) &&
2897                (stats->as_u32.low < val))
2898             {
2899                 /* due to asynchrous nature of reading the counters
2900                  * from status block and reading the counters from
2901                  * chip scratchpad mem, it is possible that the values
2902                  * are out of syn */
2903                 stats->as_u32.low = 0;
2904             }
2905             else
2906             {
2907                 LM_DEC64(stats, val);
2908             }
2909             break;
2910 
2911         case LM_STATS_ERRORED_TRANSMIT_CNT:
2912         case LM_STATS_RCV_OVERRUN:
2913         case LM_STATS_XMIT_UNDERRUN:
2914             /* These counters are always zero. */
2915             stats->as_u32.low = 0;
2916             stats->as_u32.high = 0;
2917             break;
2918 
2919         case LM_STATS_RCV_NO_BUFFER_DROP:
2920             /* com_no_buffer */
2921             REG_RD_IND(
2922                 pdev,
2923                 OFFSETOF(reg_space_t, com.com_scratch[0])+COM_HSI_OFFSETOFF(com_unicast_no_buffer),
2924                 &val);
2925             stats->as_u32.low = val;
2926             REG_RD_IND(
2927                 pdev,
2928                 OFFSETOF(reg_space_t, com.com_scratch[0])+COM_HSI_OFFSETOFF(com_mcast_no_buffer),
2929                 &val);
2930             stats->as_u32.low += val;
2931             REG_RD_IND(
2932                 pdev,
2933                 OFFSETOF(reg_space_t, com.com_scratch[0])+COM_HSI_OFFSETOFF(com_bcast_no_buffer),
2934                 &val);
2935             stats->as_u32.low += val;
2936 
2937             stats->as_u32.high = 0;
2938             break;
2939 
2940         case LM_STATS_BYTES_RCV:
2941             stats->as_u32.low = sb->stat_IfHCInOctets_lo;
2942             stats->as_u32.high = sb->stat_IfHCInOctets_hi;
2943             break;
2944 
2945         case LM_STATS_BYTES_XMIT:
2946             stats->as_u32.low = sb->stat_IfHCOutOctets_lo;
2947             stats->as_u32.high = sb->stat_IfHCOutOctets_hi;
2948             break;
2949 
2950         case LM_STATS_IF_IN_DISCARDS:
2951             /* com_no_buffer */
2952             REG_RD_IND(
2953                 pdev,
2954                 OFFSETOF(reg_space_t, com.com_scratch[0])+COM_HSI_OFFSETOFF(com_unicast_no_buffer),
2955                 &val);
2956             stats->as_u32.low = val;
2957             REG_RD_IND(
2958                 pdev,
2959                 OFFSETOF(reg_space_t, com.com_scratch[0])+COM_HSI_OFFSETOFF(com_mcast_no_buffer),
2960                 &val);
2961             stats->as_u32.low += val;
2962             REG_RD_IND(
2963                 pdev,
2964                 OFFSETOF(reg_space_t, com.com_scratch[0])+COM_HSI_OFFSETOFF(com_bcast_no_buffer),
2965                 &val);
2966             stats->as_u32.low += val;
2967             stats->as_u32.low += sb->stat_Dot3StatsFCSErrors;
2968 
2969             stats->as_u32.high = 0;
2970             break;
2971 
2972         case LM_STATS_XMIT_DISCARDS:
2973         case LM_STATS_IF_IN_ERRORS:
2974         case LM_STATS_IF_OUT_ERRORS:
2975             stats->as_u32.low = 0;
2976             stats->as_u32.high = 0;
2977             break;
2978 
2979         case LM_STATS_DIRECTED_BYTES_RCV:
2980             /* rxp_unicast_bytes_rcvd */
2981             REG_RD_IND(
2982                 pdev,
2983                 OFFSETOF(reg_space_t, rxp.rxp_scratch[0])+RXP_HSI_OFFSETOFF(rxp_unicast_bytes_rcvd)+4,
2984                 &stats->as_u32.low);
2985             REG_RD_IND(
2986                 pdev,
2987                 OFFSETOF(reg_space_t, rxp.rxp_scratch[0])+RXP_HSI_OFFSETOFF(rxp_unicast_bytes_rcvd),
2988                 &stats->as_u32.high);
2989             break;
2990 
2991         case LM_STATS_MULTICAST_BYTES_RCV:
2992             /* rxp_multicast_bytes_rcvd */
2993             REG_RD_IND(
2994                 pdev,
2995                 OFFSETOF(reg_space_t, rxp.rxp_scratch[0])+RXP_HSI_OFFSETOFF(rxp_multicast_bytes_rcvd)+4,
2996                 &stats->as_u32.low);
2997             REG_RD_IND(
2998                 pdev,
2999                 OFFSETOF(reg_space_t, rxp.rxp_scratch[0])+RXP_HSI_OFFSETOFF(rxp_multicast_bytes_rcvd),
3000                 &stats->as_u32.high);
3001             break;
3002 
3003         case LM_STATS_BROADCAST_BYTES_RCV:
3004             /* rxp_broadcast_bytes_rcvd */
3005             REG_RD_IND(
3006                 pdev,
3007                 OFFSETOF(reg_space_t, rxp.rxp_scratch[0])+RXP_HSI_OFFSETOFF(rxp_broadcast_bytes_rcvd)+4,
3008                 &stats->as_u32.low);
3009             REG_RD_IND(
3010                 pdev,
3011                 OFFSETOF(reg_space_t, rxp.rxp_scratch[0])+RXP_HSI_OFFSETOFF(rxp_broadcast_bytes_rcvd),
3012                 &stats->as_u32.high);
3013             break;
3014 
3015         case LM_STATS_DIRECTED_BYTES_XMIT:
3016             /* unicast_bytes_xmit_lo */
3017             REG_RD_IND(
3018                 pdev,
3019                 OFFSETOF(reg_space_t, tpat.tpat_scratch[0])+TPAT_HSI_OFFSETOFF(unicast_bytes_xmit)+4,
3020                 &stats->as_u32.low);
3021             REG_RD_IND(
3022                 pdev,
3023                 OFFSETOF(reg_space_t, tpat.tpat_scratch[0])+TPAT_HSI_OFFSETOFF(unicast_bytes_xmit),
3024                 &stats->as_u32.high);
3025             break;
3026 
3027         case LM_STATS_MULTICAST_BYTES_XMIT:
3028             /* multicast_bytes_xmit */
3029             REG_RD_IND(
3030                 pdev,
3031                 OFFSETOF(reg_space_t, tpat.tpat_scratch[0])+TPAT_HSI_OFFSETOFF(multicast_bytes_xmit)+4,
3032                 &stats->as_u32.low);
3033             REG_RD_IND(
3034                 pdev,
3035                 OFFSETOF(reg_space_t, tpat.tpat_scratch[0])+TPAT_HSI_OFFSETOFF(multicast_bytes_xmit),
3036                 &stats->as_u32.high);
3037             break;
3038 
3039         case LM_STATS_BROADCAST_BYTES_XMIT:
3040             /* broadcast_bytes_xmit */
3041             REG_RD_IND(
3042                 pdev,
3043                 OFFSETOF(reg_space_t, tpat.tpat_scratch[0])+TPAT_HSI_OFFSETOFF(broadcast_bytes_xmit)+4,
3044                 &stats->as_u32.low);
3045             REG_RD_IND(
3046                 pdev,
3047                 OFFSETOF(reg_space_t, tpat.tpat_scratch[0])+TPAT_HSI_OFFSETOFF(broadcast_bytes_xmit),
3048                 &stats->as_u32.high);
3049             break;
3050 
3051         default:
3052             stats->as_u32.low = 0;
3053             stats->as_u32.high = 0;
3054 
3055             lm_status = LM_STATUS_INVALID_PARAMETER;
3056             break;
3057     }
3058 
3059     //REG_WR(pdev, hc.hc_stats_ticks, val);
3060 
3061     return lm_status;
3062 } /* lm_get_stats */
3063 
3064 
3065 
3066 /*******************************************************************************
3067  * Description:
3068  *
3069  * Return:
3070  ******************************************************************************/
3071 STATIC lm_nwuf_t *
3072 find_nwuf(
3073     lm_nwuf_list_t *nwuf_list,
3074     u32_t mask_size,
3075     u8_t *byte_mask,
3076     u8_t *pattern,
3077     u32_t max_nwuf_cnt)
3078 {
3079     lm_nwuf_t *nwuf;
3080     u8_t found;
3081     u32_t idx;
3082     u32_t j;
3083     u32_t k;
3084 
3085     for(idx = 0; idx < max_nwuf_cnt; idx++)
3086     {
3087         nwuf = &nwuf_list->nwuf_arr[idx];
3088 
3089         if((nwuf->size&0xffff) != mask_size)
3090         {
3091             continue;
3092         }
3093 
3094         found = TRUE;
3095         for(j = 0; j < mask_size && found == TRUE; j++)
3096         {
3097             if(nwuf->mask[j] != byte_mask[j])
3098             {
3099                 found = FALSE;
3100                 break;
3101             }
3102 
3103             for(k = 0; k < 8; k++)
3104             {
3105                 if((byte_mask[j] & (1 << k)) &&
3106                     (nwuf->pattern[j*8 + k] != pattern[j*8 + k]))
3107                 {
3108                     found = FALSE;
3109                     break;
3110                 }
3111             }
3112         }
3113 
3114         if(found)
3115         {
3116             return nwuf;
3117         }
3118     }
3119 
3120     return NULL;
3121 } /* find_nwuf */
3122 
3123 
3124 
3125 /*******************************************************************************
3126  * Description:
3127  *
3128  * Return:
3129  ******************************************************************************/
3130 lm_status_t
3131 lm_add_nwuf(
3132     lm_device_t *pdev,
3133     u32_t pattern_size,
3134     u32_t mask_size,
3135     u8_t *byte_mask,
3136     u8_t *pattern)
3137 {
3138     lm_nwuf_t *nwuf;
3139     u32_t idx;
3140 /*
3141     u32_t i;
3142 */
3143     u32_t j;
3144     u32_t k;
3145     u32_t l;
3146     u32_t combind_size;
3147     u32_t max_nwuf_cnt;
3148 
3149     if(CHIP_NUM(pdev) == CHIP_NUM_5709)
3150     {
3151         max_nwuf_cnt = LM_MAX_NWUF_CNT_5709;
3152     }
3153     else
3154     {
3155         max_nwuf_cnt = LM_MAX_NWUF_CNT;
3156     }
3157 
3158     combind_size = (pattern_size<<16) & 0xffff0000;
3159     combind_size |= mask_size;
3160     pattern_size &= 0xffff;
3161     mask_size &= 0xffff;
3162 
3163 
3164         //DbgBreakIf(mask_size == 0xc &&pattern_size == 0x4a);
3165 
3166 
3167     if(mask_size == 0 || mask_size > LM_NWUF_PATTERN_MASK_SIZE)
3168     {
3169         DbgBreakMsg("Invalid byte mask size\n");
3170 
3171         return LM_STATUS_FAILURE;
3172     }
3173 
3174     /* If this is a duplicate entry, we are done. */
3175     nwuf = find_nwuf(
3176             &pdev->nwuf_list,
3177             mask_size,
3178             byte_mask, pattern,
3179             max_nwuf_cnt);
3180 
3181     if(nwuf)
3182     {
3183         DbgMessage(pdev, INFORM, "Duplicated nwuf entry.\n");
3184 
3185         return LM_STATUS_EXISTING_OBJECT;
3186     }
3187 
3188     /* Find an empty slot. */
3189     nwuf = NULL;
3190     for(idx = 0; idx < max_nwuf_cnt; idx++)
3191     {
3192         if(pdev->nwuf_list.nwuf_arr[idx].size == 0)
3193         {
3194             nwuf = &pdev->nwuf_list.nwuf_arr[idx];
3195             break;
3196         }
3197     }
3198 
3199     /*
3200      * LHDBG_PRINT(("%p Adding NWUF[%d], mask size: %d, pattern size: %d\n",
3201                 pdev,idx,mask_size,pattern_size));
3202     LHDBG_PRINT(("mask array:\n"));
3203 
3204     for (i=0;i<mask_size;i++)
3205     {
3206         if (0 == i%16) LH_PRINTK(("\n"));
3207         LH_PRINTK(("%02x ", byte_mask[i]));
3208     }
3209     LH_PRINTK(("\npattern:\n"));
3210 
3211     for (i=0;i<mask_size;i++)
3212     {
3213         for (j=0;j<8;j++)
3214         {
3215             if (0 == (i*8+j)%16)
3216             {
3217                 LH_PRINTK(("\n"));
3218             }
3219             if (byte_mask[i] & 1<<j)
3220             {
3221                 LH_PRINTK(("[%02x] ",pattern[i*8+j]));
3222             }
3223             else
3224             {
3225                 if (pattern_size && i*8+j>=pattern_size)
3226                 {
3227                     LH_PRINTK(("-%02x- ",pattern[i*8+j]));
3228                 }
3229                 else
3230                 {
3231                     LH_PRINTK((" %02x  ",pattern[i*8+j]));
3232                 }
3233 
3234             }
3235         }
3236     }
3237     LH_PRINTK(("\n"));
3238 */
3239 
3240     if(nwuf == NULL)
3241     {
3242         DbgMessage(pdev, WARN, "Cannot add Nwuf, exceeded maximum.\n");
3243 
3244         return LM_STATUS_RESOURCE;
3245     }
3246 
3247     pdev->nwuf_list.cnt++;
3248 
3249     /* Save nwuf data. */
3250     nwuf->size = mask_size;
3251 
3252     if (pattern_size)
3253     {
3254         nwuf->size = combind_size;
3255         goto _handle_win7_pattern;
3256     }
3257 
3258     for(j = 0; j < mask_size; j++)
3259     {
3260         nwuf->mask[j] = byte_mask[j];
3261 
3262         for(k = 0; k < 8; k++)
3263         {
3264             if(byte_mask[j] & (1 << k))
3265             {
3266                 nwuf->pattern[j*8 + k] = pattern[j*8 + k];
3267             }
3268             else
3269             {
3270                 nwuf->pattern[j*8 + k] = 0;
3271             }
3272         }
3273     }
3274 
3275     /* The byte patterns immediately following the byte that is enabled
3276      * for comparision need to be set to 0xff.  This will help facilitate
3277      * the programming of pattern onto the chip.  The end of the pattern is
3278      * indicated by the first 0xff byte that is not enabled for comparision. */
3279     if(byte_mask[mask_size-1])
3280     {
3281         k = 8;
3282         while(k)
3283         {
3284             k--;
3285             if(byte_mask[mask_size-1] & (1 << k))
3286             {
3287                 break;
3288             }
3289 
3290             nwuf->pattern[(mask_size-1)*8 + k] = 0xff;
3291         }
3292     }
3293 
3294     /* Set the rest of the pattern to 0xff. */
3295     for(j = mask_size; j < LM_NWUF_PATTERN_MASK_SIZE; j++)
3296     {
3297         nwuf->mask[j] = 0;
3298 
3299         for(k = 0; k < 8; k++)
3300         {
3301             nwuf->pattern[j*8 + k] = 0xff;
3302         }
3303     }
3304 /*
3305     LHDBG_PRINT(("Dumping pattern before return\n"));
3306     for (i=0;i<128;i++)
3307     {
3308         if (i!=0 && i%16==0)
3309         {
3310             LH_PRINTK(("\n"));
3311         }
3312 
3313         LH_PRINTK(("%02x ",nwuf->pattern[i]));
3314 
3315     }
3316     LH_PRINTK(("\nEnd of add_nwuf\n"));
3317 */
3318     return LM_STATUS_SUCCESS;
3319 _handle_win7_pattern:
3320     /*
3321      * this is new for win7
3322      */
3323     l=0;
3324 
3325     /*for lxdiag build*/
3326 #ifdef LINUX
3327 	{
3328 		u8_t idx;
3329 		for (idx=0; idx< LM_NWUF_PATTERN_MASK_SIZE; idx++)
3330 					nwuf->mask[idx] = 0;
3331 	}
3332 #else
3333     memset(nwuf->mask,0,LM_NWUF_PATTERN_MASK_SIZE);
3334 #endif
3335 
3336     for(j = 0; j < mask_size ; j++)
3337     {
3338         nwuf->mask[j] = byte_mask[j];
3339 
3340         for(k = 0; k < 8 ; k++)
3341         {
3342             if ( l<pattern_size )
3343             {
3344                 if(byte_mask[j] & (1 << k))
3345                 {
3346                     nwuf->pattern[j*8 + k] = pattern[j*8 + k];
3347                 }
3348                 else
3349                 {
3350                     nwuf->pattern[j*8 + k] = 0;
3351                 }
3352             }
3353             else
3354             {
3355                 nwuf->pattern[j*8 + k] = 0xff;
3356             }
3357             l++;
3358         }
3359     }
3360 /*
3361     LHDBG_PRINT(("Dumping pattern before return\n"));
3362     for (i=0;i<128;i++)
3363     {
3364         if (i!=0 && i%16==0)
3365         {
3366             LH_PRINTK(("\n"));
3367         }
3368 
3369         LH_PRINTK(("%02x ",nwuf->pattern[i]));
3370 
3371     }
3372     LH_PRINTK(("\nEnd of add_nwuf\n"));
3373 */
3374     return LM_STATUS_SUCCESS;
3375 } /* lm_add_nwuf */
3376 
3377 
3378 /*******************************************************************************
3379  * Description:
3380  *
3381  * Return:
3382  ******************************************************************************/
3383 lm_status_t
3384 lm_del_nwuf(
3385     lm_device_t *pdev,
3386     u32_t mask_size,
3387     u8_t *byte_mask,
3388     u8_t *pattern)
3389 {
3390     lm_nwuf_t *nwuf;
3391     u32_t k;
3392     u32_t max_nwuf_cnt;
3393 
3394     if(CHIP_NUM(pdev) == CHIP_NUM_5709)
3395     {
3396         max_nwuf_cnt = LM_MAX_NWUF_CNT_5709;
3397     }
3398     else
3399     {
3400         max_nwuf_cnt = LM_MAX_NWUF_CNT;
3401     }
3402 
3403     mask_size &= 0xffff;
3404     if(mask_size == 0 || mask_size > LM_NWUF_PATTERN_MASK_SIZE)
3405     {
3406         DbgBreakMsg("Invalid byte mask size\n");
3407 
3408         return LM_STATUS_FAILURE;
3409     }
3410 
3411     /* Look for a matching pattern. */
3412     nwuf = find_nwuf(
3413             &pdev->nwuf_list,
3414             mask_size,
3415             byte_mask,
3416             pattern,
3417             max_nwuf_cnt);
3418 
3419     if(nwuf == NULL)
3420     {
3421         return LM_STATUS_OBJECT_NOT_FOUND;
3422     }
3423 
3424     nwuf->size = 0;
3425 
3426     for(k = 0; k < LM_NWUF_PATTERN_MASK_SIZE; k++)
3427     {
3428         nwuf->mask[k] = 0;
3429     }
3430 
3431     for(k = 0; k < LM_NWUF_PATTERN_SIZE; k++)
3432     {
3433         nwuf->pattern[k] = 0xff;
3434     }
3435 
3436     pdev->nwuf_list.cnt--;
3437 
3438     return LM_STATUS_SUCCESS;
3439 } /* lm_del_nwuf */
3440 
3441 
3442 
3443 /*******************************************************************************
3444  * Description:
3445  *
3446  * Return:
3447  ******************************************************************************/
3448 void
3449 lm_clear_nwuf(
3450     lm_device_t *pdev)
3451 {
3452     u32_t j;
3453     u32_t k;
3454     u32_t max_nwuf_cnt;
3455 
3456     if(CHIP_NUM(pdev) == CHIP_NUM_5709)
3457     {
3458         max_nwuf_cnt = LM_MAX_NWUF_CNT_5709;
3459     }
3460     else
3461     {
3462         max_nwuf_cnt = LM_MAX_NWUF_CNT;
3463     }
3464 
3465     for(j = 0; j < max_nwuf_cnt; j++)
3466     {
3467         pdev->nwuf_list.nwuf_arr[j].size = 0;
3468 
3469         for(k = 0; k < LM_NWUF_PATTERN_MASK_SIZE; k++)
3470         {
3471             pdev->nwuf_list.nwuf_arr[j].mask[k] = 0;
3472         }
3473 
3474         for(k = 0; k < LM_NWUF_PATTERN_SIZE; k++)
3475         {
3476             pdev->nwuf_list.nwuf_arr[j].pattern[k] = 0xff;
3477         }
3478     }
3479 
3480     pdev->nwuf_list.cnt = 0;
3481 } /* lm_clear_nwuf */
3482 
3483 
3484 
3485 /*******************************************************************************
3486  * Description:
3487  *
3488  * Return:
3489  ******************************************************************************/
3490 STATIC u32_t
3491 init_nwuf_5709(
3492     lm_device_t *pdev,
3493     lm_nwuf_list_t *nwuf_list)
3494 {
3495     lm_nwuf_t *nwuf;
3496     u16_t prev_val;
3497     u32_t nwuf_len;
3498     u32_t nwuf_cnt;
3499     u32_t offset;
3500     u8_t mask;
3501     u32_t val;
3502     u32_t idx;
3503     u8_t bit;
3504     u16_t pattern_size;
3505     u32_t nwuf_size[LM_MAX_NWUF_CNT_5709];
3506 
3507     DbgBreakIf(CHIP_NUM(pdev) != CHIP_NUM_5709);
3508     DbgBreakIf(LM_NWUF_PATTERN_SIZE > 128);
3509     DbgBreakIf(LM_MAX_NWUF_CNT_5709 > 8);
3510 
3511     REG_WR(pdev, rpm.rpm_acpi_byte_enable_ctrl, RPM_ACPI_BYTE_ENABLE_CTRL_INIT);
3512 
3513     for(idx = 0; idx < LM_MAX_NWUF_CNT_5709; idx++)
3514     {
3515         nwuf = &nwuf_list->nwuf_arr[idx];
3516         nwuf_size[idx] = nwuf->size;
3517     }
3518     for(idx = 0; idx < 1000; idx++)
3519     {
3520         mm_wait(pdev, 5);
3521 
3522         REG_RD(pdev, rpm.rpm_acpi_byte_enable_ctrl, &val);
3523         if((val & RPM_ACPI_BYTE_ENABLE_CTRL_INIT) == 0)
3524         {
3525             break;
3526         }
3527     }
3528     DbgBreakIf(val & RPM_ACPI_BYTE_ENABLE_CTRL_INIT);
3529 
3530     val = 0;
3531     for(idx = 0; idx < 4; idx++)
3532     {
3533         nwuf = &nwuf_list->nwuf_arr[idx];
3534         pattern_size = nwuf->size >>16;
3535         nwuf->size &= 0xffff;
3536 
3537         DbgBreakIf(nwuf->size > LM_NWUF_PATTERN_MASK_SIZE);
3538 
3539         if(nwuf->size == 0)
3540         {
3541             continue;
3542         }
3543         if (pattern_size)
3544         {
3545             val |= (pattern_size) << ((3 - idx) * 8);
3546         }
3547         else
3548         {
3549             val |= (nwuf->size * 8) << ((3 - idx) * 8);
3550         }
3551     }
3552     REG_WR(pdev, rpm.rpm_acpi_pattern_len0, val);
3553 
3554     val = 0;
3555     for(idx = 4; idx < LM_MAX_NWUF_CNT_5709; idx++)
3556     {
3557         nwuf = &nwuf_list->nwuf_arr[idx];
3558         pattern_size = nwuf->size >>16;
3559         nwuf->size &= 0xffff;
3560 
3561         DbgBreakIf(nwuf->size > LM_NWUF_PATTERN_MASK_SIZE);
3562 
3563         if(nwuf->size == 0)
3564         {
3565             continue;
3566         }
3567 
3568         if (pattern_size)
3569         {
3570             val |= (pattern_size) << ((7 - idx) * 8);
3571         }
3572         else
3573         {
3574             val |= (nwuf->size * 8) << ((7 - idx) * 8);
3575         }
3576 
3577         // old code val |= (nwuf->size * 8) << ((7 - idx) * 8);
3578     }
3579     REG_WR(pdev, rpm.rpm_acpi_pattern_len1, val);
3580 
3581     for(offset = 0; offset < LM_NWUF_PATTERN_SIZE; offset++)
3582     {
3583         val = 0;
3584 
3585         for(idx = 0; idx < LM_MAX_NWUF_CNT_5709; idx++)
3586         {
3587             nwuf = &nwuf_list->nwuf_arr[idx];
3588             pattern_size = nwuf_size[idx]>>16;
3589 
3590             if(nwuf->size == 0 || offset > nwuf->size * 8)
3591             {
3592                 continue;
3593             }
3594 
3595             mask = nwuf->mask[offset/8];
3596             bit = offset % 8;
3597 
3598             if(mask & (1 << bit))
3599             {
3600                 val |= 1 << idx;
3601             }
3602         }
3603 
3604         REG_WR(pdev, rpm.rpm_acpi_data, val);
3605 
3606         /* Perform the Write to the byte enable memory, The actual pattern
3607          * byte enables start from byte address 2. the first two bytes of
3608          * a packet are always 0 and inserted by EMAC to align the IP header
3609          * to 4-byte boudary. */
3610         REG_WR(
3611             pdev,
3612             rpm.rpm_acpi_byte_enable_ctrl,
3613             RPM_ACPI_BYTE_ENABLE_CTRL_WR | offset);
3614         REG_RD(pdev, rpm.rpm_acpi_byte_enable_ctrl, &val);
3615         DbgBreakIf(val & RPM_ACPI_BYTE_ENABLE_CTRL_WR);
3616     }
3617 
3618     nwuf_cnt = 0;
3619 
3620     for(idx = 0; idx < LM_MAX_NWUF_CNT_5709; idx++)
3621     {
3622         REG_WR(
3623             pdev,
3624             rpm.rpm_acpi_pattern_ctrl,
3625             RPM_ACPI_PATTERN_CTRL_CRC_SM_CLR|idx);
3626         REG_RD(pdev, rpm.rpm_acpi_pattern_ctrl, &val);
3627         DbgBreakIf(val & RPM_ACPI_PATTERN_CTRL_CRC_SM_CLR);
3628 
3629         nwuf = &nwuf_list->nwuf_arr[idx];
3630         if(nwuf->size == 0)
3631         {
3632             continue;
3633         }
3634         pattern_size = nwuf_size[idx]>>16;
3635 
3636         /* The CRC calculation is done on 64-bit data. So the length of the
3637          * pattern over which CRC needs to be calculated needs to be padded
3638          * by 0 to 7 bytes to make it 8 byte aligned. */
3639 
3640         if (pattern_size)
3641         {
3642             nwuf_len = pattern_size;
3643         }
3644         else
3645         {
3646             nwuf_len = (nwuf->size * 8);
3647         }
3648         nwuf_len += 2;  /* 2-byte padding. */
3649         nwuf_len = (nwuf_len + 3) & ~3;
3650 
3651         prev_val = 0;
3652 
3653         for(offset = 0; offset < nwuf_len; offset += 4)
3654         {
3655             val = 0;
3656 
3657             for(bit = 0; bit < 4; bit++)
3658             {
3659                 if (pattern_size)
3660                 {
3661                     if(offset < pattern_size)
3662                     {
3663                         mask = nwuf->mask[offset/8];
3664                     }
3665                     else
3666                     {
3667                         mask = 0;
3668                     }
3669                 }
3670                 else
3671                 {
3672                     if(offset < nwuf->size * 8)
3673                     {
3674                         mask = nwuf->mask[offset/8];
3675                     }
3676                     else
3677                     {
3678                         mask = 0;
3679                     }
3680                 }
3681                 if(mask & (1 << (bit + (offset % 8))))
3682                 {
3683                     val |= nwuf->pattern[offset+bit] << ((3 - bit) * 8);
3684                 }
3685             }
3686 
3687             REG_WR(pdev, rpm.rpm_acpi_data, (prev_val << 16) | (val >> 16));
3688             prev_val = (u16_t) val;
3689 
3690             REG_WR(
3691                 pdev,
3692                 rpm.rpm_acpi_pattern_ctrl,
3693                 RPM_ACPI_PATTERN_CTRL_WR | idx);
3694             REG_RD(pdev, rpm.rpm_acpi_pattern_ctrl, &val);
3695             DbgBreakIf(val & RPM_ACPI_PATTERN_CTRL_WR);
3696         }
3697 
3698         nwuf_cnt++;
3699     }
3700     for(idx = 0; idx < LM_MAX_NWUF_CNT_5709; idx++)
3701     {
3702         nwuf = &nwuf_list->nwuf_arr[idx];
3703         nwuf->size = nwuf_size[idx];
3704     }
3705 
3706     return nwuf_cnt;
3707 } /* init_nwuf_5709 */
3708 
3709 
3710 
3711 /*******************************************************************************
3712  * Description:
3713  *
3714  * Return:
3715  ******************************************************************************/
3716 STATIC u32_t
3717 init_nwuf_5706(
3718     lm_device_t *pdev,
3719     lm_nwuf_list_t *nwuf_list)
3720 {
3721     typedef union _acpi_wol_pat_t
3722     {
3723         #if defined(LITTLE_ENDIAN)
3724         struct _acpi_wol_pat_as_u8_t
3725         {
3726             u8_t pat[7];
3727             u8_t ena;
3728         } as_u8;
3729 
3730         struct _acpi_wol_pat_as_u32_t
3731         {
3732             u32_t low;
3733             u32_t high;
3734         } as_u32;
3735         #elif defined(BIG_ENDIAN)
3736         struct _acpi_wol_pat_as_u8_t
3737         {
3738             u8_t ena;
3739             u8_t pat[7];
3740         } as_u8;
3741 
3742         struct _acpi_wol_pat_as_u32_t
3743         {
3744             u32_t high;
3745             u32_t low;
3746         } as_u32;
3747         #endif
3748     } acpi_wol_pat_t;
3749 
3750     u32_t filler_pattern_idx;
3751     acpi_wol_pat_t wol_pat;
3752     u32_t pattern_cnt;
3753     u8_t val;
3754     u32_t j;
3755     u32_t k;
3756     u8_t idx;
3757     u32_t nwuf_size[LM_MAX_NWUF_CNT];
3758     lm_nwuf_t *nwuf;
3759 
3760     /*
3761      * 06/08 doesn't seem to have pattern size like those of 09
3762      */
3763     for(idx = 0; idx < LM_MAX_NWUF_CNT; idx++)
3764     {
3765         nwuf = &nwuf_list->nwuf_arr[idx];
3766         nwuf_size[idx] = nwuf->size;
3767         nwuf->size &= 0xffff;
3768     }
3769 
3770     DbgBreakIf(LM_NWUF_PATTERN_SIZE > 128);
3771     DbgBreakIf(LM_MAX_NWUF_CNT > 7);
3772     DbgBreakIf(CHIP_NUM(pdev) != CHIP_NUM_5706 &&
3773                CHIP_NUM(pdev) != CHIP_NUM_5708);
3774 
3775     /* If a pattern is not present, we will fill the pattern buffer
3776      * with the pattern with this index.  The pattern buffer cannot
3777      * have an empty pattern otherwise we will get a false detection. */
3778     filler_pattern_idx = 0;
3779 
3780     /* Find out the number of patterns. */
3781     pattern_cnt = 0;
3782     for(k = 0; k < LM_MAX_NWUF_CNT; k++)
3783     {
3784         if(nwuf_list->nwuf_arr[k].size)
3785         {
3786             pattern_cnt++;
3787             filler_pattern_idx = k;
3788         }
3789     }
3790 
3791     /* Program the pattern. */
3792     for(j = 0; j < LM_NWUF_PATTERN_SIZE; j++)
3793     {
3794         wol_pat.as_u32.low = 0x0;
3795         wol_pat.as_u32.high = 0x0;
3796 
3797         /* Build the enable bits. */
3798         wol_pat.as_u8.ena = 0;
3799         for(k = 0; k < LM_MAX_NWUF_CNT; k++)
3800         {
3801             if(nwuf_list->nwuf_arr[k].size == 0)
3802             {
3803                 val = nwuf_list->nwuf_arr[filler_pattern_idx].mask[j/8];
3804             }
3805             else if((j/8) >= nwuf_list->nwuf_arr[k].size)
3806             {
3807                 val = 0;
3808             }
3809             else
3810             {
3811                 val = nwuf_list->nwuf_arr[k].mask[j/8];
3812             }
3813 
3814             /* Determine if a byte is enabled for comparision. */
3815             if(val & (1 << (j % 8)))
3816             {
3817                 wol_pat.as_u8.ena |= 1 << k;
3818             }
3819         }
3820 
3821         DbgMessage1(pdev, VERBOSE, "%02x: ", j);
3822 
3823         /* Enter the byte of each pattern that will be used for comparison. */
3824         for(k = 0; k < LM_MAX_NWUF_CNT; k++)
3825         {
3826             /* Check to see if we are at the end of the pattern.  0xff
3827              * will terminate the pattern.  If there is no pattern present
3828              * we cannot terminate with 0xff. */
3829             if(nwuf_list->nwuf_arr[k].size == 0)
3830             {
3831                 val = nwuf_list->nwuf_arr[filler_pattern_idx].pattern[j];
3832                 DbgMessage(pdev, VERBOSE, "xx ");
3833             }
3834             else if((j/8) >= nwuf_list->nwuf_arr[k].size)
3835             {
3836                 val = 0xff;
3837                 DbgMessage(pdev, VERBOSE, "ff ");
3838             }
3839             else
3840             {
3841                 val = nwuf_list->nwuf_arr[k].pattern[j];
3842                 DbgMessage1(pdev, VERBOSE, "%02x ", val);
3843             }
3844 
3845             /* Format of the ACPI_WOL pattern from low address to high on a
3846              * little endian system:
3847              *    pat0_6 pat0_5 pat0_4 pat0_3 pat0_2 pat0_1 pat0_0 ena0
3848              *
3849              * on a big endian system:
3850              *    ena0 pat0_0 pat0_1 pat0_2 pat0_3 pat0_4 pat0_5 pat0_6 */
3851             #if defined(LITTLE_ENDIAN)
3852             wol_pat.as_u8.pat[6-k] = val;
3853             #elif defined(BIG_ENDIAN)
3854             wol_pat.as_u8.pat[k] = val;
3855             #endif
3856         }
3857 
3858         DbgMessage2(pdev, VERBOSE, "   %08x %08x\n",
3859             wol_pat.as_u32.high, wol_pat.as_u32.low);
3860 
3861         /* Swap the even 64-bit word with the odd 64-bit word.  This is
3862          * they way it works.  Don't ask why.  So the values written
3863          * to the header buffer looks as follows:
3864          *    0x0000:  ena1   pat1_0 pat1_1 pat1_2
3865          *    0x0004:  pat1_3 pat1_4 pat1_5 pat1_6
3866          *    0x0008:  ena0   pat0_0 pat0_1 pat0_2
3867          *    0x000c:  pat0_3 pat0_4 pat0_5 pat0_6
3868          *    0x0010:  ena3   pat3_0 pat3_1 pat3_2
3869          *    0x0014:  pat3_3 pat3_4 pat3_5 pat3_6
3870          *    0x0018:  ena2   pat2_0 pat2_1 pat2_2
3871          *    0x001c:  pat2_3 pat2_4 pat2_5 pat2_6 */
3872         if(j % 2)
3873         {
3874             REG_WR_IND(
3875                 pdev,
3876                 OFFSETOF(reg_space_t, tas.tas_thbuf[(j-1) * 2]),
3877                 wol_pat.as_u32.high);
3878             REG_WR_IND(
3879                 pdev,
3880                 OFFSETOF(reg_space_t, tas.tas_thbuf[(j-1) * 2 + 1]),
3881                 wol_pat.as_u32.low);
3882         }
3883         else
3884         {
3885             REG_WR_IND(
3886                 pdev,
3887                 OFFSETOF(reg_space_t, tas.tas_thbuf[(j+1) * 2]),
3888                 wol_pat.as_u32.high);
3889             REG_WR_IND(
3890                 pdev,
3891                 OFFSETOF(reg_space_t, tas.tas_thbuf[(j+1) * 2 + 1]),
3892                 wol_pat.as_u32.low);
3893         }
3894     }
3895 
3896     for(idx = 0; idx < LM_MAX_NWUF_CNT; idx++)
3897     {
3898         nwuf = &nwuf_list->nwuf_arr[idx];
3899         nwuf->size = nwuf_size[idx];
3900     }
3901 
3902     return pattern_cnt;
3903 } /* init_nwuf_5706 */
3904 
3905 
3906 
3907 /*******************************************************************************
3908  * Description:
3909  *
3910  * Return:
3911  ******************************************************************************/
3912 STATIC u32_t
3913 init_nwuf(
3914     lm_device_t *pdev,
3915     lm_nwuf_list_t *nwuf_list)
3916 {
3917     u32_t nwuf_cnt;
3918 
3919     if(CHIP_NUM(pdev) == CHIP_NUM_5706 || CHIP_NUM(pdev) == CHIP_NUM_5708)
3920     {
3921         nwuf_cnt = init_nwuf_5706(pdev, nwuf_list);
3922     }
3923     else
3924     {
3925         nwuf_cnt = init_nwuf_5709(pdev, nwuf_list);
3926     }
3927 
3928     return nwuf_cnt;
3929 } /* init_nwuf */
3930 
3931 
3932 
3933 /*******************************************************************************
3934  * Description:
3935  *
3936  * Return:
3937  ******************************************************************************/
3938 STATIC void
3939 set_d0_power_state(
3940     lm_device_t *pdev,
3941     u8_t set_pci_pm)
3942 {
3943     u32_t val;
3944     u32_t idx;
3945 
3946     /* This step should be done by the OS or the caller.  Windows is
3947      * already doing this. */
3948     if(set_pci_pm)
3949     {
3950         /* Set the device to D0 state.  If a device is already in D3 state,
3951          * we will not be able to read the PCICFG_PM_CSR register using the
3952          * PCI memory command, we need to use config access here. */
3953         (void) mm_read_pci(
3954             pdev,
3955             OFFSETOF(reg_space_t, pci_config.pcicfg_pm_csr),
3956             &val);
3957 
3958         /* Set the device to D0 state.  This may be already done by the OS. */
3959         val &= ~PCICFG_PM_CSR_STATE;
3960         val |= PCICFG_PM_CSR_STATE_D0 | PCICFG_PM_CSR_PME_STATUS;
3961 
3962         (void) mm_write_pci(
3963             pdev,
3964             OFFSETOF(reg_space_t, pci_config.pcicfg_pm_csr),
3965             val);
3966     }
3967 
3968     /* With 5706_A1, the chip gets a reset coming out of D3.  Wait
3969      * for the boot to code finish running before we continue.  Without
3970      * this wait, we could run into lockup or the PHY may not work. */
3971     if(CHIP_ID(pdev) == CHIP_ID_5706_A1)
3972     {
3973         for(idx = 0; idx < 1000; idx++)
3974         {
3975             mm_wait(pdev, 15);
3976         }
3977     }
3978 
3979     /* Clear the ACPI_RCVD and MPKT_RCVD bits and disable magic packet. */
3980     REG_RD(pdev, emac.emac_mode, &val);
3981     val |= EMAC_MODE_MPKT_RCVD | EMAC_MODE_ACPI_RCVD;
3982     val &= ~EMAC_MODE_MPKT;
3983     REG_WR(pdev, emac.emac_mode, val);
3984 
3985     /* Disable interesting packet detection. */
3986     REG_RD(pdev, rpm.rpm_config, &val);
3987     val &= ~RPM_CONFIG_ACPI_ENA;
3988     REG_WR(pdev, rpm.rpm_config, val);
3989 } /* set_d0_power_state */
3990 
3991 
3992 
3993 /*******************************************************************************
3994  * Description:
3995  *
3996  * Return:
3997  ******************************************************************************/
3998 STATIC void
3999 set_d3_power_state(
4000     lm_device_t *pdev,
4001     lm_wake_up_mode_t wake_up_mode,
4002     u8_t set_pci_pm)
4003 {
4004     u32_t fw_timed_out;
4005     u32_t reset_reason;
4006     u32_t gpio_pin;
4007     u32_t val;
4008     u32_t cnt;
4009 
4010     /* Set up magic and interesting packet detection. */
4011     if(wake_up_mode & (LM_WAKE_UP_MODE_MAGIC_PACKET | LM_WAKE_UP_MODE_NWUF))
4012     {
4013         /* Enable magic packet detection. */
4014         REG_RD(pdev, emac.emac_mode, &val);
4015         if(wake_up_mode & LM_WAKE_UP_MODE_MAGIC_PACKET)
4016         {
4017             val |= EMAC_MODE_MPKT;
4018         }
4019         else
4020         {
4021             val &= ~EMAC_MODE_MPKT;
4022         }
4023 
4024         /* Enable port mode. */
4025         val &= ~EMAC_MODE_PORT;
4026         if(CHIP_REV(pdev) == CHIP_REV_FPGA || CHIP_REV(pdev) == CHIP_REV_IKOS)
4027         {
4028             /* IKOS or FPGA always run in GMII mode even if its actual
4029              * link speed is 10mb or 100mb. */
4030             val |= EMAC_MODE_PORT_GMII;
4031         }
4032         else
4033         {
4034             val |= EMAC_MODE_PORT_MII;
4035         }
4036         val |= EMAC_MODE_MPKT_RCVD | EMAC_MODE_ACPI_RCVD;
4037 
4038         REG_WR(pdev, emac.emac_mode, val);
4039 
4040         /* Set up the receive mask. */
4041         (void) lm_set_rx_mask(
4042             pdev,
4043             RX_FILTER_USER_IDX0,
4044             LM_RX_MASK_ACCEPT_UNICAST |
4045                 LM_RX_MASK_ACCEPT_ALL_MULTICAST |
4046                 LM_RX_MASK_ACCEPT_BROADCAST);
4047 
4048         /* The first four address slots are use for magic packet detection.
4049          * we need to initialize all four address slots. */
4050         for(cnt = 0; cnt < 4; cnt++)
4051         {
4052             (void) lm_set_mac_addr(pdev, cnt, pdev->params.mac_addr);
4053         }
4054 
4055         /* Need to enable EMAC and RPM for WOL. */
4056         REG_WR(
4057             pdev,
4058             misc.misc_enable_set_bits,
4059             MISC_ENABLE_SET_BITS_RX_PARSER_MAC_ENABLE |
4060                 MISC_ENABLE_SET_BITS_TX_HEADER_Q_ENABLE |
4061                 MISC_ENABLE_SET_BITS_EMAC_ENABLE);
4062 
4063         /* Enable interesting packet detection.  This must be done after
4064          * the necessary blocks are enabled, otherwise we may wake-up on
4065          * a bogus first packet.  Need to document this in prm. */
4066         REG_RD(pdev, rpm.rpm_config, &val);
4067         if(wake_up_mode & LM_WAKE_UP_MODE_NWUF)
4068         {
4069             REG_WR(pdev, rpm.rpm_config, val & ~RPM_CONFIG_ACPI_ENA);
4070 
4071             /* Also need to be documented in the prm - to prevent a false
4072              * detection, we need to disable ACP_EN if there is no pattern
4073              * programmed.  There is no way of preventing false detection
4074              * by intializing the pattern buffer a certain way. */
4075             if(init_nwuf(pdev, &pdev->nwuf_list))
4076             {
4077                 val |= RPM_CONFIG_ACPI_ENA;
4078             }
4079             else
4080             {
4081                 val &= ~RPM_CONFIG_ACPI_ENA;
4082             }
4083         }
4084         else
4085         {
4086             val &= ~RPM_CONFIG_ACPI_ENA;
4087         }
4088         REG_WR(pdev, rpm.rpm_config, val);
4089 
4090         /* xinan requires rbuf to be enabled.  enabling it for teton
4091          * does not hurt. */
4092         REG_WR(
4093             pdev,
4094             misc.misc_enable_set_bits,
4095             MISC_ENABLE_SET_BITS_RX_MBUF_ENABLE);
4096 
4097         reset_reason = LM_REASON_WOL_SUSPEND;
4098     }
4099     else
4100     {
4101         reset_reason = LM_REASON_NO_WOL_SUSPEND;
4102     }
4103 
4104     /* Allow the firmware to make any final changes to the chip before
4105      * we go into D3 mode.  The timeout period is longer because the
4106      * firwmare could take more time to download management firmware
4107      * which occurs during this stage of the reset. */
4108     fw_timed_out = fw_reset_sync(
4109         pdev,
4110         reset_reason,
4111         DRV_MSG_DATA_WAIT3,
4112         FW_ACK_TIME_OUT_MS*1000 * 3);
4113 
4114     /* If the firmware is not running, we have to switch to vaux power,
4115      * otherwise let the firmware do it. */
4116     if(fw_timed_out)
4117     {
4118         /* Power down the PHY. */
4119         if(pdev->params.enable_remote_phy == FALSE)
4120         {
4121             if(CHIP_REV(pdev) != CHIP_REV_FPGA &&
4122                 CHIP_REV(pdev) != CHIP_REV_IKOS)
4123             {
4124                 (void) lm_mwrite(
4125                     pdev,
4126                     pdev->params.phy_addr,
4127                     0x1c,
4128                     0xa821);
4129             }
4130         }
4131 
4132         /* Minimum core clock for a particular link.
4133          *    10Mb      core_clk = 6.25Mhz
4134          *    100Mb     core_clk = 12Mhz
4135          *    1Gb       core_clk = 100Mhz (use PLL)
4136          *
4137          * The driver is configured to autoneg to 10/100Mb for WOL mode.  So
4138          * the core clock needs to be configured to 12Mhz. */
4139         REG_RD(pdev, misc.misc_clock_control_bits, &val);
4140         val &= ~(MISC_CLOCK_CONTROL_BITS_CORE_CLK_DISABLE |
4141             MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT |
4142             MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_TE);
4143 
4144         /* Select the 12.5m alt clock. */
4145         REG_WR(
4146             pdev,
4147             misc.misc_clock_control_bits,
4148             MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_12_TE | val);
4149 
4150         /* Switch to the alt clock. */
4151         REG_WR(
4152             pdev,
4153             misc.misc_clock_control_bits,
4154             MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_12_TE |
4155                 MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT |
4156                 val);
4157 
4158         /* Disable core clock to non-wol blocks. */
4159         REG_WR(
4160             pdev,
4161             misc.misc_clock_control_bits,
4162             MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_12_TE |
4163                 MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT |
4164                 MISC_CLOCK_CONTROL_BITS_CORE_CLK_DISABLE |
4165                 val);
4166 
4167         gpio_pin = 1 << 2;  /* GPIO 2 */
4168 
4169         /* Switch to vaux power by bring GPIO2 to low. */
4170         REG_RD(pdev, misc.misc_spio, &val);
4171         val &= ~(gpio_pin << 24);           /* use this gpio as output. */
4172         val |= gpio_pin << 16;              /* clear the gpio. */
4173         REG_WR(pdev, misc.misc_spio, val);
4174 
4175         /* This step should be done by the OS or the caller.  Windows is
4176          * already doing this. */
4177         if(set_pci_pm)
4178         {
4179             /* Set the device to D3 state. */
4180             REG_RD_OFFSET(
4181                 pdev,
4182                 OFFSETOF(reg_space_t, pci_config.pcicfg_pm_csr),
4183                 &val);
4184 
4185             val &= ~PCICFG_PM_CSR_STATE;
4186             val |= PCICFG_PM_CSR_STATE_D3_HOT;
4187 
4188             REG_WR_OFFSET(
4189                 pdev,
4190                 OFFSETOF(reg_space_t, pci_config.pcicfg_pm_csr),
4191                 val);
4192         }
4193     }
4194 } /* set_d3_power_state */
4195 
4196 
4197 
4198 /*******************************************************************************
4199  * Description:
4200  *
4201  * Return:
4202  ******************************************************************************/
4203 void
4204 lm_set_power_state(
4205     lm_device_t *pdev,
4206     lm_power_state_t power_state,
4207     lm_wake_up_mode_t wake_up_mode,     /* Valid when power_state is D3. */
4208     u8_t set_pci_pm)
4209 {
4210     if(power_state == LM_POWER_STATE_D0)
4211     {
4212         set_d0_power_state(pdev, set_pci_pm);
4213     }
4214     else
4215     {
4216         set_d3_power_state(pdev, wake_up_mode, set_pci_pm);
4217     }
4218 } /* lm_set_power_state */
4219 
4220 
4221 
4222 #ifndef EXCLUDE_KQE_SUPPORT
4223 /*******************************************************************************
4224  * Description:
4225  *
4226  * Return:
4227  ******************************************************************************/
4228 u32_t
4229 lm_submit_kernel_wqes(
4230     lm_device_t *pdev,
4231     kwqe_t *wqes[],
4232     u32_t num_wqes)
4233 {
4234     kwqe_t *prod_qe;
4235     u16_t prod_idx;
4236     u32_t qe_cnt;
4237 
4238     if(num_wqes > pdev->kq_info.kwqe_left)
4239     {
4240         pdev->kq_info.no_kwq_bd_left++;
4241 
4242         return 0;
4243     }
4244 
4245     pdev->kq_info.kwqe_left -= num_wqes;
4246 
4247     prod_qe = pdev->kq_info.kwq_prod_qe;
4248     prod_idx = pdev->kq_info.kwq_prod_idx;
4249 
4250     qe_cnt = num_wqes;
4251     while(qe_cnt)
4252     {
4253         *prod_qe = *(*wqes);
4254 
4255         if(prod_qe == pdev->kq_info.kwq_last_qe)
4256         {
4257             prod_qe = pdev->kq_info.kwq_virt;
4258         }
4259         else
4260         {
4261             prod_qe++;
4262         }
4263 
4264         wqes++;
4265         prod_idx++;
4266         qe_cnt--;
4267     }
4268 
4269     pdev->kq_info.kwq_prod_qe = prod_qe;
4270     pdev->kq_info.kwq_prod_idx = prod_idx;
4271 
4272     MBQ_WR16(
4273         pdev,
4274         GET_CID(pdev->kq_info.kwq_cid_addr),
4275         OFFSETOF(krnlq_context_t, krnlq_host_qidx),
4276         prod_idx);
4277 
4278     return num_wqes;
4279 } /* lm_submit_kernel_wqes */
4280 #endif /* EXCLUDE_KQE_SUPPORT */
4281 
4282 
4283 
4284 /*******************************************************************************
4285  * Description:
4286  *
4287  * Return:
4288  ******************************************************************************/
4289 lm_interrupt_status_t
4290 lm_get_interrupt_status(
4291     lm_device_t *pdev)
4292 {
4293     lm_interrupt_status_t intr_status;
4294     u32_t deasserted_attns;
4295     u32_t asserted_attns;
4296     lm_rx_chain_t *rxq;
4297     lm_tx_chain_t *txq;
4298     u16_t hw_con_idx;
4299     u32_t val;
4300     u32_t idx;
4301 
4302     intr_status = LM_NO_EVENT_ACTIVE;
4303 
4304     /* Determine link change status. */
4305     if(pdev->params.link_chng_mode == LINK_CHNG_MODE_USE_STATUS_REG)
4306     {
4307         REG_RD(pdev, emac.emac_status, &val);
4308         if(pdev->params.phy_int_mode == PHY_INT_MODE_MI_INTERRUPT)
4309         {
4310             if(val & EMAC_STATUS_MI_INT)
4311             {
4312                 intr_status |= LM_PHY_EVENT_ACTIVE;
4313             }
4314         }
4315         else if(val & EMAC_STATUS_LINK_CHANGE)
4316         {
4317             intr_status |= LM_PHY_EVENT_ACTIVE;
4318         }
4319 
4320         GET_ATTN_CHNG_BITS(pdev, &asserted_attns, &deasserted_attns);
4321     }
4322     else
4323     {
4324         GET_ATTN_CHNG_BITS(pdev, &asserted_attns, &deasserted_attns);
4325 
4326         if(asserted_attns & STATUS_ATTN_BITS_LINK_STATE)
4327         {
4328             intr_status |= LM_PHY_EVENT_ACTIVE;
4329         }
4330         else if(deasserted_attns & STATUS_ATTN_BITS_LINK_STATE)
4331         {
4332             intr_status |= LM_PHY_EVENT_ACTIVE;
4333         }
4334     }
4335 
4336     /* Get driver pulse event.  MCP uses the TIMER_ABORT attention to
4337      * signal to the driver to write a driver pulse to the firmware. */
4338     if((asserted_attns & STATUS_ATTN_BITS_TIMER_ABORT) ||
4339         (deasserted_attns & STATUS_ATTN_BITS_TIMER_ABORT))
4340     {
4341         if(pdev->params.enable_remote_phy)
4342         {
4343             REG_RD_IND(
4344                 pdev,
4345                 pdev->hw_info.shmem_base +
4346                     OFFSETOF(shmem_region_t, fw_evt_mb.fw_evt_code_mb),
4347                 &val);
4348 
4349             if(val == 0)
4350             {
4351                 intr_status |= LM_KNOCK_KNOCK_EVENT;
4352             }
4353             else if(val == FW_EVT_CODE_LINK_STATUS_CHANGE_EVENT)
4354             {
4355                 intr_status |= LM_PHY_EVENT_ACTIVE;
4356             }
4357             else
4358             {
4359                 DbgBreakMsg("not a valid fw event.\n");
4360             }
4361         }
4362         else
4363         {
4364             intr_status |= LM_KNOCK_KNOCK_EVENT;
4365         }
4366 
4367         if(asserted_attns & STATUS_ATTN_BITS_TIMER_ABORT)
4368         {
4369             REG_WR(
4370                 pdev,
4371                 pci_config.pcicfg_status_bit_set_cmd,
4372                 asserted_attns & STATUS_ATTN_BITS_TIMER_ABORT);
4373         }
4374         else
4375         {
4376             REG_WR(
4377                 pdev,
4378                 pci_config.pcicfg_status_bit_clear_cmd,
4379                 deasserted_attns & STATUS_ATTN_BITS_TIMER_ABORT);
4380         }
4381     }
4382 
4383     /* get l2 tx events. */
4384     for(idx = 0; idx < pdev->tx_info.num_txq; idx++)
4385     {
4386         txq = &pdev->tx_info.chain[idx];
4387 
4388         hw_con_idx = *txq->hw_con_idx_ptr;
4389         if((hw_con_idx & MAX_BD_PER_PAGE) == MAX_BD_PER_PAGE)
4390         {
4391             hw_con_idx++;
4392         }
4393 
4394         if(hw_con_idx != txq->con_idx)
4395         {
4396             intr_status |= LM_TX0_EVENT_ACTIVE << txq->idx;
4397         }
4398     }
4399 
4400     /* get l2 rx events. */
4401     for(idx = 0; idx < pdev->rx_info.num_rxq; idx++)
4402     {
4403         rxq = &pdev->rx_info.chain[idx];
4404 
4405         hw_con_idx = *rxq->hw_con_idx_ptr;
4406         if((hw_con_idx & MAX_BD_PER_PAGE) == MAX_BD_PER_PAGE)
4407         {
4408             hw_con_idx++;
4409         }
4410 
4411         if(hw_con_idx != rxq->con_idx)
4412         {
4413             intr_status |= LM_RX0_EVENT_ACTIVE << rxq->idx;
4414         }
4415     }
4416 
4417     #ifndef EXCLUDE_KQE_SUPPORT
4418     if(CHIP_NUM(pdev) == CHIP_NUM_5706 || CHIP_NUM(pdev) == CHIP_NUM_5708)
4419     {
4420         /* HC install problem:  as a workaround, rx_quick_consumer_index15
4421          * is high jacked for use as cmd_con_idx.  The original cmd_con_idx
4422          * is not used. */
4423         if(pdev->kq_info.kwq_con_idx !=
4424             pdev->vars.status_virt->deflt.status_rx_quick_consumer_index15)
4425         {
4426             intr_status |= LM_KWQ_EVENT_ACTIVE;
4427         }
4428     }
4429     else
4430     {
4431         if(pdev->kq_info.kwq_con_idx !=
4432             pdev->vars.status_virt->deflt.status_cmd_consumer_index)
4433         {
4434             intr_status |= LM_KWQ_EVENT_ACTIVE;
4435         }
4436     }
4437 
4438     if(pdev->kq_info.kcq_con_idx !=
4439         pdev->vars.status_virt->deflt.status_completion_producer_index)
4440     {
4441         intr_status |= LM_KCQ_EVENT_ACTIVE;
4442     }
4443     #endif
4444 
4445     #if INCLUDE_OFLD_SUPPORT
4446     else if(pdev->params.hcopy_desc_cnt)
4447     {
4448         if(pdev->ofld.hcopy_chain.con_idx !=
4449             *(pdev->ofld.hcopy_chain.hw_con_idx_ptr))
4450         {
4451             intr_status |= LM_KCQ_EVENT_ACTIVE;
4452         }
4453     }
4454     #endif
4455 
4456     return intr_status;
4457 } /* lm_get_interrupt_status */
4458 
4459 
4460 
4461 #ifndef EXCLUDE_KQE_SUPPORT
4462 /*******************************************************************************
4463  * Description:
4464  *
4465  * Return:
4466  ******************************************************************************/
4467 void
4468 lm_ack_completed_wqes(
4469     lm_device_t *pdev)
4470 {
4471     u16_t new_con_idx;
4472     kwqe_t *con_qe;
4473     u16_t num_wqes;
4474     u16_t con_idx;
4475 
4476     /* HC install problem:  as a workaround, rx_quick_consumer_index15
4477      * is high jacked for use as cmd_con_idx.  The original cmd_con_idx
4478      * is not used. */
4479     if(CHIP_NUM(pdev) == CHIP_NUM_5706 || CHIP_NUM(pdev) == CHIP_NUM_5708)
4480     {
4481         new_con_idx =
4482             pdev->vars.status_virt->deflt.status_rx_quick_consumer_index15;
4483     }
4484     else
4485     {
4486         new_con_idx = pdev->vars.status_virt->deflt.status_cmd_consumer_index;
4487     }
4488 
4489     num_wqes = (u16_t) S16_SUB(new_con_idx, pdev->kq_info.kwq_con_idx);
4490     pdev->kq_info.kwqe_left += num_wqes;
4491 
4492     con_idx = new_con_idx;
4493     con_qe = pdev->kq_info.kwq_con_qe + num_wqes;
4494 
4495     /* Check for con_qe wrap around. */
4496     if((u8_t *) con_qe > (u8_t *) pdev->kq_info.kwq_last_qe)
4497     {
4498         con_qe = (kwqe_t *) ((u8_t *) pdev->kq_info.kwq_virt +
4499             ((u8_t *) con_qe - (u8_t *) pdev->kq_info.kwq_last_qe));
4500         con_qe--;
4501     }
4502 
4503     pdev->kq_info.kwq_con_idx = con_idx;
4504     pdev->kq_info.kwq_con_qe = con_qe;
4505 
4506     /* Make sure the con_qe and con_idx are consistent. */
4507     DbgBreakIf(((((u8_t *) con_qe - (u8_t *) pdev->kq_info.kwq_virt) /
4508         sizeof(kwqe_t)) & 0x7f) != (con_idx & 0x7f));
4509 
4510     #if DBG
4511     /* Make sure all the kwqes are accounted for. */
4512     if(S16_SUB(pdev->kq_info.kwq_prod_idx, con_idx) >= 0)
4513     {
4514         num_wqes = pdev->kq_info.kwqe_left +
4515             (u32_t) S16_SUB(pdev->kq_info.kwq_prod_idx, con_idx);
4516     }
4517     else
4518     {
4519         num_wqes = pdev->kq_info.kwqe_left + 0x10000 - con_idx +
4520             pdev->kq_info.kwq_prod_idx;
4521     }
4522 
4523     DbgBreakIf(num_wqes != (LM_PAGE_SIZE/sizeof(kwqe_t)) *
4524         pdev->params.kwq_page_cnt - 1);
4525     #endif
4526 } /* lm_ack_completed_wqes */
4527 
4528 
4529 
4530 /*******************************************************************************
4531  * Description:
4532  *
4533  * Return:
4534  ******************************************************************************/
4535 u32_t
4536 lm_get_kernel_cqes(
4537     lm_device_t *pdev,
4538     kcqe_t *cqe_ptr[],
4539     u32_t ptr_cnt)
4540 {
4541     kcqe_t *con_qe;
4542     u16_t prod_idx;
4543     u32_t num_cqes;
4544     u16_t con_idx;
4545 
4546     DbgMessage(pdev, VERBOSEint, "### lm_get_kernel_cqes\n");
4547 
4548     con_idx = pdev->kq_info.kcq_con_idx;
4549     con_qe = pdev->kq_info.kcq_con_qe;
4550 
4551     DbgBreakIf(((((u8_t *) con_qe - (u8_t *) pdev->kq_info.kcq_virt) /
4552         sizeof(kcqe_t)) & 0x7f) != (con_idx & 0x7f));
4553 
4554     num_cqes = 0;
4555     prod_idx = pdev->vars.status_virt->deflt.status_completion_producer_index;
4556 
4557     while(con_idx != prod_idx && num_cqes != ptr_cnt)
4558     {
4559         *cqe_ptr = con_qe;
4560         cqe_ptr++;
4561         num_cqes++;
4562         con_idx++;
4563 
4564         if(con_qe == pdev->kq_info.kcq_last_qe)
4565         {
4566             con_qe = pdev->kq_info.kcq_virt;
4567         }
4568         else
4569         {
4570             con_qe++;
4571         }
4572 
4573         prod_idx =
4574             pdev->vars.status_virt->deflt.status_completion_producer_index;
4575     }
4576 
4577     /* Make sure the last entry in the array does not have the 'next'
4578      * bit set.  We want to ensure the array contains all the cqes
4579      * for a completion.
4580      *
4581      * This piece of code also takes care of the case where a completion
4582      * spans multiple kcqes and not all the kcqes have been dma'd to
4583      * the host.  For example, if a completion consists of A, B, C, and D
4584      * kcqes.  The status block may tell us A and B have been dma'd.  In
4585      * this case, we don't want to return kcqes A and B in the array. */
4586     cqe_ptr--;
4587     while(num_cqes && ((*cqe_ptr)->kcqe_flags & KCQE_FLAGS_NEXT))
4588     {
4589         num_cqes--;
4590         cqe_ptr--;
4591     }
4592 
4593     DbgBreakIf(num_cqes == 0);
4594 
4595     return num_cqes;
4596 } /* lm_get_kernel_cqes */
4597 
4598 
4599 
4600 /*******************************************************************************
4601  * Description:
4602  *
4603  * Return:
4604  ******************************************************************************/
4605 u8_t
4606 lm_ack_kernel_cqes(
4607     lm_device_t *pdev,
4608     u32_t num_cqes)
4609 {
4610     kcqe_t *con_qe;
4611     u16_t prod_idx;
4612     u16_t con_idx;
4613 
4614     DbgMessage(pdev, VERBOSEint, "### lm_ack_kernel_cqes\n");
4615 
4616     con_idx = pdev->kq_info.kcq_con_idx;
4617 
4618     if(num_cqes)
4619     {
4620         /* Advance the consumer index and the con_qe pointer */
4621         con_idx += (u16_t) num_cqes;
4622         con_qe = pdev->kq_info.kcq_con_qe + num_cqes;
4623 
4624         /* Check for con_qe wrap around. */
4625         if((u8_t *) con_qe > (u8_t *) pdev->kq_info.kcq_last_qe)
4626         {
4627             con_qe = (kcqe_t *) ((u8_t *) pdev->kq_info.kcq_virt +
4628                 ((u8_t *) con_qe - (u8_t *) pdev->kq_info.kcq_last_qe));
4629             con_qe--;
4630         }
4631 
4632         pdev->kq_info.kcq_con_idx = con_idx;
4633         pdev->kq_info.kcq_con_qe = con_qe;
4634 
4635         /* Don't acknowledge the last 'kcq_history_size' entries so the
4636          * chip will not over write them with new entries.  We are doing
4637          * this to have a history of the kcq entries for debugging. */
4638         if(pdev->params.kcq_history_size)
4639         {
4640             /* The con_idx should always be ahead of history_kcq_con_idx. */
4641             DbgBreakIf(S16_SUB(con_idx, pdev->kq_info.history_kcq_con_idx) < 0);
4642 
4643             /* Number of entries between con_idx and history_kcq_con_idx. */
4644             num_cqes = (u32_t) S16_SUB(
4645                 con_idx,
4646                 pdev->kq_info.history_kcq_con_idx);
4647 
4648             /* Don't advance the consumer index if the number of history
4649              * entries is less than 'kcq_history_size'. */
4650             if(num_cqes >= pdev->params.kcq_history_size)
4651             {
4652                 /* Make sure we will have at most kcq_history_size entires. */
4653                 num_cqes -= pdev->params.kcq_history_size;
4654 
4655                 DbgBreakIf(num_cqes > pdev->params.kcq_history_size);
4656 
4657                 /* Advance the consumer index and the con_qe pointer */
4658                 pdev->kq_info.history_kcq_con_idx += (u16_t) num_cqes;
4659                 con_qe = pdev->kq_info.history_kcq_con_qe + num_cqes;
4660 
4661                 /* Check for con_qe wrap around. */
4662                 if((u8_t *) con_qe > (u8_t *) pdev->kq_info.kcq_last_qe)
4663                 {
4664                     con_qe = (kcqe_t *) ((u8_t *) pdev->kq_info.kcq_virt +
4665                         ((u8_t *) con_qe -
4666                          (u8_t *) pdev->kq_info.kcq_last_qe));
4667                     con_qe--;
4668                 }
4669                 pdev->kq_info.history_kcq_con_qe = con_qe;
4670 
4671                 MBQ_WR16(
4672                     pdev,
4673                     GET_CID(pdev->kq_info.kcq_cid_addr),
4674                     OFFSETOF(krnlq_context_t, krnlq_host_qidx),
4675                     pdev->kq_info.history_kcq_con_idx);
4676             }
4677         }
4678         else
4679         {
4680             MBQ_WR16(
4681                 pdev,
4682                 GET_CID(pdev->kq_info.kcq_cid_addr),
4683                 OFFSETOF(krnlq_context_t, krnlq_host_qidx),
4684                 con_idx);
4685         }
4686     }
4687 
4688     prod_idx = pdev->vars.status_virt->deflt.status_completion_producer_index;
4689 
4690     DbgBreakIf(S16_SUB(prod_idx, con_idx) < 0);
4691 
4692     return con_idx != prod_idx;
4693 } /* lm_ack_kernel_cqes */
4694 #endif /* EXCLUDE_KQE_SUPPORT */
4695 
4696 
4697 
4698 #ifndef EXCLUDE_RSS_SUPPORT
4699 #if RSS_LOOKUP_TABLE_WA
4700 /*******************************************************************************
4701  * Description:
4702  *
4703  * Return:
4704  ******************************************************************************/
4705 u64_t
4706 rss_f64(
4707     u8_t* key,
4708     u8_t s,
4709     u8_t e
4710     )
4711 {
4712     u64_t f;
4713 
4714     for( f=0; s<=e; ++s )
4715     {
4716         f = (f << 8);
4717         f |= key[s];
4718     }
4719 
4720     return f;
4721 }
4722 
4723 
4724 
4725 /*******************************************************************************
4726  * Description:
4727  *
4728  * Return:
4729  ******************************************************************************/
4730 u32_t
4731 rss_hash_byte(
4732     u8_t* key,
4733     u8_t  byte,
4734     u8_t  s,
4735     u8_t  e,
4736     u32_t rst
4737     )
4738 {
4739     u8_t i;
4740     u64_t key_msb;
4741 
4742     key_msb = rss_f64(key, s,e);
4743 
4744     for( i=0x80; i!=0; i>>=1 )
4745     {
4746         if( i & byte )
4747         {
4748             u32_t k;
4749 
4750             k = (u32_t)(key_msb >> 32);
4751             rst ^= k;
4752         }
4753         key_msb = (key_msb << 1);
4754     }
4755 
4756     return rst;
4757 }
4758 
4759 
4760 
4761 /*******************************************************************************
4762  * Description:
4763  *
4764  * Return:
4765  ******************************************************************************/
4766 void
4767 rss_gen_one_table(
4768     u8_t* key,
4769     u8_t  s,
4770     u8_t  e,
4771     u32_t* gtbl
4772     )
4773 {
4774     u32_t i;
4775 
4776     for( i = 0; i < 256; ++i )
4777     {
4778         gtbl[i] = rss_hash_byte( key, (u8_t)i, s, e, 0 );
4779     }
4780 }
4781 
4782 
4783 
4784 /*******************************************************************************
4785  * Description:
4786  *
4787  * Return:
4788  ******************************************************************************/
4789 void
4790 rss_gen_tables(
4791     u8_t* key,
4792     u32_t* tables
4793     )
4794 {
4795     u8_t t;
4796 
4797     for( t = 0; t < 12; ++t )
4798     {
4799         rss_gen_one_table( key, t, (u8_t)(t+7), tables );
4800         tables += 256;
4801     }
4802 }
4803 #endif
4804 
4805 
4806 #ifndef LM_NON_LEGACY_MODE_SUPPORT
4807 /*******************************************************************************
4808  * Description:
4809  *
4810  * Return:
4811  ******************************************************************************/
4812 lm_status_t
4813 lm_enable_rss(
4814     lm_device_t *pdev,
4815     lm_rss_hash_t hash_type,
4816     u8_t *indirection_table,
4817     u32_t table_size,
4818     u8_t *hash_key,
4819     u32_t key_size)
4820 {
4821     l2_kwqe_rss_table_update_t *rss_update;
4822     u8_t rss_key[RSS_HASH_KEY_SIZE];
4823     lm_address_t rss_table_phy;
4824     u8_t *rss_table_virt;
4825     kwqe_t *prod_qe;
4826     u16_t prod_idx;
4827     u32_t idx;
4828     u32_t val;
4829 
4830     if(pdev->kq_info.kwqe_left < 2)
4831     {
4832         pdev->kq_info.no_kwq_bd_left++;
4833         return LM_STATUS_RESOURCE;
4834     }
4835 
4836     pdev->kq_info.kwqe_left -= 2;
4837 
4838     DbgBreakIf(key_size > RSS_HASH_KEY_SIZE);
4839 
4840     /* Initialize the rss key array. */
4841     if(key_size > RSS_HASH_KEY_SIZE)
4842     {
4843         key_size = RSS_HASH_KEY_SIZE;
4844     }
4845 
4846     for(idx = 0; idx < key_size; idx++)
4847     {
4848         rss_key[idx] = hash_key[idx];
4849     }
4850 
4851     for(idx = key_size; idx < RSS_HASH_KEY_SIZE; idx++)
4852     {
4853         rss_key[idx] = 0;
4854     }
4855 
4856     DbgBreakIf(table_size > RSS_INDIRECTION_TABLE_SIZE);
4857 
4858     if(table_size > RSS_INDIRECTION_TABLE_SIZE)
4859     {
4860         table_size = RSS_INDIRECTION_TABLE_SIZE;
4861     }
4862 
4863     if(CHIP_NUM(pdev) == CHIP_NUM_5709)
4864     {
4865         REG_RD(pdev, rlup.rlup_rss_config, &val);
4866         val &= ~RLUP_RSS_CONFIG_IPV4_RSS_TYPE_OFF_XI;
4867         val &= ~RLUP_RSS_CONFIG_IPV6_RSS_TYPE_OFF_XI;
4868         REG_WR(pdev, rlup.rlup_rss_config, val);
4869 
4870         val = (rss_key[0] << 24) |
4871               (rss_key[1] << 16) |
4872               (rss_key[2] << 8) |
4873                rss_key[3];
4874         REG_WR(pdev, rlup.rlup_rss_key1, val);
4875 
4876         val = (rss_key[4] << 24) |
4877               (rss_key[5] << 16) |
4878               (rss_key[6] << 8) |
4879                rss_key[7];
4880         REG_WR(pdev, rlup.rlup_rss_key2, val);
4881 
4882         val = (rss_key[8] << 24) |
4883               (rss_key[9] << 16) |
4884               (rss_key[10] << 8) |
4885                rss_key[11];
4886         REG_WR(pdev, rlup.rlup_rss_key3, val);
4887 
4888         val = (rss_key[12] << 24) |
4889               (rss_key[13] << 16) |
4890               (rss_key[14] << 8) |
4891                rss_key[15];
4892         REG_WR(pdev, rlup.rlup_rss_key4, val);
4893 
4894         val = (rss_key[16] << 24) |
4895               (rss_key[17] << 16) |
4896               (rss_key[18] << 8) |
4897                rss_key[19];
4898         REG_WR(pdev, rlup.rlup_ipv6_rss_key5, val);
4899 
4900         val = (rss_key[20] << 24) |
4901               (rss_key[21] << 16) |
4902               (rss_key[22] << 8) |
4903                rss_key[23];
4904         REG_WR(pdev, rlup.rlup_ipv6_rss_key6, val);
4905 
4906         val = (rss_key[24] << 24) |
4907               (rss_key[25] << 16) |
4908               (rss_key[26] << 8) |
4909                rss_key[27];
4910         REG_WR(pdev, rlup.rlup_ipv6_rss_key7, val);
4911 
4912         val = (rss_key[28] << 24) |
4913               (rss_key[29] << 16) |
4914               (rss_key[30] << 8) |
4915                rss_key[31];
4916         REG_WR(pdev, rlup.rlup_ipv6_rss_key8, val);
4917 
4918         val = (rss_key[32] << 24) |
4919               (rss_key[33] << 16) |
4920               (rss_key[34] << 8) |
4921                rss_key[35];
4922         REG_WR(pdev, rlup.rlup_ipv6_rss_key9, val);
4923 
4924         val = (rss_key[36] << 24) |
4925               (rss_key[37] << 16) |
4926               (rss_key[38] << 8) |
4927                rss_key[39];
4928         REG_WR(pdev, rlup.rlup_ipv6_rss_key10, val);
4929     }
4930 
4931     rss_table_virt = pdev->rx_info.rss_ind_table_virt;
4932     rss_table_phy = pdev->rx_info.rss_ind_table_phy;
4933 
4934     for(idx = 0; idx < table_size; idx++)
4935     {
4936         rss_table_virt[idx] = indirection_table[idx];
4937     }
4938 
4939     prod_qe = pdev->kq_info.kwq_prod_qe;
4940     prod_idx = pdev->kq_info.kwq_prod_idx;
4941 
4942     /* Initialize the RSS update KWQE. */
4943     rss_update = (l2_kwqe_rss_table_update_t *) prod_qe;
4944 
4945     rss_update->rss_flags = L2_KWQE_FLAGS_LAYER_MASK_L2;
4946     rss_update->rss_opcode = L2_KWQE_OPCODE_VALUE_UPDATE_RSS;
4947 
4948     rss_update->rss_table_size = (u16_t) table_size;
4949     rss_update->rss_table_haddr_lo = rss_table_phy.as_u32.low;
4950     rss_update->rss_table_haddr_hi = rss_table_phy.as_u32.high;
4951     rss_update->rss_host_opaque = 0;
4952     rss_update->rss_hash_type = hash_type;
4953 
4954     #if RSS_LOOKUP_TABLE_WA
4955     rss_table_virt += RSS_INDIRECTION_TABLE_SIZE;
4956     LM_INC64(&rss_table_phy, RSS_INDIRECTION_TABLE_SIZE);
4957 
4958     rss_update->rss_lookup_table_lo = rss_table_phy.as_u32.low;
4959     rss_update->rss_lookup_table_hi = rss_table_phy.as_u32.high;
4960 
4961     rss_gen_tables(rss_key, (u32_t *) rss_table_virt);
4962     #endif
4963 
4964     /* Advance to the next KWQE. */
4965     if(prod_qe == pdev->kq_info.kwq_last_qe)
4966     {
4967         prod_qe = pdev->kq_info.kwq_virt;
4968     }
4969     else
4970     {
4971         prod_qe++;
4972     }
4973     prod_idx++;
4974 
4975     /* Initialize the RSS enable KWQE. */
4976     rss_update = (l2_kwqe_rss_table_update_t *) prod_qe;
4977 
4978     rss_update->rss_flags = L2_KWQE_FLAGS_LAYER_MASK_L2;
4979     rss_update->rss_opcode = L2_KWQE_OPCODE_VALUE_ENABLE_RSS;
4980     rss_update->rss_host_opaque = 0;
4981     rss_update->rss_hash_type = hash_type;
4982 
4983     /* Advance to the next KWQE. */
4984     if(prod_qe == pdev->kq_info.kwq_last_qe)
4985     {
4986         prod_qe = pdev->kq_info.kwq_virt;
4987     }
4988     else
4989     {
4990         prod_qe++;
4991     }
4992     prod_idx++;
4993 
4994     pdev->kq_info.kwq_prod_qe = prod_qe;
4995     pdev->kq_info.kwq_prod_idx = prod_idx;
4996 
4997     MBQ_WR16(
4998         pdev,
4999         GET_CID(pdev->kq_info.kwq_cid_addr),
5000         OFFSETOF(krnlq_context_t, krnlq_host_qidx),
5001         prod_idx);
5002 
5003     return LM_STATUS_SUCCESS;
5004 } /* lm_enable_rss */
5005 #else /* LM_LEAGCY_MODE_SUPPORT */
5006 /*******************************************************************************
5007  * Description:
5008  *
5009  * Return:
5010  ******************************************************************************/
5011 lm_status_t
5012 lm_enable_rss(
5013     lm_device_t *pdev,
5014     lm_rss_hash_t hash_type,
5015     PROCESSOR_NUMBER *indirection_table,
5016     u32_t table_size,
5017     u8_t *hash_key,
5018     u32_t key_size,
5019     u8_t *cpu_tbl,
5020     u8_t *rss_qidx_tbl)
5021 {
5022     l2_kwqe_rss_table_update_t *rss_update;
5023     u8_t rss_key[RSS_HASH_KEY_SIZE];
5024     lm_address_t rss_table_phy;
5025     u8_t *rss_table_virt;
5026     kwqe_t *prod_qe;
5027     u16_t prod_idx;
5028     u32_t idx;
5029     u32_t val;
5030 
5031     if(pdev->kq_info.kwqe_left < 2)
5032     {
5033         pdev->kq_info.no_kwq_bd_left++;
5034         return LM_STATUS_RESOURCE;
5035     }
5036 
5037     pdev->kq_info.kwqe_left -= 2;
5038 
5039     DbgBreakIf(key_size > RSS_HASH_KEY_SIZE);
5040 
5041     /* Initialize the rss key array. */
5042     if(key_size > RSS_HASH_KEY_SIZE)
5043     {
5044         key_size = RSS_HASH_KEY_SIZE;
5045     }
5046 
5047     for(idx = 0; idx < key_size; idx++)
5048     {
5049         rss_key[idx] = hash_key[idx];
5050     }
5051 
5052     for(idx = key_size; idx < RSS_HASH_KEY_SIZE; idx++)
5053     {
5054         rss_key[idx] = 0;
5055     }
5056 
5057     DbgBreakIf(table_size > RSS_INDIRECTION_TABLE_SIZE);
5058 
5059     if(table_size > RSS_INDIRECTION_TABLE_SIZE)
5060     {
5061         table_size = RSS_INDIRECTION_TABLE_SIZE;
5062     }
5063 
5064     if(CHIP_NUM(pdev) == CHIP_NUM_5709)
5065     {
5066         REG_RD(pdev, rlup.rlup_rss_config, &val);
5067         val &= ~RLUP_RSS_CONFIG_IPV4_RSS_TYPE_OFF_XI;
5068         val &= ~RLUP_RSS_CONFIG_IPV6_RSS_TYPE_OFF_XI;
5069         REG_WR(pdev, rlup.rlup_rss_config, val);
5070 
5071         val = (rss_key[0] << 24) |
5072               (rss_key[1] << 16) |
5073               (rss_key[2] << 8) |
5074                rss_key[3];
5075         REG_WR(pdev, rlup.rlup_rss_key1, val);
5076 
5077         val = (rss_key[4] << 24) |
5078               (rss_key[5] << 16) |
5079               (rss_key[6] << 8) |
5080                rss_key[7];
5081         REG_WR(pdev, rlup.rlup_rss_key2, val);
5082 
5083         val = (rss_key[8] << 24) |
5084               (rss_key[9] << 16) |
5085               (rss_key[10] << 8) |
5086                rss_key[11];
5087         REG_WR(pdev, rlup.rlup_rss_key3, val);
5088 
5089         val = (rss_key[12] << 24) |
5090               (rss_key[13] << 16) |
5091               (rss_key[14] << 8) |
5092                rss_key[15];
5093         REG_WR(pdev, rlup.rlup_rss_key4, val);
5094 
5095         val = (rss_key[16] << 24) |
5096               (rss_key[17] << 16) |
5097               (rss_key[18] << 8) |
5098                rss_key[19];
5099         REG_WR(pdev, rlup.rlup_ipv6_rss_key5, val);
5100 
5101         val = (rss_key[20] << 24) |
5102               (rss_key[21] << 16) |
5103               (rss_key[22] << 8) |
5104                rss_key[23];
5105         REG_WR(pdev, rlup.rlup_ipv6_rss_key6, val);
5106 
5107         val = (rss_key[24] << 24) |
5108               (rss_key[25] << 16) |
5109               (rss_key[26] << 8) |
5110                rss_key[27];
5111         REG_WR(pdev, rlup.rlup_ipv6_rss_key7, val);
5112 
5113         val = (rss_key[28] << 24) |
5114               (rss_key[29] << 16) |
5115               (rss_key[30] << 8) |
5116                rss_key[31];
5117         REG_WR(pdev, rlup.rlup_ipv6_rss_key8, val);
5118 
5119         val = (rss_key[32] << 24) |
5120               (rss_key[33] << 16) |
5121               (rss_key[34] << 8) |
5122                rss_key[35];
5123         REG_WR(pdev, rlup.rlup_ipv6_rss_key9, val);
5124 
5125         val = (rss_key[36] << 24) |
5126               (rss_key[37] << 16) |
5127               (rss_key[38] << 8) |
5128                rss_key[39];
5129         REG_WR(pdev, rlup.rlup_ipv6_rss_key10, val);
5130     }
5131 
5132     rss_table_virt = pdev->rx_info.rss_ind_table_virt;
5133     rss_table_phy = pdev->rx_info.rss_ind_table_phy;
5134 
5135     pdev->rx_info.rss_tbl_size = table_size;
5136     if(!cpu_tbl) /* indirection table already had queue idx? */
5137     {
5138         for(idx = 0; idx < table_size; idx++)
5139             rss_table_virt[idx] = indirection_table[idx].Number;
5140     }
5141     else
5142     {
5143         /* map the cpu num in the indirection table to queue idx
5144          * according to the cpu table passed down from the um, then
5145          * rebuilt the table with queue idx*/
5146         u8_t *rss_cpu_tbl = &cpu_tbl[1];
5147 
5148         for(idx = 0; idx < table_size; idx++)
5149         {
5150             for(val = 0; val < cpu_tbl[0]; val++)
5151             {
5152                 if(indirection_table[idx].Number == rss_cpu_tbl[val])
5153                 {
5154                     if(pdev->vars.interrupt_mode == IRQ_MODE_MSIX_BASED ||
5155                        pdev->vars.interrupt_mode == IRQ_MODE_MSI_BASED)
5156                     {
5157                         rss_table_virt[idx] = rss_qidx_tbl[rss_cpu_tbl[val] + 1];
5158                     }
5159                     else
5160                     {
5161                         rss_table_virt[idx] = (u8_t)val;
5162                     }
5163                     break;
5164                 }
5165             }
5166         }
5167     }
5168 
5169     prod_qe = pdev->kq_info.kwq_prod_qe;
5170     prod_idx = pdev->kq_info.kwq_prod_idx;
5171 
5172     /* Initialize the RSS update KWQE. */
5173     rss_update = (l2_kwqe_rss_table_update_t *) prod_qe;
5174 
5175     rss_update->rss_flags = L2_KWQE_FLAGS_LAYER_MASK_L2;
5176     rss_update->rss_opcode = L2_KWQE_OPCODE_VALUE_UPDATE_RSS;
5177 
5178     rss_update->rss_table_size = (u16_t) table_size;
5179     rss_update->rss_table_haddr_lo = rss_table_phy.as_u32.low;
5180     rss_update->rss_table_haddr_hi = rss_table_phy.as_u32.high;
5181     rss_update->rss_host_opaque = 0;
5182     rss_update->rss_hash_type = hash_type;
5183 
5184     #if RSS_LOOKUP_TABLE_WA
5185     rss_table_virt += RSS_INDIRECTION_TABLE_SIZE;
5186     LM_INC64(&rss_table_phy, RSS_INDIRECTION_TABLE_SIZE);
5187 
5188     rss_update->rss_lookup_table_lo = rss_table_phy.as_u32.low;
5189     rss_update->rss_lookup_table_hi = rss_table_phy.as_u32.high;
5190 
5191     rss_gen_tables(rss_key, (u32_t *) rss_table_virt);
5192     #endif
5193 
5194     /* Advance to the next KWQE. */
5195     if(prod_qe == pdev->kq_info.kwq_last_qe)
5196     {
5197         prod_qe = pdev->kq_info.kwq_virt;
5198     }
5199     else
5200     {
5201         prod_qe++;
5202     }
5203     prod_idx++;
5204 
5205     /* Initialize the RSS enable KWQE. */
5206     rss_update = (l2_kwqe_rss_table_update_t *) prod_qe;
5207 
5208     rss_update->rss_flags = L2_KWQE_FLAGS_LAYER_MASK_L2;
5209     rss_update->rss_opcode = L2_KWQE_OPCODE_VALUE_ENABLE_RSS;
5210     rss_update->rss_host_opaque = 0;
5211     rss_update->rss_hash_type = hash_type;
5212 
5213     /* Advance to the next KWQE. */
5214     if(prod_qe == pdev->kq_info.kwq_last_qe)
5215     {
5216         prod_qe = pdev->kq_info.kwq_virt;
5217     }
5218     else
5219     {
5220         prod_qe++;
5221     }
5222     prod_idx++;
5223 
5224     pdev->kq_info.kwq_prod_qe = prod_qe;
5225     pdev->kq_info.kwq_prod_idx = prod_idx;
5226 
5227     MBQ_WR16(
5228         pdev,
5229         GET_CID(pdev->kq_info.kwq_cid_addr),
5230         OFFSETOF(krnlq_context_t, krnlq_host_qidx),
5231         prod_idx);
5232 
5233     return LM_STATUS_SUCCESS;
5234 } /* lm_enable_rss */
5235 #endif /* LM_NON_LEGACY_MODE_SUPPORT */
5236 
5237 
5238 /*******************************************************************************
5239  * Description:
5240  *
5241  * Return:
5242  ******************************************************************************/
5243 lm_status_t
5244 lm_disable_rss(
5245     lm_device_t *pdev)
5246 {
5247     l2_kwqe_rss_table_update_t *rss_update;
5248     kwqe_t *prod_qe;
5249     u16_t prod_idx;
5250     u32_t val;
5251 
5252     if(pdev->kq_info.kwqe_left < 1)
5253     {
5254         pdev->kq_info.no_kwq_bd_left++;
5255         return LM_STATUS_RESOURCE;
5256     }
5257 
5258     pdev->kq_info.kwqe_left -= 1;
5259 
5260     if(CHIP_NUM(pdev) == CHIP_NUM_5709)
5261     {
5262         REG_RD(pdev, rlup.rlup_rss_config, &val);
5263         val &= ~RLUP_RSS_CONFIG_IPV4_RSS_TYPE_OFF_XI;
5264         val &= ~RLUP_RSS_CONFIG_IPV6_RSS_TYPE_OFF_XI;
5265         REG_WR(pdev, rlup.rlup_rss_config, val);
5266     }
5267 
5268     prod_qe = pdev->kq_info.kwq_prod_qe;
5269     prod_idx = pdev->kq_info.kwq_prod_idx;
5270 
5271     /* Initialize the RSS enable KWQE. */
5272     rss_update = (l2_kwqe_rss_table_update_t *) prod_qe;
5273 
5274     rss_update->rss_flags = L2_KWQE_FLAGS_LAYER_MASK_L2;
5275     rss_update->rss_opcode = L2_KWQE_OPCODE_VALUE_DISABLE_RSS;
5276 
5277     /* Advance to the next KWQE. */
5278     if(prod_qe == pdev->kq_info.kwq_last_qe)
5279     {
5280         prod_qe = pdev->kq_info.kwq_virt;
5281     }
5282     else
5283     {
5284         prod_qe++;
5285     }
5286     prod_idx++;
5287 
5288     pdev->kq_info.kwq_prod_qe = prod_qe;
5289     pdev->kq_info.kwq_prod_idx = prod_idx;
5290 
5291     MBQ_WR16(
5292         pdev,
5293         GET_CID(pdev->kq_info.kwq_cid_addr),
5294         OFFSETOF(krnlq_context_t, krnlq_host_qidx),
5295         prod_idx);
5296 
5297     return LM_STATUS_SUCCESS;
5298 } /* lm_disable_rss */
5299 #endif /* EXCLUDE_RSS_SUPPORT */
5300 
5301 /*******************************************************************************
5302  * Description:
5303  *
5304  * Return:
5305  ******************************************************************************/
5306 void lm_set_pcie_nfe_report(lm_device_t *pdev)
5307 {
5308     if(CHIP_NUM(pdev) == CHIP_NUM_5709 &&
5309        pdev->params.disable_pcie_nfr)
5310     {
5311         u16_t pci_devctl;
5312         REG_RD(pdev,pci_config.pcicfg_device_control,&pci_devctl);
5313         pci_devctl &= ~PCICFG_DEVICE_CONTROL_NON_FATAL_REP_ENA;
5314         REG_WR(pdev,pci_config.pcicfg_device_control,pci_devctl);
5315     }
5316 }
5317 
5318 /*******************************************************************************
5319  * Description:
5320  *
5321  * Return:
5322  ******************************************************************************/
5323 void lm_clear_coalescing_ticks(lm_device_t *pdev)
5324 {
5325     pdev->params.tx_quick_cons_trip = 1;
5326     pdev->params.tx_quick_cons_trip_int = 1;
5327     pdev->params.rx_quick_cons_trip = 1;
5328     pdev->params.rx_quick_cons_trip_int = 1;
5329     pdev->params.comp_prod_trip = 1;
5330     pdev->params.comp_prod_trip_int = 1;
5331 
5332     pdev->params.tx_ticks = 0;
5333     pdev->params.tx_ticks_int = 0;
5334     pdev->params.com_ticks = 0;
5335     pdev->params.com_ticks_int = 0;
5336     pdev->params.cmd_ticks = 0;
5337     pdev->params.cmd_ticks_int = 0;
5338     pdev->params.rx_ticks = 0;
5339     pdev->params.rx_ticks_int = 0;
5340     pdev->params.stats_ticks = 0;
5341 
5342     /* Xinan per-processor HC configuration. */
5343     pdev->params.psb_tx_cons_trip = 0x10001;
5344     pdev->params.psb_rx_cons_trip = 0x10001;
5345     pdev->params.psb_comp_prod_trip = 0x10001;
5346 
5347     pdev->params.psb_tx_ticks = 0;
5348     pdev->params.psb_rx_ticks = 0;
5349     pdev->params.psb_com_ticks = 0;
5350     pdev->params.psb_cmd_ticks = 0;
5351     pdev->params.psb_period_ticks = 0;
5352 }
5353 
5354 u8_t lm_is_mmio_ok(lm_device_t *pdev)
5355 {
5356     u32_t val;
5357     REG_RD(pdev, pci_config.pcicfg_vendor_id, &val);
5358     if (0xffffffff == val)
5359     {
5360         return FALSE;
5361     }
5362     else
5363     {
5364         return TRUE;
5365     }
5366 }
5367 
5368 #if defined(LM_NON_LEGACY_MODE_SUPPORT)
5369 /*******************************************************************************
5370  * Description:
5371  *
5372  * Return:
5373  ******************************************************************************/
5374 void
5375 lm_create_q_group(
5376     lm_device_t *pdev,
5377     u32_t q_group_id,
5378     u32_t lookahead_sz
5379     )
5380 {
5381     u32_t val;
5382     lm_rx_chain_t *rxq;
5383 
5384     rxq = &pdev->rx_info.chain[q_group_id];
5385     rxq->vmq_lookahead_size = lookahead_sz;
5386 
5387     val = lookahead_sz << 16;
5388     CTX_WR(
5389         pdev,
5390         rxq->cid_addr,
5391         WORD_ALIGNED_OFFSETOF(l2_bd_chain_context_t,
5392                               l2ctx_vmq_lookahead_sz),
5393         val);
5394 }
5395 
5396 /*******************************************************************************
5397  * Description:
5398  *
5399  * Return:
5400  ******************************************************************************/
5401 lm_status_t
5402 lm_destroy_q_group(
5403     lm_device_t *pdev,
5404     u32_t q_group_id,
5405     u32_t num_queues
5406     )
5407 {
5408     u32_t num_kwqes_needed;
5409     kwqe_t *prod_qe;
5410     u16_t prod_idx;
5411     l2_kwqe_vm_free_rx_queue_t *kwqe_free_rxq;
5412 
5413     num_kwqes_needed = num_queues;
5414 
5415     if(pdev->kq_info.kwqe_left < num_kwqes_needed)
5416     {
5417         DbgMessage(pdev, WARN, "No more KWQE left.\n");
5418 
5419         pdev->kq_info.no_kwq_bd_left++;
5420 
5421         return LM_STATUS_RESOURCE;
5422     }
5423 
5424     prod_qe = pdev->kq_info.kwq_prod_qe;
5425     prod_idx = pdev->kq_info.kwq_prod_idx;
5426 
5427     kwqe_free_rxq = (l2_kwqe_vm_free_rx_queue_t *) prod_qe;
5428 
5429     if(q_group_id <= RX_CHAIN_IDX3)
5430     {
5431         if(q_group_id == RX_CHAIN_IDX0)
5432         {
5433             u8_t idx;
5434             /* default queue may have more than 1 queue pairs */
5435             for(idx = 0; idx < num_queues; idx++)
5436             {
5437                 kwqe_free_rxq->flags = L2_KWQE_FLAGS_LAYER_MASK_L2;
5438                 kwqe_free_rxq->queue_type = L2_NORMAL_QUEUE;
5439 
5440                 if(idx == 0)
5441                     kwqe_free_rxq->qid = (u8_t)q_group_id;
5442                 else
5443                 {
5444                     kwqe_free_rxq->qid = idx + 3;
5445                 }
5446 
5447                 kwqe_free_rxq->opcode = L2_KWQE_OPCODE_VALUE_VM_FREE_RX_QUEUE;
5448 
5449                 /* Advance to the next KWQE. */
5450                 if(prod_qe == pdev->kq_info.kwq_last_qe)
5451                 {
5452                     prod_qe = pdev->kq_info.kwq_virt;
5453                 }
5454                 else
5455                 {
5456                     prod_qe++;
5457                 }
5458                 prod_idx++;
5459 
5460                 pdev->kq_info.kwqe_left -= 1;
5461                 kwqe_free_rxq = (l2_kwqe_vm_free_rx_queue_t *) prod_qe;
5462             }
5463             pdev->kq_info.kwq_prod_qe = prod_qe;
5464             pdev->kq_info.kwq_prod_idx = prod_idx;
5465 
5466             MBQ_WR16(
5467                 pdev,
5468                 GET_CID(pdev->kq_info.kwq_cid_addr),
5469                 OFFSETOF(krnlq_context_t, krnlq_host_qidx),
5470                 prod_idx);
5471 
5472             return LM_STATUS_SUCCESS;
5473         }
5474         else
5475         {
5476             kwqe_free_rxq->queue_type = L2_NORMAL_QUEUE;
5477             kwqe_free_rxq->qid = (u8_t)q_group_id;
5478             pdev->kq_info.kwqe_left -= 1;
5479 #if INCLUDE_OFLD_SUPPORT
5480             if(q_group_id == RX_CHAIN_IDX2 &&
5481                !s_list_is_empty(&pdev->rx_info.chain[RX_CHAIN_IDX1].active_descq))
5482             {
5483                 kwqe_free_rxq->flags = L2_KWQE_FLAGS_LAYER_MASK_L2;
5484                 kwqe_free_rxq->opcode = L2_KWQE_OPCODE_VALUE_VM_FREE_RX_QUEUE;
5485 
5486                 /* Advance to the next KWQE. */
5487                 if(prod_qe == pdev->kq_info.kwq_last_qe)
5488                 {
5489                     prod_qe = pdev->kq_info.kwq_virt;
5490                 }
5491                 else
5492                 {
5493                     prod_qe++;
5494                 }
5495                 prod_idx++;
5496 
5497                 /* flush the catchup RX queue too */
5498                 kwqe_free_rxq = (l2_kwqe_vm_free_rx_queue_t *) prod_qe;
5499                 kwqe_free_rxq->queue_type = L2_NORMAL_QUEUE;
5500                 kwqe_free_rxq->qid = (u8_t)RX_CHAIN_IDX1;
5501                 pdev->kq_info.kwqe_left -= 1;
5502             }
5503 #endif
5504         }
5505     }
5506     else
5507     {
5508         kwqe_free_rxq->queue_type = L2_VM_QUEUE;
5509         kwqe_free_rxq->qid = (u8_t)q_group_id;
5510         pdev->kq_info.kwqe_left -= 1;
5511     }
5512     kwqe_free_rxq->flags = L2_KWQE_FLAGS_LAYER_MASK_L2;
5513     kwqe_free_rxq->opcode = L2_KWQE_OPCODE_VALUE_VM_FREE_RX_QUEUE;
5514 
5515     /* Advance to the next KWQE. */
5516     if(prod_qe == pdev->kq_info.kwq_last_qe)
5517     {
5518         prod_qe = pdev->kq_info.kwq_virt;
5519     }
5520     else
5521     {
5522         prod_qe++;
5523     }
5524     prod_idx++;
5525 
5526     pdev->kq_info.kwq_prod_qe = prod_qe;
5527     pdev->kq_info.kwq_prod_idx = prod_idx;
5528 
5529     MBQ_WR16(
5530         pdev,
5531         GET_CID(pdev->kq_info.kwq_cid_addr),
5532         OFFSETOF(krnlq_context_t, krnlq_host_qidx),
5533         prod_idx);
5534 
5535     return LM_STATUS_SUCCESS;
5536 }
5537 
5538 /*******************************************************************************
5539  * Description:
5540  *
5541  * Return:
5542  ******************************************************************************/
5543 VOID
5544 lm_update_defq_filter_ctx(
5545     lm_device_t *pdev,
5546     u8_t valid
5547     )
5548 {
5549     u32_t ctx_offset = pdev->vars.hw_filter_ctx_offset;
5550     u32_t val = 0;
5551 
5552     if(valid)
5553         val |= L2_VM_FILTER_MAC << 16;
5554 
5555     REG_WR_IND(
5556         pdev,
5557         OFFSETOF(reg_space_t, rxp.rxp_scratch[0])+ctx_offset,
5558         val);
5559 }
5560 
5561 /*******************************************************************************
5562  * Description:
5563  *
5564  * Return:
5565  ******************************************************************************/
5566 lm_status_t
5567 lm_chng_q_group_filter(
5568     lm_device_t *pdev,
5569     u32_t q_group_id,
5570     u8_t  *dest_mac,
5571     u16_t *vlan_ptr,
5572     u32_t filter_id
5573     )
5574 {
5575     kwqe_t *prod_qe;
5576     u16_t prod_idx;
5577 
5578     if(pdev->kq_info.kwqe_left < 1)
5579     {
5580         DbgMessage(pdev, WARN, "No more KWQE left.\n");
5581 
5582         pdev->kq_info.no_kwq_bd_left++;
5583 
5584         return LM_STATUS_RESOURCE;
5585     }
5586 
5587     prod_qe = pdev->kq_info.kwq_prod_qe;
5588     prod_idx = pdev->kq_info.kwq_prod_idx;
5589 
5590     pdev->kq_info.kwqe_left -= 1;
5591     if(dest_mac == NULL && vlan_ptr == NULL)
5592     {
5593         /* clear filter operation */
5594         l2_kwqe_vm_remove_rx_filter_t * kwqe_remove_rx_filter =
5595             (l2_kwqe_vm_remove_rx_filter_t *) prod_qe;
5596         kwqe_remove_rx_filter->flags = L2_KWQE_FLAGS_LAYER_MASK_L2;
5597         kwqe_remove_rx_filter->qid = (u8_t)q_group_id;
5598         kwqe_remove_rx_filter->filter_id = (u8_t)filter_id;
5599         kwqe_remove_rx_filter->opcode = L2_KWQE_OPCODE_VALUE_VM_REMOVE_RX_FILTER;
5600     }
5601     else
5602     {
5603         /* set filter operation */
5604         l2_kwqe_vm_set_rx_filter_t * kwqe_set_rx_filter =
5605             (l2_kwqe_vm_set_rx_filter_t *) prod_qe;
5606 
5607         kwqe_set_rx_filter->flags = L2_KWQE_FLAGS_LAYER_MASK_L2;
5608         kwqe_set_rx_filter->qid = (u8_t)q_group_id;
5609         kwqe_set_rx_filter->filter_id = (u8_t)filter_id;
5610         if(vlan_ptr)
5611         {
5612             kwqe_set_rx_filter->vlan = *vlan_ptr;
5613             kwqe_set_rx_filter->filter_type = L2_VM_FILTER_MAC_VLAN;
5614         }
5615         else
5616         {
5617             kwqe_set_rx_filter->filter_type = L2_VM_FILTER_MAC;
5618         }
5619         kwqe_set_rx_filter->opcode = L2_KWQE_OPCODE_VALUE_VM_SET_RX_FILTER;
5620     }
5621 
5622     /* Advance to the next KWQE. */
5623     if(prod_qe == pdev->kq_info.kwq_last_qe)
5624     {
5625         prod_qe = pdev->kq_info.kwq_virt;
5626     }
5627     else
5628     {
5629         prod_qe++;
5630     }
5631     prod_idx++;
5632 
5633     pdev->kq_info.kwq_prod_qe = prod_qe;
5634     pdev->kq_info.kwq_prod_idx = prod_idx;
5635 
5636     MBQ_WR16(
5637         pdev,
5638         GET_CID(pdev->kq_info.kwq_cid_addr),
5639         OFFSETOF(krnlq_context_t, krnlq_host_qidx),
5640         prod_idx);
5641     return LM_STATUS_PENDING;
5642 }
5643 
5644 /*******************************************************************************
5645  * Description:
5646  *
5647  * Return:
5648  ******************************************************************************/
5649 u32_t
5650 lm_service_l2_kcqes(
5651     struct _lm_device_t *pdev,
5652     kcqe_t *cqe_ptr[],
5653     u32_t num_cqes)
5654 {
5655     u32_t cqe_serviced_cnt;
5656     u32_t cqe_cnt;
5657     u8_t success;
5658     kcqe_t *kcqe;
5659     lm_status_t lm_status;
5660 
5661     cqe_serviced_cnt = 0;
5662     while(num_cqes)
5663     {
5664         /* Determine the number of cqes for a completion.  Some
5665          * completions span several cqes. */
5666         cqe_cnt = 0;
5667         while(cqe_ptr[cqe_cnt]->kcqe_flags & KCQE_FLAGS_NEXT)
5668         {
5669             cqe_cnt++;
5670         }
5671         cqe_cnt++;
5672 
5673         DbgBreakIf(cqe_cnt > num_cqes);
5674 
5675         kcqe = *cqe_ptr;
5676 
5677         DbgBreakIf((kcqe->kcqe_flags & KCQE_FLAGS_LAYER_MASK) !=
5678                     KCQE_FLAGS_LAYER_MASK_L2);
5679 
5680         switch(kcqe->kcqe_opcode)
5681         {
5682             case L2_KCQE_OPCODE_VALUE_VM_FREE_RX_QUEUE:
5683                 /* initiate rx buffer abort */
5684                 {
5685                     l2_kcqe_vm_free_rx_queue_t *kcqe_free_rxq;
5686 
5687                     kcqe_free_rxq = (l2_kcqe_vm_free_rx_queue_t *)kcqe;
5688                     mm_q_grp_abort_rx_request(
5689                         pdev,
5690                         kcqe_free_rxq->qid);
5691                 }
5692                 break;
5693 
5694             case L2_KCQE_OPCODE_VALUE_VM_SET_RX_FILTER:
5695             case L2_KCQE_OPCODE_VALUE_VM_REMOVE_RX_FILTER:
5696                 {
5697                     l2_kcqe_vm_set_rx_filter_t *kcqe_filter;
5698 
5699                     kcqe_filter = (l2_kcqe_vm_set_rx_filter_t *)kcqe;
5700                     if(kcqe_filter->status == SC_SUCCESS)
5701                     {
5702                         lm_status = LM_STATUS_SUCCESS;
5703                     }
5704                     else
5705                     {
5706                         lm_status = LM_STATUS_FAILURE;
5707                     }
5708                     mm_comp_l2_filter_chng_req(
5709                         pdev,
5710                         lm_status,
5711                         kcqe_filter->qid);
5712                 }
5713                 break;
5714 
5715             case L2_KCQE_OPCODE_VALUE_VM_ALLOC_RX_QUEUE:
5716             case L2_KCQE_OPCODE_VALUE_RX_PACKET:
5717             case L2_KCQE_OPCODE_VALUE_ENABLE_RSS:
5718             case L2_KCQE_OPCODE_VALUE_DISABLE_RSS:
5719             case L2_KCQE_OPCODE_VALUE_UPDATE_RSS:
5720             case L2_KCQE_OPCODE_VALUE_FLUSH_BD_CHAIN:
5721                 /* no need to do anything in the driver */
5722                 break;
5723 
5724             default:
5725                 DbgBreakMsg("invalid l2 kcqe.\n");
5726                 break;
5727         }
5728 
5729         cqe_ptr += cqe_cnt;
5730         num_cqes -= cqe_cnt;
5731         cqe_serviced_cnt += cqe_cnt;
5732     }
5733 
5734     return cqe_serviced_cnt;
5735 }
5736 #endif /* LM_NON_LEGACY_MODE_SUPPORT */
5737