mcdi_mac.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. /****************************************************************************
  2. * Driver for Solarflare Solarstorm network controllers and boards
  3. * Copyright 2009-2010 Solarflare Communications Inc.
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License version 2 as published
  7. * by the Free Software Foundation, incorporated herein by reference.
  8. */
  9. #include "net_driver.h"
  10. #include "efx.h"
  11. #include "mac.h"
  12. #include "mcdi.h"
  13. #include "mcdi_pcol.h"
  14. static int efx_mcdi_set_mac(struct efx_nic *efx)
  15. {
  16. u32 reject, fcntl;
  17. u8 cmdbytes[MC_CMD_SET_MAC_IN_LEN];
  18. memcpy(cmdbytes + MC_CMD_SET_MAC_IN_ADDR_OFST,
  19. efx->net_dev->dev_addr, ETH_ALEN);
  20. MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_MTU,
  21. EFX_MAX_FRAME_LEN(efx->net_dev->mtu));
  22. MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_DRAIN, 0);
  23. /* The MCDI command provides for controlling accept/reject
  24. * of broadcast packets too, but the driver doesn't currently
  25. * expose this. */
  26. reject = (efx->promiscuous) ? 0 :
  27. (1 << MC_CMD_SET_MAC_IN_REJECT_UNCST_LBN);
  28. MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_REJECT, reject);
  29. switch (efx->wanted_fc) {
  30. case EFX_FC_RX | EFX_FC_TX:
  31. fcntl = MC_CMD_FCNTL_BIDIR;
  32. break;
  33. case EFX_FC_RX:
  34. fcntl = MC_CMD_FCNTL_RESPOND;
  35. break;
  36. default:
  37. fcntl = MC_CMD_FCNTL_OFF;
  38. break;
  39. }
  40. if (efx->wanted_fc & EFX_FC_AUTO)
  41. fcntl = MC_CMD_FCNTL_AUTO;
  42. MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_FCNTL, fcntl);
  43. return efx_mcdi_rpc(efx, MC_CMD_SET_MAC, cmdbytes, sizeof(cmdbytes),
  44. NULL, 0, NULL);
  45. }
  46. static int efx_mcdi_get_mac_faults(struct efx_nic *efx, u32 *faults)
  47. {
  48. u8 outbuf[MC_CMD_GET_LINK_OUT_LEN];
  49. size_t outlength;
  50. int rc;
  51. BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0);
  52. rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0,
  53. outbuf, sizeof(outbuf), &outlength);
  54. if (rc)
  55. goto fail;
  56. *faults = MCDI_DWORD(outbuf, GET_LINK_OUT_MAC_FAULT);
  57. return 0;
  58. fail:
  59. netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n",
  60. __func__, rc);
  61. return rc;
  62. }
  63. int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr,
  64. u32 dma_len, int enable, int clear)
  65. {
  66. u8 inbuf[MC_CMD_MAC_STATS_IN_LEN];
  67. int rc;
  68. efx_dword_t *cmd_ptr;
  69. int period = enable ? 1000 : 0;
  70. u32 addr_hi;
  71. u32 addr_lo;
  72. BUILD_BUG_ON(MC_CMD_MAC_STATS_OUT_LEN != 0);
  73. addr_lo = ((u64)dma_addr) >> 0;
  74. addr_hi = ((u64)dma_addr) >> 32;
  75. MCDI_SET_DWORD(inbuf, MAC_STATS_IN_DMA_ADDR_LO, addr_lo);
  76. MCDI_SET_DWORD(inbuf, MAC_STATS_IN_DMA_ADDR_HI, addr_hi);
  77. cmd_ptr = (efx_dword_t *)MCDI_PTR(inbuf, MAC_STATS_IN_CMD);
  78. EFX_POPULATE_DWORD_7(*cmd_ptr,
  79. MC_CMD_MAC_STATS_CMD_DMA, !!enable,
  80. MC_CMD_MAC_STATS_CMD_CLEAR, clear,
  81. MC_CMD_MAC_STATS_CMD_PERIODIC_CHANGE, 1,
  82. MC_CMD_MAC_STATS_CMD_PERIODIC_ENABLE, !!enable,
  83. MC_CMD_MAC_STATS_CMD_PERIODIC_CLEAR, 0,
  84. MC_CMD_MAC_STATS_CMD_PERIODIC_NOEVENT, 1,
  85. MC_CMD_MAC_STATS_CMD_PERIOD_MS, period);
  86. MCDI_SET_DWORD(inbuf, MAC_STATS_IN_DMA_LEN, dma_len);
  87. rc = efx_mcdi_rpc(efx, MC_CMD_MAC_STATS, inbuf, sizeof(inbuf),
  88. NULL, 0, NULL);
  89. if (rc)
  90. goto fail;
  91. return 0;
  92. fail:
  93. netif_err(efx, hw, efx->net_dev, "%s: %s failed rc=%d\n",
  94. __func__, enable ? "enable" : "disable", rc);
  95. return rc;
  96. }
  97. static int efx_mcdi_mac_reconfigure(struct efx_nic *efx)
  98. {
  99. int rc;
  100. rc = efx_mcdi_set_mac(efx);
  101. if (rc != 0)
  102. return rc;
  103. /* Restore the multicast hash registers. */
  104. efx->type->push_multicast_hash(efx);
  105. return 0;
  106. }
  107. static bool efx_mcdi_mac_check_fault(struct efx_nic *efx)
  108. {
  109. u32 faults;
  110. int rc = efx_mcdi_get_mac_faults(efx, &faults);
  111. return (rc != 0) || (faults != 0);
  112. }
  113. const struct efx_mac_operations efx_mcdi_mac_operations = {
  114. .reconfigure = efx_mcdi_mac_reconfigure,
  115. .update_stats = efx_port_dummy_op_void,
  116. .check_fault = efx_mcdi_mac_check_fault,
  117. };