ef10_rx.c revision 283514
1283514Sarybchik/*- 2283514Sarybchik * Copyright (c) 2012-2015 Solarflare Communications Inc. 3283514Sarybchik * All rights reserved. 4283514Sarybchik * 5283514Sarybchik * Redistribution and use in source and binary forms, with or without 6283514Sarybchik * modification, are permitted provided that the following conditions are met: 7283514Sarybchik * 8283514Sarybchik * 1. Redistributions of source code must retain the above copyright notice, 9283514Sarybchik * this list of conditions and the following disclaimer. 10283514Sarybchik * 2. Redistributions in binary form must reproduce the above copyright notice, 11283514Sarybchik * this list of conditions and the following disclaimer in the documentation 12283514Sarybchik * and/or other materials provided with the distribution. 13283514Sarybchik * 14283514Sarybchik * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15283514Sarybchik * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16283514Sarybchik * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17283514Sarybchik * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 18283514Sarybchik * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19283514Sarybchik * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20283514Sarybchik * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21283514Sarybchik * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22283514Sarybchik * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23283514Sarybchik * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 24283514Sarybchik * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25283514Sarybchik * 26283514Sarybchik * The views and conclusions contained in the software and documentation are 27283514Sarybchik * those of the authors and should not be interpreted as representing official 28283514Sarybchik * policies, either expressed or implied, of the FreeBSD Project. 29283514Sarybchik */ 30283514Sarybchik 31283514Sarybchik#include <sys/cdefs.h> 32283514Sarybchik__FBSDID("$FreeBSD: head/sys/dev/sfxge/common/hunt_rx.c 283514 2015-05-25 08:34:55Z arybchik $"); 33283514Sarybchik 34283514Sarybchik#include "efsys.h" 35283514Sarybchik#include "efx.h" 36283514Sarybchik#include "efx_impl.h" 37283514Sarybchik 38283514Sarybchik 39283514Sarybchik#if EFSYS_OPT_HUNTINGTON 40283514Sarybchik 41283514Sarybchik 42283514Sarybchikstatic __checkReturn int 43283514Sarybchikefx_mcdi_init_rxq( 44283514Sarybchik __in efx_nic_t *enp, 45283514Sarybchik __in uint32_t size, 46283514Sarybchik __in uint32_t target_evq, 47283514Sarybchik __in uint32_t label, 48283514Sarybchik __in uint32_t instance, 49283514Sarybchik __in efsys_mem_t *esmp) 50283514Sarybchik{ 51283514Sarybchik efx_mcdi_req_t req; 52283514Sarybchik uint8_t payload[ 53283514Sarybchik MAX(MC_CMD_INIT_RXQ_IN_LEN(EFX_RXQ_NBUFS(EFX_RXQ_MAXNDESCS)), 54283514Sarybchik MC_CMD_INIT_RXQ_OUT_LEN)]; 55283514Sarybchik int npages = EFX_RXQ_NBUFS(size); 56283514Sarybchik int i; 57283514Sarybchik efx_qword_t *dma_addr; 58283514Sarybchik uint64_t addr; 59283514Sarybchik int rc; 60283514Sarybchik 61283514Sarybchik EFSYS_ASSERT3U(size, <=, EFX_RXQ_MAXNDESCS); 62283514Sarybchik 63283514Sarybchik (void) memset(payload, 0, sizeof (payload)); 64283514Sarybchik req.emr_cmd = MC_CMD_INIT_RXQ; 65283514Sarybchik req.emr_in_buf = payload; 66283514Sarybchik req.emr_in_length = MC_CMD_INIT_RXQ_IN_LEN(npages); 67283514Sarybchik req.emr_out_buf = payload; 68283514Sarybchik req.emr_out_length = MC_CMD_INIT_RXQ_OUT_LEN; 69283514Sarybchik 70283514Sarybchik MCDI_IN_SET_DWORD(req, INIT_RXQ_IN_SIZE, size); 71283514Sarybchik MCDI_IN_SET_DWORD(req, INIT_RXQ_IN_TARGET_EVQ, target_evq); 72283514Sarybchik MCDI_IN_SET_DWORD(req, INIT_RXQ_IN_LABEL, label); 73283514Sarybchik MCDI_IN_SET_DWORD(req, INIT_RXQ_IN_INSTANCE, instance); 74283514Sarybchik MCDI_IN_POPULATE_DWORD_5(req, INIT_RXQ_IN_FLAGS, 75283514Sarybchik INIT_RXQ_IN_FLAG_BUFF_MODE, 0, 76283514Sarybchik INIT_RXQ_IN_FLAG_HDR_SPLIT, 0, 77283514Sarybchik INIT_RXQ_IN_FLAG_TIMESTAMP, 0, 78283514Sarybchik INIT_RXQ_IN_CRC_MODE, 0, 79283514Sarybchik INIT_RXQ_IN_FLAG_PREFIX, 1); 80283514Sarybchik MCDI_IN_SET_DWORD(req, INIT_RXQ_IN_OWNER_ID, 0); 81283514Sarybchik MCDI_IN_SET_DWORD(req, INIT_RXQ_IN_PORT_ID, EVB_PORT_ID_ASSIGNED); 82283514Sarybchik 83283514Sarybchik dma_addr = MCDI_IN2(req, efx_qword_t, INIT_RXQ_IN_DMA_ADDR); 84283514Sarybchik addr = EFSYS_MEM_ADDR(esmp); 85283514Sarybchik 86283514Sarybchik for (i = 0; i < npages; i++) { 87283514Sarybchik EFX_POPULATE_QWORD_2(*dma_addr, 88283514Sarybchik EFX_DWORD_1, (uint32_t)(addr >> 32), 89283514Sarybchik EFX_DWORD_0, (uint32_t)(addr & 0xffffffff)); 90283514Sarybchik 91283514Sarybchik dma_addr++; 92283514Sarybchik addr += EFX_BUF_SIZE; 93283514Sarybchik } 94283514Sarybchik 95283514Sarybchik efx_mcdi_execute(enp, &req); 96283514Sarybchik 97283514Sarybchik if (req.emr_rc != 0) { 98283514Sarybchik rc = req.emr_rc; 99283514Sarybchik goto fail1; 100283514Sarybchik } 101283514Sarybchik 102283514Sarybchik return (0); 103283514Sarybchik 104283514Sarybchikfail1: 105283514Sarybchik EFSYS_PROBE1(fail1, int, rc); 106283514Sarybchik 107283514Sarybchik return (rc); 108283514Sarybchik} 109283514Sarybchik 110283514Sarybchikstatic __checkReturn int 111283514Sarybchikefx_mcdi_fini_rxq( 112283514Sarybchik __in efx_nic_t *enp, 113283514Sarybchik __in uint32_t instance) 114283514Sarybchik{ 115283514Sarybchik efx_mcdi_req_t req; 116283514Sarybchik uint8_t payload[MAX(MC_CMD_FINI_RXQ_IN_LEN, 117283514Sarybchik MC_CMD_FINI_RXQ_OUT_LEN)]; 118283514Sarybchik int rc; 119283514Sarybchik 120283514Sarybchik (void) memset(payload, 0, sizeof (payload)); 121283514Sarybchik req.emr_cmd = MC_CMD_FINI_RXQ; 122283514Sarybchik req.emr_in_buf = payload; 123283514Sarybchik req.emr_in_length = MC_CMD_FINI_RXQ_IN_LEN; 124283514Sarybchik req.emr_out_buf = payload; 125283514Sarybchik req.emr_out_length = MC_CMD_FINI_RXQ_OUT_LEN; 126283514Sarybchik 127283514Sarybchik MCDI_IN_SET_DWORD(req, FINI_RXQ_IN_INSTANCE, instance); 128283514Sarybchik 129283514Sarybchik efx_mcdi_execute(enp, &req); 130283514Sarybchik 131283514Sarybchik if ((req.emr_rc != 0) && (req.emr_rc != MC_CMD_ERR_EALREADY)) { 132283514Sarybchik rc = req.emr_rc; 133283514Sarybchik goto fail1; 134283514Sarybchik } 135283514Sarybchik 136283514Sarybchik return (0); 137283514Sarybchik 138283514Sarybchikfail1: 139283514Sarybchik EFSYS_PROBE1(fail1, int, rc); 140283514Sarybchik 141283514Sarybchik return (rc); 142283514Sarybchik} 143283514Sarybchik 144283514Sarybchik#if EFSYS_OPT_RX_SCALE 145283514Sarybchikstatic __checkReturn int 146283514Sarybchikefx_mcdi_rss_context_alloc( 147283514Sarybchik __in efx_nic_t *enp, 148283514Sarybchik __out uint32_t *rss_contextp) 149283514Sarybchik{ 150283514Sarybchik efx_mcdi_req_t req; 151283514Sarybchik uint8_t payload[MAX(MC_CMD_RSS_CONTEXT_ALLOC_IN_LEN, 152283514Sarybchik MC_CMD_RSS_CONTEXT_ALLOC_OUT_LEN)]; 153283514Sarybchik uint32_t rss_context; 154283514Sarybchik int rc; 155283514Sarybchik 156283514Sarybchik (void) memset(payload, 0, sizeof (payload)); 157283514Sarybchik req.emr_cmd = MC_CMD_RSS_CONTEXT_ALLOC; 158283514Sarybchik req.emr_in_buf = payload; 159283514Sarybchik req.emr_in_length = MC_CMD_RSS_CONTEXT_ALLOC_IN_LEN; 160283514Sarybchik req.emr_out_buf = payload; 161283514Sarybchik req.emr_out_length = MC_CMD_RSS_CONTEXT_ALLOC_OUT_LEN; 162283514Sarybchik 163283514Sarybchik MCDI_IN_SET_DWORD(req, RSS_CONTEXT_ALLOC_IN_UPSTREAM_PORT_ID, 164283514Sarybchik EVB_PORT_ID_ASSIGNED); 165283514Sarybchik MCDI_IN_SET_DWORD(req, RSS_CONTEXT_ALLOC_IN_TYPE, 166283514Sarybchik MC_CMD_RSS_CONTEXT_ALLOC_IN_TYPE_EXCLUSIVE); 167283514Sarybchik /* NUM_QUEUES is only used to validate indirection table offsets */ 168283514Sarybchik MCDI_IN_SET_DWORD(req, RSS_CONTEXT_ALLOC_IN_NUM_QUEUES, 64); 169283514Sarybchik 170283514Sarybchik efx_mcdi_execute(enp, &req); 171283514Sarybchik 172283514Sarybchik if (req.emr_rc != 0) { 173283514Sarybchik rc = req.emr_rc; 174283514Sarybchik goto fail1; 175283514Sarybchik } 176283514Sarybchik 177283514Sarybchik if (req.emr_out_length_used < MC_CMD_RSS_CONTEXT_ALLOC_OUT_LEN) { 178283514Sarybchik rc = EMSGSIZE; 179283514Sarybchik goto fail2; 180283514Sarybchik } 181283514Sarybchik 182283514Sarybchik rss_context = MCDI_OUT_DWORD(req, RSS_CONTEXT_ALLOC_OUT_RSS_CONTEXT_ID); 183283514Sarybchik if (rss_context == HUNTINGTON_RSS_CONTEXT_INVALID) { 184283514Sarybchik rc = ENOENT; 185283514Sarybchik goto fail3; 186283514Sarybchik } 187283514Sarybchik 188283514Sarybchik *rss_contextp = rss_context; 189283514Sarybchik 190283514Sarybchik return (0); 191283514Sarybchik 192283514Sarybchikfail3: 193283514Sarybchik EFSYS_PROBE(fail3); 194283514Sarybchikfail2: 195283514Sarybchik EFSYS_PROBE(fail2); 196283514Sarybchikfail1: 197283514Sarybchik EFSYS_PROBE1(fail1, int, rc); 198283514Sarybchik 199283514Sarybchik return (rc); 200283514Sarybchik} 201283514Sarybchik#endif /* EFSYS_OPT_RX_SCALE */ 202283514Sarybchik 203283514Sarybchik#if EFSYS_OPT_RX_SCALE 204283514Sarybchikstatic int 205283514Sarybchikefx_mcdi_rss_context_free( 206283514Sarybchik __in efx_nic_t *enp, 207283514Sarybchik __in uint32_t rss_context) 208283514Sarybchik{ 209283514Sarybchik efx_mcdi_req_t req; 210283514Sarybchik uint8_t payload[MAX(MC_CMD_RSS_CONTEXT_FREE_IN_LEN, 211283514Sarybchik MC_CMD_RSS_CONTEXT_FREE_OUT_LEN)]; 212283514Sarybchik int rc; 213283514Sarybchik 214283514Sarybchik if (rss_context == HUNTINGTON_RSS_CONTEXT_INVALID) { 215283514Sarybchik rc = EINVAL; 216283514Sarybchik goto fail1; 217283514Sarybchik } 218283514Sarybchik 219283514Sarybchik (void) memset(payload, 0, sizeof (payload)); 220283514Sarybchik req.emr_cmd = MC_CMD_RSS_CONTEXT_FREE; 221283514Sarybchik req.emr_in_buf = payload; 222283514Sarybchik req.emr_in_length = MC_CMD_RSS_CONTEXT_FREE_IN_LEN; 223283514Sarybchik req.emr_out_buf = payload; 224283514Sarybchik req.emr_out_length = MC_CMD_RSS_CONTEXT_FREE_OUT_LEN; 225283514Sarybchik 226283514Sarybchik MCDI_IN_SET_DWORD(req, RSS_CONTEXT_FREE_IN_RSS_CONTEXT_ID, rss_context); 227283514Sarybchik 228283514Sarybchik efx_mcdi_execute(enp, &req); 229283514Sarybchik 230283514Sarybchik if (req.emr_rc != 0) { 231283514Sarybchik rc = req.emr_rc; 232283514Sarybchik goto fail2; 233283514Sarybchik } 234283514Sarybchik 235283514Sarybchik return (0); 236283514Sarybchik 237283514Sarybchikfail2: 238283514Sarybchik EFSYS_PROBE(fail2); 239283514Sarybchikfail1: 240283514Sarybchik EFSYS_PROBE1(fail1, int, rc); 241283514Sarybchik 242283514Sarybchik return (rc); 243283514Sarybchik} 244283514Sarybchik#endif /* EFSYS_OPT_RX_SCALE */ 245283514Sarybchik 246283514Sarybchik#if EFSYS_OPT_RX_SCALE 247283514Sarybchikstatic int 248283514Sarybchikefx_mcdi_rss_context_set_flags( 249283514Sarybchik __in efx_nic_t *enp, 250283514Sarybchik __in uint32_t rss_context, 251283514Sarybchik __in efx_rx_hash_type_t type) 252283514Sarybchik{ 253283514Sarybchik efx_mcdi_req_t req; 254283514Sarybchik uint8_t payload[MAX(MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_LEN, 255283514Sarybchik MC_CMD_RSS_CONTEXT_SET_FLAGS_OUT_LEN)]; 256283514Sarybchik int rc; 257283514Sarybchik 258283514Sarybchik if (rss_context == HUNTINGTON_RSS_CONTEXT_INVALID) { 259283514Sarybchik rc = EINVAL; 260283514Sarybchik goto fail1; 261283514Sarybchik } 262283514Sarybchik 263283514Sarybchik (void) memset(payload, 0, sizeof (payload)); 264283514Sarybchik req.emr_cmd = MC_CMD_RSS_CONTEXT_SET_FLAGS; 265283514Sarybchik req.emr_in_buf = payload; 266283514Sarybchik req.emr_in_length = MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_LEN; 267283514Sarybchik req.emr_out_buf = payload; 268283514Sarybchik req.emr_out_length = MC_CMD_RSS_CONTEXT_SET_FLAGS_OUT_LEN; 269283514Sarybchik 270283514Sarybchik MCDI_IN_SET_DWORD(req, RSS_CONTEXT_SET_FLAGS_IN_RSS_CONTEXT_ID, 271283514Sarybchik rss_context); 272283514Sarybchik 273283514Sarybchik MCDI_IN_POPULATE_DWORD_4(req, RSS_CONTEXT_SET_FLAGS_IN_FLAGS, 274283514Sarybchik RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_IPV4_EN, 275283514Sarybchik (type & (1U << EFX_RX_HASH_IPV4)) ? 1 : 0, 276283514Sarybchik RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_TCPV4_EN, 277283514Sarybchik (type & (1U << EFX_RX_HASH_TCPIPV4)) ? 1 : 0, 278283514Sarybchik RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_IPV6_EN, 279283514Sarybchik (type & (1U << EFX_RX_HASH_IPV6)) ? 1 : 0, 280283514Sarybchik RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_TCPV6_EN, 281283514Sarybchik (type & (1U << EFX_RX_HASH_TCPIPV6)) ? 1 : 0); 282283514Sarybchik 283283514Sarybchik efx_mcdi_execute(enp, &req); 284283514Sarybchik 285283514Sarybchik if (req.emr_rc != 0) { 286283514Sarybchik rc = req.emr_rc; 287283514Sarybchik goto fail2; 288283514Sarybchik } 289283514Sarybchik 290283514Sarybchik return (0); 291283514Sarybchik 292283514Sarybchikfail2: 293283514Sarybchik EFSYS_PROBE(fail2); 294283514Sarybchikfail1: 295283514Sarybchik EFSYS_PROBE1(fail1, int, rc); 296283514Sarybchik 297283514Sarybchik return (rc); 298283514Sarybchik} 299283514Sarybchik#endif /* EFSYS_OPT_RX_SCALE */ 300283514Sarybchik 301283514Sarybchik#if EFSYS_OPT_RX_SCALE 302283514Sarybchikstatic int 303283514Sarybchikefx_mcdi_rss_context_set_key( 304283514Sarybchik __in efx_nic_t *enp, 305283514Sarybchik __in uint32_t rss_context, 306283514Sarybchik __in_ecount(n) uint8_t *key, 307283514Sarybchik __in size_t n) 308283514Sarybchik{ 309283514Sarybchik efx_mcdi_req_t req; 310283514Sarybchik uint8_t payload[MAX(MC_CMD_RSS_CONTEXT_SET_KEY_IN_LEN, 311283514Sarybchik MC_CMD_RSS_CONTEXT_SET_KEY_OUT_LEN)]; 312283514Sarybchik int rc; 313283514Sarybchik 314283514Sarybchik if (rss_context == HUNTINGTON_RSS_CONTEXT_INVALID) { 315283514Sarybchik rc = EINVAL; 316283514Sarybchik goto fail1; 317283514Sarybchik } 318283514Sarybchik 319283514Sarybchik (void) memset(payload, 0, sizeof (payload)); 320283514Sarybchik req.emr_cmd = MC_CMD_RSS_CONTEXT_SET_KEY; 321283514Sarybchik req.emr_in_buf = payload; 322283514Sarybchik req.emr_in_length = MC_CMD_RSS_CONTEXT_SET_KEY_IN_LEN; 323283514Sarybchik req.emr_out_buf = payload; 324283514Sarybchik req.emr_out_length = MC_CMD_RSS_CONTEXT_SET_KEY_OUT_LEN; 325283514Sarybchik 326283514Sarybchik MCDI_IN_SET_DWORD(req, RSS_CONTEXT_SET_KEY_IN_RSS_CONTEXT_ID, 327283514Sarybchik rss_context); 328283514Sarybchik 329283514Sarybchik EFSYS_ASSERT3U(n, ==, MC_CMD_RSS_CONTEXT_SET_KEY_IN_TOEPLITZ_KEY_LEN); 330283514Sarybchik if (n != MC_CMD_RSS_CONTEXT_SET_KEY_IN_TOEPLITZ_KEY_LEN) { 331283514Sarybchik rc = EINVAL; 332283514Sarybchik goto fail2; 333283514Sarybchik } 334283514Sarybchik 335283514Sarybchik memcpy(MCDI_IN2(req, uint8_t, RSS_CONTEXT_SET_KEY_IN_TOEPLITZ_KEY), 336283514Sarybchik key, n); 337283514Sarybchik 338283514Sarybchik efx_mcdi_execute(enp, &req); 339283514Sarybchik 340283514Sarybchik if (req.emr_rc != 0) { 341283514Sarybchik rc = req.emr_rc; 342283514Sarybchik goto fail3; 343283514Sarybchik } 344283514Sarybchik 345283514Sarybchik return (0); 346283514Sarybchik 347283514Sarybchikfail3: 348283514Sarybchik EFSYS_PROBE(fail3); 349283514Sarybchikfail2: 350283514Sarybchik EFSYS_PROBE(fail2); 351283514Sarybchikfail1: 352283514Sarybchik EFSYS_PROBE1(fail1, int, rc); 353283514Sarybchik 354283514Sarybchik return (rc); 355283514Sarybchik} 356283514Sarybchik#endif /* EFSYS_OPT_RX_SCALE */ 357283514Sarybchik 358283514Sarybchik#if EFSYS_OPT_RX_SCALE 359283514Sarybchikstatic int 360283514Sarybchikefx_mcdi_rss_context_set_table( 361283514Sarybchik __in efx_nic_t *enp, 362283514Sarybchik __in uint32_t rss_context, 363283514Sarybchik __in_ecount(n) unsigned int *table, 364283514Sarybchik __in size_t n) 365283514Sarybchik{ 366283514Sarybchik efx_mcdi_req_t req; 367283514Sarybchik uint8_t payload[MAX(MC_CMD_RSS_CONTEXT_SET_TABLE_IN_LEN, 368283514Sarybchik MC_CMD_RSS_CONTEXT_SET_TABLE_OUT_LEN)]; 369283514Sarybchik uint8_t *req_table; 370283514Sarybchik int i, rc; 371283514Sarybchik 372283514Sarybchik if (rss_context == HUNTINGTON_RSS_CONTEXT_INVALID) { 373283514Sarybchik rc = EINVAL; 374283514Sarybchik goto fail1; 375283514Sarybchik } 376283514Sarybchik 377283514Sarybchik (void) memset(payload, 0, sizeof (payload)); 378283514Sarybchik req.emr_cmd = MC_CMD_RSS_CONTEXT_SET_TABLE; 379283514Sarybchik req.emr_in_buf = payload; 380283514Sarybchik req.emr_in_length = MC_CMD_RSS_CONTEXT_SET_TABLE_IN_LEN; 381283514Sarybchik req.emr_out_buf = payload; 382283514Sarybchik req.emr_out_length = MC_CMD_RSS_CONTEXT_SET_TABLE_OUT_LEN; 383283514Sarybchik 384283514Sarybchik MCDI_IN_SET_DWORD(req, RSS_CONTEXT_SET_TABLE_IN_RSS_CONTEXT_ID, 385283514Sarybchik rss_context); 386283514Sarybchik 387283514Sarybchik req_table = 388283514Sarybchik MCDI_IN2(req, uint8_t, RSS_CONTEXT_SET_TABLE_IN_INDIRECTION_TABLE); 389283514Sarybchik 390283514Sarybchik for (i = 0; 391283514Sarybchik i < MC_CMD_RSS_CONTEXT_SET_TABLE_IN_INDIRECTION_TABLE_LEN; 392283514Sarybchik i++) { 393283514Sarybchik req_table[i] = (n > 0) ? (uint8_t)table[i % n] : 0; 394283514Sarybchik } 395283514Sarybchik 396283514Sarybchik efx_mcdi_execute(enp, &req); 397283514Sarybchik 398283514Sarybchik if (req.emr_rc != 0) { 399283514Sarybchik rc = req.emr_rc; 400283514Sarybchik goto fail2; 401283514Sarybchik } 402283514Sarybchik 403283514Sarybchik return (0); 404283514Sarybchik 405283514Sarybchikfail2: 406283514Sarybchik EFSYS_PROBE(fail2); 407283514Sarybchikfail1: 408283514Sarybchik EFSYS_PROBE1(fail1, int, rc); 409283514Sarybchik 410283514Sarybchik return (rc); 411283514Sarybchik} 412283514Sarybchik#endif /* EFSYS_OPT_RX_SCALE */ 413283514Sarybchik 414283514Sarybchik 415283514Sarybchik __checkReturn int 416283514Sarybchikhunt_rx_init( 417283514Sarybchik __in efx_nic_t *enp) 418283514Sarybchik{ 419283514Sarybchik#if EFSYS_OPT_RX_SCALE 420283514Sarybchik 421283514Sarybchik if (efx_mcdi_rss_context_alloc(enp, &enp->en_rss_context) == 0) { 422283514Sarybchik /* 423283514Sarybchik * Allocated an exclusive RSS context, which allows both the 424283514Sarybchik * indirection table and key to be modified. 425283514Sarybchik */ 426283514Sarybchik enp->en_rss_support = EFX_RX_SCALE_EXCLUSIVE; 427283514Sarybchik enp->en_hash_support = EFX_RX_HASH_AVAILABLE; 428283514Sarybchik } else { 429283514Sarybchik /* 430283514Sarybchik * Failed to allocate an exclusive RSS context. Continue 431283514Sarybchik * operation without support for RSS. The pseudo-header in 432283514Sarybchik * received packets will not contain a Toeplitz hash value. 433283514Sarybchik */ 434283514Sarybchik enp->en_rss_support = EFX_RX_SCALE_UNAVAILABLE; 435283514Sarybchik enp->en_hash_support = EFX_RX_HASH_UNAVAILABLE; 436283514Sarybchik } 437283514Sarybchik 438283514Sarybchik#endif /* EFSYS_OPT_RX_SCALE */ 439283514Sarybchik 440283514Sarybchik return (0); 441283514Sarybchik} 442283514Sarybchik 443283514Sarybchik#if EFSYS_OPT_RX_HDR_SPLIT 444283514Sarybchik __checkReturn int 445283514Sarybchikhunt_rx_hdr_split_enable( 446283514Sarybchik __in efx_nic_t *enp, 447283514Sarybchik __in unsigned int hdr_buf_size, 448283514Sarybchik __in unsigned int pld_buf_size) 449283514Sarybchik{ 450283514Sarybchik int rc; 451283514Sarybchik 452283514Sarybchik /* FIXME */ 453283514Sarybchik _NOTE(ARGUNUSED(enp, hdr_buf_size, pld_buf_size)) 454283514Sarybchik if (B_FALSE) { 455283514Sarybchik rc = ENOTSUP; 456283514Sarybchik goto fail1; 457283514Sarybchik } 458283514Sarybchik /* FIXME */ 459283514Sarybchik 460283514Sarybchik return (0); 461283514Sarybchik 462283514Sarybchikfail1: 463283514Sarybchik EFSYS_PROBE1(fail1, int, rc); 464283514Sarybchik 465283514Sarybchik return (rc); 466283514Sarybchik} 467283514Sarybchik#endif /* EFSYS_OPT_RX_HDR_SPLIT */ 468283514Sarybchik 469283514Sarybchik#if EFSYS_OPT_RX_SCATTER 470283514Sarybchik __checkReturn int 471283514Sarybchikhunt_rx_scatter_enable( 472283514Sarybchik __in efx_nic_t *enp, 473283514Sarybchik __in unsigned int buf_size) 474283514Sarybchik{ 475283514Sarybchik _NOTE(ARGUNUSED(enp, buf_size)) 476283514Sarybchik return (0); 477283514Sarybchik} 478283514Sarybchik#endif /* EFSYS_OPT_RX_SCATTER */ 479283514Sarybchik 480283514Sarybchik#if EFSYS_OPT_RX_SCALE 481283514Sarybchik __checkReturn int 482283514Sarybchikhunt_rx_scale_mode_set( 483283514Sarybchik __in efx_nic_t *enp, 484283514Sarybchik __in efx_rx_hash_alg_t alg, 485283514Sarybchik __in efx_rx_hash_type_t type, 486283514Sarybchik __in boolean_t insert) 487283514Sarybchik{ 488283514Sarybchik int rc; 489283514Sarybchik 490283514Sarybchik EFSYS_ASSERT3U(alg, ==, EFX_RX_HASHALG_TOEPLITZ); 491283514Sarybchik EFSYS_ASSERT3U(insert, ==, B_TRUE); 492283514Sarybchik 493283514Sarybchik if ((alg != EFX_RX_HASHALG_TOEPLITZ) || (insert == B_FALSE)) { 494283514Sarybchik rc = EINVAL; 495283514Sarybchik goto fail1; 496283514Sarybchik } 497283514Sarybchik 498283514Sarybchik if (enp->en_rss_support == EFX_RX_SCALE_UNAVAILABLE) { 499283514Sarybchik rc = ENOTSUP; 500283514Sarybchik goto fail2; 501283514Sarybchik } 502283514Sarybchik 503283514Sarybchik if ((rc = efx_mcdi_rss_context_set_flags(enp, 504283514Sarybchik enp->en_rss_context, type)) != 0) 505283514Sarybchik goto fail3; 506283514Sarybchik 507283514Sarybchik return (0); 508283514Sarybchik 509283514Sarybchikfail3: 510283514Sarybchik EFSYS_PROBE(fail3); 511283514Sarybchikfail2: 512283514Sarybchik EFSYS_PROBE(fail2); 513283514Sarybchikfail1: 514283514Sarybchik EFSYS_PROBE1(fail1, int, rc); 515283514Sarybchik 516283514Sarybchik return (rc); 517283514Sarybchik} 518283514Sarybchik#endif /* EFSYS_OPT_RX_SCALE */ 519283514Sarybchik 520283514Sarybchik#if EFSYS_OPT_RX_SCALE 521283514Sarybchik __checkReturn int 522283514Sarybchikhunt_rx_scale_key_set( 523283514Sarybchik __in efx_nic_t *enp, 524283514Sarybchik __in_ecount(n) uint8_t *key, 525283514Sarybchik __in size_t n) 526283514Sarybchik{ 527283514Sarybchik int rc; 528283514Sarybchik 529283514Sarybchik if (enp->en_rss_support == EFX_RX_SCALE_UNAVAILABLE) { 530283514Sarybchik rc = ENOTSUP; 531283514Sarybchik goto fail1; 532283514Sarybchik } 533283514Sarybchik 534283514Sarybchik if ((rc = efx_mcdi_rss_context_set_key(enp, 535283514Sarybchik enp->en_rss_context, key, n)) != 0) 536283514Sarybchik goto fail2; 537283514Sarybchik 538283514Sarybchik return (0); 539283514Sarybchik 540283514Sarybchikfail2: 541283514Sarybchik EFSYS_PROBE(fail2); 542283514Sarybchikfail1: 543283514Sarybchik EFSYS_PROBE1(fail1, int, rc); 544283514Sarybchik 545283514Sarybchik return (rc); 546283514Sarybchik} 547283514Sarybchik#endif /* EFSYS_OPT_RX_SCALE */ 548283514Sarybchik 549283514Sarybchik#if EFSYS_OPT_RX_SCALE 550283514Sarybchik __checkReturn int 551283514Sarybchikhunt_rx_scale_tbl_set( 552283514Sarybchik __in efx_nic_t *enp, 553283514Sarybchik __in_ecount(n) unsigned int *table, 554283514Sarybchik __in size_t n) 555283514Sarybchik{ 556283514Sarybchik int rc; 557283514Sarybchik 558283514Sarybchik if (enp->en_rss_support == EFX_RX_SCALE_UNAVAILABLE) { 559283514Sarybchik rc = ENOTSUP; 560283514Sarybchik goto fail1; 561283514Sarybchik } 562283514Sarybchik 563283514Sarybchik if ((rc = efx_mcdi_rss_context_set_table(enp, 564283514Sarybchik enp->en_rss_context, table, n)) != 0) 565283514Sarybchik goto fail2; 566283514Sarybchik 567283514Sarybchik return (0); 568283514Sarybchik 569283514Sarybchikfail2: 570283514Sarybchik EFSYS_PROBE(fail2); 571283514Sarybchikfail1: 572283514Sarybchik EFSYS_PROBE1(fail1, int, rc); 573283514Sarybchik 574283514Sarybchik return (rc); 575283514Sarybchik} 576283514Sarybchik#endif /* EFSYS_OPT_RX_SCALE */ 577283514Sarybchik 578283514Sarybchik void 579283514Sarybchikhunt_rx_qpost( 580283514Sarybchik __in efx_rxq_t *erp, 581283514Sarybchik __in_ecount(n) efsys_dma_addr_t *addrp, 582283514Sarybchik __in size_t size, 583283514Sarybchik __in unsigned int n, 584283514Sarybchik __in unsigned int completed, 585283514Sarybchik __in unsigned int added) 586283514Sarybchik{ 587283514Sarybchik efx_qword_t qword; 588283514Sarybchik unsigned int i; 589283514Sarybchik unsigned int offset; 590283514Sarybchik unsigned int id; 591283514Sarybchik 592283514Sarybchik /* The client driver must not overfill the queue */ 593283514Sarybchik EFSYS_ASSERT3U(added - completed + n, <=, 594283514Sarybchik EFX_RXQ_LIMIT(erp->er_mask + 1)); 595283514Sarybchik 596283514Sarybchik id = added & (erp->er_mask); 597283514Sarybchik for (i = 0; i < n; i++) { 598283514Sarybchik EFSYS_PROBE4(rx_post, unsigned int, erp->er_index, 599283514Sarybchik unsigned int, id, efsys_dma_addr_t, addrp[i], 600283514Sarybchik size_t, size); 601283514Sarybchik 602283514Sarybchik EFX_POPULATE_QWORD_3(qword, 603283514Sarybchik ESF_DZ_RX_KER_BYTE_CNT, (uint32_t)(size), 604283514Sarybchik ESF_DZ_RX_KER_BUF_ADDR_DW0, 605283514Sarybchik (uint32_t)(addrp[i] & 0xffffffff), 606283514Sarybchik ESF_DZ_RX_KER_BUF_ADDR_DW1, 607283514Sarybchik (uint32_t)(addrp[i] >> 32)); 608283514Sarybchik 609283514Sarybchik offset = id * sizeof (efx_qword_t); 610283514Sarybchik EFSYS_MEM_WRITEQ(erp->er_esmp, offset, &qword); 611283514Sarybchik 612283514Sarybchik id = (id + 1) & (erp->er_mask); 613283514Sarybchik } 614283514Sarybchik} 615283514Sarybchik 616283514Sarybchik void 617283514Sarybchikhunt_rx_qpush( 618283514Sarybchik __in efx_rxq_t *erp, 619283514Sarybchik __in unsigned int added, 620283514Sarybchik __inout unsigned int *pushedp) 621283514Sarybchik{ 622283514Sarybchik efx_nic_t *enp = erp->er_enp; 623283514Sarybchik unsigned int pushed = *pushedp; 624283514Sarybchik uint32_t wptr; 625283514Sarybchik efx_dword_t dword; 626283514Sarybchik 627283514Sarybchik /* Hardware has alignment restriction for WPTR */ 628283514Sarybchik wptr = P2ALIGN(added, HUNTINGTON_RX_WPTR_ALIGN); 629283514Sarybchik if (pushed == wptr) 630283514Sarybchik return; 631283514Sarybchik 632283514Sarybchik *pushedp = wptr; 633283514Sarybchik 634283514Sarybchik /* Push the populated descriptors out */ 635283514Sarybchik wptr &= erp->er_mask; 636283514Sarybchik 637283514Sarybchik EFX_POPULATE_DWORD_1(dword, ERF_DZ_RX_DESC_WPTR, wptr); 638283514Sarybchik 639283514Sarybchik /* Guarantee ordering of memory (descriptors) and PIO (doorbell) */ 640283514Sarybchik EFX_DMA_SYNC_QUEUE_FOR_DEVICE(erp->er_esmp, erp->er_mask + 1, 641283514Sarybchik wptr, pushed & erp->er_mask); 642283514Sarybchik EFSYS_PIO_WRITE_BARRIER(); 643283514Sarybchik EFX_BAR_TBL_WRITED(enp, ER_DZ_RX_DESC_UPD_REG, 644283514Sarybchik erp->er_index, &dword, B_FALSE); 645283514Sarybchik} 646283514Sarybchik 647283514Sarybchik __checkReturn int 648283514Sarybchikhunt_rx_qflush( 649283514Sarybchik __in efx_rxq_t *erp) 650283514Sarybchik{ 651283514Sarybchik efx_nic_t *enp = erp->er_enp; 652283514Sarybchik int rc; 653283514Sarybchik 654283514Sarybchik if ((rc = efx_mcdi_fini_rxq(enp, erp->er_index)) != 0) 655283514Sarybchik goto fail1; 656283514Sarybchik 657283514Sarybchik return (0); 658283514Sarybchik 659283514Sarybchikfail1: 660283514Sarybchik EFSYS_PROBE1(fail1, int, rc); 661283514Sarybchik 662283514Sarybchik return (rc); 663283514Sarybchik} 664283514Sarybchik 665283514Sarybchik void 666283514Sarybchikhunt_rx_qenable( 667283514Sarybchik __in efx_rxq_t *erp) 668283514Sarybchik{ 669283514Sarybchik /* FIXME */ 670283514Sarybchik _NOTE(ARGUNUSED(erp)) 671283514Sarybchik /* FIXME */ 672283514Sarybchik} 673283514Sarybchik 674283514Sarybchik __checkReturn int 675283514Sarybchikhunt_rx_qcreate( 676283514Sarybchik __in efx_nic_t *enp, 677283514Sarybchik __in unsigned int index, 678283514Sarybchik __in unsigned int label, 679283514Sarybchik __in efx_rxq_type_t type, 680283514Sarybchik __in efsys_mem_t *esmp, 681283514Sarybchik __in size_t n, 682283514Sarybchik __in uint32_t id, 683283514Sarybchik __in efx_evq_t *eep, 684283514Sarybchik __in efx_rxq_t *erp) 685283514Sarybchik{ 686283514Sarybchik efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 687283514Sarybchik int rc; 688283514Sarybchik 689283514Sarybchik _NOTE(ARGUNUSED(erp)) 690283514Sarybchik 691283514Sarybchik EFX_STATIC_ASSERT(EFX_EV_RX_NLABELS == (1 << ESF_DZ_RX_QLABEL_WIDTH)); 692283514Sarybchik EFSYS_ASSERT3U(label, <, EFX_EV_RX_NLABELS); 693283514Sarybchik EFSYS_ASSERT3U(enp->en_rx_qcount + 1, <, encp->enc_rxq_limit); 694283514Sarybchik 695283514Sarybchik EFX_STATIC_ASSERT(ISP2(EFX_RXQ_MAXNDESCS)); 696283514Sarybchik EFX_STATIC_ASSERT(ISP2(EFX_RXQ_MINNDESCS)); 697283514Sarybchik 698283514Sarybchik if (!ISP2(n) || (n < EFX_RXQ_MINNDESCS) || (n > EFX_RXQ_MAXNDESCS)) { 699283514Sarybchik rc = EINVAL; 700283514Sarybchik goto fail1; 701283514Sarybchik } 702283514Sarybchik if (index >= encp->enc_rxq_limit) { 703283514Sarybchik rc = EINVAL; 704283514Sarybchik goto fail2; 705283514Sarybchik } 706283514Sarybchik 707283514Sarybchik /* 708283514Sarybchik * FIXME: Siena code handles different queue types (default, header 709283514Sarybchik * split, scatter); we'll need to do something more here later, but 710283514Sarybchik * all that stuff is TBD for now. 711283514Sarybchik */ 712283514Sarybchik 713283514Sarybchik if ((rc = efx_mcdi_init_rxq(enp, n, eep->ee_index, label, index, 714283514Sarybchik esmp)) != 0) 715283514Sarybchik goto fail3; 716283514Sarybchik 717283514Sarybchik erp->er_eep = eep; 718283514Sarybchik erp->er_label = label; 719283514Sarybchik 720283514Sarybchik hunt_ev_rxlabel_init(eep, erp, label); 721283514Sarybchik 722283514Sarybchik return (0); 723283514Sarybchik 724283514Sarybchikfail3: 725283514Sarybchik EFSYS_PROBE(fail3); 726283514Sarybchikfail2: 727283514Sarybchik EFSYS_PROBE(fail2); 728283514Sarybchikfail1: 729283514Sarybchik EFSYS_PROBE1(fail1, int, rc); 730283514Sarybchik 731283514Sarybchik return (rc); 732283514Sarybchik} 733283514Sarybchik 734283514Sarybchik void 735283514Sarybchikhunt_rx_qdestroy( 736283514Sarybchik __in efx_rxq_t *erp) 737283514Sarybchik{ 738283514Sarybchik efx_nic_t *enp = erp->er_enp; 739283514Sarybchik efx_evq_t *eep = erp->er_eep; 740283514Sarybchik unsigned int label = erp->er_label; 741283514Sarybchik 742283514Sarybchik hunt_ev_rxlabel_fini(eep, label); 743283514Sarybchik 744283514Sarybchik EFSYS_ASSERT(enp->en_rx_qcount != 0); 745283514Sarybchik --enp->en_rx_qcount; 746283514Sarybchik 747283514Sarybchik EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_rxq_t), erp); 748283514Sarybchik} 749283514Sarybchik 750283514Sarybchik void 751283514Sarybchikhunt_rx_fini( 752283514Sarybchik __in efx_nic_t *enp) 753283514Sarybchik{ 754283514Sarybchik#if EFSYS_OPT_RX_SCALE 755283514Sarybchik if (enp->en_rss_support != EFX_RX_SCALE_UNAVAILABLE) { 756283514Sarybchik (void) efx_mcdi_rss_context_free(enp, enp->en_rss_context); 757283514Sarybchik } 758283514Sarybchik enp->en_rss_context = 0; 759283514Sarybchik enp->en_rss_support = EFX_RX_SCALE_UNAVAILABLE; 760283514Sarybchik#else 761283514Sarybchik _NOTE(ARGUNUSED(enp)) 762283514Sarybchik#endif /* EFSYS_OPT_RX_SCALE */ 763283514Sarybchik} 764283514Sarybchik 765283514Sarybchik#endif /* EFSYS_OPT_HUNTINGTON */ 766