static uint32_t send_cmd_to_user(uint32_t command_id)
{
    uint32_t ret = TUI_DCI_ERR_NO_RESPONSE;

    /* Init shared variables */
    g_cmd_id = command_id;
    g_user_rsp.id = TLC_TUI_CMD_NONE;
    g_user_rsp.return_code = TLC_TUI_ERR_UNKNOWN_CMD;


    /* S.LSI : Clean up previous response. */
    complete_all(&io_comp);
    INIT_COMPLETION(io_comp);

    /* Give way to ioctl thread */
    complete(&dci_comp);
    pr_debug("send_cmd_to_user: give way to ioctl thread\n");

    /* Wait for ioctl thread to complete */
    wait_for_completion_interruptible(&io_comp);
    pr_debug("send_cmd_to_user: Got an answer from ioctl thread.\n");
    INIT_COMPLETION(io_comp);

    /* Check id of the cmd processed by ioctl thread (paranoia) */
    if (g_user_rsp.id != command_id) {
        pr_debug("ERROR %s: Wrong response id 0x%08x iso 0x%08x\n",
                 __func__, dci->nwd_rsp.id, RSP_ID(command_id));
        ret = TUI_DCI_ERR_INTERNAL_ERROR;
    } else {
        /* retrieve return code */
        switch (g_user_rsp.return_code) {
        case TLC_TUI_OK:
            ret = TUI_DCI_OK;
            break;
        case TLC_TUI_ERROR:
            ret = TUI_DCI_ERR_INTERNAL_ERROR;
            break;
        case TLC_TUI_ERR_UNKNOWN_CMD:
            ret = TUI_DCI_ERR_UNKNOWN_CMD;
            break;
        }
    }

    return ret;
}
/**
 * Read charge-current via ADC.
 *
 * The ISL CCMON (charge-current-monitor) pin is connected to
 * the PMIC MPP#X pin.
 * This not required when notify_by_pmic is used where the PMIC
 * uses BMS to notify the ISL on charging-done / charge-resume.
 */
