usb: gadget: f_qc_rndis: Add RNDIS support using IPA over BAM2BAM

On some targets RNDIS function uses BAM to BAM transport,
and is handled by the f_qc_rndis driver. This change
adds RNDIS support using IPA over BAM2BAM.
This is snapshot of the qcrndis driver as of kernel
msm-4.9 'commit e4c6a37f8770697d4 ("msm: vidc: avoid OOB
write while accessing memory")'.

Change-Id: I34e9ab6ca25ea515a36ffd54216a09177e5fa746
Signed-off-by: Shilpa Suresh <sbsure@codeaurora.org>
Signed-off-by: Chetan C R <cchinnad@codeaurora.org>
Signed-off-by: Swetha Chikkaboraiah <schikk@codeaurora.org>
This commit is contained in:
Shilpa Suresh 2020-03-11 19:03:48 +05:30 committed by Chetan C R
parent ddb6484558
commit 0f1b035635
11 changed files with 5018 additions and 14 deletions

File diff suppressed because it is too large Load diff

View file

@ -190,6 +190,9 @@ config USB_RNDIS
config USB_F_RNDIS
tristate
config USB_F_QCRNDIS
tristate
config USB_F_MASS_STORAGE
tristate
@ -247,6 +250,9 @@ config USB_F_MTP
config USB_F_PTP
tristate
config USB_F_RMNET_BAM
tristate
# this first set of drivers all depend on bulk-capable hardware.
config USB_CONFIGFS
@ -331,6 +337,15 @@ config USB_CONFIGFS_ECM_SUBSET
On hardware that can't implement the full protocol,
a simple CDC subset is used, placing fewer demands on USB.
config USB_CONFIGFS_QCRNDIS
bool "QCRNDIS"
depends on USB_CONFIGFS
depends on NET
depends on RNDIS_IPA
select USB_U_ETHER
select USB_RNDIS
select USB_F_QCRNDIS
config USB_CONFIGFS_RNDIS
bool "RNDIS"
depends on USB_CONFIGFS
@ -348,6 +363,18 @@ config USB_CONFIGFS_RNDIS
XP, you'll need to download drivers from Microsoft's website; a URL
is given in comments found in that info file.
config USB_CONFIGFS_RMNET_BAM
bool "RMNET_BAM"
depends on USB_CONFIGFS
select USB_F_RMNET_BAM
help
RmNet interface is a new logical device in QMI framework for data
services. RmNet in accordance with QMI architecture uses Data I/O
channel for IP data transfer and control I/O channel for QMI
messaging (functionality similar to AT commands).
RmNet interface is an alternative to standard CDC-ECM and windows
RNDIS.
config USB_CONFIGFS_EEM
bool "Ethernet Emulation Model (EEM)"
depends on USB_CONFIGFS

View file

@ -69,3 +69,5 @@ usb_f_mtp-y := f_mtp.o
obj-$(CONFIG_USB_F_MTP) += usb_f_mtp.o
usb_f_ptp-y := f_ptp.o
obj-$(CONFIG_USB_F_PTP) += usb_f_ptp.o
usb_f_qcrndis-y := f_qc_rndis.o u_data_ipa.o
obj-$(CONFIG_USB_F_QCRNDIS) += usb_f_qcrndis.o

File diff suppressed because it is too large Load diff

View file

