diff options
Diffstat (limited to 'drivers/infiniband/hw/qib/qib_init.c')
| -rw-r--r-- | drivers/infiniband/hw/qib/qib_init.c | 104 | 
1 files changed, 71 insertions, 33 deletions
diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c index 24e802f4ea2..8d3c78ddc90 100644 --- a/drivers/infiniband/hw/qib/qib_init.c +++ b/drivers/infiniband/hw/qib/qib_init.c @@ -130,7 +130,6 @@ void qib_set_ctxtcnt(struct qib_devdata *dd)  int qib_create_ctxts(struct qib_devdata *dd)  {  	unsigned i; -	int ret;  	int local_node_id = pcibus_to_node(dd->pcidev->bus);  	if (local_node_id < 0) @@ -145,8 +144,7 @@ int qib_create_ctxts(struct qib_devdata *dd)  	if (!dd->rcd) {  		qib_dev_err(dd,  			"Unable to allocate ctxtdata array, failing\n"); -		ret = -ENOMEM; -		goto done; +		return -ENOMEM;  	}  	/* create (one or more) kctxt */ @@ -163,15 +161,14 @@ int qib_create_ctxts(struct qib_devdata *dd)  		if (!rcd) {  			qib_dev_err(dd,  				"Unable to allocate ctxtdata for Kernel ctxt, failing\n"); -			ret = -ENOMEM; -			goto done; +			kfree(dd->rcd); +			dd->rcd = NULL; +			return -ENOMEM;  		}  		rcd->pkeys[0] = QIB_DEFAULT_P_KEY;  		rcd->seq_cnt = 1;  	} -	ret = 0; -done: -	return ret; +	return 0;  }  /* @@ -233,7 +230,7 @@ struct qib_ctxtdata *qib_create_ctxtdata(struct qib_pportdata *ppd, u32 ctxt,  /*   * Common code for initializing the physical port structure.   */ -void qib_init_pportdata(struct qib_pportdata *ppd, struct qib_devdata *dd, +int qib_init_pportdata(struct qib_pportdata *ppd, struct qib_devdata *dd,  			u8 hw_pidx, u8 port)  {  	int size; @@ -243,6 +240,7 @@ void qib_init_pportdata(struct qib_pportdata *ppd, struct qib_devdata *dd,  	spin_lock_init(&ppd->sdma_lock);  	spin_lock_init(&ppd->lflags_lock); +	spin_lock_init(&ppd->cc_shadow_lock);  	init_waitqueue_head(&ppd->state_wait);  	init_timer(&ppd->symerr_clear_timer); @@ -250,8 +248,10 @@ void qib_init_pportdata(struct qib_pportdata *ppd, struct qib_devdata *dd,  	ppd->symerr_clear_timer.data = (unsigned long)ppd;  	ppd->qib_wq = NULL; - -	spin_lock_init(&ppd->cc_shadow_lock); +	ppd->ibport_data.pmastats = +		alloc_percpu(struct qib_pma_counters); +	if (!ppd->ibport_data.pmastats) +		return -ENOMEM;  	if (qib_cc_table_size < IB_CCT_MIN_ENTRIES)  		goto bail; @@ -299,7 +299,7 @@ void qib_init_pportdata(struct qib_pportdata *ppd, struct qib_devdata *dd,  		goto bail_3;  	} -	return; +	return 0;  bail_3:  	kfree(ppd->ccti_entries_shadow); @@ -313,7 +313,7 @@ bail_1:  bail:  	/* User is intentionally disabling the congestion control agent */  	if (!qib_cc_table_size) -		return; +		return 0;  	if (qib_cc_table_size < IB_CCT_MIN_ENTRIES) {  		qib_cc_table_size = 0; @@ -324,7 +324,7 @@ bail:  	qib_dev_err(dd, "Congestion Control Agent disabled for port %d\n",  		port); -	return; +	return 0;  }  static int init_pioavailregs(struct qib_devdata *dd) @@ -525,6 +525,7 @@ static void enable_chip(struct qib_devdata *dd)  static void verify_interrupt(unsigned long opaque)  {  	struct qib_devdata *dd = (struct qib_devdata *) opaque; +	u64 int_counter;  	if (!dd)  		return; /* being torn down */ @@ -533,7 +534,8 @@ static void verify_interrupt(unsigned long opaque)  	 * If we don't have a lid or any interrupts, let the user know and  	 * don't bother checking again.  	 */ -	if (dd->int_counter == 0) { +	int_counter = qib_int_counter(dd) - dd->z_int_counter; +	if (int_counter == 0) {  		if (!dd->f_intr_fallback(dd))  			dev_err(&dd->pcidev->dev,  				"No interrupts detected, not usable.\n"); @@ -633,6 +635,12 @@ wq_error:  	return -ENOMEM;  } +static void qib_free_pportdata(struct qib_pportdata *ppd) +{ +	free_percpu(ppd->ibport_data.pmastats); +	ppd->ibport_data.pmastats = NULL; +} +  /**   * qib_init - do the actual initialization sequence on the chip   * @dd: the qlogic_ib device @@ -920,6 +928,7 @@ static void qib_shutdown_device(struct qib_devdata *dd)  			destroy_workqueue(ppd->qib_wq);  			ppd->qib_wq = NULL;  		} +		qib_free_pportdata(ppd);  	}  	qib_update_eeprom_log(dd); @@ -1079,9 +1088,34 @@ void qib_free_devdata(struct qib_devdata *dd)  #ifdef CONFIG_DEBUG_FS  	qib_dbg_ibdev_exit(&dd->verbs_dev);  #endif +	free_percpu(dd->int_counter);  	ib_dealloc_device(&dd->verbs_dev.ibdev);  } +u64 qib_int_counter(struct qib_devdata *dd) +{ +	int cpu; +	u64 int_counter = 0; + +	for_each_possible_cpu(cpu) +		int_counter += *per_cpu_ptr(dd->int_counter, cpu); +	return int_counter; +} + +u64 qib_sps_ints(void) +{ +	unsigned long flags; +	struct qib_devdata *dd; +	u64 sps_ints = 0; + +	spin_lock_irqsave(&qib_devs_lock, flags); +	list_for_each_entry(dd, &qib_dev_list, list) { +		sps_ints += qib_int_counter(dd); +	} +	spin_unlock_irqrestore(&qib_devs_lock, flags); +	return sps_ints; +} +  /*   * Allocate our primary per-unit data structure.  Must be done via verbs   * allocator, because the verbs cleanup process both does cleanup and @@ -1097,14 +1131,10 @@ struct qib_devdata *qib_alloc_devdata(struct pci_dev *pdev, size_t extra)  	int ret;  	dd = (struct qib_devdata *) ib_alloc_device(sizeof(*dd) + extra); -	if (!dd) { -		dd = ERR_PTR(-ENOMEM); -		goto bail; -	} +	if (!dd) +		return ERR_PTR(-ENOMEM); -#ifdef CONFIG_DEBUG_FS -	qib_dbg_ibdev_init(&dd->verbs_dev); -#endif +	INIT_LIST_HEAD(&dd->list);  	idr_preload(GFP_KERNEL);  	spin_lock_irqsave(&qib_devs_lock, flags); @@ -1121,11 +1151,13 @@ struct qib_devdata *qib_alloc_devdata(struct pci_dev *pdev, size_t extra)  	if (ret < 0) {  		qib_early_err(&pdev->dev,  			      "Could not allocate unit ID: error %d\n", -ret); -#ifdef CONFIG_DEBUG_FS -		qib_dbg_ibdev_exit(&dd->verbs_dev); -#endif -		ib_dealloc_device(&dd->verbs_dev.ibdev); -		dd = ERR_PTR(ret); +		goto bail; +	} +	dd->int_counter = alloc_percpu(u64); +	if (!dd->int_counter) { +		ret = -ENOMEM; +		qib_early_err(&pdev->dev, +			      "Could not allocate per-cpu int_counter\n");  		goto bail;  	} @@ -1139,9 +1171,15 @@ struct qib_devdata *qib_alloc_devdata(struct pci_dev *pdev, size_t extra)  			qib_early_err(&pdev->dev,  				"Could not alloc cpulist info, cpu affinity might be wrong\n");  	} - -bail: +#ifdef CONFIG_DEBUG_FS +	qib_dbg_ibdev_init(&dd->verbs_dev); +#endif  	return dd; +bail: +	if (!list_empty(&dd->list)) +		list_del_init(&dd->list); +	ib_dealloc_device(&dd->verbs_dev.ibdev); +	return ERR_PTR(ret);;  }  /* @@ -1234,7 +1272,7 @@ static int qib_notify_dca(struct notifier_block *nb, unsigned long event,   * Do all the generic driver unit- and chip-independent memory   * allocation and initialization.   */ -static int __init qlogic_ib_init(void) +static int __init qib_ib_init(void)  {  	int ret; @@ -1278,12 +1316,12 @@ bail:  	return ret;  } -module_init(qlogic_ib_init); +module_init(qib_ib_init);  /*   * Do the non-unit driver cleanup, memory free, etc. at unload.   */ -static void __exit qlogic_ib_cleanup(void) +static void __exit qib_ib_cleanup(void)  {  	int ret; @@ -1308,7 +1346,7 @@ static void __exit qlogic_ib_cleanup(void)  	qib_dev_cleanup();  } -module_exit(qlogic_ib_cleanup); +module_exit(qib_ib_cleanup);  /* this can only be called after a successful initialization */  static void cleanup_device_data(struct qib_devdata *dd)  | 