static int isl_read_adc(int channel, int *mv_reading)
{
	int ret;
	void *h;
	struct adc_chan_result adc_chan_result;
	struct completion  conv_complete_evt;

	pr_debug("called for %d\n", channel);
	ret = adc_channel_open(channel, &h);
	if (ret) {
		pr_err("couldnt open channel %d ret=%d\n", channel, ret);
		goto out;
	}
	init_completion(&conv_complete_evt);
	ret = adc_channel_request_conv(h, &conv_complete_evt);
	if (ret) {
		pr_err("couldnt request conv channel %d ret=%d\n",
						channel, ret);
		goto out;
	}
	ret = wait_for_completion_interruptible(&conv_complete_evt);
	if (ret) {
		pr_err("wait interrupted channel %d ret=%d\n", channel, ret);
		goto out;
	}
	ret = adc_channel_read_result(h, &adc_chan_result);
	if (ret) {
		pr_err("couldnt read result channel %d ret=%d\n",
						channel, ret);
		goto out;
	}
	ret = adc_channel_close(h);
	if (ret)
		pr_err("couldnt close channel %d ret=%d\n", channel, ret);
	if (mv_reading)
		*mv_reading = (int)adc_chan_result.measurement;

	pr_debug("done for %d\n", channel);
	return adc_chan_result.physical;
out:
	*mv_reading = 0;
	pr_debug("done with error for %d\n", channel);

	return -EINVAL;
}
Exemplo n.º 3
0
static int exec_test_job(struct device *ksdev, u32 *jobdesc)
{
	struct exec_test_result testres;
	struct caam_drv_private_sm *kspriv;
	int rtn = 0;

	kspriv = dev_get_drvdata(ksdev);

	init_completion(&testres.completion);

	rtn = caam_jr_enqueue(kspriv->smringdev, jobdesc, exec_test_done,
			      &testres);
	if (!rtn) {
		wait_for_completion_interruptible(&testres.completion);
		rtn = testres.error;
	}
	return rtn;
}
Exemplo n.º 4
0
static long cptest_ioctl(struct file *filp,unsigned int cmd,unsigned long arg)
{
	printk("%s,Enter\n",__func__);
	switch(cmd){
	case WAIT_FOR_CP:
		printk("%s, wait_for_completion.\n",__func__);
		wait_for_completion_interruptible(&cp_dev->cp_completion);
		break;
	case COMPLETE_CP:
		printk("%s, wake_up_completion.\n",__func__);
		complete(&cp_dev->cp_completion);
		break;
	default:
		pr_err("%s, illegal cmd.\n",__func__);
		return -ENOIOCTLCMD;
	}
	return 0;
}
int wlan_logging_sock_deactivate_svc(void)
{

	nl_srv_unregister(ANI_NL_MSG_LOG, wlan_logging_proc_sock_rx_msg);
	clear_default_logtoapp_log_level();
	gapp_pid = INVALID_PID;

	gwlan_logging.exit = true;
	INIT_COMPLETION(gwlan_logging.shutdown_comp);
	wake_up_interruptible(&gwlan_logging.wait_queue);
	wait_for_completion_interruptible(&gwlan_logging.shutdown_comp);

	vfree(gplog_msg);

	pr_info("%s: Deactivate wlan_logging svc\n", __func__);

	return 0;
}
static void switch_work_f(struct work_struct *work)
{
#if 0

	int rc, i;
	u32 res = 0;
	struct adc_chan_result adc_result;
	struct pm8058_othc *dd =
		container_of(work, struct pm8058_othc, switch_work);
	DECLARE_COMPLETION_ONSTACK(adc_wait);
	u8 num_adc_samples = dd->switch_config->num_adc_samples;

	/* sleep for settling time */
	msleep(dd->switch_config->voltage_settling_time_ms);

	for (i = 0; i < num_adc_samples; i++) {
		rc = adc_channel_request_conv(dd->adc_handle, &adc_wait);
		if (rc) {
			pr_err("adc_channel_request_conv failed\n");
			goto bail_out;
		}
		rc = wait_for_completion_interruptible(&adc_wait);
		if (rc) {
			pr_err("wait_for_completion_interruptible failed\n");
			goto bail_out;
		}
		rc = adc_channel_read_result(dd->adc_handle, &adc_result);
		if (rc) {
			pr_err("adc_channel_read_result failed\n");
			goto bail_out;
		}
		res += adc_result.physical;
	}
bail_out:
	if (i == num_adc_samples && num_adc_samples != 0) {
		res /= num_adc_samples;
		othc_report_switch(dd, res);
	} else
		pr_err("Insufficient ADC samples\n");

	enable_irq(dd->othc_irq_sw);
#endif    
  
}
Exemplo n.º 7
0
static int pwm_ir_tx_transmit_with_timer(struct pwm_ir_packet *pkt)
{
    int rc = 0;

    init_completion(&pkt->done);

    hrtimer_init(&pkt->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
    pkt->timer.function = pwm_ir_tx_timer;

    hrtimer_start(&pkt->timer, ns_to_ktime(0), HRTIMER_MODE_REL);

    rc = wait_for_completion_interruptible(&pkt->done);
    if (rc != 0) { /* signal exit immediately */
        pkt->abort = true;
        wait_for_completion(&pkt->done);
    }

    return pkt->next ? : -ERESTARTSYS;
}
Exemplo n.º 8
0
static int
gpio_pwm_stop_sync(struct pwm_channel *p)
{
    struct gpio_pwm *gp = to_gpio_pwm(p);
    int ret;
    int was_on = hrtimer_active(&gp->timer);

    if (was_on) {
        do {
            init_completion(&p->complete);
            set_bit(FLAG_STOP, &p->flags);
            ret = wait_for_completion_interruptible(&p->complete);
            if (ret)
                return ret;
        } while (p->flags & BIT(FLAG_STOP));
    }

    return was_on;
}
Exemplo n.º 9
0
static int target_xcopy_issue_pt_cmd(struct xcopy_pt_cmd *xpt_cmd)
{
	struct se_cmd *se_cmd = &xpt_cmd->se_cmd;
	sense_reason_t sense_rc;

	sense_rc = transport_generic_new_cmd(se_cmd);
	if (sense_rc)
		return -EINVAL;

	if (se_cmd->data_direction == DMA_TO_DEVICE)
		target_execute_cmd(se_cmd);

	wait_for_completion_interruptible(&xpt_cmd->xpt_passthrough_sem);

	pr_debug("target_xcopy_issue_pt_cmd(): SCSI status: 0x%02x\n",
			se_cmd->scsi_status);

	return (se_cmd->scsi_status) ? -EINVAL : 0;
}
int tlc_wait_cmd(uint32_t *cmd_id)
{
    /* Create the TlcTui Main thread and start secure driver (only
       1st time) */
    if (dr_session_handle.session_id == 0) {
        thread_id = kthread_run(main_thread, NULL, "dci_thread");
        if (!thread_id) {
            pr_debug(KERN_ERR "Unable to start Trusted UI main thread\n");
            return -EFAULT;
        }
    }

    /* Wait for signal from DCI handler */
    /* In case of an interrupted sys call, return with -EINTR */
    wait_for_completion_interruptible(&dci_comp);
    INIT_COMPLETION(dci_comp);

    *cmd_id = g_cmd_id;
    return 0;
}
Exemplo n.º 11
0
static int erase_write (struct mtd_info *mtd, unsigned long pos,
			int len, const char *buf)
{
	struct erase_info erase = {};
	DECLARE_COMPLETION(erase_completion);
	size_t retlen;
	int ret;

	/*
	 * First, let's erase the flash block.
	 */

	erase.mtd = mtd;
	erase.priv = (u_long)&erase_completion;
	erase.callback = erase_callback;
	erase.addr = pos;
	erase.len = len;


	ret = mtd->erase(mtd, &erase);
	if (ret) {
		printk (KERN_WARNING "mtdblock: erase of region [0x%lx, 0x%x] "
				     "on \"%s\" failed\n",
			pos, len, mtd->name);
		return ret;
	}

	wait_for_completion_interruptible(&erase_completion);

	/*
	 * Next, writhe data to flash.
	 */

	ret = mtd->write(mtd, pos, len, &retlen, buf);
	if (ret)
		return ret;
	if (retlen != len)
		return -EIO;
	return 0;
}
Exemplo n.º 12
0
static void broadsheet_watchdog_thread_body(void)
{
    // Repair us in one way or another if we still should.
    //
    if ( broadsheet_watchdog_timer_active && broadsheet_watchdog_timer_primed )
    {
        broadsheet_watchdog_timer_primed = false;
        
        // Reset Broadsheet if it's not still ready.
        //
        if ( !BS_STILL_READY() && (EINKFB_SUCCESS == EINKFB_LOCK_ENTRY()) )
        {
            // If we were forcing the hardware not to be ready, unforce it now.
            // Forcing the hardware not to be ready is for debugging purposes,
            // and we treat it as a one-shot.
            //
            controller_set_force_hw_not_ready(false);
            
            bs_sw_init(FULL_BRINGUP_CONTROLLER, DONT_BRINGUP_PANEL);
            bs_cmd_ld_img_upd_data(fx_update_partial, UPD_DATA_RESTORE);
            EINKFB_LOCK_EXIT();
            
            // If Broadsheet's still not ready after we've tried to bring it
            // back up, tell the eInk HAL that we're in real trouble.
            //
            if ( !BS_STILL_READY() )
                EINKFB_NEEDS_RESET();
        }
        
        // Do a panel update repair if it hasn't already been done.
        //
        if ( !BS_UPD_REPAIR() && (EINKFB_SUCCESS == EINKFB_LOCK_ENTRY()) )
        {
            bs_cmd_upd_repair();
            EINKFB_LOCK_EXIT();
        }
    }
    
    wait_for_completion_interruptible(&broadsheet_watchdog_thread_complete);
}
static uint32_t sendCmdToUser(uint32_t commandId)
{
	dciReturnCode_t ret = TUI_DCI_ERR_NO_RESPONSE;

	/* Init shared variables */
	gCmdId = commandId;
	gUserRsp.id = TLC_TUI_CMD_NONE;
	gUserRsp.returnCode = TLC_TUI_ERR_UNKNOWN_CMD;
	
	/* Give way to ioctl thread */
	complete(&dciComp);
	pr_debug("sendCmdToUser: give way to ioctl thread\n");

	/* Wait for ioctl thread to complete */
	wait_for_completion_interruptible(&ioComp);
	pr_debug("sendCmdToUser: Got an answer from ioctl thread.\n");
	INIT_COMPLETION(ioComp);

	/* Check id of the cmd processed by ioctl thread (paranoïa) */
	if (gUserRsp.id != commandId) {
		pr_debug("sendCmdToUser ERROR: Wrong response id 0x%08x iso 0x%08x\n",
				pDci->nwdRsp.id, RSP_ID(commandId));
		ret = TUI_DCI_ERR_INTERNAL_ERROR;
	} else {
		/* retrieve return code */
		switch (gUserRsp.returnCode) {
		case TLC_TUI_OK:
			ret = TUI_DCI_OK;
			break;
		case TLC_TUI_ERROR:
			ret = TUI_DCI_ERR_INTERNAL_ERROR;
			break;
		case TLC_TUI_ERR_UNKNOWN_CMD:
			ret = TUI_DCI_ERR_UNKNOWN_CMD;
			break;
		}
	}

	return ret;
}
Exemplo n.º 14
0
static void execute_ftrace_cmd(char* cmd)
{
	int ret;

	if ( get_radio_flag() == 0 )
		return;

	//wait until ftrace cmd can be executed
	ret = wait_for_completion_interruptible(&ftrace_cmd_can_be_executed);
	INIT_COMPLETION(ftrace_cmd_can_be_executed);
	if (!ret) {
		//copy cmd to ftrace_cmd buffer
		mutex_lock(&ftrace_cmd_lock);
		memset(ftrace_cmd, 0, sizeof(ftrace_cmd));
		strcpy(ftrace_cmd, cmd);
		pr_info("%s(%s)\n", __func__, ftrace_cmd);
		mutex_unlock(&ftrace_cmd_lock);

		//signal the waiting thread there is pending cmd
		complete(&ftrace_cmd_pending);
	}
}
static int accessory_adc_detect(struct pm8058_othc *dd, int accessory)
{

	int rc;
	u32 res;
	struct adc_chan_result accessory_adc_result;
	DECLARE_COMPLETION_ONSTACK(accessory_adc_wait);

	rc = adc_channel_request_conv(dd->accessory_adc_handle,
						&accessory_adc_wait);
	if (rc) {
		pr_err("adc_channel_request_conv failed\n");
		goto adc_failed;
	}
	rc = wait_for_completion_interruptible(&accessory_adc_wait);
	if (rc) {
		pr_err("wait_for_completion_interruptible failed\n");
		goto adc_failed;
	}
	rc = adc_channel_read_result(dd->accessory_adc_handle,
						&accessory_adc_result);
	if (rc) {
		pr_err("adc_channel_read_result failed\n");
		goto adc_failed;
	}

	res = accessory_adc_result.physical;

	if (res >= dd->accessory_info[accessory].adc_thres.min_threshold &&
		res <= dd->accessory_info[accessory].adc_thres.max_threshold) {
		pr_debug("Accessory on ADC detected!, ADC Value = %u\n", res);
		return 1;
	}

adc_failed:
    

	return 0;
}
Exemplo n.º 16
0
int tegra_dc_wait_for_vsync(struct tegra_dc *dc)
{
	int ret = -ENOTTY;

	if (!(dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE) || !dc->enabled)
		return ret;

	/*
	 * Logic is as follows
	 * a) Indicate we need a vblank.
	 * b) Wait for completion to be signalled from isr.
	 * c) Initialize completion for next iteration.
	 */

	tegra_dc_hold_dc_out(dc);
	dc->out->user_needs_vblank = true;

	ret = wait_for_completion_interruptible(&dc->out->user_vblank_comp);
	init_completion(&dc->out->user_vblank_comp);
	tegra_dc_release_dc_out(dc);

	return ret;
}
Exemplo n.º 17
0
void r8712_usb_write_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
{
	unsigned int pipe;
	struct _adapter *padapter = (struct _adapter *)pintfhdl->adapter;
	struct intf_priv *pintfpriv = pintfhdl->pintfpriv;
	struct io_queue *pio_queue = padapter->pio_queue;
	struct dvobj_priv *pdvobj = (struct dvobj_priv *)pintfpriv->intf_dev;
	struct usb_device *pusbd = pdvobj->pusbdev;
	struct urb *piorw_urb = pintfpriv->piorw_urb;

	if ((padapter->bDriverStopped) || (padapter->bSurpriseRemoved) ||
	    (padapter->pwrctrlpriv.pnp_bstop_trx))
		return;
	/* translate DMA FIFO addr to pipehandle */
	pipe = ffaddr2pipehdl(pdvobj, addr);
	if (pipe == 0)
		return;
	usb_fill_bulk_urb(piorw_urb, pusbd, pipe,
			  wmem, cnt, usb_write_mem_complete,
			  pio_queue);
	usb_submit_urb(piorw_urb, GFP_ATOMIC);
	wait_for_completion_interruptible(&pintfpriv->io_retevt_comp);
}
static int debug_log(struct ipc_log_context *ilctxt,
		     char *buff, int size, int cont)
{
	int i = 0;
	int ret;

	if (size < MAX_MSG_DECODED_SIZE) {
		pr_err("%s: buffer size %d < %d\n", __func__, size,
			MAX_MSG_DECODED_SIZE);
		return -ENOMEM;
	}
	do {
		i = ipc_log_extract(ilctxt, buff, size - 1);
		if (cont && i == 0) {
			ret = wait_for_completion_interruptible(
				&ilctxt->read_avail);
			if (ret < 0)
				return ret;
		}
	} while (cont && i == 0);

	return i;
}
Exemplo n.º 19
0
void mdp_dma_s_update(struct msm_fb_data_type *mfd)
{
	down(&mfd->dma->mutex);
	if ((mfd) && (!mfd->dma->busy) && (mfd->panel_power_on)) {
		mfd->dma->busy = TRUE;
		INIT_COMPLETION(mfd->dma->comp);

		down(&mfd->sem);
		mfd->ibuf_flushed = TRUE;
		mdp_dma_s_update_lcd(mfd);
		up(&mfd->sem);

		// wait until DMA finishes the current job
		wait_for_completion_interruptible(&mfd->dma->comp);

		// signal if pan function is waiting for the update completion
		if (mfd->pan_waiting) {
			mfd->pan_waiting = FALSE;
			complete(&mfd->pan_comp);
		}
	}
	up(&mfd->dma->mutex);
}
Exemplo n.º 20
0
static int msm_ispif_intf_reset(uint8_t intftype)
{
	int rc = 0;
	uint32_t data;

	switch (intftype) {
	case PIX0:
		data = (0x1 << STROBED_RST_EN) +
			(0x1 << PIX_VFE_RST_STB) +
			(0x1 << PIX_CSID_RST_STB);
		msm_io_w(data, ispif->base + ISPIF_RST_CMD_ADDR);
		break;

	case RDI0:
		data = (0x1 << STROBED_RST_EN) +
			(0x1 << RDI_VFE_RST_STB)  +
			(0x1 << RDI_CSID_RST_STB);
		msm_io_w(data, ispif->base + ISPIF_RST_CMD_ADDR);
		break;

	case RDI1:
		data = (0x1 << STROBED_RST_EN) +
			(0x1 << RDI_1_VFE_RST_STB) +
			(0x1 << RDI_1_CSID_RST_STB);
		msm_io_w(data, ispif->base + ISPIF_RST_CMD_ADDR);
		break;

	default:
		rc = -EINVAL;
		break;
	}
	if (rc >= 0)
		rc = wait_for_completion_interruptible(
				&ispif->reset_complete);

	return rc;
}
static int mdss_mdp_video_prepare(struct mdss_mdp_ctl *ctl, void *arg)
{
	struct mdss_mdp_video_ctx *ctx;

	ctx = (struct mdss_mdp_video_ctx *) ctl->priv_data;
	if (!ctx) {
		pr_err("invalid ctx\n");
		return -ENODEV;
	}

	if (ctx->timegen_en) {
		u32 intr_type = MDSS_MDP_IRQ_PING_PONG_COMP;

		pr_debug("waiting for ping pong %d done\n", ctx->pp_num);
		mdss_mdp_set_intr_callback(intr_type, ctx->pp_num,
					   mdss_mdp_video_pp_intr_done, ctx);
		mdss_mdp_irq_enable(intr_type, ctx->pp_num);

		wait_for_completion_interruptible(&ctx->pp_comp);
		mdss_mdp_irq_disable(intr_type, ctx->pp_num);
	}

	return 0;
}
Exemplo n.º 22
0
/*
 * This thread processes interrupts reported by the Primary Interrupt Handler.
 */
static int twl6030_irq_thread(void *data)
{
	long irq = (long)data;
	static unsigned i2c_errors;
	static const unsigned max_i2c_errors = 100;
	int ret;

	current->flags |= PF_NOFREEZE;

	while (!kthread_should_stop()) {
		int i;
		union {
		u8 bytes[4];
		u32 int_sts;
		} sts;
		u32 int_sts; /* sts.int_sts converted to CPU endianness */

		/* Wait for IRQ, then read PIH irq status (also blocking) */
		wait_for_completion_interruptible(&irq_event);

		/* read INT_STS_A, B and C in one shot using a burst read */
		ret = twl_i2c_read(TWL_MODULE_PIH, sts.bytes,
				REG_INT_STS_A, 3);
		if (ret) {
			pr_warning("twl6030: I2C error %d reading PIH ISR\n",
					ret);
			if (++i2c_errors >= max_i2c_errors) {
				printk(KERN_ERR "Maximum I2C error count"
						" exceeded.  Terminating %s.\n",
						__func__);
				break;
			}
			complete(&irq_event);
			continue;
		}



		sts.bytes[3] = 0; /* Only 24 bits are valid*/

		/*
		 * Since VBUS status bit is not reliable for VBUS disconnect
		 * use CHARGER VBUS detection status bit instead.
		 */
		if (sts.bytes[2] & 0x10)
			sts.bytes[2] |= 0x08;

		int_sts = le32_to_cpu(sts.int_sts);
		for (i = 0; int_sts; int_sts >>= 1, i++) {
			local_irq_disable();
			if (int_sts & 0x1) {
				int module_irq = twl6030_irq_base +
					twl6030_interrupt_mapping[i];
				generic_handle_irq(module_irq);

			}
		local_irq_enable();
		}
		ret = twl_i2c_write(TWL_MODULE_PIH, sts.bytes,
				REG_INT_STS_A, 3); /* clear INT_STS_A */
		if (ret)
			pr_warning("twl6030: I2C error in clearing PIH ISR\n");

		enable_irq(irq);
	}

	return 0;
}
Exemplo n.º 23
0
struct iscsi_conn *iscsi_tx_thread_pre_handler(struct iscsi_thread_set *ts)
{
	int ret;

	spin_lock_bh(&ts->ts_state_lock);
	if (ts->create_threads) {
		spin_unlock_bh(&ts->ts_state_lock);
		goto sleep;
	}

	flush_signals(current);

	if (ts->delay_inactive && (--ts->thread_count == 0)) {
		spin_unlock_bh(&ts->ts_state_lock);
		iscsi_del_ts_from_active_list(ts);

		if (!iscsit_global->in_shutdown)
			iscsi_deallocate_extra_thread_sets();

		iscsi_add_ts_to_inactive_list(ts);
		spin_lock_bh(&ts->ts_state_lock);
	}
	if ((ts->status == ISCSI_THREAD_SET_RESET) &&
	    (ts->thread_clear & ISCSI_CLEAR_TX_THREAD))
		complete(&ts->tx_restart_comp);

	ts->thread_clear &= ~ISCSI_CLEAR_TX_THREAD;
	spin_unlock_bh(&ts->ts_state_lock);
sleep:
	ret = wait_for_completion_interruptible(&ts->tx_start_comp);
	pr_info("%s: %s/%d (thread set %d) got %d waiting for tx_start_comp\n",
		__func__, current->comm, task_pid_nr(current), ts->thread_id, ret);
	if (ret != 0)
		return NULL;

	if (iscsi_signal_thread_pre_handler(ts) < 0)
		return NULL;

	if (!ts->conn) {
		pr_err("struct iscsi_thread_set->conn is NULL for "
			" thread_id: %d, going back to sleep\n",
			ts->thread_id);
		goto sleep;
	}

	iscsi_check_to_add_additional_sets();
	/*
	 * From the TX thread, up the tx_post_start_comp that the RX Thread is
	 * sleeping on in iscsi_rx_thread_pre_handler(), then up the
	 * rx_post_start_comp that iscsi_activate_thread_set() is sleeping on.
	 */
	spin_lock_bh(&ts->ts_state_lock);
	ts->thread_clear |= ISCSI_CLEAR_TX_THREAD;
	spin_unlock_bh(&ts->ts_state_lock);
	complete(&ts->tx_post_start_comp);
	complete(&ts->rx_post_start_comp);

	spin_lock_bh(&ts->ts_state_lock);
	ts->status = ISCSI_THREAD_SET_ACTIVE;
	spin_unlock_bh(&ts->ts_state_lock);

	pr_info("%s/%d: returning connection %p for tx thread\n",
		current->comm, task_pid_nr(current), ts->conn);

	return ts->conn;
}
Exemplo n.º 24
0
/***************************************************************************************
 *
 * Sync up the buffers before we shutdown, else under-run errors will happen
 *
 **************************************************************************************/
int audio_sync(struct file *file)
{
	audio_state_t *state = file->private_data;
	audio_stream_t *s = state->output_stream;
	audio_buf_t *b;
	u_int shiftval = 0;
	unsigned long flags;

	DECLARE_WAITQUEUE(wait, current);

	FN_IN;

	if (!(file->f_mode & FMODE_WRITE) || !s->buffers || s->mapped) {
		FN_OUT(1);
		return 0;
	}

	/*
	 * Send current buffer if it contains data.  Be sure to send
	 * a full sample count.
	 */
	b = &s->buffers[s->usr_head];
	if (b->offset &= ~3) {
		/* Wait for a buffer to become free */
		if (wait_for_completion_interruptible(&s->wfc))
			return 0;
		/*
		 * HACK ALERT !
		 * To avoid increased complexity in the rest of the code
		 * where full fragment sizes are assumed, we cheat a little
		 * with the start pointer here and don't forget to restore
		 * it later.
		 */
		
		/* As this is a last frag we need only one dma channel
		 * to complete. So it's need to unlink dma channels
		 * to avoid empty dma work.
		 */
		if (!cpu_is_omap1510() && AUDIO_QUEUE_EMPTY(s))
			omap_sound_dma_unlink_lch(s);

		shiftval = s->fragsize - b->offset;
		b->offset = shiftval;
		b->dma_addr -= shiftval;
		b->data -= shiftval;
		local_irq_save(flags);
		s->bytecount -= shiftval;
		if (++s->usr_head >= s->nbfrags)
			s->usr_head = 0;

		s->pending_frags++;
		audio_process_dma(s);
		local_irq_restore(flags);
	}

	/* Let's wait for all buffers to complete */
	set_current_state(TASK_INTERRUPTIBLE);
	add_wait_queue(&s->wq, &wait);
	while ((s->pending_frags || (s->wfc.done < s->nbfrags))
	       && !signal_pending(current)) {
		schedule();
		set_current_state(TASK_INTERRUPTIBLE);
	}
	set_current_state(TASK_RUNNING);
	remove_wait_queue(&s->wq, &wait);

	/* undo the pointer hack above */
	if (shiftval) {
		local_irq_save(flags);
		b->dma_addr += shiftval;
		b->data += shiftval;
		/* ensure sane DMA code behavior if not yet processed */
		if (b->offset != 0)
			b->offset = s->fragsize;
		local_irq_restore(flags);
	}

	FN_OUT(0);
	return 0;
}
Exemplo n.º 25
0
int hmac_md5(v_U8_t *key, v_U8_t ksize, char *plaintext, v_U8_t psize,
                v_U8_t *output, v_U8_t outlen)
{
    int ret = 0;
    struct crypto_ahash *tfm;
    struct scatterlist sg;
    struct ahash_request *req;
    struct hmac_md5_result tresult;
    void *hash_buff = NULL;

    unsigned char hash_result[64];
    int i;

    memset(output, 0, outlen);

    init_completion(&tresult.completion);

    tfm = wcnss_wlan_crypto_alloc_ahash("hmac(md5)", CRYPTO_ALG_TYPE_AHASH,
                                        CRYPTO_ALG_TYPE_AHASH_MASK);
    if (IS_ERR(tfm)) {
        VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "crypto_alloc_ahash failed");
                ret = PTR_ERR(tfm);
                goto err_tfm;
    }

    req = ahash_request_alloc(tfm, GFP_KERNEL);
    if (!req) {
        VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "failed to allocate request for hmac(md5)");
        ret = -ENOMEM;
        goto err_req;
    }

    ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
                                        hmac_md5_complete, &tresult);

    hash_buff = kzalloc(psize, GFP_KERNEL);
    if (!hash_buff) {
        VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "failed to kzalloc hash_buff");
        ret = -ENOMEM;
        goto err_hash_buf;
    }

    memset(hash_result, 0, 64);
    memcpy(hash_buff, plaintext, psize);
    sg_init_one(&sg, hash_buff, psize);

    if (ksize) {
        crypto_ahash_clear_flags(tfm, ~0);
        ret = wcnss_wlan_crypto_ahash_setkey(tfm, key, ksize);

        if (ret) {
            VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "crypto_ahash_setkey failed");
            goto err_setkey;
        }
    }

    ahash_request_set_crypt(req, &sg, hash_result, psize);
    ret = wcnss_wlan_crypto_ahash_digest(req);

    VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "ret 0x%x");

    switch (ret) {
        case 0:
            for (i=0; i< outlen; i++)
                    output[i] = hash_result[i];
            break;
        case -EINPROGRESS:
        case -EBUSY:
             ret = wait_for_completion_interruptible(&tresult.completion);
             if (!ret && !tresult.err) {
                  INIT_COMPLETION(tresult.completion);
                  break;
             } else {
                 VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "wait_for_completion_interruptible failed");
                 if (!ret)
                     ret = tresult.err;
                 goto out;
             }
        default:
              goto out;
        }

