Skip to content

Commit 469981b

Browse files
mkalderondavem330
authored andcommitted
qed: Add unaligned and packed packet processing
The fpdu data structure is preallocated per connection. Each connection stores the current status of the connection: either nothing pending, or there is a partial fpdu that is waiting for the rest of the fpdu (incomplete bytes != 0). The same structure is also used for splitting a packet when there are packed fpdus. The structure is initialized with all data required for sending the fpdu back to the FW. A fpdu will always be spanned across a maximum of 3 tx bds. One for the header, one for the partial fdpu received and one for the remainder (unaligned) packet. In case of packed fpdu's, two fragments are used, one for the header and one for the data. Corner cases are not handled in the patch for clarity, and will be added as a separate patch. 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 fcb39f6 commit 469981b

File tree

2 files changed

+270
-0
lines changed

2 files changed

+270
-0
lines changed

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

Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1419,6 +1419,7 @@ void qed_iwarp_resc_free(struct qed_hwfn *p_hwfn)
14191419

14201420
qed_rdma_bmap_free(p_hwfn, &p_hwfn->p_rdma_info->tcp_cid_map, 1);
14211421
kfree(iwarp_info->mpa_bufs);
1422+
kfree(iwarp_info->partial_fpdus);
14221423
}
14231424

14241425
int qed_iwarp_accept(void *rdma_cxt, struct qed_iwarp_accept_in *iparams)
@@ -1716,8 +1717,170 @@ qed_iwarp_parse_rx_pkt(struct qed_hwfn *p_hwfn,
17161717
return 0;
17171718
}
17181719

