165 lines
5.4 KiB
C
165 lines
5.4 KiB
C
|
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||
|
|
/*
|
||
|
|
* Copyright (C) 2016 MediaTek Inc.
|
||
|
|
*/
|
||
|
|
|
||
|
|
#ifndef __PORT_T_H__
|
||
|
|
#define __PORT_T_H__
|
||
|
|
#include "ccci_core.h"
|
||
|
|
|
||
|
|
/* packet will be dropped if port's Rx buffer full */
|
||
|
|
#define PORT_F_ALLOW_DROP (1<<0)
|
||
|
|
/* rx buffer has been full once */
|
||
|
|
#define PORT_F_RX_FULLED (1<<1)
|
||
|
|
/* CCCI header will be provided by user, but not by CCCI */
|
||
|
|
#define PORT_F_USER_HEADER (1<<2)
|
||
|
|
/* Rx queue only has this one port */
|
||
|
|
#define PORT_F_RX_EXCLUSIVE (1<<3)
|
||
|
|
/* Check whether need remove ccci header while recv skb*/
|
||
|
|
#define PORT_F_ADJUST_HEADER (1<<4)
|
||
|
|
/* Enable port channel traffic*/
|
||
|
|
#define PORT_F_CH_TRAFFIC (1<<5)
|
||
|
|
/* Dump raw data if CH_TRAFFIC set*/
|
||
|
|
#define PORT_F_DUMP_RAW_DATA (1<<6)
|
||
|
|
/* Need export char dev node for userspace*/
|
||
|
|
#define PORT_F_WITH_CHAR_NODE (1<<7)
|
||
|
|
|
||
|
|
/* reused for net tx, Data queue, same bit as RX_FULLED */
|
||
|
|
#define PORT_F_TX_DATA_FULLED (1<<1)
|
||
|
|
#define PORT_F_TX_ACK_FULLED (1<<8)
|
||
|
|
|
||
|
|
/*Can be clean when MD is invalid*/
|
||
|
|
#define PORT_F_CLEAN (1<<9)
|
||
|
|
/*Dump pkt of ccmni*/
|
||
|
|
#define PORT_F_NET_DUMP (1<<10)
|
||
|
|
enum {
|
||
|
|
PORT_DBG_DUMP_RILD = 0,
|
||
|
|
PORT_DBG_DUMP_AUDIO,
|
||
|
|
PORT_DBG_DUMP_IMS,
|
||
|
|
};
|
||
|
|
struct port_t;
|
||
|
|
struct port_ops {
|
||
|
|
/* must-have */
|
||
|
|
int (*init)(struct port_t *port);
|
||
|
|
int (*recv_skb)(struct port_t *port, struct sk_buff *skb);
|
||
|
|
/* optional */
|
||
|
|
int (*recv_match)(struct port_t *port, struct sk_buff *skb);
|
||
|
|
void (*md_state_notify)(struct port_t *port, unsigned int md_state);
|
||
|
|
void (*queue_state_notify)(struct port_t *port, int dir, int qno,
|
||
|
|
unsigned int qstate);
|
||
|
|
void (*dump_info)(struct port_t *port, unsigned int flag);
|
||
|
|
};
|
||
|
|
typedef void (*port_skb_handler)(struct port_t *port, struct sk_buff *skb);
|
||
|
|
struct port_t {
|
||
|
|
/* don't change the sequence unless
|
||
|
|
* you modified modem drivers as well
|
||
|
|
*/
|
||
|
|
/* identity */
|
||
|
|
enum CCCI_CH tx_ch;
|
||
|
|
enum CCCI_CH rx_ch;
|
||
|
|
/*
|
||
|
|
*
|
||
|
|
* here is a nasty trick, we assume no modem provide
|
||
|
|
* more than 0xF0 queues, so we use
|
||
|
|
* the lower 4 bit to smuggle info for network ports.
|
||
|
|
* Attention, in this trick we assume hardware queue index
|
||
|
|
* for net port will not exceed 0xF.
|
||
|
|
* check NET_ACK_TXQ_INDEX@port_net.c
|
||
|
|
*/
|
||
|
|
unsigned char txq_index;
|
||
|
|
unsigned char rxq_index;
|
||
|
|
unsigned char txq_exp_index;
|
||
|
|
unsigned char rxq_exp_index;
|
||
|
|
unsigned char hif_id;
|
||
|
|
unsigned short flags;
|
||
|
|
struct port_ops *ops;
|
||
|
|
/* device node related */
|
||
|
|
unsigned int minor;
|
||
|
|
char *name;
|
||
|
|
/* un-initiallized in defination, always put them at the end */
|
||
|
|
int md_id;
|
||
|
|
void *port_proxy;
|
||
|
|
void *private_data;
|
||
|
|
atomic_t usage_cnt;
|
||
|
|
struct list_head entry;
|
||
|
|
struct list_head exp_entry;
|
||
|
|
struct list_head queue_entry;
|
||
|
|
unsigned int major; /*dynamic alloc*/
|
||
|
|
unsigned int minor_base;
|
||
|
|
/*
|
||
|
|
* the Tx and Rx flow are asymmetric due to ports are
|
||
|
|
* mutilplexed on queues.
|
||
|
|
* Tx: data block are sent directly to queue's list,
|
||
|
|
* so port won't maitain a Tx list. It only
|
||
|
|
* provide a wait_queue_head for blocking write.
|
||
|
|
* Rx: due to modem needs to dispatch Rx packet
|
||
|
|
* as quickly as possible, so port needs a
|
||
|
|
* Rx list to hold packets.
|
||
|
|
*/
|
||
|
|
struct sk_buff_head rx_skb_list;
|
||
|
|
/* add high prio rx list for udc */
|
||
|
|
struct sk_buff_head rx_skb_list_hp;
|
||
|
|
unsigned char skb_from_pool;
|
||
|
|
spinlock_t rx_req_lock;
|
||
|
|
wait_queue_head_t rx_wq; /* for uplayer user */
|
||
|
|
int rx_length;
|
||
|
|
int rx_length_th;
|
||
|
|
struct wakeup_source *rx_wakelock;
|
||
|
|
unsigned int tx_busy_count;
|
||
|
|
unsigned int rx_busy_count;
|
||
|
|
int interception;
|
||
|
|
unsigned int rx_pkg_cnt;
|
||
|
|
unsigned int rx_drop_cnt;
|
||
|
|
unsigned int tx_pkg_cnt;
|
||
|
|
port_skb_handler skb_handler;
|
||
|
|
struct sk_buff_head port_rx_list;
|
||
|
|
atomic_t is_up; /*for ccmni status*/
|
||
|
|
spinlock_t flag_lock;
|
||
|
|
};
|
||
|
|
/****************************************************************************/
|
||
|
|
/* API Region called by ccci port object */
|
||
|
|
/****************************************************************************/
|
||
|
|
/*
|
||
|
|
*This API used to some port create kthread handle,
|
||
|
|
*which have same kthread handle flow.
|
||
|
|
*/
|
||
|
|
int port_kthread_handler(void *arg);
|
||
|
|
/*
|
||
|
|
*This API used to some port to receive native HIF RX data,
|
||
|
|
*which have same RX receive flow.
|
||
|
|
*/
|
||
|
|
int port_recv_skb(struct port_t *port, struct sk_buff *skb);
|
||
|
|
|
||
|
|
int port_user_register(struct port_t *port);
|
||
|
|
int port_user_unregister(struct port_t *port);
|
||
|
|
int port_ask_more_req_to_md(struct port_t *port);
|
||
|
|
int port_write_room_to_md(struct port_t *port);
|
||
|
|
void port_ch_dump(struct port_t *port, int dir, void *msg_buf, int len);
|
||
|
|
int port_get_capability(int md_id);
|
||
|
|
struct port_t *port_get_by_node(int major, int minor);
|
||
|
|
struct port_t *port_get_by_minor(int md_id, int minor);
|
||
|
|
struct port_t *port_get_by_channel(int md_id, enum CCCI_CH ch);
|
||
|
|
int port_send_skb_to_md(struct port_t *port, struct sk_buff *skb,
|
||
|
|
int blocking);
|
||
|
|
int port_net_send_skb_to_md(struct port_t *port, int is_ack,
|
||
|
|
struct sk_buff *skb);
|
||
|
|
int port_send_msg_to_md(struct port_t *port, unsigned int msg,
|
||
|
|
unsigned int resv, int blocking);
|
||
|
|
|
||
|
|
int port_dev_open(struct inode *inode, struct file *file);
|
||
|
|
int port_dev_close(struct inode *inode, struct file *file);
|
||
|
|
ssize_t port_dev_read(struct file *file, char *buf, size_t count,
|
||
|
|
loff_t *ppos);
|
||
|
|
ssize_t port_dev_write(struct file *file, const char __user *buf, size_t count,
|
||
|
|
loff_t *ppos);
|
||
|
|
long port_dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
|
||
|
|
#ifdef CONFIG_COMPAT
|
||
|
|
long port_dev_compat_ioctl(struct file *filp, unsigned int cmd,
|
||
|
|
unsigned long arg);
|
||
|
|
#endif
|
||
|
|
int port_dev_mmap(struct file *fp, struct vm_area_struct *vma);
|
||
|
|
|
||
|
|
int find_port_by_channel(int channel, struct port_t **port);
|
||
|
|
int send_new_time_to_new_md(int md_id, int tz);
|
||
|
|
#endif /* __PORT_T_H__ */
|