mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	net/smc: add new link state and related helpers
Before a link can be reused it must have been cleared. Lowest current link state is INACTIVE, which does not mean that the link is already cleared. Add a new state UNUSED that is set when the link is cleared and can be reused. Add helper smc_llc_usable_link() to find an active link in a link group, and smc_link_usable() to determine if a link is usable. Signed-off-by: Karsten Graul <kgraul@linux.ibm.com> Reviewed-by: Ursula Braun <ubraun@linux.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									e07d31dc16
								
							
						
					
					
						commit
						d854fcbfae
					
				
					 5 changed files with 42 additions and 20 deletions
				
			
		| 
						 | 
					@ -260,7 +260,7 @@ static void smc_lgr_free_work(struct work_struct *work)
 | 
				
			||||||
		for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
 | 
							for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
 | 
				
			||||||
			struct smc_link *lnk = &lgr->lnk[i];
 | 
								struct smc_link *lnk = &lgr->lnk[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (lnk->state != SMC_LNK_INACTIVE)
 | 
								if (smc_link_usable(lnk))
 | 
				
			||||||
				smc_llc_link_inactive(lnk);
 | 
									smc_llc_link_inactive(lnk);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -286,7 +286,7 @@ static u8 smcr_next_link_id(struct smc_link_group *lgr)
 | 
				
			||||||
		if (!link_id)	/* skip zero as link_id */
 | 
							if (!link_id)	/* skip zero as link_id */
 | 
				
			||||||
			link_id = ++lgr->next_link_id;
 | 
								link_id = ++lgr->next_link_id;
 | 
				
			||||||
		for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
 | 
							for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
 | 
				
			||||||
			if (lgr->lnk[i].state != SMC_LNK_INACTIVE &&
 | 
								if (smc_link_usable(&lgr->lnk[i]) &&
 | 
				
			||||||
			    lgr->lnk[i].link_id == link_id)
 | 
								    lgr->lnk[i].link_id == link_id)
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -350,6 +350,7 @@ static int smcr_link_init(struct smc_link_group *lgr, struct smc_link *lnk,
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	put_device(&ini->ib_dev->ibdev->dev);
 | 
						put_device(&ini->ib_dev->ibdev->dev);
 | 
				
			||||||
	memset(lnk, 0, sizeof(struct smc_link));
 | 
						memset(lnk, 0, sizeof(struct smc_link));
 | 
				
			||||||
 | 
						lnk->state = SMC_LNK_UNUSED;
 | 
				
			||||||
	if (!atomic_dec_return(&ini->ib_dev->lnk_cnt))
 | 
						if (!atomic_dec_return(&ini->ib_dev->lnk_cnt))
 | 
				
			||||||
		wake_up(&ini->ib_dev->lnks_deleted);
 | 
							wake_up(&ini->ib_dev->lnks_deleted);
 | 
				
			||||||
	return rc;
 | 
						return rc;
 | 
				
			||||||
| 
						 | 
					@ -500,6 +501,8 @@ void smc_conn_free(struct smc_connection *conn)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void smcr_link_clear(struct smc_link *lnk)
 | 
					static void smcr_link_clear(struct smc_link *lnk)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct smc_ib_device *smcibdev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (lnk->peer_qpn == 0)
 | 
						if (lnk->peer_qpn == 0)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	lnk->peer_qpn = 0;
 | 
						lnk->peer_qpn = 0;
 | 
				
			||||||
| 
						 | 
					@ -510,8 +513,11 @@ static void smcr_link_clear(struct smc_link *lnk)
 | 
				
			||||||
	smc_ib_dealloc_protection_domain(lnk);
 | 
						smc_ib_dealloc_protection_domain(lnk);
 | 
				
			||||||
	smc_wr_free_link_mem(lnk);
 | 
						smc_wr_free_link_mem(lnk);
 | 
				
			||||||
	put_device(&lnk->smcibdev->ibdev->dev);
 | 
						put_device(&lnk->smcibdev->ibdev->dev);
 | 
				
			||||||
	if (!atomic_dec_return(&lnk->smcibdev->lnk_cnt))
 | 
						smcibdev = lnk->smcibdev;
 | 
				
			||||||
		wake_up(&lnk->smcibdev->lnks_deleted);
 | 
						memset(lnk, 0, sizeof(struct smc_link));
 | 
				
			||||||
 | 
						lnk->state = SMC_LNK_UNUSED;
 | 
				
			||||||
 | 
						if (!atomic_dec_return(&smcibdev->lnk_cnt))
 | 
				
			||||||
 | 
							wake_up(&smcibdev->lnks_deleted);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void smcr_buf_free(struct smc_link_group *lgr, bool is_rmb,
 | 
					static void smcr_buf_free(struct smc_link_group *lgr, bool is_rmb,
 | 
				
			||||||
| 
						 | 
					@ -604,8 +610,7 @@ static void smc_lgr_free(struct smc_link_group *lgr)
 | 
				
			||||||
			wake_up(&lgr->smcd->lgrs_deleted);
 | 
								wake_up(&lgr->smcd->lgrs_deleted);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
 | 
							for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
 | 
				
			||||||
			if (lgr->lnk[i].state == SMC_LNK_INACTIVE)
 | 
								if (lgr->lnk[i].state != SMC_LNK_UNUSED)
 | 
				
			||||||
				continue;
 | 
					 | 
				
			||||||
				smcr_link_clear(&lgr->lnk[i]);
 | 
									smcr_link_clear(&lgr->lnk[i]);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (!atomic_dec_return(&lgr_cnt))
 | 
							if (!atomic_dec_return(&lgr_cnt))
 | 
				
			||||||
| 
						 | 
					@ -686,7 +691,7 @@ static void smc_lgr_cleanup(struct smc_link_group *lgr)
 | 
				
			||||||
		for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
 | 
							for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
 | 
				
			||||||
			struct smc_link *lnk = &lgr->lnk[i];
 | 
								struct smc_link *lnk = &lgr->lnk[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (lnk->state != SMC_LNK_INACTIVE)
 | 
								if (smc_link_usable(lnk))
 | 
				
			||||||
				smc_llc_link_inactive(lnk);
 | 
									smc_llc_link_inactive(lnk);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -764,7 +769,7 @@ void smc_port_terminate(struct smc_ib_device *smcibdev, u8 ibport)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		/* tbd - terminate only when no more links are active */
 | 
							/* tbd - terminate only when no more links are active */
 | 
				
			||||||
		for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
 | 
							for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
 | 
				
			||||||
			if (lgr->lnk[i].state == SMC_LNK_INACTIVE ||
 | 
								if (!smc_link_usable(&lgr->lnk[i]) ||
 | 
				
			||||||
			    lgr->lnk[i].state == SMC_LNK_DELETING)
 | 
								    lgr->lnk[i].state == SMC_LNK_DELETING)
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			if (lgr->lnk[i].smcibdev == smcibdev &&
 | 
								if (lgr->lnk[i].smcibdev == smcibdev &&
 | 
				
			||||||
| 
						 | 
					@ -1161,8 +1166,7 @@ static int smcr_buf_map_usable_links(struct smc_link_group *lgr,
 | 
				
			||||||
	for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
 | 
						for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
 | 
				
			||||||
		struct smc_link *lnk = &lgr->lnk[i];
 | 
							struct smc_link *lnk = &lgr->lnk[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (lnk->state != SMC_LNK_ACTIVE &&
 | 
							if (!smc_link_usable(lnk))
 | 
				
			||||||
		    lnk->state != SMC_LNK_ACTIVATING)
 | 
					 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		if (smcr_buf_map_link(buf_desc, is_rmb, lnk)) {
 | 
							if (smcr_buf_map_link(buf_desc, is_rmb, lnk)) {
 | 
				
			||||||
			smcr_buf_unuse(buf_desc, lnk);
 | 
								smcr_buf_unuse(buf_desc, lnk);
 | 
				
			||||||
| 
						 | 
					@ -1294,14 +1298,14 @@ static int __smc_buf_create(struct smc_sock *smc, bool is_smcd, bool is_rmb)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void smc_sndbuf_sync_sg_for_cpu(struct smc_connection *conn)
 | 
					void smc_sndbuf_sync_sg_for_cpu(struct smc_connection *conn)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (!conn->lgr || conn->lgr->is_smcd)
 | 
						if (!conn->lgr || conn->lgr->is_smcd || !smc_link_usable(conn->lnk))
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	smc_ib_sync_sg_for_cpu(conn->lnk, conn->sndbuf_desc, DMA_TO_DEVICE);
 | 
						smc_ib_sync_sg_for_cpu(conn->lnk, conn->sndbuf_desc, DMA_TO_DEVICE);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void smc_sndbuf_sync_sg_for_device(struct smc_connection *conn)
 | 
					void smc_sndbuf_sync_sg_for_device(struct smc_connection *conn)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (!conn->lgr || conn->lgr->is_smcd)
 | 
						if (!conn->lgr || conn->lgr->is_smcd || !smc_link_usable(conn->lnk))
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	smc_ib_sync_sg_for_device(conn->lnk, conn->sndbuf_desc, DMA_TO_DEVICE);
 | 
						smc_ib_sync_sg_for_device(conn->lnk, conn->sndbuf_desc, DMA_TO_DEVICE);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1313,8 +1317,7 @@ void smc_rmb_sync_sg_for_cpu(struct smc_connection *conn)
 | 
				
			||||||
	if (!conn->lgr || conn->lgr->is_smcd)
 | 
						if (!conn->lgr || conn->lgr->is_smcd)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
 | 
						for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
 | 
				
			||||||
		if (conn->lgr->lnk[i].state != SMC_LNK_ACTIVE &&
 | 
							if (!smc_link_usable(&conn->lgr->lnk[i]))
 | 
				
			||||||
		    conn->lgr->lnk[i].state != SMC_LNK_ACTIVATING)
 | 
					 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		smc_ib_sync_sg_for_cpu(&conn->lgr->lnk[i], conn->rmb_desc,
 | 
							smc_ib_sync_sg_for_cpu(&conn->lgr->lnk[i], conn->rmb_desc,
 | 
				
			||||||
				       DMA_FROM_DEVICE);
 | 
									       DMA_FROM_DEVICE);
 | 
				
			||||||
| 
						 | 
					@ -1328,8 +1331,7 @@ void smc_rmb_sync_sg_for_device(struct smc_connection *conn)
 | 
				
			||||||
	if (!conn->lgr || conn->lgr->is_smcd)
 | 
						if (!conn->lgr || conn->lgr->is_smcd)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
 | 
						for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
 | 
				
			||||||
		if (conn->lgr->lnk[i].state != SMC_LNK_ACTIVE &&
 | 
							if (!smc_link_usable(&conn->lgr->lnk[i]))
 | 
				
			||||||
		    conn->lgr->lnk[i].state != SMC_LNK_ACTIVATING)
 | 
					 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		smc_ib_sync_sg_for_device(&conn->lgr->lnk[i], conn->rmb_desc,
 | 
							smc_ib_sync_sg_for_device(&conn->lgr->lnk[i], conn->rmb_desc,
 | 
				
			||||||
					  DMA_FROM_DEVICE);
 | 
										  DMA_FROM_DEVICE);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,6 +32,7 @@ enum smc_lgr_role {		/* possible roles of a link group */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum smc_link_state {			/* possible states of a link */
 | 
					enum smc_link_state {			/* possible states of a link */
 | 
				
			||||||
 | 
						SMC_LNK_UNUSED,		/* link is unused */
 | 
				
			||||||
	SMC_LNK_INACTIVE,	/* link is inactive */
 | 
						SMC_LNK_INACTIVE,	/* link is inactive */
 | 
				
			||||||
	SMC_LNK_ACTIVATING,	/* link is being activated */
 | 
						SMC_LNK_ACTIVATING,	/* link is being activated */
 | 
				
			||||||
	SMC_LNK_ACTIVE,		/* link is active */
 | 
						SMC_LNK_ACTIVE,		/* link is active */
 | 
				
			||||||
| 
						 | 
					@ -295,6 +296,14 @@ static inline struct smc_connection *smc_lgr_find_conn(
 | 
				
			||||||
	return res;
 | 
						return res;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* returns true if the specified link is usable */
 | 
				
			||||||
 | 
					static inline bool smc_link_usable(struct smc_link *lnk)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (lnk->state == SMC_LNK_UNUSED || lnk->state == SMC_LNK_INACTIVE)
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct smc_sock;
 | 
					struct smc_sock;
 | 
				
			||||||
struct smc_clc_msg_accept_confirm;
 | 
					struct smc_clc_msg_accept_confirm;
 | 
				
			||||||
struct smc_clc_msg_local;
 | 
					struct smc_clc_msg_local;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -372,7 +372,7 @@ static void smc_llc_send_message_work(struct work_struct *work)
 | 
				
			||||||
	struct smc_wr_buf *wr_buf;
 | 
						struct smc_wr_buf *wr_buf;
 | 
				
			||||||
	int rc;
 | 
						int rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (llcwrk->link->state == SMC_LNK_INACTIVE)
 | 
						if (!smc_link_usable(llcwrk->link))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	rc = smc_llc_add_pending_send(llcwrk->link, &wr_buf, &pend);
 | 
						rc = smc_llc_add_pending_send(llcwrk->link, &wr_buf, &pend);
 | 
				
			||||||
	if (rc)
 | 
						if (rc)
 | 
				
			||||||
| 
						 | 
					@ -562,7 +562,7 @@ static void smc_llc_rx_handler(struct ib_wc *wc, void *buf)
 | 
				
			||||||
		return; /* short message */
 | 
							return; /* short message */
 | 
				
			||||||
	if (llc->raw.hdr.length != sizeof(*llc))
 | 
						if (llc->raw.hdr.length != sizeof(*llc))
 | 
				
			||||||
		return; /* invalid message */
 | 
							return; /* invalid message */
 | 
				
			||||||
	if (link->state == SMC_LNK_INACTIVE)
 | 
						if (!smc_link_usable(link))
 | 
				
			||||||
		return; /* link not active, drop msg */
 | 
							return; /* link not active, drop msg */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (llc->raw.hdr.common.type) {
 | 
						switch (llc->raw.hdr.common.type) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,6 +35,17 @@ enum smc_llc_msg_type {
 | 
				
			||||||
	SMC_LLC_DELETE_RKEY		= 0x09,
 | 
						SMC_LLC_DELETE_RKEY		= 0x09,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* returns a usable link of the link group, or NULL */
 | 
				
			||||||
 | 
					static inline struct smc_link *smc_llc_usable_link(struct smc_link_group *lgr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++)
 | 
				
			||||||
 | 
							if (smc_link_usable(&lgr->lnk[i]))
 | 
				
			||||||
 | 
								return &lgr->lnk[i];
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* transmit */
 | 
					/* transmit */
 | 
				
			||||||
int smc_llc_send_confirm_link(struct smc_link *lnk,
 | 
					int smc_llc_send_confirm_link(struct smc_link *lnk,
 | 
				
			||||||
			      enum smc_llc_reqresp reqresp);
 | 
								      enum smc_llc_reqresp reqresp);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -207,7 +207,7 @@ int smc_wr_tx_get_free_slot(struct smc_link *link,
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		rc = wait_event_interruptible_timeout(
 | 
							rc = wait_event_interruptible_timeout(
 | 
				
			||||||
			link->wr_tx_wait,
 | 
								link->wr_tx_wait,
 | 
				
			||||||
			link->state == SMC_LNK_INACTIVE ||
 | 
								!smc_link_usable(link) ||
 | 
				
			||||||
			lgr->terminating ||
 | 
								lgr->terminating ||
 | 
				
			||||||
			(smc_wr_tx_get_free_slot_index(link, &idx) != -EBUSY),
 | 
								(smc_wr_tx_get_free_slot_index(link, &idx) != -EBUSY),
 | 
				
			||||||
			SMC_WR_TX_WAIT_FREE_SLOT_TIME);
 | 
								SMC_WR_TX_WAIT_FREE_SLOT_TIME);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue