void diagfwd_exit(void)
{
	smd_close(driver->ch);
	smd_close(driver->chqdsp);
	driver->ch = 0;		/*SMD can make this NULL */
	driver->chqdsp = 0;

	if (driver->usb_connected)
		diag_close();

	platform_driver_unregister(&msm_smd_ch1_driver);

	diag_usb_unregister();

	kfree(driver->usb_buf_in);
	kfree(driver->usb_buf_in_qdsp);
	kfree(driver->usb_buf_out);
	kfree(driver->hdlc_buf);
	kfree(driver->msg_masks);
	kfree(driver->log_masks);
	kfree(driver->event_masks);
	kfree(driver->client_map);
	kfree(driver->buf_tbl);
	kfree(driver->data_ready);
	kfree(driver->table);
	kfree(driver->pkt_buf);
	kfree(driver->usb_write_ptr);
	kfree(driver->usb_write_ptr_qdsp);
	kfree(driver->usb_read_ptr);
}
示例#2
0
static void hci_smd_deregister_dev(struct hci_smd_data *hsmd)
{
	tasklet_kill(&hs.rx_task);

	if (hsmd->hdev) {
		if (hci_unregister_dev(hsmd->hdev) < 0)
			BT_ERR("Can't unregister HCI device %s",
				hsmd->hdev->name);

		hci_free_dev(hsmd->hdev);
		hsmd->hdev = NULL;
	}

	smd_close(hs.event_channel);
	smd_close(hs.data_channel);

	if (wake_lock_active(&hs.wake_lock_rx))
		wake_unlock(&hs.wake_lock_rx);
	if (wake_lock_active(&hs.wake_lock_tx))
		wake_unlock(&hs.wake_lock_tx);

	/*Destroy the timer used to monitor the Rx queue for emptiness */
	if (hs.rx_q_timer.function) {
		del_timer_sync(&hs.rx_q_timer);
		hs.rx_q_timer.function = NULL;
		hs.rx_q_timer.data = 0;
	}
}
static void hci_smd_deregister_dev(struct hci_smd_data *hsmd)
{
	tasklet_kill(&hs.rx_task);

	if (!test_and_clear_bit(HCI_REGISTER_SET, &hsmd->flags)) {
		BT_ERR("HCI device un-registered already");
		return;
	} else
		BT_INFO("HCI device un-registration going on");

	if (hsmd->hdev) {
		if (hci_unregister_dev(hsmd->hdev) < 0)
			BT_ERR("Can't unregister HCI device %s",
				hsmd->hdev->name);

		hci_free_dev(hsmd->hdev);
		hsmd->hdev = NULL;
	}

	smd_close(hs.event_channel);
	smd_close(hs.data_channel);

	if (wake_lock_active(&hs.wake_lock_rx))
		wake_unlock(&hs.wake_lock_rx);
	if (wake_lock_active(&hs.wake_lock_tx))
		wake_unlock(&hs.wake_lock_tx);

	/*Destroy the timer used to monitor the Rx queue for emptiness */
	if (hs.rx_q_timer.function) {
		del_timer_sync(&hs.rx_q_timer);
		hs.rx_q_timer.function = NULL;
		hs.rx_q_timer.data = 0;
	}
}
示例#4
0
void diagfwd_exit(void)
{
	smd_close(driver->ch);
	smd_close(driver->chqdsp);
	driver->ch = 0;		/*SMD can make this NULL */
	driver->chqdsp = 0;
#ifdef CONFIG_DIAG_OVER_USB
	if (driver->usb_connected)
		usb_diag_free_req(driver->legacy_ch);
#endif
	platform_driver_unregister(&msm_smd_ch1_driver);
#ifdef CONFIG_DIAG_OVER_USB
	usb_diag_close(driver->legacy_ch);
#endif

	kfree(driver->buf_in_1);
	kfree(driver->buf_in_2);
	kfree(driver->buf_in_qdsp_1);
	kfree(driver->buf_in_qdsp_2);
#if defined(CONFIG_MACH_MECHA) //|| defined(CONFIG_ARCH_MSM8X60_LTE)
	kfree(driver->buf_in_mdm_1);
	kfree(driver->buf_in_mdm_2);
#endif
	kfree(driver->usb_buf_out);
	kfree(driver->hdlc_buf);
	kfree(driver->msg_masks);
	kfree(driver->log_masks);
	kfree(driver->event_masks);
	kfree(driver->client_map);
	kfree(driver->buf_tbl);
	kfree(driver->data_ready);
#if defined(CONFIG_MACH_MECHA) //|| defined(CONFIG_ARCH_MSM8X60_LTE)
	kfree(driver->mdmclient_map);
	//kfree(driver->mdmbuf_tbl);
	kfree(driver->mdmdata_ready);
#endif
	kfree(driver->table);
	kfree(driver->pkt_buf);
	kfree(driver->write_ptr_1);
	kfree(driver->write_ptr_2);
	kfree(driver->write_ptr_qdsp_1);
	kfree(driver->write_ptr_qdsp_2);
#if defined(CONFIG_MACH_MECHA) //|| defined(CONFIG_ARCH_MSM8X60_LTE)
	kfree(driver->write_ptr_mdm_1);
	kfree(driver->write_ptr_mdm_2);
#endif
	kfree(driver->usb_read_ptr);
#ifdef CONFIG_DIAG_NO_MODEM
	kfree(driver->apps_rsp_buf);
#endif
	destroy_workqueue(driver->diag_wq);
}
示例#5
0
void diagfwd_exit(void)
{
	smd_close(driver->ch);
	smd_close(driver->chqdsp);
	driver->ch = 0;		/*SMD can make this NULL */
	driver->chqdsp = 0;
#ifdef CONFIG_DIAG_OVER_USB
#ifdef CONFIG_SH_USB_CUST
	if (driver->usb_connected)
		diag_close();
#else /* CONFIG_SH_USB_CUST */
	if (driver->usb_connected)
		usb_diag_free_req(driver->legacy_ch);
#endif /* CONFIG_SH_USB_CUST */
#endif
	platform_driver_unregister(&msm_smd_ch1_driver);
#ifdef CONFIG_DIAG_OVER_USB
#ifdef CONFIG_SH_USB_CUST
	diag_usb_unregister();
#else /* CONFIG_SH_USB_CUST */
	usb_diag_close(driver->legacy_ch);
#endif /* CONFIG_SH_USB_CUST */
#endif


	kfree(driver->buf_in_1);
	kfree(driver->buf_in_2);
	kfree(driver->buf_in_qdsp_1);
	kfree(driver->buf_in_qdsp_2);
	kfree(driver->usb_buf_out);
	kfree(driver->hdlc_buf);
	kfree(driver->msg_masks);
	kfree(driver->log_masks);
	kfree(driver->event_masks);
	kfree(driver->client_map);
	kfree(driver->buf_tbl);
	kfree(driver->data_ready);
	kfree(driver->table);
	kfree(driver->pkt_buf);
	kfree(driver->write_ptr_1);
	kfree(driver->write_ptr_2);
	kfree(driver->write_ptr_qdsp_1);
	kfree(driver->write_ptr_qdsp_2);
	kfree(driver->usb_read_ptr);
	kfree(driver->apps_rsp_buf);
#ifndef CONFIG_SH_USB_CUST
	destroy_workqueue(driver->diag_wq);
#endif /* CONFIG_SH_USB_CUST */
}
示例#6
0
void diagfwd_cntl_exit(void)
{
	smd_close(driver->ch_cntl);
	smd_close(driver->chqdsp_cntl);
	smd_close(driver->ch_wcnss_cntl);
	driver->ch_cntl = 0;
	driver->chqdsp_cntl = 0;
	driver->ch_wcnss_cntl = 0;
	platform_driver_unregister(&msm_smd_ch1_cntl_driver);
	platform_driver_unregister(&diag_smd_lite_cntl_driver);

	kfree(driver->buf_in_cntl);
	kfree(driver->buf_in_qdsp_cntl);
	kfree(driver->buf_in_wcnss_cntl);
}
示例#7
0
void diag_smd_enable(smd_channel_t *ch, char *src, int mode)
{
	int r = 0;
	static smd_channel_t *_ch = NULL;
	DIAGFWD_INFO("smd_try_open(%s): mode=%d\n", src, mode);

	mutex_lock(&driver->smd_lock);
	diag_smd_function_mode = mode;
	if (mode) {
		if (!driver->ch) {
			r = smd_open(SMDDIAG_NAME, &driver->ch, driver, diag_smd_notify);
			if (!r)
				_ch = driver->ch;
		} else
			_ch = driver->ch;
	} else {
		if (driver->ch) {
			r = smd_close(driver->ch);
			driver->ch = NULL;
			if (!r)
				_ch = driver->ch;
		}
	}
	ch = _ch;
	mutex_unlock(&driver->smd_lock);
	DIAGFWD_INFO("smd_try_open(%s): r=%d _ch=%x\n", src, r, (unsigned int)ch);
}
示例#8
0
文件: smd_tty.c 项目: NooNameR/QSD3.0
static void smd_tty_close(struct tty_struct *tty, struct file *f)
{
	struct smd_tty_info *info = tty->driver_data;
	unsigned long flags;

	if (info == 0)
		return;

	mutex_lock(&smd_tty_lock);
	if (--info->open_count == 0) {
		spin_lock_irqsave(&info->reset_lock, flags);
		info->is_open = 0;
		spin_unlock_irqrestore(&info->reset_lock, flags);
		if (info->tty) {
			tasklet_kill(&info->tty_tsklt);
			wake_lock_destroy(&info->wake_lock);
			info->tty = 0;
		}
		tty->driver_data = 0;
		del_timer(&info->buf_req_timer);
		if (info->ch) {
			smd_close(info->ch);
			info->ch = 0;
			pil_put(info->pil);
		}
	}
	mutex_unlock(&smd_tty_lock);
}
static int grmnet_ctrl_smd_ch_remove(struct platform_device *pdev)
{
	struct rmnet_ctrl_port	*port;
	struct smd_ch_info	*c;
	int			i;

	pr_debug("%s: name:%s\n", __func__, pdev->name);

	for (i = 0; i < n_rmnet_ctrl_ports; i++) {
		port = ctrl_smd_ports[i].port;
		c = &port->ctrl_ch;

		if (!strncmp(c->name, pdev->name, SMD_CH_MAX_LEN)) {
			clear_bit(CH_READY, &c->flags);
			clear_bit(CH_OPENED, &c->flags);
			if (c->ch) {
				smd_close(c->ch);
				c->ch = NULL;
			}
			break;
		}
	}

	return 0;
}
示例#10
0
void diagfwd_cntl_exit(void)
{
	smd_close(driver->ch_cntl);
	smd_close(driver->chlpass_cntl);
	smd_close(driver->ch_wcnss_cntl);
	driver->ch_cntl = 0;
	driver->chlpass_cntl = 0;
	driver->ch_wcnss_cntl = 0;
	destroy_workqueue(driver->diag_cntl_wq);
	platform_driver_unregister(&msm_smd_ch1_cntl_driver);
	platform_driver_unregister(&diag_smd_lite_cntl_driver);

	kfree(driver->buf_in_cntl);
	kfree(driver->buf_in_lpass_cntl);
	kfree(driver->buf_in_wcnss_cntl);
}
示例#11
0
void gsmd_ctrl_disconnect(struct grmnet *gr, u8 port_num)
{
	struct rmnet_ctrl_port	*port;
	unsigned long		flags;
	struct smd_ch_info	*c;

	pr_debug("%s: grmnet:%p port#%d\n", __func__, gr, port_num);

	if (port_num >= n_ports) {
		pr_err("%s: invalid portno#%d\n", __func__, port_num);
		return;
	}

	if (!gr) {
		pr_err("%s: grmnet port is null\n", __func__);
		return;
	}

	port = ports[port_num].port;
	c = &port->ctrl_ch;

	spin_lock_irqsave(&port->port_lock, flags);
	port->port_usb = 0;
	gr->send_cpkt_request = 0;
	gr->send_cbits_tomodem = 0;
	c->cbits_tomodem = 0;
	spin_unlock_irqrestore(&port->port_lock, flags);

	if (test_bit(CH_OPENED, &c->flags)) {
		/* this should send the dtr zero */
		smd_close(c->ch);
		clear_bit(CH_OPENED, &c->flags);
	}
}
static int rpcrouter_smd_remote_qdsp_close(void)
{
	/*
	 * TBD: Implement when we have N way SMSM ported
	 * smsm_change_state(SMSM_APPS_STATE, SMSM_RPCINIT, 0);
	 */
	return smd_close(smd_remote_qdsp_xprt.channel);
}
示例#13
0
static int __devexit
wcnss_ctrl_remove(struct platform_device *pdev)
{
	if (penv && penv->smd_ch)
		smd_close(penv->smd_ch);

	return 0;
}
示例#14
0
static int
diag_ioctl(struct inode *inode, struct file *file,
	  unsigned int cmd, unsigned long arg)
{
	struct bt_diag_context *ctxt = &_context;
	void __user *argp = (void __user *)arg;
	int tmp_value;
	unsigned long flags;
	dbg("diag_ioctl\n");

	if (_IOC_TYPE(cmd) != USB_DIAG_IOC_MAGIC) {
		dbg("IOC_TYPE not USB_DIAG_IOC_MAGIC\n");
		return -ENOTTY;
	}

	switch (cmd) {
	case USB_DIAG_FUNC_IOC_ENABLE_SET:
		if (copy_from_user(&tmp_value, argp, sizeof(int))) {
			dbg("copy_from_user fail\n");
			return -EFAULT;
		}
		dbg("IOCTL USB_DIAG_FUNC_IOC_ENABLE_SET %d\n", tmp_value);
		if (tmp_value)	{
			/*TODO: enable BT interface*/
			dbg("smd_open: SMD_DIAG\n");
			smd_open("SMD_DIAG", &ctxt->ch, ctxt, smd_diag_notify);
			wake_lock(&btport_wake_lock);
		} else	{
			/*TODO: disable BT interface*/
			dbg("smd_close: SMD_DIAG\n");
			smd_close(ctxt->ch);
			wake_unlock(&btport_wake_lock);
		}
		break;
	case USB_DIAG_FUNC_IOC_ENABLE_GET:
		/*TODO: assign BT enable to tmp_value*/
		if (copy_to_user(argp, &tmp_value, sizeof(tmp_value)))
			return -EFAULT;
		break;
	case USB_DIAG_FUNC_IOC_REGISTER_SET:
		spin_lock_irqsave(&ctxt->lock_reg_num, flags);
		if (copy_from_user(ctxt->id_table, (unsigned char *)argp, sizeof(unsigned char)*TABLE_SIZE)) {
			spin_unlock_irqrestore(&ctxt->lock_reg_num, flags);
			return -EFAULT;
		}
		spin_unlock_irqrestore(&ctxt->lock_reg_num, flags);
		break;
	case USB_DIAG_FUNC_IOC_AMR_SET:
		if (copy_from_user(&ctxt->is2ARM11, argp, sizeof(int)))
			return -EFAULT;
		dbg("IOCTL USB_DIAG_FUNC_IOC_AMR_SET %d\n", ctxt->is2ARM11);
		break;
	default:
		return -ENOTTY;
	}

	return 0;
}
static void smd_tty_port_shutdown(struct tty_port *tport)
{
	struct smd_tty_info *info;
	struct tty_struct *tty = tty_port_tty_get(tport);
	unsigned long flags;
#ifdef CONFIG_LGE_USES_SMD_DS_TTY
	int res = 0;
	int n = tty->index;
#endif

	info = tty->driver_data;
	if (info == 0) {
		tty_kref_put(tty);
		return;
	}

	mutex_lock(&smd_tty_lock);
	spin_lock_irqsave(&info->reset_lock, flags);
	info->is_open = 0;
	spin_unlock_irqrestore(&info->reset_lock, flags);

	tasklet_kill(&info->tty_tsklt);
	wake_lock_destroy(&info->wake_lock);
	wake_lock_destroy(&info->ra_wake_lock);

	SMD_TTY_INFO("%s with PID %u closed port %s",
			current->comm, current->pid,
			info->smd->port_name);
	tty->driver_data = NULL;
	del_timer(&info->buf_req_timer);

	smd_close(info->ch);
#ifdef CONFIG_LGE_USES_SMD_DS_TTY
	/*           
                                                       
                                                   
                                                
                                                      
                                                      
                                                  
                                                      
                                                
                                    
  */
	pr_info("%s: waiting to close smd %s completely\n",
			__func__, smd_tty[n].smd->port_name);
	/* wait for reopen ready status in seconds */
	res = wait_event_interruptible_timeout(
			info->ch_opened_wait_queue,
			!info->is_open, (lge_ds_modem_wait * HZ));
	if (res == 0) {
		/* just in case, remain result value */
		res = -ETIMEDOUT;
		pr_err("%s: timeout to wait for %s smd_close.\
				next smd_open may fail....%d\n",
				__func__, smd_tty[n].smd->port_name, res);
	}
static int msm_diag_smd_close(void)
{
	struct diag_context *ctxt = &_context;
	int r;

	r = smd_close(ctxt->ch);
    ctxt->ch = 0;
	return r;
}
static void radio_hci_smd_deregister(void)
{
	radio_hci_unregister_dev();
	kfree(hs.hdev);
	hs.hdev = NULL;

	smd_close(hs.fm_channel);
	hs.fm_channel = 0;
	fmsmd_set = 0;
}
示例#18
0
static int wp_diag_device_op_release(struct inode *inode, struct file *filp)
{
	//printk(KERN_INFO "wp_diag: %s, i_rdev %d\n", __FUNCTION__, inode->i_rdev);
	if (_wp_context.configured) {
		smd_close(_wp_context.ch);
		list_del(&_wp_context.read_q);
		_wp_context.configured = 0;
	}
	return 0;
}
void diag_dci_exit(void)
{
	smd_close(driver->ch_dci);
	driver->ch_dci = 0;
	platform_driver_unregister(&msm_diag_dci_driver);
	kfree(driver->dci_tbl);
	kfree(driver->dci_notify_tbl);
	kfree(driver->apps_dci_buf);
	kfree(driver->buf_in_dci);
	kfree(driver->write_ptr_dci);
}
示例#20
0
void diagfwd_exit(void)
{
	smd_close(driver->ch);
	smd_close(driver->chqdsp);
	smd_close(driver->ch_wcnss);
	driver->ch = 0;		/* SMD can make this NULL */
	driver->chqdsp = 0;
	driver->ch_wcnss = 0;
	smd_diag_initialized = 0;
#ifdef CONFIG_DIAG_OVER_USB
	if (driver->usb_connected)
		usb_diag_free_req(driver->legacy_ch);
	usb_diag_close(driver->legacy_ch);
#endif
	platform_driver_unregister(&msm_smd_ch1_driver);
	platform_driver_unregister(&diag_smd_lite_driver);
	kfree(driver->buf_in_1);
	kfree(driver->buf_in_2);
	kfree(driver->buf_in_qdsp_1);
	kfree(driver->buf_in_qdsp_2);
	kfree(driver->buf_in_wcnss);
	kfree(driver->usb_buf_out);
	kfree(driver->hdlc_buf);
	kfree(driver->msg_masks);
	kfree(driver->log_masks);
	kfree(driver->event_masks);
	kfree(driver->client_map);
	kfree(driver->buf_tbl);
	kfree(driver->data_ready);
	kfree(driver->table);
	kfree(driver->pkt_buf);
	kfree(driver->write_ptr_1);
	kfree(driver->write_ptr_2);
	kfree(driver->write_ptr_qdsp_1);
	kfree(driver->write_ptr_qdsp_2);
	kfree(driver->write_ptr_wcnss);
	kfree(driver->usb_read_ptr);
	kfree(driver->apps_rsp_buf);
	kfree(driver->user_space_data);
	destroy_workqueue(driver->diag_wq);
}
示例#21
0
static int __rmnet_close(struct net_device *dev)
{
	struct rmnet_private *p = netdev_priv(dev);
	int rc;

	if (p->ch) {
		rc = smd_close(p->ch);
		p->ch = 0;
		return rc;
	} else
		return -EBADF;
}
示例#22
0
void diag_smd_destructor(struct diag_smd_info *smd_info)
{
	if (smd_info->ch)
		smd_close(smd_info->ch);

	smd_info->ch = 0;
	smd_info->ch_save = 0;
	kfree(smd_info->buf_in_1);
	kfree(smd_info->buf_in_2);
	kfree(smd_info->write_ptr_1);
	kfree(smd_info->write_ptr_2);
}
示例#23
0
static int nmea_release(struct inode *ip, struct file *fp)
{
	int r = 0;

	mutex_lock(&nmea_ch_lock);
	if (nmea_devp->ch != 0) {
		r = smd_close(nmea_devp->ch);
		nmea_devp->ch = 0;
	}
	mutex_unlock(&nmea_ch_lock);

	return r;
}
示例#24
0
static void smd_tty_close(struct tty_struct *tty, struct file *f)
{
	struct smd_tty_info *info = tty->driver_data;
	unsigned long flags;
#ifdef CONFIG_LGE_USES_SMD_DS_TTY
	int res = 0;
	int n = tty->index;
#endif

	if (info == 0)
		return;

	mutex_lock(&smd_tty_lock);
	if (--info->open_count == 0) {
		spin_lock_irqsave(&info->reset_lock, flags);
		info->is_open = 0;
		spin_unlock_irqrestore(&info->reset_lock, flags);
		if (info->tty) {
			tasklet_kill(&info->tty_tsklt);
			wake_lock_destroy(&info->wake_lock);
			info->tty = 0;
		}
		tty->driver_data = 0;
		del_timer(&info->buf_req_timer);
		if (info->ch) {
			smd_close(info->ch);
#ifdef CONFIG_LGE_USES_SMD_DS_TTY
			/* LGE_CHANGE
			 * At current qct smd_tty framework, if smd_tty_open()
			 * is invoked by process before smd_tty_close() is
			 * completely finished, smd_tty_open() may fail
			 * because smd_tty_close() does not wait to close smd
			 * channel from modem. To fix this situation, new SMD
			 * notify status, SMD_EVENT_REOPEN_READY is used.
			 * Until smd_tty receive this status, smd_tty_close()
			 * will be wait(in fact, process will be wait).
			 * 2011-10-12, [email protected]
			 */
			pr_info("%s: waiting to close smd %s completely\n",
					__func__, smd_tty[n].smd->port_name);
			/* wait for reopen ready status in seconds */
			res = wait_event_interruptible_timeout(
				info->ch_opened_wait_queue,
				!info->is_open, (lge_ds_modem_wait * HZ));
			if (res == 0) {
				/* just in case, remain result value */
				res = -ETIMEDOUT;
				pr_err("%s: timeout to wait for %s smd_close.\
						next smd_open may fail....%d\n",
						__func__, smd_tty[n].smd->port_name, res);
			}
示例#25
0
static void smd_tty_close(struct tty_struct *tty, struct file *f)
{
    struct smd_tty_info *info = tty->driver_data;
    unsigned long flags;
#ifdef CONFIG_LGE_USES_SMD_DS_TTY
    int res = 0;
    int n = tty->index;
#endif

    if (info == 0)
        return;

    mutex_lock(&smd_tty_lock);
    if (--info->open_count == 0) {
        spin_lock_irqsave(&info->reset_lock, flags);
        info->is_open = 0;
        spin_unlock_irqrestore(&info->reset_lock, flags);
        if (info->tty) {
            tasklet_kill(&info->tty_tsklt);
            wake_lock_destroy(&info->wake_lock);
            info->tty = 0;
        }
        tty->driver_data = 0;
        del_timer(&info->buf_req_timer);
        if (info->ch) {
            smd_close(info->ch);
#ifdef CONFIG_LGE_USES_SMD_DS_TTY
            /*









            */
            pr_info("%s: waiting to close smd %s completely\n",
                    __func__, smd_tty[n].smd->port_name);
            /* wait for reopen ready status in seconds */
            res = wait_event_interruptible_timeout(
                      info->ch_opened_wait_queue,
                      !info->is_open, (lge_ds_modem_wait * HZ));
            if (res == 0) {
                /* just in case, remain result value */
                res = -ETIMEDOUT;
                pr_err("%s: timeout to wait for %s smd_close.\
						next smd_open may fail....%d\n",
                       __func__, smd_tty[n].smd->port_name, res);
            }
static int smm6260net_stop(struct net_device *dev)
{
	struct smm6260net_private *p = netdev_priv(dev);
	int r=0;
	pr_info("haozz smm6260net_stop(),%d\n",p->ucount);
        if(p->ch && !(--p->ucount)){
			r = smd_close(p->ch);
		if(r < 0)
			return -ENODEV;
		p->ch = NULL;
		netif_stop_queue(dev);
	}	
	return 0;
}
static void hci_smd_deregister_dev(struct hci_smd_data *hsmd)
{
	tasklet_kill(&hs.rx_task);
	if (ssr_state)
		BT_DBG("SSR state is : %x", ssr_state);
	/* Though the hci_smd driver is not registered with the hci
	 * need to close the opened channels as a part of cleaup
	 */
	if (!test_and_clear_bit(HCI_REGISTER_SET, &hsmd->flags)) {
		BT_ERR("HCI device un-registered already");
	} else {
		BT_INFO("HCI device un-registration going on");

		if (hsmd->hdev) {
			if (hci_unregister_dev(hsmd->hdev) < 0)
				BT_ERR("Can't unregister HCI device %s",
					hsmd->hdev->name);

			hci_free_dev(hsmd->hdev);
			hsmd->hdev = NULL;
		}
	}
	smd_close(hs.event_channel);
	smd_close(hs.data_channel);

	if (wake_lock_active(&hs.wake_lock_rx))
		wake_unlock(&hs.wake_lock_rx);
	if (wake_lock_active(&hs.wake_lock_tx))
		wake_unlock(&hs.wake_lock_tx);

	/*Destroy the timer used to monitor the Rx queue for emptiness */
	if (hs.rx_q_timer.function) {
		del_timer_sync(&hs.rx_q_timer);
		hs.rx_q_timer.function = NULL;
		hs.rx_q_timer.data = 0;
	}
}
static int __rmnet_close(struct net_device *dev)
{
	struct rmnet_private *p = netdev_priv(dev);
	int rc;
	unsigned long flags;

	if (p->ch) {
		rc = smd_close(p->ch);
		spin_lock_irqsave(&p->lock, flags);
		p->ch = 0;
		spin_unlock_irqrestore(&p->lock, flags);
		return rc;
	} else
		return -EBADF;
}
static ssize_t smd_lge_release(struct inode *ip, struct file *fp)
{
	int ret = 0;

	SMD_LGE_INFO("%s \n", __func__);
	if (psmd_device->ch != 0) {
		ret = smd_close(psmd_device->ch);
		psmd_device->ch = 0;
	}

	kfree(psmd_device->tx_buff);
	kfree(psmd_device->rx_buff);

	return ret;
}
int apr_tal_close(struct apr_svc_ch_dev *apr_ch)
{
	int r;

	if (!apr_ch->ch)
		return -EINVAL;

	mutex_lock(&apr_ch->m_lock);
	r = smd_close(apr_ch->ch);
	apr_ch->ch = NULL;
	apr_ch->func = NULL;
	apr_ch->priv = NULL;
	mutex_unlock(&apr_ch->m_lock);
	return r;
}