@ -1006,6 +1006,18 @@ int rndis_set_param_medium(struct rndis_params *params, u32 medium, u32 speed)
}
EXPORT_SYMBOL_GPL(rndis_set_param_medium);
u32 rndis_get_dl_max_xfer_size(struct rndis_params *params)
{
pr_debug("%s:\n", __func__);
return params->dl_max_xfer_size;
}
u32 rndis_get_ul_max_xfer_size(struct rndis_params *params)
{
pr_debug("%s:\n", __func__);
return params->ul_max_xfer_size;
}
void rndis_set_max_pkt_xfer(struct rndis_params *params, u8 max_pkt_per_xfer)
{
pr_debug("%s:\n", __func__);

View file

@ -174,6 +174,7 @@ typedef struct rndis_params {
u32 host_rndis_major_ver;
u32 host_rndis_minor_ver;
u32 dl_max_xfer_size;
u32 ul_max_xfer_size;
const char *vendorDescr;
u8 pkt_alignment_factor;
void (*resp_avail)(void *v);
@ -196,6 +197,8 @@ int rndis_set_param_vendor(struct rndis_params *params, u32 vendorID,
int rndis_set_param_medium(struct rndis_params *params, u32 medium,
u32 speed);
void rndis_set_max_pkt_xfer(struct rndis_params *params, u8 max_pkt_per_xfer);
u32 rndis_get_ul_max_xfer_size(struct rndis_params *params);
u32 rndis_get_dl_max_xfer_size(struct rndis_params *params);
void rndis_add_hdr(struct sk_buff *skb);
int rndis_rm_hdr(struct gether *port, struct sk_buff *skb,
struct sk_buff_head *list);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,172 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2014,2016,2020, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __U_DATA_IPA_H
#define __U_DATA_IPA_H
#include <linux/usb/composite.h>
#include <linux/rndis_ipa.h>
#include <linux/usb/gadget.h>
#include <linux/cdev.h>
#include <linux/ipa_usb.h>
#include <linux/usb_bam.h>
#include "u_rmnet.h"
enum ipa_func_type {
USB_IPA_FUNC_ECM,
USB_IPA_FUNC_MBIM,
USB_IPA_FUNC_RMNET,
USB_IPA_FUNC_RNDIS,
USB_IPA_FUNC_DPL,
USB_IPA_NUM_FUNCS,
};
/* Max Number of IPA data ports supported */
#define IPA_N_PORTS USB_IPA_NUM_FUNCS
struct ipa_function_bind_info {
struct usb_string *string_defs;
int data_str_idx;
struct usb_interface_descriptor *data_desc;
struct usb_endpoint_descriptor *fs_in_desc;
struct usb_endpoint_descriptor *fs_out_desc;
struct usb_endpoint_descriptor *fs_notify_desc;
struct usb_endpoint_descriptor *hs_in_desc;
struct usb_endpoint_descriptor *hs_out_desc;
struct usb_endpoint_descriptor *hs_notify_desc;
struct usb_endpoint_descriptor *ss_in_desc;
struct usb_endpoint_descriptor *ss_out_desc;
struct usb_endpoint_descriptor *ss_notify_desc;
struct usb_descriptor_header **fs_desc_hdr;
struct usb_descriptor_header **hs_desc_hdr;
struct usb_descriptor_header **ss_desc_hdr;
};
/* for configfs support */
#define MAX_INST_NAME_LEN 40
struct f_rndis_qc_opts {
struct usb_function_instance func_inst;
struct f_rndis_qc *rndis;
u32 vendor_id;
const char *manufacturer;
struct net_device *net;
int refcnt;
};
struct f_rmnet_opts {
struct usb_function_instance func_inst;
struct f_rmnet *dev;
int refcnt;
};
#ifdef CONFIG_USB_F_QCRNDIS
void ipa_data_port_select(enum ipa_func_type func);
void ipa_data_disconnect(struct data_port *gp, enum ipa_func_type func);
int ipa_data_connect(struct data_port *gp, enum ipa_func_type func,
u8 src_connection_idx, u8 dst_connection_idx);
int ipa_data_setup(enum ipa_func_type func);
void ipa_data_free(enum ipa_func_type func);
void ipa_data_flush_workqueue(void);
void ipa_data_resume(struct data_port *gp, enum ipa_func_type func,
bool remote_wakeup_enabled);
void ipa_data_suspend(struct data_port *gp, enum ipa_func_type func,
bool remote_wakeup_enabled);
void ipa_data_set_ul_max_xfer_size(u32 ul_max_xfer_size);
void ipa_data_set_dl_max_xfer_size(u32 dl_max_transfer_size);
void ipa_data_set_ul_max_pkt_num(u8 ul_max_packets_number);
void ipa_data_start_rx_tx(enum ipa_func_type func);
void ipa_data_start_rndis_ipa(enum ipa_func_type func);
void ipa_data_stop_rndis_ipa(enum ipa_func_type func);
#else
static inline void ipa_data_port_select(enum ipa_func_type func)
{
}
static inline void ipa_data_disconnect(struct data_port *gp,
enum ipa_func_type func)
{
}
static inline int ipa_data_connect(struct data_port *gp,
enum ipa_func_type func, u8 src_connection_idx,
u8 dst_connection_idx)
{
return 0;
}
static inline int ipa_data_setup(enum ipa_func_type func)
{
return 0;
}
static inline void ipa_data_free(enum ipa_func_type func)
{
}
void ipa_data_flush_workqueue(void)
{
}
static inline void ipa_data_resume(struct data_port *gp,
enum ipa_func_type func, bool remote_wakeup_enabled)
{
}
static inline void ipa_data_suspend(struct data_port *gp,
enum ipa_func_type func, bool remote_wakeup_enabled)
{
}
#endif /* CONFIG_USB_F_QCRNDIS */
#ifdef CONFIG_USB_F_QCRNDIS
void *rndis_qc_get_ipa_priv(void);
void *rndis_qc_get_ipa_rx_cb(void);
bool rndis_qc_get_skip_ep_config(void);
void *rndis_qc_get_ipa_tx_cb(void);
void rndis_ipa_reset_trigger(void);
#else
static inline void *rndis_qc_get_ipa_priv(void)
{
return NULL;
}
static inline void *rndis_qc_get_ipa_rx_cb(void)
{
return NULL;
}
static inline bool rndis_qc_get_skip_ep_config(void)
{
return true;
}
static inline void *rndis_qc_get_ipa_tx_cb(void)
{
return NULL;
}
static inline void rndis_ipa_reset_trigger(void)
{
}
#endif /* CONFIG_USB_F_QCRNDIS */
#if IS_ENABLED(CONFIG_USB_CONFIGFS_RMNET_BAM)
void gqti_ctrl_update_ipa_pipes(void *gr, enum qti_port_type qport,
u32 ipa_prod, u32 ipa_cons);
#else
static inline void gqti_ctrl_update_ipa_pipes(void *gr,
enum qti_port_type qport,
u32 ipa_prod, u32 ipa_cons)
{
}
#endif /* CONFIG_USB_CONFIGFS_RMNET_BAM */
#endif

View file

@ -1804,6 +1804,19 @@ int ipa_is_vlan_mode(enum ipa_vlan_ifaces iface, bool *res);
bool ipa_get_lan_rx_napi(void);
#else /* (CONFIG_IPA || CONFIG_IPA3) */
/* low-level IPA client Connect / Disconnect */
static inline int ipa_connect(const struct ipa_connect_params *in,
struct ipa_sps_params *sps, u32 *clnt_hdl)
{
return -EPERM;
}
static inline int ipa_disconnect(u32 clnt_hdl)
{
return -EPERM;
}
/*
* Resume / Suspend
*/

View file

@ -1,15 +1,17 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
* Copyright (c) 2011-2017, 2020, The Linux Foundation. All rights reserved.
*/
#ifndef _USB_BAM_H_
#define _USB_BAM_H_
#include <linux/msm-sps.h>
#include <linux/ipa.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/usb/ch9.h>
#define MAX_BAMS NUM_CTRL /* Bam per USB controllers */
@ -43,6 +45,61 @@ enum usb_bam_pipe_type {
USB_BAM_MAX_PIPE_TYPES,
};
/*
* struct usb_bam_connect_ipa_params: Connect Bam pipe to IPA peer information.
* @ src_idx: Source pipe index in usb bam pipes lists.
* @ dst_idx: Destination pipe index in usb bam pipes lists.
* @ src_pipe: The source pipe index in the sps level.
* @ dst_pipe: The destination pipe index in the sps level.
* @ keep_ipa_awake: When true, IPA will not be clock gated.
* @ ipa_cons_ep_idx: The pipe index on the IPA peer bam side, consumer.
* @ ipa_prod_ep_idx: The pipe index on the IPA peer bam side, producer.
* @ prod_clnt_hdl: Producer client handle returned by IPA driver
* @ cons_clnt_hdl: Consumer client handle returned by IPA driver
* @ src_client: Source IPA client type.
* @ dst_client: Destination IPA client type.
* @ ipa_ep_cfg: Configuration of IPA end-point (see struct ipa_ep_cfg)
* @priv: Callback cookie to the notify event.
* @notify: Callback on data path event by IPA (see enum ipa_dp_evt_type)
* This call back gets back the priv cookie.
* for Bam2Bam mode, this callback is in the tethering bridge.
* @ activity_notify: Callback to be notified on and data being pushed into the
* USB consumer pipe.
* @ inactivity_notify: Callback to be notified on inactivity of all the current
* open pipes between the USB bam and its peer.
* @ skip_ep_cfg: boolean field that determines if Apps-processor
* should or should not confiugre this end-point.
* (Please see struct teth_bridge_init_params)
* @ reset_pipe_after_lpm: bool to indicate if IPA should reset pipe after LPM.
* @ usb_connection_speed: The actual speed the USB core currently works at.
*/
struct usb_bam_connect_ipa_params {
u8 src_idx;
u8 dst_idx;
u32 *src_pipe;
u32 *dst_pipe;
bool keep_ipa_awake;
enum usb_bam_pipe_dir dir;
/* Parameters for Port Mapper */
u32 ipa_cons_ep_idx;
u32 ipa_prod_ep_idx;
/* client handle assigned by IPA to client */
u32 prod_clnt_hdl;
u32 cons_clnt_hdl;
/* params assigned by the CD */
enum ipa_client_type src_client;
enum ipa_client_type dst_client;
struct ipa_ep_cfg ipa_ep_cfg;
void *priv;
void (*notify)(void *priv, enum ipa_dp_evt_type evt,
unsigned long data);
int (*activity_notify)(void *priv);
int (*inactivity_notify)(void *priv);
bool skip_ep_cfg;
bool reset_pipe_after_lpm;
enum usb_device_speed usb_connection_speed;
};
#if IS_ENABLED(CONFIG_USB_BAM)
/**
* Connect USB-to-Peripheral SPS connection.
@ -63,6 +120,36 @@ enum usb_bam_pipe_type {
int usb_bam_connect(enum usb_ctrl bam_type, int idx, u32 *bam_pipe_idx,
unsigned long iova);
/**
* Connect USB-to-IPA SPS connection.
*
* This function returns the allocated pipes number and clnt
* handles. Assumes that the user first connects producer pipes
* and only after that consumer pipes, since that's the correct
* sequence for the handshake with the IPA.
*
* @bam_type - USB BAM type - dwc3/CI/hsic
*
* @ipa_params - in/out parameters
*
* @return 0 on success, negative value on error
*/
int usb_bam_connect_ipa(enum usb_ctrl bam_type,
struct usb_bam_connect_ipa_params *ipa_params);
/**
* Disconnect USB-to-IPA SPS connection.
*
* @bam_type - USB BAM type - dwc3/CI/hsic
*
* @ipa_params - in/out parameters
*
* @return 0 on success, negative value on error
*/
int usb_bam_disconnect_ipa(enum usb_ctrl bam_type,
struct usb_bam_connect_ipa_params *ipa_params);
/**
* Register a wakeup callback from peer BAM.
*
@ -99,6 +186,27 @@ int usb_bam_register_start_stop_cbs(enum usb_ctrl bam_type,
void (*stop)(void *, enum usb_bam_pipe_dir),
void *param);
/**
* Start usb suspend sequence
*
* @ipa_params - in/out parameters
*
* @bam_type - USB BAM type - dwc3/CI/hsic
*/
void usb_bam_suspend(enum usb_ctrl bam_type,
struct usb_bam_connect_ipa_params *ipa_params);
/**
* Start usb resume sequence
*
* @bam_type - USB BAM type - dwc3/CI/hsic
*
* @ipa_params - in/out parameters
*/
void usb_bam_resume(enum usb_ctrl bam_type,
struct usb_bam_connect_ipa_params *ipa_params);
/**
* Disconnect USB-to-Periperal SPS connection.
*
@ -183,6 +291,13 @@ enum usb_ctrl usb_bam_get_bam_type(const char *core_name);
int usb_bam_get_pipe_type(enum usb_ctrl bam_type,
u8 idx, enum usb_bam_pipe_type *type);
/*
* Indicates whether USB producer is granted to IPA resource manager.
*
* @return true when producer granted, false when prodcuer is released.
*/
bool usb_bam_get_prod_granted(enum usb_ctrl bam_type, u8 idx);
/* Allocates memory for data fifo and descriptor fifos. */
int usb_bam_alloc_fifos(enum usb_ctrl cur_bam, u8 idx);
@ -197,6 +312,18 @@ static inline int usb_bam_connect(enum usb_ctrl bam, u8 idx, u32 *bam_pipe_idx,
return -ENODEV;
}
static inline int usb_bam_connect_ipa(enum usb_ctrl bam_type,
struct usb_bam_connect_ipa_params *ipa_params)
{
return -ENODEV;
}
static inline int usb_bam_disconnect_ipa(enum usb_ctrl bam_type,
struct usb_bam_connect_ipa_params *ipa_params)
{
return -ENODEV;
}
static inline int usb_bam_register_wake_cb(enum usb_ctrl bam_type, u8 idx,
int (*callback)(void *), void *param)
{
@ -211,6 +338,12 @@ static inline int usb_bam_register_start_stop_cbs(enum usb_ctrl bam, u8 idx,
return -ENODEV;
}
static inline void usb_bam_suspend(enum usb_ctrl bam_type,
struct usb_bam_connect_ipa_params *ipa_params){}
static inline void usb_bam_resume(enum usb_ctrl bam_type,
struct usb_bam_connect_ipa_params *ipa_params) {}
static inline int usb_bam_disconnect_pipe(enum usb_ctrl bam_type, u8 idx)
{
return -ENODEV;
@ -248,6 +381,11 @@ static inline int usb_bam_get_pipe_type(enum usb_ctrl bam_type, u8 idx,
return -ENODEV;
}
static inline bool usb_bam_get_prod_granted(enum usb_ctrl bam_type, u8 idx)
{
return false;
}
static inline int usb_bam_alloc_fifos(enum usb_ctrl cur_bam, u8 idx)
{
return false;

View file

@ -5,7 +5,7 @@
#include <linux/types.h>
#include <linux/ioctl.h>
#define MAX_QTI_PKT_SIZE 2048
#define MAX_QTI_PKT_SIZE 8192
#define QTI_CTRL_IOCTL_MAGIC 'r'
#define QTI_CTRL_GET_LINE_STATE _IOR(QTI_CTRL_IOCTL_MAGIC, 2, int)