Skip to content

Commit 1e28eaa

Browse files
mkalderondavem330
authored andcommitted
qed: Add iWARP support for fpdu spanned over more than two tcp packets
We continue to maintain a maximum of three buffers per fpdu, to ensure that there are enough buffers for additional unaligned mpa packets. To support this, if a fpdu is split over more than two tcp packets, we use an intermediate buffer to copy the data to the previous buffer, then we can release the data. We need an intermediate buffer as the initial buffer partial packet could be located at the end of the packet, not leaving room for additional data. This is a corner case, and will usually not be the case. Signed-off-by: Michal Kalderon <Michal.Kalderon@cavium.com> Signed-off-by: Ariel Elior <Ariel.Elior@cavium.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent c7d1d83 commit 1e28eaa

File tree

2 files changed

+194
-0
lines changed

2 files changed

+194
-0
lines changed

drivers/net/ethernet/qlogic/qed/qed_iwarp.c

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1420,6 +1420,7 @@ void qed_iwarp_resc_free(struct qed_hwfn *p_hwfn)
14201420
qed_rdma_bmap_free(p_hwfn, &p_hwfn->p_rdma_info->tcp_cid_map, 1);
14211421
kfree(iwarp_info->mpa_bufs);
14221422
kfree(iwarp_info->partial_fpdus);
1423+
kfree(iwarp_info->mpa_intermediate_buf);
14231424
}
14241425

14251426
int qed_iwarp_accept(void *rdma_cxt, struct qed_iwarp_accept_in *iparams)
@@ -1762,6 +1763,11 @@ char *pkt_type_str[] = {
17621763
"QED_IWARP_MPA_PKT_UNALIGNED"
17631764
};
17641765

1766+
static int
1767+
qed_iwarp_recycle_pkt(struct qed_hwfn *p_hwfn,
1768+
struct qed_iwarp_fpdu *fpdu,
1769+
struct qed_iwarp_ll2_buff *buf);
1770+
17651771
static enum qed_iwarp_mpa_pkt_type
17661772
qed_iwarp_mpa_classify(struct qed_hwfn *p_hwfn,
17671773
struct qed_iwarp_fpdu *fpdu,
@@ -1822,6 +1828,68 @@ qed_iwarp_init_fpdu(struct qed_iwarp_ll2_buff *buf,
18221828
fpdu->mpa_frag_len = fpdu->fpdu_length - fpdu->incomplete_bytes;
18231829
}
18241830

1831+
static int
1832+
qed_iwarp_cp_pkt(struct qed_hwfn *p_hwfn,
1833+
struct qed_iwarp_fpdu *fpdu,
1834+
struct unaligned_opaque_data *pkt_data,
1835+
struct qed_iwarp_ll2_buff *buf, u16 tcp_payload_size)
1836+
{
1837+
u8 *tmp_buf = p_hwfn->p_rdma_info->iwarp.mpa_intermediate_buf;
1838+
int rc;
1839+
1840+
/* need to copy the data from the partial packet stored in fpdu
1841+
* to the new buf, for this we also need to move the data currently
1842+
* placed on the buf. The assumption is that the buffer is big enough
1843+
* since fpdu_length <= mss, we use an intermediate buffer since
1844+
* we may need to copy the new data to an overlapping location
1845+
*/
1846+
if ((fpdu->mpa_frag_len + tcp_payload_size) > (u16)buf->buff_size) {
1847+
DP_ERR(p_hwfn,
1848+
"MPA ALIGN: Unexpected: buffer is not large enough for split fpdu buff_size = %d mpa_frag_len = %d, tcp_payload_size = %d, incomplete_bytes = %d\n",
1849+
buf->buff_size, fpdu->mpa_frag_len,
1850+
tcp_payload_size, fpdu->incomplete_bytes);
1851+
return -EINVAL;
1852+
}
1853+
1854+
DP_VERBOSE(p_hwfn, QED_MSG_RDMA,
1855+
"MPA ALIGN Copying fpdu: [%p, %d] [%p, %d]\n",
1856+
fpdu->mpa_frag_virt, fpdu->mpa_frag_len,
1857+
(u8 *)(buf->data) + pkt_data->first_mpa_offset,
1858+
tcp_payload_size);
1859+
1860+
memcpy(tmp_buf, fpdu->mpa_frag_virt, fpdu->mpa_frag_len);
1861+
memcpy(tmp_buf + fpdu->mpa_frag_len,
1862+
(u8 *)(buf->data) + pkt_data->first_mpa_offset,
1863+
tcp_payload_size);
1864+
1865+
rc = qed_iwarp_recycle_pkt(p_hwfn, fpdu, fpdu->mpa_buf);
1866+
if (rc)
1867+
return rc;
1868+
1869+
/* If we managed to post the buffer copy the data to the new buffer
1870+
* o/w this will occur in the next round...
1871+
*/
1872+
memcpy((u8 *)(buf->data), tmp_buf,
1873+
fpdu->mpa_frag_len + tcp_payload_size);
1874+
1875+
fpdu->mpa_buf = buf;
1876+
/* fpdu->pkt_hdr remains as is */
1877+
/* fpdu->mpa_frag is overridden with new buf */
1878+
fpdu->mpa_frag = buf->data_phys_addr;
1879+
fpdu->mpa_frag_virt = buf->data;
1880+
fpdu->mpa_frag_len += tcp_payload_size;
1881+
1882+
fpdu->incomplete_bytes -= tcp_payload_size;
1883+
1884+
DP_VERBOSE(p_hwfn,
1885+
QED_MSG_RDMA,
1886+
"MPA ALIGN: split fpdu buff_size = %d mpa_frag_len = %d, tcp_payload_size = %d, incomplete_bytes = %d\n",
1887+
buf->buff_size, fpdu->mpa_frag_len, tcp_payload_size,
1888+
fpdu->incomplete_bytes);
1889+
1890+
return 0;
1891+
}
1892+
18251893
static void
18261894
qed_iwarp_update_fpdu_length(struct qed_hwfn *p_hwfn,
18271895
struct qed_iwarp_fpdu *fpdu, u8 *mpa_data)
@@ -1843,6 +1911,90 @@ qed_iwarp_update_fpdu_length(struct qed_hwfn *p_hwfn,
18431911
}
18441912
}
18451913

