Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/irdma/irdma_cm.c
Context not available. | |||||
{ | { | ||||
struct ifnet *ip_dev = NULL; | struct ifnet *ip_dev = NULL; | ||||
struct in6_addr laddr6; | struct in6_addr laddr6; | ||||
u16 scope_id = 0; | |||||
irdma_copy_ip_htonl(laddr6.__u6_addr.__u6_addr32, addr); | irdma_copy_ip_htonl(laddr6.__u6_addr.__u6_addr32, addr); | ||||
if (vlan_id) | if (vlan_id) | ||||
Context not available. | |||||
if (mac) | if (mac) | ||||
eth_zero_addr(mac); | eth_zero_addr(mac); | ||||
ip_dev = ip6_ifp_find(&init_net, laddr6, 0); | if (IN6_IS_SCOPE_LINKLOCAL(&laddr6) || | ||||
IN6_IS_ADDR_MC_INTFACELOCAL(&laddr6)) | |||||
scope_id = ntohs(laddr6.__u6_addr.__u6_addr16[1]); | |||||
ip_dev = ip6_ifp_find(&init_net, laddr6, scope_id); | |||||
if (ip_dev) { | if (ip_dev) { | ||||
if (vlan_id) | if (vlan_id) | ||||
*vlan_id = rdma_vlan_dev_vlan_id(ip_dev); | *vlan_id = rdma_vlan_dev_vlan_id(ip_dev); | ||||
Context not available. | |||||
* @rem_addr: remote address | * @rem_addr: remote address | ||||
*/ | */ | ||||
bool | bool | ||||
irdma_ipv4_is_lpb(struct vnet *vnet, u32 loc_addr, u32 rem_addr) | irdma_ipv4_is_lpb(u32 loc_addr, u32 rem_addr) | ||||
{ | { | ||||
bool ret; | return ipv4_is_loopback(htonl(rem_addr)) || (loc_addr == rem_addr); | ||||
CURVNET_SET_QUIET(vnet); | |||||
ret = ipv4_is_loopback(htonl(rem_addr)) || (loc_addr == rem_addr); | |||||
CURVNET_RESTORE(); | |||||
return (ret); | |||||
} | } | ||||
/** | /** | ||||
Context not available. | |||||
static int | static int | ||||
irdma_cm_create_ah(struct irdma_cm_node *cm_node, bool wait) | irdma_cm_create_ah(struct irdma_cm_node *cm_node, bool wait) | ||||
{ | { | ||||
struct rdma_cm_id *rdma_id = (struct rdma_cm_id *)cm_node->cm_id->context; | |||||
struct vnet *vnet = rdma_id->route.addr.dev_addr.net; | |||||
struct irdma_ah_info ah_info = {0}; | struct irdma_ah_info ah_info = {0}; | ||||
struct irdma_device *iwdev = cm_node->iwdev; | struct irdma_device *iwdev = cm_node->iwdev; | ||||
#ifdef VIMAGE | |||||
struct rdma_cm_id *rdma_id = (struct rdma_cm_id *)cm_node->cm_id->context; | |||||
struct vnet *vnet = rdma_id->route.addr.dev_addr.net; | |||||
#endif | |||||
ether_addr_copy(ah_info.mac_addr, IF_LLADDR(iwdev->netdev)); | ether_addr_copy(ah_info.mac_addr, IF_LLADDR(iwdev->netdev)); | ||||
Context not available. | |||||
ah_info.ipv4_valid = true; | ah_info.ipv4_valid = true; | ||||
ah_info.dest_ip_addr[0] = cm_node->rem_addr[0]; | ah_info.dest_ip_addr[0] = cm_node->rem_addr[0]; | ||||
ah_info.src_ip_addr[0] = cm_node->loc_addr[0]; | ah_info.src_ip_addr[0] = cm_node->loc_addr[0]; | ||||
ah_info.do_lpbk = irdma_ipv4_is_lpb(vnet, | #ifdef VIMAGE | ||||
ah_info.src_ip_addr[0], | CURVNET_SET_QUIET(vnet); | ||||
ah_info.do_lpbk = irdma_ipv4_is_lpb(ah_info.src_ip_addr[0], | |||||
ah_info.dest_ip_addr[0]); | ah_info.dest_ip_addr[0]); | ||||
CURVNET_RESTORE(); | |||||
#endif | |||||
} else { | } else { | ||||
memcpy(ah_info.dest_ip_addr, cm_node->rem_addr, | memcpy(ah_info.dest_ip_addr, cm_node->rem_addr, | ||||
sizeof(ah_info.dest_ip_addr)); | sizeof(ah_info.dest_ip_addr)); | ||||
Context not available. | |||||
} | } | ||||
static void | static void | ||||
irdma_cm_node_free_cb(struct rcu_head *rcu_head) | irdma_destroy_connection(struct irdma_cm_node *cm_node) | ||||
{ | { | ||||
struct irdma_cm_node *cm_node = | |||||
container_of(rcu_head, struct irdma_cm_node, rcu_head); | |||||
struct irdma_cm_core *cm_core = cm_node->cm_core; | struct irdma_cm_core *cm_core = cm_node->cm_core; | ||||
struct irdma_qp *iwqp; | struct irdma_qp *iwqp; | ||||
struct irdma_cm_info nfo; | struct irdma_cm_info nfo; | ||||
Context not available. | |||||
} | } | ||||
cm_core->cm_free_ah(cm_node); | cm_core->cm_free_ah(cm_node); | ||||
kfree(cm_node); | |||||
} | } | ||||
/** | /** | ||||
Context not available. | |||||
spin_unlock_irqrestore(&cm_core->ht_lock, flags); | spin_unlock_irqrestore(&cm_core->ht_lock, flags); | ||||
/* wait for all list walkers to exit their grace period */ | irdma_destroy_connection(cm_node); | ||||
call_rcu(&cm_node->rcu_head, irdma_cm_node_free_cb); | |||||
kfree_rcu(cm_node, rcu_head); | |||||
} | } | ||||
/** | /** | ||||
Context not available. | |||||
} | } | ||||
cm_id = iwqp->cm_id; | cm_id = iwqp->cm_id; | ||||
/* make sure we havent already closed this connection */ | |||||
if (!cm_id) { | |||||
spin_unlock_irqrestore(&iwqp->lock, flags); | |||||
return; | |||||
} | |||||
original_hw_tcp_state = iwqp->hw_tcp_state; | original_hw_tcp_state = iwqp->hw_tcp_state; | ||||
original_ibqp_state = iwqp->ibqp_state; | original_ibqp_state = iwqp->ibqp_state; | ||||
last_ae = iwqp->last_aeq; | last_ae = iwqp->last_aeq; | ||||
Context not available. | |||||
disconn_status = -ECONNRESET; | disconn_status = -ECONNRESET; | ||||
} | } | ||||
if ((original_hw_tcp_state == IRDMA_TCP_STATE_CLOSED || | if (original_hw_tcp_state == IRDMA_TCP_STATE_CLOSED || | ||||
original_hw_tcp_state == IRDMA_TCP_STATE_TIME_WAIT || | original_hw_tcp_state == IRDMA_TCP_STATE_TIME_WAIT || | ||||
last_ae == IRDMA_AE_RDMAP_ROE_BAD_LLP_CLOSE || | last_ae == IRDMA_AE_RDMAP_ROE_BAD_LLP_CLOSE || | ||||
last_ae == IRDMA_AE_BAD_CLOSE || | last_ae == IRDMA_AE_BAD_CLOSE || | ||||
last_ae == IRDMA_AE_LLP_CONNECTION_RESET || iwdev->rf->reset)) { | last_ae == IRDMA_AE_LLP_CONNECTION_RESET || iwdev->rf->reset || !cm_id) { | ||||
issue_close = 1; | issue_close = 1; | ||||
iwqp->cm_id = NULL; | iwqp->cm_id = NULL; | ||||
qp->term_flags = 0; | qp->term_flags = 0; | ||||
Context not available. | |||||
spin_unlock_irqrestore(&iwqp->lock, flags); | spin_unlock_irqrestore(&iwqp->lock, flags); | ||||
if (issue_flush && !iwqp->sc_qp.qp_uk.destroy_pending) { | if (issue_flush && !iwqp->sc_qp.qp_uk.destroy_pending) { | ||||
if (!iwqp->user_mode) | |||||
queue_delayed_work(iwqp->iwdev->cleanup_wq, | |||||
&iwqp->dwork_flush, | |||||
msecs_to_jiffies(IRDMA_FLUSH_DELAY_MS)); | |||||
irdma_flush_wqes(iwqp, IRDMA_FLUSH_SQ | IRDMA_FLUSH_RQ | | irdma_flush_wqes(iwqp, IRDMA_FLUSH_SQ | IRDMA_FLUSH_RQ | | ||||
IRDMA_FLUSH_WAIT); | IRDMA_FLUSH_WAIT); | ||||
Context not available. | |||||
struct irdma_cm_node *cm_node; | struct irdma_cm_node *cm_node; | ||||
struct list_head teardown_list; | struct list_head teardown_list; | ||||
struct ib_qp_attr attr; | struct ib_qp_attr attr; | ||||
struct irdma_sc_vsi *vsi = &iwdev->vsi; | |||||
struct irdma_sc_qp *sc_qp; | |||||
struct irdma_qp *qp; | |||||
int i; | |||||
INIT_LIST_HEAD(&teardown_list); | INIT_LIST_HEAD(&teardown_list); | ||||
Context not available. | |||||
irdma_cm_disconn(cm_node->iwqp); | irdma_cm_disconn(cm_node->iwqp); | ||||
irdma_rem_ref_cm_node(cm_node); | irdma_rem_ref_cm_node(cm_node); | ||||
} | } | ||||
if (!iwdev->roce_mode) | |||||
return; | |||||
INIT_LIST_HEAD(&teardown_list); | |||||
for (i = 0; i < IRDMA_MAX_USER_PRIORITY; i++) { | |||||
mutex_lock(&vsi->qos[i].qos_mutex); | |||||
list_for_each_safe(list_node, list_core_temp, | |||||
&vsi->qos[i].qplist) { | |||||
u32 qp_ip[4]; | |||||
sc_qp = container_of(list_node, struct irdma_sc_qp, | |||||
list); | |||||
if (sc_qp->qp_uk.qp_type != IRDMA_QP_TYPE_ROCE_RC) | |||||
continue; | |||||
qp = sc_qp->qp_uk.back_qp; | |||||
if (!disconnect_all) { | |||||
if (nfo->ipv4) | |||||
qp_ip[0] = qp->udp_info.local_ipaddr[3]; | |||||
else | |||||
memcpy(qp_ip, | |||||
&qp->udp_info.local_ipaddr[0], | |||||
sizeof(qp_ip)); | |||||
} | |||||
if (disconnect_all || | |||||
(nfo->vlan_id == (qp->udp_info.vlan_tag & EVL_VLID_MASK) && | |||||
!memcmp(qp_ip, ipaddr, nfo->ipv4 ? 4 : 16))) { | |||||
spin_lock(&iwdev->rf->qptable_lock); | |||||
if (iwdev->rf->qp_table[sc_qp->qp_uk.qp_id]) { | |||||
irdma_qp_add_ref(&qp->ibqp); | |||||
list_add(&qp->teardown_entry, | |||||
&teardown_list); | |||||
} | |||||
spin_unlock(&iwdev->rf->qptable_lock); | |||||
} | |||||
} | |||||
mutex_unlock(&vsi->qos[i].qos_mutex); | |||||
} | |||||
list_for_each_safe(list_node, list_core_temp, &teardown_list) { | |||||
qp = container_of(list_node, struct irdma_qp, teardown_entry); | |||||
attr.qp_state = IB_QPS_ERR; | |||||
irdma_modify_qp_roce(&qp->ibqp, &attr, IB_QP_STATE, NULL); | |||||
irdma_qp_rem_ref(&qp->ibqp); | |||||
} | |||||
} | } | ||||
Context not available. |