qlcnic_dcb.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /*
  2. * QLogic qlcnic NIC Driver
  3. * Copyright (c) 2009-2013 QLogic Corporation
  4. *
  5. * See LICENSE.qlcnic for copyright and licensing details.
  6. */
  7. #include "qlcnic.h"
  8. #define QLC_DCB_MAX_TC 0x8
  9. #define QLC_DCB_TSA_SUPPORT(V) (V & 0x1)
  10. #define QLC_DCB_ETS_SUPPORT(V) ((V >> 1) & 0x1)
  11. #define QLC_DCB_VERSION_SUPPORT(V) ((V >> 2) & 0xf)
  12. #define QLC_DCB_MAX_NUM_TC(V) ((V >> 20) & 0xf)
  13. #define QLC_DCB_MAX_NUM_ETS_TC(V) ((V >> 24) & 0xf)
  14. #define QLC_DCB_MAX_NUM_PFC_TC(V) ((V >> 28) & 0xf)
  15. static void __qlcnic_dcb_free(struct qlcnic_adapter *);
  16. static int __qlcnic_dcb_attach(struct qlcnic_adapter *);
  17. static int __qlcnic_dcb_query_hw_capability(struct qlcnic_adapter *, char *);
  18. static void __qlcnic_dcb_get_info(struct qlcnic_adapter *);
  19. static int qlcnic_82xx_dcb_get_hw_capability(struct qlcnic_adapter *);
  20. static int qlcnic_83xx_dcb_get_hw_capability(struct qlcnic_adapter *);
  21. struct qlcnic_dcb_capability {
  22. bool tsa_capability;
  23. bool ets_capability;
  24. u8 max_num_tc;
  25. u8 max_ets_tc;
  26. u8 max_pfc_tc;
  27. u8 dcb_capability;
  28. };
  29. struct qlcnic_dcb_cfg {
  30. struct qlcnic_dcb_capability capability;
  31. u32 version;
  32. };
  33. static struct qlcnic_dcb_ops qlcnic_83xx_dcb_ops = {
  34. .free = __qlcnic_dcb_free,
  35. .attach = __qlcnic_dcb_attach,
  36. .query_hw_capability = __qlcnic_dcb_query_hw_capability,
  37. .get_info = __qlcnic_dcb_get_info,
  38. .get_hw_capability = qlcnic_83xx_dcb_get_hw_capability,
  39. };
  40. static struct qlcnic_dcb_ops qlcnic_82xx_dcb_ops = {
  41. .free = __qlcnic_dcb_free,
  42. .attach = __qlcnic_dcb_attach,
  43. .query_hw_capability = __qlcnic_dcb_query_hw_capability,
  44. .get_info = __qlcnic_dcb_get_info,
  45. .get_hw_capability = qlcnic_82xx_dcb_get_hw_capability,
  46. };
  47. void qlcnic_set_dcb_ops(struct qlcnic_adapter *adapter)
  48. {
  49. if (qlcnic_82xx_check(adapter))
  50. adapter->dcb->ops = &qlcnic_82xx_dcb_ops;
  51. else if (qlcnic_83xx_check(adapter))
  52. adapter->dcb->ops = &qlcnic_83xx_dcb_ops;
  53. }
  54. int __qlcnic_register_dcb(struct qlcnic_adapter *adapter)
  55. {
  56. struct qlcnic_dcb *dcb;
  57. dcb = kzalloc(sizeof(struct qlcnic_dcb), GFP_ATOMIC);
  58. if (!dcb)
  59. return -ENOMEM;
  60. adapter->dcb = dcb;
  61. qlcnic_set_dcb_ops(adapter);
  62. return 0;
  63. }
  64. static void __qlcnic_dcb_free(struct qlcnic_adapter *adapter)
  65. {
  66. struct qlcnic_dcb *dcb = adapter->dcb;
  67. if (!dcb)
  68. return;
  69. kfree(dcb->cfg);
  70. dcb->cfg = NULL;
  71. kfree(dcb);
  72. adapter->dcb = NULL;
  73. }
  74. static void __qlcnic_dcb_get_info(struct qlcnic_adapter *adapter)
  75. {
  76. qlcnic_dcb_get_hw_capability(adapter);
  77. }
  78. static int __qlcnic_dcb_attach(struct qlcnic_adapter *adapter)
  79. {
  80. struct qlcnic_dcb *dcb = adapter->dcb;
  81. dcb->cfg = kzalloc(sizeof(struct qlcnic_dcb_cfg), GFP_ATOMIC);
  82. if (!dcb->cfg)
  83. return -ENOMEM;
  84. qlcnic_dcb_get_info(adapter);
  85. return 0;
  86. }
  87. static int __qlcnic_dcb_query_hw_capability(struct qlcnic_adapter *adapter,
  88. char *buf)
  89. {
  90. struct qlcnic_cmd_args cmd;
  91. u32 mbx_out;
  92. int err;
  93. err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DCB_QUERY_CAP);
  94. if (err)
  95. return err;
  96. err = qlcnic_issue_cmd(adapter, &cmd);
  97. if (err) {
  98. dev_err(&adapter->pdev->dev,
  99. "Failed to query DCBX capability, err %d\n", err);
  100. } else {
  101. mbx_out = cmd.rsp.arg[1];
  102. if (buf)
  103. memcpy(buf, &mbx_out, sizeof(u32));
  104. }
  105. qlcnic_free_mbx_args(&cmd);
  106. return err;
  107. }
  108. static int __qlcnic_dcb_get_capability(struct qlcnic_adapter *adapter, u32 *val)
  109. {
  110. struct qlcnic_dcb_capability *cap = &adapter->dcb->cfg->capability;
  111. u32 mbx_out;
  112. int err;
  113. memset(cap, 0, sizeof(struct qlcnic_dcb_capability));
  114. err = qlcnic_dcb_query_hw_capability(adapter, (char *)val);
  115. if (err)
  116. return err;
  117. mbx_out = *val;
  118. if (QLC_DCB_TSA_SUPPORT(mbx_out))
  119. cap->tsa_capability = true;
  120. if (QLC_DCB_ETS_SUPPORT(mbx_out))
  121. cap->ets_capability = true;
  122. cap->max_num_tc = QLC_DCB_MAX_NUM_TC(mbx_out);
  123. cap->max_ets_tc = QLC_DCB_MAX_NUM_ETS_TC(mbx_out);
  124. cap->max_pfc_tc = QLC_DCB_MAX_NUM_PFC_TC(mbx_out);
  125. if (cap->max_num_tc > QLC_DCB_MAX_TC ||
  126. cap->max_ets_tc > cap->max_num_tc ||
  127. cap->max_pfc_tc > cap->max_num_tc) {
  128. dev_err(&adapter->pdev->dev, "Invalid DCB configuration\n");
  129. return -EINVAL;
  130. }
  131. return err;
  132. }
  133. static int qlcnic_82xx_dcb_get_hw_capability(struct qlcnic_adapter *adapter)
  134. {
  135. struct qlcnic_dcb_cfg *cfg = adapter->dcb->cfg;
  136. struct qlcnic_dcb_capability *cap;
  137. u32 mbx_out;
  138. int err;
  139. err = __qlcnic_dcb_get_capability(adapter, &mbx_out);
  140. if (err)
  141. return err;
  142. cap = &cfg->capability;
  143. cap->dcb_capability = DCB_CAP_DCBX_VER_CEE | DCB_CAP_DCBX_LLD_MANAGED;
  144. if (cap->dcb_capability && cap->tsa_capability && cap->ets_capability)
  145. set_bit(__QLCNIC_DCB_STATE, &adapter->state);
  146. return err;
  147. }
  148. static int qlcnic_83xx_dcb_get_hw_capability(struct qlcnic_adapter *adapter)
  149. {
  150. struct qlcnic_dcb_capability *cap = &adapter->dcb->cfg->capability;
  151. u32 mbx_out;
  152. int err;
  153. err = __qlcnic_dcb_get_capability(adapter, &mbx_out);
  154. if (err)
  155. return err;
  156. if (mbx_out & BIT_2)
  157. cap->dcb_capability = DCB_CAP_DCBX_VER_CEE;
  158. if (mbx_out & BIT_3)
  159. cap->dcb_capability |= DCB_CAP_DCBX_VER_IEEE;
  160. if (cap->dcb_capability)
  161. cap->dcb_capability |= DCB_CAP_DCBX_LLD_MANAGED;
  162. if (cap->dcb_capability && cap->tsa_capability && cap->ets_capability)
  163. set_bit(__QLCNIC_DCB_STATE, &adapter->state);
  164. return err;
  165. }