Пример #1
0
static int do_sync_request(sclp_cmdw_t cmd, void *sccb)
{
	struct completion completion;
	struct sclp_req *request;
	int rc;

	request = kzalloc(sizeof(*request), GFP_KERNEL);
	if (!request)
		return -ENOMEM;
	request->command = cmd;
	request->sccb = sccb;
	request->status = SCLP_REQ_FILLED;
	request->callback = sclp_sync_callback;
	request->callback_data = &completion;
	init_completion(&completion);

	/* Perform sclp request. */
	rc = sclp_add_request(request);
	if (rc)
		goto out;
	wait_for_completion(&completion);

	/* Check response. */
	if (request->status != SCLP_REQ_DONE) {
		pr_warning("sync request failed (cmd=0x%08x, "
			   "status=0x%02x)\n", cmd, request->status);
		rc = -EIO;
	}
out:
	kfree(request);
	return rc;
}
static int sdias_sclp_send(struct sclp_req *req)
{
	int retries;
	int rc;

	for (retries = SDIAS_RETRIES; retries; retries--) {
		sclp_req_done = 0;
		TRACE("add request\n");
		rc = sclp_add_request(req);
		if (rc) {
			/* not initiated, wait some time and retry */
			set_current_state(TASK_INTERRUPTIBLE);
			TRACE("add request failed: rc = %i\n",rc);
			schedule_timeout(SDIAS_SLEEP_TICKS);
			continue;
		}
		/* initiated, wait for completion of service call */
		wait_event(sdias_wq, (sclp_req_done == 1));
		if (req->status == SCLP_REQ_FAILED) {
			TRACE("sclp request failed\n");
			rc = -EIO;
			continue;
		}
		TRACE("request done\n");
		break;
	}
	return rc;
}
Пример #3
0
int
sclp_emit_buffer(struct sclp_buffer *buffer,
		 void (*callback)(struct sclp_buffer *, int))
{
	struct write_sccb *sccb;

	/* add current line if there is one */
	if (buffer->current_line != NULL)
		sclp_finalize_mto(buffer);

	/* Are there messages in the output buffer ? */
	if (buffer->mto_number == 0)
		return -EIO;

	sccb = buffer->sccb;
	if (sclp_rw_event.sclp_receive_mask & EVTYP_MSG_MASK)
		/* Use normal write message */
		sccb->msg_buf.header.type = EVTYP_MSG;
	else if (sclp_rw_event.sclp_receive_mask & EVTYP_PMSGCMD_MASK)
		/* Use write priority message */
		sccb->msg_buf.header.type = EVTYP_PMSGCMD;
	else
		return -ENOSYS;
	buffer->request.command = SCLP_CMDW_WRITE_EVENT_DATA;
	buffer->request.status = SCLP_REQ_FILLED;
	buffer->request.callback = sclp_writedata_callback;
	buffer->request.callback_data = buffer;
	buffer->request.sccb = sccb;
	buffer->callback = callback;
	return sclp_add_request(&buffer->request);
}
Пример #4
0
static void
sclp_buffer_retry(unsigned long data)
{
	struct sclp_buffer *buffer = (struct sclp_buffer *) data;
	buffer->request.status = SCLP_REQ_FILLED;
	buffer->sccb->header.response_code = 0x0000;
	sclp_add_request(&buffer->request);
}
Пример #5
0
static int do_configure(sclp_cmdw_t cmd)
{
	struct chp_cfg_data *data;
	int rc;

	if (!SCLP_HAS_CHP_RECONFIG)
		return -EOPNOTSUPP;
	/* Prepare sccb. */
	data = (struct chp_cfg_data *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
	if (!data)
		return -ENOMEM;
	data->sccb.header.length = sizeof(struct chp_cfg_sccb);
	data->req.command = cmd;
	data->req.sccb = &(data->sccb);
	data->req.status = SCLP_REQ_FILLED;
	data->req.callback = chp_callback;
	data->req.callback_data = &(data->completion);
	init_completion(&data->completion);

	/* Perform sclp request. */
	rc = sclp_add_request(&(data->req));
	if (rc)
		goto out;
	wait_for_completion(&data->completion);

	/* Check response .*/
	if (data->req.status != SCLP_REQ_DONE) {
		printk(KERN_WARNING TAG "configure channel-path request failed "
		       "(status=0x%02x)\n", data->req.status);
		rc = -EIO;
		goto out;
	}
	switch (data->sccb.header.response_code) {
	case 0x0020:
	case 0x0120:
	case 0x0440:
	case 0x0450:
		break;
	default:
		printk(KERN_WARNING TAG "configure channel-path failed "
		       "(cmd=0x%08x, response=0x%04x)\n", cmd,
		       data->sccb.header.response_code);
		rc = -EIO;
		break;
	}
out:
	free_page((unsigned long) data);

	return rc;
}
Пример #6
0
/**
 * sclp_chp_read_info - perform read channel-path information sclp command
 * @info: resulting channel-path information data
 *
 * Perform read channel-path information sclp command and wait for completion.
 * On success, store channel-path information in @info and return 0. Return
 * non-zero otherwise.
 */
int sclp_chp_read_info(struct sclp_chp_info *info)
{
	struct chp_info_data *data;
	int rc;

	if (!SCLP_HAS_CHP_INFO)
		return -EOPNOTSUPP;
	/* Prepare sccb. */
	data = (struct chp_info_data *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
	if (!data)
		return -ENOMEM;
	data->sccb.header.length = sizeof(struct chp_info_sccb);
	data->req.command = SCLP_CMDW_READ_CHANNEL_PATH_INFORMATION;
	data->req.sccb = &(data->sccb);
	data->req.status = SCLP_REQ_FILLED;
	data->req.callback = chp_callback;
	data->req.callback_data = &(data->completion);
	init_completion(&data->completion);

	/* Perform sclp request. */
	rc = sclp_add_request(&(data->req));
	if (rc)
		goto out;
	wait_for_completion(&data->completion);

	/* Check response .*/
	if (data->req.status != SCLP_REQ_DONE) {
		printk(KERN_WARNING TAG "read channel-path info request failed "
		       "(status=0x%02x)\n", data->req.status);
		rc = -EIO;
		goto out;
	}
	if (data->sccb.header.response_code != 0x0010) {
		printk(KERN_WARNING TAG "read channel-path info failed "
		       "(response=0x%04x)\n", data->sccb.header.response_code);
		rc = -EIO;
		goto out;
	}
	memcpy(info->recognized, data->sccb.recognized,
	       SCLP_CHP_INFO_MASK_SIZE);
	memcpy(info->standby, data->sccb.standby,
	       SCLP_CHP_INFO_MASK_SIZE);
	memcpy(info->configured, data->sccb.configured,
	       SCLP_CHP_INFO_MASK_SIZE);
out:
	free_page((unsigned long) data);

	return rc;
}
Пример #7
0
/*
 * Setup the request structure in the struct sclp_buffer to do SCLP Write
 * Event Data and pass the request to the core SCLP loop.
 */
void
sclp_emit_buffer(struct sclp_buffer *buffer,
		 void (*callback)(struct sclp_buffer *, int))
{
	struct write_sccb *sccb;

	/* add current line if there is one */
	if (buffer->current_line != NULL)
		sclp_finalize_mto(buffer);

	/* Are there messages in the output buffer ? */
	if (buffer->mto_number == 0) {
		if (callback != NULL)
			callback(buffer, 0);
		return;
	}

	sccb = buffer->sccb;
	if (sclp_rw_event.sclp_send_mask & EvTyp_Msg_Mask)
		/* Use normal write message */
		sccb->msg_buf.header.type = EvTyp_Msg;
	else if (sclp_rw_event.sclp_send_mask & EvTyp_PMsgCmd_Mask)
		/* Use write priority message */
		sccb->msg_buf.header.type = EvTyp_PMsgCmd;
	else {
		if (callback != NULL)
			callback(buffer, -ENOSYS);
		return;
	}
	buffer->request.command = SCLP_CMDW_WRITEDATA;
	buffer->request.status = SCLP_REQ_FILLED;
	buffer->request.callback = sclp_writedata_callback;
	buffer->request.callback_data = buffer;
	buffer->request.sccb = sccb;
	buffer->callback = callback;
	sclp_add_request(&buffer->request);
}
Пример #8
0
static void
sclp_writedata_callback(struct sclp_req *request, void *data)
{
	int rc;
	struct sclp_buffer *buffer;
	struct write_sccb *sccb;

	buffer = (struct sclp_buffer *) data;
	sccb = buffer->sccb;

	if (request->status == SCLP_REQ_FAILED) {
		if (buffer->callback != NULL)
			buffer->callback(buffer, -EIO);
		return;
	}
	/* check SCLP response code and choose suitable action	*/
	switch (sccb->header.response_code) {
	case 0x0020 :
		/* Normal completion, buffer processed, message(s) sent */
		rc = 0;
		break;

	case 0x0340: /* Contained SCLP equipment check */
		if (++buffer->retry_count > SCLP_BUFFER_MAX_RETRY) {
			rc = -EIO;
			break;
		}
		/* remove processed buffers and requeue rest */
		if (sclp_remove_processed((struct sccb_header *) sccb) > 0) {
			/* not all buffers were processed */
			sccb->header.response_code = 0x0000;
			buffer->request.status = SCLP_REQ_FILLED;
			rc = sclp_add_request(request);
			if (rc == 0)
				return;
		} else
			rc = 0;
		break;

	case 0x0040: /* SCLP equipment check */
	case 0x05f0: /* Target resource in improper state */
		if (++buffer->retry_count > SCLP_BUFFER_MAX_RETRY) {
			rc = -EIO;
			break;
		}
		/* retry request */
		sccb->header.response_code = 0x0000;
		buffer->request.status = SCLP_REQ_FILLED;
		rc = sclp_add_request(request);
		if (rc == 0)
			return;
		break;
	default:
		if (sccb->header.response_code == 0x71f0)
			rc = -ENOMEM;
		else
			rc = -EINVAL;
		break;
	}
	if (buffer->callback != NULL)
		buffer->callback(buffer, rc);
}
Пример #9
0
int sclp_pci_report(struct zpci_report_error_header *report, u32 fh, u32 fid)
{
	DECLARE_COMPLETION_ONSTACK(completion);
	struct err_notify_sccb *sccb;
	struct sclp_req req;
	int ret;

	ret = sclp_pci_check_report(report);
	if (ret)
		return ret;

	mutex_lock(&sclp_pci_mutex);
	ret = sclp_register(&sclp_pci_event);
	if (ret)
		goto out_unlock;

	if (!(sclp_pci_event.sclp_receive_mask & EVTYP_ERRNOTIFY_MASK)) {
		ret = -EOPNOTSUPP;
		goto out_unregister;
	}

	sccb = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
	if (!sccb) {
		ret = -ENOMEM;
		goto out_unregister;
	}

	memset(&req, 0, sizeof(req));
	req.callback_data = &completion;
	req.callback = sclp_pci_callback;
	req.command = SCLP_CMDW_WRITE_EVENT_DATA;
	req.status = SCLP_REQ_FILLED;
	req.sccb = sccb;

	sccb->evbuf.header.length = sizeof(sccb->evbuf) + report->length;
	sccb->evbuf.header.type = EVTYP_ERRNOTIFY;
	sccb->header.length = sizeof(sccb->header) + sccb->evbuf.header.length;

	sccb->evbuf.action = report->action;
	sccb->evbuf.atype = SCLP_ATYPE_PCI;
	sccb->evbuf.fh = fh;
	sccb->evbuf.fid = fid;

	memcpy(sccb->evbuf.data, report->data, report->length);

	ret = sclp_add_request(&req);
	if (ret)
		goto out_free_req;

	wait_for_completion(&completion);
	if (req.status != SCLP_REQ_DONE) {
		pr_warn("request failed (status=0x%02x)\n",
			req.status);
		ret = -EIO;
		goto out_free_req;
	}

	if (sccb->header.response_code != 0x0020) {
		pr_warn("request failed with response code 0x%x\n",
			sccb->header.response_code);
		ret = -EIO;
	}

out_free_req:
	free_page((unsigned long) sccb);
out_unregister:
	sclp_unregister(&sclp_pci_event);
out_unlock:
	mutex_unlock(&sclp_pci_mutex);
	return ret;
}
Пример #10
0
static void
sclp_writedata_callback(struct sclp_req *request, void *data)
{
	int rc;
	struct sclp_buffer *buffer;
	struct write_sccb *sccb;

	buffer = (struct sclp_buffer *) data;
	sccb = buffer->sccb;

	if (request->status == SCLP_REQ_FAILED) {
		if (buffer->callback != NULL)
			buffer->callback(buffer, -EIO);
		return;
	}
	
	switch (sccb->header.response_code) {
	case 0x0020 :
		
		rc = 0;
		break;

	case 0x0340: 
		if (++buffer->retry_count > SCLP_BUFFER_MAX_RETRY) {
			rc = -EIO;
			break;
		}
		
		if (sclp_remove_processed((struct sccb_header *) sccb) > 0) {
			
			sccb->header.response_code = 0x0000;
			buffer->request.status = SCLP_REQ_FILLED;
			rc = sclp_add_request(request);
			if (rc == 0)
				return;
		} else
			rc = 0;
		break;

	case 0x0040: 
	case 0x05f0: 
		if (++buffer->retry_count > SCLP_BUFFER_MAX_RETRY) {
			rc = -EIO;
			break;
		}
		
		sccb->header.response_code = 0x0000;
		buffer->request.status = SCLP_REQ_FILLED;
		rc = sclp_add_request(request);
		if (rc == 0)
			return;
		break;
	default:
		if (sccb->header.response_code == 0x71f0)
			rc = -ENOMEM;
		else
			rc = -EINVAL;
		break;
	}
	if (buffer->callback != NULL)
		buffer->callback(buffer, rc);
}