static void diag_mask_update_work_fn(struct work_struct *work)
{
	uint8_t peripheral;

	for (peripheral = 0; peripheral <= NUM_PERIPHERALS; peripheral++) {
		if (!(driver->mask_update & PERIPHERAL_MASK(peripheral)))
			continue;
		mutex_lock(&driver->cntl_lock);
		driver->mask_update ^= PERIPHERAL_MASK(peripheral);
		mutex_unlock(&driver->cntl_lock);
		diag_send_updates_peripheral(peripheral);
	}
}
Exemple #2
0
static int periph_clk_enable(struct clk *clk)
{
	struct pmc_platdata *plat = dev_get_platdata(clk->dev);
	struct at91_pmc *pmc = plat->reg_base;
	enum periph_clk_type clk_type;
	void *addr;

	if (clk->id < PERIPHERAL_ID_MIN)
		return -1;

	clk_type = dev_get_driver_data(dev_get_parent(clk->dev));
	if (clk_type == CLK_PERIPH_AT91RM9200) {
		addr = &pmc->pcer;
		if (clk->id > PERIPHERAL_ID_MAX)
			addr = &pmc->pcer1;

		setbits_le32(addr, PERIPHERAL_MASK(clk->id));
	} else {
		writel(clk->id & AT91_PMC_PCR_PID_MASK, &pmc->pcr);
		setbits_le32(&pmc->pcr,
			     AT91_PMC_PCR_CMD_WRITE | AT91_PMC_PCR_EN);
	}

	return 0;
}
static void diag_stm_update_work_fn(struct work_struct *work)
{
	uint8_t i;
	uint16_t peripheral_mask = 0;
	int err = 0;

	mutex_lock(&driver->cntl_lock);
	peripheral_mask = driver->stm_peripheral;
	driver->stm_peripheral = 0;
	mutex_unlock(&driver->cntl_lock);

	if (peripheral_mask == 0)
		return;

	for (i = 0; i < NUM_PERIPHERALS; i++) {
		if (!driver->feature[i].stm_support)
				continue;
		if (peripheral_mask & PERIPHERAL_MASK(i)) {
			err = diag_send_stm_state(i,
				(uint8_t)(driver->stm_state_requested[i]));
			if (!err) {
				driver->stm_state[i] =
					driver->stm_state_requested[i];
			}
		}
	}
}
static void diag_close_transport_work_fn(struct work_struct *work)
{
	uint8_t transport;
	uint8_t peripheral;

	mutex_lock(&driver->cntl_lock);
	for (peripheral = 0; peripheral <= NUM_PERIPHERALS; peripheral++) {
		if (!(driver->close_transport & PERIPHERAL_MASK(peripheral)))
			continue;
		driver->close_transport ^= PERIPHERAL_MASK(peripheral);
		transport = driver->feature[peripheral].sockets_enabled ?
					TRANSPORT_SMD : TRANSPORT_SOCKET;
		diagfwd_close_transport(transport, peripheral);
	}
	mutex_unlock(&driver->cntl_lock);
}
void diag_cntl_channel_open(struct diagfwd_info *p_info)
{
	if (!p_info)
		return;
	driver->mask_update |= PERIPHERAL_MASK(p_info->peripheral);
	queue_work(driver->cntl_wq, &driver->mask_update_work);
	diag_notify_md_client(p_info->peripheral, DIAG_STATUS_OPEN);
}
static void process_socket_feature(uint8_t peripheral)
{
	if (peripheral >= NUM_PERIPHERALS)
		return;

	mutex_lock(&driver->cntl_lock);
	driver->close_transport |= PERIPHERAL_MASK(peripheral);
	queue_work(driver->cntl_wq, &driver->close_transport_work);
	mutex_unlock(&driver->cntl_lock);
}
static void enable_stm_feature(uint8_t peripheral)
{
	if (peripheral >= NUM_PERIPHERALS)
		return;

	mutex_lock(&driver->cntl_lock);
	driver->feature[peripheral].stm_support = ENABLE_STM;
	driver->stm_peripheral |= PERIPHERAL_MASK(peripheral);
	mutex_unlock(&driver->cntl_lock);

	queue_work(driver->cntl_wq, &(driver->stm_update_work));
}
void diag_cntl_channel_close(struct diagfwd_info *p_info)
{
	uint8_t peripheral;

	if (!p_info)
		return;

	peripheral = p_info->peripheral;
	if (peripheral >= NUM_PERIPHERALS)
		return;

	driver->feature[peripheral].sent_feature_mask = 0;
	driver->feature[peripheral].rcvd_feature_mask = 0;
	flush_workqueue(driver->cntl_wq);
	reg_dirty |= PERIPHERAL_MASK(peripheral);
	diag_cmd_remove_reg_by_proc(peripheral);
	driver->feature[peripheral].stm_support = DISABLE_STM;
	driver->feature[peripheral].log_on_demand = 0;
	driver->stm_state[peripheral] = DISABLE_STM;
	driver->stm_state_requested[peripheral] = DISABLE_STM;
	reg_dirty ^= PERIPHERAL_MASK(peripheral);
	diag_notify_md_client(peripheral, DIAG_STATUS_CLOSED);
}
void diag_notify_md_client(uint8_t peripheral, int data)
{
	int stat = 0;
	struct siginfo info;

	if (driver->logging_mode != MEMORY_DEVICE_MODE)
		return;

	memset(&info, 0, sizeof(struct siginfo));
	info.si_code = SI_QUEUE;
	info.si_int = (PERIPHERAL_MASK(peripheral) | data);
	info.si_signo = SIGCONT;
	if (driver->md_proc[DIAG_LOCAL_PROC].mdlog_process) {
		stat = send_sig_info(info.si_signo, &info,
			driver->md_proc[DIAG_LOCAL_PROC].mdlog_process);
		if (stat)
			pr_err("diag: Err sending signal to memory device client, signal data: 0x%x, stat: %d\n",
			       info.si_int, stat);
	}

}
void diag_cntl_process_read_data(struct diagfwd_info *p_info, void *buf,
				 int len)
{
	int read_len = 0;
	int header_len = sizeof(struct diag_ctrl_pkt_header_t);
	uint8_t *ptr = buf;
	struct diag_ctrl_pkt_header_t *ctrl_pkt = NULL;

	if (!buf || len <= 0 || !p_info)
		return;

	if (reg_dirty & PERIPHERAL_MASK(p_info->peripheral)) {
		pr_err_ratelimited("diag: dropping command registration from peripheral %d\n",
		       p_info->peripheral);
		return;
	}

	while (read_len + header_len < len) {
		ctrl_pkt = (struct diag_ctrl_pkt_header_t *)ptr;
		switch (ctrl_pkt->pkt_id) {
		case DIAG_CTRL_MSG_REG:
			process_command_registration(ptr, ctrl_pkt->len,
						     p_info->peripheral);
			break;
		case DIAG_CTRL_MSG_DEREG:
			process_command_deregistration(ptr, ctrl_pkt->len,
						       p_info->peripheral);
			break;
		case DIAG_CTRL_MSG_FEATURE:
			process_incoming_feature_mask(ptr, ctrl_pkt->len,
						      p_info->peripheral);
			break;
		case DIAG_CTRL_MSG_LAST_EVENT_REPORT:
			process_last_event_report(ptr, ctrl_pkt->len,
						  p_info->peripheral);
			break;
		case DIAG_CTRL_MSG_LOG_RANGE_REPORT:
			process_log_range_report(ptr, ctrl_pkt->len,
						 p_info->peripheral);
			break;
		case DIAG_CTRL_MSG_SSID_RANGE_REPORT:
			process_ssid_range_report(ptr, ctrl_pkt->len,
						  p_info->peripheral);
			break;
		case DIAG_CTRL_MSG_BUILD_MASK_REPORT:
			process_build_mask_report(ptr, ctrl_pkt->len,
						  p_info->peripheral);
			break;
		case DIAG_CTRL_MSG_PD_STATUS:
			process_pd_status(ptr, ctrl_pkt->len,
						p_info->peripheral);
			break;
		default:
			DIAGFWD_DBUG("diag: Control packet %d not supported\n",
				 ctrl_pkt->pkt_id);
		}
		ptr += header_len + ctrl_pkt->len;
		read_len += header_len + ctrl_pkt->len;
	}

	return;
}