staging/mei: propagate error codes up in the write flow

Change mei_write_message's return type from bool to int
to enable propagation of the error code up to caller functions.
The function now returns -EIO when low level write fails and 0
on success.
A similar change is done in intermediate caller functions:
mei_send_flow_control, mei_connect, and mei_disconnect

This makes code more alike to typical Linux kernel error
handling.

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Tomas Winkler 2012-03-14 14:39:42 +02:00 committed by Greg Kroah-Hartman
parent 5f9092f36f
commit 1ccb7b6249
6 changed files with 61 additions and 80 deletions

View file

@ -366,7 +366,7 @@ void mei_host_start_message(struct mei_device *dev)
host_start_req->host_version.major_version = HBM_MAJOR_VERSION; host_start_req->host_version.major_version = HBM_MAJOR_VERSION;
host_start_req->host_version.minor_version = HBM_MINOR_VERSION; host_start_req->host_version.minor_version = HBM_MINOR_VERSION;
dev->recvd_msg = false; dev->recvd_msg = false;
if (!mei_write_message(dev, mei_hdr, (unsigned char *)host_start_req, if (mei_write_message(dev, mei_hdr, (unsigned char *)host_start_req,
mei_hdr->length)) { mei_hdr->length)) {
dev_dbg(&dev->pdev->dev, "write send version message to FW fail.\n"); dev_dbg(&dev->pdev->dev, "write send version message to FW fail.\n");
dev->mei_state = MEI_RESETING; dev->mei_state = MEI_RESETING;
@ -399,7 +399,7 @@ void mei_host_enum_clients_message(struct mei_device *dev)
host_enum_req = (struct hbm_host_enum_request *) &dev->wr_msg_buf[1]; host_enum_req = (struct hbm_host_enum_request *) &dev->wr_msg_buf[1];
memset(host_enum_req, 0, sizeof(struct hbm_host_enum_request)); memset(host_enum_req, 0, sizeof(struct hbm_host_enum_request));
host_enum_req->hbm_cmd = HOST_ENUM_REQ_CMD; host_enum_req->hbm_cmd = HOST_ENUM_REQ_CMD;
if (!mei_write_message(dev, mei_hdr, (unsigned char *)host_enum_req, if (mei_write_message(dev, mei_hdr, (unsigned char *)host_enum_req,
mei_hdr->length)) { mei_hdr->length)) {
dev->mei_state = MEI_RESETING; dev->mei_state = MEI_RESETING;
dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n"); dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n");
@ -407,7 +407,7 @@ void mei_host_enum_clients_message(struct mei_device *dev)
} }
dev->init_clients_state = MEI_ENUM_CLIENTS_MESSAGE; dev->init_clients_state = MEI_ENUM_CLIENTS_MESSAGE;
dev->init_clients_timer = INIT_CLIENTS_TIMEOUT; dev->init_clients_timer = INIT_CLIENTS_TIMEOUT;
return ; return;
} }
@ -485,7 +485,7 @@ int mei_host_client_properties(struct mei_device *dev)
host_cli_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD; host_cli_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD;
host_cli_req->address = b; host_cli_req->address = b;
if (!mei_write_message(dev, mei_header, if (mei_write_message(dev, mei_header,
(unsigned char *)host_cli_req, (unsigned char *)host_cli_req,
mei_header->length)) { mei_header->length)) {
dev->mei_state = MEI_RESETING; dev->mei_state = MEI_RESETING;
@ -608,7 +608,7 @@ void mei_host_init_iamthif(struct mei_device *dev)
dev->iamthif_msg_buf = msg_buf; dev->iamthif_msg_buf = msg_buf;
if (!mei_connect(dev, &dev->iamthif_cl)) { if (mei_connect(dev, &dev->iamthif_cl)) {
dev_dbg(&dev->pdev->dev, "Failed to connect to AMTHI client\n"); dev_dbg(&dev->pdev->dev, "Failed to connect to AMTHI client\n");
dev->iamthif_cl.state = MEI_FILE_DISCONNECTED; dev->iamthif_cl.state = MEI_FILE_DISCONNECTED;
dev->iamthif_cl.host_client_id = 0; dev->iamthif_cl.host_client_id = 0;
@ -670,14 +670,12 @@ int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl)
if (dev->mei_host_buffer_is_empty) { if (dev->mei_host_buffer_is_empty) {
dev->mei_host_buffer_is_empty = false; dev->mei_host_buffer_is_empty = false;
if (mei_disconnect(dev, cl)) { if (mei_disconnect(dev, cl)) {
mdelay(10); /* Wait for hardware disconnection ready */
list_add_tail(&cb->cb_list,
&dev->ctrl_rd_list.mei_cb.cb_list);
} else {
rets = -ENODEV; rets = -ENODEV;
dev_dbg(&dev->pdev->dev, "failed to call mei_disconnect.\n"); dev_dbg(&dev->pdev->dev, "failed to call mei_disconnect.\n");
goto free; goto free;
} }
mdelay(10); /* Wait for hardware disconnection ready */
list_add_tail(&cb->cb_list, &dev->ctrl_rd_list.mei_cb.cb_list);
} else { } else {
dev_dbg(&dev->pdev->dev, "add disconnect cb to control write list\n"); dev_dbg(&dev->pdev->dev, "add disconnect cb to control write list\n");
list_add_tail(&cb->cb_list, list_add_tail(&cb->cb_list,

View file

@ -125,7 +125,7 @@ int mei_count_empty_write_slots(struct mei_device *dev)
* @write_buffer: message buffer will be written * @write_buffer: message buffer will be written
* @write_length: message size will be written * @write_length: message size will be written
* *
* returns 1 if success, 0 - otherwise. * This function returns -EIO if write has failed
*/ */
int mei_write_message(struct mei_device *dev, int mei_write_message(struct mei_device *dev,
struct mei_msg_hdr *header, struct mei_msg_hdr *header,
@ -157,7 +157,7 @@ int mei_write_message(struct mei_device *dev,
dw_to_write = ((write_length + 3) / 4); dw_to_write = ((write_length + 3) / 4);
if (dw_to_write > empty_slots) if (dw_to_write > empty_slots)
return 0; return -EIO;
mei_reg_write(dev, H_CB_WW, *((u32 *) header)); mei_reg_write(dev, H_CB_WW, *((u32 *) header));
@ -177,9 +177,9 @@ int mei_write_message(struct mei_device *dev,
mei_hcsr_set(dev); mei_hcsr_set(dev);
dev->me_hw_state = mei_mecsr_read(dev); dev->me_hw_state = mei_mecsr_read(dev);
if ((dev->me_hw_state & ME_RDY_HRA) != ME_RDY_HRA) if ((dev->me_hw_state & ME_RDY_HRA) != ME_RDY_HRA)
return 0; return -EIO;
return 1; return 0;
} }
/** /**
@ -308,7 +308,7 @@ int mei_flow_ctrl_reduce(struct mei_device *dev, struct mei_cl *cl)
* @dev: the device structure * @dev: the device structure
* @cl: private data of the file object * @cl: private data of the file object
* *
* returns 1 if success, 0 - otherwise. * This function returns -EIO on write failure
*/ */
int mei_send_flow_control(struct mei_device *dev, struct mei_cl *cl) int mei_send_flow_control(struct mei_device *dev, struct mei_cl *cl)
{ {
@ -330,14 +330,11 @@ int mei_send_flow_control(struct mei_device *dev, struct mei_cl *cl)
memset(mei_flow_control->reserved, 0, memset(mei_flow_control->reserved, 0,
sizeof(mei_flow_control->reserved)); sizeof(mei_flow_control->reserved));
dev_dbg(&dev->pdev->dev, "sending flow control host client = %d, ME client = %d\n", dev_dbg(&dev->pdev->dev, "sending flow control host client = %d, ME client = %d\n",
cl->host_client_id, cl->me_client_id); cl->host_client_id, cl->me_client_id);
if (!mei_write_message(dev, mei_hdr,
return mei_write_message(dev, mei_hdr,
(unsigned char *) mei_flow_control, (unsigned char *) mei_flow_control,
sizeof(struct hbm_flow_control))) sizeof(struct hbm_flow_control));
return 0;
return 1;
} }
/** /**
@ -371,7 +368,7 @@ int mei_other_client_is_connecting(struct mei_device *dev,
* @dev: the device structure * @dev: the device structure
* @cl: private data of the file object * @cl: private data of the file object
* *
* returns 1 if success, 0 - otherwise. * This function returns -EIO on write failure
*/ */
int mei_disconnect(struct mei_device *dev, struct mei_cl *cl) int mei_disconnect(struct mei_device *dev, struct mei_cl *cl)
{ {
@ -393,12 +390,9 @@ int mei_disconnect(struct mei_device *dev, struct mei_cl *cl)
mei_cli_disconnect->hbm_cmd = CLIENT_DISCONNECT_REQ_CMD; mei_cli_disconnect->hbm_cmd = CLIENT_DISCONNECT_REQ_CMD;
mei_cli_disconnect->reserved[0] = 0; mei_cli_disconnect->reserved[0] = 0;
if (!mei_write_message(dev, mei_hdr, return mei_write_message(dev, mei_hdr,
(unsigned char *) mei_cli_disconnect, (unsigned char *) mei_cli_disconnect,
sizeof(struct hbm_client_disconnect_request))) sizeof(struct hbm_client_disconnect_request));
return 0;
return 1;
} }
/** /**
@ -407,7 +401,7 @@ int mei_disconnect(struct mei_device *dev, struct mei_cl *cl)
* @dev: the device structure * @dev: the device structure
* @cl: private data of the file object * @cl: private data of the file object
* *
* returns 1 if success, 0 - otherwise. * This function returns -EIO on write failure
*/ */
int mei_connect(struct mei_device *dev, struct mei_cl *cl) int mei_connect(struct mei_device *dev, struct mei_cl *cl)
{ {
@ -428,10 +422,7 @@ int mei_connect(struct mei_device *dev, struct mei_cl *cl)
mei_cli_connect->hbm_cmd = CLIENT_CONNECT_REQ_CMD; mei_cli_connect->hbm_cmd = CLIENT_CONNECT_REQ_CMD;
mei_cli_connect->reserved = 0; mei_cli_connect->reserved = 0;
if (!mei_write_message(dev, mei_hdr, return mei_write_message(dev, mei_hdr,
(unsigned char *) mei_cli_connect, (unsigned char *) mei_cli_connect,
sizeof(struct hbm_client_connect_request))) sizeof(struct hbm_client_connect_request));
return 0;
return 1;
} }

View file

@ -263,26 +263,25 @@ quit:
static int _mei_irq_thread_iamthif_read(struct mei_device *dev, s32 *slots) static int _mei_irq_thread_iamthif_read(struct mei_device *dev, s32 *slots)
{ {
if (((*slots) * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) if (((*slots) * sizeof(u32)) < (sizeof(struct mei_msg_hdr)
+ sizeof(struct hbm_flow_control))) { + sizeof(struct hbm_flow_control))) {
*slots -= (sizeof(struct mei_msg_hdr) +
sizeof(struct hbm_flow_control) + 3) / 4;
if (!mei_send_flow_control(dev, &dev->iamthif_cl)) {
dev_dbg(&dev->pdev->dev, "iamthif flow control failed\n");
} else {
dev_dbg(&dev->pdev->dev, "iamthif flow control success\n");
dev->iamthif_state = MEI_IAMTHIF_READING;
dev->iamthif_flow_control_pending = false;
dev->iamthif_msg_buf_index = 0;
dev->iamthif_msg_buf_size = 0;
dev->iamthif_stall_timer = IAMTHIF_STALL_TIMER;
dev->mei_host_buffer_is_empty =
mei_host_buffer_is_empty(dev);
}
return 0;
} else {
return -EMSGSIZE; return -EMSGSIZE;
} }
*slots -= (sizeof(struct mei_msg_hdr) +
sizeof(struct hbm_flow_control) + 3) / 4;
if (mei_send_flow_control(dev, &dev->iamthif_cl)) {
dev_dbg(&dev->pdev->dev, "iamthif flow control failed\n");
return -EIO;
}
dev_dbg(&dev->pdev->dev, "iamthif flow control success\n");
dev->iamthif_state = MEI_IAMTHIF_READING;
dev->iamthif_flow_control_pending = false;
dev->iamthif_msg_buf_index = 0;
dev->iamthif_msg_buf_size = 0;
dev->iamthif_stall_timer = IAMTHIF_STALL_TIMER;
dev->mei_host_buffer_is_empty = mei_host_buffer_is_empty(dev);
return 0;
} }
/** /**
@ -306,7 +305,7 @@ static int _mei_irq_thread_close(struct mei_device *dev, s32 *slots,
*slots -= (sizeof(struct mei_msg_hdr) + *slots -= (sizeof(struct mei_msg_hdr) +
sizeof(struct hbm_client_disconnect_request) + 3) / 4; sizeof(struct hbm_client_disconnect_request) + 3) / 4;
if (!mei_disconnect(dev, cl)) { if (mei_disconnect(dev, cl)) {
cl->status = 0; cl->status = 0;
cb_pos->information = 0; cb_pos->information = 0;
list_move_tail(&cb_pos->cb_list, list_move_tail(&cb_pos->cb_list,
@ -838,24 +837,21 @@ static int _mei_irq_thread_read(struct mei_device *dev, s32 *slots,
{ {
if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) + if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) +
sizeof(struct hbm_flow_control))) { sizeof(struct hbm_flow_control))) {
*slots -= (sizeof(struct mei_msg_hdr) +
sizeof(struct hbm_flow_control) + 3) / 4;
if (!mei_send_flow_control(dev, cl)) {
cl->status = -ENODEV;
cb_pos->information = 0;
list_move_tail(&cb_pos->cb_list,
&cmpl_list->mei_cb.cb_list);
return -ENODEV;
} else {
list_move_tail(&cb_pos->cb_list,
&dev->read_list.mei_cb.cb_list);
}
} else {
/* return the cancel routine */ /* return the cancel routine */
list_del(&cb_pos->cb_list); list_del(&cb_pos->cb_list);
return -EBADMSG; return -EBADMSG;
} }
*slots -= (sizeof(struct mei_msg_hdr) +
sizeof(struct hbm_flow_control) + 3) / 4;
if (mei_send_flow_control(dev, cl)) {
cl->status = -ENODEV;
cb_pos->information = 0;
list_move_tail(&cb_pos->cb_list, &cmpl_list->mei_cb.cb_list);
return -ENODEV;
}
list_move_tail(&cb_pos->cb_list, &dev->read_list.mei_cb.cb_list);
return 0; return 0;
} }
@ -881,7 +877,7 @@ static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots,
cl->state = MEI_FILE_CONNECTING; cl->state = MEI_FILE_CONNECTING;
*slots -= (sizeof(struct mei_msg_hdr) + *slots -= (sizeof(struct mei_msg_hdr) +
sizeof(struct hbm_client_connect_request) + 3) / 4; sizeof(struct hbm_client_connect_request) + 3) / 4;
if (!mei_connect(dev, cl)) { if (mei_connect(dev, cl)) {
cl->status = -ENODEV; cl->status = -ENODEV;
cb_pos->information = 0; cb_pos->information = 0;
list_del(&cb_pos->cb_list); list_del(&cb_pos->cb_list);
@ -938,7 +934,7 @@ static int _mei_irq_thread_cmpl(struct mei_device *dev, s32 *slots,
mei_hdr->length); mei_hdr->length);
*slots -= (sizeof(struct mei_msg_hdr) + *slots -= (sizeof(struct mei_msg_hdr) +
mei_hdr->length + 3) / 4; mei_hdr->length + 3) / 4;
if (!mei_write_message(dev, mei_hdr, if (mei_write_message(dev, mei_hdr,
(unsigned char *) (unsigned char *)
(cb_pos->request_buffer.data + (cb_pos->request_buffer.data +
cb_pos->information), cb_pos->information),
@ -967,7 +963,7 @@ static int _mei_irq_thread_cmpl(struct mei_device *dev, s32 *slots,
(*slots) -= (sizeof(struct mei_msg_hdr) + (*slots) -= (sizeof(struct mei_msg_hdr) +
mei_hdr->length + 3) / 4; mei_hdr->length + 3) / 4;
if (!mei_write_message(dev, mei_hdr, if (mei_write_message(dev, mei_hdr,
(unsigned char *) (unsigned char *)
(cb_pos->request_buffer.data + (cb_pos->request_buffer.data +
cb_pos->information), cb_pos->information),
@ -1028,7 +1024,7 @@ static int _mei_irq_thread_cmpl_iamthif(struct mei_device *dev, s32 *slots,
*slots -= (sizeof(struct mei_msg_hdr) + *slots -= (sizeof(struct mei_msg_hdr) +
mei_hdr->length + 3) / 4; mei_hdr->length + 3) / 4;
if (!mei_write_message(dev, mei_hdr, if (mei_write_message(dev, mei_hdr,
(dev->iamthif_msg_buf + (dev->iamthif_msg_buf +
dev->iamthif_msg_buf_index), dev->iamthif_msg_buf_index),
mei_hdr->length)) { mei_hdr->length)) {
@ -1063,7 +1059,7 @@ static int _mei_irq_thread_cmpl_iamthif(struct mei_device *dev, s32 *slots,
*slots -= (sizeof(struct mei_msg_hdr) + *slots -= (sizeof(struct mei_msg_hdr) +
mei_hdr->length + 3) / 4; mei_hdr->length + 3) / 4;
if (!mei_write_message(dev, mei_hdr, if (mei_write_message(dev, mei_hdr,
(dev->iamthif_msg_buf + (dev->iamthif_msg_buf +
dev->iamthif_msg_buf_index), dev->iamthif_msg_buf_index),
mei_hdr->length)) { mei_hdr->length)) {

View file

@ -162,7 +162,7 @@ int mei_ioctl_connect_client(struct file *file,
&& !mei_other_client_is_connecting(dev, cl)) { && !mei_other_client_is_connecting(dev, cl)) {
dev_dbg(&dev->pdev->dev, "Sending Connect Message\n"); dev_dbg(&dev->pdev->dev, "Sending Connect Message\n");
dev->mei_host_buffer_is_empty = false; dev->mei_host_buffer_is_empty = false;
if (!mei_connect(dev, cl)) { if (mei_connect(dev, cl)) {
dev_dbg(&dev->pdev->dev, "Sending connect message - failed\n"); dev_dbg(&dev->pdev->dev, "Sending connect message - failed\n");
rets = -ENODEV; rets = -ENODEV;
goto end; goto end;
@ -434,13 +434,11 @@ int mei_start_read(struct mei_device *dev, struct mei_cl *cl)
cl->read_cb = cb; cl->read_cb = cb;
if (dev->mei_host_buffer_is_empty) { if (dev->mei_host_buffer_is_empty) {
dev->mei_host_buffer_is_empty = false; dev->mei_host_buffer_is_empty = false;
if (!mei_send_flow_control(dev, cl)) { if (mei_send_flow_control(dev, cl)) {
rets = -ENODEV; rets = -ENODEV;
goto unlock; goto unlock;
} else {
list_add_tail(&cb->cb_list,
&dev->read_list.mei_cb.cb_list);
} }
list_add_tail(&cb->cb_list, &dev->read_list.mei_cb.cb_list);
} else { } else {
list_add_tail(&cb->cb_list, &dev->ctrl_wr_list.mei_cb.cb_list); list_add_tail(&cb->cb_list, &dev->ctrl_wr_list.mei_cb.cb_list);
} }
@ -500,7 +498,7 @@ int amthi_write(struct mei_device *dev, struct mei_cl_cb *cb)
mei_hdr.me_addr = dev->iamthif_cl.me_client_id; mei_hdr.me_addr = dev->iamthif_cl.me_client_id;
mei_hdr.reserved = 0; mei_hdr.reserved = 0;
dev->iamthif_msg_buf_index += mei_hdr.length; dev->iamthif_msg_buf_index += mei_hdr.length;
if (!mei_write_message(dev, &mei_hdr, if (mei_write_message(dev, &mei_hdr,
(unsigned char *)(dev->iamthif_msg_buf), (unsigned char *)(dev->iamthif_msg_buf),
mei_hdr.length)) mei_hdr.length))
return -ENODEV; return -ENODEV;

View file

@ -740,7 +740,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
mei_hdr.reserved = 0; mei_hdr.reserved = 0;
dev_dbg(&dev->pdev->dev, "call mei_write_message header=%08x.\n", dev_dbg(&dev->pdev->dev, "call mei_write_message header=%08x.\n",
*((u32 *) &mei_hdr)); *((u32 *) &mei_hdr));
if (!mei_write_message(dev, &mei_hdr, if (mei_write_message(dev, &mei_hdr,
(unsigned char *) (write_cb->request_buffer.data), (unsigned char *) (write_cb->request_buffer.data),
mei_hdr.length)) { mei_hdr.length)) {
rets = -ENODEV; rets = -ENODEV;

View file

@ -74,7 +74,7 @@ bool mei_wd_host_init(struct mei_device *dev)
dev_dbg(&dev->pdev->dev, "check wd_cl\n"); dev_dbg(&dev->pdev->dev, "check wd_cl\n");
if (MEI_FILE_CONNECTING == dev->wd_cl.state) { if (MEI_FILE_CONNECTING == dev->wd_cl.state) {
if (!mei_connect(dev, &dev->wd_cl)) { if (mei_connect(dev, &dev->wd_cl)) {
dev_dbg(&dev->pdev->dev, "Failed to connect to WD client\n"); dev_dbg(&dev->pdev->dev, "Failed to connect to WD client\n");
dev->wd_cl.state = MEI_FILE_DISCONNECTED; dev->wd_cl.state = MEI_FILE_DISCONNECTED;
dev->wd_cl.host_client_id = 0; dev->wd_cl.host_client_id = 0;
@ -119,9 +119,7 @@ int mei_wd_send(struct mei_device *dev)
else else
return -EINVAL; return -EINVAL;
if (mei_write_message(dev, mei_hdr, dev->wd_data, mei_hdr->length)) return mei_write_message(dev, mei_hdr, dev->wd_data, mei_hdr->length);
return 0;
return -EIO;
} }
/** /**