18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: ISC
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2019 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#include "mt76.h"
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_cistruct sk_buff *
98c2ecf20Sopenharmony_cimt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data,
108c2ecf20Sopenharmony_ci		   int data_len)
118c2ecf20Sopenharmony_ci{
128c2ecf20Sopenharmony_ci	const struct mt76_mcu_ops *ops = dev->mcu_ops;
138c2ecf20Sopenharmony_ci	int length = ops->headroom + data_len + ops->tailroom;
148c2ecf20Sopenharmony_ci	struct sk_buff *skb;
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci	skb = alloc_skb(length, GFP_KERNEL);
178c2ecf20Sopenharmony_ci	if (!skb)
188c2ecf20Sopenharmony_ci		return NULL;
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci	memset(skb->head, 0, length);
218c2ecf20Sopenharmony_ci	skb_reserve(skb, ops->headroom);
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci	if (data && data_len)
248c2ecf20Sopenharmony_ci		skb_put_data(skb, data, data_len);
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci	return skb;
278c2ecf20Sopenharmony_ci}
288c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(mt76_mcu_msg_alloc);
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_cistruct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev,
318c2ecf20Sopenharmony_ci				      unsigned long expires)
328c2ecf20Sopenharmony_ci{
338c2ecf20Sopenharmony_ci	unsigned long timeout;
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	if (!time_is_after_jiffies(expires))
368c2ecf20Sopenharmony_ci		return NULL;
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci	timeout = expires - jiffies;
398c2ecf20Sopenharmony_ci	wait_event_timeout(dev->mcu.wait,
408c2ecf20Sopenharmony_ci			   (!skb_queue_empty(&dev->mcu.res_q) ||
418c2ecf20Sopenharmony_ci			    test_bit(MT76_MCU_RESET, &dev->phy.state)),
428c2ecf20Sopenharmony_ci			   timeout);
438c2ecf20Sopenharmony_ci	return skb_dequeue(&dev->mcu.res_q);
448c2ecf20Sopenharmony_ci}
458c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(mt76_mcu_get_response);
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_civoid mt76_mcu_rx_event(struct mt76_dev *dev, struct sk_buff *skb)
488c2ecf20Sopenharmony_ci{
498c2ecf20Sopenharmony_ci	skb_queue_tail(&dev->mcu.res_q, skb);
508c2ecf20Sopenharmony_ci	wake_up(&dev->mcu.wait);
518c2ecf20Sopenharmony_ci}
528c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(mt76_mcu_rx_event);
53