Beispiel #1
0
static int ss333_force_crash_exit(struct modem_ctl *mc)
{
	struct io_device *iod = mc->iod;
	struct link_device *ld = get_current_link(iod);

	mif_err("+++\n");

	mif_add_timer(&mc->crash_ack_timer, FORCE_CRASH_ACK_TIMEOUT,
			      handle_no_response_cp_crash, (unsigned long)mc);

	if (mc->wake_lock && !wake_lock_active(mc->wake_lock)) {
		wake_lock(mc->wake_lock);
		mif_err("%s->wake_lock locked\n", mc->name);
	}

	if (ld->off)
		ld->off(ld);

	gpio_set_value(mc->gpio_ap_dump_int, 1);
	mif_info("set ap_dump_int(%d) to high=%d\n",
		mc->gpio_ap_dump_int, gpio_get_value(mc->gpio_ap_dump_int));

	mif_err("---\n");
	return 0;
}
static int _cmc221_idpram_upload(struct dpram_link_device *dpld,
		struct dpram_dump_arg *dumparg)
{
	struct link_device *ld = &dpld->ld;
	int ret;
	u8 __iomem *src;
	int buff_size = CMC22x_DUMP_BUFF_SIZE;

	if ((dpld->dump_rcvd & 0x1) == 0)
		cmc221_idpram_send_msg(dpld, CMC22x_1ST_BUFF_READY);
	else
		cmc221_idpram_send_msg(dpld, CMC22x_2ND_BUFF_READY);

	init_completion(&dpld->dump_recv_done);

	mif_add_timer(&dpld->dump_timer, DUMP_WAIT_TIMEOUT,
		_cmc221_idpram_wait_dump, (unsigned long)dpld);

	ret = wait_for_completion_interruptible_timeout(
			&dpld->dump_recv_done, DUMP_TIMEOUT);
	if (!ret) {
		mif_info("%s: ERR! CP didn't send dump data!!!\n", ld->name);
		goto err_out;
	}

	if (cmc221_idpram_recv_msg(dpld) == CMC22x_CP_DUMP_END) {
		mif_info("%s: CMC22x_CP_DUMP_END\n", ld->name);
		return 0;
	}

	if ((dpld->dump_rcvd & 0x1) == 0)
		src = dpld->ul_map.buff;
	else
		src = dpld->ul_map.buff + CMC22x_DUMP_BUFF_SIZE;

	memcpy(dpld->buff, src, buff_size);

	ret = copy_to_user(dumparg->buff, dpld->buff, buff_size);
	if (ret < 0) {
		mif_info("%s: ERR! copy_to_user fail\n", ld->name);
		goto err_out;
	}

	dpld->dump_rcvd++;
	return buff_size;

err_out:
	return -EIO;
}
static int cmc221_idpram_upload(struct dpram_link_device *dpld,
			struct dpram_dump_arg *dumparg)
{
	int ret;
	u8 __iomem *src;
	int buff_size = CMC22x_DUMP_BUFF_SIZE;

	if ((dpld->crash_rcvd & 0x1) == 0)
		cmc221_idpram_send_msg(dpld, CMC22x_1ST_BUFF_READY);
	else
		cmc221_idpram_send_msg(dpld, CMC22x_2ND_BUFF_READY);

	init_completion(&dpld->crash_cmpl);

	mif_add_timer(&dpld->crash_timer, DUMP_WAIT_TIMEOUT,
		cmc221_idpram_wait_dump, (unsigned long)dpld);

	ret = wait_for_completion_timeout(&dpld->crash_cmpl, DUMP_TIMEOUT);
	if (!ret) {
		mif_info("ERR! no dump from CP!!!\n");
		goto err_out;
	}

	if (cmc221_idpram_recv_msg(dpld) == CMC22x_CP_DUMP_END) {
		mif_info("recv CMC22x_CP_DUMP_END\n");
		return 0;
	}

	if ((dpld->crash_rcvd & 0x1) == 0)
		src = dpld->ul_map.buff;
	else
		src = dpld->ul_map.buff + CMC22x_DUMP_BUFF_SIZE;

	memcpy(dpld->buff, src, buff_size);

