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

Commit c89ac202 authored by Sujeev Dias's avatar Sujeev Dias Committed by Gerrit - the friendly Code Review server
Browse files

mhi: core: Add support for multiple MHI devices



In order to support multiple MHI devices connected
to same host we have, re-organize struct mhi_device_ctxt
such that all information related to device is included inside
struct mhi_device_ctxt. Created an abstract power management
layer to operate MHI in bus master, and slave mode. PCIe bus,
device, slot are extracted from DT to identify physical device.

CRs-Fixed: 1086301
Change-Id: I27a12b7412db75e4843794d80146ca7475b02fdc
Signed-off-by: default avatarSujeev Dias <sdias@codeaurora.org>
parent 02d4f876
Loading
Loading
Loading
Loading
+18 −4
Original line number Diff line number Diff line
@@ -7,6 +7,10 @@ signals.

Required properties:
  - compatible: should be "qcom,mhi"
  - qcom,pci-dev_id: device id reported by modem
  - qcom,pci-domain: pci root complex device connected to
  - qcom,pci-bus: pci bus device connected to
  - qcom,pci-slot: pci slot device connected to
  - Refer to "Documentation/devicetree/bindings/esoc/esoc_client.txt" for
    below properties:
	- esoc-names
@@ -24,13 +28,24 @@ Required properties:
	    C = event ring associated with channel
	    D = flags defined by mhi_macros.h GET_CHAN_PROPS
  - mhi-event-cfg-#: mhi event ring configuration parameters for platform
    defined as below <A B C D E>:
	    A = maximum event descriptors
	    B = MSI associated with event
	    C = interrupt moderation (see MHI specification)
	    D = Associated channel
	    E = flags defined by mhi_macros.h GET_EV_PROPS
  - mhi-event-rings: number of event rings supported by platform
  - mhi-dev-address-win-size: size of the MHI device addressing window
  - qcom,mhi-address-window: range of the MHI device addressing window

Example:

	mhi: qcom,mhi {
		compatible = "qcom,mhi";
		qcom,pci-dev_id = <0x0301>;
		qcom,pci-domain = <2>;
		qcom,pci-bus = <4>;
		qcom,pci-slot = <0>;
		qcom,mhi-address-window = <0x0 0x80000000 0x0 0xbfffffff>;
		esoc-names = "mdm";
		esoc-0 = <&mdm1>;
		qcom,msm-bus,name = "mhi";
@@ -39,8 +54,7 @@ Example:
		qcom,msm-bus,vectors-KBps =
				<100 512 0 0>,
				<100 512 1200000000 1200000000>;
		mhi-event-rings = <6>;
		mhi-event-rings = <1>;
		mhi-chan-cfg-102 = <0x66 0x80 0x5 0x62>;
		mhi-event-cfg-0 = <0x80 0x0 0x0 0x11>;
		mhi-dev-address-win-size= <0x10 0x00000000>;
		mhi-event-cfg-0 = <0x80 0x0 0x0 0x0 0x11>;
	};
+1 −2
Original line number Diff line number Diff line
@@ -665,8 +665,7 @@ static int diag_mhi_register_ch(int id, struct diag_mhi_ch_t *ch)
	atomic_set(&(ch->opened), 0);
	ctxt = SET_CH_CTXT(id, ch->type);
	ch->client_info.mhi_client_cb = mhi_notifier;
	return mhi_register_channel(&ch->hdl, ch->chan, 0, &ch->client_info,
				    (void *)(uintptr_t)ctxt);
	return mhi_register_channel(&ch->hdl, NULL);
}

int diag_mhi_init()
+83 −19
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/of_device.h>
#include <linux/rtnetlink.h>

