ef10_rx.c revision 293752
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 293752 2016-01-12 13:32:04Z arybchik $"); 33283514Sarybchik 34283514Sarybchik#include "efsys.h" 35283514Sarybchik#include "efx.h" 36283514Sarybchik#include "efx_impl.h" 37283514Sarybchik 38283514Sarybchik 39283514Sarybchik#if EFSYS_OPT_HUNTINGTON 40283514Sarybchik 41283514Sarybchik 42291436Sarybchikstatic __checkReturn efx_rc_t 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, 49291747Sarybchik __in efsys_mem_t *esmp, 50291747Sarybchik __in boolean_t disable_scatter) 51283514Sarybchik{ 52283514Sarybchik efx_mcdi_req_t req; 53283514Sarybchik uint8_t payload[ 54283514Sarybchik MAX(MC_CMD_INIT_RXQ_IN_LEN(EFX_RXQ_NBUFS(EFX_RXQ_MAXNDESCS)), 55283514Sarybchik MC_CMD_INIT_RXQ_OUT_LEN)]; 56283514Sarybchik int npages = EFX_RXQ_NBUFS(size); 57283514Sarybchik int i; 58283514Sarybchik efx_qword_t *dma_addr; 59283514Sarybchik uint64_t addr; 60291436Sarybchik efx_rc_t rc; 61283514Sarybchik 62283514Sarybchik EFSYS_ASSERT3U(size, <=, EFX_RXQ_MAXNDESCS); 63283514Sarybchik 64283514Sarybchik (void) memset(payload, 0, sizeof (payload)); 65283514Sarybchik req.emr_cmd = MC_CMD_INIT_RXQ; 66283514Sarybchik req.emr_in_buf = payload; 67283514Sarybchik req.emr_in_length = MC_CMD_INIT_RXQ_IN_LEN(npages); 68283514Sarybchik req.emr_out_buf = payload; 69283514Sarybchik req.emr_out_length = MC_CMD_INIT_RXQ_OUT_LEN; 70283514Sarybchik 71283514Sarybchik MCDI_IN_SET_DWORD(req, INIT_RXQ_IN_SIZE, size); 72283514Sarybchik MCDI_IN_SET_DWORD(req, INIT_RXQ_IN_TARGET_EVQ, target_evq); 73283514Sarybchik MCDI_IN_SET_DWORD(req, INIT_RXQ_IN_LABEL, label); 74283514Sarybchik MCDI_IN_SET_DWORD(req, INIT_RXQ_IN_INSTANCE, instance); 75291747Sarybchik MCDI_IN_POPULATE_DWORD_6(req, INIT_RXQ_IN_FLAGS, 76291747Sarybchik INIT_RXQ_IN_FLAG_BUFF_MODE, 0, 77291747Sarybchik INIT_RXQ_IN_FLAG_HDR_SPLIT, 0, 78291747Sarybchik INIT_RXQ_IN_FLAG_TIMESTAMP, 0, 79291747Sarybchik INIT_RXQ_IN_CRC_MODE, 0, 80291747Sarybchik INIT_RXQ_IN_FLAG_PREFIX, 1, 81291747Sarybchik INIT_RXQ_IN_FLAG_DISABLE_SCATTER, disable_scatter); 82283514Sarybchik MCDI_IN_SET_DWORD(req, INIT_RXQ_IN_OWNER_ID, 0); 83283514Sarybchik MCDI_IN_SET_DWORD(req, INIT_RXQ_IN_PORT_ID, EVB_PORT_ID_ASSIGNED); 84283514Sarybchik 85283514Sarybchik dma_addr = MCDI_IN2(req, efx_qword_t, INIT_RXQ_IN_DMA_ADDR); 86283514Sarybchik addr = EFSYS_MEM_ADDR(esmp); 87283514Sarybchik 88283514Sarybchik for (i = 0; i < npages; i++) { 89283514Sarybchik EFX_POPULATE_QWORD_2(*dma_addr, 90283514Sarybchik EFX_DWORD_1, (uint32_t)(addr >> 32), 91283514Sarybchik EFX_DWORD_0, (uint32_t)(addr & 0xffffffff)); 92283514Sarybchik 93283514Sarybchik dma_addr++; 94283514Sarybchik addr += EFX_BUF_SIZE; 95283514Sarybchik } 96283514Sarybchik 97283514Sarybchik efx_mcdi_execute(enp, &req); 98283514Sarybchik 99283514Sarybchik if (req.emr_rc != 0) { 100283514Sarybchik rc = req.emr_rc; 101283514Sarybchik goto fail1; 102283514Sarybchik } 103283514Sarybchik 104283514Sarybchik return (0); 105283514Sarybchik 106283514Sarybchikfail1: 107291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 108283514Sarybchik 109283514Sarybchik return (rc); 110283514Sarybchik} 111283514Sarybchik 112291436Sarybchikstatic __checkReturn efx_rc_t 113283514Sarybchikefx_mcdi_fini_rxq( 114283514Sarybchik __in efx_nic_t *enp, 115283514Sarybchik __in uint32_t instance) 116283514Sarybchik{ 117283514Sarybchik efx_mcdi_req_t req; 118283514Sarybchik uint8_t payload[MAX(MC_CMD_FINI_RXQ_IN_LEN, 119283514Sarybchik MC_CMD_FINI_RXQ_OUT_LEN)]; 120291436Sarybchik efx_rc_t rc; 121283514Sarybchik 122283514Sarybchik (void) memset(payload, 0, sizeof (payload)); 123283514Sarybchik req.emr_cmd = MC_CMD_FINI_RXQ; 124283514Sarybchik req.emr_in_buf = payload; 125283514Sarybchik req.emr_in_length = MC_CMD_FINI_RXQ_IN_LEN; 126283514Sarybchik req.emr_out_buf = payload; 127283514Sarybchik req.emr_out_length = MC_CMD_FINI_RXQ_OUT_LEN; 128283514Sarybchik 129283514Sarybchik MCDI_IN_SET_DWORD(req, FINI_RXQ_IN_INSTANCE, instance); 130283514Sarybchik 131283514Sarybchik efx_mcdi_execute(enp, &req); 132283514Sarybchik 133283514Sarybchik if ((req.emr_rc != 0) && (req.emr_rc != MC_CMD_ERR_EALREADY)) { 134283514Sarybchik rc = req.emr_rc; 135283514Sarybchik goto fail1; 136283514Sarybchik } 137283514Sarybchik 138283514Sarybchik return (0); 139283514Sarybchik 140283514Sarybchikfail1: 141291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 142283514Sarybchik 143283514Sarybchik return (rc); 144283514Sarybchik} 145283514Sarybchik 146283514Sarybchik#if EFSYS_OPT_RX_SCALE 147291436Sarybchikstatic __checkReturn efx_rc_t 148283514Sarybchikefx_mcdi_rss_context_alloc( 149283514Sarybchik __in efx_nic_t *enp, 150283514Sarybchik __out uint32_t *rss_contextp) 151283514Sarybchik{ 152283514Sarybchik efx_mcdi_req_t req; 153283514Sarybchik uint8_t payload[MAX(MC_CMD_RSS_CONTEXT_ALLOC_IN_LEN, 154283514Sarybchik MC_CMD_RSS_CONTEXT_ALLOC_OUT_LEN)]; 155283514Sarybchik uint32_t rss_context; 156291436Sarybchik efx_rc_t rc; 157283514Sarybchik 158283514Sarybchik (void) memset(payload, 0, sizeof (payload)); 159283514Sarybchik req.emr_cmd = MC_CMD_RSS_CONTEXT_ALLOC; 160283514Sarybchik req.emr_in_buf = payload; 161283514Sarybchik req.emr_in_length = MC_CMD_RSS_CONTEXT_ALLOC_IN_LEN; 162283514Sarybchik req.emr_out_buf = payload; 163283514Sarybchik req.emr_out_length = MC_CMD_RSS_CONTEXT_ALLOC_OUT_LEN; 164283514Sarybchik 165283514Sarybchik MCDI_IN_SET_DWORD(req, RSS_CONTEXT_ALLOC_IN_UPSTREAM_PORT_ID, 166283514Sarybchik EVB_PORT_ID_ASSIGNED); 167283514Sarybchik MCDI_IN_SET_DWORD(req, RSS_CONTEXT_ALLOC_IN_TYPE, 168283514Sarybchik MC_CMD_RSS_CONTEXT_ALLOC_IN_TYPE_EXCLUSIVE); 169283514Sarybchik /* NUM_QUEUES is only used to validate indirection table offsets */ 170283514Sarybchik MCDI_IN_SET_DWORD(req, RSS_CONTEXT_ALLOC_IN_NUM_QUEUES, 64); 171283514Sarybchik 172283514Sarybchik efx_mcdi_execute(enp, &req); 173283514Sarybchik 174283514Sarybchik if (req.emr_rc != 0) { 175283514Sarybchik rc = req.emr_rc; 176283514Sarybchik goto fail1; 177283514Sarybchik } 178283514Sarybchik 179283514Sarybchik if (req.emr_out_length_used < MC_CMD_RSS_CONTEXT_ALLOC_OUT_LEN) { 180283514Sarybchik rc = EMSGSIZE; 181283514Sarybchik goto fail2; 182283514Sarybchik } 183283514Sarybchik 184283514Sarybchik rss_context = MCDI_OUT_DWORD(req, RSS_CONTEXT_ALLOC_OUT_RSS_CONTEXT_ID); 185283514Sarybchik if (rss_context == HUNTINGTON_RSS_CONTEXT_INVALID) { 186283514Sarybchik rc = ENOENT; 187283514Sarybchik goto fail3; 188283514Sarybchik } 189283514Sarybchik 190283514Sarybchik *rss_contextp = rss_context; 191283514Sarybchik 192283514Sarybchik return (0); 193283514Sarybchik 194283514Sarybchikfail3: 195283514Sarybchik EFSYS_PROBE(fail3); 196283514Sarybchikfail2: 197283514Sarybchik EFSYS_PROBE(fail2); 198283514Sarybchikfail1: 199291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 200283514Sarybchik 201283514Sarybchik return (rc); 202283514Sarybchik} 203283514Sarybchik#endif /* EFSYS_OPT_RX_SCALE */ 204283514Sarybchik 205283514Sarybchik#if EFSYS_OPT_RX_SCALE 206291436Sarybchikstatic efx_rc_t 207283514Sarybchikefx_mcdi_rss_context_free( 208283514Sarybchik __in efx_nic_t *enp, 209283514Sarybchik __in uint32_t rss_context) 210283514Sarybchik{ 211283514Sarybchik efx_mcdi_req_t req; 212283514Sarybchik uint8_t payload[MAX(MC_CMD_RSS_CONTEXT_FREE_IN_LEN, 213283514Sarybchik MC_CMD_RSS_CONTEXT_FREE_OUT_LEN)]; 214291436Sarybchik efx_rc_t rc; 215283514Sarybchik 216283514Sarybchik if (rss_context == HUNTINGTON_RSS_CONTEXT_INVALID) { 217283514Sarybchik rc = EINVAL; 218283514Sarybchik goto fail1; 219283514Sarybchik } 220283514Sarybchik 221283514Sarybchik (void) memset(payload, 0, sizeof (payload)); 222283514Sarybchik req.emr_cmd = MC_CMD_RSS_CONTEXT_FREE; 223283514Sarybchik req.emr_in_buf = payload; 224283514Sarybchik req.emr_in_length = MC_CMD_RSS_CONTEXT_FREE_IN_LEN; 225283514Sarybchik req.emr_out_buf = payload; 226283514Sarybchik req.emr_out_length = MC_CMD_RSS_CONTEXT_FREE_OUT_LEN; 227283514Sarybchik 228283514Sarybchik MCDI_IN_SET_DWORD(req, RSS_CONTEXT_FREE_IN_RSS_CONTEXT_ID, rss_context); 229283514Sarybchik 230283514Sarybchik efx_mcdi_execute(enp, &req); 231283514Sarybchik 232283514Sarybchik if (req.emr_rc != 0) { 233283514Sarybchik rc = req.emr_rc; 234283514Sarybchik goto fail2; 235283514Sarybchik } 236283514Sarybchik 237283514Sarybchik return (0); 238283514Sarybchik 239283514Sarybchikfail2: 240283514Sarybchik EFSYS_PROBE(fail2); 241283514Sarybchikfail1: 242291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 243283514Sarybchik 244283514Sarybchik return (rc); 245283514Sarybchik} 246283514Sarybchik#endif /* EFSYS_OPT_RX_SCALE */ 247283514Sarybchik 248283514Sarybchik#if EFSYS_OPT_RX_SCALE 249291436Sarybchikstatic efx_rc_t 250283514Sarybchikefx_mcdi_rss_context_set_flags( 251283514Sarybchik __in efx_nic_t *enp, 252283514Sarybchik __in uint32_t rss_context, 253283514Sarybchik __in efx_rx_hash_type_t type) 254283514Sarybchik{ 255283514Sarybchik efx_mcdi_req_t req; 256283514Sarybchik uint8_t payload[MAX(MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_LEN, 257283514Sarybchik MC_CMD_RSS_CONTEXT_SET_FLAGS_OUT_LEN)]; 258291436Sarybchik efx_rc_t rc; 259283514Sarybchik 260283514Sarybchik if (rss_context == HUNTINGTON_RSS_CONTEXT_INVALID) { 261283514Sarybchik rc = EINVAL; 262283514Sarybchik goto fail1; 263283514Sarybchik } 264283514Sarybchik 265283514Sarybchik (void) memset(payload, 0, sizeof (payload)); 266283514Sarybchik req.emr_cmd = MC_CMD_RSS_CONTEXT_SET_FLAGS; 267283514Sarybchik req.emr_in_buf = payload; 268283514Sarybchik req.emr_in_length = MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_LEN; 269283514Sarybchik req.emr_out_buf = payload; 270283514Sarybchik req.emr_out_length = MC_CMD_RSS_CONTEXT_SET_FLAGS_OUT_LEN; 271283514Sarybchik 272283514Sarybchik MCDI_IN_SET_DWORD(req, RSS_CONTEXT_SET_FLAGS_IN_RSS_CONTEXT_ID, 273283514Sarybchik rss_context); 274283514Sarybchik 275283514Sarybchik MCDI_IN_POPULATE_DWORD_4(req, RSS_CONTEXT_SET_FLAGS_IN_FLAGS, 276283514Sarybchik RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_IPV4_EN, 277283514Sarybchik (type & (1U << EFX_RX_HASH_IPV4)) ? 1 : 0, 278283514Sarybchik RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_TCPV4_EN, 279283514Sarybchik (type & (1U << EFX_RX_HASH_TCPIPV4)) ? 1 : 0, 280283514Sarybchik RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_IPV6_EN, 281283514Sarybchik (type & (1U << EFX_RX_HASH_IPV6)) ? 1 : 0, 282283514Sarybchik RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_TCPV6_EN, 283283514Sarybchik (type & (1U << EFX_RX_HASH_TCPIPV6)) ? 1 : 0); 284283514Sarybchik 285283514Sarybchik efx_mcdi_execute(enp, &req); 286283514Sarybchik 287283514Sarybchik if (req.emr_rc != 0) { 288283514Sarybchik rc = req.emr_rc; 289283514Sarybchik goto fail2; 290283514Sarybchik } 291283514Sarybchik 292283514Sarybchik return (0); 293283514Sarybchik 294283514Sarybchikfail2: 295283514Sarybchik EFSYS_PROBE(fail2); 296283514Sarybchikfail1: 297291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 298283514Sarybchik 299283514Sarybchik return (rc); 300283514Sarybchik} 301283514Sarybchik#endif /* EFSYS_OPT_RX_SCALE */ 302283514Sarybchik 303283514Sarybchik#if EFSYS_OPT_RX_SCALE 304291436Sarybchikstatic efx_rc_t 305283514Sarybchikefx_mcdi_rss_context_set_key( 306283514Sarybchik __in efx_nic_t *enp, 307283514Sarybchik __in uint32_t rss_context, 308283514Sarybchik __in_ecount(n) uint8_t *key, 309283514Sarybchik __in size_t n) 310283514Sarybchik{ 311283514Sarybchik efx_mcdi_req_t req; 312283514Sarybchik uint8_t payload[MAX(MC_CMD_RSS_CONTEXT_SET_KEY_IN_LEN, 313283514Sarybchik MC_CMD_RSS_CONTEXT_SET_KEY_OUT_LEN)]; 314291436Sarybchik efx_rc_t rc; 315283514Sarybchik 316283514Sarybchik if (rss_context == HUNTINGTON_RSS_CONTEXT_INVALID) { 317283514Sarybchik rc = EINVAL; 318283514Sarybchik goto fail1; 319283514Sarybchik } 320283514Sarybchik 321283514Sarybchik (void) memset(payload, 0, sizeof (payload)); 322283514Sarybchik req.emr_cmd = MC_CMD_RSS_CONTEXT_SET_KEY; 323283514Sarybchik req.emr_in_buf = payload; 324283514Sarybchik req.emr_in_length = MC_CMD_RSS_CONTEXT_SET_KEY_IN_LEN; 325283514Sarybchik req.emr_out_buf = payload; 326283514Sarybchik req.emr_out_length = MC_CMD_RSS_CONTEXT_SET_KEY_OUT_LEN; 327283514Sarybchik 328283514Sarybchik MCDI_IN_SET_DWORD(req, RSS_CONTEXT_SET_KEY_IN_RSS_CONTEXT_ID, 329283514Sarybchik rss_context); 330283514Sarybchik 331283514Sarybchik EFSYS_ASSERT3U(n, ==, MC_CMD_RSS_CONTEXT_SET_KEY_IN_TOEPLITZ_KEY_LEN); 332283514Sarybchik if (n != MC_CMD_RSS_CONTEXT_SET_KEY_IN_TOEPLITZ_KEY_LEN) { 333283514Sarybchik rc = EINVAL; 334283514Sarybchik goto fail2; 335283514Sarybchik } 336283514Sarybchik 337283514Sarybchik memcpy(MCDI_IN2(req, uint8_t, RSS_CONTEXT_SET_KEY_IN_TOEPLITZ_KEY), 338283514Sarybchik key, n); 339283514Sarybchik 340283514Sarybchik efx_mcdi_execute(enp, &req); 341283514Sarybchik 342283514Sarybchik if (req.emr_rc != 0) { 343283514Sarybchik rc = req.emr_rc; 344283514Sarybchik goto fail3; 345283514Sarybchik } 346283514Sarybchik 347283514Sarybchik return (0); 348283514Sarybchik 349283514Sarybchikfail3: 350283514Sarybchik EFSYS_PROBE(fail3); 351283514Sarybchikfail2: 352283514Sarybchik EFSYS_PROBE(fail2); 353283514Sarybchikfail1: 354291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 355283514Sarybchik 356283514Sarybchik return (rc); 357283514Sarybchik} 358283514Sarybchik#endif /* EFSYS_OPT_RX_SCALE */ 359283514Sarybchik 360283514Sarybchik#if EFSYS_OPT_RX_SCALE 361291436Sarybchikstatic efx_rc_t 362283514Sarybchikefx_mcdi_rss_context_set_table( 363283514Sarybchik __in efx_nic_t *enp, 364283514Sarybchik __in uint32_t rss_context, 365283514Sarybchik __in_ecount(n) unsigned int *table, 366283514Sarybchik __in size_t n) 367283514Sarybchik{ 368283514Sarybchik efx_mcdi_req_t req; 369283514Sarybchik uint8_t payload[MAX(MC_CMD_RSS_CONTEXT_SET_TABLE_IN_LEN, 370283514Sarybchik MC_CMD_RSS_CONTEXT_SET_TABLE_OUT_LEN)]; 371283514Sarybchik uint8_t *req_table; 372283514Sarybchik int i, rc; 373283514Sarybchik 374283514Sarybchik if (rss_context == HUNTINGTON_RSS_CONTEXT_INVALID) { 375283514Sarybchik rc = EINVAL; 376283514Sarybchik goto fail1; 377283514Sarybchik } 378283514Sarybchik 379283514Sarybchik (void) memset(payload, 0, sizeof (payload)); 380283514Sarybchik req.emr_cmd = MC_CMD_RSS_CONTEXT_SET_TABLE; 381283514Sarybchik req.emr_in_buf = payload; 382283514Sarybchik req.emr_in_length = MC_CMD_RSS_CONTEXT_SET_TABLE_IN_LEN; 383283514Sarybchik req.emr_out_buf = payload; 384283514Sarybchik req.emr_out_length = MC_CMD_RSS_CONTEXT_SET_TABLE_OUT_LEN; 385283514Sarybchik 386283514Sarybchik MCDI_IN_SET_DWORD(req, RSS_CONTEXT_SET_TABLE_IN_RSS_CONTEXT_ID, 387283514Sarybchik rss_context); 388283514Sarybchik 389283514Sarybchik req_table = 390283514Sarybchik MCDI_IN2(req, uint8_t, RSS_CONTEXT_SET_TABLE_IN_INDIRECTION_TABLE); 391283514Sarybchik 392283514Sarybchik for (i = 0; 393283514Sarybchik i < MC_CMD_RSS_CONTEXT_SET_TABLE_IN_INDIRECTION_TABLE_LEN; 394283514Sarybchik i++) { 395283514Sarybchik req_table[i] = (n > 0) ? (uint8_t)table[i % n] : 0; 396283514Sarybchik } 397283514Sarybchik 398283514Sarybchik efx_mcdi_execute(enp, &req); 399283514Sarybchik 400283514Sarybchik if (req.emr_rc != 0) { 401283514Sarybchik rc = req.emr_rc; 402283514Sarybchik goto fail2; 403283514Sarybchik } 404283514Sarybchik 405283514Sarybchik return (0); 406283514Sarybchik 407283514Sarybchikfail2: 408283514Sarybchik EFSYS_PROBE(fail2); 409283514Sarybchikfail1: 410291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 411283514Sarybchik 412283514Sarybchik return (rc); 413283514Sarybchik} 414283514Sarybchik#endif /* EFSYS_OPT_RX_SCALE */ 415283514Sarybchik 416283514Sarybchik 417291436Sarybchik __checkReturn efx_rc_t 418283514Sarybchikhunt_rx_init( 419283514Sarybchik __in efx_nic_t *enp) 420283514Sarybchik{ 421283514Sarybchik#if EFSYS_OPT_RX_SCALE 422283514Sarybchik 423283514Sarybchik if (efx_mcdi_rss_context_alloc(enp, &enp->en_rss_context) == 0) { 424283514Sarybchik /* 425283514Sarybchik * Allocated an exclusive RSS context, which allows both the 426283514Sarybchik * indirection table and key to be modified. 427283514Sarybchik */ 428283514Sarybchik enp->en_rss_support = EFX_RX_SCALE_EXCLUSIVE; 429283514Sarybchik enp->en_hash_support = EFX_RX_HASH_AVAILABLE; 430283514Sarybchik } else { 431283514Sarybchik /* 432283514Sarybchik * Failed to allocate an exclusive RSS context. Continue 433283514Sarybchik * operation without support for RSS. The pseudo-header in 434283514Sarybchik * received packets will not contain a Toeplitz hash value. 435283514Sarybchik */ 436283514Sarybchik enp->en_rss_support = EFX_RX_SCALE_UNAVAILABLE; 437283514Sarybchik enp->en_hash_support = EFX_RX_HASH_UNAVAILABLE; 438283514Sarybchik } 439283514Sarybchik 440283514Sarybchik#endif /* EFSYS_OPT_RX_SCALE */ 441283514Sarybchik 442283514Sarybchik return (0); 443283514Sarybchik} 444283514Sarybchik 445283514Sarybchik#if EFSYS_OPT_RX_HDR_SPLIT 446291436Sarybchik __checkReturn efx_rc_t 447283514Sarybchikhunt_rx_hdr_split_enable( 448283514Sarybchik __in efx_nic_t *enp, 449283514Sarybchik __in unsigned int hdr_buf_size, 450283514Sarybchik __in unsigned int pld_buf_size) 451283514Sarybchik{ 452291436Sarybchik efx_rc_t rc; 453283514Sarybchik 454283514Sarybchik /* FIXME */ 455283514Sarybchik _NOTE(ARGUNUSED(enp, hdr_buf_size, pld_buf_size)) 456283514Sarybchik if (B_FALSE) { 457283514Sarybchik rc = ENOTSUP; 458283514Sarybchik goto fail1; 459283514Sarybchik } 460283514Sarybchik /* FIXME */ 461283514Sarybchik 462283514Sarybchik return (0); 463283514Sarybchik 464283514Sarybchikfail1: 465291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 466283514Sarybchik 467283514Sarybchik return (rc); 468283514Sarybchik} 469283514Sarybchik#endif /* EFSYS_OPT_RX_HDR_SPLIT */ 470283514Sarybchik 471283514Sarybchik#if EFSYS_OPT_RX_SCATTER 472291436Sarybchik __checkReturn efx_rc_t 473283514Sarybchikhunt_rx_scatter_enable( 474283514Sarybchik __in efx_nic_t *enp, 475283514Sarybchik __in unsigned int buf_size) 476283514Sarybchik{ 477283514Sarybchik _NOTE(ARGUNUSED(enp, buf_size)) 478283514Sarybchik return (0); 479283514Sarybchik} 480283514Sarybchik#endif /* EFSYS_OPT_RX_SCATTER */ 481283514Sarybchik 482283514Sarybchik#if EFSYS_OPT_RX_SCALE 483291436Sarybchik __checkReturn efx_rc_t 484283514Sarybchikhunt_rx_scale_mode_set( 485283514Sarybchik __in efx_nic_t *enp, 486283514Sarybchik __in efx_rx_hash_alg_t alg, 487283514Sarybchik __in efx_rx_hash_type_t type, 488283514Sarybchik __in boolean_t insert) 489283514Sarybchik{ 490291436Sarybchik efx_rc_t rc; 491283514Sarybchik 492283514Sarybchik EFSYS_ASSERT3U(alg, ==, EFX_RX_HASHALG_TOEPLITZ); 493283514Sarybchik EFSYS_ASSERT3U(insert, ==, B_TRUE); 494283514Sarybchik 495283514Sarybchik if ((alg != EFX_RX_HASHALG_TOEPLITZ) || (insert == B_FALSE)) { 496283514Sarybchik rc = EINVAL; 497283514Sarybchik goto fail1; 498283514Sarybchik } 499283514Sarybchik 500283514Sarybchik if (enp->en_rss_support == EFX_RX_SCALE_UNAVAILABLE) { 501283514Sarybchik rc = ENOTSUP; 502283514Sarybchik goto fail2; 503283514Sarybchik } 504283514Sarybchik 505283514Sarybchik if ((rc = efx_mcdi_rss_context_set_flags(enp, 506283514Sarybchik enp->en_rss_context, type)) != 0) 507283514Sarybchik goto fail3; 508283514Sarybchik 509283514Sarybchik return (0); 510283514Sarybchik 511283514Sarybchikfail3: 512283514Sarybchik EFSYS_PROBE(fail3); 513283514Sarybchikfail2: 514283514Sarybchik EFSYS_PROBE(fail2); 515283514Sarybchikfail1: 516291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 517283514Sarybchik 518283514Sarybchik return (rc); 519283514Sarybchik} 520283514Sarybchik#endif /* EFSYS_OPT_RX_SCALE */ 521283514Sarybchik 522283514Sarybchik#if EFSYS_OPT_RX_SCALE 523291436Sarybchik __checkReturn efx_rc_t 524283514Sarybchikhunt_rx_scale_key_set( 525283514Sarybchik __in efx_nic_t *enp, 526283514Sarybchik __in_ecount(n) uint8_t *key, 527283514Sarybchik __in size_t n) 528283514Sarybchik{ 529291436Sarybchik efx_rc_t rc; 530283514Sarybchik 531283514Sarybchik if (enp->en_rss_support == EFX_RX_SCALE_UNAVAILABLE) { 532283514Sarybchik rc = ENOTSUP; 533283514Sarybchik goto fail1; 534283514Sarybchik } 535283514Sarybchik 536283514Sarybchik if ((rc = efx_mcdi_rss_context_set_key(enp, 537283514Sarybchik enp->en_rss_context, key, n)) != 0) 538283514Sarybchik goto fail2; 539283514Sarybchik 540283514Sarybchik return (0); 541283514Sarybchik 542283514Sarybchikfail2: 543283514Sarybchik EFSYS_PROBE(fail2); 544283514Sarybchikfail1: 545291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 546283514Sarybchik 547283514Sarybchik return (rc); 548283514Sarybchik} 549283514Sarybchik#endif /* EFSYS_OPT_RX_SCALE */ 550283514Sarybchik 551283514Sarybchik#if EFSYS_OPT_RX_SCALE 552291436Sarybchik __checkReturn efx_rc_t 553283514Sarybchikhunt_rx_scale_tbl_set( 554283514Sarybchik __in efx_nic_t *enp, 555283514Sarybchik __in_ecount(n) unsigned int *table, 556283514Sarybchik __in size_t n) 557283514Sarybchik{ 558291436Sarybchik efx_rc_t rc; 559283514Sarybchik 560283514Sarybchik if (enp->en_rss_support == EFX_RX_SCALE_UNAVAILABLE) { 561283514Sarybchik rc = ENOTSUP; 562283514Sarybchik goto fail1; 563283514Sarybchik } 564283514Sarybchik 565283514Sarybchik if ((rc = efx_mcdi_rss_context_set_table(enp, 566283514Sarybchik enp->en_rss_context, table, n)) != 0) 567283514Sarybchik goto fail2; 568283514Sarybchik 569283514Sarybchik return (0); 570283514Sarybchik 571283514Sarybchikfail2: 572283514Sarybchik EFSYS_PROBE(fail2); 573283514Sarybchikfail1: 574291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 575283514Sarybchik 576283514Sarybchik return (rc); 577283514Sarybchik} 578283514Sarybchik#endif /* EFSYS_OPT_RX_SCALE */ 579283514Sarybchik 580283514Sarybchik void 581283514Sarybchikhunt_rx_qpost( 582283514Sarybchik __in efx_rxq_t *erp, 583283514Sarybchik __in_ecount(n) efsys_dma_addr_t *addrp, 584283514Sarybchik __in size_t size, 585283514Sarybchik __in unsigned int n, 586283514Sarybchik __in unsigned int completed, 587283514Sarybchik __in unsigned int added) 588283514Sarybchik{ 589283514Sarybchik efx_qword_t qword; 590283514Sarybchik unsigned int i; 591283514Sarybchik unsigned int offset; 592283514Sarybchik unsigned int id; 593283514Sarybchik 594283514Sarybchik /* The client driver must not overfill the queue */ 595283514Sarybchik EFSYS_ASSERT3U(added - completed + n, <=, 596283514Sarybchik EFX_RXQ_LIMIT(erp->er_mask + 1)); 597283514Sarybchik 598283514Sarybchik id = added & (erp->er_mask); 599283514Sarybchik for (i = 0; i < n; i++) { 600283514Sarybchik EFSYS_PROBE4(rx_post, unsigned int, erp->er_index, 601283514Sarybchik unsigned int, id, efsys_dma_addr_t, addrp[i], 602283514Sarybchik size_t, size); 603283514Sarybchik 604283514Sarybchik EFX_POPULATE_QWORD_3(qword, 605283514Sarybchik ESF_DZ_RX_KER_BYTE_CNT, (uint32_t)(size), 606283514Sarybchik ESF_DZ_RX_KER_BUF_ADDR_DW0, 607283514Sarybchik (uint32_t)(addrp[i] & 0xffffffff), 608283514Sarybchik ESF_DZ_RX_KER_BUF_ADDR_DW1, 609283514Sarybchik (uint32_t)(addrp[i] >> 32)); 610283514Sarybchik 611283514Sarybchik offset = id * sizeof (efx_qword_t); 612283514Sarybchik EFSYS_MEM_WRITEQ(erp->er_esmp, offset, &qword); 613283514Sarybchik 614283514Sarybchik id = (id + 1) & (erp->er_mask); 615283514Sarybchik } 616283514Sarybchik} 617283514Sarybchik 618283514Sarybchik void 619283514Sarybchikhunt_rx_qpush( 620283514Sarybchik __in efx_rxq_t *erp, 621283514Sarybchik __in unsigned int added, 622283514Sarybchik __inout unsigned int *pushedp) 623283514Sarybchik{ 624283514Sarybchik efx_nic_t *enp = erp->er_enp; 625283514Sarybchik unsigned int pushed = *pushedp; 626283514Sarybchik uint32_t wptr; 627283514Sarybchik efx_dword_t dword; 628283514Sarybchik 629283514Sarybchik /* Hardware has alignment restriction for WPTR */ 630283514Sarybchik wptr = P2ALIGN(added, HUNTINGTON_RX_WPTR_ALIGN); 631283514Sarybchik if (pushed == wptr) 632283514Sarybchik return; 633283514Sarybchik 634283514Sarybchik *pushedp = wptr; 635283514Sarybchik 636283514Sarybchik /* Push the populated descriptors out */ 637283514Sarybchik wptr &= erp->er_mask; 638283514Sarybchik 639283514Sarybchik EFX_POPULATE_DWORD_1(dword, ERF_DZ_RX_DESC_WPTR, wptr); 640283514Sarybchik 641283514Sarybchik /* Guarantee ordering of memory (descriptors) and PIO (doorbell) */ 642283514Sarybchik EFX_DMA_SYNC_QUEUE_FOR_DEVICE(erp->er_esmp, erp->er_mask + 1, 643283514Sarybchik wptr, pushed & erp->er_mask); 644283514Sarybchik EFSYS_PIO_WRITE_BARRIER(); 645283514Sarybchik EFX_BAR_TBL_WRITED(enp, ER_DZ_RX_DESC_UPD_REG, 646283514Sarybchik erp->er_index, &dword, B_FALSE); 647283514Sarybchik} 648283514Sarybchik 649291436Sarybchik __checkReturn efx_rc_t 650283514Sarybchikhunt_rx_qflush( 651283514Sarybchik __in efx_rxq_t *erp) 652283514Sarybchik{ 653283514Sarybchik efx_nic_t *enp = erp->er_enp; 654291436Sarybchik efx_rc_t rc; 655283514Sarybchik 656283514Sarybchik if ((rc = efx_mcdi_fini_rxq(enp, erp->er_index)) != 0) 657283514Sarybchik goto fail1; 658283514Sarybchik 659283514Sarybchik return (0); 660283514Sarybchik 661283514Sarybchikfail1: 662291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 663283514Sarybchik 664283514Sarybchik return (rc); 665283514Sarybchik} 666283514Sarybchik 667283514Sarybchik void 668283514Sarybchikhunt_rx_qenable( 669283514Sarybchik __in efx_rxq_t *erp) 670283514Sarybchik{ 671283514Sarybchik /* FIXME */ 672283514Sarybchik _NOTE(ARGUNUSED(erp)) 673283514Sarybchik /* FIXME */ 674283514Sarybchik} 675283514Sarybchik 676291436Sarybchik __checkReturn efx_rc_t 677283514Sarybchikhunt_rx_qcreate( 678283514Sarybchik __in efx_nic_t *enp, 679283514Sarybchik __in unsigned int index, 680283514Sarybchik __in unsigned int label, 681283514Sarybchik __in efx_rxq_type_t type, 682283514Sarybchik __in efsys_mem_t *esmp, 683283514Sarybchik __in size_t n, 684283514Sarybchik __in uint32_t id, 685283514Sarybchik __in efx_evq_t *eep, 686283514Sarybchik __in efx_rxq_t *erp) 687283514Sarybchik{ 688283514Sarybchik efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 689291436Sarybchik efx_rc_t rc; 690291747Sarybchik boolean_t disable_scatter; 691283514Sarybchik 692283514Sarybchik _NOTE(ARGUNUSED(erp)) 693283514Sarybchik 694283514Sarybchik EFX_STATIC_ASSERT(EFX_EV_RX_NLABELS == (1 << ESF_DZ_RX_QLABEL_WIDTH)); 695283514Sarybchik EFSYS_ASSERT3U(label, <, EFX_EV_RX_NLABELS); 696283514Sarybchik EFSYS_ASSERT3U(enp->en_rx_qcount + 1, <, encp->enc_rxq_limit); 697283514Sarybchik 698283514Sarybchik EFX_STATIC_ASSERT(ISP2(EFX_RXQ_MAXNDESCS)); 699283514Sarybchik EFX_STATIC_ASSERT(ISP2(EFX_RXQ_MINNDESCS)); 700283514Sarybchik 701283514Sarybchik if (!ISP2(n) || (n < EFX_RXQ_MINNDESCS) || (n > EFX_RXQ_MAXNDESCS)) { 702283514Sarybchik rc = EINVAL; 703283514Sarybchik goto fail1; 704283514Sarybchik } 705283514Sarybchik if (index >= encp->enc_rxq_limit) { 706283514Sarybchik rc = EINVAL; 707283514Sarybchik goto fail2; 708283514Sarybchik } 709283514Sarybchik 710291747Sarybchik /* Scatter can only be disabled if the firmware supports doing so */ 711291747Sarybchik if ((type != EFX_RXQ_TYPE_SCATTER) && 712291747Sarybchik enp->en_nic_cfg.enc_rx_disable_scatter_supported) { 713291747Sarybchik disable_scatter = B_TRUE; 714291747Sarybchik } else { 715291747Sarybchik disable_scatter = B_FALSE; 716291747Sarybchik } 717291747Sarybchik 718283514Sarybchik /* 719291747Sarybchik * Note: EFX_RXQ_TYPE_SPLIT_HEADER and EFX_RXQ_TYPE_SPLIT_PAYLOAD are 720291747Sarybchik * not supported here. 721283514Sarybchik */ 722283514Sarybchik 723283514Sarybchik if ((rc = efx_mcdi_init_rxq(enp, n, eep->ee_index, label, index, 724291747Sarybchik esmp, disable_scatter)) != 0) 725283514Sarybchik goto fail3; 726283514Sarybchik 727283514Sarybchik erp->er_eep = eep; 728283514Sarybchik erp->er_label = label; 729283514Sarybchik 730293752Sarybchik ef10_ev_rxlabel_init(eep, erp, label); 731283514Sarybchik 732283514Sarybchik return (0); 733283514Sarybchik 734283514Sarybchikfail3: 735283514Sarybchik EFSYS_PROBE(fail3); 736283514Sarybchikfail2: 737283514Sarybchik EFSYS_PROBE(fail2); 738283514Sarybchikfail1: 739291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 740283514Sarybchik 741283514Sarybchik return (rc); 742283514Sarybchik} 743283514Sarybchik 744283514Sarybchik void 745283514Sarybchikhunt_rx_qdestroy( 746283514Sarybchik __in efx_rxq_t *erp) 747283514Sarybchik{ 748283514Sarybchik efx_nic_t *enp = erp->er_enp; 749283514Sarybchik efx_evq_t *eep = erp->er_eep; 750283514Sarybchik unsigned int label = erp->er_label; 751283514Sarybchik 752293752Sarybchik ef10_ev_rxlabel_fini(eep, label); 753283514Sarybchik 754283514Sarybchik EFSYS_ASSERT(enp->en_rx_qcount != 0); 755283514Sarybchik --enp->en_rx_qcount; 756283514Sarybchik 757283514Sarybchik EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_rxq_t), erp); 758283514Sarybchik} 759283514Sarybchik 760283514Sarybchik void 761283514Sarybchikhunt_rx_fini( 762283514Sarybchik __in efx_nic_t *enp) 763283514Sarybchik{ 764283514Sarybchik#if EFSYS_OPT_RX_SCALE 765283514Sarybchik if (enp->en_rss_support != EFX_RX_SCALE_UNAVAILABLE) { 766283514Sarybchik (void) efx_mcdi_rss_context_free(enp, enp->en_rss_context); 767283514Sarybchik } 768283514Sarybchik enp->en_rss_context = 0; 769283514Sarybchik enp->en_rss_support = EFX_RX_SCALE_UNAVAILABLE; 770283514Sarybchik#else 771283514Sarybchik _NOTE(ARGUNUSED(enp)) 772283514Sarybchik#endif /* EFSYS_OPT_RX_SCALE */ 773283514Sarybchik} 774283514Sarybchik 775283514Sarybchik#endif /* EFSYS_OPT_HUNTINGTON */ 776