	ret = copy_to_user(dumparg->buff, dpld->buff, buff_size);
	if (ret < 0) {
		mif_info("ERR! copy_to_user fail\n");
		goto err_out;
	}

	dpld->crash_rcvd++;
	return buff_size;

err_out:
	return -EIO;
}
static int ss300_force_crash_exit(struct modem_ctl *mc)
{
	mif_err("+++\n");

	mif_add_timer(&mc->crash_ack_timer, FORCE_CRASH_ACK_TIMEOUT,
			      handle_no_response_cp_crash, (unsigned long)mc);

	if (mc->wake_lock && !wake_lock_active(mc->wake_lock)) {
		wake_lock(mc->wake_lock);
		mif_err("%s->wake_lock locked\n", mc->name);
	}

	gpio_set_value(mc->gpio_ap_dump_int, 1);
	mif_info("set ap_dump_int(%d) to high=%d\n",
		mc->gpio_ap_dump_int, gpio_get_value(mc->gpio_ap_dump_int));

	mif_err("---\n");
	return 0;
}
Beispiel #5
0
static inline void start_pm_wdog(struct modem_link_pm *pm, enum pm_state state,
				 enum pm_state w_state, enum pm_event w_event,
				 unsigned long ms)
{
	struct pm_wdog *wdog = &pm->wdog;
	struct timer_list *timer = &wdog->timer;
	unsigned long expire = msecs_to_jiffies(ms);

	wdog->state = state;
	wdog->w_state = w_state;
	wdog->w_event = w_event;

#if 0
	snprintf(wdog->msg, MAX_STR_LEN, "%s: PM WDOG wait for {%s@%s}",
		 pm->link_name, pm_event2str(w_event), pm_state2str(state));
#endif

	mif_add_timer(timer, expire, pm_wdog_bark, (unsigned long)wdog);
}
Beispiel #6
0
static int trigger_force_cp_crash(struct dpram_link_device *dpld)
{
	struct link_device *ld = &dpld->ld;

	if (ld->mode == LINK_MODE_ULOAD) {
		mif_err("%s: CP crash is already in progress\n", ld->mc->name);
		return 0;
	}

	ld->mode = LINK_MODE_ULOAD;
	mif_err("%s: called by %pf\n", ld->name, __builtin_return_address(0));

	dpram_wake_up(dpld);

	send_intr(dpld, INT_CMD(INT_CMD_CRASH_EXIT));

	mif_add_timer(&dpld->crash_ack_timer, FORCE_CRASH_ACK_TIMEOUT,
			handle_no_crash_ack, (unsigned long)dpld);

	return 0;
}
static void _cmc221_idpram_wait_dump(unsigned long arg)
{
	struct dpram_link_device *dpld = (struct dpram_link_device *)arg;
	u16 msg;

	msg = cmc221_idpram_recv_msg(dpld);
	if (msg == CMC22x_CP_DUMP_END) {
		complete_all(&dpld->dump_recv_done);
		return;
	}

	if (((dpld->dump_rcvd & 0x1) == 0) && (msg == CMC22x_1ST_BUFF_FULL)) {
		complete_all(&dpld->dump_recv_done);
		return;
	}

	if (((dpld->dump_rcvd & 0x1) == 1) && (msg == CMC22x_2ND_BUFF_FULL)) {
		complete_all(&dpld->dump_recv_done);
		return;
	}

	mif_add_timer(&dpld->dump_timer, DUMP_WAIT_TIMEOUT,
		_cmc221_idpram_wait_dump, (unsigned long)dpld);
}
/**
@brief		trigger an enforced CP crash

@param mld	the pointer to a mem_link_device instance
*/
void mem_forced_cp_crash(struct mem_link_device *mld)
{
	struct link_device *ld = &mld->link_dev;
	struct modem_ctl *mc = ld->mc;
	unsigned long flags;
	bool duplicated = false;
#ifdef DEBUG_MODEM_IF
	struct utc_time t;
#endif

#ifdef DEBUG_MODEM_IF
	get_utc_time(&t);
#endif

	/* Disable normal IPC */
	set_magic(mld, MEM_CRASH_MAGIC);
	set_access(mld, 0);

	spin_lock_irqsave(&mld->lock, flags);
	if (mld->forced_cp_crash)
		duplicated = true;
	else
		mld->forced_cp_crash = true;
	spin_unlock_irqrestore(&mld->lock, flags);

	if (duplicated) {
#ifdef DEBUG_MODEM_IF
		evt_log(HMSU_FMT " %s: %s: ALREADY in progress <%pf>\n",
			t.hour, t.min, t.sec, t.us, CALLEE, ld->name, CALLER);
#endif
		return;
	}

	if (!cp_online(mc)) {
#ifdef DEBUG_MODEM_IF
		evt_log(HMSU_FMT " %s: %s: %s.state %s != ONLINE <%pf>\n",
			t.hour, t.min, t.sec, t.us,
			CALLEE, ld->name, mc->name, mc_state(mc), CALLER);
#endif
		return;
	}

	if (!wake_lock_active(&mld->dump_wlock))
		wake_lock(&mld->dump_wlock);

	stop_net_ifaces(ld);

	/**
	 * If there is no CRASH_ACK from a CP in FORCE_CRASH_ACK_TIMEOUT,
	 * handle_no_cp_crash_ack() will be executed.
	 */
	mif_add_timer(&mld->crash_ack_timer, FORCE_CRASH_ACK_TIMEOUT,
		      handle_no_cp_crash_ack, (unsigned long)mld);

	/* Send CRASH_EXIT command to a CP */
	send_ipc_irq(mld, cmd2int(CMD_CRASH_EXIT));

#ifdef DEBUG_MODEM_IF
	evt_log(HMSU_FMT " CRASH_EXIT: %s->%s: CP_CRASH_REQ <by %pf>\n",
		t.hour, t.min, t.sec, t.us, ld->name, mc->name, CALLER);

	if (in_interrupt())
		queue_work(system_nrt_wq, &mld->dump_work);
	else
		save_mem_dump(mld);
#endif
}
void mem_forced_cp_crash(struct mem_link_device *mld)
{
	struct link_device *ld = &mld->link_dev;
	struct modem_ctl *mc = ld->mc;
	bool duplicated = false;
	unsigned long flags;

	/* Disable normal IPC */
	set_magic(mld, MEM_CRASH_MAGIC);
	set_access(mld, 0);

	spin_lock_irqsave(&mld->lock, flags);
	if (atomic_read(&mc->forced_cp_crash))
		duplicated = true;
	else
		atomic_set(&mc->forced_cp_crash, 1);
	spin_unlock_irqrestore(&mld->lock, flags);

	if (duplicated) {
		evt_log(0, "%s: %s: ALREADY in progress <%pf>\n",
			FUNC, ld->name, CALLER);
		return;
	}

	if (!cp_online(mc)) {
		evt_log(0, "%s: %s: %s.state %s != ONLINE <%pf>\n",
			FUNC, ld->name, mc->name, mc_state(mc), CALLER);
		return;
	}

	if (mc->wake_lock) {
		if (!wake_lock_active(mc->wake_lock)) {
			wake_lock(mc->wake_lock);
			mif_err("%s->wake_lock locked\n", mc->name);
		}
	}

	if (mld->attrs & LINK_ATTR(LINK_ATTR_MEM_DUMP)) {
		stop_net_ifaces(ld);

		if (mld->debug_info)
			mld->debug_info();

		/**
		 * If there is no CRASH_ACK from CP in a timeout,
		 * handle_no_cp_crash_ack() will be executed.
		 */
		mif_add_timer(&mc->crash_ack_timer, FORCE_CRASH_ACK_TIMEOUT,
			      handle_no_cp_crash_ack, (unsigned long)mld);

		/* Send CRASH_EXIT command to a CP */
		send_ipc_irq(mld, cmd2int(CMD_CRASH_EXIT));
	} else {
		modemctl_notify_event(MDM_EVENT_CP_FORCE_CRASH);
	}

	evt_log(0, "%s->%s: CP_CRASH_REQ <%pf>\n", ld->name, mc->name, CALLER);

#ifdef DEBUG_MODEM_IF
	if (in_interrupt())
		queue_work(system_nrt_wq, &mld->dump_work);
	else
		save_mem_dump(mld);
#endif
}