1914+
#define QED_IWARP_IS_RIGHT_EDGE(_curr_pkt) \
1915+
(GET_FIELD((_curr_pkt)->flags, \
1916+
UNALIGNED_OPAQUE_DATA_PKT_REACHED_WIN_RIGHT_EDGE))
1917+
1918+
/* This function is used to recycle a buffer using the ll2 drop option. It
1919+
* uses the mechanism to ensure that all buffers posted to tx before this one
1920+
* were completed. The buffer sent here will be sent as a cookie in the tx
1921+
* completion function and can then be reposted to rx chain when done. The flow
1922+
* that requires this is the flow where a FPDU splits over more than 3 tcp
1923+
* segments. In this case the driver needs to re-post a rx buffer instead of
1924+
* the one received, but driver can't simply repost a buffer it copied from
1925+
* as there is a case where the buffer was originally a packed FPDU, and is
1926+
* partially posted to FW. Driver needs to ensure FW is done with it.
1927+
*/
1928+
static int
1929+
qed_iwarp_recycle_pkt(struct qed_hwfn *p_hwfn,
1930+
struct qed_iwarp_fpdu *fpdu,
1931+
struct qed_iwarp_ll2_buff *buf)
1932+
{
1933+
struct qed_ll2_tx_pkt_info tx_pkt;
1934+
u8 ll2_handle;
1935+
int rc;
1936+
1937+
memset(&tx_pkt, 0, sizeof(tx_pkt));
1938+
tx_pkt.num_of_bds = 1;
1939+
tx_pkt.tx_dest = QED_LL2_TX_DEST_DROP;
1940+
tx_pkt.l4_hdr_offset_w = fpdu->pkt_hdr_size >> 2;
1941+
tx_pkt.first_frag = fpdu->pkt_hdr;
1942+
tx_pkt.first_frag_len = fpdu->pkt_hdr_size;
1943+
buf->piggy_buf = NULL;
1944+
tx_pkt.cookie = buf;
1945+
1946+
ll2_handle = p_hwfn->p_rdma_info->iwarp.ll2_mpa_handle;
1947+
1948+
rc = qed_ll2_prepare_tx_packet(p_hwfn, ll2_handle, &tx_pkt, true);
1949+
if (rc)
1950+
DP_VERBOSE(p_hwfn, QED_MSG_RDMA,
1951+
"Can't drop packet rc=%d\n", rc);
1952+
1953+
DP_VERBOSE(p_hwfn,
1954+
QED_MSG_RDMA,
1955+
"MPA_ALIGN: send drop tx packet [%lx, 0x%x], buf=%p, rc=%d\n",
1956+
(unsigned long int)tx_pkt.first_frag,
1957+
tx_pkt.first_frag_len, buf, rc);
1958+
1959+
return rc;
1960+
}
1961+
1962+
static int
1963+
qed_iwarp_win_right_edge(struct qed_hwfn *p_hwfn, struct qed_iwarp_fpdu *fpdu)
1964+
{
1965+
struct qed_ll2_tx_pkt_info tx_pkt;
1966+
u8 ll2_handle;
1967+
int rc;
1968+
1969+
memset(&tx_pkt, 0, sizeof(tx_pkt));
1970+
tx_pkt.num_of_bds = 1;
1971+
tx_pkt.tx_dest = QED_LL2_TX_DEST_LB;
1972+
tx_pkt.l4_hdr_offset_w = fpdu->pkt_hdr_size >> 2;
1973+
1974+
tx_pkt.first_frag = fpdu->pkt_hdr;
1975+
tx_pkt.first_frag_len = fpdu->pkt_hdr_size;
1976+
tx_pkt.enable_ip_cksum = true;
1977+
tx_pkt.enable_l4_cksum = true;
1978+
tx_pkt.calc_ip_len = true;
1979+
/* vlan overload with enum iwarp_ll2_tx_queues */
1980+
tx_pkt.vlan = IWARP_LL2_ALIGNED_RIGHT_TRIMMED_TX_QUEUE;
1981+
1982+
ll2_handle = p_hwfn->p_rdma_info->iwarp.ll2_mpa_handle;
1983+
1984+
rc = qed_ll2_prepare_tx_packet(p_hwfn, ll2_handle, &tx_pkt, true);
1985+
if (rc)
1986+
DP_VERBOSE(p_hwfn, QED_MSG_RDMA,
1987+
"Can't send right edge rc=%d\n", rc);
1988+
DP_VERBOSE(p_hwfn,
1989+
QED_MSG_RDMA,
1990+
"MPA_ALIGN: Sent right edge FPDU num_bds=%d [%lx, 0x%x], rc=%d\n",
1991+
tx_pkt.num_of_bds,
1992+
(unsigned long int)tx_pkt.first_frag,
1993+
tx_pkt.first_frag_len, rc);
1994+
1995+
return rc;
1996+
}
1997+
18461998
static int
18471999
qed_iwarp_send_fpdu(struct qed_hwfn *p_hwfn,
18482000
struct qed_iwarp_fpdu *fpdu,
@@ -1971,6 +2123,20 @@ qed_iwarp_process_mpa_pkt(struct qed_hwfn *p_hwfn,
19712123
mpa_buf->tcp_payload_len,
19722124
mpa_buf->placement_offset);
19732125

2126+
if (!QED_IWARP_IS_RIGHT_EDGE(curr_pkt)) {
2127+
mpa_buf->tcp_payload_len = 0;
2128+
break;
2129+
}
2130+
2131+
rc = qed_iwarp_win_right_edge(p_hwfn, fpdu);
2132+
2133+
if (rc) {
2134+
DP_VERBOSE(p_hwfn, QED_MSG_RDMA,
2135+
"Can't send FPDU:reset rc=%d\n", rc);
2136+
memset(fpdu, 0, sizeof(*fpdu));
2137+
break;
2138+
}
2139+
19742140
mpa_buf->tcp_payload_len = 0;
19752141
break;
19762142
case QED_IWARP_MPA_PKT_PACKED:
@@ -1994,6 +2160,28 @@ qed_iwarp_process_mpa_pkt(struct qed_hwfn *p_hwfn,
19942160
break;
19952161
case QED_IWARP_MPA_PKT_UNALIGNED:
19962162
qed_iwarp_update_fpdu_length(p_hwfn, fpdu, mpa_data);
2163+
if (mpa_buf->tcp_payload_len < fpdu->incomplete_bytes) {
2164+
/* special handling of fpdu split over more
2165+
* than 2 segments
2166+
*/
2167+
if (QED_IWARP_IS_RIGHT_EDGE(curr_pkt)) {
2168+
rc = qed_iwarp_win_right_edge(p_hwfn,
2169+
fpdu);
2170+
/* packet will be re-processed later */
2171+
if (rc)
2172+
return rc;
2173+
}
2174+
2175+
rc = qed_iwarp_cp_pkt(p_hwfn, fpdu, curr_pkt,
2176+
buf,
2177+
mpa_buf->tcp_payload_len);
2178+
if (rc) /* packet will be re-processed later */
2179+
return rc;
2180+
2181+
mpa_buf->tcp_payload_len = 0;
2182+
break;
2183+
}
2184+
19972185
rc = qed_iwarp_send_fpdu(p_hwfn, fpdu, curr_pkt, buf,
19982186
mpa_buf->tcp_payload_len,
19992187
pkt_type);
@@ -2510,6 +2698,11 @@ qed_iwarp_ll2_start(struct qed_hwfn *p_hwfn,
25102698
goto err;
25112699

25122700
iwarp_info->max_num_partial_fpdus = (u16)p_hwfn->p_rdma_info->num_qps;
2701+
2702+
iwarp_info->mpa_intermediate_buf = kzalloc(mpa_buff_size, GFP_KERNEL);
2703+
if (!iwarp_info->mpa_intermediate_buf)
2704+
goto err;
2705+
25132706
/* The mpa_bufs array serves for pending RX packets received on the
25142707
* mpa ll2 that don't have place on the tx ring and require later
25152708
* processing. We can't fail on allocation of such a struct therefore

drivers/net/ethernet/qlogic/qed/qed_iwarp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ struct qed_iwarp_info {
107107
enum mpa_rtr_type rtr_type;
108108
struct qed_iwarp_fpdu *partial_fpdus;
109109
struct qed_iwarp_ll2_mpa_buf *mpa_bufs;
110+
u8 *mpa_intermediate_buf;
110111
u16 max_num_partial_fpdus;
111112
};
112113

0 commit comments

Comments
 (0)