diff options
| -rw-r--r-- | drivers/net/ehea/ehea.h | 3 | ||||
| -rw-r--r-- | drivers/net/ehea/ehea_main.c | 95 | ||||
| -rw-r--r-- | drivers/net/ehea/ehea_phyp.c | 6 | ||||
| -rw-r--r-- | drivers/net/ehea/ehea_phyp.h | 6 | ||||
| -rw-r--r-- | drivers/net/ehea/ehea_qmr.c | 184 | ||||
| -rw-r--r-- | drivers/net/ehea/ehea_qmr.h | 7 | 
6 files changed, 187 insertions, 114 deletions
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index 1fefb2dddc1..f8899339baa 100644 --- a/drivers/net/ehea/ehea.h +++ b/drivers/net/ehea/ehea.h @@ -39,7 +39,7 @@  #include <asm/io.h>  #define DRV_NAME	"ehea" -#define DRV_VERSION	"EHEA_0053" +#define DRV_VERSION	"EHEA_0054"  #define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \  	| NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR) @@ -309,6 +309,7 @@ struct ehea_cq {   * Memory Region   */  struct ehea_mr { +	struct ehea_adapter *adapter;  	u64 handle;  	u64 vaddr;  	u32 lkey; diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index db0d79ebae8..8bceb4e6bb8 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -546,19 +546,19 @@ static int ehea_poll(struct net_device *dev, int *budget)  		cqe = ehea_poll_rq1(pr->qp, &wqe_index);  		cqe_skb = ehea_poll_cq(pr->send_cq); -		if (!cqe && !cqe_skb)  +		if (!cqe && !cqe_skb)  			return 0; -		if (!netif_rx_reschedule(dev, dev->quota))  +		if (!netif_rx_reschedule(dev, dev->quota))  			return 0;  	} -	 +  	cqe = ehea_proc_rwqes(dev, pr, budget);  	cqe_skb = ehea_proc_cqes(pr, 300);  	if (cqe || cqe_skb)  		pr->poll_counter++; -        +  	return 1;  } @@ -1011,7 +1011,7 @@ static int ehea_configure_port(struct ehea_port *port)  		else  			cb0->default_qpn_arr[i] =  				port->port_res[0].qp->init_attr.qp_nr; -	 +  	if (netif_msg_ifup(port))  		ehea_dump(cb0, sizeof(*cb0), "ehea_configure_port"); @@ -1033,52 +1033,35 @@ out:  	return ret;  } -static int ehea_gen_smrs(struct ehea_port_res *pr) +int ehea_gen_smrs(struct ehea_port_res *pr)  { -	u64 hret; +	int ret;  	struct ehea_adapter *adapter = pr->port->adapter; -	hret = ehea_h_register_smr(adapter->handle, adapter->mr.handle, -				   adapter->mr.vaddr, EHEA_MR_ACC_CTRL, -				   adapter->pd, &pr->send_mr); -	if (hret != H_SUCCESS) +	ret = ehea_gen_smr(adapter, &adapter->mr, &pr->send_mr); +	if (ret)  		goto out; -	hret = ehea_h_register_smr(adapter->handle, adapter->mr.handle, -				   adapter->mr.vaddr, EHEA_MR_ACC_CTRL, -				   adapter->pd, &pr->recv_mr); -	if (hret != H_SUCCESS) -		goto out_freeres; +	ret = ehea_gen_smr(adapter, &adapter->mr, &pr->recv_mr); +	if (ret) +		goto out_free;  	return 0; -out_freeres: -	hret = ehea_h_free_resource(adapter->handle, pr->send_mr.handle); -	if (hret != H_SUCCESS) -		ehea_error("failed freeing SMR"); +out_free: +	ehea_rem_mr(&pr->send_mr);  out: +	ehea_error("Generating SMRS failed\n");  	return -EIO;  } -static int ehea_rem_smrs(struct ehea_port_res *pr) +int ehea_rem_smrs(struct ehea_port_res *pr)  { -	struct ehea_adapter *adapter = pr->port->adapter; -	int ret = 0; -	u64 hret; - -	hret = ehea_h_free_resource(adapter->handle, pr->send_mr.handle); -	if (hret != H_SUCCESS) { -		ret = -EIO; -		ehea_error("failed freeing send SMR for pr=%p", pr); -	} - -	hret = ehea_h_free_resource(adapter->handle, pr->recv_mr.handle); -	if (hret != H_SUCCESS) { -		ret = -EIO; -		ehea_error("failed freeing recv SMR for pr=%p", pr); -	} - -	return ret; +	if ((ehea_rem_mr(&pr->send_mr)) +	    || (ehea_rem_mr(&pr->recv_mr))) +		return -EIO; +	else +		return 0;  }  static int ehea_init_q_skba(struct ehea_q_skb_arr *q_skba, int max_q_entries) @@ -2243,7 +2226,7 @@ static int ehea_down(struct net_device *dev)  	ehea_free_interrupts(dev);  	for (i = 0; i < port->num_def_qps; i++) -		while (test_bit(__LINK_STATE_RX_SCHED,  +		while (test_bit(__LINK_STATE_RX_SCHED,  				&port->port_res[i].d_netdev->state))  			msleep(1); @@ -2418,7 +2401,7 @@ static struct device *ehea_register_port(struct ehea_port *port,  		ehea_error("failed to register attributes, ret=%d", ret);  		goto out_unreg_of_dev;  	} -	 +  	return &port->ofdev.dev;  out_unreg_of_dev: @@ -2517,7 +2500,7 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,  	}  	ret = ehea_get_jumboframe_status(port, &jumbo); -	if (ret)  +	if (ret)  		ehea_error("failed determining jumbo frame status for %s",  			   port->netdev->name); @@ -2560,7 +2543,7 @@ static int ehea_setup_ports(struct ehea_adapter *adapter)  	lhea_dn = adapter->ebus_dev->ofdev.node;  	while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) { -		 +  		dn_log_port_id = (u32*)get_property(eth_dn, "ibm,hea-port-no",  						    NULL);  		if (!dn_log_port_id) { @@ -2574,7 +2557,7 @@ static int ehea_setup_ports(struct ehea_adapter *adapter)  							  eth_dn);  		if (adapter->port[i])  			ehea_info("%s -> logical port id #%d", -				  adapter->port[i]->netdev->name,  +				  adapter->port[i]->netdev->name,  				  *dn_log_port_id);  		i++;  	}; @@ -2590,8 +2573,8 @@ static int ehea_setup_ports(struct ehea_adapter *adapter)  	return -EINVAL;  } -static struct device_node *ehea_get_eth_dn(struct ehea_adapter *adapter,  -					   u32 logical_port_id)  +static struct device_node *ehea_get_eth_dn(struct ehea_adapter *adapter, +					   u32 logical_port_id)  {  	struct device_node *lhea_dn;  	struct device_node *eth_dn = NULL; @@ -2599,7 +2582,7 @@ static struct device_node *ehea_get_eth_dn(struct ehea_adapter *adapter,  	lhea_dn = adapter->ebus_dev->ofdev.node;  	while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) { -		 +  		dn_log_port_id = (u32*)get_property(eth_dn, "ibm,hea-port-no",  						    NULL);  		if (dn_log_port_id) @@ -2631,14 +2614,14 @@ static ssize_t ehea_probe_port(struct device *dev,  			  port->netdev->name);  		return -EINVAL;  	} -	 +  	eth_dn = ehea_get_eth_dn(adapter, logical_port_id);  	if (!eth_dn) {  		ehea_info("no logical port with id %d found", logical_port_id);  		return -EINVAL;  	} -		 +  	port = ehea_setup_single_port(adapter, logical_port_id, eth_dn);  	of_node_put(eth_dn); @@ -2652,8 +2635,8 @@ static ssize_t ehea_probe_port(struct device *dev,  		ehea_info("added %s (logical port id=%d)", port->netdev->name,  			  logical_port_id); -	} else  -		return -EIO;	        +	} else +		return -EIO;  	return (ssize_t) count;  } @@ -2748,7 +2731,7 @@ static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,  	dev->ofdev.dev.driver_data = adapter; -	ret = ehea_reg_mr_adapter(adapter); +	ret = ehea_reg_kernel_mr(adapter, &adapter->mr);  	if (ret) {  		dev_err(&dev->ofdev.dev, "reg_mr_adapter failed\n");  		goto out_free_ad; @@ -2813,7 +2796,7 @@ out_kill_eq:  	ehea_destroy_eq(adapter->neq);  out_free_res: -	ehea_h_free_resource(adapter->handle, adapter->mr.handle); +	ehea_rem_mr(&adapter->mr);  out_free_ad:  	kfree(adapter); @@ -2824,7 +2807,6 @@ out:  static int __devexit ehea_remove(struct ibmebus_dev *dev)  {  	struct ehea_adapter *adapter = dev->ofdev.dev.driver_data; -	u64 hret;  	int i;  	for (i = 0; i < EHEA_MAX_PORTS; i++) @@ -2841,12 +2823,7 @@ static int __devexit ehea_remove(struct ibmebus_dev *dev)  	tasklet_kill(&adapter->neq_tasklet);  	ehea_destroy_eq(adapter->neq); - -	hret = ehea_h_free_resource(adapter->handle, adapter->mr.handle); -	if (hret) { -		dev_err(&dev->ofdev.dev, "free_resource_mr failed"); -		return -EIO; -	} +	ehea_rem_mr(&adapter->mr);  	kfree(adapter);  	return 0;  } diff --git a/drivers/net/ehea/ehea_phyp.c b/drivers/net/ehea/ehea_phyp.c index bc3c0054726..95c4a7f9cc8 100644 --- a/drivers/net/ehea/ehea_phyp.c +++ b/drivers/net/ehea/ehea_phyp.c @@ -478,12 +478,14 @@ u64 ehea_h_disable_and_get_hea(const u64 adapter_handle, const u64 qp_handle)  				 0, 0, 0, 0, 0, 0);             /* R7-R12 */  } -u64 ehea_h_free_resource(const u64 adapter_handle, const u64 res_handle) +u64 ehea_h_free_resource(const u64 adapter_handle, const u64 res_handle, +			 u64 force_bit)  {  	return ehea_plpar_hcall_norets(H_FREE_RESOURCE,  				       adapter_handle,	   /* R4 */  				       res_handle,         /* R5 */ -				       0, 0, 0, 0, 0);     /* R6-R10 */ +				       force_bit, +				       0, 0, 0, 0);        /* R7-R10 */  }  u64 ehea_h_alloc_resource_mr(const u64 adapter_handle, const u64 vaddr, diff --git a/drivers/net/ehea/ehea_phyp.h b/drivers/net/ehea/ehea_phyp.h index 90acddb068a..d17a45a7e71 100644 --- a/drivers/net/ehea/ehea_phyp.h +++ b/drivers/net/ehea/ehea_phyp.h @@ -414,7 +414,11 @@ u64 ehea_h_register_rpage(const u64 adapter_handle,  u64 ehea_h_disable_and_get_hea(const u64 adapter_handle, const u64 qp_handle); -u64 ehea_h_free_resource(const u64 adapter_handle, const u64 res_handle); +#define FORCE_FREE 1 +#define NORMAL_FREE 0 + +u64 ehea_h_free_resource(const u64 adapter_handle, const u64 res_handle, +			 u64 force_bit);  u64 ehea_h_alloc_resource_mr(const u64 adapter_handle, const u64 vaddr,  			     const u64 length, const u32 access_ctrl, diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c index 96ff3b67999..f24a8862977 100644 --- a/drivers/net/ehea/ehea_qmr.c +++ b/drivers/net/ehea/ehea_qmr.c @@ -197,7 +197,7 @@ out_kill_hwq:  	hw_queue_dtor(&cq->hw_queue);  out_freeres: -	ehea_h_free_resource(adapter->handle, cq->fw_handle); +	ehea_h_free_resource(adapter->handle, cq->fw_handle, FORCE_FREE);  out_freemem:  	kfree(cq); @@ -206,25 +206,38 @@ out_nomem:  	return NULL;  } -int ehea_destroy_cq(struct ehea_cq *cq) +u64 ehea_destroy_cq_res(struct ehea_cq *cq, u64 force)  { -	u64 adapter_handle, hret; +	u64 hret; +	u64 adapter_handle = cq->adapter->handle; + +        /* deregister all previous registered pages */ +	hret = ehea_h_free_resource(adapter_handle, cq->fw_handle, force); +	if (hret != H_SUCCESS) +		return hret; + +	hw_queue_dtor(&cq->hw_queue); +	kfree(cq); + +	return hret; +} +int ehea_destroy_cq(struct ehea_cq *cq) +{ +	u64 hret;  	if (!cq)  		return 0; -	adapter_handle = cq->adapter->handle; +	if ((hret = ehea_destroy_cq_res(cq, NORMAL_FREE)) == H_R_STATE) { +		ehea_error_data(cq->adapter, cq->fw_handle); +		hret = ehea_destroy_cq_res(cq, FORCE_FREE); +	} -	/* deregister all previous registered pages */ -	hret = ehea_h_free_resource(adapter_handle, cq->fw_handle);  	if (hret != H_SUCCESS) {  		ehea_error("destroy CQ failed");  		return -EIO;  	} -	hw_queue_dtor(&cq->hw_queue); -	kfree(cq); -  	return 0;  } @@ -297,7 +310,7 @@ out_kill_hwq:  	hw_queue_dtor(&eq->hw_queue);  out_freeres: -	ehea_h_free_resource(adapter->handle, eq->fw_handle); +	ehea_h_free_resource(adapter->handle, eq->fw_handle, FORCE_FREE);  out_freemem:  	kfree(eq); @@ -316,27 +329,41 @@ struct ehea_eqe *ehea_poll_eq(struct ehea_eq *eq)  	return eqe;  } -int ehea_destroy_eq(struct ehea_eq *eq) +u64 ehea_destroy_eq_res(struct ehea_eq *eq, u64 force)  {  	u64 hret;  	unsigned long flags; -	if (!eq) -		return 0; -  	spin_lock_irqsave(&eq->spinlock, flags); -	hret = ehea_h_free_resource(eq->adapter->handle, eq->fw_handle); +	hret = ehea_h_free_resource(eq->adapter->handle, eq->fw_handle, force);  	spin_unlock_irqrestore(&eq->spinlock, flags); -	if (hret != H_SUCCESS) { -		ehea_error("destroy_eq failed"); -		return -EIO; -	} +	if (hret != H_SUCCESS) +		return hret;  	hw_queue_dtor(&eq->hw_queue);  	kfree(eq); +	return hret; +} + +int ehea_destroy_eq(struct ehea_eq *eq) +{ +	u64 hret; +	if (!eq) +		return 0; + +	if ((hret = ehea_destroy_eq_res(eq, NORMAL_FREE)) == H_R_STATE) { +		ehea_error_data(eq->adapter, eq->fw_handle); +		hret = ehea_destroy_eq_res(eq, FORCE_FREE); +	} + +	if (hret != H_SUCCESS) { +		ehea_error("destroy EQ failed"); +		return -EIO; +        } +  	return 0;  } @@ -471,41 +498,56 @@ out_kill_hwsq:  out_freeres:  	ehea_h_disable_and_get_hea(adapter->handle, qp->fw_handle); -	ehea_h_free_resource(adapter->handle, qp->fw_handle); +	ehea_h_free_resource(adapter->handle, qp->fw_handle, FORCE_FREE);  out_freemem:  	kfree(qp);  	return NULL;  } -int ehea_destroy_qp(struct ehea_qp *qp) +u64 ehea_destroy_qp_res(struct ehea_qp *qp, u64 force)  { -	u64 hret; -	struct ehea_qp_init_attr *qp_attr = &qp->init_attr; +        u64 hret; +        struct ehea_qp_init_attr *qp_attr = &qp->init_attr; -	if (!qp) -		return 0; -	ehea_h_disable_and_get_hea(qp->adapter->handle, qp->fw_handle); -	hret = ehea_h_free_resource(qp->adapter->handle, qp->fw_handle); -	if (hret != H_SUCCESS) { -		ehea_error("destroy_qp failed"); -		return -EIO; -	} +        ehea_h_disable_and_get_hea(qp->adapter->handle, qp->fw_handle); +        hret = ehea_h_free_resource(qp->adapter->handle, qp->fw_handle, force); +        if (hret != H_SUCCESS) +                return hret; -	hw_queue_dtor(&qp->hw_squeue); -	hw_queue_dtor(&qp->hw_rqueue1); +        hw_queue_dtor(&qp->hw_squeue); +        hw_queue_dtor(&qp->hw_rqueue1); -   	if (qp_attr->rq_count > 1) -		hw_queue_dtor(&qp->hw_rqueue2); -   	if (qp_attr->rq_count > 2) -		hw_queue_dtor(&qp->hw_rqueue3); -	kfree(qp); +        if (qp_attr->rq_count > 1) +                hw_queue_dtor(&qp->hw_rqueue2); +        if (qp_attr->rq_count > 2) +                hw_queue_dtor(&qp->hw_rqueue3); +        kfree(qp); -	return 0; +        return hret;  } -int ehea_reg_mr_adapter(struct ehea_adapter *adapter) +int ehea_destroy_qp(struct ehea_qp *qp) +{ +        u64 hret; +        if (!qp) +                return 0; + +        if ((hret = ehea_destroy_qp_res(qp, NORMAL_FREE)) == H_R_STATE) { +                ehea_error_data(qp->adapter, qp->fw_handle); +                hret = ehea_destroy_qp_res(qp, FORCE_FREE); +        } + +        if (hret != H_SUCCESS) { +                ehea_error("destroy QP failed"); +                return -EIO; +        } + +        return 0; +} + +int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr)  {  	int i, k, ret;  	u64 hret, pt_abs, start, end, nr_pages; @@ -526,14 +568,14 @@ int ehea_reg_mr_adapter(struct ehea_adapter *adapter)  	hret = ehea_h_alloc_resource_mr(adapter->handle, start, end - start,  					acc_ctrl, adapter->pd, -					&adapter->mr.handle, &adapter->mr.lkey); +					&mr->handle, &mr->lkey);  	if (hret != H_SUCCESS) {  		ehea_error("alloc_resource_mr failed");  		ret = -EIO;  		goto out;  	} -	adapter->mr.vaddr = KERNELBASE; +	mr->vaddr = KERNELBASE;  	k = 0;  	while (nr_pages > 0) { @@ -545,7 +587,7 @@ int ehea_reg_mr_adapter(struct ehea_adapter *adapter)  							     EHEA_PAGESIZE)));  			hret = ehea_h_register_rpage_mr(adapter->handle, -							adapter->mr.handle, 0, +							mr->handle, 0,  							0, (u64)pt_abs,  							num_pages);  			nr_pages -= num_pages; @@ -554,34 +596,68 @@ int ehea_reg_mr_adapter(struct ehea_adapter *adapter)  							  (k * EHEA_PAGESIZE)));  			hret = ehea_h_register_rpage_mr(adapter->handle, -							adapter->mr.handle, 0, +							mr->handle, 0,  							0, abs_adr,1);  			nr_pages--;  		}  		if ((hret != H_SUCCESS) && (hret != H_PAGE_REGISTERED)) {  			ehea_h_free_resource(adapter->handle, -						adapter->mr.handle); -			ehea_error("register_rpage_mr failed: hret = %lX", -				   hret); +					     mr->handle, FORCE_FREE); +			ehea_error("register_rpage_mr failed");  			ret = -EIO;  			goto out;  		}  	}  	if (hret != H_SUCCESS) { -		ehea_h_free_resource(adapter->handle, adapter->mr.handle); -		ehea_error("register_rpage failed for last page: hret = %lX", -			   hret); +		ehea_h_free_resource(adapter->handle, mr->handle, +				     FORCE_FREE); +		ehea_error("register_rpage failed for last page");  		ret = -EIO;  		goto out;  	} + +	mr->adapter = adapter;  	ret = 0;  out:  	kfree(pt);  	return ret;  } +int ehea_rem_mr(struct ehea_mr *mr) +{ +	u64 hret; + +	if (!mr || !mr->adapter) +		return -EINVAL; + +	hret = ehea_h_free_resource(mr->adapter->handle, mr->handle, +				    FORCE_FREE); +	if (hret != H_SUCCESS) { +		ehea_error("destroy MR failed"); +		return -EIO; +	} + +	return 0; +} + +int ehea_gen_smr(struct ehea_adapter *adapter, struct ehea_mr *old_mr, +		 struct ehea_mr *shared_mr) +{ +	u64 hret; + +	hret = ehea_h_register_smr(adapter->handle, old_mr->handle, +				   old_mr->vaddr, EHEA_MR_ACC_CTRL, +				   adapter->pd, shared_mr); +	if (hret != H_SUCCESS) +		return -EIO; + +	shared_mr->adapter = adapter; + +	return 0; +} +  void print_error_data(u64 *data)  {  	int length; @@ -597,6 +673,14 @@ void print_error_data(u64 *data)  		ehea_error("QP (resource=%lX) state: AER=0x%lX, AERR=0x%lX, "  			   "port=%lX", resource, data[6], data[12], data[22]); +	if (type == 0x4) /* Completion Queue */ +		ehea_error("CQ (resource=%lX) state: AER=0x%lX", resource, +			   data[6]); + +	if (type == 0x3) /* Event Queue */ +		ehea_error("EQ (resource=%lX) state: AER=0x%lX", resource, +			   data[6]); +  	ehea_dump(data, length, "error data");  } diff --git a/drivers/net/ehea/ehea_qmr.h b/drivers/net/ehea/ehea_qmr.h index 99d6b70a087..24603312eb8 100644 --- a/drivers/net/ehea/ehea_qmr.h +++ b/drivers/net/ehea/ehea_qmr.h @@ -361,7 +361,12 @@ struct ehea_qp *ehea_create_qp(struct ehea_adapter * adapter, u32 pd,  int ehea_destroy_qp(struct ehea_qp *qp); -int ehea_reg_mr_adapter(struct ehea_adapter *adapter); +int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr); + +int ehea_gen_smr(struct ehea_adapter *adapter, struct ehea_mr *old_mr, +		 struct ehea_mr *shared_mr); + +int ehea_rem_mr(struct ehea_mr *mr);  void ehea_error_data(struct ehea_adapter *adapter, u64 res_handle);  |