|  | @@ -26,6 +26,7 @@ Skeleton NIC driver for Etherboot
 | 
		
	
		
			
			| 26 | 26 |  #include "arbel.h"
 | 
		
	
		
			
			| 27 | 27 |  
 | 
		
	
		
			
			| 28 | 28 |  
 | 
		
	
		
			
			|  | 29 | +#define MLX_RX_MAX_FILL NUM_IPOIB_RCV_WQES
 | 
		
	
		
			
			| 29 | 30 |  
 | 
		
	
		
			
			| 30 | 31 |  struct mlx_nic {
 | 
		
	
		
			
			| 31 | 32 |  	/** Queue pair handle */
 | 
		
	
	
		
			
			|  | @@ -36,35 +37,65 @@ struct mlx_nic {
 | 
		
	
		
			
			| 36 | 37 |  	cq_t snd_cqh;
 | 
		
	
		
			
			| 37 | 38 |  	/** Receive completion queue */
 | 
		
	
		
			
			| 38 | 39 |  	cq_t rcv_cqh;
 | 
		
	
		
			
			|  | 40 | +
 | 
		
	
		
			
			|  | 41 | +	/** RX fill level */
 | 
		
	
		
			
			|  | 42 | +	unsigned int rx_fill;
 | 
		
	
		
			
			| 39 | 43 |  };
 | 
		
	
		
			
			| 40 | 44 |  
 | 
		
	
		
			
			| 41 | 45 |  
 | 
		
	
		
			
			| 42 | 46 |  static struct io_buffer *static_ipoib_tx_ring[NUM_IPOIB_SND_WQES];
 | 
		
	
		
			
			|  | 47 | +static struct io_buffer *static_ipoib_rx_ring[NUM_IPOIB_RCV_WQES];
 | 
		
	
		
			
			| 43 | 48 |  
 | 
		
	
		
			
			| 44 | 49 |  static struct arbel static_arbel;
 | 
		
	
		
			
			| 45 | 50 |  static struct arbel_send_work_queue static_arbel_ipoib_send_wq = {
 | 
		
	
		
			
			| 46 | 51 |  	.doorbell_idx = IPOIB_SND_QP_DB_IDX,
 | 
		
	
		
			
			| 47 | 52 |  };
 | 
		
	
		
			
			|  | 53 | +static struct arbel_send_work_queue static_arbel_ipoib_recv_wq = {
 | 
		
	
		
			
			|  | 54 | +	.doorbell_idx = IPOIB_RCV_QP_DB_IDX,
 | 
		
	
		
			
			|  | 55 | +};
 | 
		
	
		
			
			| 48 | 56 |  static struct arbel_completion_queue static_arbel_ipoib_send_cq = {
 | 
		
	
		
			
			| 49 | 57 |  	.doorbell_idx = IPOIB_SND_CQ_CI_DB_IDX,
 | 
		
	
		
			
			| 50 | 58 |  };
 | 
		
	
		
			
			|  | 59 | +static struct arbel_completion_queue static_arbel_ipoib_recv_cq = {
 | 
		
	
		
			
			|  | 60 | +	.doorbell_idx = IPOIB_RCV_CQ_CI_DB_IDX,
 | 
		
	
		
			
			|  | 61 | +};
 | 
		
	
		
			
			| 51 | 62 |  
 | 
		
	
		
			
			|  | 63 | +static struct ib_completion_queue static_ipoib_send_cq;
 | 
		
	
		
			
			|  | 64 | +static struct ib_completion_queue static_ipoib_recv_cq;
 | 
		
	
		
			
			| 52 | 65 |  static struct ib_device static_ibdev = {
 | 
		
	
		
			
			| 53 | 66 |  	.dev_priv = &static_arbel,
 | 
		
	
		
			
			| 54 | 67 |  };
 | 
		
	
		
			
			| 55 | 68 |  static struct ib_queue_pair static_ipoib_qp = {
 | 
		
	
		
			
			| 56 | 69 |  	.send = {
 | 
		
	
		
			
			|  | 70 | +		.qp = &static_ipoib_qp,
 | 
		
	
		
			
			|  | 71 | +		.is_send = 1,
 | 
		
	
		
			
			|  | 72 | +		.cq = &static_ipoib_send_cq,
 | 
		
	
		
			
			| 57 | 73 |  		.num_wqes = NUM_IPOIB_SND_WQES,
 | 
		
	
		
			
			| 58 | 74 |  		.iobufs = static_ipoib_tx_ring,
 | 
		
	
		
			
			| 59 | 75 |  		.dev_priv = &static_arbel_ipoib_send_wq,
 | 
		
	
		
			
			|  | 76 | +		.list = LIST_HEAD_INIT ( static_ipoib_qp.send.list ),
 | 
		
	
		
			
			|  | 77 | +	},
 | 
		
	
		
			
			|  | 78 | +	.recv = {
 | 
		
	
		
			
			|  | 79 | +		.qp = &static_ipoib_qp,
 | 
		
	
		
			
			|  | 80 | +		.is_send = 0,
 | 
		
	
		
			
			|  | 81 | +		.cq = &static_ipoib_recv_cq,
 | 
		
	
		
			
			|  | 82 | +		.num_wqes = NUM_IPOIB_RCV_WQES,
 | 
		
	
		
			
			|  | 83 | +		.iobufs = static_ipoib_rx_ring,
 | 
		
	
		
			
			|  | 84 | +		.dev_priv = &static_arbel_ipoib_recv_wq,
 | 
		
	
		
			
			|  | 85 | +		.list = LIST_HEAD_INIT ( static_ipoib_qp.recv.list ),
 | 
		
	
		
			
			| 60 | 86 |  	},
 | 
		
	
		
			
			| 61 |  | -	.list = LIST_HEAD_INIT ( static_ipoib_qp.list ),
 | 
		
	
		
			
			| 62 | 87 |  };
 | 
		
	
		
			
			| 63 | 88 |  static struct ib_completion_queue static_ipoib_send_cq = {
 | 
		
	
		
			
			| 64 | 89 |  	.cqn = 1234, /* Only used for debug messages */
 | 
		
	
		
			
			| 65 | 90 |  	.num_cqes = NUM_IPOIB_SND_CQES,
 | 
		
	
		
			
			| 66 | 91 |  	.dev_priv = &static_arbel_ipoib_send_cq,
 | 
		
	
		
			
			| 67 |  | -	.queue_pairs = LIST_HEAD_INIT ( static_ipoib_send_cq.queue_pairs ),
 | 
		
	
		
			
			|  | 92 | +	.work_queues = LIST_HEAD_INIT ( static_ipoib_send_cq.work_queues ),
 | 
		
	
		
			
			|  | 93 | +};
 | 
		
	
		
			
			|  | 94 | +static struct ib_completion_queue static_ipoib_recv_cq = {
 | 
		
	
		
			
			|  | 95 | +	.cqn = 2345, /* Only used for debug messages */
 | 
		
	
		
			
			|  | 96 | +	.num_cqes = NUM_IPOIB_RCV_CQES,
 | 
		
	
		
			
			|  | 97 | +	.dev_priv = &static_arbel_ipoib_recv_cq,
 | 
		
	
		
			
			|  | 98 | +	.work_queues = LIST_HEAD_INIT ( static_ipoib_recv_cq.work_queues ),
 | 
		
	
		
			
			| 68 | 99 |  };
 | 
		
	
		
			
			| 69 | 100 |  
 | 
		
	
		
			
			| 70 | 101 |  
 | 
		
	
	
		
			
			|  | @@ -157,36 +188,6 @@ static int mlx_transmit_direct ( struct net_device *netdev,
 | 
		
	
		
			
			| 157 | 188 |  }
 | 
		
	
		
			
			| 158 | 189 |  
 | 
		
	
		
			
			| 159 | 190 |  
 | 
		
	
		
			
			| 160 |  | -static void arbel_poll_cq ( struct ib_device *ibdev,
 | 
		
	
		
			
			| 161 |  | -			    struct ib_completion_queue *cq,
 | 
		
	
		
			
			| 162 |  | -			    ib_completer_t complete_send,
 | 
		
	
		
			
			| 163 |  | -			    ib_completer_t complete_recv );
 | 
		
	
		
			
			| 164 |  | -
 | 
		
	
		
			
			| 165 |  | -static void temp_complete_send ( struct ib_device *ibdev __unused,
 | 
		
	
		
			
			| 166 |  | -				 struct ib_queue_pair *qp,
 | 
		
	
		
			
			| 167 |  | -				 struct ib_completion *completion,
 | 
		
	
		
			
			| 168 |  | -				 struct io_buffer *iobuf ) {
 | 
		
	
		
			
			| 169 |  | -	struct net_device *netdev = qp->priv;
 | 
		
	
		
			
			| 170 |  | -
 | 
		
	
		
			
			| 171 |  | -	DBG ( "Wahey! TX completion\n" );
 | 
		
	
		
			
			| 172 |  | -	netdev_tx_complete_err ( netdev, iobuf,
 | 
		
	
		
			
			| 173 |  | -				 ( completion->syndrome ? -EIO : 0 ) );
 | 
		
	
		
			
			| 174 |  | -}
 | 
		
	
		
			
			| 175 |  | -
 | 
		
	
		
			
			| 176 |  | -static void temp_complete_recv ( struct ib_device *ibdev __unused,
 | 
		
	
		
			
			| 177 |  | -				 struct ib_queue_pair *qp __unused,
 | 
		
	
		
			
			| 178 |  | -				 struct ib_completion *completion __unused,
 | 
		
	
		
			
			| 179 |  | -				 struct io_buffer *iobuf __unused ) {
 | 
		
	
		
			
			| 180 |  | -	DBG ( "AARGH! recv completion\n" );
 | 
		
	
		
			
			| 181 |  | -}
 | 
		
	
		
			
			| 182 |  | -
 | 
		
	
		
			
			| 183 |  | -static void mlx_poll_cq_direct ( struct net_device *netdev ) {
 | 
		
	
		
			
			| 184 |  | -	struct mlx_nic *mlx = netdev->priv;
 | 
		
	
		
			
			| 185 |  | -
 | 
		
	
		
			
			| 186 |  | -	arbel_poll_cq ( &static_ibdev, &static_ipoib_send_cq,
 | 
		
	
		
			
			| 187 |  | -			temp_complete_send, temp_complete_recv );
 | 
		
	
		
			
			| 188 |  | -}
 | 
		
	
		
			
			| 189 |  | -
 | 
		
	
		
			
			| 190 | 191 |  /**
 | 
		
	
		
			
			| 191 | 192 |   * Handle TX completion
 | 
		
	
		
			
			| 192 | 193 |   *
 | 
		
	
	
		
			
			|  | @@ -233,6 +234,44 @@ static void mlx_rx_complete ( struct net_device *netdev,
 | 
		
	
		
			
			| 233 | 234 |  	netdev_rx ( netdev, iobuf );
 | 
		
	
		
			
			| 234 | 235 |  }
 | 
		
	
		
			
			| 235 | 236 |  
 | 
		
	
		
			
			|  | 237 | +static void arbel_poll_cq ( struct ib_device *ibdev,
 | 
		
	
		
			
			|  | 238 | +			    struct ib_completion_queue *cq,
 | 
		
	
		
			
			|  | 239 | +			    ib_completer_t complete_send,
 | 
		
	
		
			
			|  | 240 | +			    ib_completer_t complete_recv );
 | 
		
	
		
			
			|  | 241 | +
 | 
		
	
		
			
			|  | 242 | +static void temp_complete_send ( struct ib_device *ibdev __unused,
 | 
		
	
		
			
			|  | 243 | +				 struct ib_queue_pair *qp,
 | 
		
	
		
			
			|  | 244 | +				 struct ib_completion *completion,
 | 
		
	
		
			
			|  | 245 | +				 struct io_buffer *iobuf ) {
 | 
		
	
		
			
			|  | 246 | +	struct net_device *netdev = qp->priv;
 | 
		
	
		
			
			|  | 247 | +
 | 
		
	
		
			
			|  | 248 | +	DBG ( "Wahey! TX completion\n" );
 | 
		
	
		
			
			|  | 249 | +	netdev_tx_complete_err ( netdev, iobuf,
 | 
		
	
		
			
			|  | 250 | +				 ( completion->syndrome ? -EIO : 0 ) );
 | 
		
	
		
			
			|  | 251 | +}
 | 
		
	
		
			
			|  | 252 | +
 | 
		
	
		
			
			|  | 253 | +static void temp_complete_recv ( struct ib_device *ibdev __unused,
 | 
		
	
		
			
			|  | 254 | +				 struct ib_queue_pair *qp,
 | 
		
	
		
			
			|  | 255 | +				 struct ib_completion *completion,
 | 
		
	
		
			
			|  | 256 | +				 struct io_buffer *iobuf ) {
 | 
		
	
		
			
			|  | 257 | +	struct net_device *netdev = qp->priv;
 | 
		
	
		
			
			|  | 258 | +	struct mlx_nic *mlx = netdev->priv;
 | 
		
	
		
			
			|  | 259 | +
 | 
		
	
		
			
			|  | 260 | +	DBG ( "Yay! RX completion on %p len %zx:\n", iobuf, completion->len );
 | 
		
	
		
			
			|  | 261 | +	//	DBG_HD ( iobuf, sizeof ( *iobuf ) );
 | 
		
	
		
			
			|  | 262 | +	//	DBG_HD ( iobuf->data, 256 );
 | 
		
	
		
			
			|  | 263 | +	if ( completion->syndrome ) {
 | 
		
	
		
			
			|  | 264 | +		netdev_rx_err ( netdev, iobuf, -EIO );
 | 
		
	
		
			
			|  | 265 | +	} else {
 | 
		
	
		
			
			|  | 266 | +		iob_put ( iobuf, completion->len );
 | 
		
	
		
			
			|  | 267 | +		iob_pull ( iobuf, sizeof ( struct ib_global_route_header ) );
 | 
		
	
		
			
			|  | 268 | +		netdev_rx ( netdev, iobuf );
 | 
		
	
		
			
			|  | 269 | +	}
 | 
		
	
		
			
			|  | 270 | +
 | 
		
	
		
			
			|  | 271 | +	mlx->rx_fill--;
 | 
		
	
		
			
			|  | 272 | +}
 | 
		
	
		
			
			|  | 273 | +
 | 
		
	
		
			
			|  | 274 | +#if 0
 | 
		
	
		
			
			| 236 | 275 |  /**
 | 
		
	
		
			
			| 237 | 276 |   * Poll completion queue
 | 
		
	
		
			
			| 238 | 277 |   *
 | 
		
	
	
		
			
			|  | @@ -267,6 +306,32 @@ static void mlx_poll_cq ( struct net_device *netdev, cq_t cq,
 | 
		
	
		
			
			| 267 | 306 |  		free_wqe ( ib_cqe.wqe );
 | 
		
	
		
			
			| 268 | 307 |  	}
 | 
		
	
		
			
			| 269 | 308 |  }
 | 
		
	
		
			
			|  | 309 | +#endif
 | 
		
	
		
			
			|  | 310 | +
 | 
		
	
		
			
			|  | 311 | +static int arbel_post_recv ( struct ib_device *ibdev,
 | 
		
	
		
			
			|  | 312 | +			     struct ib_queue_pair *qp,
 | 
		
	
		
			
			|  | 313 | +			     struct io_buffer *iobuf );
 | 
		
	
		
			
			|  | 314 | +
 | 
		
	
		
			
			|  | 315 | +static void mlx_refill_rx ( struct net_device *netdev ) {
 | 
		
	
		
			
			|  | 316 | +	struct mlx_nic *mlx = netdev->priv;
 | 
		
	
		
			
			|  | 317 | +	struct io_buffer *iobuf;
 | 
		
	
		
			
			|  | 318 | +	int rc;
 | 
		
	
		
			
			|  | 319 | +
 | 
		
	
		
			
			|  | 320 | +	while ( mlx->rx_fill < MLX_RX_MAX_FILL ) {
 | 
		
	
		
			
			|  | 321 | +		iobuf = alloc_iob ( 2048 );
 | 
		
	
		
			
			|  | 322 | +		if ( ! iobuf )
 | 
		
	
		
			
			|  | 323 | +			break;
 | 
		
	
		
			
			|  | 324 | +		DBG ( "Posting RX buffer %p:\n", iobuf );
 | 
		
	
		
			
			|  | 325 | +		//		memset ( iobuf->data, 0xaa, 256 );
 | 
		
	
		
			
			|  | 326 | +		//		DBG_HD ( iobuf, sizeof ( *iobuf ) );
 | 
		
	
		
			
			|  | 327 | +		if ( ( rc = arbel_post_recv ( &static_ibdev, &static_ipoib_qp,
 | 
		
	
		
			
			|  | 328 | +					      iobuf ) ) != 0 ) {
 | 
		
	
		
			
			|  | 329 | +			free_iob ( iobuf );
 | 
		
	
		
			
			|  | 330 | +			break;
 | 
		
	
		
			
			|  | 331 | +		}
 | 
		
	
		
			
			|  | 332 | +		mlx->rx_fill++;
 | 
		
	
		
			
			|  | 333 | +	}
 | 
		
	
		
			
			|  | 334 | +}
 | 
		
	
		
			
			| 270 | 335 |  
 | 
		
	
		
			
			| 271 | 336 |  /**
 | 
		
	
		
			
			| 272 | 337 |   * Poll for completed and received packets
 | 
		
	
	
		
			
			|  | @@ -291,8 +356,13 @@ static void mlx_poll ( struct net_device *netdev ) {
 | 
		
	
		
			
			| 291 | 356 |  	}
 | 
		
	
		
			
			| 292 | 357 |  
 | 
		
	
		
			
			| 293 | 358 |  	/* Poll completion queues */
 | 
		
	
		
			
			| 294 |  | -	mlx_poll_cq_direct ( netdev );
 | 
		
	
		
			
			| 295 |  | -	mlx_poll_cq ( netdev, mlx->rcv_cqh, mlx_rx_complete );
 | 
		
	
		
			
			|  | 359 | +	arbel_poll_cq ( &static_ibdev, &static_ipoib_send_cq,
 | 
		
	
		
			
			|  | 360 | +			temp_complete_send, temp_complete_recv );
 | 
		
	
		
			
			|  | 361 | +	arbel_poll_cq ( &static_ibdev, &static_ipoib_recv_cq,
 | 
		
	
		
			
			|  | 362 | +			temp_complete_send, temp_complete_recv );
 | 
		
	
		
			
			|  | 363 | +	//	mlx_poll_cq ( netdev, mlx->rcv_cqh, mlx_rx_complete );
 | 
		
	
		
			
			|  | 364 | +
 | 
		
	
		
			
			|  | 365 | +	mlx_refill_rx ( netdev );
 | 
		
	
		
			
			| 296 | 366 |  }
 | 
		
	
		
			
			| 297 | 367 |  
 | 
		
	
		
			
			| 298 | 368 |  /**
 | 
		
	
	
		
			
			|  | @@ -397,12 +467,9 @@ static int arbel_post_send ( struct ib_device *ibdev,
 | 
		
	
		
			
			| 397 | 467 |  	memcpy ( &wqe->ud.u.dwords[4], gid, sizeof ( *gid ) );
 | 
		
	
		
			
			| 398 | 468 |  	MLX_FILL_1 ( &wqe->ud, 8, destination_qp, av->dest_qp );
 | 
		
	
		
			
			| 399 | 469 |  	MLX_FILL_1 ( &wqe->ud, 9, q_key, av->qkey );
 | 
		
	
		
			
			|  | 470 | +	MLX_FILL_1 ( &wqe->data[0], 0, byte_count, iob_len ( iobuf ) );
 | 
		
	
		
			
			| 400 | 471 |  	MLX_FILL_1 ( &wqe->data[0], 3,
 | 
		
	
		
			
			| 401 | 472 |  		     local_address_l, virt_to_bus ( iobuf->data ) );
 | 
		
	
		
			
			| 402 |  | -	MLX_FILL_1 ( &wqe->data[0], 0, byte_count, iob_len ( iobuf ) );
 | 
		
	
		
			
			| 403 |  | -
 | 
		
	
		
			
			| 404 |  | -	DBG ( "Work queue entry:\n" );
 | 
		
	
		
			
			| 405 |  | -	DBG_HD ( wqe, sizeof ( *wqe ) );
 | 
		
	
		
			
			| 406 | 473 |  
 | 
		
	
		
			
			| 407 | 474 |  	/* Update previous work queue entry's "next" field */
 | 
		
	
		
			
			| 408 | 475 |  	nds = ( ( offsetof ( typeof ( *wqe ), data ) +
 | 
		
	
	
		
			
			|  | @@ -413,16 +480,11 @@ static int arbel_post_send ( struct ib_device *ibdev,
 | 
		
	
		
			
			| 413 | 480 |  		     f, 1,
 | 
		
	
		
			
			| 414 | 481 |  		     always1, 1 );
 | 
		
	
		
			
			| 415 | 482 |  
 | 
		
	
		
			
			| 416 |  | -	DBG ( "Previous work queue entry's next field:\n" );
 | 
		
	
		
			
			| 417 |  | -	DBG_HD ( &prev_wqe->next, sizeof ( prev_wqe->next ) );
 | 
		
	
		
			
			| 418 |  | -
 | 
		
	
		
			
			| 419 | 483 |  	/* Update doorbell record */
 | 
		
	
		
			
			|  | 484 | +	barrier();
 | 
		
	
		
			
			| 420 | 485 |  	db_rec = &arbel->db_rec[arbel_send_wq->doorbell_idx];
 | 
		
	
		
			
			| 421 | 486 |  	MLX_FILL_1 ( &db_rec->qp, 0,
 | 
		
	
		
			
			| 422 | 487 |  		     counter, ( ( wq->next_idx + 1 ) & 0xffff ) );
 | 
		
	
		
			
			| 423 |  | -	barrier();
 | 
		
	
		
			
			| 424 |  | -	DBG ( "Doorbell record:\n" );
 | 
		
	
		
			
			| 425 |  | -	DBG_HD ( db_rec, 8 );
 | 
		
	
		
			
			| 426 | 488 |  
 | 
		
	
		
			
			| 427 | 489 |  	/* Ring doorbell register */
 | 
		
	
		
			
			| 428 | 490 |  	MLX_FILL_4 ( &db_reg.send, 0,
 | 
		
	
	
		
			
			|  | @@ -441,6 +503,51 @@ static int arbel_post_send ( struct ib_device *ibdev,
 | 
		
	
		
			
			| 441 | 503 |  	return 0;
 | 
		
	
		
			
			| 442 | 504 |  }
 | 
		
	
		
			
			| 443 | 505 |  
 | 
		
	
		
			
			|  | 506 | +/**
 | 
		
	
		
			
			|  | 507 | + * Post receive work queue entry
 | 
		
	
		
			
			|  | 508 | + *
 | 
		
	
		
			
			|  | 509 | + * @v ibdev		Infiniband device
 | 
		
	
		
			
			|  | 510 | + * @v qp		Queue pair
 | 
		
	
		
			
			|  | 511 | + * @v iobuf		I/O buffer
 | 
		
	
		
			
			|  | 512 | + * @ret rc		Return status code
 | 
		
	
		
			
			|  | 513 | + */
 | 
		
	
		
			
			|  | 514 | +static int arbel_post_recv ( struct ib_device *ibdev,
 | 
		
	
		
			
			|  | 515 | +			     struct ib_queue_pair *qp,
 | 
		
	
		
			
			|  | 516 | +			     struct io_buffer *iobuf ) {
 | 
		
	
		
			
			|  | 517 | +	struct arbel *arbel = ibdev->dev_priv;
 | 
		
	
		
			
			|  | 518 | +	struct ib_work_queue *wq = &qp->recv;
 | 
		
	
		
			
			|  | 519 | +	struct arbel_recv_work_queue *arbel_recv_wq = wq->dev_priv;
 | 
		
	
		
			
			|  | 520 | +	struct arbelprm_recv_wqe *wqe;
 | 
		
	
		
			
			|  | 521 | +	union arbelprm_doorbell_record *db_rec;
 | 
		
	
		
			
			|  | 522 | +	unsigned int wqe_idx_mask;
 | 
		
	
		
			
			|  | 523 | +
 | 
		
	
		
			
			|  | 524 | +	/* Allocate work queue entry */
 | 
		
	
		
			
			|  | 525 | +	wqe_idx_mask = ( wq->num_wqes - 1 );
 | 
		
	
		
			
			|  | 526 | +	if ( wq->iobufs[wq->next_idx & wqe_idx_mask] ) {
 | 
		
	
		
			
			|  | 527 | +		DBGC ( arbel, "Arbel %p receive queue full", arbel );
 | 
		
	
		
			
			|  | 528 | +		return -ENOBUFS;
 | 
		
	
		
			
			|  | 529 | +	}
 | 
		
	
		
			
			|  | 530 | +	wq->iobufs[wq->next_idx & wqe_idx_mask] = iobuf;
 | 
		
	
		
			
			|  | 531 | +	wqe = &arbel_recv_wq->wqe[wq->next_idx & wqe_idx_mask].recv;
 | 
		
	
		
			
			|  | 532 | +
 | 
		
	
		
			
			|  | 533 | +	/* Construct work queue entry */
 | 
		
	
		
			
			|  | 534 | +	MLX_FILL_1 ( &wqe->data[0], 0, byte_count, iob_tailroom ( iobuf ) );
 | 
		
	
		
			
			|  | 535 | +	MLX_FILL_1 ( &wqe->data[0], 1, l_key, arbel->reserved_lkey );
 | 
		
	
		
			
			|  | 536 | +	MLX_FILL_1 ( &wqe->data[0], 3,
 | 
		
	
		
			
			|  | 537 | +		     local_address_l, virt_to_bus ( iobuf->data ) );
 | 
		
	
		
			
			|  | 538 | +
 | 
		
	
		
			
			|  | 539 | +	/* Update doorbell record */
 | 
		
	
		
			
			|  | 540 | +	barrier();
 | 
		
	
		
			
			|  | 541 | +	db_rec = &arbel->db_rec[arbel_recv_wq->doorbell_idx];
 | 
		
	
		
			
			|  | 542 | +	MLX_FILL_1 ( &db_rec->qp, 0,
 | 
		
	
		
			
			|  | 543 | +		     counter, ( ( wq->next_idx + 1 ) & 0xffff ) );	
 | 
		
	
		
			
			|  | 544 | +
 | 
		
	
		
			
			|  | 545 | +	/* Update work queue's index */
 | 
		
	
		
			
			|  | 546 | +	wq->next_idx++;
 | 
		
	
		
			
			|  | 547 | +
 | 
		
	
		
			
			|  | 548 | +	return 0;	
 | 
		
	
		
			
			|  | 549 | +}
 | 
		
	
		
			
			|  | 550 | +
 | 
		
	
		
			
			| 444 | 551 |  /**
 | 
		
	
		
			
			| 445 | 552 |   * Handle completion
 | 
		
	
		
			
			| 446 | 553 |   *
 | 
		
	
	
		
			
			|  | @@ -458,7 +565,6 @@ static int arbel_complete ( struct ib_device *ibdev,
 | 
		
	
		
			
			| 458 | 565 |  			    ib_completer_t complete_recv ) {
 | 
		
	
		
			
			| 459 | 566 |  	struct arbel *arbel = ibdev->dev_priv;
 | 
		
	
		
			
			| 460 | 567 |  	struct ib_completion completion;
 | 
		
	
		
			
			| 461 |  | -	struct ib_queue_pair *qp;
 | 
		
	
		
			
			| 462 | 568 |  	struct ib_work_queue *wq;
 | 
		
	
		
			
			| 463 | 569 |  	struct io_buffer *iobuf;
 | 
		
	
		
			
			| 464 | 570 |  	struct arbel_send_work_queue *arbel_send_wq;
 | 
		
	
	
		
			
			|  | @@ -466,7 +572,7 @@ static int arbel_complete ( struct ib_device *ibdev,
 | 
		
	
		
			
			| 466 | 572 |  	ib_completer_t complete;
 | 
		
	
		
			
			| 467 | 573 |  	unsigned int opcode;
 | 
		
	
		
			
			| 468 | 574 |  	unsigned long qpn;
 | 
		
	
		
			
			| 469 |  | -	unsigned int is_send;
 | 
		
	
		
			
			|  | 575 | +	int is_send;
 | 
		
	
		
			
			| 470 | 576 |  	unsigned long wqe_adr;
 | 
		
	
		
			
			| 471 | 577 |  	unsigned int wqe_idx;
 | 
		
	
		
			
			| 472 | 578 |  	int rc = 0;
 | 
		
	
	
		
			
			|  | @@ -489,22 +595,20 @@ static int arbel_complete ( struct ib_device *ibdev,
 | 
		
	
		
			
			| 489 | 595 |  		/* Don't return immediately; propagate error to completer */
 | 
		
	
		
			
			| 490 | 596 |  	}
 | 
		
	
		
			
			| 491 | 597 |  
 | 
		
	
		
			
			| 492 |  | -	/* Identify queue pair */
 | 
		
	
		
			
			| 493 |  | -	qp = ib_find_qp ( &cq->queue_pairs, qpn );
 | 
		
	
		
			
			| 494 |  | -	if ( ! qp ) {
 | 
		
	
		
			
			| 495 |  | -		DBGC ( arbel, "Arbel %p CQN %lx unknown QPN %lx\n",
 | 
		
	
		
			
			| 496 |  | -		       arbel, cq->cqn, qpn );
 | 
		
	
		
			
			|  | 598 | +	/* Identify work queue */
 | 
		
	
		
			
			|  | 599 | +	wq = ib_find_wq ( cq, qpn, is_send );
 | 
		
	
		
			
			|  | 600 | +	if ( ! wq ) {
 | 
		
	
		
			
			|  | 601 | +		DBGC ( arbel, "Arbel %p CQN %lx unknown %s QPN %lx\n",
 | 
		
	
		
			
			|  | 602 | +		       arbel, cq->cqn, ( is_send ? "send" : "recv" ), qpn );
 | 
		
	
		
			
			| 497 | 603 |  		return -EIO;
 | 
		
	
		
			
			| 498 | 604 |  	}
 | 
		
	
		
			
			| 499 | 605 |  
 | 
		
	
		
			
			| 500 | 606 |  	/* Identify work queue entry index */
 | 
		
	
		
			
			| 501 | 607 |  	if ( is_send ) {
 | 
		
	
		
			
			| 502 |  | -		wq = &qp->send;
 | 
		
	
		
			
			| 503 | 608 |  		arbel_send_wq = wq->dev_priv;
 | 
		
	
		
			
			| 504 | 609 |  		wqe_idx = ( ( wqe_adr - virt_to_bus ( arbel_send_wq->wqe ) ) /
 | 
		
	
		
			
			| 505 | 610 |  			    sizeof ( arbel_send_wq->wqe[0] ) );
 | 
		
	
		
			
			| 506 | 611 |  	} else {
 | 
		
	
		
			
			| 507 |  | -		wq = &qp->recv;
 | 
		
	
		
			
			| 508 | 612 |  		arbel_recv_wq = wq->dev_priv;
 | 
		
	
		
			
			| 509 | 613 |  		wqe_idx = ( ( wqe_adr - virt_to_bus ( arbel_recv_wq->wqe ) ) /
 | 
		
	
		
			
			| 510 | 614 |  			    sizeof ( arbel_recv_wq->wqe[0] ) );
 | 
		
	
	
		
			
			|  | @@ -521,7 +625,7 @@ static int arbel_complete ( struct ib_device *ibdev,
 | 
		
	
		
			
			| 521 | 625 |  
 | 
		
	
		
			
			| 522 | 626 |  	/* Pass off to caller's completion handler */
 | 
		
	
		
			
			| 523 | 627 |  	complete = ( is_send ? complete_send : complete_recv );
 | 
		
	
		
			
			| 524 |  | -	complete ( ibdev, qp, &completion, iobuf );
 | 
		
	
		
			
			|  | 628 | +	complete ( ibdev, wq->qp, &completion, iobuf );
 | 
		
	
		
			
			| 525 | 629 |  
 | 
		
	
		
			
			| 526 | 630 |  	return rc;
 | 
		
	
		
			
			| 527 | 631 |  }			     
 | 
		
	
	
		
			
			|  | @@ -577,6 +681,7 @@ static void arbel_poll_cq ( struct ib_device *ibdev,
 | 
		
	
		
			
			| 577 | 681 |  /** Arbel Infiniband operations */
 | 
		
	
		
			
			| 578 | 682 |  static struct ib_device_operations arbel_ib_operations = {
 | 
		
	
		
			
			| 579 | 683 |  	.post_send	= arbel_post_send,
 | 
		
	
		
			
			|  | 684 | +	.post_recv	= arbel_post_recv,
 | 
		
	
		
			
			| 580 | 685 |  	.poll_cq	= arbel_poll_cq,
 | 
		
	
		
			
			| 581 | 686 |  };
 | 
		
	
		
			
			| 582 | 687 |  
 | 
		
	
	
		
			
			|  | @@ -636,14 +741,21 @@ static int arbel_probe ( struct pci_device *pci,
 | 
		
	
		
			
			| 636 | 741 |  	/* Hack up IB structures */
 | 
		
	
		
			
			| 637 | 742 |  	static_arbel.uar = memfree_pci_dev.uar;
 | 
		
	
		
			
			| 638 | 743 |  	static_arbel.db_rec = dev_ib_data.uar_context_base;
 | 
		
	
		
			
			|  | 744 | +	static_arbel.reserved_lkey = dev_ib_data.mkey;
 | 
		
	
		
			
			| 639 | 745 |  	static_arbel_ipoib_send_wq.wqe =
 | 
		
	
		
			
			| 640 | 746 |  		( ( struct udqp_st * ) qph )->snd_wq;
 | 
		
	
		
			
			|  | 747 | +	static_arbel_ipoib_recv_wq.wqe =
 | 
		
	
		
			
			|  | 748 | +		( ( struct udqp_st * ) qph )->rcv_wq;
 | 
		
	
		
			
			| 641 | 749 |  	static_arbel_ipoib_send_cq.cqe =
 | 
		
	
		
			
			| 642 | 750 |  		( ( struct cq_st * ) ib_data.ipoib_snd_cq )->cq_buf;
 | 
		
	
		
			
			|  | 751 | +	static_arbel_ipoib_recv_cq.cqe =
 | 
		
	
		
			
			|  | 752 | +		( ( struct cq_st * ) ib_data.ipoib_rcv_cq )->cq_buf;
 | 
		
	
		
			
			| 643 | 753 |  	static_ipoib_qp.qpn = ib_get_qpn ( qph );
 | 
		
	
		
			
			| 644 | 754 |  	static_ipoib_qp.priv = netdev;
 | 
		
	
		
			
			| 645 |  | -	list_add ( &static_ipoib_qp.list,
 | 
		
	
		
			
			| 646 |  | -		   &static_ipoib_send_cq.queue_pairs );
 | 
		
	
		
			
			|  | 755 | +	list_add ( &static_ipoib_qp.send.list,
 | 
		
	
		
			
			|  | 756 | +		   &static_ipoib_send_cq.work_queues );
 | 
		
	
		
			
			|  | 757 | +	list_add ( &static_ipoib_qp.recv.list,
 | 
		
	
		
			
			|  | 758 | +		   &static_ipoib_recv_cq.work_queues );
 | 
		
	
		
			
			| 647 | 759 |  
 | 
		
	
		
			
			| 648 | 760 |  	/* Register network device */
 | 
		
	
		
			
			| 649 | 761 |  	if ( ( rc = register_netdev ( netdev ) ) != 0 )
 |