#define RMNET_MHI_DRIVER_NAME "rmnet_mhi"
#define RMNET_MHI_DEV_NAME    "rmnet_mhi%d"
@@ -79,6 +80,7 @@ struct __packed mhi_skb_priv {

struct rmnet_mhi_private {
	struct list_head	      node;
	u32                           dev_id;
	struct mhi_client_handle      *tx_client_handle;
	struct mhi_client_handle      *rx_client_handle;
	enum MHI_CLIENT_CHANNEL       tx_channel;
@@ -792,6 +794,8 @@ static int rmnet_mhi_enable_iface(struct rmnet_mhi_private *rmnet_mhi_ptr)
	int ret = 0;
	struct rmnet_mhi_private **rmnet_mhi_ctxt = NULL;
	int r = 0;
	char ifalias[IFALIASZ];
	struct mhi_client_handle *client_handle = NULL;

	rmnet_log(rmnet_mhi_ptr, MSG_INFO, "Entered.\n");

@@ -825,6 +829,7 @@ static int rmnet_mhi_enable_iface(struct rmnet_mhi_private *rmnet_mhi_ptr)
		} else {
			rmnet_mhi_ptr->tx_enabled = 1;
		}
		client_handle = rmnet_mhi_ptr->tx_client_handle;
	}
	if (rmnet_mhi_ptr->rx_client_handle != NULL) {
		rmnet_log(rmnet_mhi_ptr,
@@ -840,7 +845,26 @@ static int rmnet_mhi_enable_iface(struct rmnet_mhi_private *rmnet_mhi_ptr)
		} else {
			rmnet_mhi_ptr->rx_enabled = 1;
		}
		/* Both tx & rx client handle contain same device info */
		client_handle = rmnet_mhi_ptr->rx_client_handle;
	}

	if (!client_handle) {
		ret = -EINVAL;
		goto net_dev_alloc_fail;
	}

	snprintf(ifalias,
		 sizeof(ifalias),
		 "%s_%04x_%02u.%02u.%02u_%u",
		 RMNET_MHI_DRIVER_NAME,
		 client_handle->dev_id,
		 client_handle->domain,
		 client_handle->bus,
		 client_handle->slot,
		 rmnet_mhi_ptr->dev_id);

	rtnl_lock();
	rmnet_mhi_ptr->dev =
		alloc_netdev(sizeof(struct rmnet_mhi_private *),
			     RMNET_MHI_DEV_NAME,
@@ -853,7 +877,9 @@ static int rmnet_mhi_enable_iface(struct rmnet_mhi_private *rmnet_mhi_ptr)
		goto net_dev_alloc_fail;
	}
	SET_NETDEV_DEV(rmnet_mhi_ptr->dev, &rmnet_mhi_ptr->pdev->dev);
	dev_set_alias(rmnet_mhi_ptr->dev, ifalias, strlen(ifalias));
	rmnet_mhi_ctxt = netdev_priv(rmnet_mhi_ptr->dev);
	rtnl_unlock();
	*rmnet_mhi_ctxt = rmnet_mhi_ptr;

	ret = dma_set_mask(&(rmnet_mhi_ptr->dev->dev),
@@ -980,17 +1006,16 @@ static void rmnet_mhi_cb(struct mhi_cb_info *cb_info)
	}
}

static struct mhi_client_info_t rmnet_mhi_info = {rmnet_mhi_cb};

#ifdef CONFIG_DEBUG_FS
struct dentry *dentry = NULL;

