|  | @@ -45,6 +45,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 | 
		
	
		
			
			| 45 | 45 |   *
 | 
		
	
		
			
			| 46 | 46 |   */
 | 
		
	
		
			
			| 47 | 47 |  
 | 
		
	
		
			
			|  | 48 | +static void intelxl_reopen_admin ( struct intelxl_nic *intelxl );
 | 
		
	
		
			
			|  | 49 | +
 | 
		
	
		
			
			| 48 | 50 |  /******************************************************************************
 | 
		
	
		
			
			| 49 | 51 |   *
 | 
		
	
		
			
			| 50 | 52 |   * Device reset
 | 
		
	
	
		
			
			|  | @@ -133,19 +135,16 @@ static const struct intelxl_admin_offsets intelxl_admin_offsets = {
 | 
		
	
		
			
			| 133 | 135 |  };
 | 
		
	
		
			
			| 134 | 136 |  
 | 
		
	
		
			
			| 135 | 137 |  /**
 | 
		
	
		
			
			| 136 |  | - * Create admin queue
 | 
		
	
		
			
			|  | 138 | + * Allocate admin queue
 | 
		
	
		
			
			| 137 | 139 |   *
 | 
		
	
		
			
			| 138 | 140 |   * @v intelxl		Intel device
 | 
		
	
		
			
			| 139 | 141 |   * @v admin		Admin queue
 | 
		
	
		
			
			| 140 | 142 |   * @ret rc		Return status code
 | 
		
	
		
			
			| 141 | 143 |   */
 | 
		
	
		
			
			| 142 |  | -static int intelxl_create_admin ( struct intelxl_nic *intelxl,
 | 
		
	
		
			
			| 143 |  | -				  struct intelxl_admin *admin ) {
 | 
		
	
		
			
			|  | 144 | +static int intelxl_alloc_admin ( struct intelxl_nic *intelxl,
 | 
		
	
		
			
			|  | 145 | +				 struct intelxl_admin *admin ) {
 | 
		
	
		
			
			| 144 | 146 |  	size_t buf_len = ( sizeof ( admin->buf[0] ) * INTELXL_ADMIN_NUM_DESC );
 | 
		
	
		
			
			| 145 | 147 |  	size_t len = ( sizeof ( admin->desc[0] ) * INTELXL_ADMIN_NUM_DESC );
 | 
		
	
		
			
			| 146 |  | -	const struct intelxl_admin_offsets *regs = admin->regs;
 | 
		
	
		
			
			| 147 |  | -	void *admin_regs = ( intelxl->regs + admin->base );
 | 
		
	
		
			
			| 148 |  | -	physaddr_t address;
 | 
		
	
		
			
			| 149 | 148 |  
 | 
		
	
		
			
			| 150 | 149 |  	/* Allocate admin queue */
 | 
		
	
		
			
			| 151 | 150 |  	admin->buf = malloc_dma ( ( buf_len + len ), INTELXL_ALIGN );
 | 
		
	
	
		
			
			|  | @@ -153,6 +152,30 @@ static int intelxl_create_admin ( struct intelxl_nic *intelxl,
 | 
		
	
		
			
			| 153 | 152 |  		return -ENOMEM;
 | 
		
	
		
			
			| 154 | 153 |  	admin->desc = ( ( ( void * ) admin->buf ) + buf_len );
 | 
		
	
		
			
			| 155 | 154 |  
 | 
		
	
		
			
			|  | 155 | +	DBGC ( intelxl, "INTELXL %p A%cQ is at [%08llx,%08llx) buf "
 | 
		
	
		
			
			|  | 156 | +	       "[%08llx,%08llx)\n", intelxl,
 | 
		
	
		
			
			|  | 157 | +	       ( ( admin == &intelxl->command ) ? 'T' : 'R' ),
 | 
		
	
		
			
			|  | 158 | +	       ( ( unsigned long long ) virt_to_bus ( admin->desc ) ),
 | 
		
	
		
			
			|  | 159 | +	       ( ( unsigned long long ) ( virt_to_bus ( admin->desc ) + len ) ),
 | 
		
	
		
			
			|  | 160 | +	       ( ( unsigned long long ) virt_to_bus ( admin->buf ) ),
 | 
		
	
		
			
			|  | 161 | +	       ( ( unsigned long long ) ( virt_to_bus ( admin->buf ) +
 | 
		
	
		
			
			|  | 162 | +					  buf_len ) ) );
 | 
		
	
		
			
			|  | 163 | +	return 0;
 | 
		
	
		
			
			|  | 164 | +}
 | 
		
	
		
			
			|  | 165 | +
 | 
		
	
		
			
			|  | 166 | +/**
 | 
		
	
		
			
			|  | 167 | + * Enable admin queue
 | 
		
	
		
			
			|  | 168 | + *
 | 
		
	
		
			
			|  | 169 | + * @v intelxl		Intel device
 | 
		
	
		
			
			|  | 170 | + * @v admin		Admin queue
 | 
		
	
		
			
			|  | 171 | + */
 | 
		
	
		
			
			|  | 172 | +static void intelxl_enable_admin ( struct intelxl_nic *intelxl,
 | 
		
	
		
			
			|  | 173 | +				   struct intelxl_admin *admin ) {
 | 
		
	
		
			
			|  | 174 | +	size_t len = ( sizeof ( admin->desc[0] ) * INTELXL_ADMIN_NUM_DESC );
 | 
		
	
		
			
			|  | 175 | +	const struct intelxl_admin_offsets *regs = admin->regs;
 | 
		
	
		
			
			|  | 176 | +	void *admin_regs = ( intelxl->regs + admin->base );
 | 
		
	
		
			
			|  | 177 | +	physaddr_t address;
 | 
		
	
		
			
			|  | 178 | +
 | 
		
	
		
			
			| 156 | 179 |  	/* Initialise admin queue */
 | 
		
	
		
			
			| 157 | 180 |  	memset ( admin->desc, 0, len );
 | 
		
	
		
			
			| 158 | 181 |  
 | 
		
	
	
		
			
			|  | @@ -177,33 +200,33 @@ static int intelxl_create_admin ( struct intelxl_nic *intelxl,
 | 
		
	
		
			
			| 177 | 200 |  	writel ( ( INTELXL_ADMIN_LEN_LEN ( INTELXL_ADMIN_NUM_DESC ) |
 | 
		
	
		
			
			| 178 | 201 |  		   INTELXL_ADMIN_LEN_ENABLE ),
 | 
		
	
		
			
			| 179 | 202 |  		 admin_regs + regs->len );
 | 
		
	
		
			
			| 180 |  | -
 | 
		
	
		
			
			| 181 |  | -	DBGC ( intelxl, "INTELXL %p A%cQ is at [%08llx,%08llx) buf "
 | 
		
	
		
			
			| 182 |  | -	       "[%08llx,%08llx)\n", intelxl,
 | 
		
	
		
			
			| 183 |  | -	       ( ( admin == &intelxl->command ) ? 'T' : 'R' ),
 | 
		
	
		
			
			| 184 |  | -	       ( ( unsigned long long ) address ),
 | 
		
	
		
			
			| 185 |  | -	       ( ( unsigned long long ) address + len ),
 | 
		
	
		
			
			| 186 |  | -	       ( ( unsigned long long ) virt_to_bus ( admin->buf ) ),
 | 
		
	
		
			
			| 187 |  | -	       ( ( unsigned long long ) ( virt_to_bus ( admin->buf ) +
 | 
		
	
		
			
			| 188 |  | -					  buf_len ) ) );
 | 
		
	
		
			
			| 189 |  | -	return 0;
 | 
		
	
		
			
			| 190 | 203 |  }
 | 
		
	
		
			
			| 191 | 204 |  
 | 
		
	
		
			
			| 192 | 205 |  /**
 | 
		
	
		
			
			| 193 |  | - * Destroy admin queue
 | 
		
	
		
			
			|  | 206 | + * Disable admin queue
 | 
		
	
		
			
			| 194 | 207 |   *
 | 
		
	
		
			
			| 195 | 208 |   * @v intelxl		Intel device
 | 
		
	
		
			
			| 196 | 209 |   * @v admin		Admin queue
 | 
		
	
		
			
			| 197 | 210 |   */
 | 
		
	
		
			
			| 198 |  | -static void intelxl_destroy_admin ( struct intelxl_nic *intelxl,
 | 
		
	
		
			
			|  | 211 | +static void intelxl_disable_admin ( struct intelxl_nic *intelxl,
 | 
		
	
		
			
			| 199 | 212 |  				    struct intelxl_admin *admin ) {
 | 
		
	
		
			
			| 200 |  | -	size_t buf_len = ( sizeof ( admin->buf[0] ) * INTELXL_ADMIN_NUM_DESC );
 | 
		
	
		
			
			| 201 |  | -	size_t len = ( sizeof ( admin->desc[0] ) * INTELXL_ADMIN_NUM_DESC );
 | 
		
	
		
			
			| 202 | 213 |  	const struct intelxl_admin_offsets *regs = admin->regs;
 | 
		
	
		
			
			| 203 | 214 |  	void *admin_regs = ( intelxl->regs + admin->base );
 | 
		
	
		
			
			| 204 | 215 |  
 | 
		
	
		
			
			| 205 | 216 |  	/* Disable queue */
 | 
		
	
		
			
			| 206 | 217 |  	writel ( 0, admin_regs + regs->len );
 | 
		
	
		
			
			|  | 218 | +}
 | 
		
	
		
			
			|  | 219 | +
 | 
		
	
		
			
			|  | 220 | +/**
 | 
		
	
		
			
			|  | 221 | + * Free admin queue
 | 
		
	
		
			
			|  | 222 | + *
 | 
		
	
		
			
			|  | 223 | + * @v intelxl		Intel device
 | 
		
	
		
			
			|  | 224 | + * @v admin		Admin queue
 | 
		
	
		
			
			|  | 225 | + */
 | 
		
	
		
			
			|  | 226 | +static void intelxl_free_admin ( struct intelxl_nic *intelxl __unused,
 | 
		
	
		
			
			|  | 227 | +				 struct intelxl_admin *admin ) {
 | 
		
	
		
			
			|  | 228 | +	size_t buf_len = ( sizeof ( admin->buf[0] ) * INTELXL_ADMIN_NUM_DESC );
 | 
		
	
		
			
			|  | 229 | +	size_t len = ( sizeof ( admin->desc[0] ) * INTELXL_ADMIN_NUM_DESC );
 | 
		
	
		
			
			| 207 | 230 |  
 | 
		
	
		
			
			| 208 | 231 |  	/* Free queue */
 | 
		
	
		
			
			| 209 | 232 |  	free_dma ( admin->buf, ( buf_len + len ) );
 | 
		
	
	
		
			
			|  | @@ -705,23 +728,18 @@ static void intelxl_poll_admin ( struct net_device *netdev ) {
 | 
		
	
		
			
			| 705 | 728 |   * @ret rc		Return status code
 | 
		
	
		
			
			| 706 | 729 |   */
 | 
		
	
		
			
			| 707 | 730 |  static int intelxl_open_admin ( struct intelxl_nic *intelxl ) {
 | 
		
	
		
			
			| 708 |  | -	unsigned int i;
 | 
		
	
		
			
			| 709 | 731 |  	int rc;
 | 
		
	
		
			
			| 710 | 732 |  
 | 
		
	
		
			
			| 711 |  | -	/* Create admin event queue */
 | 
		
	
		
			
			| 712 |  | -	if ( ( rc = intelxl_create_admin ( intelxl, &intelxl->event ) ) != 0 )
 | 
		
	
		
			
			| 713 |  | -		goto err_create_event;
 | 
		
	
		
			
			|  | 733 | +	/* Allocate admin event queue */
 | 
		
	
		
			
			|  | 734 | +	if ( ( rc = intelxl_alloc_admin ( intelxl, &intelxl->event ) ) != 0 )
 | 
		
	
		
			
			|  | 735 | +		goto err_alloc_event;
 | 
		
	
		
			
			| 714 | 736 |  
 | 
		
	
		
			
			| 715 |  | -	/* Create admin command queue */
 | 
		
	
		
			
			| 716 |  | -	if ( ( rc = intelxl_create_admin ( intelxl, &intelxl->command ) ) != 0 )
 | 
		
	
		
			
			| 717 |  | -		goto err_create_command;
 | 
		
	
		
			
			| 718 |  | -
 | 
		
	
		
			
			| 719 |  | -	/* Initialise all admin event queue descriptors */
 | 
		
	
		
			
			| 720 |  | -	for ( i = 0 ; i < INTELXL_ADMIN_NUM_DESC ; i++ )
 | 
		
	
		
			
			| 721 |  | -		intelxl_admin_event_init ( intelxl, i );
 | 
		
	
		
			
			|  | 737 | +	/* Allocate admin command queue */
 | 
		
	
		
			
			|  | 738 | +	if ( ( rc = intelxl_alloc_admin ( intelxl, &intelxl->command ) ) != 0 )
 | 
		
	
		
			
			|  | 739 | +		goto err_alloc_command;
 | 
		
	
		
			
			| 722 | 740 |  
 | 
		
	
		
			
			| 723 |  | -	/* Post all descriptors to event queue */
 | 
		
	
		
			
			| 724 |  | -	intelxl_refill_admin ( intelxl );
 | 
		
	
		
			
			|  | 741 | +	/* (Re)open admin queues */
 | 
		
	
		
			
			|  | 742 | +	intelxl_reopen_admin ( intelxl );
 | 
		
	
		
			
			| 725 | 743 |  
 | 
		
	
		
			
			| 726 | 744 |  	/* Get firmware version */
 | 
		
	
		
			
			| 727 | 745 |  	if ( ( rc = intelxl_admin_version ( intelxl ) ) != 0 )
 | 
		
	
	
		
			
			|  | @@ -735,13 +753,37 @@ static int intelxl_open_admin ( struct intelxl_nic *intelxl ) {
 | 
		
	
		
			
			| 735 | 753 |  
 | 
		
	
		
			
			| 736 | 754 |   err_driver:
 | 
		
	
		
			
			| 737 | 755 |   err_version:
 | 
		
	
		
			
			| 738 |  | -	intelxl_destroy_admin ( intelxl, &intelxl->command );
 | 
		
	
		
			
			| 739 |  | - err_create_command:
 | 
		
	
		
			
			| 740 |  | -	intelxl_destroy_admin ( intelxl, &intelxl->event );
 | 
		
	
		
			
			| 741 |  | - err_create_event:
 | 
		
	
		
			
			|  | 756 | +	intelxl_disable_admin ( intelxl, &intelxl->command );
 | 
		
	
		
			
			|  | 757 | +	intelxl_disable_admin ( intelxl, &intelxl->event );
 | 
		
	
		
			
			|  | 758 | +	intelxl_free_admin ( intelxl, &intelxl->command );
 | 
		
	
		
			
			|  | 759 | + err_alloc_command:
 | 
		
	
		
			
			|  | 760 | +	intelxl_free_admin ( intelxl, &intelxl->event );
 | 
		
	
		
			
			|  | 761 | + err_alloc_event:
 | 
		
	
		
			
			| 742 | 762 |  	return rc;
 | 
		
	
		
			
			| 743 | 763 |  }
 | 
		
	
		
			
			| 744 | 764 |  
 | 
		
	
		
			
			|  | 765 | +/**
 | 
		
	
		
			
			|  | 766 | + * Reopen admin queues (after virtual function reset)
 | 
		
	
		
			
			|  | 767 | + *
 | 
		
	
		
			
			|  | 768 | + * @v intelxl		Intel device
 | 
		
	
		
			
			|  | 769 | + */
 | 
		
	
		
			
			|  | 770 | +static void intelxl_reopen_admin ( struct intelxl_nic *intelxl ) {
 | 
		
	
		
			
			|  | 771 | +	unsigned int i;
 | 
		
	
		
			
			|  | 772 | +
 | 
		
	
		
			
			|  | 773 | +	/* Enable admin event queue */
 | 
		
	
		
			
			|  | 774 | +	intelxl_enable_admin ( intelxl, &intelxl->event );
 | 
		
	
		
			
			|  | 775 | +
 | 
		
	
		
			
			|  | 776 | +	/* Enable admin command queue */
 | 
		
	
		
			
			|  | 777 | +	intelxl_enable_admin ( intelxl, &intelxl->command );
 | 
		
	
		
			
			|  | 778 | +
 | 
		
	
		
			
			|  | 779 | +	/* Initialise all admin event queue descriptors */
 | 
		
	
		
			
			|  | 780 | +	for ( i = 0 ; i < INTELXL_ADMIN_NUM_DESC ; i++ )
 | 
		
	
		
			
			|  | 781 | +		intelxl_admin_event_init ( intelxl, i );
 | 
		
	
		
			
			|  | 782 | +
 | 
		
	
		
			
			|  | 783 | +	/* Post all descriptors to event queue */
 | 
		
	
		
			
			|  | 784 | +	intelxl_refill_admin ( intelxl );
 | 
		
	
		
			
			|  | 785 | +}
 | 
		
	
		
			
			|  | 786 | +
 | 
		
	
		
			
			| 745 | 787 |  /**
 | 
		
	
		
			
			| 746 | 788 |   * Close admin queues
 | 
		
	
		
			
			| 747 | 789 |   *
 | 
		
	
	
		
			
			|  | @@ -752,11 +794,13 @@ static void intelxl_close_admin ( struct intelxl_nic *intelxl ) {
 | 
		
	
		
			
			| 752 | 794 |  	/* Shut down admin queues */
 | 
		
	
		
			
			| 753 | 795 |  	intelxl_admin_shutdown ( intelxl );
 | 
		
	
		
			
			| 754 | 796 |  
 | 
		
	
		
			
			| 755 |  | -	/* Destroy admin command queue */
 | 
		
	
		
			
			| 756 |  | -	intelxl_destroy_admin ( intelxl, &intelxl->command );
 | 
		
	
		
			
			|  | 797 | +	/* Disable admin queues */
 | 
		
	
		
			
			|  | 798 | +	intelxl_disable_admin ( intelxl, &intelxl->command );
 | 
		
	
		
			
			|  | 799 | +	intelxl_disable_admin ( intelxl, &intelxl->event );
 | 
		
	
		
			
			| 757 | 800 |  
 | 
		
	
		
			
			| 758 |  | -	/* Destroy admin event queue */
 | 
		
	
		
			
			| 759 |  | -	intelxl_destroy_admin ( intelxl, &intelxl->event );
 | 
		
	
		
			
			|  | 801 | +	/* Free admin queues */
 | 
		
	
		
			
			|  | 802 | +	intelxl_free_admin ( intelxl, &intelxl->command );
 | 
		
	
		
			
			|  | 803 | +	intelxl_free_admin ( intelxl, &intelxl->event );
 | 
		
	
		
			
			| 760 | 804 |  }
 | 
		
	
		
			
			| 761 | 805 |  
 | 
		
	
		
			
			| 762 | 806 |  /******************************************************************************
 |