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; }
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; }
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; }