static void rmnet_mhi_create_debugfs(struct rmnet_mhi_private *rmnet_mhi_ptr)
{
	char node_name[15];
	char node_name[32];
	int i;
	const umode_t mode = (S_IRUSR | S_IWUSR);
	struct dentry *file;
	struct mhi_client_handle *client_handle;

	const struct {
		char *name;
@@ -1046,8 +1071,20 @@ static void rmnet_mhi_create_debugfs(struct rmnet_mhi_private *rmnet_mhi_ptr)
		},
	};

	snprintf(node_name, sizeof(node_name), "%s%d",
		 RMNET_MHI_DRIVER_NAME, rmnet_mhi_ptr->pdev->id);
	/* Both tx & rx client handle contain same device info */
	client_handle = rmnet_mhi_ptr->rx_client_handle;
	if (!client_handle)
		client_handle = rmnet_mhi_ptr->tx_client_handle;

	snprintf(node_name,
		 sizeof(node_name),
		 "%s_%04x_%02u.%02u.%02u_%u",
		 RMNET_MHI_DRIVER_NAME,
		 client_handle->dev_id,
		 client_handle->domain,
		 client_handle->bus,
		 client_handle->slot,
		 rmnet_mhi_ptr->dev_id);

	if (IS_ERR_OR_NULL(dentry))
		return;
@@ -1108,11 +1145,16 @@ static int rmnet_mhi_probe(struct platform_device *pdev)
	int rc;
	u32 channel;
	struct rmnet_mhi_private *rmnet_mhi_ptr;
	char node_name[15];
	struct mhi_client_handle *client_handle = NULL;
	char node_name[32];
	struct mhi_client_info_t client_info;

	if (unlikely(pdev->dev.of_node == NULL))
		return -ENODEV;

	if (!mhi_is_device_ready(&pdev->dev, "qcom,mhi"))
		return -EPROBE_DEFER;

	pdev->id = of_alias_get_id(pdev->dev.of_node, "mhi_rmnet");
	if (unlikely(pdev->id < 0))
		return -ENODEV;
