Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 78eb129d authored by Dean Luick's avatar Dean Luick Committed by Doug Ledford
Browse files

IB/hfi1: Add shared ASIC structure



Create a shared structure to exist between devices that share the
same ASIC.

Reviewed-by: default avatarMitko Haralanov <mitko.haralanov@intel.com>
Reviewed-by: default avatarEaswar Hariharan <easwar.hariharan@intel.com>
Signed-off-by: default avatarDean Luick <dean.luick@intel.com>
Signed-off-by: default avatarJubin John <jubin.john@intel.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent 3afb6f63
Loading
Loading
Loading
Loading
+25 −3
Original line number Diff line number Diff line
@@ -13800,15 +13800,20 @@ void hfi1_start_cleanup(struct hfi1_devdata *dd)
	((dev)->base_guid & ~(1ULL << GUID_HFI_INDEX_SHIFT))

/*
 * Information can be shared between the two HFIs on the same ASIC
 * in the same OS.  This function finds the peer device and sets
 * up a shared structure.
 *
 * Certain chip functions need to be initialized only once per asic
 * instead of per-device. This function finds the peer device and
 * checks whether that chip initialization needs to be done by this
 * device.
 */
static void asic_should_init(struct hfi1_devdata *dd)
static int init_asic_data(struct hfi1_devdata *dd)
{
	unsigned long flags;
	struct hfi1_devdata *tmp, *peer = NULL;
	int ret = 0;

	spin_lock_irqsave(&hfi1_devs_lock, flags);
	/* Find our peer device */
@@ -13826,7 +13831,22 @@ static void asic_should_init(struct hfi1_devdata *dd)
	 */
	if (!peer || !(peer->flags & HFI1_DO_INIT_ASIC))
		dd->flags |= HFI1_DO_INIT_ASIC;

	if (peer) {
		dd->asic_data = peer->asic_data;
	} else {
		dd->asic_data = kzalloc(sizeof(*dd->asic_data), GFP_KERNEL);
		if (!dd->asic_data) {
			ret = -ENOMEM;
			goto done;
		}
		mutex_init(&dd->asic_data->asic_resource_mutex);
	}
	dd->asic_data->dds[dd->hfi1_id] = dd; /* self back-pointer */

done:
	spin_unlock_irqrestore(&hfi1_devs_lock, flags);
	return ret;
}

/*
@@ -14076,8 +14096,10 @@ struct hfi1_devdata *hfi1_init_dd(struct pci_dev *pdev,
	/* needs to be done before we look for the peer device */
	read_guid(dd);

	/* should this device init the ASIC block? */
	asic_should_init(dd);
	/* set up shared ASIC data with peer device */
	ret = init_asic_data(dd);
	if (ret)
		goto bail_cleanup;

	/* obtain chip sizes, reset chip CSRs */
	init_chip(dd);
+9 −0
Original line number Diff line number Diff line
@@ -805,6 +805,12 @@ struct hfi1_temp {
	u8 triggers;      /* temperature triggers */
};

/* common data between shared ASIC HFIs */
struct hfi1_asic_data {
	struct hfi1_devdata *dds[2];	/* back pointers */
	struct mutex asic_resource_mutex;
};

/* device data struct now contains only "general per-device" info.
 * fields related to a physical IB port are in a hfi1_pportdata struct.
 */
@@ -880,6 +886,9 @@ struct hfi1_devdata {
	wait_queue_head_t		  sdma_unfreeze_wq;
	atomic_t			  sdma_unfreeze_count;

	/* common data between shared ASIC HFIs in this OS */
	struct hfi1_asic_data *asic_data;

	/* hfi1_pportdata, points to array of (physical) port-specific
	 * data structs, indexed by pidx (0..n-1)
	 */
+20 −0
Original line number Diff line number Diff line
@@ -974,6 +974,25 @@ void hfi1_free_ctxtdata(struct hfi1_devdata *dd, struct hfi1_ctxtdata *rcd)
	kfree(rcd);
}

/*
 * Release our hold on the shared asic data.  If we are the last one,
 * free the structure.  Must be holding hfi1_devs_lock.
 */
static void release_asic_data(struct hfi1_devdata *dd)
{
	int other;

	if (!dd->asic_data)
		return;
	dd->asic_data->dds[dd->hfi1_id] = NULL;
	other = dd->hfi1_id ? 0 : 1;
	if (!dd->asic_data->dds[other]) {
		/* we are the last holder, free it */
		kfree(dd->asic_data);
	}
	dd->asic_data = NULL;
}

void hfi1_free_devdata(struct hfi1_devdata *dd)
{
	unsigned long flags;
@@ -981,6 +1000,7 @@ void hfi1_free_devdata(struct hfi1_devdata *dd)
	spin_lock_irqsave(&hfi1_devs_lock, flags);
	idr_remove(&hfi1_unit_table, dd->unit);
	list_del(&dd->list);
	release_asic_data(dd);
	spin_unlock_irqrestore(&hfi1_devs_lock, flags);
	free_platform_config(dd);
	rcu_barrier(); /* wait for rcu callbacks to complete */