1/*- 2 * Copyright (c) 2012-2015 Solarflare Communications Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, --- 15 unchanged lines hidden (view full) --- 24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 * The views and conclusions contained in the software and documentation are 27 * those of the authors and should not be interpreted as representing official 28 * policies, either expressed or implied, of the FreeBSD Project. 29 */ 30 31#include <sys/cdefs.h> |
32__FBSDID("$FreeBSD: head/sys/dev/sfxge/common/hunt_mcdi.c 291985 2015-12-08 06:25:52Z arybchik $"); |
33 34#include "efsys.h" 35#include "efx.h" 36#include "efx_impl.h" 37 38 39#if EFSYS_OPT_HUNTINGTON 40 --- 183 unchanged lines hidden (view full) --- 224 EFX_BAR_WRITED(enp, ER_DZ_MC_DB_HWRD_REG, &dword, B_FALSE); 225} 226 227 void 228hunt_mcdi_request_copyout( 229 __in efx_nic_t *enp, 230 __in efx_mcdi_req_t *emrp) 231{ |
232#if EFSYS_OPT_MCDI_LOGGING |
233 const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; |
234#endif /* EFSYS_OPT_MCDI_LOGGING */ |
235 efx_dword_t hdr[2]; |
236 unsigned int hdr_len; |
237 size_t bytes; 238 239 if (emrp->emr_out_buf == NULL) 240 return; 241 242 /* Read the command header to detect MCDI response format */ |
243 hdr_len = sizeof (hdr[0]); 244 hunt_mcdi_read_response(enp, &hdr[0], 0, hdr_len); |
245 if (EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_CODE) == MC_CMD_V2_EXTN) { |
246 /* 247 * Read the actual payload length. The length given in the event 248 * is only correct for responses with the V1 format. 249 */ |
250 hunt_mcdi_read_response(enp, &hdr[1], hdr_len, sizeof (hdr[1])); 251 hdr_len += sizeof (hdr[1]); 252 |
253 emrp->emr_out_length_used = EFX_DWORD_FIELD(hdr[1], 254 MC_CMD_V2_EXTN_IN_ACTUAL_LEN); |
255 } 256 257 /* Copy payload out into caller supplied buffer */ 258 bytes = MIN(emrp->emr_out_length_used, emrp->emr_out_length); |
259 hunt_mcdi_read_response(enp, emrp->emr_out_buf, hdr_len, bytes); |
260 261#if EFSYS_OPT_MCDI_LOGGING 262 if (emtp->emt_logger != NULL) { 263 emtp->emt_logger(emtp->emt_context, 264 EFX_LOG_MCDI_RESPONSE, |
265 &hdr, hdr_len, 266 emrp->emr_out_buf, bytes); |
267 } 268#endif /* EFSYS_OPT_MCDI_LOGGING */ 269} 270 271static __checkReturn boolean_t 272hunt_mcdi_poll_response( 273 __in efx_nic_t *enp) 274{ 275 const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; 276 efsys_mem_t *esmp = emtp->emt_dma_mem; 277 efx_dword_t hdr; 278 279 EFSYS_MEM_READD(esmp, 0, &hdr); 280 return (EFX_DWORD_FIELD(hdr, MCDI_HEADER_RESPONSE) ? B_TRUE : B_FALSE); 281} 282 |
283 void 284hunt_mcdi_read_response( 285 __in efx_nic_t *enp, 286 __out void *bufferp, 287 __in size_t offset, 288 __in size_t length) 289{ 290 const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; 291 efsys_mem_t *esmp = emtp->emt_dma_mem; 292 unsigned int pos; 293 efx_dword_t data; 294 295 for (pos = 0; pos < length; pos += sizeof (efx_dword_t)) { 296 EFSYS_MEM_READD(esmp, offset + pos, &data); 297 memcpy((uint8_t *)bufferp + pos, &data, 298 MIN(sizeof (data), length - pos)); 299 } 300} 301 |
302 __checkReturn boolean_t 303hunt_mcdi_request_poll( 304 __in efx_nic_t *enp) 305{ |
306#if EFSYS_OPT_MCDI_LOGGING |
307 const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; |
308#endif /* EFSYS_OPT_MCDI_LOGGING */ 309 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); |
310 efx_mcdi_req_t *emrp; 311 efx_dword_t hdr[2]; |
312 unsigned int hdr_len; 313 unsigned int data_len; |
314 unsigned int seq; 315 unsigned int cmd; |
316 int state; 317 efx_rc_t rc; 318 319 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_HUNTINGTON); 320 321 /* Serialise against post-watchdog efx_mcdi_ev* */ 322 EFSYS_LOCK(enp->en_eslp, state); 323 324 EFSYS_ASSERT(emip->emi_pending_req != NULL); 325 EFSYS_ASSERT(!emip->emi_ev_cpl); 326 emrp = emip->emi_pending_req; 327 |
328 /* Check if a response is available */ 329 if (hunt_mcdi_poll_response(enp) == B_FALSE) { 330 EFSYS_UNLOCK(enp->en_eslp, state); 331 return (B_FALSE); 332 } 333 334 /* Read the response header */ |
335 hdr_len = sizeof (hdr[0]); 336 hunt_mcdi_read_response(enp, &hdr[0], 0, hdr_len); 337 |
338 if (EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_CODE) == MC_CMD_V2_EXTN) { |
339 hunt_mcdi_read_response(enp, &hdr[1], hdr_len, sizeof (hdr[1])); 340 hdr_len += sizeof (hdr[1]); |
341 342 cmd = EFX_DWORD_FIELD(hdr[1], MC_CMD_V2_EXTN_IN_EXTENDED_CMD); |
343 data_len = 344 EFX_DWORD_FIELD(hdr[1], MC_CMD_V2_EXTN_IN_ACTUAL_LEN); |
345 } else { 346 cmd = EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_CODE); |
347 data_len = EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_DATALEN); |
348 } 349 350 /* Request complete */ 351 emip->emi_pending_req = NULL; 352 seq = (emip->emi_seq - 1) & EFX_MASK32(MCDI_HEADER_SEQ); 353 354 /* Check for synchronous reboot */ |
355 if (EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_ERROR) != 0 && data_len == 0) { |
356 /* The MC has rebooted since the request was sent. */ 357 EFSYS_SPIN(EFX_MCDI_STATUS_SLEEP_US); 358 hunt_mcdi_poll_reboot(enp); 359 360 EFSYS_UNLOCK(enp->en_eslp, state); 361 rc = EIO; 362 goto fail1; 363 } --- 7 unchanged lines hidden (view full) --- 371 if (cmd != emrp->emr_cmd || 372 EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_SEQ) != seq) { 373 /* Response is for a different request */ 374 rc = EIO; 375 goto fail2; 376 } 377 if (EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_ERROR)) { 378 efx_dword_t err[2]; |
379 unsigned int err_len = MIN(data_len, sizeof (err)); 380 int err_code = MC_CMD_ERR_EPROTO; 381 int err_arg = 0; |
382 383 /* Read error code (and arg num for MCDI v2 commands) */ |
384 hunt_mcdi_read_response(enp, &err[0], hdr_len, err_len); |
385 |
386 if (err_len >= MC_CMD_ERR_CODE_OFST + sizeof (efx_dword_t)) 387 err_code = EFX_DWORD_FIELD(err[0], EFX_DWORD_0); |
388 |
389 if (err_len >= MC_CMD_ERR_ARG_OFST + sizeof (efx_dword_t)) 390 err_arg = EFX_DWORD_FIELD(err[1], EFX_DWORD_0); 391 |
392#if EFSYS_OPT_MCDI_LOGGING 393 if (emtp->emt_logger != NULL) { 394 emtp->emt_logger(emtp->emt_context, 395 EFX_LOG_MCDI_RESPONSE, |
396 &hdr, hdr_len, 397 &err, err_len); |
398 } 399#endif /* EFSYS_OPT_MCDI_LOGGING */ 400 |
401 rc = efx_mcdi_request_errcode(err_code); |
402 if (!emrp->emr_quiet) { 403 EFSYS_PROBE3(mcdi_err_arg, int, emrp->emr_cmd, |
404 int, err_code, int, err_arg); |
405 } 406 goto fail3; 407 408 } else { |
409 emrp->emr_out_length_used = data_len; |
410 emrp->emr_rc = 0; 411 hunt_mcdi_request_copyout(enp, emrp); 412 } 413 414 goto out; 415 416fail3: 417 if (!emrp->emr_quiet) --- 138 unchanged lines hidden --- |