Changeset 686 for trunk/hal/tsar_mips32/drivers/soclib_nic.c
- Timestamp:
- Jan 13, 2021, 12:47:53 AM (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/hal/tsar_mips32/drivers/soclib_nic.c
r679 r686 1 1 /* 2 * soclib_nic.c - SOCLIB_NIC (Network Interface Controler) driver implementation.2 * soclib_nic.c - VCI_MASTER_NIC (Network Interface Controler) driver implementation. 3 3 * 4 4 * Author Alain Greiner (2016,2017,2018,2019,2020) … … 64 64 remote_busylock_acquire( lock_xp ); 65 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++ )66 nolock_printk("\n***** chbuf %s : cxy %x / ptr %x / wid %d / rid %d *****\n", 67 name, local_cxy , chbuf, chbuf->wid, chbuf->rid ); 68 69 for( i = 0 ; i < CONFIG_SOCK_QUEUES_DEPTH ; i++ ) 70 70 { 71 71 uint32_t * container = chbuf->cont_ptr[i]; … … 76 76 if( container[511] ) 77 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] ); 78 nolock_printk(" - %d : FULL / cont_ptr %x / plen %d\n", 79 i, chbuf->cont_ptr[i], container[510] ); 83 80 } 84 81 else 85 82 { 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] ); 83 nolock_printk(" - %d : EMPTY / cont_ptr %x\n", 84 i, chbuf->cont_ptr[i] ); 90 85 } 91 86 } … … 101 96 void soclib_nic_init( chdev_t * chdev ) 102 97 { 103 uint32_t i; 104 kmem_req_t req; 105 ppn_t ppn; 106 uint64_t padr; 98 uint32_t * container; // local pointer on one container 99 uint32_t cont_per_page; // number of containers per page 100 uint32_t cont_gid; // container global index (in chbuf) 101 bool_t cont_error; // not enough memory for chbuf containers 102 103 ppn_t ppn; // used for both the chbuf descriptor and the containers 104 uint64_t padr; // used for both the chbuf descriptor and the containers 105 106 assert( __FUNCTION__ , (chdev->func == DEV_FUNC_NIC), 107 "bad func argument" ); 108 109 assert( __FUNCTION__ , (sizeof(nic_cont_t) == 2048), 110 "container size must be 2048 bytes" ); 111 112 assert( __FUNCTION__ , (CONFIG_PPM_PAGE_ORDER >= 11 ), 113 "page size cannot be smaller than container size" ); 107 114 108 115 // set driver specific fields in chdev descriptor … … 122 129 uint32_t cycle = (uint32_t)hal_get_cycles(); 123 130 if( (is_rx == false) && DEBUG_HAL_NIC_RX < cycle ) 124 printk("\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 );131 printk("\n[%s] thread[%x,%x] enter : NIC_TX channel %d / chdev %x / cycle %d\n", 132 __FUNCTION__, this->process->pid, this->trdid, channel, chdev, cycle ); 126 133 if( is_rx && DEBUG_HAL_NIC_RX < cycle ) 127 printk("\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 130 131 // get number of channels from hardware134 printk("\n[%s] thread[%x,%x] enter : NIC_RX channel %d / chdev %x / cycle %d\n", 135 __FUNCTION__, this->process->pid, this->trdid, channel, chdev, cycle ); 136 #endif 137 138 // get number of channels from NIC hardware register 132 139 uint32_t channels = hal_remote_l32( XPTR( nic_cxy, 133 140 nic_ptr + NIC_GLOBAL_OFFSET + NIC_G_CHANNELS )); … … 144 151 if( channel >= channels ) 145 152 { 146 printk("\n[ PANIC] in %s illegal channel index\n", __FUNCTION__ );153 printk("\n[ERROR] in %s illegal channel index\n", __FUNCTION__ ); 147 154 return; 148 155 } 149 156 150 157 // allocate memory for chbuf descriptor 151 req.type = KMEM_KCM; 152 req.order = bits_log2( sizeof(nic_chbuf_t) ); 153 req.flags = AF_KERNEL; 154 nic_chbuf_t * chbuf = kmem_alloc( &req ); 158 nic_chbuf_t * chbuf = kmem_alloc( bits_log2( sizeof(nic_chbuf_t) ) , AF_KERNEL ); 155 159 156 160 if( chbuf == NULL ) 157 161 { 158 printk("\n[ PANIC] in %s : cannot allocate chbuf descriptor\n", __FUNCTION__ );162 printk("\n[ERROR] in %s : cannot allocate chbuf descriptor\n", __FUNCTION__ ); 159 163 return; 160 164 } … … 166 170 // software L2/L3 cache coherence for chbuf WID & RID 167 171 if( chdev_dir.iob ) dev_mmc_sync( XPTR( local_cxy , chbuf ) , 8 ); 168 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 ); 177 178 if( container == NULL ) 179 { 180 printk("\n[PANIC] in %s : cannot allocate container\n", __FUNCTION__ ); 181 return; 172 173 cont_error = false; 174 cont_gid = 0; 175 cont_per_page = 1 << (CONFIG_PPM_PAGE_ORDER - 11); 176 177 // allocate containers & complete chbuf initialisation 178 // depending on the PPM page size, we pack several 179 // 248 bytes containers in one single page. 180 181 // lopp on containers 182 while( cont_gid < CONFIG_SOCK_QUEUES_DEPTH ) 183 { 184 if( (cont_gid & (cont_per_page - 1)) == 0 ) // allocate one PPM page 185 { 186 container = kmem_alloc( CONFIG_PPM_PAGE_ORDER , AF_KERNEL ); 187 188 if( container == NULL ) 189 { 190 cont_error = true; 191 break; 192 } 193 } 194 else // increment container base address 195 { 196 container = container + 512; 182 197 } 183 198 … … 190 205 // compute container physical address 191 206 ppn = ppm_base2ppn( XPTR( local_cxy , container ) ); 192 padr = ((uint64_t)ppn << CONFIG_PPM_PAGE_ SHIFT) |207 padr = ((uint64_t)ppn << CONFIG_PPM_PAGE_ORDER) | 193 208 ((intptr_t)container & CONFIG_PPM_PAGE_MASK); 194 209 195 210 // complete chbuf initialisation 196 chbuf->cont_ptr[i] = container; 197 chbuf->cont_pad[i] = padr; 211 chbuf->cont_ptr[cont_gid] = container; 212 chbuf->cont_pad[cont_gid] = padr; 213 214 // increment container index 215 cont_gid++; 216 } 217 218 // release allocated containers and chbuf if not enough memory 219 if( cont_error ) 220 { 221 // loop on allocated containers 222 while( cont_gid ) 223 { 224 // release container when required 225 if( (cont_gid & (cont_per_page - 1)) == 0 ) 226 kmem_free( chbuf->cont_ptr[cont_gid] , CONFIG_PPM_PAGE_ORDER ); 227 228 // decrement container index 229 cont_gid--; 230 } 231 232 // release chbuf descriptor 233 kmem_free( chbuf , bits_log2(sizeof(nic_chbuf_t)) ); 234 235 return; 198 236 } 199 237 … … 204 242 // get NIC channel segment base and chbuf depth 205 243 uint32_t * channel_base = nic_ptr + NIC_CHANNEL_SPAN * channel; 206 uint32_t nbufs = SOCLIB_NIC_CHBUF_DEPTH;244 uint32_t nbufs = CONFIG_SOCK_QUEUES_DEPTH; 207 245 208 246 // compute chbuf physical address 209 247 ppn = ppm_base2ppn( XPTR( local_cxy , chbuf ) ); 210 padr = ((uint64_t)ppn << CONFIG_PPM_PAGE_ SHIFT) |248 padr = ((uint64_t)ppn << CONFIG_PPM_PAGE_ORDER) | 211 249 ((intptr_t)chbuf & CONFIG_PPM_PAGE_MASK); 212 250 … … 267 305 thread_t * this = CURRENT_THREAD; 268 306 269 // check calling thread == client thread 270 assert( __FUNCTION__, (thread_xp == XPTR( local_cxy , this )),"calling thread must be the client thread");307 assert( __FUNCTION__, (thread_xp == XPTR( local_cxy , this )), 308 "calling thread must be the client thread"); 271 309 272 310 // get command type … … 286 324 287 325 // check chdev is local 288 assert( __FUNCTION__, (dev_cxy == local_cxy), "illegal cluster for a WRITE command"); 326 assert( __FUNCTION__, (dev_cxy == local_cxy), 327 "illegal cluster for a WRITE command"); 289 328 290 329 // get command arguments … … 293 332 294 333 // check packet length 295 assert( __FUNCTION__, (length <= 2040), "packet length too large"); 334 assert( __FUNCTION__, (length <= 2040), 335 "packet length too large"); 296 336 297 337 // get chbuf descriptor pointer … … 313 353 uint32_t cycle = (uint32_t)hal_get_cycles(); 314 354 if( DEBUG_HAL_NIC_TX < cycle ) 315 printk("\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 ); 317 soclib_nic_chbuf_display( chbuf , dev_ptr->name ); 355 printk("\n[%s] thread[%x,%x] enter / WRITE / %s / chbuf (%x,%x) / len %d / cycle %d\n", 356 __FUNCTION__, this->process->pid, this->trdid, dev_ptr->name, local_cxy, chbuf, length, cycle ); 318 357 #endif 319 358 // check container STS … … 327 366 cycle = (uint32_t)hal_get_cycles(); 328 367 if( DEBUG_HAL_NIC_TX < cycle ) 329 printk("\n[%s] thread[%x,%x] WRITE failure : NIC_TX[%d] queue full / cycle %d\n",368 printk("\n[%s] thread[%x,%x] exit / WRITE failure : NIC_TX[%d] queue full / cycle %d\n", 330 369 __FUNCTION__, this->process->pid , this->trdid , dev_ptr->channel , cycle ); 331 soclib_nic_chbuf_display( chbuf , dev_ptr->name );332 370 #endif 333 371 } … … 346 384 347 385 // update current container WID 348 chbuf->wid = (index + 1) % SOCLIB_NIC_CHBUF_DEPTH;386 chbuf->wid = (index + 1) % CONFIG_SOCK_QUEUES_DEPTH; 349 387 350 388 // software L2/L3 cache coherence for container DATA write … … 364 402 cycle = (uint32_t)hal_get_cycles(); 365 403 if( DEBUG_HAL_NIC_TX < cycle ) 366 printk("\n[%s] thread[%x,%x] WRITE success on NIC_TX[%d] / len %d / cycle %d\n",404 printk("\n[%s] thread[%x,%x] exit / WRITE success on NIC_TX[%d] / len %d / cycle %d\n", 367 405 __FUNCTION__, this->process->pid, this->trdid, dev_ptr->channel , length, cycle ); 368 soclib_nic_chbuf_display( chbuf , dev_ptr->name ); 406 if((DEBUG_HAL_NIC_TX < cycle) && (DEBUG_HAL_NIC_TX & 1)) 407 putb( "64 first bytes moved to TX queue by NIC driver" , buffer , 64 ); 369 408 #endif 370 409 } … … 377 416 378 417 // check chdev is local 379 assert( __FUNCTION__, (dev_cxy == local_cxy), "illegal cluster for a READ command"); 418 assert( __FUNCTION__, (dev_cxy == local_cxy), 419 "illegal cluster for a READ command"); 380 420 381 421 // get target buffer … … 400 440 uint32_t cycle = (uint32_t)hal_get_cycles(); 401 441 if( DEBUG_HAL_NIC_RX < cycle ) 402 printk("\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 ); 404 soclib_nic_chbuf_display( chbuf , dev_ptr->name ); 442 printk("\n[%s] thread[%x,%x] enter / READ / %s / chbuf (%x,%x) / cycle %d\n", 443 __FUNCTION__, this->process->pid, this->trdid, dev_ptr->name, local_cxy, chbuf, cycle ); 405 444 #endif 406 445 // check container state … … 414 453 cycle = (uint32_t)hal_get_cycles(); 415 454 if( DEBUG_HAL_NIC_RX < cycle ) 416 printk("\n[%s] thread[%x,%x] READ failure : NIC_RX[%d] queue empty / cycle %d\n",455 printk("\n[%s] thread[%x,%x] exit / READ failure : NIC_RX[%d] queue empty / cycle %d\n", 417 456 __FUNCTION__, this->process->pid, this->trdid, dev_ptr->channel , cycle ); 418 soclib_nic_chbuf_display( chbuf , dev_ptr->name );419 457 #endif 420 458 } … … 436 474 437 475 // update current container WID 438 chbuf->rid = (index + 1) % SOCLIB_NIC_CHBUF_DEPTH;476 chbuf->rid = (index + 1) % CONFIG_SOCK_QUEUES_DEPTH; 439 477 440 478 // software L2/L3 cache coherence for container STS write … … 451 489 uint32_t cycle = (uint32_t)hal_get_cycles(); 452 490 if( DEBUG_HAL_NIC_RX < cycle ) 453 printk("\n[%s] thread[%x,%x] READ success on NIC_RX[%d] queue / len %d / cycle %d\n",491 printk("\n[%s] thread[%x,%x] exit / READ success on NIC_RX[%d] queue / len %d / cycle %d\n", 454 492 __FUNCTION__, this->process->pid, this->trdid , dev_ptr->channel , length , cycle ); 455 soclib_nic_chbuf_display( chbuf , dev_ptr->name ); 493 if((DEBUG_HAL_NIC_RX < cycle) && (DEBUG_HAL_NIC_RX & 1)) 494 putb("64 first bytes moved from RX queue by NIC driver" , buffer , 64 ); 456 495 #endif 457 496 } … … 491 530 cxy_t base_cxy = GET_CXY( base_xp ); 492 531 493 // get channel and runfrom the "length" and "status" arguments532 // get "channel" and "run" arguments from the "length" and "status" arguments 494 533 uint32_t channel = this->nic_cmd.length; 495 534 uint32_t run = this->nic_cmd.status; … … 613 652 void __attribute__ ((noinline)) soclib_nic_isr( chdev_t * chdev ) 614 653 { 615 // get base, size, channel, is_rx from NIC channel device NIC654 // get base, size, channel, is_rx, name, and server from NIC chdev 616 655 xptr_t base_xp = chdev->base; 617 656 uint32_t channel = chdev->channel; 618 657 bool_t is_rx = chdev->is_rx; 658 thread_t * server = chdev->server; 619 659 620 660 // get NIC peripheral cluster and local pointer … … 630 670 uint32_t status = hal_remote_l32( XPTR( nic_cxy , ptr ) ); 631 671 632 // check status value 633 if( is_rx && (status != NIC_CHANNEL_STATUS_IDLE) ) 634 printk("\n[PANIC] in %s : error reported by NIC_RX[%d]\n", __FUNCTION__, channel ); 635 if( (is_rx == false) && (status != NIC_CHANNEL_STATUS_IDLE) ) 636 printk("\n[PANIC] in %s : error reported by NIC_TX[%d]\n", __FUNCTION__, channel ); 637 638 // unblock server thread 639 thread_t * server = chdev->server; 640 thread_unblock( XPTR( local_cxy , server ) , THREAD_BLOCKED_ISR ); 672 // check status value 673 if( status == NIC_CHANNEL_STATUS_ERROR ) // error reported 674 { 641 675 642 676 #if (DEBUG_HAL_NIC_RX || DEBUG_HAL_NIC_TX) 643 677 uint32_t cycle = (uint32_t)hal_get_cycles(); 644 if( is_rx && DEBUG_HAL_NIC_RX < cycle ) 645 printk("\n[%s] ISR unblocks NIC_RX[%d] server thread / cycle %d\n", 646 __FUNCTION__, channel, cycle ); 647 if( (is_rx == false) && DEBUG_HAL_NIC_TX < cycle ) 648 printk("\n[%s] ISR unblocks NIC_TX[%d] server thread / cycle %d\n", 649 __FUNCTION__, channel, cycle ); 650 #endif 678 printk("\n[%s] error reported for %s / status %d / cycle %d\n", 679 __FUNCTION__ , chdev->name , status , cycle ); 680 #endif 681 server->nic_cmd.error = 1; 682 } 683 else if( status != NIC_CHANNEL_STATUS_IDLE) // no error but DMA BUSY 684 { 685 686 #if (DEBUG_HAL_NIC_RX || DEBUG_HAL_NIC_TX) 687 uint32_t cycle = (uint32_t)hal_get_cycles(); 688 printk("\n[%s] warning reported for %s / status %d / cycle %d\n", 689 __FUNCTION__ , chdev->name , status , cycle ); 690 #endif 691 server->nic_cmd.error = 0; 692 } 693 else 694 { 695 696 #if (DEBUG_HAL_NIC_RX || DEBUG_HAL_NIC_TX) 697 uint32_t cycle = (uint32_t)hal_get_cycles(); 698 printk("\n[%s] irq reported for %s / status %d / cycle %d\n", 699 __FUNCTION__ , chdev->name , status , cycle ); 700 #endif 701 server->nic_cmd.error = 0; 702 } 703 704 // unblock server thread 705 server->nic_cmd.status = status; 706 thread_unblock( XPTR( local_cxy , server ) , THREAD_BLOCKED_ISR ); 651 707 652 708 } // end soclib_nic_isr()
Note: See TracChangeset
for help on using the changeset viewer.