cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mcu.c (2912B)


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