Merge branch 'libcxgb-next'
Varun Prakash says: ==================== iw_cxgb4,cxgbit: remove duplicate code This patch series removes duplicate code from iw_cxgb4 and cxgbit by adding common function definitions in libcxgb. Please review. ==================== Reviewed-by: Steve Wise <swise@opengridcomputing.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
09f090d811
@ -1,6 +1,7 @@
|
||||
config INFINIBAND_CXGB4
|
||||
tristate "Chelsio T4/T5 RDMA Driver"
|
||||
depends on CHELSIO_T4 && INET && (IPV6 || IPV6=n)
|
||||
select CHELSIO_LIB
|
||||
select GENERIC_ALLOCATOR
|
||||
---help---
|
||||
This is an iWARP/RDMA driver for the Chelsio T4 and T5
|
||||
|
@ -1,4 +1,5 @@
|
||||
ccflags-y := -Idrivers/net/ethernet/chelsio/cxgb4
|
||||
ccflags-y += -Idrivers/net/ethernet/chelsio/libcxgb
|
||||
|
||||
obj-$(CONFIG_INFINIBAND_CXGB4) += iw_cxgb4.o
|
||||
|
||||
|
@ -49,6 +49,7 @@
|
||||
|
||||
#include <rdma/ib_addr.h>
|
||||
|
||||
#include <libcxgb_cm.h>
|
||||
#include "iw_cxgb4.h"
|
||||
#include "clip_tbl.h"
|
||||
|
||||
@ -239,15 +240,13 @@ int c4iw_ofld_send(struct c4iw_rdev *rdev, struct sk_buff *skb)
|
||||
|
||||
static void release_tid(struct c4iw_rdev *rdev, u32 hwtid, struct sk_buff *skb)
|
||||
{
|
||||
struct cpl_tid_release *req;
|
||||
u32 len = roundup(sizeof(struct cpl_tid_release), 16);
|
||||
|
||||
skb = get_skb(skb, sizeof *req, GFP_KERNEL);
|
||||
skb = get_skb(skb, len, GFP_KERNEL);
|
||||
if (!skb)
|
||||
return;
|
||||
req = (struct cpl_tid_release *) skb_put(skb, sizeof(*req));
|
||||
INIT_TP_WR(req, hwtid);
|
||||
OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_TID_RELEASE, hwtid));
|
||||
set_wr_txq(skb, CPL_PRIORITY_SETUP, 0);
|
||||
|
||||
cxgb_mk_tid_release(skb, len, hwtid, 0);
|
||||
c4iw_ofld_send(rdev, skb);
|
||||
return;
|
||||
}
|
||||
@ -464,72 +463,6 @@ static struct net_device *get_real_dev(struct net_device *egress_dev)
|
||||
return rdma_vlan_dev_real_dev(egress_dev) ? : egress_dev;
|
||||
}
|
||||
|
||||
static int our_interface(struct c4iw_dev *dev, struct net_device *egress_dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
egress_dev = get_real_dev(egress_dev);
|
||||
for (i = 0; i < dev->rdev.lldi.nports; i++)
|
||||
if (dev->rdev.lldi.ports[i] == egress_dev)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dst_entry *find_route6(struct c4iw_dev *dev, __u8 *local_ip,
|
||||
__u8 *peer_ip, __be16 local_port,
|
||||
__be16 peer_port, u8 tos,
|
||||
__u32 sin6_scope_id)
|
||||
{
|
||||
struct dst_entry *dst = NULL;
|
||||
|
||||
if (IS_ENABLED(CONFIG_IPV6)) {
|
||||
struct flowi6 fl6;
|
||||
|
||||
memset(&fl6, 0, sizeof(fl6));
|
||||
memcpy(&fl6.daddr, peer_ip, 16);
|
||||
memcpy(&fl6.saddr, local_ip, 16);
|
||||
if (ipv6_addr_type(&fl6.daddr) & IPV6_ADDR_LINKLOCAL)
|
||||
fl6.flowi6_oif = sin6_scope_id;
|
||||
dst = ip6_route_output(&init_net, NULL, &fl6);
|
||||
if (!dst)
|
||||
goto out;
|
||||
if (!our_interface(dev, ip6_dst_idev(dst)->dev) &&
|
||||
!(ip6_dst_idev(dst)->dev->flags & IFF_LOOPBACK)) {
|
||||
dst_release(dst);
|
||||
dst = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return dst;
|
||||
}
|
||||
|
||||
static struct dst_entry *find_route(struct c4iw_dev *dev, __be32 local_ip,
|
||||
__be32 peer_ip, __be16 local_port,
|
||||
__be16 peer_port, u8 tos)
|
||||
{
|
||||
struct rtable *rt;
|
||||
struct flowi4 fl4;
|
||||
struct neighbour *n;
|
||||
|
||||
rt = ip_route_output_ports(&init_net, &fl4, NULL, peer_ip, local_ip,
|
||||
peer_port, local_port, IPPROTO_TCP,
|
||||
tos, 0);
|
||||
if (IS_ERR(rt))
|
||||
return NULL;
|
||||
n = dst_neigh_lookup(&rt->dst, &peer_ip);
|
||||
if (!n)
|
||||
return NULL;
|
||||
if (!our_interface(dev, n->dev) &&
|
||||
!(n->dev->flags & IFF_LOOPBACK)) {
|
||||
neigh_release(n);
|
||||
dst_release(&rt->dst);
|
||||
return NULL;
|
||||
}
|
||||
neigh_release(n);
|
||||
return &rt->dst;
|
||||
}
|
||||
|
||||
static void arp_failure_discard(void *handle, struct sk_buff *skb)
|
||||
{
|
||||
pr_err(MOD "ARP failure\n");
|
||||
@ -704,58 +637,34 @@ static int send_flowc(struct c4iw_ep *ep)
|
||||
|
||||
static int send_halfclose(struct c4iw_ep *ep)
|
||||
{
|
||||
struct cpl_close_con_req *req;
|
||||
struct sk_buff *skb = skb_dequeue(&ep->com.ep_skb_list);
|
||||
int wrlen = roundup(sizeof *req, 16);
|
||||
u32 wrlen = roundup(sizeof(struct cpl_close_con_req), 16);
|
||||
|
||||
PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
|
||||
if (WARN_ON(!skb))
|
||||
return -ENOMEM;
|
||||
|
||||
set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx);
|
||||
t4_set_arp_err_handler(skb, NULL, arp_failure_discard);
|
||||
req = (struct cpl_close_con_req *) skb_put(skb, wrlen);
|
||||
memset(req, 0, wrlen);
|
||||
INIT_TP_WR(req, ep->hwtid);
|
||||
OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_CLOSE_CON_REQ,
|
||||
ep->hwtid));
|
||||
cxgb_mk_close_con_req(skb, wrlen, ep->hwtid, ep->txq_idx,
|
||||
NULL, arp_failure_discard);
|
||||
|
||||
return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
|
||||
}
|
||||
|
||||
static int send_abort(struct c4iw_ep *ep)
|
||||
{
|
||||
struct cpl_abort_req *req;
|
||||
int wrlen = roundup(sizeof *req, 16);
|
||||
u32 wrlen = roundup(sizeof(struct cpl_abort_req), 16);
|
||||
struct sk_buff *req_skb = skb_dequeue(&ep->com.ep_skb_list);
|
||||
|
||||
PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
|
||||
if (WARN_ON(!req_skb))
|
||||
return -ENOMEM;
|
||||
|
||||
set_wr_txq(req_skb, CPL_PRIORITY_DATA, ep->txq_idx);
|
||||
t4_set_arp_err_handler(req_skb, ep, abort_arp_failure);
|
||||
req = (struct cpl_abort_req *)skb_put(req_skb, wrlen);
|
||||
memset(req, 0, wrlen);
|
||||
INIT_TP_WR(req, ep->hwtid);
|
||||
OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ABORT_REQ, ep->hwtid));
|
||||
req->cmd = CPL_ABORT_SEND_RST;
|
||||
cxgb_mk_abort_req(req_skb, wrlen, ep->hwtid, ep->txq_idx,
|
||||
ep, abort_arp_failure);
|
||||
|
||||
return c4iw_l2t_send(&ep->com.dev->rdev, req_skb, ep->l2t);
|
||||
}
|
||||
|
||||
static void best_mtu(const unsigned short *mtus, unsigned short mtu,
|
||||
unsigned int *idx, int use_ts, int ipv6)
|
||||
{
|
||||
unsigned short hdr_size = (ipv6 ?
|
||||
sizeof(struct ipv6hdr) :
|
||||
sizeof(struct iphdr)) +
|
||||
sizeof(struct tcphdr) +
|
||||
(use_ts ?
|
||||
round_up(TCPOLEN_TIMESTAMP, 4) : 0);
|
||||
unsigned short data_size = mtu - hdr_size;
|
||||
|
||||
cxgb4_best_aligned_mtu(mtus, hdr_size, data_size, 8, idx);
|
||||
}
|
||||
|
||||
static int send_connect(struct c4iw_ep *ep)
|
||||
{
|
||||
struct cpl_act_open_req *req = NULL;
|
||||
@ -768,7 +677,7 @@ static int send_connect(struct c4iw_ep *ep)
|
||||
u64 opt0;
|
||||
u32 opt2;
|
||||
unsigned int mtu_idx;
|
||||
int wscale;
|
||||
u32 wscale;
|
||||
int win, sizev4, sizev6, wrlen;
|
||||
struct sockaddr_in *la = (struct sockaddr_in *)
|
||||
&ep->com.local_addr;
|
||||
@ -815,10 +724,10 @@ static int send_connect(struct c4iw_ep *ep)
|
||||
}
|
||||
set_wr_txq(skb, CPL_PRIORITY_SETUP, ep->ctrlq_idx);
|
||||
|
||||
best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx,
|
||||
enable_tcp_timestamps,
|
||||
(AF_INET == ep->com.remote_addr.ss_family) ? 0 : 1);
|
||||
wscale = compute_wscale(rcv_win);
|
||||
cxgb_best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx,
|
||||
enable_tcp_timestamps,
|
||||
(ep->com.remote_addr.ss_family == AF_INET) ? 0 : 1);
|
||||
wscale = cxgb_compute_wscale(rcv_win);
|
||||
|
||||
/*
|
||||
* Specify the largest window that will fit in opt0. The
|
||||
@ -1445,9 +1354,9 @@ static void established_upcall(struct c4iw_ep *ep)
|
||||
|
||||
static int update_rx_credits(struct c4iw_ep *ep, u32 credits)
|
||||
{
|
||||
struct cpl_rx_data_ack *req;
|
||||
struct sk_buff *skb;
|
||||
int wrlen = roundup(sizeof *req, 16);
|
||||
u32 wrlen = roundup(sizeof(struct cpl_rx_data_ack), 16);
|
||||
u32 credit_dack;
|
||||
|
||||
PDBG("%s ep %p tid %u credits %u\n", __func__, ep, ep->hwtid, credits);
|
||||
skb = get_skb(NULL, wrlen, GFP_KERNEL);
|
||||
@ -1464,15 +1373,12 @@ static int update_rx_credits(struct c4iw_ep *ep, u32 credits)
|
||||
if (ep->rcv_win > RCV_BUFSIZ_M * 1024)
|
||||
credits += ep->rcv_win - RCV_BUFSIZ_M * 1024;
|
||||
|
||||
req = (struct cpl_rx_data_ack *) skb_put(skb, wrlen);
|
||||
memset(req, 0, wrlen);
|
||||
INIT_TP_WR(req, ep->hwtid);
|
||||
OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_RX_DATA_ACK,
|
||||
ep->hwtid));
|
||||
req->credit_dack = cpu_to_be32(credits | RX_FORCE_ACK_F |
|
||||
RX_DACK_CHANGE_F |
|
||||
RX_DACK_MODE_V(dack_mode));
|
||||
set_wr_txq(skb, CPL_PRIORITY_ACK, ep->ctrlq_idx);
|
||||
credit_dack = credits | RX_FORCE_ACK_F | RX_DACK_CHANGE_F |
|
||||
RX_DACK_MODE_V(dack_mode);
|
||||
|
||||
cxgb_mk_rx_data_ack(skb, wrlen, ep->hwtid, ep->ctrlq_idx,
|
||||
credit_dack);
|
||||
|
||||
c4iw_ofld_send(&ep->com.dev->rdev, skb);
|
||||
return credits;
|
||||
}
|
||||
@ -1970,7 +1876,7 @@ static int send_fw_act_open_req(struct c4iw_ep *ep, unsigned int atid)
|
||||
struct sk_buff *skb;
|
||||
struct fw_ofld_connection_wr *req;
|
||||
unsigned int mtu_idx;
|
||||
int wscale;
|
||||
u32 wscale;
|
||||
struct sockaddr_in *sin;
|
||||
int win;
|
||||
|
||||
@ -1995,10 +1901,10 @@ static int send_fw_act_open_req(struct c4iw_ep *ep, unsigned int atid)
|
||||
htons(FW_OFLD_CONNECTION_WR_CPLRXDATAACK_F);
|
||||
req->tcb.tx_max = (__force __be32) jiffies;
|
||||
req->tcb.rcv_adv = htons(1);
|
||||
best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx,
|
||||
enable_tcp_timestamps,
|
||||
(AF_INET == ep->com.remote_addr.ss_family) ? 0 : 1);
|
||||
wscale = compute_wscale(rcv_win);
|
||||
cxgb_best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx,
|
||||
enable_tcp_timestamps,
|
||||
(ep->com.remote_addr.ss_family == AF_INET) ? 0 : 1);
|
||||
wscale = cxgb_compute_wscale(rcv_win);
|
||||
|
||||
/*
|
||||
* Specify the largest window that will fit in opt0. The
|
||||
@ -2052,15 +1958,6 @@ static inline int act_open_has_tid(int status)
|
||||
status != CPL_ERR_CONN_EXIST);
|
||||
}
|
||||
|
||||
/* Returns whether a CPL status conveys negative advice.
|
||||
*/
|
||||
static int is_neg_adv(unsigned int status)
|
||||
{
|
||||
return status == CPL_ERR_RTX_NEG_ADVICE ||
|
||||
status == CPL_ERR_PERSIST_NEG_ADVICE ||
|
||||
status == CPL_ERR_KEEPALV_NEG_ADVICE;
|
||||
}
|
||||
|
||||
static char *neg_adv_str(unsigned int status)
|
||||
{
|
||||
switch (status) {
|
||||
@ -2214,16 +2111,21 @@ static int c4iw_reconnect(struct c4iw_ep *ep)
|
||||
|
||||
/* find a route */
|
||||
if (ep->com.cm_id->m_local_addr.ss_family == AF_INET) {
|
||||
ep->dst = find_route(ep->com.dev, laddr->sin_addr.s_addr,
|
||||
raddr->sin_addr.s_addr, laddr->sin_port,
|
||||
raddr->sin_port, ep->com.cm_id->tos);
|
||||
ep->dst = cxgb_find_route(&ep->com.dev->rdev.lldi, get_real_dev,
|
||||
laddr->sin_addr.s_addr,
|
||||
raddr->sin_addr.s_addr,
|
||||
laddr->sin_port,
|
||||
raddr->sin_port, ep->com.cm_id->tos);
|
||||
iptype = 4;
|
||||
ra = (__u8 *)&raddr->sin_addr;
|
||||
} else {
|
||||
ep->dst = find_route6(ep->com.dev, laddr6->sin6_addr.s6_addr,
|
||||
raddr6->sin6_addr.s6_addr,
|
||||
laddr6->sin6_port, raddr6->sin6_port, 0,
|
||||
raddr6->sin6_scope_id);
|
||||
ep->dst = cxgb_find_route6(&ep->com.dev->rdev.lldi,
|
||||
get_real_dev,
|
||||
laddr6->sin6_addr.s6_addr,
|
||||
raddr6->sin6_addr.s6_addr,
|
||||
laddr6->sin6_port,
|
||||
raddr6->sin6_port, 0,
|
||||
raddr6->sin6_scope_id);
|
||||
iptype = 6;
|
||||
ra = (__u8 *)&raddr6->sin6_addr;
|
||||
}
|
||||
@ -2295,7 +2197,7 @@ static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
|
||||
PDBG("%s ep %p atid %u status %u errno %d\n", __func__, ep, atid,
|
||||
status, status2errno(status));
|
||||
|
||||
if (is_neg_adv(status)) {
|
||||
if (cxgb_is_neg_adv(status)) {
|
||||
PDBG("%s Connection problems for atid %u status %u (%s)\n",
|
||||
__func__, atid, status, neg_adv_str(status));
|
||||
ep->stats.connect_neg_adv++;
|
||||
@ -2422,7 +2324,7 @@ static int accept_cr(struct c4iw_ep *ep, struct sk_buff *skb,
|
||||
unsigned int mtu_idx;
|
||||
u64 opt0;
|
||||
u32 opt2;
|
||||
int wscale;
|
||||
u32 wscale;
|
||||
struct cpl_t5_pass_accept_rpl *rpl5 = NULL;
|
||||
int win;
|
||||
enum chip_type adapter_type = ep->com.dev->rdev.lldi.adapter_type;
|
||||
@ -2443,10 +2345,10 @@ static int accept_cr(struct c4iw_ep *ep, struct sk_buff *skb,
|
||||
OPCODE_TID(rpl) = cpu_to_be32(MK_OPCODE_TID(CPL_PASS_ACCEPT_RPL,
|
||||
ep->hwtid));
|
||||
|
||||
best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx,
|
||||
enable_tcp_timestamps && req->tcpopt.tstamp,
|
||||
(AF_INET == ep->com.remote_addr.ss_family) ? 0 : 1);
|
||||
wscale = compute_wscale(rcv_win);
|
||||
cxgb_best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx,
|
||||
enable_tcp_timestamps && req->tcpopt.tstamp,
|
||||
(ep->com.remote_addr.ss_family == AF_INET) ? 0 : 1);
|
||||
wscale = cxgb_compute_wscale(rcv_win);
|
||||
|
||||
/*
|
||||
* Specify the largest window that will fit in opt0. The
|
||||
@ -2518,42 +2420,6 @@ static void reject_cr(struct c4iw_dev *dev, u32 hwtid, struct sk_buff *skb)
|
||||
return;
|
||||
}
|
||||
|
||||
static void get_4tuple(struct cpl_pass_accept_req *req, enum chip_type type,
|
||||
int *iptype, __u8 *local_ip, __u8 *peer_ip,
|
||||
__be16 *local_port, __be16 *peer_port)
|
||||
{
|
||||
int eth_len = (CHELSIO_CHIP_VERSION(type) <= CHELSIO_T5) ?
|
||||
ETH_HDR_LEN_G(be32_to_cpu(req->hdr_len)) :
|
||||
T6_ETH_HDR_LEN_G(be32_to_cpu(req->hdr_len));
|
||||
int ip_len = (CHELSIO_CHIP_VERSION(type) <= CHELSIO_T5) ?
|
||||
IP_HDR_LEN_G(be32_to_cpu(req->hdr_len)) :
|
||||
T6_IP_HDR_LEN_G(be32_to_cpu(req->hdr_len));
|
||||
struct iphdr *ip = (struct iphdr *)((u8 *)(req + 1) + eth_len);
|
||||
struct ipv6hdr *ip6 = (struct ipv6hdr *)((u8 *)(req + 1) + eth_len);
|
||||
struct tcphdr *tcp = (struct tcphdr *)
|
||||
((u8 *)(req + 1) + eth_len + ip_len);
|
||||
|
||||
if (ip->version == 4) {
|
||||
PDBG("%s saddr 0x%x daddr 0x%x sport %u dport %u\n", __func__,
|
||||
ntohl(ip->saddr), ntohl(ip->daddr), ntohs(tcp->source),
|
||||
ntohs(tcp->dest));
|
||||
*iptype = 4;
|
||||
memcpy(peer_ip, &ip->saddr, 4);
|
||||
memcpy(local_ip, &ip->daddr, 4);
|
||||
} else {
|
||||
PDBG("%s saddr %pI6 daddr %pI6 sport %u dport %u\n", __func__,
|
||||
ip6->saddr.s6_addr, ip6->daddr.s6_addr, ntohs(tcp->source),
|
||||
ntohs(tcp->dest));
|
||||
*iptype = 6;
|
||||
memcpy(peer_ip, ip6->saddr.s6_addr, 16);
|
||||
memcpy(local_ip, ip6->daddr.s6_addr, 16);
|
||||
}
|
||||
*peer_port = tcp->source;
|
||||
*local_port = tcp->dest;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct c4iw_ep *child_ep = NULL, *parent_ep;
|
||||
@ -2582,8 +2448,8 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
|
||||
goto reject;
|
||||
}
|
||||
|
||||
get_4tuple(req, parent_ep->com.dev->rdev.lldi.adapter_type, &iptype,
|
||||
local_ip, peer_ip, &local_port, &peer_port);
|
||||
cxgb_get_4tuple(req, parent_ep->com.dev->rdev.lldi.adapter_type,
|
||||
&iptype, local_ip, peer_ip, &local_port, &peer_port);
|
||||
|
||||
/* Find output route */
|
||||
if (iptype == 4) {
|
||||
@ -2591,18 +2457,19 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
|
||||
, __func__, parent_ep, hwtid,
|
||||
local_ip, peer_ip, ntohs(local_port),
|
||||
ntohs(peer_port), peer_mss);
|
||||
dst = find_route(dev, *(__be32 *)local_ip, *(__be32 *)peer_ip,
|
||||
local_port, peer_port,
|
||||
tos);
|
||||
dst = cxgb_find_route(&dev->rdev.lldi, get_real_dev,
|
||||
*(__be32 *)local_ip, *(__be32 *)peer_ip,
|
||||
local_port, peer_port, tos);
|
||||
} else {
|
||||
PDBG("%s parent ep %p hwtid %u laddr %pI6 raddr %pI6 lport %d rport %d peer_mss %d\n"
|
||||
, __func__, parent_ep, hwtid,
|
||||
local_ip, peer_ip, ntohs(local_port),
|
||||
ntohs(peer_port), peer_mss);
|
||||
dst = find_route6(dev, local_ip, peer_ip, local_port, peer_port,
|
||||
PASS_OPEN_TOS_G(ntohl(req->tos_stid)),
|
||||
((struct sockaddr_in6 *)
|
||||
&parent_ep->com.local_addr)->sin6_scope_id);
|
||||
dst = cxgb_find_route6(&dev->rdev.lldi, get_real_dev,
|
||||
local_ip, peer_ip, local_port, peer_port,
|
||||
PASS_OPEN_TOS_G(ntohl(req->tos_stid)),
|
||||
((struct sockaddr_in6 *)
|
||||
&parent_ep->com.local_addr)->sin6_scope_id);
|
||||
}
|
||||
if (!dst) {
|
||||
printk(KERN_ERR MOD "%s - failed to find dst entry!\n",
|
||||
@ -2835,18 +2702,18 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct cpl_abort_req_rss *req = cplhdr(skb);
|
||||
struct c4iw_ep *ep;
|
||||
struct cpl_abort_rpl *rpl;
|
||||
struct sk_buff *rpl_skb;
|
||||
struct c4iw_qp_attributes attrs;
|
||||
int ret;
|
||||
int release = 0;
|
||||
unsigned int tid = GET_TID(req);
|
||||
u32 len = roundup(sizeof(struct cpl_abort_rpl), 16);
|
||||
|
||||
ep = get_ep_from_tid(dev, tid);
|
||||
if (!ep)
|
||||
return 0;
|
||||
|
||||
if (is_neg_adv(req->status)) {
|
||||
if (cxgb_is_neg_adv(req->status)) {
|
||||
PDBG("%s Negative advice on abort- tid %u status %d (%s)\n",
|
||||
__func__, ep->hwtid, req->status,
|
||||
neg_adv_str(req->status));
|
||||
@ -2939,11 +2806,9 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
|
||||
release = 1;
|
||||
goto out;
|
||||
}
|
||||
set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx);
|
||||
rpl = (struct cpl_abort_rpl *) skb_put(rpl_skb, sizeof(*rpl));
|
||||
INIT_TP_WR(rpl, ep->hwtid);
|
||||
OPCODE_TID(rpl) = cpu_to_be32(MK_OPCODE_TID(CPL_ABORT_RPL, ep->hwtid));
|
||||
rpl->cmd = CPL_ABORT_NO_RST;
|
||||
|
||||
cxgb_mk_abort_rpl(rpl_skb, len, ep->hwtid, ep->txq_idx);
|
||||
|
||||
c4iw_ofld_send(&ep->com.dev->rdev, rpl_skb);
|
||||
out:
|
||||
if (release)
|
||||
@ -3375,9 +3240,11 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
|
||||
PDBG("%s saddr %pI4 sport 0x%x raddr %pI4 rport 0x%x\n",
|
||||
__func__, &laddr->sin_addr, ntohs(laddr->sin_port),
|
||||
ra, ntohs(raddr->sin_port));
|
||||
ep->dst = find_route(dev, laddr->sin_addr.s_addr,
|
||||
raddr->sin_addr.s_addr, laddr->sin_port,
|
||||
raddr->sin_port, cm_id->tos);
|
||||
ep->dst = cxgb_find_route(&dev->rdev.lldi, get_real_dev,
|
||||
laddr->sin_addr.s_addr,
|
||||
raddr->sin_addr.s_addr,
|
||||
laddr->sin_port,
|
||||
raddr->sin_port, cm_id->tos);
|
||||
} else {
|
||||
iptype = 6;
|
||||
ra = (__u8 *)&raddr6->sin6_addr;
|
||||
@ -3396,10 +3263,12 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
|
||||
__func__, laddr6->sin6_addr.s6_addr,
|
||||
ntohs(laddr6->sin6_port),
|
||||
raddr6->sin6_addr.s6_addr, ntohs(raddr6->sin6_port));
|
||||
ep->dst = find_route6(dev, laddr6->sin6_addr.s6_addr,
|
||||
raddr6->sin6_addr.s6_addr,
|
||||
laddr6->sin6_port, raddr6->sin6_port, 0,
|
||||
raddr6->sin6_scope_id);
|
||||
ep->dst = cxgb_find_route6(&dev->rdev.lldi, get_real_dev,
|
||||
laddr6->sin6_addr.s6_addr,
|
||||
raddr6->sin6_addr.s6_addr,
|
||||
laddr6->sin6_port,
|
||||
raddr6->sin6_port, 0,
|
||||
raddr6->sin6_scope_id);
|
||||
}
|
||||
if (!ep->dst) {
|
||||
printk(KERN_ERR MOD "%s - cannot find route.\n", __func__);
|
||||
@ -4041,8 +3910,9 @@ static int rx_pkt(struct c4iw_dev *dev, struct sk_buff *skb)
|
||||
ntohl(iph->daddr), ntohs(tcph->dest), ntohl(iph->saddr),
|
||||
ntohs(tcph->source), iph->tos);
|
||||
|
||||
dst = find_route(dev, iph->daddr, iph->saddr, tcph->dest, tcph->source,
|
||||
iph->tos);
|
||||
dst = cxgb_find_route(&dev->rdev.lldi, get_real_dev,
|
||||
iph->daddr, iph->saddr, tcph->dest,
|
||||
tcph->source, iph->tos);
|
||||
if (!dst) {
|
||||
pr_err("%s - failed to find dst entry!\n",
|
||||
__func__);
|
||||
@ -4317,7 +4187,7 @@ static int peer_abort_intr(struct c4iw_dev *dev, struct sk_buff *skb)
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
if (is_neg_adv(req->status)) {
|
||||
if (cxgb_is_neg_adv(req->status)) {
|
||||
PDBG("%s Negative advice on abort- tid %u status %d (%s)\n",
|
||||
__func__, ep->hwtid, req->status,
|
||||
neg_adv_str(req->status));
|
||||
|
@ -881,15 +881,6 @@ static inline struct c4iw_listen_ep *to_listen_ep(struct iw_cm_id *cm_id)
|
||||
return cm_id->provider_data;
|
||||
}
|
||||
|
||||
static inline int compute_wscale(int win)
|
||||
{
|
||||
int wscale = 0;
|
||||
|
||||
while (wscale < 14 && (65535<<wscale) < win)
|
||||
wscale++;
|
||||
return wscale;
|
||||
}
|
||||
|
||||
static inline int ocqp_supported(const struct cxgb4_lld_info *infop)
|
||||
{
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(CONFIG_PPC64)
|
||||
|
@ -1,3 +1,5 @@
|
||||
ccflags-y := -Idrivers/net/ethernet/chelsio/cxgb4
|
||||
|
||||
obj-$(CONFIG_CHELSIO_LIB) += libcxgb.o
|
||||
|
||||
libcxgb-y := libcxgb_ppm.o
|
||||
libcxgb-y := libcxgb_ppm.o libcxgb_cm.o
|
||||
|
149
drivers/net/ethernet/chelsio/libcxgb/libcxgb_cm.c
Normal file
149
drivers/net/ethernet/chelsio/libcxgb/libcxgb_cm.c
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Chelsio Communications, Inc. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <net/route.h>
|
||||
#include <net/ip6_route.h>
|
||||
|
||||
#include "libcxgb_cm.h"
|
||||
|
||||
void
|
||||
cxgb_get_4tuple(struct cpl_pass_accept_req *req, enum chip_type type,
|
||||
int *iptype, __u8 *local_ip, __u8 *peer_ip,
|
||||
__be16 *local_port, __be16 *peer_port)
|
||||
{
|
||||
int eth_len = (CHELSIO_CHIP_VERSION(type) <= CHELSIO_T5) ?
|
||||
ETH_HDR_LEN_G(be32_to_cpu(req->hdr_len)) :
|
||||
T6_ETH_HDR_LEN_G(be32_to_cpu(req->hdr_len));
|
||||
int ip_len = (CHELSIO_CHIP_VERSION(type) <= CHELSIO_T5) ?
|
||||
IP_HDR_LEN_G(be32_to_cpu(req->hdr_len)) :
|
||||
T6_IP_HDR_LEN_G(be32_to_cpu(req->hdr_len));
|
||||
struct iphdr *ip = (struct iphdr *)((u8 *)(req + 1) + eth_len);
|
||||
struct ipv6hdr *ip6 = (struct ipv6hdr *)((u8 *)(req + 1) + eth_len);
|
||||
struct tcphdr *tcp = (struct tcphdr *)
|
||||
((u8 *)(req + 1) + eth_len + ip_len);
|
||||
|
||||
if (ip->version == 4) {
|
||||
pr_debug("%s saddr 0x%x daddr 0x%x sport %u dport %u\n",
|
||||
__func__, ntohl(ip->saddr), ntohl(ip->daddr),
|
||||
ntohs(tcp->source), ntohs(tcp->dest));
|
||||
*iptype = 4;
|
||||
memcpy(peer_ip, &ip->saddr, 4);
|
||||
memcpy(local_ip, &ip->daddr, 4);
|
||||
} else {
|
||||
pr_debug("%s saddr %pI6 daddr %pI6 sport %u dport %u\n",
|
||||
__func__, ip6->saddr.s6_addr, ip6->daddr.s6_addr,
|
||||
ntohs(tcp->source), ntohs(tcp->dest));
|
||||
*iptype = 6;
|
||||
memcpy(peer_ip, ip6->saddr.s6_addr, 16);
|
||||
memcpy(local_ip, ip6->daddr.s6_addr, 16);
|
||||
}
|
||||
*peer_port = tcp->source;
|
||||
*local_port = tcp->dest;
|
||||
}
|
||||
EXPORT_SYMBOL(cxgb_get_4tuple);
|
||||
|
||||
static bool
|
||||
cxgb_our_interface(struct cxgb4_lld_info *lldi,
|
||||
struct net_device *(*get_real_dev)(struct net_device *),
|
||||
struct net_device *egress_dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
egress_dev = get_real_dev(egress_dev);
|
||||
for (i = 0; i < lldi->nports; i++)
|
||||
if (lldi->ports[i] == egress_dev)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
struct dst_entry *
|
||||
cxgb_find_route(struct cxgb4_lld_info *lldi,
|
||||
struct net_device *(*get_real_dev)(struct net_device *),
|
||||
__be32 local_ip, __be32 peer_ip, __be16 local_port,
|
||||
__be16 peer_port, u8 tos)
|
||||
{
|
||||
struct rtable *rt;
|
||||
struct flowi4 fl4;
|
||||
struct neighbour *n;
|
||||
|
||||
rt = ip_route_output_ports(&init_net, &fl4, NULL, peer_ip, local_ip,
|
||||
peer_port, local_port, IPPROTO_TCP,
|
||||
tos, 0);
|
||||
if (IS_ERR(rt))
|
||||
return NULL;
|
||||
n = dst_neigh_lookup(&rt->dst, &peer_ip);
|
||||
if (!n)
|
||||
return NULL;
|
||||
if (!cxgb_our_interface(lldi, get_real_dev, n->dev) &&
|
||||
!(n->dev->flags & IFF_LOOPBACK)) {
|
||||
neigh_release(n);
|
||||
dst_release(&rt->dst);
|
||||
return NULL;
|
||||
}
|
||||
neigh_release(n);
|
||||
return &rt->dst;
|
||||
}
|
||||
EXPORT_SYMBOL(cxgb_find_route);
|
||||
|
||||
struct dst_entry *
|
||||
cxgb_find_route6(struct cxgb4_lld_info *lldi,
|
||||
struct net_device *(*get_real_dev)(struct net_device *),
|
||||
__u8 *local_ip, __u8 *peer_ip, __be16 local_port,
|
||||
__be16 peer_port, u8 tos, __u32 sin6_scope_id)
|
||||
{
|
||||
struct dst_entry *dst = NULL;
|
||||
|
||||
if (IS_ENABLED(CONFIG_IPV6)) {
|
||||
struct flowi6 fl6;
|
||||
|
||||
memset(&fl6, 0, sizeof(fl6));
|
||||
memcpy(&fl6.daddr, peer_ip, 16);
|
||||
memcpy(&fl6.saddr, local_ip, 16);
|
||||
if (ipv6_addr_type(&fl6.daddr) & IPV6_ADDR_LINKLOCAL)
|
||||
fl6.flowi6_oif = sin6_scope_id;
|
||||
dst = ip6_route_output(&init_net, NULL, &fl6);
|
||||
if (!dst)
|
||||
goto out;
|
||||
if (!cxgb_our_interface(lldi, get_real_dev,
|
||||
ip6_dst_idev(dst)->dev) &&
|
||||
!(ip6_dst_idev(dst)->dev->flags & IFF_LOOPBACK)) {
|
||||
dst_release(dst);
|
||||
dst = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return dst;
|
||||
}
|
||||
EXPORT_SYMBOL(cxgb_find_route6);
|
160
drivers/net/ethernet/chelsio/libcxgb/libcxgb_cm.h
Normal file
160
drivers/net/ethernet/chelsio/libcxgb/libcxgb_cm.h
Normal file
@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Chelsio Communications, Inc. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __LIBCXGB_CM_H__
|
||||
#define __LIBCXGB_CM_H__
|
||||
|
||||
|
||||
#include <net/tcp.h>
|
||||
|
||||
#include <cxgb4.h>
|
||||
#include <t4_msg.h>
|
||||
#include <l2t.h>
|
||||
|
||||
void
|
||||
cxgb_get_4tuple(struct cpl_pass_accept_req *, enum chip_type,
|
||||
int *, __u8 *, __u8 *, __be16 *, __be16 *);
|
||||
struct dst_entry *
|
||||
cxgb_find_route(struct cxgb4_lld_info *,
|
||||
struct net_device *(*)(struct net_device *),
|
||||
__be32, __be32, __be16, __be16, u8);
|
||||
struct dst_entry *
|
||||
cxgb_find_route6(struct cxgb4_lld_info *,
|
||||
struct net_device *(*)(struct net_device *),
|
||||
__u8 *, __u8 *, __be16, __be16, u8, __u32);
|
||||
|
||||
/* Returns whether a CPL status conveys negative advice.
|
||||
*/
|
||||
static inline bool cxgb_is_neg_adv(unsigned int status)
|
||||
{
|
||||
return status == CPL_ERR_RTX_NEG_ADVICE ||
|
||||
status == CPL_ERR_PERSIST_NEG_ADVICE ||
|
||||
status == CPL_ERR_KEEPALV_NEG_ADVICE;
|
||||
}
|
||||
|
||||
static inline void
|
||||
cxgb_best_mtu(const unsigned short *mtus, unsigned short mtu,
|
||||
unsigned int *idx, int use_ts, int ipv6)
|
||||
{
|
||||
unsigned short hdr_size = (ipv6 ?
|
||||
sizeof(struct ipv6hdr) :
|
||||
sizeof(struct iphdr)) +
|
||||
sizeof(struct tcphdr) +
|
||||
(use_ts ?
|
||||
round_up(TCPOLEN_TIMESTAMP, 4) : 0);
|
||||
unsigned short data_size = mtu - hdr_size;
|
||||
|
||||
cxgb4_best_aligned_mtu(mtus, hdr_size, data_size, 8, idx);
|
||||
}
|
||||
|
||||
static inline u32 cxgb_compute_wscale(u32 win)
|
||||
{
|
||||
u32 wscale = 0;
|
||||
|
||||
while (wscale < 14 && (65535 << wscale) < win)
|
||||
wscale++;
|
||||
return wscale;
|
||||
}
|
||||
|
||||
static inline void
|
||||
cxgb_mk_tid_release(struct sk_buff *skb, u32 len, u32 tid, u16 chan)
|
||||
{
|
||||
struct cpl_tid_release *req;
|
||||
|
||||
req = (struct cpl_tid_release *)__skb_put(skb, len);
|
||||
memset(req, 0, len);
|
||||
|
||||
INIT_TP_WR(req, tid);
|
||||
OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_TID_RELEASE, tid));
|
||||
set_wr_txq(skb, CPL_PRIORITY_SETUP, chan);
|
||||
}
|
||||
|
||||
static inline void
|
||||
cxgb_mk_close_con_req(struct sk_buff *skb, u32 len, u32 tid, u16 chan,
|
||||
void *handle, arp_err_handler_t handler)
|
||||
{
|
||||
struct cpl_close_con_req *req;
|
||||
|
||||
req = (struct cpl_close_con_req *)__skb_put(skb, len);
|
||||
memset(req, 0, len);
|
||||
|
||||
INIT_TP_WR(req, tid);
|
||||
OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_CLOSE_CON_REQ, tid));
|
||||
set_wr_txq(skb, CPL_PRIORITY_DATA, chan);
|
||||
t4_set_arp_err_handler(skb, handle, handler);
|
||||
}
|
||||
|
||||
static inline void
|
||||
cxgb_mk_abort_req(struct sk_buff *skb, u32 len, u32 tid, u16 chan,
|
||||
void *handle, arp_err_handler_t handler)
|
||||
{
|
||||
struct cpl_abort_req *req;
|
||||
|
||||
req = (struct cpl_abort_req *)__skb_put(skb, len);
|
||||
memset(req, 0, len);
|
||||
|
||||
INIT_TP_WR(req, tid);
|
||||
OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ABORT_REQ, tid));
|
||||
req->cmd = CPL_ABORT_SEND_RST;
|
||||
set_wr_txq(skb, CPL_PRIORITY_DATA, chan);
|
||||
t4_set_arp_err_handler(skb, handle, handler);
|
||||
}
|
||||
|
||||
static inline void
|
||||
cxgb_mk_abort_rpl(struct sk_buff *skb, u32 len, u32 tid, u16 chan)
|
||||
{
|
||||
struct cpl_abort_rpl *rpl;
|
||||
|
||||
rpl = (struct cpl_abort_rpl *)__skb_put(skb, len);
|
||||
memset(rpl, 0, len);
|
||||
|
||||
INIT_TP_WR(rpl, tid);
|
||||
OPCODE_TID(rpl) = cpu_to_be32(MK_OPCODE_TID(CPL_ABORT_RPL, tid));
|
||||
rpl->cmd = CPL_ABORT_NO_RST;
|
||||
set_wr_txq(skb, CPL_PRIORITY_DATA, chan);
|
||||
}
|
||||
|
||||
static inline void
|
||||
cxgb_mk_rx_data_ack(struct sk_buff *skb, u32 len, u32 tid, u16 chan,
|
||||
u32 credit_dack)
|
||||
{
|
||||
struct cpl_rx_data_ack *req;
|
||||
|
||||
req = (struct cpl_rx_data_ack *)__skb_put(skb, len);
|
||||
memset(req, 0, len);
|
||||
|
||||
INIT_TP_WR(req, tid);
|
||||
OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_RX_DATA_ACK, tid));
|
||||
req->credit_dack = cpu_to_be32(credit_dack);
|
||||
set_wr_txq(skb, CPL_PRIORITY_ACK, chan);
|
||||
}
|
||||
#endif
|
@ -24,6 +24,7 @@
|
||||
#include <net/ip6_route.h>
|
||||
#include <net/addrconf.h>
|
||||
|
||||
#include <libcxgb_cm.h>
|
||||
#include "cxgbit.h"
|
||||
#include "clip_tbl.h"
|
||||
|
||||
@ -72,15 +73,6 @@ out:
|
||||
return wr_waitp->ret;
|
||||
}
|
||||
|
||||
/* Returns whether a CPL status conveys negative advice.
|
||||
*/
|
||||
static int cxgbit_is_neg_adv(unsigned int status)
|
||||
{
|
||||
return status == CPL_ERR_RTX_NEG_ADVICE ||
|
||||
status == CPL_ERR_PERSIST_NEG_ADVICE ||
|
||||
status == CPL_ERR_KEEPALV_NEG_ADVICE;
|
||||
}
|
||||
|
||||
static int cxgbit_np_hashfn(const struct cxgbit_np *cnp)
|
||||
{
|
||||
return ((unsigned long)cnp >> 10) & (NP_INFO_HASH_SIZE - 1);
|
||||
@ -623,21 +615,14 @@ void cxgbit_free_np(struct iscsi_np *np)
|
||||
static void cxgbit_send_halfclose(struct cxgbit_sock *csk)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct cpl_close_con_req *req;
|
||||
unsigned int len = roundup(sizeof(struct cpl_close_con_req), 16);
|
||||
u32 len = roundup(sizeof(struct cpl_close_con_req), 16);
|
||||
|
||||
skb = alloc_skb(len, GFP_ATOMIC);
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
req = (struct cpl_close_con_req *)__skb_put(skb, len);
|
||||
memset(req, 0, len);
|
||||
|
||||
set_wr_txq(skb, CPL_PRIORITY_DATA, csk->txq_idx);
|
||||
INIT_TP_WR(req, csk->tid);
|
||||
OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_CLOSE_CON_REQ,
|
||||
csk->tid));
|
||||
req->rsvd = 0;
|
||||
cxgb_mk_close_con_req(skb, len, csk->tid, csk->txq_idx,
|
||||
NULL, NULL);
|
||||
|
||||
cxgbit_skcb_flags(skb) |= SKCBF_TX_FLAG_COMPL;
|
||||
__skb_queue_tail(&csk->txq, skb);
|
||||
@ -662,9 +647,8 @@ static void cxgbit_abort_arp_failure(void *handle, struct sk_buff *skb)
|
||||
|
||||
static int cxgbit_send_abort_req(struct cxgbit_sock *csk)
|
||||
{
|
||||
struct cpl_abort_req *req;
|
||||
unsigned int len = roundup(sizeof(*req), 16);
|
||||
struct sk_buff *skb;
|
||||
u32 len = roundup(sizeof(struct cpl_abort_req), 16);
|
||||
|
||||
pr_debug("%s: csk %p tid %u; state %d\n",
|
||||
__func__, csk, csk->tid, csk->com.state);
|
||||
@ -675,15 +659,9 @@ static int cxgbit_send_abort_req(struct cxgbit_sock *csk)
|
||||
cxgbit_send_tx_flowc_wr(csk);
|
||||
|
||||
skb = __skb_dequeue(&csk->skbq);
|
||||
req = (struct cpl_abort_req *)__skb_put(skb, len);
|
||||
memset(req, 0, len);
|
||||
cxgb_mk_abort_req(skb, len, csk->tid, csk->txq_idx,
|
||||
csk->com.cdev, cxgbit_abort_arp_failure);
|
||||
|
||||
set_wr_txq(skb, CPL_PRIORITY_DATA, csk->txq_idx);
|
||||
t4_set_arp_err_handler(skb, csk->com.cdev, cxgbit_abort_arp_failure);
|
||||
INIT_TP_WR(req, csk->tid);
|
||||
OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ABORT_REQ,
|
||||
csk->tid));
|
||||
req->cmd = CPL_ABORT_SEND_RST;
|
||||
return cxgbit_l2t_send(csk->com.cdev, skb, csk->l2t);
|
||||
}
|
||||
|
||||
@ -789,109 +767,6 @@ void _cxgbit_free_csk(struct kref *kref)
|
||||
kfree(csk);
|
||||
}
|
||||
|
||||
static void
|
||||
cxgbit_get_tuple_info(struct cpl_pass_accept_req *req, int *iptype,
|
||||
__u8 *local_ip, __u8 *peer_ip, __be16 *local_port,
|
||||
__be16 *peer_port)
|
||||
{
|
||||
u32 eth_len = ETH_HDR_LEN_G(be32_to_cpu(req->hdr_len));
|
||||
u32 ip_len = IP_HDR_LEN_G(be32_to_cpu(req->hdr_len));
|
||||
struct iphdr *ip = (struct iphdr *)((u8 *)(req + 1) + eth_len);
|
||||
struct ipv6hdr *ip6 = (struct ipv6hdr *)((u8 *)(req + 1) + eth_len);
|
||||
struct tcphdr *tcp = (struct tcphdr *)
|
||||
((u8 *)(req + 1) + eth_len + ip_len);
|
||||
|
||||
if (ip->version == 4) {
|
||||
pr_debug("%s saddr 0x%x daddr 0x%x sport %u dport %u\n",
|
||||
__func__,
|
||||
ntohl(ip->saddr), ntohl(ip->daddr),
|
||||
ntohs(tcp->source),
|
||||
ntohs(tcp->dest));
|
||||
*iptype = 4;
|
||||
memcpy(peer_ip, &ip->saddr, 4);
|
||||
memcpy(local_ip, &ip->daddr, 4);
|
||||
} else {
|
||||
pr_debug("%s saddr %pI6 daddr %pI6 sport %u dport %u\n",
|
||||
__func__,
|
||||
ip6->saddr.s6_addr, ip6->daddr.s6_addr,
|
||||
ntohs(tcp->source),
|
||||
ntohs(tcp->dest));
|
||||
*iptype = 6;
|
||||
memcpy(peer_ip, ip6->saddr.s6_addr, 16);
|
||||
memcpy(local_ip, ip6->daddr.s6_addr, 16);
|
||||
}
|
||||
|
||||
*peer_port = tcp->source;
|
||||
*local_port = tcp->dest;
|
||||
}
|
||||
|
||||
static int
|
||||
cxgbit_our_interface(struct cxgbit_device *cdev, struct net_device *egress_dev)
|
||||
{
|
||||
u8 i;
|
||||
|
||||
egress_dev = cxgbit_get_real_dev(egress_dev);
|
||||
for (i = 0; i < cdev->lldi.nports; i++)
|
||||
if (cdev->lldi.ports[i] == egress_dev)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dst_entry *
|
||||
cxgbit_find_route6(struct cxgbit_device *cdev, __u8 *local_ip, __u8 *peer_ip,
|
||||
__be16 local_port, __be16 peer_port, u8 tos,
|
||||
__u32 sin6_scope_id)
|
||||
{
|
||||
struct dst_entry *dst = NULL;
|
||||
|
||||
if (IS_ENABLED(CONFIG_IPV6)) {
|
||||
struct flowi6 fl6;
|
||||
|
||||
memset(&fl6, 0, sizeof(fl6));
|
||||
memcpy(&fl6.daddr, peer_ip, 16);
|
||||
memcpy(&fl6.saddr, local_ip, 16);
|
||||
if (ipv6_addr_type(&fl6.daddr) & IPV6_ADDR_LINKLOCAL)
|
||||
fl6.flowi6_oif = sin6_scope_id;
|
||||
dst = ip6_route_output(&init_net, NULL, &fl6);
|
||||
if (!dst)
|
||||
goto out;
|
||||
if (!cxgbit_our_interface(cdev, ip6_dst_idev(dst)->dev) &&
|
||||
!(ip6_dst_idev(dst)->dev->flags & IFF_LOOPBACK)) {
|
||||
dst_release(dst);
|
||||
dst = NULL;
|
||||
}
|
||||
}
|
||||
out:
|
||||
return dst;
|
||||
}
|
||||
|
||||
static struct dst_entry *
|
||||
cxgbit_find_route(struct cxgbit_device *cdev, __be32 local_ip, __be32 peer_ip,
|
||||
__be16 local_port, __be16 peer_port, u8 tos)
|
||||
{
|
||||
struct rtable *rt;
|
||||
struct flowi4 fl4;
|
||||
struct neighbour *n;
|
||||
|
||||
rt = ip_route_output_ports(&init_net, &fl4, NULL, peer_ip,
|
||||
local_ip,
|
||||
peer_port, local_port, IPPROTO_TCP,
|
||||
tos, 0);
|
||||
if (IS_ERR(rt))
|
||||
return NULL;
|
||||
n = dst_neigh_lookup(&rt->dst, &peer_ip);
|
||||
if (!n)
|
||||
return NULL;
|
||||
if (!cxgbit_our_interface(cdev, n->dev) &&
|
||||
!(n->dev->flags & IFF_LOOPBACK)) {
|
||||
neigh_release(n);
|
||||
dst_release(&rt->dst);
|
||||
return NULL;
|
||||
}
|
||||
neigh_release(n);
|
||||
return &rt->dst;
|
||||
}
|
||||
|
||||
static void cxgbit_set_tcp_window(struct cxgbit_sock *csk, struct port_info *pi)
|
||||
{
|
||||
unsigned int linkspeed;
|
||||
@ -1072,21 +947,14 @@ int cxgbit_ofld_send(struct cxgbit_device *cdev, struct sk_buff *skb)
|
||||
|
||||
static void cxgbit_release_tid(struct cxgbit_device *cdev, u32 tid)
|
||||
{
|
||||
struct cpl_tid_release *req;
|
||||
unsigned int len = roundup(sizeof(*req), 16);
|
||||
u32 len = roundup(sizeof(struct cpl_tid_release), 16);
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = alloc_skb(len, GFP_ATOMIC);
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
req = (struct cpl_tid_release *)__skb_put(skb, len);
|
||||
memset(req, 0, len);
|
||||
|
||||
INIT_TP_WR(req, tid);
|
||||
OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(
|
||||
CPL_TID_RELEASE, tid));
|
||||
set_wr_txq(skb, CPL_PRIORITY_SETUP, 0);
|
||||
cxgb_mk_tid_release(skb, len, tid, 0);
|
||||
cxgbit_ofld_send(cdev, skb);
|
||||
}
|
||||
|
||||
@ -1108,20 +976,6 @@ cxgbit_l2t_send(struct cxgbit_device *cdev, struct sk_buff *skb,
|
||||
return ret < 0 ? ret : 0;
|
||||
}
|
||||
|
||||
static void
|
||||
cxgbit_best_mtu(const unsigned short *mtus, unsigned short mtu,
|
||||
unsigned int *idx, int use_ts, int ipv6)
|
||||
{
|
||||
unsigned short hdr_size = (ipv6 ? sizeof(struct ipv6hdr) :
|
||||
sizeof(struct iphdr)) +
|
||||
sizeof(struct tcphdr) +
|
||||
(use_ts ? round_up(TCPOLEN_TIMESTAMP,
|
||||
4) : 0);
|
||||
unsigned short data_size = mtu - hdr_size;
|
||||
|
||||
cxgb4_best_aligned_mtu(mtus, hdr_size, data_size, 8, idx);
|
||||
}
|
||||
|
||||
static void cxgbit_send_rx_credits(struct cxgbit_sock *csk, struct sk_buff *skb)
|
||||
{
|
||||
if (csk->com.state != CSK_STATE_ESTABLISHED) {
|
||||
@ -1140,22 +994,18 @@ static void cxgbit_send_rx_credits(struct cxgbit_sock *csk, struct sk_buff *skb)
|
||||
int cxgbit_rx_data_ack(struct cxgbit_sock *csk)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct cpl_rx_data_ack *req;
|
||||
unsigned int len = roundup(sizeof(*req), 16);
|
||||
u32 len = roundup(sizeof(struct cpl_rx_data_ack), 16);
|
||||
u32 credit_dack;
|
||||
|
||||
skb = alloc_skb(len, GFP_KERNEL);
|
||||
if (!skb)
|
||||
return -1;
|
||||
|
||||
req = (struct cpl_rx_data_ack *)__skb_put(skb, len);
|
||||
memset(req, 0, len);
|
||||
credit_dack = RX_DACK_CHANGE_F | RX_DACK_MODE_V(1) |
|
||||
RX_CREDITS_V(csk->rx_credits);
|
||||
|
||||
set_wr_txq(skb, CPL_PRIORITY_ACK, csk->ctrlq_idx);
|
||||
INIT_TP_WR(req, csk->tid);
|
||||
OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_RX_DATA_ACK,
|
||||
csk->tid));
|
||||
req->credit_dack = cpu_to_be32(RX_DACK_CHANGE_F | RX_DACK_MODE_V(1) |
|
||||
RX_CREDITS_V(csk->rx_credits));
|
||||
cxgb_mk_rx_data_ack(skb, len, csk->tid, csk->ctrlq_idx,
|
||||
credit_dack);
|
||||
|
||||
csk->rx_credits = 0;
|
||||
|
||||
@ -1210,15 +1060,6 @@ out:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static u32 cxgbit_compute_wscale(u32 win)
|
||||
{
|
||||
u32 wscale = 0;
|
||||
|
||||
while (wscale < 14 && (65535 << wscale) < win)
|
||||
wscale++;
|
||||
return wscale;
|
||||
}
|
||||
|
||||
static void
|
||||
cxgbit_pass_accept_rpl(struct cxgbit_sock *csk, struct cpl_pass_accept_req *req)
|
||||
{
|
||||
@ -1246,10 +1087,10 @@ cxgbit_pass_accept_rpl(struct cxgbit_sock *csk, struct cpl_pass_accept_req *req)
|
||||
INIT_TP_WR(rpl5, csk->tid);
|
||||
OPCODE_TID(rpl5) = cpu_to_be32(MK_OPCODE_TID(CPL_PASS_ACCEPT_RPL,
|
||||
csk->tid));
|
||||
cxgbit_best_mtu(csk->com.cdev->lldi.mtus, csk->mtu, &mtu_idx,
|
||||
req->tcpopt.tstamp,
|
||||
(csk->com.remote_addr.ss_family == AF_INET) ? 0 : 1);
|
||||
wscale = cxgbit_compute_wscale(csk->rcv_win);
|
||||
cxgb_best_mtu(csk->com.cdev->lldi.mtus, csk->mtu, &mtu_idx,
|
||||
req->tcpopt.tstamp,
|
||||
(csk->com.remote_addr.ss_family == AF_INET) ? 0 : 1);
|
||||
wscale = cxgb_compute_wscale(csk->rcv_win);
|
||||
/*
|
||||
* Specify the largest window that will fit in opt0. The
|
||||
* remainder will be specified in the rx_data_ack.
|
||||
@ -1340,8 +1181,8 @@ cxgbit_pass_accept_req(struct cxgbit_device *cdev, struct sk_buff *skb)
|
||||
goto rel_skb;
|
||||
}
|
||||
|
||||
cxgbit_get_tuple_info(req, &iptype, local_ip, peer_ip,
|
||||
&local_port, &peer_port);
|
||||
cxgb_get_4tuple(req, cdev->lldi.adapter_type, &iptype, local_ip,
|
||||
peer_ip, &local_port, &peer_port);
|
||||
|
||||
/* Find output route */
|
||||
if (iptype == 4) {
|
||||
@ -1350,21 +1191,23 @@ cxgbit_pass_accept_req(struct cxgbit_device *cdev, struct sk_buff *skb)
|
||||
, __func__, cnp, tid,
|
||||
local_ip, peer_ip, ntohs(local_port),
|
||||
ntohs(peer_port), peer_mss);
|
||||
dst = cxgbit_find_route(cdev, *(__be32 *)local_ip,
|
||||
*(__be32 *)peer_ip,
|
||||
local_port, peer_port,
|
||||
PASS_OPEN_TOS_G(ntohl(req->tos_stid)));
|
||||
dst = cxgb_find_route(&cdev->lldi, cxgbit_get_real_dev,
|
||||
*(__be32 *)local_ip,
|
||||
*(__be32 *)peer_ip,
|
||||
local_port, peer_port,
|
||||
PASS_OPEN_TOS_G(ntohl(req->tos_stid)));
|
||||
} else {
|
||||
pr_debug("%s parent sock %p tid %u laddr %pI6 raddr %pI6 "
|
||||
"lport %d rport %d peer_mss %d\n"
|
||||
, __func__, cnp, tid,
|
||||
local_ip, peer_ip, ntohs(local_port),
|
||||
ntohs(peer_port), peer_mss);
|
||||
dst = cxgbit_find_route6(cdev, local_ip, peer_ip,
|
||||
local_port, peer_port,
|
||||
PASS_OPEN_TOS_G(ntohl(req->tos_stid)),
|
||||
((struct sockaddr_in6 *)
|
||||
&cnp->com.local_addr)->sin6_scope_id);
|
||||
dst = cxgb_find_route6(&cdev->lldi, cxgbit_get_real_dev,
|
||||
local_ip, peer_ip,
|
||||
local_port, peer_port,
|
||||
PASS_OPEN_TOS_G(ntohl(req->tos_stid)),
|
||||
((struct sockaddr_in6 *)
|
||||
&cnp->com.local_addr)->sin6_scope_id);
|
||||
}
|
||||
if (!dst) {
|
||||
pr_err("%s - failed to find dst entry!\n",
|
||||
@ -1795,16 +1638,15 @@ static void cxgbit_abort_req_rss(struct cxgbit_sock *csk, struct sk_buff *skb)
|
||||
{
|
||||
struct cpl_abort_req_rss *hdr = cplhdr(skb);
|
||||
unsigned int tid = GET_TID(hdr);
|
||||
struct cpl_abort_rpl *rpl;
|
||||
struct sk_buff *rpl_skb;
|
||||
bool release = false;
|
||||
bool wakeup_thread = false;
|
||||
unsigned int len = roundup(sizeof(*rpl), 16);
|
||||
u32 len = roundup(sizeof(struct cpl_abort_rpl), 16);
|
||||
|
||||
pr_debug("%s: csk %p; tid %u; state %d\n",
|
||||
__func__, csk, tid, csk->com.state);
|
||||
|
||||
if (cxgbit_is_neg_adv(hdr->status)) {
|
||||
if (cxgb_is_neg_adv(hdr->status)) {
|
||||
pr_err("%s: got neg advise %d on tid %u\n",
|
||||
__func__, hdr->status, tid);
|
||||
goto rel_skb;
|
||||
@ -1839,14 +1681,8 @@ static void cxgbit_abort_req_rss(struct cxgbit_sock *csk, struct sk_buff *skb)
|
||||
cxgbit_send_tx_flowc_wr(csk);
|
||||
|
||||
rpl_skb = __skb_dequeue(&csk->skbq);
|
||||
set_wr_txq(skb, CPL_PRIORITY_DATA, csk->txq_idx);
|
||||
|
||||
rpl = (struct cpl_abort_rpl *)__skb_put(rpl_skb, len);
|
||||
memset(rpl, 0, len);
|
||||
|
||||
INIT_TP_WR(rpl, csk->tid);
|
||||
OPCODE_TID(rpl) = cpu_to_be32(MK_OPCODE_TID(CPL_ABORT_RPL, tid));
|
||||
rpl->cmd = CPL_ABORT_NO_RST;
|
||||
cxgb_mk_abort_rpl(rpl_skb, len, csk->tid, csk->txq_idx);
|
||||
cxgbit_ofld_send(csk->com.cdev, rpl_skb);
|
||||
|
||||
if (wakeup_thread) {
|
||||
|
Loading…
Reference in New Issue
Block a user