1 // SPDX-License-Identifier: ISC
3 * Copyright (C) 2019 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
9 mt76_mcu_msg_alloc(struct mt76_dev
*dev
, const void *data
,
12 const struct mt76_mcu_ops
*ops
= dev
->mcu_ops
;
13 int length
= ops
->headroom
+ data_len
+ ops
->tailroom
;
16 skb
= alloc_skb(length
, GFP_KERNEL
);
20 memset(skb
->head
, 0, length
);
21 skb_reserve(skb
, ops
->headroom
);
24 skb_put_data(skb
, data
, data_len
);
28 EXPORT_SYMBOL_GPL(mt76_mcu_msg_alloc
);
30 struct sk_buff
*mt76_mcu_get_response(struct mt76_dev
*dev
,
31 unsigned long expires
)
33 unsigned long timeout
;
35 if (!time_is_after_jiffies(expires
))
38 timeout
= expires
- jiffies
;
39 wait_event_timeout(dev
->mcu
.wait
,
40 (!skb_queue_empty(&dev
->mcu
.res_q
) ||
41 test_bit(MT76_MCU_RESET
, &dev
->phy
.state
)),
43 return skb_dequeue(&dev
->mcu
.res_q
);
45 EXPORT_SYMBOL_GPL(mt76_mcu_get_response
);
47 void mt76_mcu_rx_event(struct mt76_dev
*dev
, struct sk_buff
*skb
)
49 skb_queue_tail(&dev
->mcu
.res_q
, skb
);
50 wake_up(&dev
->mcu
.wait
);
52 EXPORT_SYMBOL_GPL(mt76_mcu_rx_event
);
54 int mt76_mcu_send_and_get_msg(struct mt76_dev
*dev
, int cmd
, const void *data
,
55 int len
, bool wait_resp
, struct sk_buff
**ret_skb
)
59 if (dev
->mcu_ops
->mcu_send_msg
)
60 return dev
->mcu_ops
->mcu_send_msg(dev
, cmd
, data
, len
, wait_resp
);
62 skb
= mt76_mcu_msg_alloc(dev
, data
, len
);
66 return mt76_mcu_skb_send_and_get_msg(dev
, skb
, cmd
, wait_resp
, ret_skb
);
68 EXPORT_SYMBOL_GPL(mt76_mcu_send_and_get_msg
);
70 int mt76_mcu_skb_send_and_get_msg(struct mt76_dev
*dev
, struct sk_buff
*skb
,
71 int cmd
, bool wait_resp
,
72 struct sk_buff
**ret_skb
)
74 unsigned long expires
;
80 mutex_lock(&dev
->mcu
.mutex
);
82 ret
= dev
->mcu_ops
->mcu_skb_send_msg(dev
, skb
, cmd
, &seq
);
91 expires
= jiffies
+ dev
->mcu
.timeout
;
94 skb
= mt76_mcu_get_response(dev
, expires
);
95 ret
= dev
->mcu_ops
->mcu_parse_response(dev
, cmd
, skb
, seq
);
100 } while (ret
== -EAGAIN
);
103 mutex_unlock(&dev
->mcu
.mutex
);
107 EXPORT_SYMBOL_GPL(mt76_mcu_skb_send_and_get_msg
);
109 int mt76_mcu_send_firmware(struct mt76_dev
*dev
, int cmd
, const void *data
,
115 cur_len
= min_t(int, 4096 - dev
->mcu_ops
->headroom
, len
);
117 err
= mt76_mcu_send_msg(dev
, cmd
, data
, cur_len
, false);
124 if (dev
->queue_ops
->tx_cleanup
)
125 dev
->queue_ops
->tx_cleanup(dev
,
126 dev
->q_mcu
[MT_MCUQ_FWDL
],
132 EXPORT_SYMBOL_GPL(mt76_mcu_send_firmware
);