out:
err_setkey:
        kfree(hash_buff);
err_hash_buf:
        ahash_request_free(req);
err_req:
        wcnss_wlan_crypto_free_ahash(tfm);
err_tfm:
        return ret;
}
Exemplo n.º 26
0
static int crypto_gcm_setkey(struct crypto_aead *aead, const u8 *key,
                             unsigned int keylen)
{
    struct crypto_gcm_ctx *ctx = crypto_aead_ctx(aead);
    struct crypto_ahash *ghash = ctx->ghash;
    struct crypto_ablkcipher *ctr = ctx->ctr;
    struct {
        be128 hash;
        u8 iv[8];

        struct crypto_gcm_setkey_result result;

        struct scatterlist sg[1];
        struct ablkcipher_request req;
    } *data;
    int err;

    crypto_ablkcipher_clear_flags(ctr, CRYPTO_TFM_REQ_MASK);
    crypto_ablkcipher_set_flags(ctr, crypto_aead_get_flags(aead) &
                                CRYPTO_TFM_REQ_MASK);

    err = crypto_ablkcipher_setkey(ctr, key, keylen);
    if (err)
        return err;

    crypto_aead_set_flags(aead, crypto_ablkcipher_get_flags(ctr) &
                          CRYPTO_TFM_RES_MASK);

    data = kzalloc(sizeof(*data) + crypto_ablkcipher_reqsize(ctr),
                   GFP_KERNEL);
    if (!data)
        return -ENOMEM;

    init_completion(&data->result.completion);
    sg_init_one(data->sg, &data->hash, sizeof(data->hash));
    ablkcipher_request_set_tfm(&data->req, ctr);
    ablkcipher_request_set_callback(&data->req, CRYPTO_TFM_REQ_MAY_SLEEP |
                                    CRYPTO_TFM_REQ_MAY_BACKLOG,
                                    crypto_gcm_setkey_done,
                                    &data->result);
    ablkcipher_request_set_crypt(&data->req, data->sg, data->sg,
                                 sizeof(data->hash), data->iv);

    err = crypto_ablkcipher_encrypt(&data->req);
    if (err == -EINPROGRESS || err == -EBUSY) {
        err = wait_for_completion_interruptible(
                  &data->result.completion);
        if (!err)
            err = data->result.err;
    }

    if (err)
        goto out;

    crypto_ahash_clear_flags(ghash, CRYPTO_TFM_REQ_MASK);
    crypto_ahash_set_flags(ghash, crypto_aead_get_flags(aead) &
                           CRYPTO_TFM_REQ_MASK);
    err = crypto_ahash_setkey(ghash, (u8 *)&data->hash, sizeof(be128));
    crypto_aead_set_flags(aead, crypto_ahash_get_flags(ghash) &
                          CRYPTO_TFM_RES_MASK);

out:
    kfree(data);
    return err;
}
Exemplo n.º 27
0
long mdm_modem_ioctl(struct file *filp, unsigned int cmd,
				unsigned long arg)
{
	int status, ret = 0;

	if (_IOC_TYPE(cmd) != CHARM_CODE) {
		pr_err("%s: invalid ioctl code\n", __func__);
		return -EINVAL;
	}

	pr_debug("%s: Entering ioctl cmd = %d\n", __func__, _IOC_NR(cmd));
	switch (cmd) {
	case WAKE_CHARM:
		pr_info("%s: Powering on mdm\n", __func__);
		mdm_drv->mdm_ready = 0;	
		mdm_drv->mdm_hsic_reconnectd = 0;
		mdm_drv->ops->power_on_mdm_cb(mdm_drv);
		break;
	case CHECK_FOR_BOOT:
		if (gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0)
			put_user(1, (unsigned long __user *) arg);
		else
			put_user(0, (unsigned long __user *) arg);
		break;
	case NORMAL_BOOT_DONE:
		{
			int ret_mdm_hsic_reconnectd = 0;
			pr_debug("%s: check if mdm is booted up\n", __func__);
			get_user(status, (unsigned long __user *) arg);
			if (status) {
				pr_debug("%s: normal boot failed\n", __func__);
				mdm_drv->mdm_boot_status = -EIO;
			} else {
				pr_info("%s: normal boot done\n", __func__);
				mdm_drv->mdm_boot_status = 0;
			}
			
	                mdm_status_change_notified = false;
	                queue_work_on(0, mdm_gpio_monitor_queue, &mdm_status_check_work);
	                
			mdm_drv->mdm_ready = 1;

			if (mdm_drv->ops->normal_boot_done_cb != NULL)
				mdm_drv->ops->normal_boot_done_cb(mdm_drv);

			ret_mdm_hsic_reconnectd = mdm_hsic_reconnectd_check_fn();

			if ( ret_mdm_hsic_reconnectd == 1 ) {
				pr_info("%s: ret_mdm_hsic_reconnectd == 1\n", __func__);
			} else {
				pr_info("%s: ret_mdm_hsic_reconnectd == 0\n", __func__);
			}

			if (!first_boot)
				complete(&mdm_boot);
			else
				first_boot = 0;
		}
		break;
	case RAM_DUMP_DONE:
		pr_debug("%s: mdm done collecting RAM dumps\n", __func__);
		get_user(status, (unsigned long __user *) arg);
		if (status)
			mdm_drv->mdm_ram_dump_status = -EIO;
		else {
			pr_info("%s: ramdump collection completed\n", __func__);
			mdm_drv->mdm_ram_dump_status = 0;
		}
		complete(&mdm_ram_dumps);
		break;
	case WAIT_FOR_RESTART:
		pr_debug("%s: wait for mdm to need images reloaded\n",
				__func__);

		if (mdm_drv) {
	        dump_gpio("MDM2AP_STATUS", mdm_drv->mdm2ap_status_gpio);
	        dump_gpio("MDM2AP_ERRFATAL", mdm_drv->mdm2ap_errfatal_gpio);
		}

		ret = wait_for_completion_interruptible(&mdm_needs_reload);
		if (!ret) {
			put_user(mdm_drv->boot_type,
					 (unsigned long __user *) arg);

			pr_err("%s: mdm_drv->boot_type:%d\n", __func__, mdm_drv->boot_type);
		}
		INIT_COMPLETION(mdm_needs_reload);
		break;
	case GET_MFG_MODE:
		pr_info("%s: board_mfg_mode()=%d\n", __func__, board_mfg_mode());
		put_user(board_mfg_mode(),
				 (unsigned long __user *) arg);
		break;
	case SET_MODEM_ERRMSG:
		pr_info("%s: Set modem fatal errmsg\n", __func__);
		ret = set_mdm_errmsg((void __user *) arg);
		break;
	case GET_RADIO_FLAG:
		pr_info("%s:get_radio_flag()=%x\n", __func__, get_radio_flag());
		put_user(get_radio_flag(),
				 (unsigned long __user *) arg);
		break;
	case EFS_SYNC_DONE:
		pr_info("%s: efs sync is done\n", __func__);
		break;
	case NV_WRITE_DONE:
		pr_info("%s: NV write done!\n", __func__);
		notify_mdm_nv_write_done();
		break;
	default:
		pr_err("%s: invalid ioctl cmd = %d\n", __func__, _IOC_NR(cmd));
		ret = -EINVAL;
		break;
	}

	return ret;
}
Exemplo n.º 28
0
void exit_lpapm_mode_mx50(int high_bus_freq)
{
	u32 reg;
	unsigned long flags;

	if (clk_get_usecount(pll1_sw_clk) == 1) {
		/* Relock PLL1 to 800MHz. */
		clk_set_parent(pll1_sw_clk, pll2);
		/* Set the divider to ARM_PODF to 3, cpu is at 160MHz. */
		__raw_writel(0x02, MXC_CCM_CACRR);

		clk_set_rate(pll1, cpu_wp_tbl[0].pll_rate);

		/* Set the divider to ARM_PODF to 5 before
		  * switching the parent.
		  */
		__raw_writel(0x4, MXC_CCM_CACRR);
		clk_set_parent(pll1_sw_clk, pll1);
	}

	if (!completion_done(&voltage_change_cmpl))
		wait_for_completion_interruptible(&voltage_change_cmpl);
	spin_lock_irqsave(&voltage_lock, flags);
	if (lp_voltage != LP_NORMAL_VOLTAGE) {
		INIT_COMPLETION(voltage_change_cmpl);
		lp_voltage = LP_NORMAL_VOLTAGE;
		if (!queue_work(voltage_wq, &voltage_change_handler))
			printk(KERN_ERR "WORK_NOT_ADDED\n");
		spin_unlock_irqrestore(&voltage_lock, flags);
		wait_for_completion_interruptible(&voltage_change_cmpl);
	} else {
		spin_unlock_irqrestore(&voltage_lock, flags);
		if (!completion_done(&voltage_change_cmpl))
			wait_for_completion_interruptible(&voltage_change_cmpl);
	}

	spin_lock_irqsave(&freq_lock, flags);
	if (!low_bus_freq_mode) {
		spin_unlock_irqrestore(&freq_lock, flags);
		return;
	}

	/* Temporarily set the dividers when the source is PLL3.
	 * No clock rate is above 133MHz.
	 */
	reg = __raw_readl(MXC_CCM_CBCDR);
	reg &= ~(MXC_CCM_CBCDR_AXI_A_PODF_MASK
		| MXC_CCM_CBCDR_AXI_B_PODF_MASK
		| MXC_CCM_CBCDR_AHB_PODF_MASK
		| MX50_CCM_CBCDR_WEIM_PODF_MASK);
	reg |= (1 << MXC_CCM_CBCDR_AXI_A_PODF_OFFSET
		|1 << MXC_CCM_CBCDR_AXI_B_PODF_OFFSET
		|1 << MXC_CCM_CBCDR_AHB_PODF_OFFSET
		|0 << MX50_CCM_CBCDR_WEIM_PODF_OFFSET);
	__raw_writel(reg, MXC_CCM_CBCDR);

	while (__raw_readl(MXC_CCM_CDHIPR) & 0xF)
		udelay(10);

	clk_set_parent(main_bus_clk, pll3);

	if (bus_freq_scaling_is_active && !high_bus_freq) {
		/* Set the dividers to the medium setpoint dividers */
		reg = __raw_readl(MXC_CCM_CBCDR);
		reg &= ~(MXC_CCM_CBCDR_AXI_A_PODF_MASK
			| MXC_CCM_CBCDR_AXI_B_PODF_MASK
			| MXC_CCM_CBCDR_AHB_PODF_MASK
			| MX50_CCM_CBCDR_WEIM_PODF_MASK);
		reg |= (1 << MXC_CCM_CBCDR_AXI_A_PODF_OFFSET
			|3 << MXC_CCM_CBCDR_AXI_B_PODF_OFFSET
			|5 << MXC_CCM_CBCDR_AHB_PODF_OFFSET
			|0 << MX50_CCM_CBCDR_WEIM_PODF_OFFSET);
		__raw_writel(reg, MXC_CCM_CBCDR);

		while (__raw_readl(MXC_CCM_CDHIPR) & 0xF)
			udelay(10);

		/*Set the main_bus_clk parent to be PLL2. */
		clk_set_parent(main_bus_clk, pll2);

		/* Set to the medium setpoint. */
		high_bus_freq_mode = 0;
		low_bus_freq_mode = 0;
		med_bus_freq_mode = 1;
		set_ddr_freq(ddr_med_rate);
	} else {
		/* Set the dividers to the default dividers */
		reg = __raw_readl(MXC_CCM_CBCDR);
		reg &= ~(MXC_CCM_CBCDR_AXI_A_PODF_MASK
			| MXC_CCM_CBCDR_AXI_B_PODF_MASK
			| MXC_CCM_CBCDR_AHB_PODF_MASK
			| MX50_CCM_CBCDR_WEIM_PODF_MASK);
		reg |= (0 << MXC_CCM_CBCDR_AXI_A_PODF_OFFSET
			|1 << MXC_CCM_CBCDR_AXI_B_PODF_OFFSET
			|2 << MXC_CCM_CBCDR_AHB_PODF_OFFSET
			|0 << MX50_CCM_CBCDR_WEIM_PODF_OFFSET);
		__raw_writel(reg, MXC_CCM_CBCDR);

		while (__raw_readl(MXC_CCM_CDHIPR) & 0xF)
			udelay(10);

		/*Set the main_bus_clk parent to be PLL2. */
		clk_set_parent(main_bus_clk, pll2);

		/* Set to the high setpoint. */
		high_bus_freq_mode = 1;
		low_bus_freq_mode = 0;
		med_bus_freq_mode = 0;
		set_ddr_freq(ddr_normal_rate);
	}
	spin_unlock_irqrestore(&freq_lock, flags);

	udelay(100);
}
Exemplo n.º 29
0
/*
get a split ipad/opad key

Split key generation-----------------------------------------------

[00] 0xb0810008    jobdesc: stidx=1 share=never len=8
[01] 0x04000014        key: class2->keyreg len=20
			@0xffe01000
[03] 0x84410014  operation: cls2-op sha1 hmac init dec
[04] 0x24940000     fifold: class2 msgdata-last2 len=0 imm
[05] 0xa4000001       jump: class2 local all ->1 [06]
[06] 0x64260028    fifostr: class2 mdsplit-jdk len=40
			@0xffe04000
*/
int gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len,
		  int split_key_pad_len, const u8 *key_in, u32 keylen,
		  u32 alg_op)
{
	u32 *desc;
	struct split_key_result result;
	dma_addr_t dma_addr_in, dma_addr_out;
	int ret = -ENOMEM;

	desc = kmalloc(CAAM_CMD_SZ * 6 + CAAM_PTR_SZ * 2, GFP_KERNEL | GFP_DMA);
	if (!desc) {
		dev_err(jrdev, "unable to allocate key input memory\n");
		return ret;
	}

	dma_addr_in = dma_map_single(jrdev, (void *)key_in, keylen,
				     DMA_TO_DEVICE);
	if (dma_mapping_error(jrdev, dma_addr_in)) {
		dev_err(jrdev, "unable to map key input memory\n");
		goto out_free;
	}

	dma_addr_out = dma_map_single(jrdev, key_out, split_key_pad_len,
				      DMA_FROM_DEVICE);
	if (dma_mapping_error(jrdev, dma_addr_out)) {
		dev_err(jrdev, "unable to map key output memory\n");
		goto out_unmap_in;
	}

	init_job_desc(desc, 0);
	append_key(desc, dma_addr_in, keylen, CLASS_2 | KEY_DEST_CLASS_REG);

	/* Sets MDHA up into an HMAC-INIT */
	append_operation(desc, alg_op | OP_ALG_DECRYPT | OP_ALG_AS_INIT);

	/*
	 * do a FIFO_LOAD of zero, this will trigger the internal key expansion
	 * into both pads inside MDHA
	 */
	append_fifo_load_as_imm(desc, NULL, 0, LDST_CLASS_2_CCB |
				FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST2);

	/*
	 * FIFO_STORE with the explicit split-key content store
	 * (0x26 output type)
	 */
	append_fifo_store(desc, dma_addr_out, split_key_len,
			  LDST_CLASS_2_CCB | FIFOST_TYPE_SPLIT_KEK);

#ifdef DEBUG
	print_hex_dump(KERN_ERR, "ctx.key@"__stringify(__LINE__)": ",
		       DUMP_PREFIX_ADDRESS, 16, 4, key_in, keylen, 1);
	print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
		       DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
#endif

	result.err = 0;
	init_completion(&result.completion);

	ret = caam_jr_enqueue(jrdev, desc, split_key_done, &result);
	if (!ret) {
		/* in progress */
		wait_for_completion_interruptible(&result.completion);
		ret = result.err;
#ifdef DEBUG
		print_hex_dump(KERN_ERR, "ctx.key@"__stringify(__LINE__)": ",
			       DUMP_PREFIX_ADDRESS, 16, 4, key_out,
			       split_key_pad_len, 1);
#endif
	}

	dma_unmap_single(jrdev, dma_addr_out, split_key_pad_len,
			 DMA_FROM_DEVICE);
out_unmap_in:
	dma_unmap_single(jrdev, dma_addr_in, keylen, DMA_TO_DEVICE);
out_free:
	kfree(desc);
	return ret;
}
Exemplo n.º 30
0
/*
 * This thread processes interrupts reported by the Primary Interrupt Handler.
 */
