source: trunk/hal/tsar_mips32/drivers/soclib_nic.c @ 678

Last change on this file since 678 was 658, checked in by alain, 4 years ago

Improve the TSAR NIC driver.

File size: 25.0 KB
RevLine 
[75]1/*
2 * soclib_nic.c - SOCLIB_NIC (Network Interface Controler) driver implementation.
3 *
[658]4 * Author     Alain Greiner (2016,2017,2018,2019,2020)
[75]5 *
6 * Copyright (c) UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-MKH.
9 *
10 * ALMOS-MKH.is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.0 of the License.
13 *
14 * ALMOS-MKH.is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ALMOS-MKH.; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
[451]24#include <hal_kernel_types.h>
[75]25#include <hal_remote.h>
26#include <hal_special.h>
27#include <chdev.h>
28#include <dev_nic.h>
29#include <kmem.h>
30#include <printk.h>
31#include <memcpy.h>
32#include <thread.h>
33#include <soclib_nic.h>
34
[658]35
36////////////////////////////////////////////////////////////////////////////////////////
37// Extern global variables
38////////////////////////////////////////////////////////////////////////////////////////
39
40extern chdev_directory_t  chdev_dir;     // allocated in kernel_init.c
41
42#if DEBUG_HAL_NIC_TX || DEBUG_HAL_NIC_RX
43
44////////////////////////////////////////////////////////////////////////////////////////
45//          static function used for SOCLIB_NIC driver debug
46////////////////////////////////////////////////////////////////////////////////////////
47static void soclib_nic_chbuf_display( nic_chbuf_t * chbuf,
48                                      char        * name )
49{
50    uint32_t i;
51
52    // software L2/L3 cache coherence for chbuf WID & RID read
53    if( chdev_dir.iob )  dev_mmc_inval( XPTR ( local_cxy , chbuf ) , 8 );
54
55    // get pointers on TXT0 chdev
56    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
57    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
58    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
59
60    // get extended pointer on remote TXT0 chdev lock
61    xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
62
63    // get TXT0 lock
64    remote_busylock_acquire( lock_xp );
65
66    nolock_printk("\n***** chbuf %s : ptr %x / wid %d / rid %d *****\n",
67    name, chbuf, chbuf->wid, chbuf->rid );
68
69    for( i = 0 ; i < SOCLIB_NIC_CHBUF_DEPTH ; i++ )
70    {
71        uint32_t * container = chbuf->cont_ptr[i];
72
73        // software L2/L3 cache coherence for container STS & PLEN read
74        if( chdev_dir.iob ) dev_mmc_inval( XPTR( local_cxy , container + 510 ), 8 );
75
76        if( container[511] )
77        {
78            nolock_printk(" - %d : FULL  / cont_ptr %x / cont_pad [%x,%x] / plen %d\n",
79            i, chbuf->cont_ptr[i],
80            (uint32_t)(chbuf->cont_pad[i]>>32),
81            (uint32_t)chbuf->cont_pad[i],
82            container[510] );
83        }
84        else
85        {
86            nolock_printk(" - %d : EMPTY / cont_ptr %x / cont_pad [%x,%x]\n",
87            i, chbuf->cont_ptr[i],
88            (uint32_t)(chbuf->cont_pad[i]>>32),
89            (uint32_t)chbuf->cont_pad[i] );
90        }
91    }
92
93    // release TXT0 lock
94    remote_busylock_release( lock_xp );
95
96}  // end soclib_nic_chbuf_display()
97
98#endif
99
[75]100///////////////////////////////////////
101void soclib_nic_init( chdev_t * chdev )
102{
103    uint32_t    i;
104    kmem_req_t  req;
[658]105    ppn_t       ppn;
106    uint64_t    padr;
[259]107
108    // set driver specific fields in chdev descriptor
109    chdev->cmd = &soclib_nic_cmd;
110    chdev->isr = &soclib_nic_isr;
[658]111
112    // get chdev channel & direction
113    bool_t   is_rx   = chdev->is_rx;
114    uint32_t channel = chdev->channel;
[75]115   
[658]116    // get NIC device cluster and local pointer
[75]117    cxy_t      nic_cxy  = GET_CXY( chdev->base );
[658]118    uint32_t * nic_ptr  = GET_PTR( chdev->base );
[75]119
[658]120#if DEBUG_HAL_NIC_TX || DEBUG_HAL_NIC_RX
121thread_t * this  = CURRENT_THREAD;
122uint32_t   cycle = (uint32_t)hal_get_cycles();
123if( (is_rx == false) && DEBUG_HAL_NIC_RX < cycle )
124printk("\n[%s] thread[%x,%x] enter : NIC_TX channel %d / chdev %x / base %x / cycle %d\n",
125__FUNCTION__, this->process->pid, this->trdid, channel, chdev, nic_ptr, cycle );
126if( is_rx && DEBUG_HAL_NIC_RX < cycle )
127printk("\n[%s] thread[%x,%x] enter : NIC_RX channel %d / chdev %x / base %x / cycle %d\n",
128__FUNCTION__, this->process->pid, this->trdid, channel, chdev, nic_ptr, cycle );
129#endif
[75]130
[658]131    // get number of channels from hardware
132    uint32_t channels = hal_remote_l32( XPTR( nic_cxy,
133                        nic_ptr + NIC_GLOBAL_OFFSET + NIC_G_CHANNELS )); 
[75]134
[658]135    // check value registered in cluster descriptor
136    if( LOCAL_CLUSTER->nb_nic_channels != channels )
137    {
138        printk("\n[PANIC] in %s : channels[soft] (%d) != channels[hard] (%d)\n",
139        __FUNCTION__, LOCAL_CLUSTER->nb_nic_channels, channels );
140        return;
141    }
142
143    // check channel index
144    if( channel >= channels ) 
145    {
146        printk("\n[PANIC] in %s illegal channel index\n", __FUNCTION__ );
147        return;
148    }
149
150    // allocate memory for chbuf descriptor
151    req.type   = KMEM_KCM;
152    req.order  = bits_log2( sizeof(nic_chbuf_t) );
[75]153    req.flags  = AF_KERNEL;
[635]154    nic_chbuf_t * chbuf = kmem_alloc( &req );
[75]155
[635]156    if( chbuf == NULL )
157    {
[658]158        printk("\n[PANIC] in %s : cannot allocate chbuf descriptor\n", __FUNCTION__ );
159        return;
[635]160    }
[75]161
[658]162    // initialise chbuf indexes
163    chbuf->wid  = 0;
164    chbuf->rid  = 0;
165     
166    // software L2/L3 cache coherence for chbuf WID & RID     
167    if( chdev_dir.iob ) dev_mmc_sync( XPTR( local_cxy , chbuf ) , 8 );
[75]168   
[658]169    // allocate containers and complete chbuf initialisation
170    for( i = 0 ; i < SOCLIB_NIC_CHBUF_DEPTH ; i++ )
171    {
172        // 2048 bytes per container
173        req.type   = KMEM_KCM;
174        req.order  = 11;
175        req.flags  = AF_KERNEL;
176        uint32_t * container  = kmem_alloc( &req );
[75]177
[658]178        if( container == NULL )
179        {
180            printk("\n[PANIC] in %s : cannot allocate container\n", __FUNCTION__ );
181            return;
182        }
183
184        // initialize container as empty
185        container[511] = 0;
186
187        // software L2/L3 cache coherence for container STS       
188        if( chdev_dir.iob ) dev_mmc_sync( XPTR( local_cxy , &container[511] ) , 4 );
189
190        // compute container physical address
191        ppn  = ppm_base2ppn( XPTR( local_cxy , container ) );
192        padr = ((uint64_t)ppn << CONFIG_PPM_PAGE_SHIFT) |
193               ((intptr_t)container & CONFIG_PPM_PAGE_MASK);
194
195        // complete chbuf initialisation       
196        chbuf->cont_ptr[i] = container;
197        chbuf->cont_pad[i] = padr;
198    }
199
200    // software L2/L3 cache coherence for chbuf descriptor
201    if( chdev_dir.iob ) dev_mmc_sync( XPTR( local_cxy , chbuf ),
202                                      sizeof(nic_chbuf_t) );
203
204    // get NIC channel segment base and chbuf depth
205    uint32_t * channel_base = nic_ptr + NIC_CHANNEL_SPAN * channel;
206    uint32_t   nbufs        = SOCLIB_NIC_CHBUF_DEPTH;
207   
208    // compute chbuf physical address
209    ppn  = ppm_base2ppn( XPTR( local_cxy , chbuf ) );
210    padr = ((uint64_t)ppn  << CONFIG_PPM_PAGE_SHIFT) |
211           ((intptr_t)chbuf & CONFIG_PPM_PAGE_MASK);
212
213    uint32_t low  = (uint32_t)(padr); 
214    uint32_t high = (uint32_t)(padr >> 32); 
215
216    // initialize the NIC channel registers
217    if( is_rx ) 
[75]218    {
[658]219        hal_remote_s32( XPTR( nic_cxy , channel_base + NIC_RX_CHBUF_DESC_LO ) , low );
220        hal_remote_s32( XPTR( nic_cxy , channel_base + NIC_RX_CHBUF_DESC_HI ) , high );
221        hal_remote_s32( XPTR( nic_cxy , channel_base + NIC_RX_CHBUF_NBUFS   ) , nbufs );
[75]222
[658]223        hal_fence();
224
225        hal_remote_s32( XPTR( nic_cxy , channel_base + NIC_RX_CHANNEL_RUN   ) , 1 );
226    }
227    else
228    {
229        hal_remote_s32( XPTR( nic_cxy , channel_base + NIC_TX_CHBUF_DESC_LO ) , low );
230        hal_remote_s32( XPTR( nic_cxy , channel_base + NIC_TX_CHBUF_DESC_HI ) , high );
231        hal_remote_s32( XPTR( nic_cxy , channel_base + NIC_TX_CHBUF_NBUFS   ) , nbufs );
232
233        hal_fence();
234
235        hal_remote_s32( XPTR( nic_cxy , channel_base + NIC_TX_CHANNEL_RUN   ) , 1 );
236    }
237
238    // register chbuf pointer in chdev descriptor extension
239    chdev->ext.nic.queue = chbuf;
[75]240       
[658]241#if DEBUG_HAL_NIC_TX || DEBUG_HAL_NIC_RX
242cycle = (uint32_t)hal_get_cycles();
243if( (is_rx == false) && DEBUG_HAL_NIC_RX < cycle )
244printk("\n[%s] thread[%x,%x] exit / NIC_TX channel %d / chbuf %x / cycle %d\n",
245__FUNCTION__, this->process->pid, this->trdid, channel, chbuf, cycle );
246if( is_rx && DEBUG_HAL_NIC_RX < cycle )
247printk("\n[%s] thread[%x,%x] exit / NIC_RX channel %d / chbuf %x / cycle %d\n",
248__FUNCTION__, this->process->pid, this->trdid, channel, chbuf, cycle );
249soclib_nic_chbuf_display( chbuf , chdev->name );
250#endif
251
[75]252} // end soclib_nic_init()
253
254//////////////////////////////////////////////////////////////////
255void __attribute__ ((noinline)) soclib_nic_cmd( xptr_t thread_xp )
256{
[657]257    uint32_t       type;         // command type   
[658]258    uint8_t      * buffer;       // pointer on command buffer   
[75]259    uint32_t       length;       // Ethernet packet length
[658]260    xptr_t         dev_xp;       // extended pointer on NIC chdev
261    chdev_t      * dev_ptr;      // local pointer on NIC chdev
262    cxy_t          dev_cxy;      // NIC chdev cluster identifier
[75]263    nic_chbuf_t  * chbuf;        // pointer on chbuf descriptor
[658]264    uint32_t       index;        // index of current container in chbuf
[75]265    uint32_t     * container;    // pointer on container (array of uint32_t)
266
[658]267    thread_t * this = CURRENT_THREAD;
[75]268
[658]269// check calling thread == client thread
270assert( (thread_xp == XPTR( local_cxy , this )), "calling thread must be the client thread");
271 
272    // get command type
273    type    = this->nic_cmd.type;
[75]274
[658]275    // get chdev pointers for device
276    dev_xp  = this->nic_cmd.dev_xp;
277    dev_ptr = GET_PTR( dev_xp );
278    dev_cxy = GET_CXY( dev_xp );
[75]279
280    // analyse command type
[657]281    switch( type )
[75]282    {
[658]283        //////////////////////////////////////////////////////////////////////////
284        case NIC_CMD_WRITE:  // move one packet from command buffer to TX queue
[75]285        {
[658]286
287// check chdev is local
288assert( (dev_cxy == local_cxy), "illegal cluster for a WRITE command");
[75]289           
[658]290            // get command arguments
291            buffer = this->nic_cmd.buffer;
292            length = this->nic_cmd.length;
[75]293
[658]294// check packet length
295assert( (length <= 2040), "packet length too large");
[75]296
[658]297            // get chbuf descriptor pointer
298            chbuf = (nic_chbuf_t *)dev_ptr->ext.nic.queue;
[75]299
[658]300            // software L2/L3 cache coherence for chbuf WID read
301            if( chdev_dir.iob )  dev_mmc_inval( XPTR ( local_cxy , chbuf ) , 8 );
[75]302
[658]303            // get container write index
304            index = chbuf->wid;
[75]305
[658]306            // get pointer on container (no L2/L3 cache coherence required)
307            container = chbuf->cont_ptr[index];
[75]308
[658]309            // software L2/L3 cache coherence for container STS read
310            if( chdev_dir.iob )  dev_mmc_inval( XPTR ( local_cxy , &container[511]) , 4 );
[75]311
[658]312#if DEBUG_HAL_NIC_TX
313uint32_t   cycle = (uint32_t)hal_get_cycles();
314if( DEBUG_HAL_NIC_TX < cycle )
315printk("\n[%s] thread[%x,%x] enter / WRITE / chdev %x / chbuf %x / len %d / cycle %d\n",
316__FUNCTION__, this->process->pid, this->trdid, dev_ptr, chbuf, length, cycle );
317soclib_nic_chbuf_display( chbuf , dev_ptr->name );
318#endif
319            // check container STS
320            if( container[511] != 0 )   // container full
321            {
322                // return failure
323                this->nic_cmd.status = 0;
324                this->nic_cmd.error  = 0;
[75]325
[658]326#if DEBUG_HAL_NIC_TX
327cycle = (uint32_t)hal_get_cycles();
328if( DEBUG_HAL_NIC_TX < cycle )
329printk("\n[%s] thread[%x,%x] WRITE failure : NIC_TX[%d] queue full / cycle %d\n",
330__FUNCTION__, this->process->pid , this->trdid , dev_ptr->channel , cycle );
331soclib_nic_chbuf_display( chbuf , dev_ptr->name );
332#endif
333            }
334            else                                       // container empty
335            {
336                // move the packet from buffer to container
337                memcpy( container , buffer , length );
[75]338
[658]339                // update packet length in container header
340                container[510] = length;
[75]341
[658]342                hal_fence();
[75]343
[658]344                // update container STS
345                container[511] = 1;
[75]346
[658]347                // update current container WID
348                chbuf->wid = (index + 1) % SOCLIB_NIC_CHBUF_DEPTH;
349
350                // software L2/L3 cache coherence for container DATA write
351                if( chdev_dir.iob ) dev_mmc_sync( XPTR( local_cxy , container ), length );
352
353                // software L2/L3 cache coherence for container LENGTH and STS write
354                if( chdev_dir.iob ) dev_mmc_sync( XPTR( local_cxy , &container[510] ) , 8 );
355               
356                // software L2/L3 cache coherence for chbuf WID write
357                if( chdev_dir.iob ) dev_mmc_sync( XPTR( local_cxy , chbuf ) , 8 );
358
359                // return success
360                this->nic_cmd.status = length;
361                this->nic_cmd.error  = 0;
362
363#if DEBUG_HAL_NIC_TX
364cycle = (uint32_t)hal_get_cycles();
365if( DEBUG_HAL_NIC_TX < cycle )
366printk("\n[%s] thread[%x,%x] WRITE success on NIC_TX[%d] / len %d / cycle %d\n",
367__FUNCTION__, this->process->pid, this->trdid, dev_ptr->channel , length, cycle );
368soclib_nic_chbuf_display( chbuf , dev_ptr->name );
369#endif
370            }
[75]371        }
372        break;  // end WRITE
373
[658]374        /////////////////////////////////////////////////////////////////////////
375        case NIC_CMD_READ:   // move one packet from RX queue to kernel buffer
[75]376        {
377
[658]378// check chdev is local
379assert( (dev_cxy == local_cxy), "illegal cluster for a READ command");
380           
381            // get target buffer
382            buffer = this->nic_cmd.buffer;
[75]383
[658]384            // get chbuf descriptor pointer
385            chbuf = (nic_chbuf_t *)dev_ptr->ext.nic.queue;
386
387            // software L2/L3 cache coherence for chbuf WID & RID read
388            if( chdev_dir.iob )  dev_mmc_inval( XPTR ( local_cxy , chbuf ) , 8 );
389
390            // get container read index
391            index = chbuf->rid;
392           
393            // get pointer on container (no L2/L3 cache coherence required)
394            container = chbuf->cont_ptr[index];
395
396            // software L2/L3 cache coherence for container STS & PLEN read
397            if( chdev_dir.iob ) dev_mmc_inval( XPTR( local_cxy , container + 510 ), 8 );
398
399#if DEBUG_HAL_NIC_RX
400uint32_t   cycle = (uint32_t)hal_get_cycles();
401if( DEBUG_HAL_NIC_RX < cycle )
402printk("\n[%s] thread[%x,%x] enter / READ / chdev %x / chbuf %x / cycle %d\n",
403__FUNCTION__, this->process->pid, this->trdid, dev_ptr, chbuf, cycle );
404soclib_nic_chbuf_display( chbuf , dev_ptr->name );
405#endif
406            // check container state
407            if( container[511] == 0 )   // container empty
[75]408            {
[658]409                // return failure
410                this->nic_cmd.status = 0;
411                this->nic_cmd.error  = 0;
412
413#if DEBUG_HAL_NIC_RX
414cycle = (uint32_t)hal_get_cycles();
415if( DEBUG_HAL_NIC_RX < cycle )
416printk("\n[%s] thread[%x,%x] READ failure : NIC_RX[%d] queue empty / cycle %d\n",
417__FUNCTION__, this->process->pid, this->trdid, dev_ptr->channel , cycle );
418soclib_nic_chbuf_display( chbuf , dev_ptr->name );
419#endif
[75]420            }
[658]421            else                      // container full
[75]422            {
[658]423                // get packet length from container
424                length = container[510];
[75]425
[658]426                // software L2/L3 cache coherence for container DATA
427                if( chdev_dir.iob ) dev_mmc_inval( XPTR( local_cxy , container) , length );
[75]428
[658]429                // move the packet from container to buffer
430                memcpy( buffer , container , length );
431
432                hal_fence();
433
434                // update container STS
435                container[511] = 0;
436
437                // update current container WID
438                chbuf->rid = (index + 1) % SOCLIB_NIC_CHBUF_DEPTH;
439
440                // software L2/L3 cache coherence for container STS write
441                if( chdev_dir.iob ) dev_mmc_sync( XPTR( local_cxy , &container[511] ), 4 );
442
443                // software L2/L3 cache coherence for chbuf RID write
444                if( chdev_dir.iob )  dev_mmc_sync( XPTR ( local_cxy , chbuf ) , 8 );
445
446                // return success
447                this->nic_cmd.status = length;
448                this->nic_cmd.error  = 0;
449
450#if DEBUG_HAL_NIC_RX
451uint32_t   cycle = (uint32_t)hal_get_cycles();
452if( DEBUG_HAL_NIC_RX < cycle )
453printk("\n[%s] thread[%x,%x] READ success on NIC_RX[%d] queue / len %d / cycle %d\n",
454__FUNCTION__, this->process->pid, this->trdid , dev_ptr->channel , length , cycle );
455soclib_nic_chbuf_display( chbuf , dev_ptr->name );
456#endif
[75]457            }
458        }
[658]459        break;    // end READ
460           
461        /////////////////////////////////////////////////////////////////////
462        case NIC_CMD_GET_KEY:      // return channel from IP addr & port
463        {
464            // get number of NIC channels
465            uint32_t channels = LOCAL_CLUSTER->nb_nic_channels;
466 
467            // get IP address and port from command in thread descriptor
468            uint32_t addr = (intptr_t)this->nic_cmd.buffer;
469            uint16_t port = (uint16_t)this->nic_cmd.length;
470 
471            // compute NIC channel index
472            uint32_t key = ( ((addr     ) & 0xFF) +
473                             ((addr > 8 ) & 0xFF) +
474                             ((addr > 16) & 0xFF) +
475                             ((addr > 24) & 0xFF) +
476                             ((port     ) & 0xFF) +
477                             ((port > 8 ) & 0xFF) ) % channels;
[75]478
[658]479            // return key in "status" and return "error"
480            this->nic_cmd.status = key;
481            this->nic_cmd.error  = 0;
482        }
483        break;  // end GET_KEY
484
485        /////////////////////////////////////////////////////////////////////
486        case NIC_CMD_SET_RUN:       // activate/desactivate one NIC channel
[75]487        {
[658]488            // get pointers on NIC peripheral
489            xptr_t     base_xp  = dev_ptr->base;
490            uint32_t * base_ptr = GET_PTR( base_xp );
491            cxy_t      base_cxy = GET_CXY( base_xp );
[75]492
[658]493            // get channel and run from the "length" and "status" arguments
494            uint32_t channel = this->nic_cmd.length;
495            uint32_t run     = this->nic_cmd.status;
[75]496
[658]497            // build pointers on channel base
498            uint32_t * channel_ptr = base_ptr + NIC_CHANNEL_SPAN * channel;
[75]499
[658]500            // set new value in NIC_RX_CHANNEL_RUN & NIC_TX_CHANNEL_RUN registers
501            hal_remote_s32( XPTR( base_cxy , channel_ptr + NIC_RX_CHANNEL_RUN ) , run );
502            hal_remote_s32( XPTR( base_cxy , channel_ptr + NIC_TX_CHANNEL_RUN ) , run );
503
504            // return "error"
505            this->nic_cmd.error  = 0;
[75]506        }
[658]507        break;  // end SET_RUN
508
509        /////////////////////////////////////////////////////////////////////
510        case NIC_CMD_GET_INSTRU:     // diplay packets counters on TXT0
511        {
512            // get pointers on NIC peripheral
513            xptr_t     base_xp  = dev_ptr->base;
514            uint32_t * base_ptr = GET_PTR( base_xp );
515            cxy_t      base_cxy = GET_CXY( base_xp );
516
517            // build pointer on global register base
518            uint32_t * global_ptr = base_ptr + NIC_GLOBAL_OFFSET;
519
520            uint32_t rx_g2s_received      = hal_remote_l32( XPTR( base_cxy , 
521                                            global_ptr + NIC_G_NPKT_RX_G2S_RECEIVED ));
522            uint32_t rx_g2s_discarded     = hal_remote_l32( XPTR( base_cxy , 
523                                            global_ptr + NIC_G_NPKT_RX_G2S_DISCARDED ));
524            uint32_t rx_des_success       = hal_remote_l32( XPTR( base_cxy , 
525                                            global_ptr + NIC_G_NPKT_RX_DES_SUCCESS ));
526            uint32_t rx_des_too_small     = hal_remote_l32( XPTR( base_cxy , 
527                                            global_ptr + NIC_G_NPKT_RX_DES_TOO_SMALL ));
528            uint32_t rx_des_too_big       = hal_remote_l32( XPTR( base_cxy , 
529                                            global_ptr + NIC_G_NPKT_RX_DES_TOO_BIG ));
530            uint32_t rx_des_mfifo_full    = hal_remote_l32( XPTR( base_cxy , 
531                                            global_ptr + NIC_G_NPKT_RX_DES_MFIFO_FULL ));
532            uint32_t rx_des_crc_fail      = hal_remote_l32( XPTR( base_cxy , 
533                                            global_ptr + NIC_G_NPKT_RX_DES_CRC_FAIL ));
534            uint32_t rx_disp_received     = hal_remote_l32( XPTR( base_cxy , 
535                                            global_ptr + NIC_G_NPKT_RX_DISP_RECEIVED ));
536            uint32_t rx_disp_dst_fail     = hal_remote_l32( XPTR( base_cxy , 
537                                            global_ptr + NIC_G_NPKT_RX_DISP_DST_FAIL ));
538            uint32_t rx_disp_ch_full      = hal_remote_l32( XPTR( base_cxy , 
539                                            global_ptr + NIC_G_NPKT_RX_DISP_CH_FULL ));
540
541            uint32_t tx_disp_received     = hal_remote_l32( XPTR( base_cxy , 
542                                            global_ptr + NIC_G_NPKT_TX_DISP_RECEIVED ));
543            uint32_t tx_disp_too_small    = hal_remote_l32( XPTR( base_cxy , 
544                                            global_ptr + NIC_G_NPKT_TX_DISP_TOO_SMALL ));
545            uint32_t tx_disp_too_big      = hal_remote_l32( XPTR( base_cxy , 
546                                            global_ptr + NIC_G_NPKT_TX_DISP_TOO_BIG ));
547            uint32_t tx_disp_transmit     = hal_remote_l32( XPTR( base_cxy , 
548                                            global_ptr + NIC_G_NPKT_TX_DISP_TRANSMIT ));
549
550            printk("\n*** NIC device Instrumentation ***\n\n"
551                   " - rx_g2s_received   = %d\n"
552                   " - rx_g2s_discarded  = %d\n"
553                   " - rx_des_success    = %d\n"
554                   " - rx_des_too_small  = %d\n"
555                   " - rx_des_too_big    = %d\n"
556                   " - rx_des_mfifo_full = %d\n"
557                   " - rx_des_crc_fail   = %d\n"
558                   " - rx_disp_received  = %d\n"
559                   " - rx_disp_dsp_fail  = %d\n"
560                   " - rx_disp_ch_full   = %d\n\n"
561                   " - tx_disp_received  = %d\n"
562                   " - tx_disp_too_small = %d\n"
563                   " - tx_disp_too_big   = %d\n"
564                   " - tx_disp_transmit  = %d\n",
565                   rx_g2s_received,
566                   rx_g2s_discarded,
567                   rx_des_success,
568                   rx_des_too_small,
569                   rx_des_too_big,
570                   rx_des_mfifo_full,
571                   rx_des_crc_fail,
572                   rx_disp_received,
573                   rx_disp_dst_fail, 
574                   rx_disp_ch_full,
575                   tx_disp_received,
576                   tx_disp_too_small,
577                   tx_disp_too_big, 
578                   tx_disp_transmit );
579
580            // return "error"
581            this->nic_cmd.error  = 0;
582        }
583        break;  // end CLEAR_INSTRU
584
585        /////////////////////////////////////////////////////////////////////
586        case NIC_CMD_CLEAR_INSTRU:  // reset instrumentation registers
587        {
588            // get pointers on NIC peripheral
589            xptr_t     base_xp  = dev_ptr->base;
590            uint32_t * base_ptr = GET_PTR( base_xp );
591            cxy_t      base_cxy = GET_CXY( base_xp );
592
593            // build pointer on relevant NIC register
594            uint32_t * reset_ptr = base_ptr + NIC_GLOBAL_OFFSET + NIC_G_NPKT_RESET;
595
596            // reset all NIC instrumentation registers
597            hal_remote_s32( XPTR( base_cxy , reset_ptr ) , 0 );
598
599            // return "error"
600            this->nic_cmd.error  = 0;
601        }
602        break;  // end GET_INSTRU
603
604        default:
605        {
[657]606            assert( false, "Unknown command <%x>\n", type );
[507]607        }
[506]608    }
[75]609} // end soclib_nic_cmd()
610
611
612/////////////////////////////////////////////////////////////////
613void __attribute__ ((noinline)) soclib_nic_isr( chdev_t * chdev )
614{
615    // get base, size, channel, is_rx from NIC channel device NIC
[658]616    xptr_t     base_xp = chdev->base;
[75]617    uint32_t   channel = chdev->channel;
618    bool_t     is_rx   = chdev->is_rx;
619
620    // get NIC peripheral cluster and local pointer
[658]621    cxy_t      nic_cxy = GET_CXY( base_xp );
622    uint32_t * nic_ptr = GET_PTR( base_xp );
[75]623
[658]624    // compute local pointer on state register
625    uint32_t  * ptr;
626    if( is_rx ) ptr = nic_ptr + (NIC_CHANNEL_SPAN * channel) + NIC_RX_CHANNEL_STATE;
627    else        ptr = nic_ptr + (NIC_CHANNEL_SPAN * channel) + NIC_TX_CHANNEL_STATE;
[75]628
629    // read NIC channel status and acknowledge IRQ
[658]630    uint32_t status = hal_remote_l32( XPTR( nic_cxy , ptr ) );
[75]631
[658]632// check status value
633if( is_rx &&  (status != NIC_CHANNEL_STATUS_IDLE) )
634printk("\n[PANIC] in %s : error reported by NIC_RX[%d]\n", __FUNCTION__, channel );
635if( (is_rx == false) &&  (status != NIC_CHANNEL_STATUS_IDLE) )
636printk("\n[PANIC] in %s : error reported by NIC_TX[%d]\n", __FUNCTION__, channel );
[493]637
[75]638    // unblock server thread
639    thread_t * server = chdev->server;
[658]640    thread_unblock( XPTR( local_cxy , server ) , THREAD_BLOCKED_ISR );
[75]641
[658]642#if (DEBUG_HAL_NIC_RX || DEBUG_HAL_NIC_TX)
643uint32_t   cycle = (uint32_t)hal_get_cycles();
644if( is_rx && DEBUG_HAL_NIC_RX < cycle )
645printk("\n[%s] ISR unblocks NIC_RX[%d] server thread / cycle %d\n",
646__FUNCTION__, channel, cycle );
647if( (is_rx == false) && DEBUG_HAL_NIC_TX < cycle )
648printk("\n[%s] ISR unblocks NIC_TX[%d] server thread / cycle %d\n",
649__FUNCTION__, channel, cycle );
650#endif
651
[75]652} // end soclib_nic_isr()
653
Note: See TracBrowser for help on using the repository browser.