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


Quelle  t7xx_port_ctrl_msg.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2021, MediaTek Inc.
 * Copyright (c) 2021-2022, Intel Corporation.
 *
 * Authors:
 *  Haijun Liu <haijun.liu@mediatek.com>
 *  Ricardo Martinez <ricardo.martinez@linux.intel.com>
 *  Moises Veleta <moises.veleta@intel.com>
 *
 * Contributors:
 *  Amir Hanania <amir.hanania@intel.com>
 *  Chiranjeevi Rapolu <chiranjeevi.rapolu@intel.com>
 *  Eliot Lee <eliot.lee@intel.com>
 *  Sreehari Kancharla <sreehari.kancharla@intel.com>
 */


#include <linux/bitfield.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/kthread.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>

#include "t7xx_port.h"
#include "t7xx_port_proxy.h"
#include "t7xx_state_monitor.h"

#define PORT_MSG_VERSION GENMASK(31, 16)
#define PORT_MSG_PRT_CNT GENMASK(15, 0)

struct port_msg {
 __le32 head_pattern;
 __le32 info;
 __le32 tail_pattern;
 __le32 data[];
};

static int port_ctl_send_msg_to_md(struct t7xx_port *port, unsigned int msg, unsigned int ex_msg)
{
 struct sk_buff *skb;
 int ret;

 skb = t7xx_ctrl_alloc_skb(0);
 if (!skb)
  return -ENOMEM;

 ret = t7xx_port_send_ctl_skb(port, skb, msg, ex_msg);
 if (ret)
  dev_kfree_skb_any(skb);

 return ret;
}

static int fsm_ee_message_handler(struct t7xx_port *port, struct t7xx_fsm_ctl *ctl,
      struct sk_buff *skb)
{
 struct ctrl_msg_header *ctrl_msg_h = (struct ctrl_msg_header *)skb->data;
 struct device *dev = &ctl->md->t7xx_dev->pdev->dev;
 enum md_state md_state;
 int ret = -EINVAL;

 md_state = t7xx_fsm_get_md_state(ctl);
 if (md_state != MD_STATE_EXCEPTION) {
  dev_err(dev, "Receive invalid MD_EX %x when MD state is %d\n",
   ctrl_msg_h->ex_msg, md_state);
  return -EINVAL;
 }

 switch (le32_to_cpu(ctrl_msg_h->ctrl_msg_id)) {
 case CTL_ID_MD_EX:
  if (le32_to_cpu(ctrl_msg_h->ex_msg) != MD_EX_CHK_ID) {
   dev_err(dev, "Receive invalid MD_EX %x\n", ctrl_msg_h->ex_msg);
   break;
  }

  ret = port_ctl_send_msg_to_md(port, CTL_ID_MD_EX, MD_EX_CHK_ID);
  if (ret) {
   dev_err(dev, "Failed to send exception message to modem\n");
   break;
  }

  ret = t7xx_fsm_append_event(ctl, FSM_EVENT_MD_EX, NULL, 0);
  if (ret)
   dev_err(dev, "Failed to append Modem Exception event");

  break;

 case CTL_ID_MD_EX_ACK:
  if (le32_to_cpu(ctrl_msg_h->ex_msg) != MD_EX_CHK_ACK_ID) {
   dev_err(dev, "Receive invalid MD_EX_ACK %x\n", ctrl_msg_h->ex_msg);
   break;
  }

  ret = t7xx_fsm_append_event(ctl, FSM_EVENT_MD_EX_REC_OK, NULL, 0);
  if (ret)
   dev_err(dev, "Failed to append Modem Exception Received event");

  break;

 case CTL_ID_MD_EX_PASS:
  ret = t7xx_fsm_append_event(ctl, FSM_EVENT_MD_EX_PASS, NULL, 0);
  if (ret)
   dev_err(dev, "Failed to append Modem Exception Passed event");

  break;

 case CTL_ID_DRV_VER_ERROR:
  dev_err(dev, "AP/MD driver version mismatch\n");
 }

 return ret;
}

/**
 * t7xx_port_enum_msg_handler() - Parse the port enumeration message to create/remove nodes.
 * @md: Modem context.
 * @msg: Message.
 *
 * Used to control create/remove device node.
 *
 * Return:
 * * 0 - Success.
 * * -EFAULT - Message check failure.
 */

int t7xx_port_enum_msg_handler(struct t7xx_modem *md, void *msg)
{
 struct device *dev = &md->t7xx_dev->pdev->dev;
 unsigned int version, port_count, i;
 struct port_msg *port_msg = msg;

 version = FIELD_GET(PORT_MSG_VERSION, le32_to_cpu(port_msg->info));
 if (version != PORT_ENUM_VER ||
     le32_to_cpu(port_msg->head_pattern) != PORT_ENUM_HEAD_PATTERN ||
     le32_to_cpu(port_msg->tail_pattern) != PORT_ENUM_TAIL_PATTERN) {
  dev_err(dev, "Invalid port control message %x:%x:%x\n",
   version, le32_to_cpu(port_msg->head_pattern),
   le32_to_cpu(port_msg->tail_pattern));
  return -EFAULT;
 }

 port_count = FIELD_GET(PORT_MSG_PRT_CNT, le32_to_cpu(port_msg->info));
 for (i = 0; i < port_count; i++) {
  u32 port_info = le32_to_cpu(port_msg->data[i]);
  unsigned int ch_id;
  bool en_flag;

  ch_id = FIELD_GET(PORT_INFO_CH_ID, port_info);
  en_flag = port_info & PORT_INFO_ENFLG;
  if (t7xx_port_proxy_chl_enable_disable(md->port_prox, ch_id, en_flag))
   dev_dbg(dev, "Port:%x not found\n", ch_id);
 }

 return 0;
}

