Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  mt76x02_mcu.c   Sprache: C

 
// SPDX-License-Identifier: ISC
/*
 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
 */


#include <linux/kernel.h>
#include <linux/firmware.h>
#include <linux/delay.h>

#include "mt76x02_mcu.h"

int mt76x02_mcu_parse_response(struct mt76_dev *mdev, int cmd,
          struct sk_buff *skb, int seq)
{
 struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
 u32 *rxfce;

 if (!skb) {
  dev_err(mdev->dev, "MCU message %02x (seq %d) timed out\n",
   abs(cmd), seq);
  dev->mcu_timeout = 1;
  return -ETIMEDOUT;
 }

 rxfce = (u32 *)skb->cb;
 if (seq != FIELD_GET(MT_RX_FCE_INFO_CMD_SEQ, *rxfce))
  return -EAGAIN;

 return 0;
}
EXPORT_SYMBOL_GPL(mt76x02_mcu_parse_response);

int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data,
    int len, bool wait_resp)
{
 struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
 unsigned long expires = jiffies + HZ;
 struct sk_buff *skb;
 u32 tx_info;
 int ret;
 u8 seq;

 if (dev->mcu_timeout)
  return -EIO;

 skb = mt76_mcu_msg_alloc(mdev, data, len);
 if (!skb)
  return -ENOMEM;

 mutex_lock(&mdev->mcu.mutex);

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

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

 ret = mt76_tx_queue_skb_raw(dev, mdev->q_mcu[MT_MCUQ_WM], skb, tx_info);
 if (ret)
  goto out;

 while (wait_resp) {
  skb = mt76_mcu_get_response(&dev->mt76, expires);
  ret = mt76x02_mcu_parse_response(mdev, cmd, skb, seq);
  dev_kfree_skb(skb);
  if (ret != -EAGAIN)
   break;
 }

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

 return ret;
}
EXPORT_SYMBOL_GPL(mt76x02_mcu_msg_send);

int mt76x02_mcu_function_select(struct mt76x02_dev *dev, enum mcu_function func,
    u32 val)
{
 struct {
  __le32 id;
  __le32 value;
 } __packed __aligned(4) msg = {
  .id = cpu_to_le32(func),
  .value = cpu_to_le32(val),
 };
 bool wait = false;

 if (func != Q_SELECT)
  wait = true;

 return mt76_mcu_send_msg(&dev->mt76, CMD_FUN_SET_OP, &msg,
     sizeof(msg), wait);
}
EXPORT_SYMBOL_GPL(mt76x02_mcu_function_select);

int mt76x02_mcu_set_radio_state(struct mt76x02_dev *dev, bool on)
{
 struct {
  __le32 mode;
  __le32 level;
 } __packed __aligned(4) msg = {
  .mode = cpu_to_le32(on ? RADIO_ON : RADIO_OFF),
  .level = cpu_to_le32(0),
 };

 return mt76_mcu_send_msg(&dev->mt76, CMD_POWER_SAVING_OP, &msg,
     sizeof(msg), false);
}
EXPORT_SYMBOL_GPL(mt76x02_mcu_set_radio_state);

int mt76x02_mcu_calibrate(struct mt76x02_dev *dev, int type, u32 param)
{
 struct {
  __le32 id;
  __le32 value;
 } __packed __aligned(4) msg = {
  .id = cpu_to_le32(type),
  .value = cpu_to_le32(param),
 };
 bool is_mt76x2e = mt76_is_mmio(&dev->mt76) && is_mt76x2(dev);
 int ret;

 if (is_mt76x2e)
  mt76_rmw(dev, MT_MCU_COM_REG0, BIT(31), 0);

 ret = mt76_mcu_send_msg(&dev->mt76, CMD_CALIBRATION_OP, &msg,
    sizeof(msg), true);
 if (ret)
  return ret;

 if (is_mt76x2e &&
     WARN_ON(!mt76_poll_msec(dev, MT_MCU_COM_REG0,
        BIT(31), BIT(31), 100)))
  return -ETIMEDOUT;

 return 0;
}
EXPORT_SYMBOL_GPL(mt76x02_mcu_calibrate);

int mt76x02_mcu_cleanup(struct mt76x02_dev *dev)
{
 struct sk_buff *skb;

 mt76_wr(dev, MT_MCU_INT_LEVEL, 1);
 usleep_range(20000, 30000);

 while ((skb = skb_dequeue(&dev->mt76.mcu.res_q)) != NULL)
  dev_kfree_skb(skb);

 return 0;
}
EXPORT_SYMBOL_GPL(mt76x02_mcu_cleanup);

void mt76x02_set_ethtool_fwver(struct mt76x02_dev *dev,
          const struct mt76x02_fw_header *h)
{
 u16 bld = le16_to_cpu(h->build_ver);
 u16 ver = le16_to_cpu(h->fw_ver);

 snprintf(dev->mt76.hw->wiphy->fw_version,
   sizeof(dev->mt76.hw->wiphy->fw_version),
   "%d.%d.%02d-b%x",
   (ver >> 12) & 0xf, (ver >> 8) & 0xf, ver & 0xf, bld);
}
EXPORT_SYMBOL_GPL(mt76x02_set_ethtool_fwver);

Messung V0.5
C=91 H=97 G=93

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge