Commit c3d9494e authored by Ursula Braun's avatar Ursula Braun Committed by Jakub Kicinski
Browse files

net/smc: no new connections on disappearing devices



Add a "going_away" indication to ISM devices and IB ports and
avoid creation of new connections on such disappearing devices.

And do not handle ISM events if ISM device is disappearing.

Signed-off-by: default avatarUrsula Braun <ubraun@linux.ibm.com>
Signed-off-by: default avatarKarsten Graul <kgraul@linux.ibm.com>
Signed-off-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
parent b3cb53c0
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -77,6 +77,7 @@ struct smcd_dev {
	bool pnetid_by_user;
	struct list_head lgr_list;
	spinlock_t lgr_lock;
	u8 going_away : 1;
};

struct smcd_dev *smcd_alloc_dev(struct device *parent, const char *name,
+23 −0
Original line number Diff line number Diff line
@@ -1060,6 +1060,27 @@ int smc_rmb_rtoken_handling(struct smc_connection *conn,
	return 0;
}

static void smc_core_going_away(void)
{
	struct smc_ib_device *smcibdev;
	struct smcd_dev *smcd;

	spin_lock(&smc_ib_devices.lock);
	list_for_each_entry(smcibdev, &smc_ib_devices.list, list) {
		int i;

		for (i = 0; i < SMC_MAX_PORTS; i++)
			set_bit(i, smcibdev->ports_going_away);
	}
	spin_unlock(&smc_ib_devices.lock);

	spin_lock(&smcd_dev_list.lock);
	list_for_each_entry(smcd, &smcd_dev_list.list, list) {
		smcd->going_away = 1;
	}
	spin_unlock(&smcd_dev_list.lock);
}

/* Called (from smc_exit) when module is removed */
void smc_core_exit(void)
{
@@ -1067,6 +1088,8 @@ void smc_core_exit(void)
	LIST_HEAD(lgr_freeing_list);
	struct smcd_dev *smcd;

	smc_core_going_away();

	spin_lock_bh(&smc_lgr_list.lock);
	list_splice_init(&smc_lgr_list.list, &lgr_freeing_list);
	spin_unlock_bh(&smc_lgr_list.lock);
+13 −2
Original line number Diff line number Diff line
@@ -242,8 +242,12 @@ static void smc_ib_port_event_work(struct work_struct *work)
	for_each_set_bit(port_idx, &smcibdev->port_event_mask, SMC_MAX_PORTS) {
		smc_ib_remember_port_attr(smcibdev, port_idx + 1);
		clear_bit(port_idx, &smcibdev->port_event_mask);
		if (!smc_ib_port_active(smcibdev, port_idx + 1))
		if (!smc_ib_port_active(smcibdev, port_idx + 1)) {
			set_bit(port_idx, smcibdev->ports_going_away);
			smc_port_terminate(smcibdev, port_idx + 1);
		} else {
			clear_bit(port_idx, smcibdev->ports_going_away);
		}
	}
}

@@ -259,8 +263,10 @@ static void smc_ib_global_event_handler(struct ib_event_handler *handler,
	switch (ibevent->event) {
	case IB_EVENT_DEVICE_FATAL:
		/* terminate all ports on device */
		for (port_idx = 0; port_idx < SMC_MAX_PORTS; port_idx++)
		for (port_idx = 0; port_idx < SMC_MAX_PORTS; port_idx++) {
			set_bit(port_idx, &smcibdev->port_event_mask);
			set_bit(port_idx, smcibdev->ports_going_away);
		}
		schedule_work(&smcibdev->port_event_work);
		break;
	case IB_EVENT_PORT_ERR:
@@ -269,6 +275,10 @@ static void smc_ib_global_event_handler(struct ib_event_handler *handler,
		port_idx = ibevent->element.port_num - 1;
		if (port_idx < SMC_MAX_PORTS) {
			set_bit(port_idx, &smcibdev->port_event_mask);
			if (ibevent->event == IB_EVENT_PORT_ERR)
				set_bit(port_idx, smcibdev->ports_going_away);
			else if (ibevent->event == IB_EVENT_PORT_ACTIVE)
				clear_bit(port_idx, smcibdev->ports_going_away);
			schedule_work(&smcibdev->port_event_work);
		}
		break;
@@ -307,6 +317,7 @@ static void smc_ib_qp_event_handler(struct ib_event *ibevent, void *priv)
		port_idx = ibevent->element.qp->port - 1;
		if (port_idx < SMC_MAX_PORTS) {
			set_bit(port_idx, &smcibdev->port_event_mask);
			set_bit(port_idx, smcibdev->ports_going_away);
			schedule_work(&smcibdev->port_event_work);
		}
		break;
+1 −0
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ struct smc_ib_device { /* ib-device infos for smc */
	u8			initialized : 1; /* ib dev CQ, evthdl done */
	struct work_struct	port_event_work;
	unsigned long		port_event_mask;
	DECLARE_BITMAP(ports_going_away, SMC_MAX_PORTS);
};

struct smc_buf_desc;
+3 −0
Original line number Diff line number Diff line
@@ -315,6 +315,7 @@ void smcd_unregister_dev(struct smcd_dev *smcd)
	spin_lock(&smcd_dev_list.lock);
	list_del(&smcd->list);
	spin_unlock(&smcd_dev_list.lock);
	smcd->going_away = 1;
	flush_workqueue(smcd->event_wq);
	destroy_workqueue(smcd->event_wq);
	smc_smcd_terminate(smcd, 0, VLAN_VID_MASK);
@@ -344,6 +345,8 @@ void smcd_handle_event(struct smcd_dev *smcd, struct smcd_event *event)
{
	struct smc_ism_event_work *wrk;

	if (smcd->going_away)
		return;
	/* copy event to event work queue, and let it be handled there */
	wrk = kmalloc(sizeof(*wrk), GFP_ATOMIC);
	if (!wrk)
Loading