Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mei: revamp client connection

Simplify connect state machine by changing the logic around
Connection request in progress - only check if we have a callback in
relevant queue.
Extract common code into mei_cl_send_connect() function

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Tomas Winkler and committed by
Greg Kroah-Hartman
0c53357c 3c666182

+83 -66
+6
drivers/misc/mei/bus.c
··· 436 436 437 437 mutex_lock(&dev->device_lock); 438 438 439 + if (mei_cl_is_connected(cl)) { 440 + mutex_unlock(&dev->device_lock); 441 + dev_warn(dev->dev, "Already connected"); 442 + return -EBUSY; 443 + } 444 + 439 445 err = mei_cl_connect(cl, NULL); 440 446 if (err < 0) { 441 447 mutex_unlock(&dev->device_lock);
+75 -22
drivers/misc/mei/client.c
··· 881 881 * 882 882 * Return: true if other client is connected, false - otherwise. 883 883 */ 884 - bool mei_cl_is_other_connecting(struct mei_cl *cl) 884 + static bool mei_cl_is_other_connecting(struct mei_cl *cl) 885 885 { 886 886 struct mei_device *dev; 887 - struct mei_cl *ocl; /* the other client */ 888 - 889 - if (WARN_ON(!cl || !cl->dev)) 890 - return false; 887 + struct mei_cl_cb *cb; 891 888 892 889 dev = cl->dev; 893 890 894 - list_for_each_entry(ocl, &dev->file_list, link) { 895 - if (ocl->state == MEI_FILE_CONNECTING && 896 - ocl != cl && 897 - cl->me_client_id == ocl->me_client_id) 891 + list_for_each_entry(cb, &dev->ctrl_rd_list.list, list) { 892 + if (cb->fop_type == MEI_FOP_CONNECT && 893 + cl->me_client_id == cb->cl->me_client_id) 898 894 return true; 899 - 900 895 } 901 896 902 897 return false; 898 + } 899 + 900 + /** 901 + * mei_cl_send_connect - send connect request 902 + * 903 + * @cl: host client 904 + * @cb: callback block 905 + * 906 + * Return: 0, OK; otherwise, error. 907 + */ 908 + static int mei_cl_send_connect(struct mei_cl *cl, struct mei_cl_cb *cb) 909 + { 910 + struct mei_device *dev; 911 + int ret; 912 + 913 + dev = cl->dev; 914 + 915 + ret = mei_hbm_cl_connect_req(dev, cl); 916 + cl->status = ret; 917 + if (ret) { 918 + cl->state = MEI_FILE_DISCONNECT_REPLY; 919 + return ret; 920 + } 921 + 922 + list_move_tail(&cb->list, &dev->ctrl_rd_list.list); 923 + cl->timer_count = MEI_CONNECT_TIMEOUT; 924 + return 0; 925 + } 926 + 927 + /** 928 + * mei_cl_irq_connect - send connect request in irq_thread context 929 + * 930 + * @cl: host client 931 + * @cb: callback block 932 + * @cmpl_list: complete list 933 + * 934 + * Return: 0, OK; otherwise, error. 935 + */ 936 + int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb, 937 + struct mei_cl_cb *cmpl_list) 938 + { 939 + struct mei_device *dev = cl->dev; 940 + u32 msg_slots; 941 + int slots; 942 + int rets; 943 + 944 + msg_slots = mei_data2slots(sizeof(struct hbm_client_connect_request)); 945 + slots = mei_hbuf_empty_slots(dev); 946 + 947 + if (mei_cl_is_other_connecting(cl)) 948 + return 0; 949 + 950 + if (slots < msg_slots) 951 + return -EMSGSIZE; 952 + 953 + rets = mei_cl_send_connect(cl, cb); 954 + if (rets) 955 + list_move_tail(&cb->list, &cmpl_list->list); 956 + 957 + return rets; 903 958 } 904 959 905 960 /** ··· 990 935 if (rets) 991 936 goto out; 992 937 938 + cl->state = MEI_FILE_CONNECTING; 939 + list_add_tail(&cb->list, &dev->ctrl_wr_list.list); 940 + 993 941 /* run hbuf acquire last so we don't have to undo */ 994 942 if (!mei_cl_is_other_connecting(cl) && mei_hbuf_acquire(dev)) { 995 - cl->state = MEI_FILE_CONNECTING; 996 - if (mei_hbm_cl_connect_req(dev, cl)) { 997 - rets = -ENODEV; 943 + rets = mei_cl_send_connect(cl, cb); 944 + if (rets) 998 945 goto out; 999 - } 1000 - cl->timer_count = MEI_CONNECT_TIMEOUT; 1001 - list_add_tail(&cb->list, &dev->ctrl_rd_list.list); 1002 - } else { 1003 - cl->state = MEI_FILE_INITIALIZING; 1004 - list_add_tail(&cb->list, &dev->ctrl_wr_list.list); 1005 946 } 1006 947 1007 948 mutex_unlock(&dev->device_lock); ··· 1008 957 mutex_lock(&dev->device_lock); 1009 958 1010 959 if (!mei_cl_is_connected(cl)) { 1011 - /* something went really wrong */ 960 + /* timeout or something went really wrong */ 1012 961 if (!cl->status) 1013 962 cl->status = -EFAULT; 1014 - mei_cl_set_disconnected(cl); 1015 963 } 1016 964 1017 965 rets = cl->status; 1018 - 1019 966 out: 1020 967 cl_dbg(dev, cl, "rpm: autosuspend\n"); 1021 968 pm_runtime_mark_last_busy(dev->dev); 1022 969 pm_runtime_put_autosuspend(dev->dev); 1023 970 1024 971 mei_io_cb_free(cb); 972 + 973 + if (!mei_cl_is_connected(cl)) 974 + mei_cl_set_disconnected(cl); 975 + 1025 976 return rets; 1026 977 } 1027 978
+2 -1
drivers/misc/mei/client.h
··· 103 103 return cl->state == MEI_FILE_CONNECTED; 104 104 } 105 105 106 - bool mei_cl_is_other_connecting(struct mei_cl *cl); 107 106 int mei_cl_disconnect(struct mei_cl *cl); 108 107 void mei_cl_set_disconnected(struct mei_cl *cl); 109 108 int mei_cl_irq_disconnect(struct mei_cl *cl, struct mei_cl_cb *cb, 110 109 struct mei_cl_cb *cmpl_list); 111 110 int mei_cl_connect(struct mei_cl *cl, struct file *file); 111 + int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb, 112 + struct mei_cl_cb *cmpl_list); 112 113 int mei_cl_read_start(struct mei_cl *cl, size_t length, struct file *fp); 113 114 int mei_cl_irq_read_msg(struct mei_cl *cl, struct mei_msg_hdr *hdr, 114 115 struct mei_cl_cb *cmpl_list);
-43
drivers/misc/mei/interrupt.c
··· 223 223 return 0; 224 224 } 225 225 226 - 227 - /** 228 - * mei_cl_irq_connect - send connect request in irq_thread context 229 - * 230 - * @cl: client 231 - * @cb: callback block. 232 - * @cmpl_list: complete list. 233 - * 234 - * Return: 0, OK; otherwise, error. 235 - */ 236 - static int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb, 237 - struct mei_cl_cb *cmpl_list) 238 - { 239 - struct mei_device *dev = cl->dev; 240 - u32 msg_slots; 241 - int slots; 242 - int ret; 243 - 244 - msg_slots = mei_data2slots(sizeof(struct hbm_client_connect_request)); 245 - slots = mei_hbuf_empty_slots(dev); 246 - 247 - if (mei_cl_is_other_connecting(cl)) 248 - return 0; 249 - 250 - if (slots < msg_slots) 251 - return -EMSGSIZE; 252 - 253 - cl->state = MEI_FILE_CONNECTING; 254 - 255 - ret = mei_hbm_cl_connect_req(dev, cl); 256 - if (ret) { 257 - cl->status = ret; 258 - cb->buf_idx = 0; 259 - list_del_init(&cb->list); 260 - return ret; 261 - } 262 - 263 - list_move_tail(&cb->list, &dev->ctrl_rd_list.list); 264 - cl->timer_count = MEI_CONNECT_TIMEOUT; 265 - return 0; 266 - } 267 - 268 - 269 226 /** 270 227 * mei_irq_read_handler - bottom half read routine after ISR to 271 228 * handle the read processing.