Merge "arm64: defconfig: Enable USB GSI function driver"

This commit is contained in:
qctecmdr 2022-11-04 13:53:10 -07:00 committed by Gerrit - the friendly Code Review server
commit 67bd5a23c8
6 changed files with 124 additions and 214 deletions

View File

@ -273,6 +273,7 @@
dev_fwnode
dev_get_by_name
dev_get_regmap
dev_get_stats
device_add
device_add_disk
device_add_groups
@ -300,6 +301,7 @@
device_wakeup_disable
device_wakeup_enable
_dev_info
__dev_kfree_skb_any
devm_add_action
devm_alloc_etherdev_mqs
devm_bitmap_zalloc
@ -1004,6 +1006,9 @@
netdev_alert
__netdev_alloc_skb
netdev_rss_key_fill
netif_carrier_off
netif_carrier_on
netif_tx_wake_queue
nonseekable_open
noop_llseek
nr_cpu_ids
@ -1590,6 +1595,7 @@
skb_dequeue
skb_free_datagram
__skb_pad
skb_pull
skb_push
skb_put
skb_queue_purge
@ -1597,6 +1603,7 @@
skb_recv_datagram
skb_set_owner_w
skb_store_bits
skb_trim
sk_error_report
sk_free
skip_spaces

View File

@ -191,11 +191,12 @@ CONFIG_STM_SOURCE_FTRACE=m
CONFIG_UCSI_QTI_GLINK=m
CONFIG_USB_CONFIGFS_F_CCID=m
CONFIG_USB_CONFIGFS_F_CDEV=m
# CONFIG_USB_CONFIGFS_F_GSI is not set
CONFIG_USB_CONFIGFS_F_GSI=m
CONFIG_USB_CONFIGFS_F_QDSS=m
CONFIG_USB_DWC3_MSM=m
CONFIG_USB_F_CCID=m
CONFIG_USB_F_CDEV=m
CONFIG_USB_F_GSI=m
CONFIG_USB_F_QDSS=m
CONFIG_USB_MSM_EUSB2_PHY=m
CONFIG_USB_MSM_SSPHY_QMP=m

View File

