Exemple #1
0
static int
mt76_mcu_msg_send(struct mt76_dev *dev, struct sk_buff *skb, enum mcu_cmd cmd)
{
	unsigned long expires = jiffies + HZ;
	u32 info;
	int ret;
	u8 seq;

	if (!skb)
		return -EINVAL;

	mutex_lock(&dev->mcu.mutex);

	seq = ++dev->mcu.msg_seq & 0xf;
	if (!seq)
		seq = ++dev->mcu.msg_seq & 0xf;

	info = MT_MCU_MSG_TYPE_CMD |
	       MT76_SET(MT_MCU_MSG_CMD_TYPE, cmd) |
	       MT76_SET(MT_MCU_MSG_CMD_SEQ, seq) |
	       MT76_SET(MT_MCU_MSG_PORT, CPU_TX_PORT) |
	       MT76_SET(MT_MCU_MSG_LEN, skb->len);

	ret = __mt76_tx_queue_skb(dev, MT_TXQ_MCU, skb, info);
	if (ret)
		goto out;

	while (1) {
		u32 *rxfce;
		bool check_seq = false;

		skb = mt76_mcu_get_response(dev, expires);
		if (!skb) {
			printk("MCU message %d (seq %d) timed out\n", cmd,
			       MT76_GET(MT_MCU_MSG_CMD_SEQ, info));
			ret = -ETIMEDOUT;
			break;
		}

		rxfce = (u32 *) skb->cb;

		if (seq == MT76_GET(MT_RX_FCE_INFO_CMD_SEQ, *rxfce))
			check_seq = true;

		dev_kfree_skb(skb);
		if (check_seq)
			break;
	}

out:
	mutex_unlock(&dev->mcu.mutex);

	return ret;
}
Exemple #2
0
static int mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb,
			       int cmd, int query, int dest,
			       struct sk_buff **skb_ret)
{
	unsigned long expires = jiffies + 10 * HZ;
	struct mt7615_mcu_rxd *rxd;
	int ret, seq;

	mutex_lock(&dev->mt76.mmio.mcu.mutex);

	ret = __mt7615_mcu_msg_send(dev, skb, cmd, query, dest, &seq);
	if (ret)
		goto out;

	while (1) {
		skb = mt76_mcu_get_response(&dev->mt76, expires);
		if (!skb) {
			dev_err(dev->mt76.dev, "Message %d (seq %d) timeout\n",
				cmd, seq);
			ret = -ETIMEDOUT;
			break;
		}

		rxd = (struct mt7615_mcu_rxd *)skb->data;
		if (seq != rxd->seq)
			continue;

		if (skb_ret) {
			int hdr_len = sizeof(*rxd);

			if (!test_bit(MT76_STATE_MCU_RUNNING,
				      &dev->mt76.state))
				hdr_len -= 4;
			skb_pull(skb, hdr_len);
			*skb_ret = skb;
		} else {
			dev_kfree_skb(skb);
		}

		break;
	}

out:
	mutex_unlock(&dev->mt76.mmio.mcu.mutex);

	return ret;
}
Exemple #3
0
static int
mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb, int cmd,
		    int query)
{
	struct mt76_dev *mdev = &dev->mt76;
	unsigned long expires = jiffies + 3 * HZ;
	struct mt7603_mcu_rxd *rxd;
	int ret, seq;

	mutex_lock(&mdev->mmio.mcu.mutex);

	ret = __mt7603_mcu_msg_send(dev, skb, cmd, query, &seq);
	if (ret)
		goto out;

	while (1) {
		bool check_seq = false;

		skb = mt76_mcu_get_response(&dev->mt76, expires);
		if (!skb) {
			dev_err(mdev->dev,
				"MCU message %d (seq %d) timed out\n",
				cmd, seq);
			dev->mcu_hang = MT7603_WATCHDOG_TIMEOUT;
			ret = -ETIMEDOUT;
			break;
		}

		rxd = (struct mt7603_mcu_rxd *)skb->data;
		if (seq == rxd->seq)
			check_seq = true;

		dev_kfree_skb(skb);

		if (check_seq)
			break;
	}

out:
	mutex_unlock(&mdev->mmio.mcu.mutex);

	return ret;
}