Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 26758ac6 authored by Subash Abhinov Kasiviswanathan's avatar Subash Abhinov Kasiviswanathan
Browse files

net: qualcomm: rmnet: Add support for dowlink marker



The downlink marker command packets provides information
about the total packets which will arrive from the physical
device. Each marker will have information about all the
flows present in the burst regarding the byte and packet
counts.

CRs-Fixed: 2233026
Change-Id: If10394aaa5ed83ea20cb5211d11a47370cc5c41c
Signed-off-by: default avatarSubash Abhinov Kasiviswanathan <subashab@codeaurora.org>
parent 9522112f
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@ static int rmnet_unregister_real_device(struct net_device *real_dev,
	if (port->nr_rmnet_devs)
		return -EINVAL;

	rmnet_map_cmd_exit(port);
	rmnet_map_tx_aggregate_exit(port);

	kfree(port);
@@ -111,6 +112,7 @@ static int rmnet_register_real_device(struct net_device *real_dev)
		INIT_HLIST_HEAD(&port->muxed_ep[entry]);

	rmnet_map_tx_aggregate_init(port);
	rmnet_map_cmd_init(port);

	netdev_dbg(real_dev, "registered with rmnet\n");
	return 0;
+4 −0
Original line number Diff line number Diff line
@@ -52,6 +52,10 @@ struct rmnet_port {
	struct hrtimer hrtimer;

	void *qmi_info;

	/* dl marker elements */
	spinlock_t dl_list_lock;
	struct list_head dl_list;
};

extern struct rtnl_link_ops rmnet_link_ops;
+5 −0
Original line number Diff line number Diff line
@@ -92,6 +92,11 @@ __rmnet_map_ingress_handler(struct sk_buff *skb,
	u8 mux_id;

	if (RMNET_MAP_GET_CD_BIT(skb)) {
		if (port->data_format & RMNET_INGRESS_FORMAT_DL_MARKER) {
			if (!rmnet_map_flow_command(skb, port))
				return;
		}

		if (port->data_format & RMNET_FLAGS_INGRESS_MAP_COMMANDS)
			return rmnet_map_command(skb, port);

+63 −1
Original line number Diff line number Diff line
@@ -34,6 +34,8 @@ enum rmnet_map_commands {
	RMNET_MAP_COMMAND_NONE,
	RMNET_MAP_COMMAND_FLOW_DISABLE,
	RMNET_MAP_COMMAND_FLOW_ENABLE,
	RMNET_MAP_COMMAND_FLOW_START = 7,
	RMNET_MAP_COMMAND_FLOW_END = 8,
	/* These should always be the last 2 elements */
	RMNET_MAP_COMMAND_UNKNOWN,
	RMNET_MAP_COMMAND_ENUM_LENGTH
@@ -63,6 +65,60 @@ struct rmnet_map_ul_csum_header {
	u16 csum_enabled:1;
} __aligned(1);

struct rmnet_map_control_command_header {
	u8  command_name;
	u8  cmd_type:2;
	u8  reserved:6;
	u16 reserved2;
	u32 transaction_id;
}  __aligned(1);

struct rmnet_map_flow_info_le {
	__be32 mux_id;
	__be32 flow_id;
	__be32 bytes;
	__be32 pkts;
} __aligned(1);

struct rmnet_map_flow_info_be {
	u32 mux_id;
	u32 flow_id;
	u32 bytes;
	u32 pkts;
} __aligned(1);

struct rmnet_map_dl_ind_hdr {
	union {
		struct {
			u32 seq;
			u32 bytes;
			u32 pkts;
			u32 flows;
			struct rmnet_map_flow_info_le flow[0];
		} le __aligned(1);
		struct {
			__be32 seq;
			__be32 bytes;
			__be32 pkts;
			__be32 flows;
			struct rmnet_map_flow_info_be flow[0];
		} be __aligned(1);
	} __aligned(1);
} __aligned(1);

struct rmnet_map_dl_ind_trl {
	union {
		__be32 seq_be;
		u32 seq_le;
	} __aligned(1);
} __aligned(1);

struct rmnet_map_dl_ind {
	void (*dl_hdr_handler)(struct rmnet_map_dl_ind_hdr *);
	void (*dl_trl_handler)(struct rmnet_map_dl_ind_trl *);
	struct list_head list;
};

#define RMNET_MAP_GET_MUX_ID(Y) (((struct rmnet_map_header *) \
				 (Y)->data)->mux_id)
#define RMNET_MAP_GET_CD_BIT(Y) (((struct rmnet_map_header *) \
@@ -95,5 +151,11 @@ int rmnet_map_tx_agg_skip(struct sk_buff *skb, int offset);
void rmnet_map_tx_aggregate(struct sk_buff *skb, struct rmnet_port *port);
void rmnet_map_tx_aggregate_init(struct rmnet_port *port);
void rmnet_map_tx_aggregate_exit(struct rmnet_port *port);

int rmnet_map_flow_command(struct sk_buff *skb, struct rmnet_port *port);
void rmnet_map_cmd_init(struct rmnet_port *port);
int rmnet_map_dl_ind_register(struct rmnet_port *port,
			      struct rmnet_map_dl_ind *dl_ind);
int rmnet_map_dl_ind_deregister(struct rmnet_port *port,
				struct rmnet_map_dl_ind *dl_ind);
void rmnet_map_cmd_exit(struct rmnet_port *port);
#endif /* _RMNET_MAP_H_ */
+147 −0
Original line number Diff line number Diff line
@@ -16,6 +16,17 @@
#include "rmnet_private.h"
#include "rmnet_vnd.h"

#define RMNET_DL_IND_HDR_SIZE (sizeof(struct rmnet_map_dl_ind_hdr) + \
			       sizeof(struct rmnet_map_header) + \
			       sizeof(struct rmnet_map_control_command_header))

#define RMNET_MAP_CMD_SIZE (sizeof(struct rmnet_map_header) + \
			    sizeof(struct rmnet_map_control_command_header))

