1 // SPDX-License-Identifier: ISC 2 /* 3 * Copyright (C) 2019 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> 4 */ 5 6 #include "mt76.h" 7 8 struct sk_buff * 9 __mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data, 10 int len, int data_len, gfp_t gfp) 11 { 12 const struct mt76_mcu_ops *ops = dev->mcu_ops; 13 struct sk_buff *skb; 14 15 len = max_t(int, len, data_len); 16 len = ops->headroom + len + ops->tailroom; 17 18 skb = alloc_skb(len, gfp); 19 if (!skb) 20 return NULL; 21 22 memset(skb->head, 0, len); 23 skb_reserve(skb, ops->headroom); 24 25 if (data && data_len) 26 skb_put_data(skb, data, data_len); 27 28 return skb; 29 } 30 EXPORT_SYMBOL_GPL(__mt76_mcu_msg_alloc); 31 32 struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev, 33 unsigned long expires) 34 { 35 unsigned long timeout; 36 37 if (!time_is_after_jiffies(expires)) 38 return NULL; 39 40 timeout = expires - jiffies; 41 wait_event_timeout(dev->mcu.wait, 42 (!skb_queue_empty(&dev->mcu.res_q) || 43 test_bit(MT76_MCU_RESET, &dev->phy.state)), 44 timeout); 45 return skb_dequeue(&dev->mcu.res_q); 46 } 47 EXPORT_SYMBOL_GPL(mt76_mcu_get_response); 48 49 void mt76_mcu_rx_event(struct mt76_dev *dev, struct sk_buff *skb) 50 { 51 skb_queue_tail(&dev->mcu.res_q, skb); 52 wake_up(&dev->mcu.wait); 53 } 54 EXPORT_SYMBOL_GPL(mt76_mcu_rx_event); 55 56 int mt76_mcu_send_and_get_msg(struct mt76_dev *dev, int cmd, const void *data, 57 int len, bool wait_resp, struct sk_buff **ret_skb) 58 { 59 struct sk_buff *skb; 60 61 if (dev->mcu_ops->mcu_send_msg) 62 return dev->mcu_ops->mcu_send_msg(dev, cmd, data, len, wait_resp); 63 64 skb = mt76_mcu_msg_alloc(dev, data, len); 65 if (!skb) 66 return -ENOMEM; 67 68 return mt76_mcu_skb_send_and_get_msg(dev, skb, cmd, wait_resp, ret_skb); 69 } 70 EXPORT_SYMBOL_GPL(mt76_mcu_send_and_get_msg); 71 72 int mt76_mcu_skb_send_and_get_msg(struct mt76_dev *dev, struct sk_buff *skb, 73 int cmd, bool wait_resp, 74 struct sk_buff **ret_skb) 75 { 76 unsigned int retry = 0; 77 struct sk_buff *orig_skb = NULL; 78 unsigned long expires; 79 int ret, seq; 80 81 if (ret_skb) 82 *ret_skb = NULL; 83 84 mutex_lock(&dev->mcu.mutex); 85 86 if (dev->mcu_ops->mcu_skb_prepare_msg) { 87 ret = dev->mcu_ops->mcu_skb_prepare_msg(dev, skb, cmd, &seq); 88 if (ret < 0) 89 goto out; 90 } 91 92 retry: 93 orig_skb = skb_get(skb); 94 ret = dev->mcu_ops->mcu_skb_send_msg(dev, skb, cmd, &seq); 95 if (ret < 0) 96 goto out; 97 98 if (!wait_resp) { 99 ret = 0; 100 goto out; 101 } 102 103 expires = jiffies + dev->mcu.timeout; 104 105 do { 106 skb = mt76_mcu_get_response(dev, expires); 107 if (!skb && !test_bit(MT76_MCU_RESET, &dev->phy.state) && 108 retry++ < dev->mcu_ops->max_retry) { 109 dev_err(dev->dev, "Retry message %08x (seq %d)\n", 110 cmd, seq); 111 skb = orig_skb; 112 goto retry; 113 } 114 115 ret = dev->mcu_ops->mcu_parse_response(dev, cmd, skb, seq); 116 if (!ret && ret_skb) 117 *ret_skb = skb; 118 else 119 dev_kfree_skb(skb); 120 } while (ret == -EAGAIN); 121 122 123 out: 124 dev_kfree_skb(orig_skb); 125 mutex_unlock(&dev->mcu.mutex); 126 127 return ret; 128 } 129 EXPORT_SYMBOL_GPL(mt76_mcu_skb_send_and_get_msg); 130 131 int __mt76_mcu_send_firmware(struct mt76_dev *dev, int cmd, const void *data, 132 int len, int max_len) 133 { 134 int err, cur_len; 135 136 while (len > 0) { 137 cur_len = min_t(int, max_len, len); 138 139 err = mt76_mcu_send_msg(dev, cmd, data, cur_len, false); 140 if (err) 141 return err; 142 143 data += cur_len; 144 len -= cur_len; 145 146 if (dev->queue_ops->tx_cleanup) 147 dev->queue_ops->tx_cleanup(dev, 148 dev->q_mcu[MT_MCUQ_FWDL], 149 false); 150 } 151 152 return 0; 153 } 154 EXPORT_SYMBOL_GPL(__mt76_mcu_send_firmware); 155