1720+
static struct qed_iwarp_fpdu *qed_iwarp_get_curr_fpdu(struct qed_hwfn *p_hwfn,
1721+
u16 cid)
1722+
{
1723+
struct qed_iwarp_info *iwarp_info = &p_hwfn->p_rdma_info->iwarp;
1724+
struct qed_iwarp_fpdu *partial_fpdu;
1725+
u32 idx;
1726+
1727+
idx = cid - qed_cxt_get_proto_cid_start(p_hwfn, PROTOCOLID_IWARP);
1728+
if (idx >= iwarp_info->max_num_partial_fpdus) {
1729+
DP_ERR(p_hwfn, "Invalid cid %x max_num_partial_fpdus=%x\n", cid,
1730+
iwarp_info->max_num_partial_fpdus);
1731+
return NULL;
1732+
}
1733+
1734+
partial_fpdu = &iwarp_info->partial_fpdus[idx];
1735+
1736+
return partial_fpdu;
1737+
}
1738+
1739+
enum qed_iwarp_mpa_pkt_type {
1740+
QED_IWARP_MPA_PKT_PACKED,
1741+
QED_IWARP_MPA_PKT_PARTIAL,
1742+
QED_IWARP_MPA_PKT_UNALIGNED
1743+
};
1744+
1745+
#define QED_IWARP_MPA_FPDU_LENGTH_SIZE (2)
1746+
#define QED_IWARP_MPA_CRC32_DIGEST_SIZE (4)
1747+
1748+
/* Pad to multiple of 4 */
1749+
#define QED_IWARP_PDU_DATA_LEN_WITH_PAD(data_len) ALIGN(data_len, 4)
1750+
#define QED_IWARP_FPDU_LEN_WITH_PAD(_mpa_len) \
1751+
(QED_IWARP_PDU_DATA_LEN_WITH_PAD((_mpa_len) + \
1752+
QED_IWARP_MPA_FPDU_LENGTH_SIZE) + \
1753+
QED_IWARP_MPA_CRC32_DIGEST_SIZE)
1754+
17191755
/* fpdu can be fragmented over maximum 3 bds: header, partial mpa, unaligned */
17201756
#define QED_IWARP_MAX_BDS_PER_FPDU 3
1757+
1758+
char *pkt_type_str[] = {
1759+
"QED_IWARP_MPA_PKT_PACKED",
1760+
"QED_IWARP_MPA_PKT_PARTIAL",
1761+
"QED_IWARP_MPA_PKT_UNALIGNED"
1762+
};
1763+
1764+
static enum qed_iwarp_mpa_pkt_type
1765+
qed_iwarp_mpa_classify(struct qed_hwfn *p_hwfn,
1766+
struct qed_iwarp_fpdu *fpdu,
1767+
u16 tcp_payload_len, u8 *mpa_data)
1768+
{
1769+
enum qed_iwarp_mpa_pkt_type pkt_type;
1770+
u16 mpa_len;
1771+
1772+
if (fpdu->incomplete_bytes) {
1773+
pkt_type = QED_IWARP_MPA_PKT_UNALIGNED;
1774+
goto out;
1775+
}
1776+
1777+
mpa_len = ntohs(*((u16 *)(mpa_data)));
1778+
fpdu->fpdu_length = QED_IWARP_FPDU_LEN_WITH_PAD(mpa_len);
1779+
1780+
if (fpdu->fpdu_length <= tcp_payload_len)
1781+
pkt_type = QED_IWARP_MPA_PKT_PACKED;
1782+
else
1783+
pkt_type = QED_IWARP_MPA_PKT_PARTIAL;
1784+
1785+
out:
1786+
DP_VERBOSE(p_hwfn, QED_MSG_RDMA,
1787+
"MPA_ALIGN: %s: fpdu_length=0x%x tcp_payload_len:0x%x\n",
1788+
pkt_type_str[pkt_type], fpdu->fpdu_length, tcp_payload_len);
1789+
1790+
return pkt_type;
1791+
}
1792+
1793+
static void
1794+
qed_iwarp_init_fpdu(struct qed_iwarp_ll2_buff *buf,
1795+
struct qed_iwarp_fpdu *fpdu,
1796+
struct unaligned_opaque_data *pkt_data,
1797+
u16 tcp_payload_size, u8 placement_offset)
1798+
{
1799+
fpdu->mpa_buf = buf;
1800+
fpdu->pkt_hdr = buf->data_phys_addr + placement_offset;
1801+
fpdu->pkt_hdr_size = pkt_data->tcp_payload_offset;
1802+
fpdu->mpa_frag = buf->data_phys_addr + pkt_data->first_mpa_offset;
1803+
fpdu->mpa_frag_virt = (u8 *)(buf->data) + pkt_data->first_mpa_offset;
1804+
1805+
if (tcp_payload_size < fpdu->fpdu_length)
1806+
fpdu->incomplete_bytes = fpdu->fpdu_length - tcp_payload_size;
1807+
else
1808+
fpdu->incomplete_bytes = 0; /* complete fpdu */
1809+
1810+
fpdu->mpa_frag_len = fpdu->fpdu_length - fpdu->incomplete_bytes;
1811+
}
1812+
1813+
static int
1814+
qed_iwarp_send_fpdu(struct qed_hwfn *p_hwfn,
1815+
struct qed_iwarp_fpdu *fpdu,
1816+
struct unaligned_opaque_data *curr_pkt,
1817+
struct qed_iwarp_ll2_buff *buf,
1818+
u16 tcp_payload_size, enum qed_iwarp_mpa_pkt_type pkt_type)
1819+
{
1820+
struct qed_ll2_tx_pkt_info tx_pkt;
1821+
u8 ll2_handle;
1822+
int rc;
1823+
1824+
memset(&tx_pkt, 0, sizeof(tx_pkt));
1825+
1826+
/* An unaligned packet means it's split over two tcp segments. So the
1827+
* complete packet requires 3 bds, one for the header, one for the
1828+
* part of the fpdu of the first tcp segment, and the last fragment
1829+
* will point to the remainder of the fpdu. A packed pdu, requires only
1830+
* two bds, one for the header and one for the data.
1831+
*/
1832+
tx_pkt.num_of_bds = (pkt_type == QED_IWARP_MPA_PKT_UNALIGNED) ? 3 : 2;
1833+
tx_pkt.tx_dest = QED_LL2_TX_DEST_LB;
1834+
tx_pkt.l4_hdr_offset_w = fpdu->pkt_hdr_size >> 2; /* offset in words */
1835+
1836+
/* Send the mpa_buf only with the last fpdu (in case of packed) */
1837+
if (pkt_type == QED_IWARP_MPA_PKT_UNALIGNED ||
1838+
tcp_payload_size <= fpdu->fpdu_length)
1839+
tx_pkt.cookie = fpdu->mpa_buf;
1840+
1841+
tx_pkt.first_frag = fpdu->pkt_hdr;
1842+
tx_pkt.first_frag_len = fpdu->pkt_hdr_size;
1843+
tx_pkt.enable_ip_cksum = true;
1844+
tx_pkt.enable_l4_cksum = true;
1845+
tx_pkt.calc_ip_len = true;
1846+
/* vlan overload with enum iwarp_ll2_tx_queues */
1847+
tx_pkt.vlan = IWARP_LL2_ALIGNED_TX_QUEUE;
1848+
1849+
ll2_handle = p_hwfn->p_rdma_info->iwarp.ll2_mpa_handle;
1850+
1851+
/* Set first fragment to header */
1852+
rc = qed_ll2_prepare_tx_packet(p_hwfn, ll2_handle, &tx_pkt, true);
1853+
if (rc)
1854+
goto out;
1855+
1856+
/* Set second fragment to first part of packet */
1857+
rc = qed_ll2_set_fragment_of_tx_packet(p_hwfn, ll2_handle,
1858+
fpdu->mpa_frag,
1859+
fpdu->mpa_frag_len);
1860+
if (rc)
1861+
goto out;
1862+
1863+
if (!fpdu->incomplete_bytes)
1864+
goto out;
1865+
1866+
/* Set third fragment to second part of the packet */
1867+
rc = qed_ll2_set_fragment_of_tx_packet(p_hwfn,
1868+
ll2_handle,
1869+
buf->data_phys_addr +
1870+
curr_pkt->first_mpa_offset,
1871+
fpdu->incomplete_bytes);
1872+
out:
1873+
DP_VERBOSE(p_hwfn,
1874+
QED_MSG_RDMA,
1875+
"MPA_ALIGN: Sent FPDU num_bds=%d first_frag_len=%x, mpa_frag_len=0x%x, incomplete_bytes:0x%x rc=%d\n",
1876+
tx_pkt.num_of_bds,
1877+
tx_pkt.first_frag_len,
1878+
fpdu->mpa_frag_len,
1879+
fpdu->incomplete_bytes, rc);
1880+
1881+
return rc;
1882+
}
1883+
17211884
static void
17221885
qed_iwarp_mpa_get_data(struct qed_hwfn *p_hwfn,
17231886
struct unaligned_opaque_data *curr_pkt,
@@ -1741,9 +1904,79 @@ static int
17411904
qed_iwarp_process_mpa_pkt(struct qed_hwfn *p_hwfn,
17421905
struct qed_iwarp_ll2_mpa_buf *mpa_buf)
17431906
{
1907+
struct unaligned_opaque_data *curr_pkt = &mpa_buf->data;
17441908
struct qed_iwarp_ll2_buff *buf = mpa_buf->ll2_buf;
1909+
enum qed_iwarp_mpa_pkt_type pkt_type;
1910+
struct qed_iwarp_fpdu *fpdu;
17451911
int rc = -EINVAL;
1912+
u8 *mpa_data;
1913+
1914+
fpdu = qed_iwarp_get_curr_fpdu(p_hwfn, curr_pkt->cid & 0xffff);
1915+
if (!fpdu) { /* something corrupt with cid, post rx back */
1916+
DP_ERR(p_hwfn, "Invalid cid, drop and post back to rx cid=%x\n",
1917+
curr_pkt->cid);
1918+
goto err;
1919+
}
17461920

1921+
do {
1922+
mpa_data = ((u8 *)(buf->data) + curr_pkt->first_mpa_offset);
1923+
1924+
pkt_type = qed_iwarp_mpa_classify(p_hwfn, fpdu,
1925+
mpa_buf->tcp_payload_len,
1926+
mpa_data);
1927+
1928+
switch (pkt_type) {
1929+
case QED_IWARP_MPA_PKT_PARTIAL:
1930+
qed_iwarp_init_fpdu(buf, fpdu,
1931+
curr_pkt,
1932+
mpa_buf->tcp_payload_len,
1933+
mpa_buf->placement_offset);
1934+
1935+
mpa_buf->tcp_payload_len = 0;
1936+
break;
1937+
case QED_IWARP_MPA_PKT_PACKED:
1938+
qed_iwarp_init_fpdu(buf, fpdu,
1939+
curr_pkt,
1940+
mpa_buf->tcp_payload_len,
1941+
mpa_buf->placement_offset);
1942+
1943+
rc = qed_iwarp_send_fpdu(p_hwfn, fpdu, curr_pkt, buf,
1944+
mpa_buf->tcp_payload_len,
1945+
pkt_type);
1946+
if (rc) {
1947+
DP_VERBOSE(p_hwfn, QED_MSG_RDMA,
1948+
"Can't send FPDU:reset rc=%d\n", rc);
1949+
memset(fpdu, 0, sizeof(*fpdu));
1950+
break;
1951+
}
1952+
1953+
mpa_buf->tcp_payload_len -= fpdu->fpdu_length;
1954+
curr_pkt->first_mpa_offset += fpdu->fpdu_length;
1955+
break;
1956+
case QED_IWARP_MPA_PKT_UNALIGNED:
1957+
rc = qed_iwarp_send_fpdu(p_hwfn, fpdu, curr_pkt, buf,
1958+
mpa_buf->tcp_payload_len,
1959+
pkt_type);
1960+
if (rc) {
1961+
DP_VERBOSE(p_hwfn, QED_MSG_RDMA,
1962+
"Can't send FPDU:delay rc=%d\n", rc);
1963+
/* don't reset fpdu -> we need it for next
1964+
* classify
1965+
*/
1966+
break;
1967+
}
1968+
1969+
mpa_buf->tcp_payload_len -= fpdu->incomplete_bytes;
1970+
curr_pkt->first_mpa_offset += fpdu->incomplete_bytes;
1971+
/* The framed PDU was sent - no more incomplete bytes */
1972+
fpdu->incomplete_bytes = 0;
1973+
break;
1974+
}
1975+
} while (mpa_buf->tcp_payload_len && !rc);
1976+
1977+
return rc;
1978+
1979+
err:
17471980
qed_iwarp_ll2_post_rx(p_hwfn,
17481981
buf,
17491982
p_hwfn->p_rdma_info->iwarp.ll2_mpa_handle);
@@ -1989,11 +2222,27 @@ static void qed_iwarp_ll2_rel_tx_pkt(void *cxt, u8 connection_handle,
19892222
kfree(buffer);
19902223
}
19912224

2225+
/* The only slowpath for iwarp ll2 is unalign flush. When this completion
2226+
* is received, need to reset the FPDU.
2227+
*/
19922228
void
19932229
qed_iwarp_ll2_slowpath(void *cxt,
19942230
u8 connection_handle,
19952231
u32 opaque_data_0, u32 opaque_data_1)
19962232
{
2233+
struct unaligned_opaque_data unalign_data;
2234+
struct qed_hwfn *p_hwfn = cxt;
2235+
struct qed_iwarp_fpdu *fpdu;
2236+
2237+
qed_iwarp_mpa_get_data(p_hwfn, &unalign_data,
2238+
opaque_data_0, opaque_data_1);
2239+
2240+
DP_VERBOSE(p_hwfn, QED_MSG_RDMA, "(0x%x) Flush fpdu\n",
2241+
unalign_data.cid);
2242+
2243+
fpdu = qed_iwarp_get_curr_fpdu(p_hwfn, (u16)unalign_data.cid);
2244+
if (fpdu)
2245+
memset(fpdu, 0, sizeof(*fpdu));
19972246
}
19982247

19992248
static int qed_iwarp_ll2_stop(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
@@ -2194,6 +2443,14 @@ qed_iwarp_ll2_start(struct qed_hwfn *p_hwfn,
21942443
iwarp_info->ll2_mpa_handle);
21952444
if (rc)
21962445
goto err;
2446+
2447+
iwarp_info->partial_fpdus = kcalloc((u16)p_hwfn->p_rdma_info->num_qps,
2448+
sizeof(*iwarp_info->partial_fpdus),
2449+
GFP_KERNEL);
2450+
if (!iwarp_info->partial_fpdus)
2451+
goto err;
2452+
2453+
iwarp_info->max_num_partial_fpdus = (u16)p_hwfn->p_rdma_info->num_qps;
21972454
/* The mpa_bufs array serves for pending RX packets received on the
21982455
* mpa ll2 that don't have place on the tx ring and require later
21992456
* processing. We can't fail on allocation of such a struct therefore

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,17 @@ struct qed_iwarp_ll2_mpa_buf {
6868
u8 placement_offset;
6969
};
7070

71+
struct qed_iwarp_fpdu {
72+
struct qed_iwarp_ll2_buff *mpa_buf;
73+
void *mpa_frag_virt;
74+
dma_addr_t mpa_frag;
75+
dma_addr_t pkt_hdr;
76+
u16 mpa_frag_len;
77+
u16 fpdu_length;
78+
u16 incomplete_bytes;
79+
u8 pkt_hdr_size;
80+
};
81+
7182
struct qed_iwarp_info {
7283
struct list_head listen_list; /* qed_iwarp_listener */
7384
struct list_head ep_list; /* qed_iwarp_ep */
@@ -87,7 +98,9 @@ struct qed_iwarp_info {
8798
u8 peer2peer;
8899
enum mpa_negotiation_mode mpa_rev;
89100
enum mpa_rtr_type rtr_type;
101+
struct qed_iwarp_fpdu *partial_fpdus;
90102
struct qed_iwarp_ll2_mpa_buf *mpa_bufs;
103+
u16 max_num_partial_fpdus;
91104
};
92105

93106
enum qed_iwarp_ep_state {

0 commit comments

Comments
 (0)