@@ -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
14241425int 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+
17211884static void
17221885qed_iwarp_mpa_get_data (struct qed_hwfn * p_hwfn ,
17231886 struct unaligned_opaque_data * curr_pkt ,
@@ -1741,9 +1904,79 @@ static int
17411904qed_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+ */
19922228void
19932229qed_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
19992248static 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
0 commit comments