|  | @@ -35,14 +35,14 @@ FILE_LICENCE ( GPL2_OR_LATER );
 | 
		
	
		
			
			| 35 | 35 |   *
 | 
		
	
		
			
			| 36 | 36 |   */
 | 
		
	
		
			
			| 37 | 37 |  
 | 
		
	
		
			
			|  | 38 | +/** Ring refill profiler */
 | 
		
	
		
			
			|  | 39 | +static struct profiler ncm_refill_profiler __profiler =
 | 
		
	
		
			
			|  | 40 | +	{ .name = "ncm.refill" };
 | 
		
	
		
			
			|  | 41 | +
 | 
		
	
		
			
			| 38 | 42 |  /** Interrupt completion profiler */
 | 
		
	
		
			
			| 39 | 43 |  static struct profiler ncm_intr_profiler __profiler =
 | 
		
	
		
			
			| 40 | 44 |  	{ .name = "ncm.intr" };
 | 
		
	
		
			
			| 41 | 45 |  
 | 
		
	
		
			
			| 42 |  | -/** Interrupt refill profiler */
 | 
		
	
		
			
			| 43 |  | -static struct profiler ncm_intr_refill_profiler __profiler =
 | 
		
	
		
			
			| 44 |  | -	{ .name = "ncm.intr_refill" };
 | 
		
	
		
			
			| 45 |  | -
 | 
		
	
		
			
			| 46 | 46 |  /** Bulk IN completion profiler */
 | 
		
	
		
			
			| 47 | 47 |  static struct profiler ncm_in_profiler __profiler =
 | 
		
	
		
			
			| 48 | 48 |  	{ .name = "ncm.in" };
 | 
		
	
	
		
			
			|  | @@ -51,55 +51,155 @@ static struct profiler ncm_in_profiler __profiler =
 | 
		
	
		
			
			| 51 | 51 |  static struct profiler ncm_in_datagram_profiler __profiler =
 | 
		
	
		
			
			| 52 | 52 |  	{ .name = "ncm.in_dgram" };
 | 
		
	
		
			
			| 53 | 53 |  
 | 
		
	
		
			
			| 54 |  | -/** Bulk IN refill profiler */
 | 
		
	
		
			
			| 55 |  | -static struct profiler ncm_in_refill_profiler __profiler =
 | 
		
	
		
			
			| 56 |  | -	{ .name = "ncm.in_refill" };
 | 
		
	
		
			
			| 57 |  | -
 | 
		
	
		
			
			| 58 | 54 |  /** Bulk OUT profiler */
 | 
		
	
		
			
			| 59 | 55 |  static struct profiler ncm_out_profiler __profiler =
 | 
		
	
		
			
			| 60 | 56 |  	{ .name = "ncm.out" };
 | 
		
	
		
			
			| 61 | 57 |  
 | 
		
	
		
			
			| 62 | 58 |  /******************************************************************************
 | 
		
	
		
			
			| 63 | 59 |   *
 | 
		
	
		
			
			| 64 |  | - * CDC-NCM communications interface
 | 
		
	
		
			
			|  | 60 | + * Ring management
 | 
		
	
		
			
			| 65 | 61 |   *
 | 
		
	
		
			
			| 66 | 62 |   ******************************************************************************
 | 
		
	
		
			
			| 67 | 63 |   */
 | 
		
	
		
			
			| 68 | 64 |  
 | 
		
	
		
			
			| 69 | 65 |  /**
 | 
		
	
		
			
			| 70 |  | - * Refill interrupt ring
 | 
		
	
		
			
			|  | 66 | + * Transcribe receive ring name (for debugging)
 | 
		
	
		
			
			|  | 67 | + *
 | 
		
	
		
			
			|  | 68 | + * @v ncm		CDC-NCM device
 | 
		
	
		
			
			|  | 69 | + * @v ring		Receive ring
 | 
		
	
		
			
			|  | 70 | + * @ret name		Receive ring name
 | 
		
	
		
			
			|  | 71 | + */
 | 
		
	
		
			
			|  | 72 | +static inline const char * ncm_rx_name ( struct ncm_device *ncm,
 | 
		
	
		
			
			|  | 73 | +					 struct ncm_rx_ring *ring ) {
 | 
		
	
		
			
			|  | 74 | +	if ( ring == &ncm->intr ) {
 | 
		
	
		
			
			|  | 75 | +		return "interrupt";
 | 
		
	
		
			
			|  | 76 | +	} else if ( ring == &ncm->in ) {
 | 
		
	
		
			
			|  | 77 | +		return "bulk IN";
 | 
		
	
		
			
			|  | 78 | +	} else {
 | 
		
	
		
			
			|  | 79 | +		return "UNKNOWN";
 | 
		
	
		
			
			|  | 80 | +	}
 | 
		
	
		
			
			|  | 81 | +}
 | 
		
	
		
			
			|  | 82 | +
 | 
		
	
		
			
			|  | 83 | +/**
 | 
		
	
		
			
			|  | 84 | + * Allocate receive ring buffers
 | 
		
	
		
			
			|  | 85 | + *
 | 
		
	
		
			
			|  | 86 | + * @v ncm		CDC-NCM device
 | 
		
	
		
			
			|  | 87 | + * @v ring		Receive ring
 | 
		
	
		
			
			|  | 88 | + * @v mtu		I/O buffer size
 | 
		
	
		
			
			|  | 89 | + * @v count		Number of I/O buffers
 | 
		
	
		
			
			|  | 90 | + * @ret rc		Return status code
 | 
		
	
		
			
			|  | 91 | + */
 | 
		
	
		
			
			|  | 92 | +static int ncm_rx_alloc ( struct ncm_device *ncm, struct ncm_rx_ring *ring,
 | 
		
	
		
			
			|  | 93 | +			  size_t mtu, unsigned int count ) {
 | 
		
	
		
			
			|  | 94 | +	struct io_buffer *iobuf;
 | 
		
	
		
			
			|  | 95 | +	struct io_buffer *tmp;
 | 
		
	
		
			
			|  | 96 | +	unsigned int i;
 | 
		
	
		
			
			|  | 97 | +	int rc;
 | 
		
	
		
			
			|  | 98 | +
 | 
		
	
		
			
			|  | 99 | +	/* Initialise ring */
 | 
		
	
		
			
			|  | 100 | +	ring->mtu = mtu;
 | 
		
	
		
			
			|  | 101 | +	INIT_LIST_HEAD ( &ring->list );
 | 
		
	
		
			
			|  | 102 | +
 | 
		
	
		
			
			|  | 103 | +	/* Allocate I/O buffers */
 | 
		
	
		
			
			|  | 104 | +	for ( i = 0 ; i < count ; i++ ) {
 | 
		
	
		
			
			|  | 105 | +		iobuf = alloc_iob ( mtu );
 | 
		
	
		
			
			|  | 106 | +		if ( ! iobuf ) {
 | 
		
	
		
			
			|  | 107 | +			DBGC ( ncm, "NCM %p could not allocate %dx %zd-byte "
 | 
		
	
		
			
			|  | 108 | +			       "buffers for %s\n", ncm, count, mtu,
 | 
		
	
		
			
			|  | 109 | +			       ncm_rx_name ( ncm, ring ) );
 | 
		
	
		
			
			|  | 110 | +			rc = -ENOMEM;
 | 
		
	
		
			
			|  | 111 | +			goto err_alloc;
 | 
		
	
		
			
			|  | 112 | +		}
 | 
		
	
		
			
			|  | 113 | +		list_add ( &iobuf->list, &ring->list );
 | 
		
	
		
			
			|  | 114 | +	}
 | 
		
	
		
			
			|  | 115 | +
 | 
		
	
		
			
			|  | 116 | +	return 0;
 | 
		
	
		
			
			|  | 117 | +
 | 
		
	
		
			
			|  | 118 | + err_alloc:
 | 
		
	
		
			
			|  | 119 | +	list_for_each_entry_safe ( iobuf, tmp, &ring->list, list ) {
 | 
		
	
		
			
			|  | 120 | +		list_del ( &iobuf->list );
 | 
		
	
		
			
			|  | 121 | +		free_iob ( iobuf );
 | 
		
	
		
			
			|  | 122 | +	}
 | 
		
	
		
			
			|  | 123 | +	return rc;
 | 
		
	
		
			
			|  | 124 | +}
 | 
		
	
		
			
			|  | 125 | +
 | 
		
	
		
			
			|  | 126 | +/**
 | 
		
	
		
			
			|  | 127 | + * Refill receive ring
 | 
		
	
		
			
			| 71 | 128 |   *
 | 
		
	
		
			
			| 72 | 129 |   * @v ncm		CDC-NCM device
 | 
		
	
		
			
			|  | 130 | + * @v ring		Receive ring
 | 
		
	
		
			
			|  | 131 | + * @ret rc		Return status code
 | 
		
	
		
			
			| 73 | 132 |   */
 | 
		
	
		
			
			| 74 |  | -static void ncm_intr_refill ( struct ncm_device *ncm ) {
 | 
		
	
		
			
			|  | 133 | +static int ncm_rx_refill ( struct ncm_device *ncm, struct ncm_rx_ring *ring ) {
 | 
		
	
		
			
			| 75 | 134 |  	struct io_buffer *iobuf;
 | 
		
	
		
			
			| 76 |  | -	size_t mtu = ncm->intr.mtu;
 | 
		
	
		
			
			| 77 | 135 |  	int rc;
 | 
		
	
		
			
			| 78 | 136 |  
 | 
		
	
		
			
			| 79 |  | -	/* Enqueue any available I/O buffers */
 | 
		
	
		
			
			| 80 |  | -	while ( ( iobuf = list_first_entry ( &ncm->intrs, struct io_buffer,
 | 
		
	
		
			
			|  | 137 | +	/* Enqueue any recycled I/O buffers */
 | 
		
	
		
			
			|  | 138 | +	while ( ( iobuf = list_first_entry ( &ring->list, struct io_buffer,
 | 
		
	
		
			
			| 81 | 139 |  					     list ) ) ) {
 | 
		
	
		
			
			| 82 | 140 |  
 | 
		
	
		
			
			| 83 | 141 |  		/* Profile refill */
 | 
		
	
		
			
			| 84 |  | -		profile_start ( &ncm_intr_refill_profiler );
 | 
		
	
		
			
			|  | 142 | +		profile_start ( &ncm_refill_profiler );
 | 
		
	
		
			
			| 85 | 143 |  
 | 
		
	
		
			
			| 86 | 144 |  		/* Reset size */
 | 
		
	
		
			
			| 87 |  | -		iob_put ( iobuf, ( mtu - iob_len ( iobuf ) ) );
 | 
		
	
		
			
			|  | 145 | +		iob_put ( iobuf, ( ring->mtu - iob_len ( iobuf ) ) );
 | 
		
	
		
			
			| 88 | 146 |  
 | 
		
	
		
			
			| 89 | 147 |  		/* Enqueue I/O buffer */
 | 
		
	
		
			
			| 90 |  | -		if ( ( rc = usb_stream ( &ncm->intr, iobuf ) ) != 0 ) {
 | 
		
	
		
			
			| 91 |  | -			DBGC ( ncm, "NCM %p could not enqueue interrupt: %s\n",
 | 
		
	
		
			
			| 92 |  | -			       ncm, strerror ( rc ) );
 | 
		
	
		
			
			| 93 |  | -			/* Leave in available list and wait for next refill */
 | 
		
	
		
			
			| 94 |  | -			return;
 | 
		
	
		
			
			|  | 148 | +		if ( ( rc = usb_stream ( &ring->ep, iobuf ) ) != 0 ) {
 | 
		
	
		
			
			|  | 149 | +			DBGC ( ncm, "NCM %p could not enqueue %s: %s\n", ncm,
 | 
		
	
		
			
			|  | 150 | +			       ncm_rx_name ( ncm, ring ), strerror ( rc ) );
 | 
		
	
		
			
			|  | 151 | +			/* Leave in recycled list and wait for next refill */
 | 
		
	
		
			
			|  | 152 | +			return rc;
 | 
		
	
		
			
			| 95 | 153 |  		}
 | 
		
	
		
			
			| 96 | 154 |  
 | 
		
	
		
			
			| 97 |  | -		/* Remove from available list */
 | 
		
	
		
			
			|  | 155 | +		/* Remove from recycled list */
 | 
		
	
		
			
			| 98 | 156 |  		list_del ( &iobuf->list );
 | 
		
	
		
			
			| 99 |  | -		profile_stop ( &ncm_intr_refill_profiler );
 | 
		
	
		
			
			|  | 157 | +		profile_stop ( &ncm_refill_profiler );
 | 
		
	
		
			
			| 100 | 158 |  	}
 | 
		
	
		
			
			|  | 159 | +
 | 
		
	
		
			
			|  | 160 | +	return 0;
 | 
		
	
		
			
			|  | 161 | +}
 | 
		
	
		
			
			|  | 162 | +
 | 
		
	
		
			
			|  | 163 | +/**
 | 
		
	
		
			
			|  | 164 | + * Recycle receive buffer
 | 
		
	
		
			
			|  | 165 | + *
 | 
		
	
		
			
			|  | 166 | + * @v ncm		CDC-NCM device
 | 
		
	
		
			
			|  | 167 | + * @v ring		Receive ring
 | 
		
	
		
			
			|  | 168 | + * @v iobuf		I/O buffer
 | 
		
	
		
			
			|  | 169 | + */
 | 
		
	
		
			
			|  | 170 | +static inline void ncm_rx_recycle ( struct ncm_device *ncm __unused,
 | 
		
	
		
			
			|  | 171 | +				    struct ncm_rx_ring *ring,
 | 
		
	
		
			
			|  | 172 | +				    struct io_buffer *iobuf ) {
 | 
		
	
		
			
			|  | 173 | +
 | 
		
	
		
			
			|  | 174 | +	/* Add to recycled list */
 | 
		
	
		
			
			|  | 175 | +	list_add_tail ( &iobuf->list, &ring->list );
 | 
		
	
		
			
			| 101 | 176 |  }
 | 
		
	
		
			
			| 102 | 177 |  
 | 
		
	
		
			
			|  | 178 | +/**
 | 
		
	
		
			
			|  | 179 | + * Free receive ring
 | 
		
	
		
			
			|  | 180 | + *
 | 
		
	
		
			
			|  | 181 | + * @v ncm		CDC-NCM device
 | 
		
	
		
			
			|  | 182 | + * @v ring		Receive ring
 | 
		
	
		
			
			|  | 183 | + */
 | 
		
	
		
			
			|  | 184 | +static void ncm_rx_free ( struct ncm_device *ncm __unused,
 | 
		
	
		
			
			|  | 185 | +			  struct ncm_rx_ring *ring ) {
 | 
		
	
		
			
			|  | 186 | +	struct io_buffer *iobuf;
 | 
		
	
		
			
			|  | 187 | +	struct io_buffer *tmp;
 | 
		
	
		
			
			|  | 188 | +
 | 
		
	
		
			
			|  | 189 | +	/* Free I/O buffers */
 | 
		
	
		
			
			|  | 190 | +	list_for_each_entry_safe ( iobuf, tmp, &ring->list, list ) {
 | 
		
	
		
			
			|  | 191 | +		list_del ( &iobuf->list );
 | 
		
	
		
			
			|  | 192 | +		free_iob ( iobuf );
 | 
		
	
		
			
			|  | 193 | +	}
 | 
		
	
		
			
			|  | 194 | +}
 | 
		
	
		
			
			|  | 195 | +
 | 
		
	
		
			
			|  | 196 | +/******************************************************************************
 | 
		
	
		
			
			|  | 197 | + *
 | 
		
	
		
			
			|  | 198 | + * CDC-NCM communications interface
 | 
		
	
		
			
			|  | 199 | + *
 | 
		
	
		
			
			|  | 200 | + ******************************************************************************
 | 
		
	
		
			
			|  | 201 | + */
 | 
		
	
		
			
			|  | 202 | +
 | 
		
	
		
			
			| 103 | 203 |  /**
 | 
		
	
		
			
			| 104 | 204 |   * Complete interrupt transfer
 | 
		
	
		
			
			| 105 | 205 |   *
 | 
		
	
	
		
			
			|  | @@ -109,7 +209,7 @@ static void ncm_intr_refill ( struct ncm_device *ncm ) {
 | 
		
	
		
			
			| 109 | 209 |   */
 | 
		
	
		
			
			| 110 | 210 |  static void ncm_intr_complete ( struct usb_endpoint *ep,
 | 
		
	
		
			
			| 111 | 211 |  				struct io_buffer *iobuf, int rc ) {
 | 
		
	
		
			
			| 112 |  | -	struct ncm_device *ncm = container_of ( ep, struct ncm_device, intr );
 | 
		
	
		
			
			|  | 212 | +	struct ncm_device *ncm = container_of ( ep, struct ncm_device, intr.ep);
 | 
		
	
		
			
			| 113 | 213 |  	struct net_device *netdev = ncm->netdev;
 | 
		
	
		
			
			| 114 | 214 |  	struct usb_setup_packet *message;
 | 
		
	
		
			
			| 115 | 215 |  	size_t len = iob_len ( iobuf );
 | 
		
	
	
		
			
			|  | @@ -161,8 +261,8 @@ static void ncm_intr_complete ( struct usb_endpoint *ep,
 | 
		
	
		
			
			| 161 | 261 |  	}
 | 
		
	
		
			
			| 162 | 262 |  
 | 
		
	
		
			
			| 163 | 263 |   done:
 | 
		
	
		
			
			| 164 |  | -	/* Return I/O buffer to available list */
 | 
		
	
		
			
			| 165 |  | -	list_add_tail ( &iobuf->list, &ncm->intrs );
 | 
		
	
		
			
			|  | 264 | +	/* Recycle buffer */
 | 
		
	
		
			
			|  | 265 | +	ncm_rx_recycle ( ncm, &ncm->intr, iobuf );
 | 
		
	
		
			
			| 166 | 266 |  	profile_stop ( &ncm_intr_profiler );
 | 
		
	
		
			
			| 167 | 267 |  }
 | 
		
	
		
			
			| 168 | 268 |  
 | 
		
	
	
		
			
			|  | @@ -178,23 +278,18 @@ static struct usb_endpoint_driver_operations ncm_intr_operations = {
 | 
		
	
		
			
			| 178 | 278 |   * @ret rc		Return status code
 | 
		
	
		
			
			| 179 | 279 |   */
 | 
		
	
		
			
			| 180 | 280 |  static int ncm_comms_open ( struct ncm_device *ncm ) {
 | 
		
	
		
			
			| 181 |  | -	struct io_buffer *iobuf;
 | 
		
	
		
			
			| 182 |  | -	struct io_buffer *tmp;
 | 
		
	
		
			
			| 183 |  | -	unsigned int i;
 | 
		
	
		
			
			| 184 | 281 |  	int rc;
 | 
		
	
		
			
			| 185 | 282 |  
 | 
		
	
		
			
			| 186 | 283 |  	/* Allocate I/O buffers */
 | 
		
	
		
			
			| 187 |  | -	for ( i = 0 ; i < NCM_INTR_FILL ; i++ ) {
 | 
		
	
		
			
			| 188 |  | -		iobuf = alloc_iob ( ncm->intr.mtu );
 | 
		
	
		
			
			| 189 |  | -		if ( ! iobuf ) {
 | 
		
	
		
			
			| 190 |  | -			rc = -ENOMEM;
 | 
		
	
		
			
			| 191 |  | -			goto err_alloc_iob;
 | 
		
	
		
			
			| 192 |  | -		}
 | 
		
	
		
			
			| 193 |  | -		list_add ( &iobuf->list, &ncm->intrs );
 | 
		
	
		
			
			|  | 284 | +	if ( ( rc = ncm_rx_alloc ( ncm, &ncm->intr, ncm->intr.ep.mtu,
 | 
		
	
		
			
			|  | 285 | +				   NCM_INTR_COUNT ) ) != 0 ) {
 | 
		
	
		
			
			|  | 286 | +		DBGC ( ncm, "NCM %p could not allocate RX buffers: %s\n",
 | 
		
	
		
			
			|  | 287 | +		       ncm, strerror ( rc ) );
 | 
		
	
		
			
			|  | 288 | +		goto err_alloc;
 | 
		
	
		
			
			| 194 | 289 |  	}
 | 
		
	
		
			
			| 195 | 290 |  
 | 
		
	
		
			
			| 196 | 291 |  	/* Open interrupt endpoint */
 | 
		
	
		
			
			| 197 |  | -	if ( ( rc = usb_endpoint_open ( &ncm->intr ) ) != 0 ) {
 | 
		
	
		
			
			|  | 292 | +	if ( ( rc = usb_endpoint_open ( &ncm->intr.ep ) ) != 0 ) {
 | 
		
	
		
			
			| 198 | 293 |  		DBGC ( ncm, "NCM %p could not open interrupt: %s\n",
 | 
		
	
		
			
			| 199 | 294 |  		       ncm, strerror ( rc ) );
 | 
		
	
		
			
			| 200 | 295 |  		goto err_open;
 | 
		
	
	
		
			
			|  | @@ -202,13 +297,10 @@ static int ncm_comms_open ( struct ncm_device *ncm ) {
 | 
		
	
		
			
			| 202 | 297 |  
 | 
		
	
		
			
			| 203 | 298 |  	return 0;
 | 
		
	
		
			
			| 204 | 299 |  
 | 
		
	
		
			
			| 205 |  | -	usb_endpoint_close ( &ncm->intr );
 | 
		
	
		
			
			|  | 300 | +	usb_endpoint_close ( &ncm->intr.ep );
 | 
		
	
		
			
			| 206 | 301 |   err_open:
 | 
		
	
		
			
			| 207 |  | - err_alloc_iob:
 | 
		
	
		
			
			| 208 |  | -	list_for_each_entry_safe ( iobuf, tmp, &ncm->intrs, list ) {
 | 
		
	
		
			
			| 209 |  | -		list_del ( &iobuf->list );
 | 
		
	
		
			
			| 210 |  | -		free_iob ( iobuf );
 | 
		
	
		
			
			| 211 |  | -	}
 | 
		
	
		
			
			|  | 302 | +	ncm_rx_free ( ncm, &ncm->intr );
 | 
		
	
		
			
			|  | 303 | + err_alloc:
 | 
		
	
		
			
			| 212 | 304 |  	return rc;
 | 
		
	
		
			
			| 213 | 305 |  }
 | 
		
	
		
			
			| 214 | 306 |  
 | 
		
	
	
		
			
			|  | @@ -218,17 +310,12 @@ static int ncm_comms_open ( struct ncm_device *ncm ) {
 | 
		
	
		
			
			| 218 | 310 |   * @v ncm		CDC-NCM device
 | 
		
	
		
			
			| 219 | 311 |   */
 | 
		
	
		
			
			| 220 | 312 |  static void ncm_comms_close ( struct ncm_device *ncm ) {
 | 
		
	
		
			
			| 221 |  | -	struct io_buffer *iobuf;
 | 
		
	
		
			
			| 222 |  | -	struct io_buffer *tmp;
 | 
		
	
		
			
			| 223 | 313 |  
 | 
		
	
		
			
			| 224 | 314 |  	/* Close interrupt endpoint */
 | 
		
	
		
			
			| 225 |  | -	usb_endpoint_close ( &ncm->intr );
 | 
		
	
		
			
			|  | 315 | +	usb_endpoint_close ( &ncm->intr.ep );
 | 
		
	
		
			
			| 226 | 316 |  
 | 
		
	
		
			
			| 227 | 317 |  	/* Free I/O buffers */
 | 
		
	
		
			
			| 228 |  | -	list_for_each_entry_safe ( iobuf, tmp, &ncm->intrs, list ) {
 | 
		
	
		
			
			| 229 |  | -		list_del ( &iobuf->list );
 | 
		
	
		
			
			| 230 |  | -		free_iob ( iobuf );
 | 
		
	
		
			
			| 231 |  | -	}
 | 
		
	
		
			
			|  | 318 | +	ncm_rx_free ( ncm, &ncm->intr );
 | 
		
	
		
			
			| 232 | 319 |  }
 | 
		
	
		
			
			| 233 | 320 |  
 | 
		
	
		
			
			| 234 | 321 |  /******************************************************************************
 | 
		
	
	
		
			
			|  | @@ -239,39 +326,48 @@ static void ncm_comms_close ( struct ncm_device *ncm ) {
 | 
		
	
		
			
			| 239 | 326 |   */
 | 
		
	
		
			
			| 240 | 327 |  
 | 
		
	
		
			
			| 241 | 328 |  /**
 | 
		
	
		
			
			| 242 |  | - * Refill bulk IN ring
 | 
		
	
		
			
			|  | 329 | + * Allocate bulk IN receive ring buffers
 | 
		
	
		
			
			| 243 | 330 |   *
 | 
		
	
		
			
			| 244 | 331 |   * @v ncm		CDC-NCM device
 | 
		
	
		
			
			|  | 332 | + * @ret rc		Return status code
 | 
		
	
		
			
			| 245 | 333 |   */
 | 
		
	
		
			
			| 246 |  | -static void ncm_in_refill ( struct ncm_device *ncm ) {
 | 
		
	
		
			
			| 247 |  | -	struct net_device *netdev = ncm->netdev;
 | 
		
	
		
			
			| 248 |  | -	struct io_buffer *iobuf;
 | 
		
	
		
			
			|  | 334 | +static int ncm_in_alloc ( struct ncm_device *ncm ) {
 | 
		
	
		
			
			|  | 335 | +	size_t mtu;
 | 
		
	
		
			
			|  | 336 | +	unsigned int count;
 | 
		
	
		
			
			| 249 | 337 |  	int rc;
 | 
		
	
		
			
			| 250 | 338 |  
 | 
		
	
		
			
			| 251 |  | -	/* Refill ring */
 | 
		
	
		
			
			| 252 |  | -	while ( ncm->fill < NCM_IN_FILL ) {
 | 
		
	
		
			
			| 253 |  | -
 | 
		
	
		
			
			| 254 |  | -		/* Profile refill */
 | 
		
	
		
			
			| 255 |  | -		profile_start ( &ncm_in_refill_profiler );
 | 
		
	
		
			
			| 256 |  | -
 | 
		
	
		
			
			| 257 |  | -		/* Allocate I/O buffer */
 | 
		
	
		
			
			| 258 |  | -		iobuf = alloc_iob ( NCM_NTB_INPUT_SIZE );
 | 
		
	
		
			
			| 259 |  | -		if ( ! iobuf ) {
 | 
		
	
		
			
			| 260 |  | -			/* Wait for next refill */
 | 
		
	
		
			
			| 261 |  | -			break;
 | 
		
	
		
			
			| 262 |  | -		}
 | 
		
	
		
			
			| 263 |  | -		iob_put ( iobuf, NCM_NTB_INPUT_SIZE );
 | 
		
	
		
			
			| 264 |  | -
 | 
		
	
		
			
			| 265 |  | -		/* Enqueue I/O buffer */
 | 
		
	
		
			
			| 266 |  | -		if ( ( rc = usb_stream ( &ncm->in, iobuf ) ) != 0 ) {
 | 
		
	
		
			
			| 267 |  | -			netdev_rx_err ( netdev, iobuf, rc );
 | 
		
	
		
			
			| 268 |  | -			break;
 | 
		
	
		
			
			| 269 |  | -		}
 | 
		
	
		
			
			| 270 |  | -
 | 
		
	
		
			
			| 271 |  | -		/* Increment fill level */
 | 
		
	
		
			
			| 272 |  | -		ncm->fill++;
 | 
		
	
		
			
			| 273 |  | -		profile_stop ( &ncm_in_refill_profiler );
 | 
		
	
		
			
			|  | 339 | +	/* Some devices have a very small number of internal buffers,
 | 
		
	
		
			
			|  | 340 | +	 * and rely on being able to pack multiple packets into each
 | 
		
	
		
			
			|  | 341 | +	 * buffer.  We therefore want to use large buffers if
 | 
		
	
		
			
			|  | 342 | +	 * possible.  However, large allocations have a reasonable
 | 
		
	
		
			
			|  | 343 | +	 * chance of failure, especially if this is not the first or
 | 
		
	
		
			
			|  | 344 | +	 * only device to be opened.
 | 
		
	
		
			
			|  | 345 | +	 *
 | 
		
	
		
			
			|  | 346 | +	 * We therefore attempt to find a usable buffer size, starting
 | 
		
	
		
			
			|  | 347 | +	 * large and working downwards until allocation succeeds.
 | 
		
	
		
			
			|  | 348 | +	 * Smaller buffers will still work, albeit with a higher
 | 
		
	
		
			
			|  | 349 | +	 * chance of packet loss and so lower overall throughput.
 | 
		
	
		
			
			|  | 350 | +	 */
 | 
		
	
		
			
			|  | 351 | +	for ( mtu = ncm->mtu ; mtu >= NCM_MIN_NTB_INPUT_SIZE ; mtu >>= 1 ) {
 | 
		
	
		
			
			|  | 352 | +
 | 
		
	
		
			
			|  | 353 | +		/* Attempt allocation at this MTU */
 | 
		
	
		
			
			|  | 354 | +		if ( mtu > NCM_MAX_NTB_INPUT_SIZE )
 | 
		
	
		
			
			|  | 355 | +			continue;
 | 
		
	
		
			
			|  | 356 | +		count = ( NCM_IN_MIN_SIZE / mtu );
 | 
		
	
		
			
			|  | 357 | +		if ( count < NCM_IN_MIN_COUNT )
 | 
		
	
		
			
			|  | 358 | +			count = NCM_IN_MIN_COUNT;
 | 
		
	
		
			
			|  | 359 | +		if ( ( count * mtu ) > NCM_IN_MAX_SIZE )
 | 
		
	
		
			
			|  | 360 | +			continue;
 | 
		
	
		
			
			|  | 361 | +		if ( ( rc = ncm_rx_alloc ( ncm, &ncm->in, mtu, count ) ) != 0 )
 | 
		
	
		
			
			|  | 362 | +			continue;
 | 
		
	
		
			
			|  | 363 | +
 | 
		
	
		
			
			|  | 364 | +		DBGC ( ncm, "NCM %p using %dx %zd-byte buffers for bulk IN\n",
 | 
		
	
		
			
			|  | 365 | +		       ncm, count, mtu );
 | 
		
	
		
			
			|  | 366 | +		return 0;
 | 
		
	
		
			
			| 274 | 367 |  	}
 | 
		
	
		
			
			|  | 368 | +
 | 
		
	
		
			
			|  | 369 | +	DBGC ( ncm, "NCM %p could not allocate bulk IN buffers\n", ncm );
 | 
		
	
		
			
			|  | 370 | +	return -ENOMEM;
 | 
		
	
		
			
			| 275 | 371 |  }
 | 
		
	
		
			
			| 276 | 372 |  
 | 
		
	
		
			
			| 277 | 373 |  /**
 | 
		
	
	
		
			
			|  | @@ -283,7 +379,7 @@ static void ncm_in_refill ( struct ncm_device *ncm ) {
 | 
		
	
		
			
			| 283 | 379 |   */
 | 
		
	
		
			
			| 284 | 380 |  static void ncm_in_complete ( struct usb_endpoint *ep, struct io_buffer *iobuf,
 | 
		
	
		
			
			| 285 | 381 |  			      int rc ) {
 | 
		
	
		
			
			| 286 |  | -	struct ncm_device *ncm = container_of ( ep, struct ncm_device, in );
 | 
		
	
		
			
			|  | 382 | +	struct ncm_device *ncm = container_of ( ep, struct ncm_device, in.ep );
 | 
		
	
		
			
			| 287 | 383 |  	struct net_device *netdev = ncm->netdev;
 | 
		
	
		
			
			| 288 | 384 |  	struct ncm_transfer_header *nth;
 | 
		
	
		
			
			| 289 | 385 |  	struct ncm_datagram_pointer *ndp;
 | 
		
	
	
		
			
			|  | @@ -299,16 +395,16 @@ static void ncm_in_complete ( struct usb_endpoint *ep, struct io_buffer *iobuf,
 | 
		
	
		
			
			| 299 | 395 |  	/* Profile overall bulk IN completion */
 | 
		
	
		
			
			| 300 | 396 |  	profile_start ( &ncm_in_profiler );
 | 
		
	
		
			
			| 301 | 397 |  
 | 
		
	
		
			
			| 302 |  | -	/* Decrement fill level */
 | 
		
	
		
			
			| 303 |  | -	ncm->fill--;
 | 
		
	
		
			
			| 304 |  | -
 | 
		
	
		
			
			| 305 | 398 |  	/* Ignore packets cancelled when the endpoint closes */
 | 
		
	
		
			
			| 306 | 399 |  	if ( ! ep->open )
 | 
		
	
		
			
			| 307 | 400 |  		goto ignore;
 | 
		
	
		
			
			| 308 | 401 |  
 | 
		
	
		
			
			| 309 | 402 |  	/* Record USB errors against the network device */
 | 
		
	
		
			
			| 310 |  | -	if ( rc != 0 )
 | 
		
	
		
			
			|  | 403 | +	if ( rc != 0 ) {
 | 
		
	
		
			
			|  | 404 | +		DBGC ( ncm, "NCM %p bulk IN failed: %s\n",
 | 
		
	
		
			
			|  | 405 | +		       ncm, strerror ( rc ) );
 | 
		
	
		
			
			| 311 | 406 |  		goto drop;
 | 
		
	
		
			
			|  | 407 | +	}
 | 
		
	
		
			
			| 312 | 408 |  
 | 
		
	
		
			
			| 313 | 409 |  	/* Locate transfer header */
 | 
		
	
		
			
			| 314 | 410 |  	len = iob_len ( iobuf );
 | 
		
	
	
		
			
			|  | @@ -358,23 +454,21 @@ static void ncm_in_complete ( struct usb_endpoint *ep, struct io_buffer *iobuf,
 | 
		
	
		
			
			| 358 | 454 |  		/* Move to next descriptor */
 | 
		
	
		
			
			| 359 | 455 |  		desc++;
 | 
		
	
		
			
			| 360 | 456 |  
 | 
		
	
		
			
			| 361 |  | -		/* Create new I/O buffer if necessary */
 | 
		
	
		
			
			| 362 |  | -		if ( remaining && desc->offset ) {
 | 
		
	
		
			
			| 363 |  | -			/* More packets remain: create new buffer */
 | 
		
	
		
			
			| 364 |  | -			pkt = alloc_iob ( pkt_len );
 | 
		
	
		
			
			| 365 |  | -			if ( ! pkt ) {
 | 
		
	
		
			
			| 366 |  | -				/* Record error and continue */
 | 
		
	
		
			
			| 367 |  | -				netdev_rx_err ( netdev, NULL, -ENOMEM );
 | 
		
	
		
			
			| 368 |  | -				continue;
 | 
		
	
		
			
			| 369 |  | -			}
 | 
		
	
		
			
			| 370 |  | -			memcpy ( iob_put ( pkt, pkt_len ),
 | 
		
	
		
			
			| 371 |  | -				 ( iobuf->data + pkt_offset ), pkt_len );
 | 
		
	
		
			
			| 372 |  | -		} else {
 | 
		
	
		
			
			| 373 |  | -			/* This is the last packet: use in situ */
 | 
		
	
		
			
			| 374 |  | -			pkt = iob_disown ( iobuf );
 | 
		
	
		
			
			| 375 |  | -			iob_pull ( pkt, pkt_offset );
 | 
		
	
		
			
			| 376 |  | -			iob_unput ( pkt, ( iob_len ( pkt ) - pkt_len ) );
 | 
		
	
		
			
			|  | 457 | +		/* Copy data to a new I/O buffer.  Our USB buffers may
 | 
		
	
		
			
			|  | 458 | +		 * be very large and so we choose to recycle the
 | 
		
	
		
			
			|  | 459 | +		 * buffers directly rather than attempt reallocation
 | 
		
	
		
			
			|  | 460 | +		 * while the device is running.  We therefore copy the
 | 
		
	
		
			
			|  | 461 | +		 * data to a new I/O buffer even if this is the only
 | 
		
	
		
			
			|  | 462 | +		 * (or last) packet within the buffer.
 | 
		
	
		
			
			|  | 463 | +		 */
 | 
		
	
		
			
			|  | 464 | +		pkt = alloc_iob ( pkt_len );
 | 
		
	
		
			
			|  | 465 | +		if ( ! pkt ) {
 | 
		
	
		
			
			|  | 466 | +			/* Record error and continue */
 | 
		
	
		
			
			|  | 467 | +			netdev_rx_err ( netdev, NULL, -ENOMEM );
 | 
		
	
		
			
			|  | 468 | +			continue;
 | 
		
	
		
			
			| 377 | 469 |  		}
 | 
		
	
		
			
			|  | 470 | +		memcpy ( iob_put ( pkt, pkt_len ),
 | 
		
	
		
			
			|  | 471 | +			 ( iobuf->data + pkt_offset ), pkt_len );
 | 
		
	
		
			
			| 378 | 472 |  
 | 
		
	
		
			
			| 379 | 473 |  		/* Strip CRC, if present */
 | 
		
	
		
			
			| 380 | 474 |  		if ( ndp->magic & cpu_to_le32 ( NCM_DATAGRAM_POINTER_MAGIC_CRC))
 | 
		
	
	
		
			
			|  | @@ -385,22 +479,20 @@ static void ncm_in_complete ( struct usb_endpoint *ep, struct io_buffer *iobuf,
 | 
		
	
		
			
			| 385 | 479 |  		profile_stop ( &ncm_in_datagram_profiler );
 | 
		
	
		
			
			| 386 | 480 |  	}
 | 
		
	
		
			
			| 387 | 481 |  
 | 
		
	
		
			
			| 388 |  | -	/* Free I/O buffer (if still present) */
 | 
		
	
		
			
			| 389 |  | -	free_iob ( iobuf );
 | 
		
	
		
			
			| 390 |  | -
 | 
		
	
		
			
			|  | 482 | +	/* Recycle I/O buffer */
 | 
		
	
		
			
			|  | 483 | +	ncm_rx_recycle ( ncm, &ncm->in, iobuf );
 | 
		
	
		
			
			| 391 | 484 |  	profile_stop ( &ncm_in_profiler );
 | 
		
	
		
			
			|  | 485 | +
 | 
		
	
		
			
			| 392 | 486 |  	return;
 | 
		
	
		
			
			| 393 | 487 |  
 | 
		
	
		
			
			| 394 | 488 |   error:
 | 
		
	
		
			
			| 395 | 489 |  	rc = -EIO;
 | 
		
	
		
			
			| 396 | 490 |   drop:
 | 
		
	
		
			
			|  | 491 | +	/* Record error against network device */
 | 
		
	
		
			
			| 397 | 492 |  	DBGC_HDA ( ncm, 0, iobuf->data, iob_len ( iobuf ) );
 | 
		
	
		
			
			| 398 |  | -	netdev_rx_err ( netdev, iobuf, rc );
 | 
		
	
		
			
			| 399 |  | -	return;
 | 
		
	
		
			
			| 400 |  | -
 | 
		
	
		
			
			|  | 493 | +	netdev_rx_err ( netdev, NULL, rc );
 | 
		
	
		
			
			| 401 | 494 |   ignore:
 | 
		
	
		
			
			| 402 |  | -	free_iob ( iobuf );
 | 
		
	
		
			
			| 403 |  | -	return;
 | 
		
	
		
			
			|  | 495 | +	ncm_rx_recycle ( ncm, &ncm->in, iobuf );
 | 
		
	
		
			
			| 404 | 496 |  }
 | 
		
	
		
			
			| 405 | 497 |  
 | 
		
	
		
			
			| 406 | 498 |  /** Bulk IN endpoint operations */
 | 
		
	
	
		
			
			|  | @@ -419,7 +511,7 @@ static int ncm_out_transmit ( struct ncm_device *ncm,
 | 
		
	
		
			
			| 419 | 511 |  			      struct io_buffer *iobuf ) {
 | 
		
	
		
			
			| 420 | 512 |  	struct ncm_ntb_header *header;
 | 
		
	
		
			
			| 421 | 513 |  	size_t len = iob_len ( iobuf );
 | 
		
	
		
			
			| 422 |  | -	size_t header_len = ( sizeof ( *header ) + ncm->padding );
 | 
		
	
		
			
			|  | 514 | +	size_t header_len = ( sizeof ( *header ) + ncm->out.padding );
 | 
		
	
		
			
			| 423 | 515 |  	int rc;
 | 
		
	
		
			
			| 424 | 516 |  
 | 
		
	
		
			
			| 425 | 517 |  	/* Profile transmissions */
 | 
		
	
	
		
			
			|  | @@ -433,7 +525,7 @@ static int ncm_out_transmit ( struct ncm_device *ncm,
 | 
		
	
		
			
			| 433 | 525 |  	/* Populate header */
 | 
		
	
		
			
			| 434 | 526 |  	header->nth.magic = cpu_to_le32 ( NCM_TRANSFER_HEADER_MAGIC );
 | 
		
	
		
			
			| 435 | 527 |  	header->nth.header_len = cpu_to_le16 ( sizeof ( header->nth ) );
 | 
		
	
		
			
			| 436 |  | -	header->nth.sequence = cpu_to_le16 ( ncm->sequence );
 | 
		
	
		
			
			|  | 528 | +	header->nth.sequence = cpu_to_le16 ( ncm->out.sequence );
 | 
		
	
		
			
			| 437 | 529 |  	header->nth.len = cpu_to_le16 ( iob_len ( iobuf ) );
 | 
		
	
		
			
			| 438 | 530 |  	header->nth.offset =
 | 
		
	
		
			
			| 439 | 531 |  		cpu_to_le16 ( offsetof ( typeof ( *header ), ndp ) );
 | 
		
	
	
		
			
			|  | @@ -446,11 +538,11 @@ static int ncm_out_transmit ( struct ncm_device *ncm,
 | 
		
	
		
			
			| 446 | 538 |  	memset ( &header->desc[1], 0, sizeof ( header->desc[1] ) );
 | 
		
	
		
			
			| 447 | 539 |  
 | 
		
	
		
			
			| 448 | 540 |  	/* Enqueue I/O buffer */
 | 
		
	
		
			
			| 449 |  | -	if ( ( rc = usb_stream ( &ncm->out, iobuf ) ) != 0 )
 | 
		
	
		
			
			|  | 541 | +	if ( ( rc = usb_stream ( &ncm->out.ep, iobuf ) ) != 0 )
 | 
		
	
		
			
			| 450 | 542 |  		return rc;
 | 
		
	
		
			
			| 451 | 543 |  
 | 
		
	
		
			
			| 452 | 544 |  	/* Increment sequence number */
 | 
		
	
		
			
			| 453 |  | -	ncm->sequence++;
 | 
		
	
		
			
			|  | 545 | +	ncm->out.sequence++;
 | 
		
	
		
			
			| 454 | 546 |  
 | 
		
	
		
			
			| 455 | 547 |  	profile_stop ( &ncm_out_profiler );
 | 
		
	
		
			
			| 456 | 548 |  	return 0;
 | 
		
	
	
		
			
			|  | @@ -465,7 +557,7 @@ static int ncm_out_transmit ( struct ncm_device *ncm,
 | 
		
	
		
			
			| 465 | 557 |   */
 | 
		
	
		
			
			| 466 | 558 |  static void ncm_out_complete ( struct usb_endpoint *ep, struct io_buffer *iobuf,
 | 
		
	
		
			
			| 467 | 559 |  			       int rc ) {
 | 
		
	
		
			
			| 468 |  | -	struct ncm_device *ncm = container_of ( ep, struct ncm_device, out );
 | 
		
	
		
			
			|  | 560 | +	struct ncm_device *ncm = container_of ( ep, struct ncm_device, out.ep );
 | 
		
	
		
			
			| 469 | 561 |  	struct net_device *netdev = ncm->netdev;
 | 
		
	
		
			
			| 470 | 562 |  
 | 
		
	
		
			
			| 471 | 563 |  	/* Report TX completion */
 | 
		
	
	
		
			
			|  | @@ -488,13 +580,17 @@ static int ncm_data_open ( struct ncm_device *ncm ) {
 | 
		
	
		
			
			| 488 | 580 |  	struct ncm_set_ntb_input_size size;
 | 
		
	
		
			
			| 489 | 581 |  	int rc;
 | 
		
	
		
			
			| 490 | 582 |  
 | 
		
	
		
			
			|  | 583 | +	/* Allocate I/O buffers */
 | 
		
	
		
			
			|  | 584 | +	if ( ( rc = ncm_in_alloc ( ncm ) ) != 0 )
 | 
		
	
		
			
			|  | 585 | +		goto err_alloc;
 | 
		
	
		
			
			|  | 586 | +
 | 
		
	
		
			
			| 491 | 587 |  	/* Set maximum input size */
 | 
		
	
		
			
			| 492 | 588 |  	memset ( &size, 0, sizeof ( size ) );
 | 
		
	
		
			
			| 493 |  | -	size.mtu = cpu_to_le32 ( NCM_NTB_INPUT_SIZE );
 | 
		
	
		
			
			|  | 589 | +	size.mtu = cpu_to_le32 ( ncm->in.mtu );
 | 
		
	
		
			
			| 494 | 590 |  	if ( ( rc = usb_control ( usb, NCM_SET_NTB_INPUT_SIZE, 0, ncm->comms,
 | 
		
	
		
			
			| 495 | 591 |  				  &size, sizeof ( size ) ) ) != 0 ) {
 | 
		
	
		
			
			| 496 |  | -		DBGC ( ncm, "NCM %p could not set input size: %s\n",
 | 
		
	
		
			
			| 497 |  | -		       ncm, strerror ( rc ) );
 | 
		
	
		
			
			|  | 592 | +		DBGC ( ncm, "NCM %p could not set input size to %zd: %s\n",
 | 
		
	
		
			
			|  | 593 | +		       ncm, ncm->in.mtu, strerror ( rc ) );
 | 
		
	
		
			
			| 498 | 594 |  		goto err_set_ntb_input_size;
 | 
		
	
		
			
			| 499 | 595 |  	}
 | 
		
	
		
			
			| 500 | 596 |  
 | 
		
	
	
		
			
			|  | @@ -507,28 +603,33 @@ static int ncm_data_open ( struct ncm_device *ncm ) {
 | 
		
	
		
			
			| 507 | 603 |  	}
 | 
		
	
		
			
			| 508 | 604 |  
 | 
		
	
		
			
			| 509 | 605 |  	/* Open bulk IN endpoint */
 | 
		
	
		
			
			| 510 |  | -	if ( ( rc = usb_endpoint_open ( &ncm->in ) ) != 0 ) {
 | 
		
	
		
			
			|  | 606 | +	if ( ( rc = usb_endpoint_open ( &ncm->in.ep ) ) != 0 ) {
 | 
		
	
		
			
			| 511 | 607 |  		DBGC ( ncm, "NCM %p could not open bulk IN: %s\n",
 | 
		
	
		
			
			| 512 | 608 |  		       ncm, strerror ( rc ) );
 | 
		
	
		
			
			| 513 | 609 |  		goto err_open_in;
 | 
		
	
		
			
			| 514 | 610 |  	}
 | 
		
	
		
			
			| 515 | 611 |  
 | 
		
	
		
			
			| 516 | 612 |  	/* Open bulk OUT endpoint */
 | 
		
	
		
			
			| 517 |  | -	if ( ( rc = usb_endpoint_open ( &ncm->out ) ) != 0 ) {
 | 
		
	
		
			
			|  | 613 | +	if ( ( rc = usb_endpoint_open ( &ncm->out.ep ) ) != 0 ) {
 | 
		
	
		
			
			| 518 | 614 |  		DBGC ( ncm, "NCM %p could not open bulk OUT: %s\n",
 | 
		
	
		
			
			| 519 | 615 |  		       ncm, strerror ( rc ) );
 | 
		
	
		
			
			| 520 | 616 |  		goto err_open_out;
 | 
		
	
		
			
			| 521 | 617 |  	}
 | 
		
	
		
			
			| 522 | 618 |  
 | 
		
	
		
			
			|  | 619 | +	/* Reset transmit sequence number */
 | 
		
	
		
			
			|  | 620 | +	ncm->out.sequence = 0;
 | 
		
	
		
			
			|  | 621 | +
 | 
		
	
		
			
			| 523 | 622 |  	return 0;
 | 
		
	
		
			
			| 524 | 623 |  
 | 
		
	
		
			
			| 525 |  | -	usb_endpoint_close ( &ncm->out );
 | 
		
	
		
			
			|  | 624 | +	usb_endpoint_close ( &ncm->out.ep );
 | 
		
	
		
			
			| 526 | 625 |   err_open_out:
 | 
		
	
		
			
			| 527 |  | -	usb_endpoint_close ( &ncm->in );
 | 
		
	
		
			
			|  | 626 | +	usb_endpoint_close ( &ncm->in.ep );
 | 
		
	
		
			
			| 528 | 627 |   err_open_in:
 | 
		
	
		
			
			| 529 | 628 |  	usb_set_interface ( usb, ncm->data, 0 );
 | 
		
	
		
			
			| 530 | 629 |   err_set_interface:
 | 
		
	
		
			
			| 531 | 630 |   err_set_ntb_input_size:
 | 
		
	
		
			
			|  | 631 | +	ncm_rx_free ( ncm, &ncm->in );
 | 
		
	
		
			
			|  | 632 | + err_alloc:
 | 
		
	
		
			
			| 532 | 633 |  	return rc;
 | 
		
	
		
			
			| 533 | 634 |  }
 | 
		
	
		
			
			| 534 | 635 |  
 | 
		
	
	
		
			
			|  | @@ -541,11 +642,14 @@ static void ncm_data_close ( struct ncm_device *ncm ) {
 | 
		
	
		
			
			| 541 | 642 |  	struct usb_device *usb = ncm->usb;
 | 
		
	
		
			
			| 542 | 643 |  
 | 
		
	
		
			
			| 543 | 644 |  	/* Close endpoints */
 | 
		
	
		
			
			| 544 |  | -	usb_endpoint_close ( &ncm->out );
 | 
		
	
		
			
			| 545 |  | -	usb_endpoint_close ( &ncm->in );
 | 
		
	
		
			
			|  | 645 | +	usb_endpoint_close ( &ncm->out.ep );
 | 
		
	
		
			
			|  | 646 | +	usb_endpoint_close ( &ncm->in.ep );
 | 
		
	
		
			
			| 546 | 647 |  
 | 
		
	
		
			
			| 547 | 648 |  	/* Reset data interface */
 | 
		
	
		
			
			| 548 | 649 |  	usb_set_interface ( usb, ncm->data, 0 );
 | 
		
	
		
			
			|  | 650 | +
 | 
		
	
		
			
			|  | 651 | +	/* Free I/O buffers */
 | 
		
	
		
			
			|  | 652 | +	ncm_rx_free ( ncm, &ncm->in );
 | 
		
	
		
			
			| 549 | 653 |  }
 | 
		
	
		
			
			| 550 | 654 |  
 | 
		
	
		
			
			| 551 | 655 |  /******************************************************************************
 | 
		
	
	
		
			
			|  | @@ -566,26 +670,30 @@ static int ncm_open ( struct net_device *netdev ) {
 | 
		
	
		
			
			| 566 | 670 |  	int rc;
 | 
		
	
		
			
			| 567 | 671 |  
 | 
		
	
		
			
			| 568 | 672 |  	/* Reset sequence number */
 | 
		
	
		
			
			| 569 |  | -	ncm->sequence = 0;
 | 
		
	
		
			
			|  | 673 | +	ncm->out.sequence = 0;
 | 
		
	
		
			
			| 570 | 674 |  
 | 
		
	
		
			
			| 571 | 675 |  	/* Open communications interface */
 | 
		
	
		
			
			| 572 | 676 |  	if ( ( rc = ncm_comms_open ( ncm ) ) != 0 )
 | 
		
	
		
			
			| 573 | 677 |  		goto err_comms_open;
 | 
		
	
		
			
			| 574 | 678 |  
 | 
		
	
		
			
			| 575 | 679 |  	/* Refill interrupt ring */
 | 
		
	
		
			
			| 576 |  | -	ncm_intr_refill ( ncm );
 | 
		
	
		
			
			|  | 680 | +	if ( ( rc = ncm_rx_refill ( ncm, &ncm->intr ) ) != 0 )
 | 
		
	
		
			
			|  | 681 | +		goto err_intr_refill;
 | 
		
	
		
			
			| 577 | 682 |  
 | 
		
	
		
			
			| 578 | 683 |  	/* Open data interface */
 | 
		
	
		
			
			| 579 | 684 |  	if ( ( rc = ncm_data_open ( ncm ) ) != 0 )
 | 
		
	
		
			
			| 580 | 685 |  		goto err_data_open;
 | 
		
	
		
			
			| 581 | 686 |  
 | 
		
	
		
			
			| 582 | 687 |  	/* Refill bulk IN ring */
 | 
		
	
		
			
			| 583 |  | -	ncm_in_refill ( ncm );
 | 
		
	
		
			
			|  | 688 | +	if ( ( rc = ncm_rx_refill ( ncm, &ncm->in ) ) != 0 )
 | 
		
	
		
			
			|  | 689 | +		goto err_in_refill;
 | 
		
	
		
			
			| 584 | 690 |  
 | 
		
	
		
			
			| 585 | 691 |  	return 0;
 | 
		
	
		
			
			| 586 | 692 |  
 | 
		
	
		
			
			|  | 693 | + err_in_refill:
 | 
		
	
		
			
			| 587 | 694 |  	ncm_data_close ( ncm );
 | 
		
	
		
			
			| 588 | 695 |   err_data_open:
 | 
		
	
		
			
			|  | 696 | + err_intr_refill:
 | 
		
	
		
			
			| 589 | 697 |  	ncm_comms_close ( ncm );
 | 
		
	
		
			
			| 590 | 698 |   err_comms_open:
 | 
		
	
		
			
			| 591 | 699 |  	return rc;
 | 
		
	
	
		
			
			|  | @@ -604,9 +712,6 @@ static void ncm_close ( struct net_device *netdev ) {
 | 
		
	
		
			
			| 604 | 712 |  
 | 
		
	
		
			
			| 605 | 713 |  	/* Close communications interface */
 | 
		
	
		
			
			| 606 | 714 |  	ncm_comms_close ( ncm );
 | 
		
	
		
			
			| 607 |  | -
 | 
		
	
		
			
			| 608 |  | -	/* Sanity check */
 | 
		
	
		
			
			| 609 |  | -	assert ( ncm->fill == 0 );
 | 
		
	
		
			
			| 610 | 715 |  }
 | 
		
	
		
			
			| 611 | 716 |  
 | 
		
	
		
			
			| 612 | 717 |  /**
 | 
		
	
	
		
			
			|  | @@ -635,15 +740,18 @@ static int ncm_transmit ( struct net_device *netdev,
 | 
		
	
		
			
			| 635 | 740 |   */
 | 
		
	
		
			
			| 636 | 741 |  static void ncm_poll ( struct net_device *netdev ) {
 | 
		
	
		
			
			| 637 | 742 |  	struct ncm_device *ncm = netdev->priv;
 | 
		
	
		
			
			|  | 743 | +	int rc;
 | 
		
	
		
			
			| 638 | 744 |  
 | 
		
	
		
			
			| 639 | 745 |  	/* Poll USB bus */
 | 
		
	
		
			
			| 640 | 746 |  	usb_poll ( ncm->bus );
 | 
		
	
		
			
			| 641 | 747 |  
 | 
		
	
		
			
			| 642 | 748 |  	/* Refill interrupt ring */
 | 
		
	
		
			
			| 643 |  | -	ncm_intr_refill ( ncm );
 | 
		
	
		
			
			|  | 749 | +	if ( ( rc = ncm_rx_refill ( ncm, &ncm->intr ) ) != 0 )
 | 
		
	
		
			
			|  | 750 | +		netdev_rx_err ( netdev, NULL, rc );
 | 
		
	
		
			
			| 644 | 751 |  
 | 
		
	
		
			
			| 645 | 752 |  	/* Refill bulk IN ring */
 | 
		
	
		
			
			| 646 |  | -	ncm_in_refill ( ncm );
 | 
		
	
		
			
			|  | 753 | +	if ( ( rc = ncm_rx_refill ( ncm, &ncm->in ) ) != 0 )
 | 
		
	
		
			
			|  | 754 | +		netdev_rx_err ( netdev, NULL, rc );
 | 
		
	
		
			
			| 647 | 755 |  }
 | 
		
	
		
			
			| 648 | 756 |  
 | 
		
	
		
			
			| 649 | 757 |  /** CDC-NCM network device operations */
 | 
		
	
	
		
			
			|  | @@ -692,10 +800,9 @@ static int ncm_probe ( struct usb_function *func,
 | 
		
	
		
			
			| 692 | 800 |  	ncm->usb = usb;
 | 
		
	
		
			
			| 693 | 801 |  	ncm->bus = usb->port->hub->bus;
 | 
		
	
		
			
			| 694 | 802 |  	ncm->netdev = netdev;
 | 
		
	
		
			
			| 695 |  | -	usb_endpoint_init ( &ncm->intr, usb, &ncm_intr_operations );
 | 
		
	
		
			
			| 696 |  | -	usb_endpoint_init ( &ncm->in, usb, &ncm_in_operations );
 | 
		
	
		
			
			| 697 |  | -	usb_endpoint_init ( &ncm->out, usb, &ncm_out_operations );
 | 
		
	
		
			
			| 698 |  | -	INIT_LIST_HEAD ( &ncm->intrs );
 | 
		
	
		
			
			|  | 803 | +	usb_endpoint_init ( &ncm->intr.ep, usb, &ncm_intr_operations );
 | 
		
	
		
			
			|  | 804 | +	usb_endpoint_init ( &ncm->in.ep, usb, &ncm_in_operations );
 | 
		
	
		
			
			|  | 805 | +	usb_endpoint_init ( &ncm->out.ep, usb, &ncm_out_operations );
 | 
		
	
		
			
			| 699 | 806 |  	DBGC ( ncm, "NCM %p on %s\n", ncm, func->name );
 | 
		
	
		
			
			| 700 | 807 |  
 | 
		
	
		
			
			| 701 | 808 |  	/* Identify interfaces */
 | 
		
	
	
		
			
			|  | @@ -726,7 +833,7 @@ static int ncm_probe ( struct usb_function *func,
 | 
		
	
		
			
			| 726 | 833 |  	}
 | 
		
	
		
			
			| 727 | 834 |  
 | 
		
	
		
			
			| 728 | 835 |  	/* Describe interrupt endpoint */
 | 
		
	
		
			
			| 729 |  | -	if ( ( rc = usb_endpoint_described ( &ncm->intr, config, comms,
 | 
		
	
		
			
			|  | 836 | +	if ( ( rc = usb_endpoint_described ( &ncm->intr.ep, config, comms,
 | 
		
	
		
			
			| 730 | 837 |  					     USB_INTERRUPT, 0 ) ) != 0 ) {
 | 
		
	
		
			
			| 731 | 838 |  		DBGC ( ncm, "NCM %p could not describe interrupt endpoint: "
 | 
		
	
		
			
			| 732 | 839 |  		       "%s\n", ncm, strerror ( rc ) );
 | 
		
	
	
		
			
			|  | @@ -734,7 +841,7 @@ static int ncm_probe ( struct usb_function *func,
 | 
		
	
		
			
			| 734 | 841 |  	}
 | 
		
	
		
			
			| 735 | 842 |  
 | 
		
	
		
			
			| 736 | 843 |  	/* Describe bulk IN endpoint */
 | 
		
	
		
			
			| 737 |  | -	if ( ( rc = usb_endpoint_described ( &ncm->in, config, data,
 | 
		
	
		
			
			|  | 844 | +	if ( ( rc = usb_endpoint_described ( &ncm->in.ep, config, data,
 | 
		
	
		
			
			| 738 | 845 |  					     USB_BULK_IN, 0 ) ) != 0 ) {
 | 
		
	
		
			
			| 739 | 846 |  		DBGC ( ncm, "NCM %p could not describe bulk IN endpoint: "
 | 
		
	
		
			
			| 740 | 847 |  		       "%s\n", ncm, strerror ( rc ) );
 | 
		
	
	
		
			
			|  | @@ -742,7 +849,7 @@ static int ncm_probe ( struct usb_function *func,
 | 
		
	
		
			
			| 742 | 849 |  	}
 | 
		
	
		
			
			| 743 | 850 |  
 | 
		
	
		
			
			| 744 | 851 |  	/* Describe bulk OUT endpoint */
 | 
		
	
		
			
			| 745 |  | -	if ( ( rc = usb_endpoint_described ( &ncm->out, config, data,
 | 
		
	
		
			
			|  | 852 | +	if ( ( rc = usb_endpoint_described ( &ncm->out.ep, config, data,
 | 
		
	
		
			
			| 746 | 853 |  					     USB_BULK_OUT, 0 ) ) != 0 ) {
 | 
		
	
		
			
			| 747 | 854 |  		DBGC ( ncm, "NCM %p could not describe bulk OUT endpoint: "
 | 
		
	
		
			
			| 748 | 855 |  		       "%s\n", ncm, strerror ( rc ) );
 | 
		
	
	
		
			
			|  | @@ -772,13 +879,17 @@ static int ncm_probe ( struct usb_function *func,
 | 
		
	
		
			
			| 772 | 879 |  		goto err_ntb_parameters;
 | 
		
	
		
			
			| 773 | 880 |  	}
 | 
		
	
		
			
			| 774 | 881 |  
 | 
		
	
		
			
			|  | 882 | +	/* Get maximum supported input size */
 | 
		
	
		
			
			|  | 883 | +	ncm->mtu = le32_to_cpu ( params.in.mtu );
 | 
		
	
		
			
			|  | 884 | +	DBGC2 ( ncm, "NCM %p maximum IN size is %zd bytes\n", ncm, ncm->mtu );
 | 
		
	
		
			
			|  | 885 | +
 | 
		
	
		
			
			| 775 | 886 |  	/* Calculate transmit padding */
 | 
		
	
		
			
			| 776 |  | -	ncm->padding = ( ( le16_to_cpu ( params.out.remainder ) -
 | 
		
	
		
			
			| 777 |  | -			   sizeof ( struct ncm_ntb_header ) - ETH_HLEN ) &
 | 
		
	
		
			
			| 778 |  | -			 ( le16_to_cpu ( params.out.divisor ) - 1 ) );
 | 
		
	
		
			
			|  | 887 | +	ncm->out.padding = ( ( le16_to_cpu ( params.out.remainder ) -
 | 
		
	
		
			
			|  | 888 | +			       sizeof ( struct ncm_ntb_header ) - ETH_HLEN ) &
 | 
		
	
		
			
			|  | 889 | +			     ( le16_to_cpu ( params.out.divisor ) - 1 ) );
 | 
		
	
		
			
			| 779 | 890 |  	DBGC2 ( ncm, "NCM %p using %zd-byte transmit padding\n",
 | 
		
	
		
			
			| 780 |  | -		ncm, ncm->padding );
 | 
		
	
		
			
			| 781 |  | -	assert ( ( ( sizeof ( struct ncm_ntb_header ) + ncm->padding +
 | 
		
	
		
			
			|  | 891 | +		ncm, ncm->out.padding );
 | 
		
	
		
			
			|  | 892 | +	assert ( ( ( sizeof ( struct ncm_ntb_header ) + ncm->out.padding +
 | 
		
	
		
			
			| 782 | 893 |  		     ETH_HLEN ) % le16_to_cpu ( params.out.divisor ) ) ==
 | 
		
	
		
			
			| 783 | 894 |  		 le16_to_cpu ( params.out.remainder ) );
 | 
		
	
		
			
			| 784 | 895 |  
 |