#define RMNET_DL_IND_TRL_SIZE (sizeof(struct rmnet_map_dl_ind_trl) + \
			       sizeof(struct rmnet_map_header) + \
			       sizeof(struct rmnet_map_control_command_header))

static u8 rmnet_map_do_flow_control(struct sk_buff *skb,
				    struct rmnet_port *port,
				    int enable)
@@ -83,6 +94,62 @@ static void rmnet_map_send_ack(struct sk_buff *skb,
	netif_tx_unlock(dev);
}

static  void rmnet_map_dl_hdr_notify(struct rmnet_port *port,
				     struct rmnet_map_dl_ind_hdr *dlhdr)
{
	struct rmnet_map_dl_ind *tmp;

	spin_lock(&port->dl_list_lock);

	list_for_each_entry(tmp, &port->dl_list, list)
		tmp->dl_hdr_handler(dlhdr);

	spin_unlock(&port->dl_list_lock);
}

static  void rmnet_map_dl_trl_notify(struct rmnet_port *port,
				     struct rmnet_map_dl_ind_trl *dltrl)
{
	struct rmnet_map_dl_ind *tmp;

	spin_lock(&port->dl_list_lock);

	list_for_each_entry(tmp, &port->dl_list, list)
		tmp->dl_trl_handler(dltrl);

	spin_unlock(&port->dl_list_lock);
}

static void rmnet_map_process_flow_start(struct sk_buff *skb,
					 struct rmnet_port *port)
{
	struct rmnet_map_dl_ind_hdr *dlhdr;

	if (skb->len < RMNET_DL_IND_HDR_SIZE)
		return;

	skb_pull(skb, RMNET_MAP_CMD_SIZE);

	dlhdr = (struct rmnet_map_dl_ind_hdr *)skb->data;

	rmnet_map_dl_hdr_notify(port, dlhdr);
}

static void rmnet_map_process_flow_end(struct sk_buff *skb,
				       struct rmnet_port *port)
{
	struct rmnet_map_dl_ind_trl *dltrl;

	if (skb->len < RMNET_DL_IND_TRL_SIZE)
		return;

	skb_pull(skb, RMNET_MAP_CMD_SIZE);

	dltrl = (struct rmnet_map_dl_ind_trl *)skb->data;

	rmnet_map_dl_trl_notify(port, dltrl);
}

/* Process MAP command frame and send N/ACK message as appropriate. Message cmd
 * name is decoded here and appropriate handler is called.
 */
@@ -112,3 +179,83 @@ void rmnet_map_command(struct sk_buff *skb, struct rmnet_port *port)
	if (rc == RMNET_MAP_COMMAND_ACK)
		rmnet_map_send_ack(skb, rc, port);
}

int rmnet_map_flow_command(struct sk_buff *skb, struct rmnet_port *port)
{
	struct rmnet_map_control_command *cmd;
	unsigned char command_name;

	cmd = RMNET_MAP_GET_CMD_START(skb);
	command_name = cmd->command_name;

	switch (command_name) {
	case RMNET_MAP_COMMAND_FLOW_START:
		rmnet_map_process_flow_start(skb, port);
		break;

	case RMNET_MAP_COMMAND_FLOW_END:
		rmnet_map_process_flow_end(skb, port);
		break;

	default:
		return 1;
	}

	consume_skb(skb);
	return 0;
}

void rmnet_map_cmd_exit(struct rmnet_port *port)
{
	struct rmnet_map_dl_ind *tmp, *idx;

	spin_lock(&port->dl_list_lock);

	list_for_each_entry_safe(tmp, idx, &port->dl_list, list)
		list_del_rcu(&tmp->list);

	spin_unlock(&port->dl_list_lock);
}

void rmnet_map_cmd_init(struct rmnet_port *port)
{
	INIT_LIST_HEAD(&port->dl_list);
	spin_lock_init(&port->dl_list_lock);
}

int rmnet_map_dl_ind_register(struct rmnet_port *port,
			      struct rmnet_map_dl_ind *dl_ind)
{
	if (!port || !dl_ind || !dl_ind->dl_hdr_handler ||
	    !dl_ind->dl_trl_handler)
		return -EINVAL;

	spin_lock(&port->dl_list_lock);
	list_add_rcu(&dl_ind->list, &port->dl_list);
	spin_unlock(&port->dl_list_lock);

	return 0;
}

int rmnet_map_dl_ind_deregister(struct rmnet_port *port,
				struct rmnet_map_dl_ind *dl_ind)
{
	struct rmnet_map_dl_ind *tmp;

	if (!port || !dl_ind)
		return -EINVAL;

	spin_lock(&port->dl_list_lock);

	list_for_each_entry(tmp, &port->dl_list, list) {
		if (tmp == dl_ind) {
			list_del_rcu(&dl_ind->list);
			goto done;
		}
	}

done:
	spin_unlock(&port->dl_list_lock);

	return 0;
}
Loading