aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/mei/interrupt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/mei/interrupt.c')
-rw-r--r--drivers/misc/mei/interrupt.c169
1 files changed, 71 insertions, 98 deletions
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 23f5463d4cae..c6ffbbe5a6c0 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -267,8 +267,7 @@ static int _mei_irq_thread_iamthif_read(struct mei_device *dev, s32 *slots)
267 + sizeof(struct hbm_flow_control))) { 267 + sizeof(struct hbm_flow_control))) {
268 return -EMSGSIZE; 268 return -EMSGSIZE;
269 } 269 }
270 *slots -= (sizeof(struct mei_msg_hdr) + 270 *slots -= mei_data2slots(sizeof(struct hbm_flow_control));
271 sizeof(struct hbm_flow_control) + 3) / 4;
272 if (mei_send_flow_control(dev, &dev->iamthif_cl)) { 271 if (mei_send_flow_control(dev, &dev->iamthif_cl)) {
273 dev_dbg(&dev->pdev->dev, "iamthif flow control failed\n"); 272 dev_dbg(&dev->pdev->dev, "iamthif flow control failed\n");
274 return -EIO; 273 return -EIO;
@@ -280,7 +279,7 @@ static int _mei_irq_thread_iamthif_read(struct mei_device *dev, s32 *slots)
280 dev->iamthif_msg_buf_index = 0; 279 dev->iamthif_msg_buf_index = 0;
281 dev->iamthif_msg_buf_size = 0; 280 dev->iamthif_msg_buf_size = 0;
282 dev->iamthif_stall_timer = IAMTHIF_STALL_TIMER; 281 dev->iamthif_stall_timer = IAMTHIF_STALL_TIMER;
283 dev->mei_host_buffer_is_empty = mei_host_buffer_is_empty(dev); 282 dev->mei_host_buffer_is_empty = mei_hbuf_is_empty(dev);
284 return 0; 283 return 0;
285} 284}
286 285
@@ -300,28 +299,25 @@ static int _mei_irq_thread_close(struct mei_device *dev, s32 *slots,
300 struct mei_cl *cl, 299 struct mei_cl *cl,
301 struct mei_io_list *cmpl_list) 300 struct mei_io_list *cmpl_list)
302{ 301{
303 if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) + 302 if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) +
304 sizeof(struct hbm_client_disconnect_request))) { 303 sizeof(struct hbm_client_disconnect_request)))
305 *slots -= (sizeof(struct mei_msg_hdr) + 304 return -EBADMSG;
306 sizeof(struct hbm_client_disconnect_request) + 3) / 4;
307 305
308 if (mei_disconnect(dev, cl)) { 306 *slots -= mei_data2slots(sizeof(struct hbm_client_disconnect_request));
309 cl->status = 0; 307
310 cb_pos->information = 0; 308 if (mei_disconnect(dev, cl)) {
311 list_move_tail(&cb_pos->cb_list, 309 cl->status = 0;
312 &cmpl_list->mei_cb.cb_list); 310 cb_pos->information = 0;
313 return -EMSGSIZE; 311 list_move_tail(&cb_pos->cb_list,
314 } else { 312 &cmpl_list->mei_cb.cb_list);
315 cl->state = MEI_FILE_DISCONNECTING; 313 return -EMSGSIZE;
316 cl->status = 0;
317 cb_pos->information = 0;
318 list_move_tail(&cb_pos->cb_list,
319 &dev->ctrl_rd_list.mei_cb.cb_list);
320 cl->timer_count = MEI_CONNECT_TIMEOUT;
321 }
322 } else { 314 } else {
323 /* return the cancel routine */ 315 cl->state = MEI_FILE_DISCONNECTING;
324 return -EBADMSG; 316 cl->status = 0;
317 cb_pos->information = 0;
318 list_move_tail(&cb_pos->cb_list,
319 &dev->ctrl_rd_list.mei_cb.cb_list);
320 cl->timer_count = MEI_CONNECT_TIMEOUT;
325 } 321 }
326 322
327 return 0; 323 return 0;
@@ -575,10 +571,9 @@ static void mei_client_disconnect_request(struct mei_device *dev,
575 disconnect_req->me_addr); 571 disconnect_req->me_addr);
576 cl_pos->state = MEI_FILE_DISCONNECTED; 572 cl_pos->state = MEI_FILE_DISCONNECTED;
577 cl_pos->timer_count = 0; 573 cl_pos->timer_count = 0;
578 if (cl_pos == &dev->wd_cl) { 574 if (cl_pos == &dev->wd_cl)
579 dev->wd_due_counter = 0;
580 dev->wd_pending = false; 575 dev->wd_pending = false;
581 } else if (cl_pos == &dev->iamthif_cl) 576 else if (cl_pos == &dev->iamthif_cl)
582 dev->iamthif_timer = 0; 577 dev->iamthif_timer = 0;
583 578
584 /* prepare disconnect response */ 579 /* prepare disconnect response */
@@ -842,8 +837,8 @@ static int _mei_irq_thread_read(struct mei_device *dev, s32 *slots,
842 return -EBADMSG; 837 return -EBADMSG;
843 } 838 }
844 839
845 *slots -= (sizeof(struct mei_msg_hdr) + 840 *slots -= mei_data2slots(sizeof(struct hbm_flow_control));
846 sizeof(struct hbm_flow_control) + 3) / 4; 841
847 if (mei_send_flow_control(dev, cl)) { 842 if (mei_send_flow_control(dev, cl)) {
848 cl->status = -ENODEV; 843 cl->status = -ENODEV;
849 cb_pos->information = 0; 844 cb_pos->information = 0;
@@ -872,27 +867,25 @@ static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots,
872 struct mei_cl *cl, 867 struct mei_cl *cl,
873 struct mei_io_list *cmpl_list) 868 struct mei_io_list *cmpl_list)
874{ 869{
875 if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) + 870 if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) +
876 sizeof(struct hbm_client_connect_request))) { 871 sizeof(struct hbm_client_connect_request))) {
877 cl->state = MEI_FILE_CONNECTING;
878 *slots -= (sizeof(struct mei_msg_hdr) +
879 sizeof(struct hbm_client_connect_request) + 3) / 4;
880 if (mei_connect(dev, cl)) {
881 cl->status = -ENODEV;
882 cb_pos->information = 0;
883 list_del(&cb_pos->cb_list);
884 return -ENODEV;
885 } else {
886 list_move_tail(&cb_pos->cb_list,
887 &dev->ctrl_rd_list.mei_cb.cb_list);
888 cl->timer_count = MEI_CONNECT_TIMEOUT;
889 }
890 } else {
891 /* return the cancel routine */ 872 /* return the cancel routine */
892 list_del(&cb_pos->cb_list); 873 list_del(&cb_pos->cb_list);
893 return -EBADMSG; 874 return -EBADMSG;
894 } 875 }
895 876
877 cl->state = MEI_FILE_CONNECTING;
878 *slots -= mei_data2slots(sizeof(struct hbm_client_connect_request));
879 if (mei_connect(dev, cl)) {
880 cl->status = -ENODEV;
881 cb_pos->information = 0;
882 list_del(&cb_pos->cb_list);
883 return -ENODEV;
884 } else {
885 list_move_tail(&cb_pos->cb_list,
886 &dev->ctrl_rd_list.mei_cb.cb_list);
887 cl->timer_count = MEI_CONNECT_TIMEOUT;
888 }
896 return 0; 889 return 0;
897} 890}
898 891
@@ -932,8 +925,7 @@ static int _mei_irq_thread_cmpl(struct mei_device *dev, s32 *slots,
932 cb_pos->information); 925 cb_pos->information);
933 dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n", 926 dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n",
934 mei_hdr->length); 927 mei_hdr->length);
935 *slots -= (sizeof(struct mei_msg_hdr) + 928 *slots -= mei_data2slots(mei_hdr->length);
936 mei_hdr->length + 3) / 4;
937 if (mei_write_message(dev, mei_hdr, 929 if (mei_write_message(dev, mei_hdr,
938 (unsigned char *) 930 (unsigned char *)
939 (cb_pos->request_buffer.data + 931 (cb_pos->request_buffer.data +
@@ -951,7 +943,7 @@ static int _mei_irq_thread_cmpl(struct mei_device *dev, s32 *slots,
951 list_move_tail(&cb_pos->cb_list, 943 list_move_tail(&cb_pos->cb_list,
952 &dev->write_waiting_list.mei_cb.cb_list); 944 &dev->write_waiting_list.mei_cb.cb_list);
953 } 945 }
954 } else if (*slots == ((dev->host_hw_state & H_CBD) >> 24)) { 946 } else if (*slots == dev->hbuf_depth) {
955 /* buffer is still empty */ 947 /* buffer is still empty */
956 mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0]; 948 mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
957 mei_hdr->host_addr = cl->host_client_id; 949 mei_hdr->host_addr = cl->host_client_id;
@@ -960,9 +952,7 @@ static int _mei_irq_thread_cmpl(struct mei_device *dev, s32 *slots,
960 (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr); 952 (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
961 mei_hdr->msg_complete = 0; 953 mei_hdr->msg_complete = 0;
962 mei_hdr->reserved = 0; 954 mei_hdr->reserved = 0;
963 955 *slots -= mei_data2slots(mei_hdr->length);
964 (*slots) -= (sizeof(struct mei_msg_hdr) +
965 mei_hdr->length + 3) / 4;
966 if (mei_write_message(dev, mei_hdr, 956 if (mei_write_message(dev, mei_hdr,
967 (unsigned char *) 957 (unsigned char *)
968 (cb_pos->request_buffer.data + 958 (cb_pos->request_buffer.data +
@@ -1021,8 +1011,7 @@ static int _mei_irq_thread_cmpl_iamthif(struct mei_device *dev, s32 *slots,
1021 mei_hdr->msg_complete = 1; 1011 mei_hdr->msg_complete = 1;
1022 mei_hdr->reserved = 0; 1012 mei_hdr->reserved = 0;
1023 1013
1024 *slots -= (sizeof(struct mei_msg_hdr) + 1014 *slots -= mei_data2slots(mei_hdr->length);
1025 mei_hdr->length + 3) / 4;
1026 1015
1027 if (mei_write_message(dev, mei_hdr, 1016 if (mei_write_message(dev, mei_hdr,
1028 (dev->iamthif_msg_buf + 1017 (dev->iamthif_msg_buf +
@@ -1046,8 +1035,8 @@ static int _mei_irq_thread_cmpl_iamthif(struct mei_device *dev, s32 *slots,
1046 &dev->write_waiting_list.mei_cb.cb_list); 1035 &dev->write_waiting_list.mei_cb.cb_list);
1047 1036
1048 } 1037 }
1049 } else if (*slots == ((dev->host_hw_state & H_CBD) >> 24)) { 1038 } else if (*slots == dev->hbuf_depth) {
1050 /* buffer is still empty */ 1039 /* buffer is still empty */
1051 mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0]; 1040 mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
1052 mei_hdr->host_addr = cl->host_client_id; 1041 mei_hdr->host_addr = cl->host_client_id;
1053 mei_hdr->me_addr = cl->me_client_id; 1042 mei_hdr->me_addr = cl->me_client_id;
@@ -1056,8 +1045,7 @@ static int _mei_irq_thread_cmpl_iamthif(struct mei_device *dev, s32 *slots,
1056 mei_hdr->msg_complete = 0; 1045 mei_hdr->msg_complete = 0;
1057 mei_hdr->reserved = 0; 1046 mei_hdr->reserved = 0;
1058 1047
1059 *slots -= (sizeof(struct mei_msg_hdr) + 1048 *slots -= mei_data2slots(mei_hdr->length);
1060 mei_hdr->length + 3) / 4;
1061 1049
1062 if (mei_write_message(dev, mei_hdr, 1050 if (mei_write_message(dev, mei_hdr,
1063 (dev->iamthif_msg_buf + 1051 (dev->iamthif_msg_buf +
@@ -1199,17 +1187,19 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
1199 struct mei_io_list *list; 1187 struct mei_io_list *list;
1200 int ret; 1188 int ret;
1201 1189
1202 if (!mei_host_buffer_is_empty(dev)) { 1190 if (!mei_hbuf_is_empty(dev)) {
1203 dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n"); 1191 dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n");
1204 return 0; 1192 return 0;
1205 } 1193 }
1206 *slots = mei_count_empty_write_slots(dev); 1194 *slots = mei_hbuf_empty_slots(dev);
1195 if (*slots <= 0)
1196 return -EMSGSIZE;
1197
1207 /* complete all waiting for write CB */ 1198 /* complete all waiting for write CB */
1208 dev_dbg(&dev->pdev->dev, "complete all waiting for write cb.\n"); 1199 dev_dbg(&dev->pdev->dev, "complete all waiting for write cb.\n");
1209 1200
1210 list = &dev->write_waiting_list; 1201 list = &dev->write_waiting_list;
1211 list_for_each_entry_safe(pos, next, 1202 list_for_each_entry_safe(pos, next, &list->mei_cb.cb_list, cb_list) {
1212 &list->mei_cb.cb_list, cb_list) {
1213 cl = (struct mei_cl *)pos->file_private; 1203 cl = (struct mei_cl *)pos->file_private;
1214 if (cl == NULL) 1204 if (cl == NULL)
1215 continue; 1205 continue;
@@ -1219,17 +1209,15 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
1219 if (MEI_WRITING == cl->writing_state && 1209 if (MEI_WRITING == cl->writing_state &&
1220 (pos->major_file_operations == MEI_WRITE) && 1210 (pos->major_file_operations == MEI_WRITE) &&
1221 (cl != &dev->iamthif_cl)) { 1211 (cl != &dev->iamthif_cl)) {
1222 dev_dbg(&dev->pdev->dev, 1212 dev_dbg(&dev->pdev->dev, "MEI WRITE COMPLETE\n");
1223 "MEI WRITE COMPLETE\n");
1224 cl->writing_state = MEI_WRITE_COMPLETE; 1213 cl->writing_state = MEI_WRITE_COMPLETE;
1225 list_add_tail(&pos->cb_list, 1214 list_add_tail(&pos->cb_list,
1226 &cmpl_list->mei_cb.cb_list); 1215 &cmpl_list->mei_cb.cb_list);
1227 } 1216 }
1228 if (cl == &dev->iamthif_cl) { 1217 if (cl == &dev->iamthif_cl) {
1229 dev_dbg(&dev->pdev->dev, "check iamthif flow control.\n"); 1218 dev_dbg(&dev->pdev->dev, "check iamthif flow control.\n");
1230 if (dev->iamthif_flow_control_pending) { 1219 if (dev->iamthif_flow_control_pending) {
1231 ret = _mei_irq_thread_iamthif_read( 1220 ret = _mei_irq_thread_iamthif_read(dev, slots);
1232 dev, slots);
1233 if (ret) 1221 if (ret)
1234 return ret; 1222 return ret;
1235 } 1223 }
@@ -1254,25 +1242,18 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
1254 } 1242 }
1255 if (dev->mei_state == MEI_ENABLED) { 1243 if (dev->mei_state == MEI_ENABLED) {
1256 if (dev->wd_pending && 1244 if (dev->wd_pending &&
1257 mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) { 1245 mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) {
1258 if (mei_wd_send(dev)) 1246 if (mei_wd_send(dev))
1259 dev_dbg(&dev->pdev->dev, "wd send failed.\n"); 1247 dev_dbg(&dev->pdev->dev, "wd send failed.\n");
1260 else 1248 else if (mei_flow_ctrl_reduce(dev, &dev->wd_cl))
1261 if (mei_flow_ctrl_reduce(dev, &dev->wd_cl)) 1249 return -ENODEV;
1262 return -ENODEV;
1263 1250
1264 dev->wd_pending = false; 1251 dev->wd_pending = false;
1265 1252
1266 if (dev->wd_timeout) { 1253 if (dev->wd_timeout)
1267 *slots -= (sizeof(struct mei_msg_hdr) + 1254 *slots -= mei_data2slots(MEI_START_WD_DATA_SIZE);
1268 MEI_START_WD_DATA_SIZE + 3) / 4; 1255 else
1269 dev->wd_due_counter = 2; 1256 *slots -= mei_data2slots(MEI_START_WD_DATA_SIZE);
1270 } else {
1271 *slots -= (sizeof(struct mei_msg_hdr) +
1272 MEI_WD_PARAMS_SIZE + 3) / 4;
1273 dev->wd_due_counter = 0;
1274 }
1275
1276 } 1257 }
1277 } 1258 }
1278 if (dev->stop) 1259 if (dev->stop)
@@ -1320,42 +1301,34 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
1320 /* complete write list CB */ 1301 /* complete write list CB */
1321 dev_dbg(&dev->pdev->dev, "complete write list cb.\n"); 1302 dev_dbg(&dev->pdev->dev, "complete write list cb.\n");
1322 list_for_each_entry_safe(pos, next, 1303 list_for_each_entry_safe(pos, next,
1323 &dev->write_list.mei_cb.cb_list, cb_list) { 1304 &dev->write_list.mei_cb.cb_list, cb_list) {
1324 cl = (struct mei_cl *)pos->file_private; 1305 cl = (struct mei_cl *)pos->file_private;
1325 if (cl == NULL) 1306 if (cl == NULL)
1326 continue; 1307 continue;
1327 1308
1328 if (cl != &dev->iamthif_cl) { 1309 if (cl != &dev->iamthif_cl) {
1329 if (!mei_flow_ctrl_creds(dev, cl)) { 1310 if (mei_flow_ctrl_creds(dev, cl) <= 0) {
1330 dev_dbg(&dev->pdev->dev, 1311 dev_dbg(&dev->pdev->dev,
1331 "No flow control" 1312 "No flow control credentials for client %d, not sending.\n",
1332 " credentials for client" 1313 cl->host_client_id);
1333 " %d, not sending.\n",
1334 cl->host_client_id);
1335 continue; 1314 continue;
1336 } 1315 }
1337 ret = _mei_irq_thread_cmpl(dev, slots, 1316 ret = _mei_irq_thread_cmpl(dev, slots, pos,
1338 pos, 1317 cl, cmpl_list);
1339 cl, cmpl_list);
1340 if (ret) 1318 if (ret)
1341 return ret; 1319 return ret;
1342 1320
1343 } else if (cl == &dev->iamthif_cl) { 1321 } else if (cl == &dev->iamthif_cl) {
1344 /* IAMTHIF IOCTL */ 1322 /* IAMTHIF IOCTL */
1345 dev_dbg(&dev->pdev->dev, "complete amthi write cb.\n"); 1323 dev_dbg(&dev->pdev->dev, "complete amthi write cb.\n");
1346 if (!mei_flow_ctrl_creds(dev, cl)) { 1324 if (mei_flow_ctrl_creds(dev, cl) <= 0) {
1347 dev_dbg(&dev->pdev->dev, 1325 dev_dbg(&dev->pdev->dev,
1348 "No flow control" 1326 "No flow control credentials for amthi client %d.\n",
1349 " credentials for amthi" 1327 cl->host_client_id);
1350 " client %d.\n",
1351 cl->host_client_id);
1352 continue; 1328 continue;
1353 } 1329 }
1354 ret = _mei_irq_thread_cmpl_iamthif(dev, 1330 ret = _mei_irq_thread_cmpl_iamthif(dev, slots, pos,
1355 slots, 1331 cl, cmpl_list);
1356 pos,
1357 cl,
1358 cmpl_list);
1359 if (ret) 1332 if (ret)
1360 return ret; 1333 return ret;
1361 1334
@@ -1555,7 +1528,7 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id)
1555end: 1528end:
1556 dev_dbg(&dev->pdev->dev, "end of bottom half function.\n"); 1529 dev_dbg(&dev->pdev->dev, "end of bottom half function.\n");
1557 dev->host_hw_state = mei_hcsr_read(dev); 1530 dev->host_hw_state = mei_hcsr_read(dev);
1558 dev->mei_host_buffer_is_empty = mei_host_buffer_is_empty(dev); 1531 dev->mei_host_buffer_is_empty = mei_hbuf_is_empty(dev);
1559 1532
1560 bus_message_received = false; 1533 bus_message_received = false;
1561 if (dev->recvd_msg && waitqueue_active(&dev->wait_recvd_msg)) { 1534 if (dev->recvd_msg && waitqueue_active(&dev->wait_recvd_msg)) {