|  | @@ -394,8 +394,9 @@ static inline void phantom_write_hilo ( struct phantom_nic *phantom,
 | 
		
	
		
			
			| 394 | 394 |   * @v buf		8-byte buffer to fill
 | 
		
	
		
			
			| 395 | 395 |   * @ret rc		Return status code
 | 
		
	
		
			
			| 396 | 396 |   */
 | 
		
	
		
			
			| 397 |  | -static int phantom_read_test_mem ( struct phantom_nic *phantom,
 | 
		
	
		
			
			| 398 |  | -				   uint64_t offset, uint32_t buf[2] ) {
 | 
		
	
		
			
			|  | 397 | +static int phantom_read_test_mem_block ( struct phantom_nic *phantom,
 | 
		
	
		
			
			|  | 398 | +					 unsigned long offset,
 | 
		
	
		
			
			|  | 399 | +					 uint32_t buf[2] ) {
 | 
		
	
		
			
			| 399 | 400 |  	unsigned int retries;
 | 
		
	
		
			
			| 400 | 401 |  	uint32_t test_control;
 | 
		
	
		
			
			| 401 | 402 |  
 | 
		
	
	
		
			
			|  | @@ -421,29 +422,58 @@ static int phantom_read_test_mem ( struct phantom_nic *phantom,
 | 
		
	
		
			
			| 421 | 422 |  	return -ETIMEDOUT;
 | 
		
	
		
			
			| 422 | 423 |  }
 | 
		
	
		
			
			| 423 | 424 |  
 | 
		
	
		
			
			|  | 425 | +/**
 | 
		
	
		
			
			|  | 426 | + * Read single byte from Phantom test memory
 | 
		
	
		
			
			|  | 427 | + *
 | 
		
	
		
			
			|  | 428 | + * @v phantom		Phantom NIC
 | 
		
	
		
			
			|  | 429 | + * @v offset		Offset within test memory
 | 
		
	
		
			
			|  | 430 | + * @ret byte		Byte read, or negative error
 | 
		
	
		
			
			|  | 431 | + */
 | 
		
	
		
			
			|  | 432 | +static int phantom_read_test_mem ( struct phantom_nic *phantom,
 | 
		
	
		
			
			|  | 433 | +				   unsigned long offset ) {
 | 
		
	
		
			
			|  | 434 | +	static union {
 | 
		
	
		
			
			|  | 435 | +		uint8_t bytes[8];
 | 
		
	
		
			
			|  | 436 | +		uint32_t dwords[2];
 | 
		
	
		
			
			|  | 437 | +	} cache;
 | 
		
	
		
			
			|  | 438 | +	static unsigned long cache_offset = -1UL;
 | 
		
	
		
			
			|  | 439 | +	unsigned long sub_offset;
 | 
		
	
		
			
			|  | 440 | +	int rc;
 | 
		
	
		
			
			|  | 441 | +
 | 
		
	
		
			
			|  | 442 | +	sub_offset = ( offset & ( sizeof ( cache ) - 1 ) );
 | 
		
	
		
			
			|  | 443 | +	offset = ( offset & ~( sizeof ( cache ) - 1 ) );
 | 
		
	
		
			
			|  | 444 | +
 | 
		
	
		
			
			|  | 445 | +	if ( cache_offset != offset ) {
 | 
		
	
		
			
			|  | 446 | +		if ( ( rc = phantom_read_test_mem_block ( phantom, offset,
 | 
		
	
		
			
			|  | 447 | +							  cache.dwords )) !=0 )
 | 
		
	
		
			
			|  | 448 | +			return rc;
 | 
		
	
		
			
			|  | 449 | +		cache_offset = offset;
 | 
		
	
		
			
			|  | 450 | +	}
 | 
		
	
		
			
			|  | 451 | +
 | 
		
	
		
			
			|  | 452 | +	return cache.bytes[sub_offset];
 | 
		
	
		
			
			|  | 453 | +}
 | 
		
	
		
			
			|  | 454 | +
 | 
		
	
		
			
			| 424 | 455 |  /**
 | 
		
	
		
			
			| 425 | 456 |   * Dump Phantom firmware dmesg log
 | 
		
	
		
			
			| 426 | 457 |   *
 | 
		
	
		
			
			| 427 | 458 |   * @v phantom		Phantom NIC
 | 
		
	
		
			
			| 428 | 459 |   * @v log		Log number
 | 
		
	
		
			
			|  | 460 | + * @v max_lines		Maximum number of lines to show, or -1 to show all
 | 
		
	
		
			
			|  | 461 | + * @ret rc		Return status code
 | 
		
	
		
			
			| 429 | 462 |   */
 | 
		
	
		
			
			| 430 |  | -static void phantom_dmesg ( struct phantom_nic *phantom, unsigned int log ) {
 | 
		
	
		
			
			|  | 463 | +static int phantom_dmesg ( struct phantom_nic *phantom, unsigned int log,
 | 
		
	
		
			
			|  | 464 | +			    unsigned int max_lines ) {
 | 
		
	
		
			
			| 431 | 465 |  	uint32_t head;
 | 
		
	
		
			
			| 432 | 466 |  	uint32_t tail;
 | 
		
	
		
			
			| 433 | 467 |  	uint32_t len;
 | 
		
	
		
			
			| 434 | 468 |  	uint32_t sig;
 | 
		
	
		
			
			| 435 | 469 |  	uint32_t offset;
 | 
		
	
		
			
			| 436 |  | -	union {
 | 
		
	
		
			
			| 437 |  | -		uint8_t bytes[8];
 | 
		
	
		
			
			| 438 |  | -		uint32_t dwords[2];
 | 
		
	
		
			
			| 439 |  | -	} buf;
 | 
		
	
		
			
			| 440 |  | -	unsigned int i;
 | 
		
	
		
			
			| 441 |  | -	int rc;
 | 
		
	
		
			
			|  | 470 | +	int byte;
 | 
		
	
		
			
			| 442 | 471 |  
 | 
		
	
		
			
			| 443 | 472 |  	/* Optimise out for non-debug builds */
 | 
		
	
		
			
			| 444 | 473 |  	if ( ! DBG_LOG )
 | 
		
	
		
			
			| 445 |  | -		return;
 | 
		
	
		
			
			|  | 474 | +		return 0;
 | 
		
	
		
			
			| 446 | 475 |  
 | 
		
	
		
			
			|  | 476 | +	/* Locate log */
 | 
		
	
		
			
			| 447 | 477 |  	head = phantom_readl ( phantom, UNM_CAM_RAM_DMESG_HEAD ( log ) );
 | 
		
	
		
			
			| 448 | 478 |  	len = phantom_readl ( phantom, UNM_CAM_RAM_DMESG_LEN ( log ) );
 | 
		
	
		
			
			| 449 | 479 |  	tail = phantom_readl ( phantom, UNM_CAM_RAM_DMESG_TAIL ( log ) );
 | 
		
	
	
		
			
			|  | @@ -456,32 +486,37 @@ static void phantom_dmesg ( struct phantom_nic *phantom, unsigned int log ) {
 | 
		
	
		
			
			| 456 | 486 |  		       sig, UNM_CAM_RAM_DMESG_SIG_MAGIC );
 | 
		
	
		
			
			| 457 | 487 |  	}
 | 
		
	
		
			
			| 458 | 488 |  
 | 
		
	
		
			
			| 459 |  | -	for ( offset = head ; offset < tail ; offset += 8 ) {
 | 
		
	
		
			
			| 460 |  | -		if ( ( rc = phantom_read_test_mem ( phantom, offset,
 | 
		
	
		
			
			| 461 |  | -						    buf.dwords ) ) != 0 ) {
 | 
		
	
		
			
			| 462 |  | -			DBGC ( phantom, "Phantom %p could not read from test "
 | 
		
	
		
			
			| 463 |  | -			       "memory: %s\n", phantom, strerror ( rc ) );
 | 
		
	
		
			
			|  | 489 | +	/* Locate start of last (max_lines) lines */
 | 
		
	
		
			
			|  | 490 | +	for ( offset = tail ; offset > head ; offset-- ) {
 | 
		
	
		
			
			|  | 491 | +		if ( ( byte = phantom_read_test_mem ( phantom,
 | 
		
	
		
			
			|  | 492 | +						      ( offset - 1 ) ) ) < 0 )
 | 
		
	
		
			
			|  | 493 | +			return byte;
 | 
		
	
		
			
			|  | 494 | +		if ( ( byte == '\n' ) && ( max_lines-- == 0 ) )
 | 
		
	
		
			
			| 464 | 495 |  			break;
 | 
		
	
		
			
			| 465 |  | -		}
 | 
		
	
		
			
			| 466 |  | -		for ( i = 0 ; ( ( i < sizeof ( buf ) ) &&
 | 
		
	
		
			
			| 467 |  | -				( offset + i ) < tail ) ; i++ ) {
 | 
		
	
		
			
			| 468 |  | -			DBG ( "%c", buf.bytes[i] );
 | 
		
	
		
			
			| 469 |  | -		}
 | 
		
	
		
			
			|  | 496 | +	}
 | 
		
	
		
			
			|  | 497 | +
 | 
		
	
		
			
			|  | 498 | +	/* Print lines */
 | 
		
	
		
			
			|  | 499 | +	for ( ; offset < tail ; offset++ ) {
 | 
		
	
		
			
			|  | 500 | +		if ( ( byte = phantom_read_test_mem ( phantom, offset ) ) < 0 )
 | 
		
	
		
			
			|  | 501 | +			return byte;
 | 
		
	
		
			
			|  | 502 | +		DBG ( "%c", byte );
 | 
		
	
		
			
			| 470 | 503 |  	}
 | 
		
	
		
			
			| 471 | 504 |  	DBG ( "\n" );
 | 
		
	
		
			
			|  | 505 | +	return 0;
 | 
		
	
		
			
			| 472 | 506 |  }
 | 
		
	
		
			
			| 473 | 507 |  
 | 
		
	
		
			
			| 474 | 508 |  /**
 | 
		
	
		
			
			| 475 | 509 |   * Dump Phantom firmware dmesg logs
 | 
		
	
		
			
			| 476 | 510 |   *
 | 
		
	
		
			
			| 477 | 511 |   * @v phantom		Phantom NIC
 | 
		
	
		
			
			|  | 512 | + * @v max_lines		Maximum number of lines to show, or -1 to show all
 | 
		
	
		
			
			| 478 | 513 |   */
 | 
		
	
		
			
			| 479 | 514 |  static void __attribute__ (( unused ))
 | 
		
	
		
			
			| 480 |  | -phantom_dmesg_all ( struct phantom_nic *phantom ) {
 | 
		
	
		
			
			|  | 515 | +phantom_dmesg_all ( struct phantom_nic *phantom, unsigned int max_lines ) {
 | 
		
	
		
			
			| 481 | 516 |  	unsigned int i;
 | 
		
	
		
			
			| 482 | 517 |  
 | 
		
	
		
			
			| 483 | 518 |  	for ( i = 0 ; i < UNM_CAM_RAM_NUM_DMESG_BUFFERS ; i++ )
 | 
		
	
		
			
			| 484 |  | -		phantom_dmesg ( phantom, i );
 | 
		
	
		
			
			|  | 519 | +		phantom_dmesg ( phantom, i, max_lines );
 | 
		
	
		
			
			| 485 | 520 |  }
 | 
		
	
		
			
			| 486 | 521 |  
 | 
		
	
		
			
			| 487 | 522 |  /***************************************************************************
 |