@@ -1133,16 +1175,30 @@ static int rmnet_mhi_probe(struct platform_device *pdev)
			goto probe_fail;
	}

	rc = of_property_read_u32(pdev->dev.of_node,
				  "cell-index",
				  &rmnet_mhi_ptr->dev_id);
	if (unlikely(rc)) {
		rmnet_log(rmnet_mhi_ptr,
			  MSG_CRITICAL,
			  "failed to get valid 'cell-index'\n");
		goto probe_fail;
	}

	client_info.dev = &pdev->dev;
	client_info.node_name = "qcom,mhi";
	client_info.mhi_client_cb = rmnet_mhi_cb;
	client_info.user_data = rmnet_mhi_ptr;

	rc = of_property_read_u32(pdev->dev.of_node,
				  "qcom,mhi-tx-channel",
				  &channel);
	if (rc == 0) {
		rmnet_mhi_ptr->tx_channel = channel;
		client_info.chan = channel;

		rc = mhi_register_channel(&rmnet_mhi_ptr->tx_client_handle,
					  rmnet_mhi_ptr->tx_channel,
					  0,
					  &rmnet_mhi_info,
					  rmnet_mhi_ptr);
					  &client_info);
		if (unlikely(rc)) {
			rmnet_log(rmnet_mhi_ptr,
				  MSG_CRITICAL,
@@ -1151,6 +1207,7 @@ static int rmnet_mhi_probe(struct platform_device *pdev)
				  rc);
			goto probe_fail;
		}
		client_handle = rmnet_mhi_ptr->tx_client_handle;
	}

	rc = of_property_read_u32(pdev->dev.of_node,
@@ -1158,11 +1215,9 @@ static int rmnet_mhi_probe(struct platform_device *pdev)
				  &channel);
	if (rc == 0) {
		rmnet_mhi_ptr->rx_channel = channel;
		client_info.chan = channel;
		rc = mhi_register_channel(&rmnet_mhi_ptr->rx_client_handle,
					  rmnet_mhi_ptr->rx_channel,
					  0,
					  &rmnet_mhi_info,
					  rmnet_mhi_ptr);
					  &client_info);
		if (unlikely(rc)) {
			rmnet_log(rmnet_mhi_ptr,
				  MSG_CRITICAL,
@@ -1171,22 +1226,31 @@ static int rmnet_mhi_probe(struct platform_device *pdev)
				  rc);
			goto probe_fail;
		}

		/* overwriting tx_client_handle is ok because dev_id and
		 * bdf are same for both channels
		 */
		client_handle = rmnet_mhi_ptr->rx_client_handle;
		INIT_WORK(&rmnet_mhi_ptr->alloc_work, rmnet_mhi_alloc_work);
		spin_lock_init(&rmnet_mhi_ptr->alloc_lock);
	}

	/* We must've have @ least one valid channel */
	if (rmnet_mhi_ptr->rx_client_handle == NULL &&
	    rmnet_mhi_ptr->tx_client_handle == NULL) {
	if (!client_handle) {
		rmnet_log(rmnet_mhi_ptr, MSG_CRITICAL,
			  "No registered channels\n");
		rc = -ENODEV;
		goto probe_fail;
	}

	snprintf(node_name, sizeof(node_name), "%s%d",
		 RMNET_MHI_DRIVER_NAME, pdev->id);
	snprintf(node_name,
		 sizeof(node_name),
		 "%s_%04x_%02u.%02u.%02u_%u",
		 RMNET_MHI_DRIVER_NAME,
		 client_handle->dev_id,
		 client_handle->domain,
		 client_handle->bus,
		 client_handle->slot,
		 rmnet_mhi_ptr->dev_id);
	rmnet_mhi_ptr->rmnet_ipc_log =
		ipc_log_context_create(RMNET_IPC_LOG_PAGES,
				       node_name, 0);
+41 −30
Original line number Diff line number Diff line
@@ -29,7 +29,6 @@
#include <linux/list.h>
#include <linux/dma-mapping.h>

extern struct mhi_pcie_devices mhi_devices;
struct mhi_device_ctxt;

enum MHI_DEBUG_LEVEL {
@@ -49,11 +48,13 @@ struct pcie_core_info {
	u32 mhi_ver;
	void __iomem *bar0_base;
	void __iomem *bar0_end;
	void __iomem *bar2_base;
	void __iomem *bar2_end;
	u32 irq_base;
	u32 max_nr_msis;
	u32 domain;
	u32 bus;
	u32 slot;
	struct pci_saved_state *pcie_state;
	bool pci_master;
};

struct bhi_ctxt_t {
@@ -64,7 +65,6 @@ struct bhi_ctxt_t {
	void *unaligned_image_loc;
	dev_t bhi_dev;
	struct cdev cdev;
	struct class *bhi_class;
	struct device *dev;
};

@@ -382,7 +382,7 @@ struct mhi_chan_cfg {
	union mhi_cmd_pkt cmd_pkt;
};

struct mhi_client_handle {
struct mhi_client_config {
	struct mhi_chan_info chan_info;
	struct mhi_device_ctxt *mhi_dev_ctxt;
	struct mhi_client_info_t client_info;
@@ -434,6 +434,8 @@ struct mhi_counters {
	atomic_t events_pending;
	u32 *msi_counter;
	u32 mhi_reset_cntr;
	u32 link_down_cntr;
	u32 link_up_cntr;
};

struct mhi_flags {
@@ -486,13 +488,17 @@ struct mhi_dev_space {
};

struct mhi_device_ctxt {
	struct list_head node;
	struct pcie_core_info core;
	struct msm_pcie_register_event mhi_pci_link_event;
	struct pci_dev *pcie_device;
	struct bhi_ctxt_t bhi_ctxt;
	struct platform_device *plat_dev;
	enum MHI_PM_STATE mhi_pm_state; /* Host driver state */
	enum MHI_STATE mhi_state; /* protocol state */
	enum MHI_EXEC_ENV dev_exec_env;

	struct mhi_dev_space dev_space;
	struct mhi_pcie_dev_info *dev_info;
	struct pcie_core_info *dev_props;
	struct mhi_ring chan_bb_list[MHI_MAX_CHANNELS];
	struct mhi_ring mhi_local_chan_ctxt[MHI_MAX_CHANNELS];

@@ -500,7 +506,6 @@ struct mhi_device_ctxt {
	struct mhi_ring mhi_local_cmd_ctxt[NR_OF_CMD_RINGS];
	struct mhi_chan_cfg mhi_chan_cfg[MHI_MAX_CHANNELS];


	struct mhi_client_handle *client_handle_list[MHI_MAX_CHANNELS];
	struct mhi_event_ring_cfg *ev_ring_props;
	struct task_struct *event_thread_handle;
@@ -517,7 +522,9 @@ struct mhi_device_ctxt {

	struct hrtimer m1_timer;
	ktime_t m1_timeout;
	u32 poll_reset_timeout_ms;

	struct notifier_block mhi_ssr_nb;
	struct esoc_desc *esoc_handle;
	void *esoc_ssr_handle;

@@ -534,30 +541,30 @@ struct mhi_device_ctxt {
	struct wakeup_source w_lock;

	char *chan_info;
	struct dentry *mhi_parent_folder;
};

struct mhi_pcie_dev_info {
	struct pcie_core_info core;
	struct mhi_device_ctxt mhi_ctxt;
	struct msm_pcie_register_event mhi_pci_link_event;
	struct pci_dev *pcie_device;
	struct pci_driver *mhi_pcie_driver;
	struct bhi_ctxt_t bhi_ctxt;
	struct platform_device *plat_dev;
	u32 link_down_cntr;
	u32 link_up_cntr;
	struct dentry *child;
	struct dentry *parent;
	void *mhi_ipc_log;

	/* Shadow functions since not all device supports runtime pm */
	void (*runtime_get)(struct mhi_device_ctxt *mhi_dev_ctxt);
	void (*runtime_put)(struct mhi_device_ctxt *mhi_dev_ctxt);
	void (*assert_wake)(struct mhi_device_ctxt *mhi_dev_ctxt,
			    bool force_set);
	void (*deassert_wake)(struct mhi_device_ctxt *mhi_dev_ctxt);
};

struct mhi_pcie_devices {
	struct mhi_pcie_dev_info device_list[MHI_MAX_SUPPORTED_DEVICES];
	s32 nr_of_devices;
struct mhi_device_driver {
	struct mutex lock;
	struct list_head head;
	struct class *mhi_bhi_class;
	struct dentry *parent;
};

struct mhi_event_ring_cfg {
	u32 nr_desc;
	u32 msi_vec;
	u32 intmod;
	enum MHI_CLIENT_CHANNEL chan;
	u32 flags;
	enum MHI_RING_CLASS class;
	enum MHI_EVENT_RING_STATE state;
@@ -570,18 +577,20 @@ struct mhi_data_buf {
	u32 bounce_flag;
};

extern struct mhi_device_driver *mhi_device_drv;

irqreturn_t mhi_msi_ipa_handlr(int irq_number, void *dev_id);
int mhi_reset_all_thread_queues(
					struct mhi_device_ctxt *mhi_dev_ctxt);
int mhi_add_elements_to_event_rings(
				struct mhi_device_ctxt *mhi_dev_ctxt,
					enum STATE_TRANSITION new_state);
int get_nr_avail_ring_elements(struct mhi_ring *ring);
int get_nr_avail_ring_elements(struct mhi_device_ctxt *mhi_dev_ctxt,
			       struct mhi_ring *ring);
int get_nr_enclosed_el(struct mhi_ring *ring, void *loc_1,
					void *loc_2, u32 *nr_el);
int mhi_init_mmio(struct mhi_device_ctxt *mhi_dev_ctxt);
int mhi_init_device_ctxt(struct mhi_pcie_dev_info *dev_info,
				struct mhi_device_ctxt *mhi_dev_ctxt);
int mhi_init_device_ctxt(struct mhi_device_ctxt *mhi_dev_ctxt);
int mhi_init_local_event_ring(struct mhi_device_ctxt *mhi_dev_ctxt,
		u32 nr_ev_el, u32 event_ring_index);
int mhi_send_cmd(struct mhi_device_ctxt *dest_device,
@@ -632,11 +641,11 @@ int mhi_wait_for_mdm(struct mhi_device_ctxt *mhi_dev_ctxt);
enum hrtimer_restart mhi_initiate_m1(struct hrtimer *timer);
int mhi_pci_suspend(struct device *dev);
int mhi_pci_resume(struct device *dev);
int mhi_init_pcie_device(struct mhi_pcie_dev_info *mhi_pcie_dev);
int mhi_init_pcie_device(struct mhi_device_ctxt *mhi_dev_ctxt);
int mhi_init_pm_sysfs(struct device *dev);
void mhi_rem_pm_sysfs(struct device *dev);
void mhi_pci_remove(struct pci_dev *mhi_device);
int mhi_ctxt_init(struct mhi_pcie_dev_info *mhi_pcie_dev);
int mhi_ctxt_init(struct mhi_device_ctxt *mhi_dev_ctxt);
int mhi_get_chan_max_buffers(u32 chan);
int mhi_esoc_register(struct mhi_device_ctxt *mhi_dev_ctxt);
void mhi_link_state_cb(struct msm_pcie_notify *notify);
@@ -644,6 +653,8 @@ void mhi_notify_clients(struct mhi_device_ctxt *mhi_dev_ctxt,
						enum MHI_CB_REASON reason);
void mhi_notify_client(struct mhi_client_handle *client_handle,
		       enum MHI_CB_REASON reason);
void mhi_runtime_get(struct mhi_device_ctxt *mhi_dev_ctxt);
void mhi_runtime_put(struct mhi_device_ctxt *mhi_dev_ctxt);
void mhi_deassert_device_wake(struct mhi_device_ctxt *mhi_dev_ctxt);
void mhi_assert_device_wake(struct mhi_device_ctxt *mhi_dev_ctxt,
			    bool force_set);
@@ -691,7 +702,7 @@ void init_event_ctxt_array(struct mhi_device_ctxt *mhi_dev_ctxt);
int create_local_ev_ctxt(struct mhi_device_ctxt *mhi_dev_ctxt);
enum MHI_STATE mhi_get_m_state(struct mhi_device_ctxt *mhi_dev_ctxt);
void process_m1_transition(struct work_struct *work);
int set_mhi_base_state(struct mhi_pcie_dev_info *mhi_pcie_dev);
int set_mhi_base_state(struct mhi_device_ctxt *mhi_dev_ctxt);
void mhi_set_m_state(struct mhi_device_ctxt *mhi_dev_ctxt,
		     enum MHI_STATE new_state);
const char *state_transition_str(enum STATE_TRANSITION state);
+38 −44
Original line number Diff line number Diff line
@@ -23,7 +23,12 @@

static int bhi_open(struct inode *mhi_inode, struct file *file_handle)
{
	file_handle->private_data = &mhi_devices.device_list[0];
	struct mhi_device_ctxt *mhi_dev_ctxt;

	mhi_dev_ctxt = container_of(mhi_inode->i_cdev,
				    struct mhi_device_ctxt,
				    bhi_ctxt.cdev);
	file_handle->private_data = mhi_dev_ctxt;
	return 0;
}

@@ -34,10 +39,9 @@ static ssize_t bhi_write(struct file *file,
	int ret_val = 0;
	u32 pcie_word_val = 0;
	u32 i = 0;
	struct bhi_ctxt_t *bhi_ctxt =
		&(((struct mhi_pcie_dev_info *)file->private_data)->bhi_ctxt);
	struct mhi_device_ctxt *mhi_dev_ctxt =
		&((struct mhi_pcie_dev_info *)file->private_data)->mhi_ctxt;
	struct mhi_device_ctxt *mhi_dev_ctxt = file->private_data;
	struct bhi_ctxt_t *bhi_ctxt = &mhi_dev_ctxt->bhi_ctxt;

	size_t amount_copied = 0;
	uintptr_t align_len = 0x1000;
	u32 tx_db_val = 0;
@@ -58,22 +62,19 @@ static ssize_t bhi_write(struct file *file,
	if (timeout <= 0 && mhi_dev_ctxt->mhi_state != MHI_STATE_BHI)
		return -EIO;

	mhi_log(MHI_MSG_INFO, "Entered. User Image size 0x%zx\n", count);
	mhi_log(mhi_dev_ctxt, MHI_MSG_INFO,
		"Entered. User Image size 0x%zx\n", count);

	bhi_ctxt->unaligned_image_loc = kmalloc(count + (align_len - 1),
						GFP_KERNEL);
	if (bhi_ctxt->unaligned_image_loc == NULL)
		return -ENOMEM;

	mhi_log(MHI_MSG_INFO, "Unaligned Img Loc: %p\n",
			bhi_ctxt->unaligned_image_loc);
	bhi_ctxt->image_loc =
			(void *)((uintptr_t)bhi_ctxt->unaligned_image_loc +
		 (align_len - (((uintptr_t)bhi_ctxt->unaligned_image_loc) %
			       align_len)));

	mhi_log(MHI_MSG_INFO, "Aligned Img Loc: %p\n", bhi_ctxt->image_loc);

	bhi_ctxt->image_size = count;

	if (0 != copy_from_user(bhi_ctxt->image_loc, buf, count)) {
@@ -83,10 +84,9 @@ static ssize_t bhi_write(struct file *file,
	amount_copied = count;
	/* Flush the writes, in anticipation for a device read */
	wmb();
	mhi_log(MHI_MSG_INFO,
		"Copied image from user at addr: %p\n", bhi_ctxt->image_loc);

	bhi_ctxt->phy_image_loc = dma_map_single(
			&mhi_dev_ctxt->dev_info->plat_dev->dev,
			&mhi_dev_ctxt->plat_dev->dev,
			bhi_ctxt->image_loc,
			bhi_ctxt->image_size,
			DMA_TO_DEVICE);
@@ -95,9 +95,8 @@ static ssize_t bhi_write(struct file *file,
		ret_val = -EIO;
		goto bhi_copy_error;
	}
	mhi_log(MHI_MSG_INFO,
		"Mapped image to DMA addr 0x%lx:\n",
		(uintptr_t)bhi_ctxt->phy_image_loc);
	mhi_log(mhi_dev_ctxt, MHI_MSG_INFO,
		"Mapped image to DMA addr 0x%llx:\n", bhi_ctxt->phy_image_loc);

	bhi_ctxt->image_size = count;

@@ -149,18 +148,18 @@ static ssize_t bhi_write(struct file *file,
						BHI_STATUS_MASK,
						BHI_STATUS_SHIFT);
		read_unlock_bh(pm_xfer_lock);
		mhi_log(MHI_MSG_CRITICAL,
		mhi_log(mhi_dev_ctxt, MHI_MSG_CRITICAL,
			"BHI STATUS 0x%x, err:0x%x errdbg1:0x%x errdbg2:0x%x errdbg3:0x%x\n",
			tx_db_val, err, errdbg1, errdbg2, errdbg3);
		if (BHI_STATUS_SUCCESS != tx_db_val)
			mhi_log(MHI_MSG_CRITICAL,
			mhi_log(mhi_dev_ctxt, MHI_MSG_CRITICAL,
				"Incorrect BHI status: %d retry: %d\n",
				tx_db_val, i);
		else
			break;
		usleep_range(20000, 25000);
	}
	dma_unmap_single(&mhi_dev_ctxt->dev_info->plat_dev->dev,
	dma_unmap_single(&mhi_dev_ctxt->plat_dev->dev,
			bhi_ctxt->phy_image_loc,
			bhi_ctxt->image_size, DMA_TO_DEVICE);

@@ -169,7 +168,7 @@ static ssize_t bhi_write(struct file *file,
	ret_val = mhi_init_state_transition(mhi_dev_ctxt,
					STATE_TRANSITION_RESET);
	if (ret_val) {
		mhi_log(MHI_MSG_CRITICAL,
		mhi_log(mhi_dev_ctxt, MHI_MSG_CRITICAL,
			"Failed to start state change event\n");
	}
	return amount_copied;
@@ -184,39 +183,36 @@ static const struct file_operations bhi_fops = {
	.open = bhi_open,
};

int bhi_probe(struct mhi_pcie_dev_info *mhi_pcie_device)
int bhi_probe(struct mhi_device_ctxt *mhi_dev_ctxt)
{
	struct bhi_ctxt_t *bhi_ctxt = &mhi_pcie_device->bhi_ctxt;
	struct bhi_ctxt_t *bhi_ctxt = &mhi_dev_ctxt->bhi_ctxt;
	const struct pcie_core_info *core = &mhi_dev_ctxt->core;
	int ret_val = 0;
	int r;
	char node_name[32];

	if (NULL == mhi_pcie_device || 0 == mhi_pcie_device->core.bar0_base
	    || 0 == mhi_pcie_device->core.bar0_end)
	if (bhi_ctxt->bhi_base == NULL)
		return -EIO;

	ret_val = alloc_chrdev_region(&bhi_ctxt->bhi_dev, 0, 1, "bhi");
	if (IS_ERR_VALUE(ret_val)) {
		mhi_log(MHI_MSG_CRITICAL,
			"Failed to alloc char device %d\n",
			ret_val);
		mhi_log(mhi_dev_ctxt, MHI_MSG_CRITICAL,
			"Failed to alloc char device %d\n", ret_val);
		return -EIO;
	}
	bhi_ctxt->bhi_class = class_create(THIS_MODULE, "bhi");
	if (IS_ERR(bhi_ctxt->bhi_class)) {
		mhi_log(MHI_MSG_CRITICAL,
			"Failed to instantiate class %d\n",
			ret_val);
		r = PTR_RET(bhi_ctxt->bhi_class);
		goto err_class_create;
	}
	cdev_init(&bhi_ctxt->cdev, &bhi_fops);
	bhi_ctxt->cdev.owner = THIS_MODULE;
	ret_val = cdev_add(&bhi_ctxt->cdev, bhi_ctxt->bhi_dev, 1);
	bhi_ctxt->dev = device_create(bhi_ctxt->bhi_class, NULL,
					bhi_ctxt->bhi_dev, NULL,
					"bhi");
	snprintf(node_name, sizeof(node_name),
		 "bhi_%04X_%02u.%02u.%02u",
		 core->dev_id, core->domain, core->bus, core->slot);
	bhi_ctxt->dev = device_create(mhi_device_drv->mhi_bhi_class,
				      NULL,
				      bhi_ctxt->bhi_dev,
				      NULL,
				      node_name);
	if (IS_ERR(bhi_ctxt->dev)) {
		mhi_log(MHI_MSG_CRITICAL,
		mhi_log(mhi_dev_ctxt, MHI_MSG_CRITICAL,
			"Failed to add bhi cdev\n");
		r = PTR_RET(bhi_ctxt->dev);
		goto err_dev_create;
@@ -224,8 +220,6 @@ int bhi_probe(struct mhi_pcie_dev_info *mhi_pcie_device)
	return 0;
err_dev_create:
	cdev_del(&bhi_ctxt->cdev);
	class_destroy(bhi_ctxt->bhi_class);
err_class_create:
	unregister_chrdev_region(MAJOR(bhi_ctxt->bhi_dev), 1);
	return r;
}
Loading