aq_ethtool.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. /*
  2. * aQuantia Corporation Network Driver
  3. * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms and conditions of the GNU General Public License,
  7. * version 2, as published by the Free Software Foundation.
  8. */
  9. /* File aq_ethtool.c: Definition of ethertool related functions. */
  10. #include "aq_ethtool.h"
  11. #include "aq_nic.h"
  12. #include "aq_vec.h"
  13. static void aq_ethtool_get_regs(struct net_device *ndev,
  14. struct ethtool_regs *regs, void *p)
  15. {
  16. struct aq_nic_s *aq_nic = netdev_priv(ndev);
  17. u32 regs_count = aq_nic_get_regs_count(aq_nic);
  18. memset(p, 0, regs_count * sizeof(u32));
  19. aq_nic_get_regs(aq_nic, regs, p);
  20. }
  21. static int aq_ethtool_get_regs_len(struct net_device *ndev)
  22. {
  23. struct aq_nic_s *aq_nic = netdev_priv(ndev);
  24. u32 regs_count = aq_nic_get_regs_count(aq_nic);
  25. return regs_count * sizeof(u32);
  26. }
  27. static u32 aq_ethtool_get_link(struct net_device *ndev)
  28. {
  29. return ethtool_op_get_link(ndev);
  30. }
  31. static int aq_ethtool_get_link_ksettings(struct net_device *ndev,
  32. struct ethtool_link_ksettings *cmd)
  33. {
  34. struct aq_nic_s *aq_nic = netdev_priv(ndev);
  35. aq_nic_get_link_ksettings(aq_nic, cmd);
  36. cmd->base.speed = netif_carrier_ok(ndev) ?
  37. aq_nic_get_link_speed(aq_nic) : 0U;
  38. return 0;
  39. }
  40. static int
  41. aq_ethtool_set_link_ksettings(struct net_device *ndev,
  42. const struct ethtool_link_ksettings *cmd)
  43. {
  44. struct aq_nic_s *aq_nic = netdev_priv(ndev);
  45. return aq_nic_set_link_ksettings(aq_nic, cmd);
  46. }
  47. static const char aq_ethtool_stat_names[][ETH_GSTRING_LEN] = {
  48. "InPackets",
  49. "InUCast",
  50. "InMCast",
  51. "InBCast",
  52. "InErrors",
  53. "OutPackets",
  54. "OutUCast",
  55. "OutMCast",
  56. "OutBCast",
  57. "InUCastOctets",
  58. "OutUCastOctets",
  59. "InMCastOctets",
  60. "OutMCastOctets",
  61. "InBCastOctets",
  62. "OutBCastOctets",
  63. "InOctets",
  64. "OutOctets",
  65. "InPacketsDma",
  66. "OutPacketsDma",
  67. "InOctetsDma",
  68. "OutOctetsDma",
  69. "InDroppedDma",
  70. };
  71. static const char aq_ethtool_queue_stat_names[][ETH_GSTRING_LEN] = {
  72. "Queue[%d] InPackets",
  73. "Queue[%d] OutPackets",
  74. "Queue[%d] Restarts",
  75. "Queue[%d] InJumboPackets",
  76. "Queue[%d] InLroPackets",
  77. "Queue[%d] InErrors",
  78. };
  79. static void aq_ethtool_stats(struct net_device *ndev,
  80. struct ethtool_stats *stats, u64 *data)
  81. {
  82. struct aq_nic_s *aq_nic = netdev_priv(ndev);
  83. struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
  84. memset(data, 0, (ARRAY_SIZE(aq_ethtool_stat_names) +
  85. ARRAY_SIZE(aq_ethtool_queue_stat_names) *
  86. cfg->vecs) * sizeof(u64));
  87. aq_nic_get_stats(aq_nic, data);
  88. }
  89. static void aq_ethtool_get_drvinfo(struct net_device *ndev,
  90. struct ethtool_drvinfo *drvinfo)
  91. {
  92. struct aq_nic_s *aq_nic = netdev_priv(ndev);
  93. struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
  94. struct pci_dev *pdev = to_pci_dev(ndev->dev.parent);
  95. u32 firmware_version = aq_nic_get_fw_version(aq_nic);
  96. u32 regs_count = aq_nic_get_regs_count(aq_nic);
  97. strlcat(drvinfo->driver, AQ_CFG_DRV_NAME, sizeof(drvinfo->driver));
  98. strlcat(drvinfo->version, AQ_CFG_DRV_VERSION, sizeof(drvinfo->version));
  99. snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
  100. "%u.%u.%u", firmware_version >> 24,
  101. (firmware_version >> 16) & 0xFFU, firmware_version & 0xFFFFU);
  102. strlcpy(drvinfo->bus_info, pdev ? pci_name(pdev) : "",
  103. sizeof(drvinfo->bus_info));
  104. drvinfo->n_stats = ARRAY_SIZE(aq_ethtool_stat_names) +
  105. cfg->vecs * ARRAY_SIZE(aq_ethtool_queue_stat_names);
  106. drvinfo->testinfo_len = 0;
  107. drvinfo->regdump_len = regs_count;
  108. drvinfo->eedump_len = 0;
  109. }
  110. static void aq_ethtool_get_strings(struct net_device *ndev,
  111. u32 stringset, u8 *data)
  112. {
  113. int i, si;
  114. struct aq_nic_s *aq_nic = netdev_priv(ndev);
  115. struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
  116. u8 *p = data;
  117. if (stringset == ETH_SS_STATS) {
  118. memcpy(p, *aq_ethtool_stat_names,
  119. sizeof(aq_ethtool_stat_names));
  120. p = p + sizeof(aq_ethtool_stat_names);
  121. for (i = 0; i < cfg->vecs; i++) {
  122. for (si = 0;
  123. si < ARRAY_SIZE(aq_ethtool_queue_stat_names);
  124. si++) {
  125. snprintf(p, ETH_GSTRING_LEN,
  126. aq_ethtool_queue_stat_names[si], i);
  127. p += ETH_GSTRING_LEN;
  128. }
  129. }
  130. }
  131. }
  132. static int aq_ethtool_get_sset_count(struct net_device *ndev, int stringset)
  133. {
  134. int ret = 0;
  135. struct aq_nic_s *aq_nic = netdev_priv(ndev);
  136. struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
  137. switch (stringset) {
  138. case ETH_SS_STATS:
  139. ret = ARRAY_SIZE(aq_ethtool_stat_names) +
  140. cfg->vecs * ARRAY_SIZE(aq_ethtool_queue_stat_names);
  141. break;
  142. default:
  143. ret = -EOPNOTSUPP;
  144. }
  145. return ret;
  146. }
  147. static u32 aq_ethtool_get_rss_indir_size(struct net_device *ndev)
  148. {
  149. return AQ_CFG_RSS_INDIRECTION_TABLE_MAX;
  150. }
  151. static u32 aq_ethtool_get_rss_key_size(struct net_device *ndev)
  152. {
  153. struct aq_nic_s *aq_nic = netdev_priv(ndev);
  154. struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
  155. return sizeof(cfg->aq_rss.hash_secret_key);
  156. }
  157. static int aq_ethtool_get_rss(struct net_device *ndev, u32 *indir, u8 *key,
  158. u8 *hfunc)
  159. {
  160. struct aq_nic_s *aq_nic = netdev_priv(ndev);
  161. struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
  162. unsigned int i = 0U;
  163. if (hfunc)
  164. *hfunc = ETH_RSS_HASH_TOP; /* Toeplitz */
  165. if (indir) {
  166. for (i = 0; i < AQ_CFG_RSS_INDIRECTION_TABLE_MAX; i++)
  167. indir[i] = cfg->aq_rss.indirection_table[i];
  168. }
  169. if (key)
  170. memcpy(key, cfg->aq_rss.hash_secret_key,
  171. sizeof(cfg->aq_rss.hash_secret_key));
  172. return 0;
  173. }
  174. static int aq_ethtool_get_rxnfc(struct net_device *ndev,
  175. struct ethtool_rxnfc *cmd,
  176. u32 *rule_locs)
  177. {
  178. struct aq_nic_s *aq_nic = netdev_priv(ndev);
  179. struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
  180. int err = 0;
  181. switch (cmd->cmd) {
  182. case ETHTOOL_GRXRINGS:
  183. cmd->data = cfg->vecs;
  184. break;
  185. default:
  186. err = -EOPNOTSUPP;
  187. break;
  188. }
  189. return err;
  190. }
  191. static int aq_ethtool_get_coalesce(struct net_device *ndev,
  192. struct ethtool_coalesce *coal)
  193. {
  194. struct aq_nic_s *aq_nic = netdev_priv(ndev);
  195. struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
  196. if (cfg->itr == AQ_CFG_INTERRUPT_MODERATION_ON ||
  197. cfg->itr == AQ_CFG_INTERRUPT_MODERATION_AUTO) {
  198. coal->rx_coalesce_usecs = cfg->rx_itr;
  199. coal->tx_coalesce_usecs = cfg->tx_itr;
  200. coal->rx_max_coalesced_frames = 0;
  201. coal->tx_max_coalesced_frames = 0;
  202. } else {
  203. coal->rx_coalesce_usecs = 0;
  204. coal->tx_coalesce_usecs = 0;
  205. coal->rx_max_coalesced_frames = 1;
  206. coal->tx_max_coalesced_frames = 1;
  207. }
  208. return 0;
  209. }
  210. static int aq_ethtool_set_coalesce(struct net_device *ndev,
  211. struct ethtool_coalesce *coal)
  212. {
  213. struct aq_nic_s *aq_nic = netdev_priv(ndev);
  214. struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
  215. /* This is not yet supported
  216. */
  217. if (coal->use_adaptive_rx_coalesce || coal->use_adaptive_tx_coalesce)
  218. return -EOPNOTSUPP;
  219. /* Atlantic only supports timing based coalescing
  220. */
  221. if (coal->rx_max_coalesced_frames > 1 ||
  222. coal->rx_coalesce_usecs_irq ||
  223. coal->rx_max_coalesced_frames_irq)
  224. return -EOPNOTSUPP;
  225. if (coal->tx_max_coalesced_frames > 1 ||
  226. coal->tx_coalesce_usecs_irq ||
  227. coal->tx_max_coalesced_frames_irq)
  228. return -EOPNOTSUPP;
  229. /* We do not support frame counting. Check this
  230. */
  231. if (!(coal->rx_max_coalesced_frames == !coal->rx_coalesce_usecs))
  232. return -EOPNOTSUPP;
  233. if (!(coal->tx_max_coalesced_frames == !coal->tx_coalesce_usecs))
  234. return -EOPNOTSUPP;
  235. if (coal->rx_coalesce_usecs > AQ_CFG_INTERRUPT_MODERATION_USEC_MAX ||
  236. coal->tx_coalesce_usecs > AQ_CFG_INTERRUPT_MODERATION_USEC_MAX)
  237. return -EINVAL;
  238. cfg->itr = AQ_CFG_INTERRUPT_MODERATION_ON;
  239. cfg->rx_itr = coal->rx_coalesce_usecs;
  240. cfg->tx_itr = coal->tx_coalesce_usecs;
  241. return aq_nic_update_interrupt_moderation_settings(aq_nic);
  242. }
  243. static int aq_ethtool_nway_reset(struct net_device *ndev)
  244. {
  245. struct aq_nic_s *aq_nic = netdev_priv(ndev);
  246. if (unlikely(!aq_nic->aq_fw_ops->renegotiate))
  247. return -EOPNOTSUPP;
  248. if (netif_running(ndev))
  249. return aq_nic->aq_fw_ops->renegotiate(aq_nic->aq_hw);
  250. return 0;
  251. }
  252. static void aq_ethtool_get_pauseparam(struct net_device *ndev,
  253. struct ethtool_pauseparam *pause)
  254. {
  255. struct aq_nic_s *aq_nic = netdev_priv(ndev);
  256. pause->autoneg = 0;
  257. if (aq_nic->aq_hw->aq_nic_cfg->flow_control & AQ_NIC_FC_RX)
  258. pause->rx_pause = 1;
  259. if (aq_nic->aq_hw->aq_nic_cfg->flow_control & AQ_NIC_FC_TX)
  260. pause->tx_pause = 1;
  261. }
  262. static int aq_ethtool_set_pauseparam(struct net_device *ndev,
  263. struct ethtool_pauseparam *pause)
  264. {
  265. struct aq_nic_s *aq_nic = netdev_priv(ndev);
  266. int err = 0;
  267. if (!aq_nic->aq_fw_ops->set_flow_control)
  268. return -EOPNOTSUPP;
  269. if (pause->autoneg == AUTONEG_ENABLE)
  270. return -EOPNOTSUPP;
  271. if (pause->rx_pause)
  272. aq_nic->aq_hw->aq_nic_cfg->flow_control |= AQ_NIC_FC_RX;
  273. else
  274. aq_nic->aq_hw->aq_nic_cfg->flow_control &= ~AQ_NIC_FC_RX;
  275. if (pause->tx_pause)
  276. aq_nic->aq_hw->aq_nic_cfg->flow_control |= AQ_NIC_FC_TX;
  277. else
  278. aq_nic->aq_hw->aq_nic_cfg->flow_control &= ~AQ_NIC_FC_TX;
  279. err = aq_nic->aq_fw_ops->set_flow_control(aq_nic->aq_hw);
  280. return err;
  281. }
  282. static void aq_get_ringparam(struct net_device *ndev,
  283. struct ethtool_ringparam *ring)
  284. {
  285. struct aq_nic_s *aq_nic = netdev_priv(ndev);
  286. struct aq_nic_cfg_s *aq_nic_cfg = aq_nic_get_cfg(aq_nic);
  287. ring->rx_pending = aq_nic_cfg->rxds;
  288. ring->tx_pending = aq_nic_cfg->txds;
  289. ring->rx_max_pending = aq_nic_cfg->aq_hw_caps->rxds_max;
  290. ring->tx_max_pending = aq_nic_cfg->aq_hw_caps->txds_max;
  291. }
  292. static int aq_set_ringparam(struct net_device *ndev,
  293. struct ethtool_ringparam *ring)
  294. {
  295. int err = 0;
  296. bool ndev_running = false;
  297. struct aq_nic_s *aq_nic = netdev_priv(ndev);
  298. struct aq_nic_cfg_s *aq_nic_cfg = aq_nic_get_cfg(aq_nic);
  299. const struct aq_hw_caps_s *hw_caps = aq_nic_cfg->aq_hw_caps;
  300. if (ring->rx_mini_pending || ring->rx_jumbo_pending) {
  301. err = -EOPNOTSUPP;
  302. goto err_exit;
  303. }
  304. if (netif_running(ndev)) {
  305. ndev_running = true;
  306. dev_close(ndev);
  307. }
  308. aq_nic_free_vectors(aq_nic);
  309. aq_nic_cfg->rxds = max(ring->rx_pending, hw_caps->rxds_min);
  310. aq_nic_cfg->rxds = min(aq_nic_cfg->rxds, hw_caps->rxds_max);
  311. aq_nic_cfg->rxds = ALIGN(aq_nic_cfg->rxds, AQ_HW_RXD_MULTIPLE);
  312. aq_nic_cfg->txds = max(ring->tx_pending, hw_caps->txds_min);
  313. aq_nic_cfg->txds = min(aq_nic_cfg->txds, hw_caps->txds_max);
  314. aq_nic_cfg->txds = ALIGN(aq_nic_cfg->txds, AQ_HW_TXD_MULTIPLE);
  315. for (aq_nic->aq_vecs = 0; aq_nic->aq_vecs < aq_nic_cfg->vecs;
  316. aq_nic->aq_vecs++) {
  317. aq_nic->aq_vec[aq_nic->aq_vecs] =
  318. aq_vec_alloc(aq_nic, aq_nic->aq_vecs, aq_nic_cfg);
  319. if (unlikely(!aq_nic->aq_vec[aq_nic->aq_vecs])) {
  320. err = -ENOMEM;
  321. goto err_exit;
  322. }
  323. }
  324. if (ndev_running)
  325. err = dev_open(ndev);
  326. err_exit:
  327. return err;
  328. }
  329. const struct ethtool_ops aq_ethtool_ops = {
  330. .get_link = aq_ethtool_get_link,
  331. .get_regs_len = aq_ethtool_get_regs_len,
  332. .get_regs = aq_ethtool_get_regs,
  333. .get_drvinfo = aq_ethtool_get_drvinfo,
  334. .get_strings = aq_ethtool_get_strings,
  335. .get_rxfh_indir_size = aq_ethtool_get_rss_indir_size,
  336. .nway_reset = aq_ethtool_nway_reset,
  337. .get_ringparam = aq_get_ringparam,
  338. .set_ringparam = aq_set_ringparam,
  339. .get_pauseparam = aq_ethtool_get_pauseparam,
  340. .set_pauseparam = aq_ethtool_set_pauseparam,
  341. .get_rxfh_key_size = aq_ethtool_get_rss_key_size,
  342. .get_rxfh = aq_ethtool_get_rss,
  343. .get_rxnfc = aq_ethtool_get_rxnfc,
  344. .get_sset_count = aq_ethtool_get_sset_count,
  345. .get_ethtool_stats = aq_ethtool_stats,
  346. .get_link_ksettings = aq_ethtool_get_link_ksettings,
  347. .set_link_ksettings = aq_ethtool_set_link_ksettings,
  348. .get_coalesce = aq_ethtool_get_coalesce,
  349. .set_coalesce = aq_ethtool_set_coalesce,
  350. };