@ -25,6 +25,8 @@ static struct gsi_inst_status {
static int major;
static struct class *gsi_class;
static DEFINE_IDA(gsi_ida);
static DECLARE_COMPLETION(wait_for_ipa_ready);
struct ipa_usb_ops ipa_ops;
/* Deregister misc device and free instance structures */
static void gsi_inst_clean(struct gsi_opts *opts);
@ -512,16 +514,12 @@ static int ipa_connect_channels(struct gsi_data_port *d_port)
GSI_EP_OP_GET_CH_INFO);
log_event_dbg("%s: USB GSI IN OPS Completed", __func__);
in_params->client =
(gsi->prot_id != IPA_USB_DIAG) ? IPA_CLIENT_USB_CONS :
IPA_CLIENT_USB_DPL_CONS;
in_params->ipa_ep_cfg.mode.mode = IPA_BASIC;
in_params->teth_prot = gsi->prot_id;
in_params->gevntcount_low_addr =
gsi_channel_info.gevntcount_low_addr;
in_params->gevntcount_hi_addr =
gsi_channel_info.gevntcount_hi_addr;
in_params->dir = GSI_CHAN_DIR_FROM_GSI;
in_params->dir = CHAN_DIR_FROM_GSI;
in_params->xfer_ring_len = gsi_channel_info.xfer_ring_len;
in_params->xfer_scratch.last_trb_addr_iova =
gsi_channel_info.last_trb_addr;
@ -569,14 +567,12 @@ static int ipa_connect_channels(struct gsi_data_port *d_port)
usb_gsi_ep_op(d_port->out_ep, (void *)&gsi_channel_info,
GSI_EP_OP_GET_CH_INFO);
log_event_dbg("%s: USB GSI OUT OPS Completed", __func__);
out_params->client = IPA_CLIENT_USB_PROD;
out_params->ipa_ep_cfg.mode.mode = IPA_BASIC;
out_params->teth_prot = gsi->prot_id;
out_params->gevntcount_low_addr =
gsi_channel_info.gevntcount_low_addr;
out_params->gevntcount_hi_addr =
gsi_channel_info.gevntcount_hi_addr;
out_params->dir = GSI_CHAN_DIR_TO_GSI;
out_params->dir = CHAN_DIR_TO_GSI;
out_params->xfer_ring_len =
gsi_channel_info.xfer_ring_len;
out_params->xfer_ring_base_addr_iova =
@ -630,7 +626,7 @@ static int ipa_connect_channels(struct gsi_data_port *d_port)
sizeof(ipa_out_channel_out_params));
log_event_dbg("%s: Calling xdci_connect", __func__);
ret = ipa_usb_xdci_connect(out_params, in_params,
ret = d_port->ipa_ops->xdci_connect(out_params, in_params,
&ipa_out_channel_out_params,
&ipa_in_channel_out_params,
conn_params);
@ -745,7 +741,7 @@ static void ipa_disconnect_channel(struct gsi_data_port *d_port)
log_event_dbg("%s: Calling xdci_disconnect", __func__);
ret = ipa_usb_xdci_disconnect(gsi->d_port.out_channel_handle,
ret = d_port->ipa_ops->xdci_disconnect(gsi->d_port.out_channel_handle,
gsi->d_port.in_channel_handle, gsi->prot_id);
if (ret)
log_event_err("%s: IPA disconnect failed %d",
@ -790,7 +786,7 @@ static int ipa_suspend_work_handler(struct gsi_data_port *d_port)
}
log_event_dbg("%s: Calling xdci_suspend", __func__);
ret = ipa_usb_xdci_suspend(gsi->d_port.out_channel_handle,
ret = d_port->ipa_ops->xdci_suspend(gsi->d_port.out_channel_handle,
gsi->d_port.in_channel_handle, gsi->prot_id,
usb_gsi_remote_wakeup_allowed(f));
if (!ret) {
@ -823,7 +819,7 @@ static void ipa_resume_work_handler(struct gsi_data_port *d_port)
log_event_dbg("%s: Calling xdci_resume", __func__);
ret = ipa_usb_xdci_resume(gsi->d_port.out_channel_handle,
ret = d_port->ipa_ops->xdci_resume(gsi->d_port.out_channel_handle,
gsi->d_port.in_channel_handle,
gsi->prot_id);
if (ret)
@ -2833,15 +2829,12 @@ static int gsi_update_function_bind_params(struct f_gsi *gsi,
return -ENOMEM;
}
static void ipa_ready_callback(void *user_data)
void ipa_ready_callback(void *ops)
{
struct f_gsi *gsi = user_data;
log_event_info("%s: ipa is ready\n", __func__);
gsi->d_port.ipa_ready = true;
wake_up_interruptible(&gsi->d_port.wait_for_ipa_ready);
memcpy(&ipa_ops, ops, sizeof(struct ipa_usb_ops));
complete_all(&wait_for_ipa_ready);
}
EXPORT_SYMBOL(ipa_ready_callback);
static int gsi_bind(struct usb_configuration *c, struct usb_function *f)
{
@ -2909,8 +2902,8 @@ static int gsi_bind(struct usb_configuration *c, struct usb_function *f)
rndis_set_param_medium(gsi->params, RNDIS_MEDIUM_802_3, 0);
/* export host's Ethernet address in CDC format */
random_ether_addr(gsi->d_port.ipa_init_params.device_ethaddr);
random_ether_addr(gsi->d_port.ipa_init_params.host_ethaddr);
eth_random_addr(gsi->d_port.ipa_init_params.device_ethaddr);
eth_random_addr(gsi->d_port.ipa_init_params.host_ethaddr);
log_event_dbg("setting host_ethaddr=%pM, device_ethaddr = %pM",
gsi->d_port.ipa_init_params.host_ethaddr,
gsi->d_port.ipa_init_params.device_ethaddr);
@ -3108,8 +3101,8 @@ static int gsi_bind(struct usb_configuration *c, struct usb_function *f)
info.notify_buf_len = GSI_CTRL_NOTIFY_BUFF_LEN;
/* export host's Ethernet address in CDC format */
random_ether_addr(gsi->d_port.ipa_init_params.device_ethaddr);
random_ether_addr(gsi->d_port.ipa_init_params.host_ethaddr);
eth_random_addr(gsi->d_port.ipa_init_params.device_ethaddr);
eth_random_addr(gsi->d_port.ipa_init_params.host_ethaddr);
log_event_dbg("setting host_ethaddr=%pM, device_ethaddr = %pM",
gsi->d_port.ipa_init_params.host_ethaddr,
gsi->d_port.ipa_init_params.device_ethaddr);
@ -3150,21 +3143,17 @@ static int gsi_bind(struct usb_configuration *c, struct usb_function *f)
if (status)
goto dereg_rndis;
status = ipa_register_ipa_ready_cb(ipa_ready_callback, gsi);
status = wait_for_completion_timeout(&wait_for_ipa_ready,
msecs_to_jiffies(GSI_IPA_READY_TIMEOUT));
if (!status) {
log_event_info("%s: ipa is not ready", __func__);
status = wait_event_interruptible_timeout(
gsi->d_port.wait_for_ipa_ready, gsi->d_port.ipa_ready,
msecs_to_jiffies(GSI_IPA_READY_TIMEOUT));
if (!status) {
log_event_err("%s: ipa ready timeout", __func__);
status = -ETIMEDOUT;
goto dereg_rndis;
}
log_event_err("%s: ipa ready timeout", __func__);
status = -ETIMEDOUT;
goto dereg_rndis;
}
gsi->d_port.ipa_ops = &ipa_ops;
gsi->d_port.ipa_usb_notify_cb = ipa_usb_notify_cb;
status = ipa_usb_init_teth_prot(gsi->prot_id,
status = gsi->d_port.ipa_ops->init_teth_prot(gsi->prot_id,
&gsi->d_port.ipa_init_params, gsi->d_port.ipa_usb_notify_cb,
gsi);
if (status) {
@ -3207,13 +3196,13 @@ static void gsi_unbind(struct usb_configuration *c, struct usb_function *f)
* 1. Make sure that any running work completed
* 2. Make sure to wait until all pending work completed i.e. workqueue
* is not having any pending work.
* Above conditions are making sure that ipa_usb_deinit_teth_prot()
* Above conditions are making sure that deinit_teth_prot()
* with ipa driver shall not fail due to unexpected state.
*/
drain_workqueue(gsi->d_port.ipa_usb_wq);
log_event_dbg("%s:id:%d: dwq end", __func__, gsi->prot_id);
ipa_usb_deinit_teth_prot(gsi->prot_id);
gsi->d_port.ipa_ops->deinit_teth_prot(gsi->prot_id);
/* Reset string ids */
rndis_gsi_string_defs[0].id = 0;
@ -3310,7 +3299,7 @@ static struct f_gsi *gsi_function_init(enum ipa_usb_teth_prot prot_id)
spin_lock_init(&gsi->d_port.lock);
init_waitqueue_head(&gsi->d_port.wait_for_ipa_ready);
init_completion(&wait_for_ipa_ready);
INIT_DELAYED_WORK(&gsi->d_port.usb_ipa_w, ipa_work_handler);

View File

@ -9,7 +9,6 @@
#include <linux/poll.h>
#include <linux/cdev.h>
#include <linux/ipa.h>
#include <uapi/linux/usb/cdc.h>
#include <linux/usb/ch9.h>
#include <linux/usb/composite.h>
@ -253,6 +252,8 @@ struct gsi_data_port {
struct ipa_usb_xdci_chan_params ipa_in_channel_params;
struct ipa_usb_xdci_chan_params ipa_out_channel_params;
struct ipa_usb_xdci_connect_params ipa_conn_pms;
struct ipa_usb_ops *ipa_ops;
};
struct f_gsi {

View File

@ -175,181 +175,34 @@ struct ipa_req_chan_out_params {
u32 db_reg_phs_addr_msb;
};
#if IS_ENABLED(CONFIG_IPA3)
struct ipa_usb_ops {
int (*init_teth_prot)(enum ipa_usb_teth_prot teth_prot,
struct ipa_usb_teth_params *teth_params,
int (*ipa_usb_notify_cb)(enum ipa_usb_notify_event, void *),
void *user_data);
int (*xdci_connect)
(struct ipa_usb_xdci_chan_params *ul_chan_params,
struct ipa_usb_xdci_chan_params *dl_chan_params,
struct ipa_req_chan_out_params *ul_out_params,
struct ipa_req_chan_out_params *dl_out_params,
struct ipa_usb_xdci_connect_params *connect_params);
int (*xdci_disconnect)(u32 ul_clnt_hdl, u32 dl_clnt_hdl,
enum ipa_usb_teth_prot teth_prot);
int (*deinit_teth_prot)(enum ipa_usb_teth_prot teth_prot);
int (*xdci_suspend)(u32 ul_clnt_hdl, u32 dl_clnt_hdl,
enum ipa_usb_teth_prot teth_prot,
bool with_remote_wakeup);
int (*xdci_resume)(u32 ul_clnt_hdl, u32 dl_clnt_hdl,
enum ipa_usb_teth_prot teth_prot);
bool (*ipa_usb_is_teth_prot_connected)
(enum ipa_usb_teth_prot usb_teth_prot);
};
/**
* ipa_usb_init_teth_prot - Peripheral should call this function to initialize
* RNDIS/ECM/teth_bridge/DPL, prior to calling ipa_usb_xdci_connect()
*
* @usb_teth_type: tethering protocol type
* @teth_params: pointer to tethering protocol parameters.
* Should be struct ipa_usb_teth_params for RNDIS/ECM,
* or NULL for teth_bridge
* @ipa_usb_notify_cb: will be called to notify USB driver on certain events
* @user_data: cookie used for ipa_usb_notify_cb
*
* @Return 0 on success, negative on failure
*/
int ipa_usb_init_teth_prot(enum ipa_usb_teth_prot teth_prot,
struct ipa_usb_teth_params *teth_params,
int (*ipa_usb_notify_cb)(enum ipa_usb_notify_event,
void *),
void *user_data);
/**
* ipa_usb_xdci_connect - Peripheral should call this function to start IN &
* OUT xDCI channels, and connect RNDIS/ECM/MBIM/RMNET.
* For DPL, only starts IN channel.
*
* @ul_chan_params: parameters for allocating UL xDCI channel. containing
* required info on event and transfer rings, and IPA EP
* configuration
* @ul_out_params: [out] opaque client handle assigned by IPA to client & DB
* registers physical address for UL channel
* @dl_chan_params: parameters for allocating DL xDCI channel. containing
* required info on event and transfer rings, and IPA EP
* configuration
* @dl_out_params: [out] opaque client handle assigned by IPA to client & DB
* registers physical address for DL channel
* @connect_params: handles and scratch params of the required channels,
* tethering protocol and the tethering protocol parameters.
*
* Note: Should not be called from atomic context
*
* @Return 0 on success, negative on failure
*/
int ipa_usb_xdci_connect(struct ipa_usb_xdci_chan_params *ul_chan_params,
struct ipa_usb_xdci_chan_params *dl_chan_params,
struct ipa_req_chan_out_params *ul_out_params,
struct ipa_req_chan_out_params *dl_out_params,
struct ipa_usb_xdci_connect_params *connect_params);
/**
* ipa_usb_xdci_disconnect - Peripheral should call this function to stop
* IN & OUT xDCI channels
* For DPL, only stops IN channel.
*
* @ul_clnt_hdl: client handle received from ipa_usb_xdci_connect()
* for OUT channel
* @dl_clnt_hdl: client handle received from ipa_usb_xdci_connect()
* for IN channel
* @teth_prot: tethering protocol
*
* Note: Should not be called from atomic context
*
* @Return 0 on success, negative on failure
*/
int ipa_usb_xdci_disconnect(u32 ul_clnt_hdl, u32 dl_clnt_hdl,
enum ipa_usb_teth_prot teth_prot);
/**
* ipa_usb_deinit_teth_prot - Peripheral should call this function to deinit
* RNDIS/ECM/MBIM/RMNET
*
* @teth_prot: tethering protocol
*
* @Return 0 on success, negative on failure
*/
int ipa_usb_deinit_teth_prot(enum ipa_usb_teth_prot teth_prot);
/**
* ipa_usb_xdci_suspend - Peripheral should call this function to suspend
* IN & OUT or DPL xDCI channels
*
* @ul_clnt_hdl: client handle previously obtained from
* ipa_usb_xdci_connect() for OUT channel
* @dl_clnt_hdl: client handle previously obtained from
* ipa_usb_xdci_connect() for IN channel
* @teth_prot: tethering protocol
* @with_remote_wakeup: Does host support remote wakeup?
*
* Note: Should not be called from atomic context
* Note: for DPL, the ul will be ignored as irrelevant
*
* @Return 0 on success, negative on failure
*/
int ipa_usb_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl,
enum ipa_usb_teth_prot teth_prot,
bool with_remote_wakeup);
/**
* ipa_usb_xdci_resume - Peripheral should call this function to resume
* IN & OUT or DPL xDCI channels
*
* @ul_clnt_hdl: client handle received from ipa_usb_xdci_connect()
* for OUT channel
* @dl_clnt_hdl: client handle received from ipa_usb_xdci_connect()
* for IN channel
* @teth_prot: tethering protocol
*
* Note: Should not be called from atomic context
* Note: for DPL, the ul will be ignored as irrelevant
*
* @Return 0 on success, negative on failure
*/
int ipa_usb_xdci_resume(u32 ul_clnt_hdl, u32 dl_clnt_hdl,
enum ipa_usb_teth_prot teth_prot);
/**
* ipa_usb_is_teth_prot_connected - Internal API for checking USB
* protocol is connected
*
* @usb_teth_prot: USB tethering protocol
* @Return true if connected, false if not
*/
bool ipa_usb_is_teth_prot_connected(enum ipa_usb_teth_prot usb_teth_prot);
#else /* IS_ENABLED(CONFIG_IPA3) */
static inline int ipa_usb_init_teth_prot(enum ipa_usb_teth_prot teth_prot,
struct ipa_usb_teth_params *teth_params,
int (*ipa_usb_notify_cb)(enum ipa_usb_notify_event,
void *),
void *user_data)
{
return -EPERM;
}
static inline int ipa_usb_xdci_connect(
struct ipa_usb_xdci_chan_params *ul_chan_params,
struct ipa_usb_xdci_chan_params *dl_chan_params,
struct ipa_req_chan_out_params *ul_out_params,
struct ipa_req_chan_out_params *dl_out_params,
struct ipa_usb_xdci_connect_params *connect_params)
{
return -EPERM;
}
static inline int ipa_usb_xdci_disconnect(u32 ul_clnt_hdl, u32 dl_clnt_hdl,
enum ipa_usb_teth_prot teth_prot)
{
return -EPERM;
}
static inline int ipa_usb_deinit_teth_prot(enum ipa_usb_teth_prot teth_prot)
{
return -EPERM;
}
static inline int ipa_usb_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl,
enum ipa_usb_teth_prot teth_prot,
bool with_remote_wakeup)
{
return -EPERM;
}
static inline int ipa_usb_xdci_resume(u32 ul_clnt_hdl, u32 dl_clnt_hdl,
enum ipa_usb_teth_prot teth_prot)
{
return -EPERM;
}
static inline int ipa_usb_is_teth_prot_connected(enum ipa_usb_teth_prot usb_teth_prot)
{
return -EPERM;
}
#endif /* IS_ENABLED(CONFIG_IPA3) */
#if IS_ENABLED(CONFIG_USB_F_GSI)
void ipa_ready_callback(void *ops);
#else
static inline void ipa_ready_callback(void *ops)
{ }
#endif
#endif /* _IPA_USB_H_ */

View File

@ -0,0 +1,59 @@
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
/*
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef __UAPI_LINUX_USB_CTRL_QTI_H
#define __UAPI_LINUX_USB_CTRL_QTI_H
#include <linux/types.h>
#include <linux/ioctl.h>
#define MAX_QTI_PKT_SIZE 2048
#define QTI_CTRL_IOCTL_MAGIC 'r'
#define QTI_CTRL_GET_LINE_STATE _IOR(QTI_CTRL_IOCTL_MAGIC, 2, int)
#define QTI_CTRL_EP_LOOKUP _IOR(QTI_CTRL_IOCTL_MAGIC, 3, struct ep_info)
#define QTI_CTRL_MODEM_OFFLINE _IO(QTI_CTRL_IOCTL_MAGIC, 4)
#define QTI_CTRL_MODEM_ONLINE _IO(QTI_CTRL_IOCTL_MAGIC, 5)
#define QTI_CTRL_DATA_BUF_INFO \
_IOR(QTI_CTRL_IOCTL_MAGIC, 6, struct data_buf_info)
#define GSI_MBIM_IOCTL_MAGIC 'o'
#define GSI_MBIM_GET_NTB_SIZE _IOR(GSI_MBIM_IOCTL_MAGIC, 2, __u32)
#define GSI_MBIM_GET_DATAGRAM_COUNT _IOR(GSI_MBIM_IOCTL_MAGIC, 3, __u16)
#define GSI_MBIM_EP_LOOKUP _IOR(GSI_MBIM_IOCTL_MAGIC, 4, struct ep_info)
#define GSI_MBIM_GPS_USB_STATUS _IOR(GSI_MBIM_IOCTL_MAGIC, 5, int)
enum peripheral_ep_type {
DATA_EP_TYPE_RESERVED = 0x0,
DATA_EP_TYPE_HSIC = 0x1,
DATA_EP_TYPE_HSUSB = 0x2,
DATA_EP_TYPE_PCIE = 0x3,
DATA_EP_TYPE_EMBEDDED = 0x4,
DATA_EP_TYPE_BAM_DMUX = 0x5,
};
struct peripheral_ep_info {
enum peripheral_ep_type ep_type;
__u32 peripheral_iface_id;
};
struct ipa_ep_pair {
__u32 cons_pipe_num;
__u32 prod_pipe_num;
};
struct ep_info {
struct peripheral_ep_info ph_ep_info;
struct ipa_ep_pair ipa_ep_pair;
};
struct data_buf_info {
__u32 epout_buf_len;
__u32 epout_total_buf_len;
__u32 epin_buf_len;
__u32 epin_total_buf_len;
};
#endif