static int twl6030_irq_thread(void *data)
{
	long irq = (long)data;
	static unsigned i2c_errors;
	static const unsigned max_i2c_errors = 100;
	int ret;

	current->flags |= PF_NOFREEZE;

	while (!kthread_should_stop()) {
		int i;
		union {
		u8 bytes[4];
		u32 int_sts;
		} sts;
		u32 int_sts; /* sts.int_sts converted to CPU endianness */

		/* Wait for IRQ, then read PIH irq status (also blocking) */
		wait_for_completion_interruptible(&irq_event);

		/* read INT_STS_A, B and C in one shot using a burst read */
		ret = twl_i2c_read(TWL_MODULE_PIH, sts.bytes,
				REG_INT_STS_A, 3);
		if (ret) {
			pr_warning("twl6030: I2C error %d reading PIH ISR\n",
					ret);
			if (++i2c_errors >= max_i2c_errors) {
				printk(KERN_ERR "Maximum I2C error count"
						" exceeded.  Terminating %s.\n",
						__func__);
				break;
			}
			complete(&irq_event);
			continue;
		}



		sts.bytes[3] = 0; /* Only 24 bits are valid*/

		/*
		 * Since VBUS status bit is not reliable for VBUS disconnect
		 * use CHARGER VBUS detection status bit instead.
		 */
		if (sts.bytes[2] & 0x10)
			sts.bytes[2] |= 0x08;

		int_sts = le32_to_cpu(sts.int_sts);
		for (i = 0; int_sts; int_sts >>= 1, i++) {
			local_irq_disable();
			if (int_sts & 0x1) {
				int module_irq = twl6030_irq_base +
					twl6030_interrupt_mapping[i];
				generic_handle_irq(module_irq);

			}
		local_irq_enable();
		}

		/*
		 * NOTE:
		 * Simulation confirms that documentation is wrong w.r.t the
		 * interrupt status clear operation. A single *byte* write to
		 * any one of STS_A to STS_C register results in all three
		 * STS registers being reset. Since it does not matter which
		 * value is written, all three registers are cleared on a
		 * single byte write, so we just use 0x0 to clear.
		 */
		ret = twl_i2c_write_u8(TWL_MODULE_PIH, 0x00, REG_INT_STS_A);
		if (ret)
			pr_warning("twl6030: I2C error in clearing PIH ISR\n");

		enable_irq(irq);
	}

	return 0;
}