diff options
Diffstat (limited to 'drivers/net/ehea/ehea_main.c')
| -rw-r--r-- | drivers/net/ehea/ehea_main.c | 60 | 
1 files changed, 59 insertions, 1 deletions
| diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 897719b49f9..a333b42111b 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -776,6 +776,53 @@ static int ehea_proc_rwqes(struct net_device *dev,  	return processed;  } +#define SWQE_RESTART_CHECK 0xdeadbeaff00d0000ull + +static void reset_sq_restart_flag(struct ehea_port *port) +{ +	int i; + +	for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) { +		struct ehea_port_res *pr = &port->port_res[i]; +		pr->sq_restart_flag = 0; +	} +} + +static void check_sqs(struct ehea_port *port) +{ +	struct ehea_swqe *swqe; +	int swqe_index; +	int i, k; + +	for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) { +		struct ehea_port_res *pr = &port->port_res[i]; +		k = 0; +		swqe = ehea_get_swqe(pr->qp, &swqe_index); +		memset(swqe, 0, SWQE_HEADER_SIZE); +		atomic_dec(&pr->swqe_avail); + +		swqe->tx_control |= EHEA_SWQE_PURGE; +		swqe->wr_id = SWQE_RESTART_CHECK; +		swqe->tx_control |= EHEA_SWQE_SIGNALLED_COMPLETION; +		swqe->tx_control |= EHEA_SWQE_IMM_DATA_PRESENT; +		swqe->immediate_data_length = 80; + +		ehea_post_swqe(pr->qp, swqe); + +		while (pr->sq_restart_flag == 0) { +			msleep(5); +			if (++k == 100) { +				ehea_error("HW/SW queues out of sync"); +				ehea_schedule_port_reset(pr->port); +				return; +			} +		} +	} + +	return; +} + +  static struct ehea_cqe *ehea_proc_cqes(struct ehea_port_res *pr, int my_quota)  {  	struct sk_buff *skb; @@ -793,6 +840,13 @@ static struct ehea_cqe *ehea_proc_cqes(struct ehea_port_res *pr, int my_quota)  		cqe_counter++;  		rmb(); + +		if (cqe->wr_id == SWQE_RESTART_CHECK) { +			pr->sq_restart_flag = 1; +			swqe_av++; +			break; +		} +  		if (cqe->status & EHEA_CQE_STAT_ERR_MASK) {  			ehea_error("Bad send completion status=0x%04X",  				   cqe->status); @@ -2675,8 +2729,10 @@ static void ehea_flush_sq(struct ehea_port *port)  		int k = 0;  		while (atomic_read(&pr->swqe_avail) < swqe_max) {  			msleep(5); -			if (++k == 20) +			if (++k == 20) { +				ehea_error("WARNING: sq not flushed completely");  				break; +			}  		}  	}  } @@ -2917,6 +2973,7 @@ static void ehea_rereg_mrs(struct work_struct *work)  					port_napi_disable(port);  					mutex_unlock(&port->port_lock);  				} +				reset_sq_restart_flag(port);  			}  			/* Unregister old memory region */ @@ -2951,6 +3008,7 @@ static void ehea_rereg_mrs(struct work_struct *work)  						mutex_lock(&port->port_lock);  						port_napi_enable(port);  						ret = ehea_restart_qps(dev); +						check_sqs(port);  						if (!ret)  							netif_wake_queue(dev);  						mutex_unlock(&port->port_lock); | 