static int control_msg_handler(struct t7xx_port *port, struct sk_buff *skb)
{
 const struct t7xx_port_conf *port_conf = port->port_conf;
 struct t7xx_fsm_ctl *ctl = port->t7xx_dev->md->fsm_ctl;
 struct ctrl_msg_header *ctrl_msg_h;
 int ret = 0;

 ctrl_msg_h = (struct ctrl_msg_header *)skb->data;
 switch (le32_to_cpu(ctrl_msg_h->ctrl_msg_id)) {
 case CTL_ID_HS2_MSG:
  skb_pull(skb, sizeof(*ctrl_msg_h));

  if (port_conf->rx_ch == PORT_CH_CONTROL_RX ||
      port_conf->rx_ch == PORT_CH_AP_CONTROL_RX) {
   int event = port_conf->rx_ch == PORT_CH_CONTROL_RX ?
        FSM_EVENT_MD_HS2 : FSM_EVENT_AP_HS2;

   ret = t7xx_fsm_append_event(ctl, event, skb->data,
          le32_to_cpu(ctrl_msg_h->data_length));
   if (ret)
    dev_err(port->dev, "Failed to append Handshake 2 event");
  }

  dev_kfree_skb_any(skb);
  break;

 case CTL_ID_MD_EX:
 case CTL_ID_MD_EX_ACK:
 case CTL_ID_MD_EX_PASS:
 case CTL_ID_DRV_VER_ERROR:
  ret = fsm_ee_message_handler(port, ctl, skb);
  dev_kfree_skb_any(skb);
  break;

 case CTL_ID_PORT_ENUM:
  skb_pull(skb, sizeof(*ctrl_msg_h));
  ret = t7xx_port_enum_msg_handler(ctl->md, (struct port_msg *)skb->data);
  if (!ret)
   ret = port_ctl_send_msg_to_md(port, CTL_ID_PORT_ENUM, 0);
  else
   ret = port_ctl_send_msg_to_md(port, CTL_ID_PORT_ENUM,
            PORT_ENUM_VER_MISMATCH);

  break;

 default:
  ret = -EINVAL;
  dev_err(port->dev, "Unknown control message ID to FSM %x\n",
   le32_to_cpu(ctrl_msg_h->ctrl_msg_id));
  break;
 }

 if (ret)
  dev_err(port->dev, "%s control message handle error: %d\n", port_conf->name, ret);

 return ret;
}

static int port_ctl_rx_thread(void *arg)
{
 while (!kthread_should_stop()) {
  struct t7xx_port *port = arg;
  struct sk_buff *skb;
  unsigned long flags;

  spin_lock_irqsave(&port->rx_wq.lock, flags);
  if (skb_queue_empty(&port->rx_skb_list) &&
      wait_event_interruptible_locked_irq(port->rx_wq,
       !skb_queue_empty(&port->rx_skb_list) ||
       kthread_should_stop())) {
   spin_unlock_irqrestore(&port->rx_wq.lock, flags);
   continue;
  }
  if (kthread_should_stop()) {
   spin_unlock_irqrestore(&port->rx_wq.lock, flags);
   break;
  }
  skb = __skb_dequeue(&port->rx_skb_list);
  spin_unlock_irqrestore(&port->rx_wq.lock, flags);

  control_msg_handler(port, skb);
 }

 return 0;
}

static int port_ctl_init(struct t7xx_port *port)
{
 const struct t7xx_port_conf *port_conf = port->port_conf;

 port->thread = kthread_run(port_ctl_rx_thread, port, "%s", port_conf->name);
 if (IS_ERR(port->thread)) {
  dev_err(port->dev, "Failed to start port control thread\n");
  return PTR_ERR(port->thread);
 }

 port->rx_length_th = CTRL_QUEUE_MAXLEN;
 return 0;
}

static void port_ctl_uninit(struct t7xx_port *port)
{
 unsigned long flags;
 struct sk_buff *skb;

 if (port->thread)
  kthread_stop(port->thread);

 spin_lock_irqsave(&port->rx_wq.lock, flags);
 port->rx_length_th = 0;
 while ((skb = __skb_dequeue(&port->rx_skb_list)) != NULL)
  dev_kfree_skb_any(skb);
 spin_unlock_irqrestore(&port->rx_wq.lock, flags);
}

struct port_ops ctl_port_ops = {
 .init = port_ctl_init,
 .recv_skb = t7xx_port_enqueue_skb,
 .uninit = port_ctl_uninit,
};

Messung V0.5
C=98 H=96 G=96

¤ Dauer der Verarbeitung: 0.11 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