mcu.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. // SPDX-License-Identifier: ISC
  2. /*
  3. * Copyright (C) 2019 Lorenzo Bianconi <[email protected]>
  4. */
  5. #include "mt76.h"
  6. struct sk_buff *
  7. __mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data,
  8. int len, int data_len, gfp_t gfp)
  9. {
  10. const struct mt76_mcu_ops *ops = dev->mcu_ops;
  11. struct sk_buff *skb;
  12. len = max_t(int, len, data_len);
  13. len = ops->headroom + len + ops->tailroom;
  14. skb = alloc_skb(len, gfp);
  15. if (!skb)
  16. return NULL;
  17. memset(skb->head, 0, len);
  18. skb_reserve(skb, ops->headroom);
  19. if (data && data_len)
  20. skb_put_data(skb, data, data_len);
  21. return skb;
  22. }
  23. EXPORT_SYMBOL_GPL(__mt76_mcu_msg_alloc);
  24. struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev,
  25. unsigned long expires)
  26. {
  27. unsigned long timeout;
  28. if (!time_is_after_jiffies(expires))
  29. return NULL;
  30. timeout = expires - jiffies;
  31. wait_event_timeout(dev->mcu.wait,
  32. (!skb_queue_empty(&dev->mcu.res_q) ||
  33. test_bit(MT76_MCU_RESET, &dev->phy.state)),
  34. timeout);
  35. return skb_dequeue(&dev->mcu.res_q);
  36. }
  37. EXPORT_SYMBOL_GPL(mt76_mcu_get_response);
  38. void mt76_mcu_rx_event(struct mt76_dev *dev, struct sk_buff *skb)
  39. {
  40. skb_queue_tail(&dev->mcu.res_q, skb);
  41. wake_up(&dev->mcu.wait);
  42. }
  43. EXPORT_SYMBOL_GPL(mt76_mcu_rx_event);
  44. int mt76_mcu_send_and_get_msg(struct mt76_dev *dev, int cmd, const void *data,
  45. int len, bool wait_resp, struct sk_buff **ret_skb)
  46. {
  47. struct sk_buff *skb;
  48. if (dev->mcu_ops->mcu_send_msg)
  49. return dev->mcu_ops->mcu_send_msg(dev, cmd, data, len, wait_resp);
  50. skb = mt76_mcu_msg_alloc(dev, data, len);
  51. if (!skb)
  52. return -ENOMEM;
  53. return mt76_mcu_skb_send_and_get_msg(dev, skb, cmd, wait_resp, ret_skb);
  54. }
  55. EXPORT_SYMBOL_GPL(mt76_mcu_send_and_get_msg);
  56. int mt76_mcu_skb_send_and_get_msg(struct mt76_dev *dev, struct sk_buff *skb,
  57. int cmd, bool wait_resp,
  58. struct sk_buff **ret_skb)
  59. {
  60. unsigned long expires;
  61. int ret, seq;
  62. if (ret_skb)
  63. *ret_skb = NULL;
  64. mutex_lock(&dev->mcu.mutex);
  65. ret = dev->mcu_ops->mcu_skb_send_msg(dev, skb, cmd, &seq);
  66. if (ret < 0)
  67. goto out;
  68. if (!wait_resp) {
  69. ret = 0;
  70. goto out;
  71. }
  72. expires = jiffies + dev->mcu.timeout;
  73. do {
  74. skb = mt76_mcu_get_response(dev, expires);
  75. ret = dev->mcu_ops->mcu_parse_response(dev, cmd, skb, seq);
  76. if (!ret && ret_skb)
  77. *ret_skb = skb;
  78. else
  79. dev_kfree_skb(skb);
  80. } while (ret == -EAGAIN);
  81. out:
  82. mutex_unlock(&dev->mcu.mutex);
  83. return ret;
  84. }
  85. EXPORT_SYMBOL_GPL(mt76_mcu_skb_send_and_get_msg);
  86. int __mt76_mcu_send_firmware(struct mt76_dev *dev, int cmd, const void *data,
  87. int len, int max_len)
  88. {
  89. int err, cur_len;
  90. while (len > 0) {
  91. cur_len = min_t(int, max_len, len);
  92. err = mt76_mcu_send_msg(dev, cmd, data, cur_len, false);
  93. if (err)
  94. return err;
  95. data += cur_len;
  96. len -= cur_len;
  97. if (dev->queue_ops->tx_cleanup)
  98. dev->queue_ops->tx_cleanup(dev,
  99. dev->q_mcu[MT_MCUQ_FWDL],
  100. false);
  101. }
  102. return 0;
  103. }
  104. EXPORT_SYMBOL_GPL(__mt76_mcu_send_firmware);