aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/mei/hbm.c
diff options
context:
space:
mode:
authorTomas Winkler <tomas.winkler@intel.com>2014-08-21 07:29:13 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-09-24 01:57:48 -0400
commit5ca2d3882d60c040285d0b45df731e11f5da7c64 (patch)
tree1c66e2f92e47ed378b512034cbc4c2e22eaaddc2 /drivers/misc/mei/hbm.c
parentd320832f64666089a06778782e42fac29abd7bf7 (diff)
mei: use list for me clients book keeping
To support dynamic addition/remove of clients it is more convenient to use list instead of static array Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc/mei/hbm.c')
-rw-r--r--drivers/misc/mei/hbm.c116
1 files changed, 44 insertions, 72 deletions
diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c
index 0b21675967f9..45659de14186 100644
--- a/drivers/misc/mei/hbm.c
+++ b/drivers/misc/mei/hbm.c
@@ -77,51 +77,20 @@ void mei_hbm_idle(struct mei_device *dev)
77 */ 77 */
78void mei_hbm_reset(struct mei_device *dev) 78void mei_hbm_reset(struct mei_device *dev)
79{ 79{
80 dev->me_clients_num = 0; 80 struct mei_me_client *me_cl, *next;
81
81 dev->me_client_presentation_num = 0; 82 dev->me_client_presentation_num = 0;
82 dev->me_client_index = 0; 83 dev->me_client_index = 0;
83 84
84 kfree(dev->me_clients); 85 list_for_each_entry_safe(me_cl, next, &dev->me_clients, list) {
85 dev->me_clients = NULL; 86 list_del(&me_cl->list);
87 kfree(me_cl);
88 }
86 89
87 mei_hbm_idle(dev); 90 mei_hbm_idle(dev);
88} 91}
89 92
90/** 93/**
91 * mei_hbm_me_cl_allocate - allocates storage for me clients
92 *
93 * @dev: the device structure
94 *
95 * returns 0 on success -ENOMEM on allocation failure
96 */
97static int mei_hbm_me_cl_allocate(struct mei_device *dev)
98{
99 struct mei_me_client *clients;
100 int b;
101
102 mei_hbm_reset(dev);
103
104 /* count how many ME clients we have */
105 for_each_set_bit(b, dev->me_clients_map, MEI_CLIENTS_MAX)
106 dev->me_clients_num++;
107
108 if (dev->me_clients_num == 0)
109 return 0;
110
111 dev_dbg(&dev->pdev->dev, "memory allocation for ME clients size=%ld.\n",
112 dev->me_clients_num * sizeof(struct mei_me_client));
113 /* allocate storage for ME clients representation */
114 clients = kcalloc(dev->me_clients_num,
115 sizeof(struct mei_me_client), GFP_KERNEL);
116 if (!clients) {
117 dev_err(&dev->pdev->dev, "memory allocation for ME clients failed.\n");
118 return -ENOMEM;
119 }
120 dev->me_clients = clients;
121 return 0;
122}
123
124/**
125 * mei_hbm_cl_hdr - construct client hbm header 94 * mei_hbm_cl_hdr - construct client hbm header
126 * 95 *
127 * @cl: client 96 * @cl: client
@@ -213,6 +182,8 @@ int mei_hbm_start_req(struct mei_device *dev)
213 const size_t len = sizeof(struct hbm_host_version_request); 182 const size_t len = sizeof(struct hbm_host_version_request);
214 int ret; 183 int ret;
215 184
185 mei_hbm_reset(dev);
186
216 mei_hbm_hdr(mei_hdr, len); 187 mei_hbm_hdr(mei_hdr, len);
217 188
218 /* host start message */ 189 /* host start message */
@@ -267,6 +238,32 @@ static int mei_hbm_enum_clients_req(struct mei_device *dev)
267 return 0; 238 return 0;
268} 239}
269 240
241/*
242 * mei_hbm_me_cl_add - add new me client to the list
243 *
244 * @dev: the device structure
245 * @res: hbm property response
246 *
247 * returns 0 on success and -ENOMEM on allocation failure
248 */
249
250static int mei_hbm_me_cl_add(struct mei_device *dev,
251 struct hbm_props_response *res)
252{
253 struct mei_me_client *me_cl;
254
255 me_cl = kzalloc(sizeof(struct mei_me_client), GFP_KERNEL);
256 if (!me_cl)
257 return -ENOMEM;
258
259 me_cl->props = res->client_properties;
260 me_cl->client_id = res->me_addr;
261 me_cl->mei_flow_ctrl_creds = 0;
262
263 list_add(&me_cl->list, &dev->me_clients);
264 return 0;
265}
266
270/** 267/**
271 * mei_hbm_prop_req - request property for a single client 268 * mei_hbm_prop_req - request property for a single client
272 * 269 *
@@ -282,11 +279,8 @@ static int mei_hbm_prop_req(struct mei_device *dev)
282 struct hbm_props_request *prop_req; 279 struct hbm_props_request *prop_req;
283 const size_t len = sizeof(struct hbm_props_request); 280 const size_t len = sizeof(struct hbm_props_request);
284 unsigned long next_client_index; 281 unsigned long next_client_index;
285 unsigned long client_num;
286 int ret; 282 int ret;
287 283
288 client_num = dev->me_client_presentation_num;
289
290 next_client_index = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX, 284 next_client_index = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX,
291 dev->me_client_index); 285 dev->me_client_index);
292 286
@@ -298,15 +292,11 @@ static int mei_hbm_prop_req(struct mei_device *dev)
298 return 0; 292 return 0;
299 } 293 }
300 294
301 dev->me_clients[client_num].client_id = next_client_index;
302 dev->me_clients[client_num].mei_flow_ctrl_creds = 0;
303
304 mei_hbm_hdr(mei_hdr, len); 295 mei_hbm_hdr(mei_hdr, len);
305 prop_req = (struct hbm_props_request *)dev->wr_msg.data; 296 prop_req = (struct hbm_props_request *)dev->wr_msg.data;
306 297
307 memset(prop_req, 0, sizeof(struct hbm_props_request)); 298 memset(prop_req, 0, sizeof(struct hbm_props_request));
308 299
309
310 prop_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD; 300 prop_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD;
311 prop_req->me_addr = next_client_index; 301 prop_req->me_addr = next_client_index;
312 302
@@ -441,11 +431,10 @@ static void mei_hbm_cl_flow_control_res(struct mei_device *dev,
441 list_for_each_entry(cl, &dev->file_list, link) { 431 list_for_each_entry(cl, &dev->file_list, link) {
442 if (mei_hbm_cl_addr_equal(cl, flow_control)) { 432 if (mei_hbm_cl_addr_equal(cl, flow_control)) {
443 cl->mei_flow_ctrl_creds++; 433 cl->mei_flow_ctrl_creds++;
444 dev_dbg(&dev->pdev->dev, "flow ctrl msg for host %d ME %d.\n", 434 dev_dbg(&dev->pdev->dev, "flow ctrl msg for host %d ME %d creds %d.\n",
445 flow_control->host_addr, flow_control->me_addr); 435 flow_control->host_addr, flow_control->me_addr,
446 dev_dbg(&dev->pdev->dev, "flow control credentials = %d.\n", 436 cl->mei_flow_ctrl_creds);
447 cl->mei_flow_ctrl_creds); 437 break;
448 break;
449 } 438 }
450 } 439 }
451} 440}
@@ -641,7 +630,6 @@ bool mei_hbm_version_is_supported(struct mei_device *dev)
641int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr) 630int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
642{ 631{
643 struct mei_bus_message *mei_msg; 632 struct mei_bus_message *mei_msg;
644 struct mei_me_client *me_client;
645 struct hbm_host_version_response *version_res; 633 struct hbm_host_version_response *version_res;
646 struct hbm_client_connect_response *connect_res; 634 struct hbm_client_connect_response *connect_res;
647 struct hbm_client_connect_response *disconnect_res; 635 struct hbm_client_connect_response *disconnect_res;
@@ -763,13 +751,14 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
763 751
764 dev->init_clients_timer = 0; 752 dev->init_clients_timer = 0;
765 753
766 if (dev->me_clients == NULL) { 754 if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
767 dev_err(&dev->pdev->dev, "hbm: properties response: mei_clients not allocated\n"); 755 dev->hbm_state != MEI_HBM_CLIENT_PROPERTIES) {
756 dev_err(&dev->pdev->dev, "hbm: properties response: state mismatch, [%d, %d]\n",
757 dev->dev_state, dev->hbm_state);
768 return -EPROTO; 758 return -EPROTO;
769 } 759 }
770 760
771 props_res = (struct hbm_props_response *)mei_msg; 761 props_res = (struct hbm_props_response *)mei_msg;
772 me_client = &dev->me_clients[dev->me_client_presentation_num];
773 762
774 if (props_res->status) { 763 if (props_res->status) {
775 dev_err(&dev->pdev->dev, "hbm: properties response: wrong status = %d\n", 764 dev_err(&dev->pdev->dev, "hbm: properties response: wrong status = %d\n",
@@ -777,20 +766,8 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
777 return -EPROTO; 766 return -EPROTO;
778 } 767 }
779 768
780 if (me_client->client_id != props_res->me_addr) { 769 mei_hbm_me_cl_add(dev, props_res);
781 dev_err(&dev->pdev->dev, "hbm: properties response: address mismatch %d ?= %d\n",
782 me_client->client_id, props_res->me_addr);
783 return -EPROTO;
784 }
785 770
786 if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
787 dev->hbm_state != MEI_HBM_CLIENT_PROPERTIES) {
788 dev_err(&dev->pdev->dev, "hbm: properties response: state mismatch, [%d, %d]\n",
789 dev->dev_state, dev->hbm_state);
790 return -EPROTO;
791 }
792
793 me_client->props = props_res->client_properties;
794 dev->me_client_index++; 771 dev->me_client_index++;
795 dev->me_client_presentation_num++; 772 dev->me_client_presentation_num++;
796 773
@@ -809,7 +786,7 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
809 BUILD_BUG_ON(sizeof(dev->me_clients_map) 786 BUILD_BUG_ON(sizeof(dev->me_clients_map)
810 < sizeof(enum_res->valid_addresses)); 787 < sizeof(enum_res->valid_addresses));
811 memcpy(dev->me_clients_map, enum_res->valid_addresses, 788 memcpy(dev->me_clients_map, enum_res->valid_addresses,
812 sizeof(enum_res->valid_addresses)); 789 sizeof(enum_res->valid_addresses));
813 790
814 if (dev->dev_state != MEI_DEV_INIT_CLIENTS || 791 if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
815 dev->hbm_state != MEI_HBM_ENUM_CLIENTS) { 792 dev->hbm_state != MEI_HBM_ENUM_CLIENTS) {
@@ -818,11 +795,6 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
818 return -EPROTO; 795 return -EPROTO;
819 } 796 }
820 797
821 if (mei_hbm_me_cl_allocate(dev)) {
822 dev_err(&dev->pdev->dev, "hbm: enumeration response: cannot allocate clients array\n");
823 return -ENOMEM;
824 }
825
826 dev->hbm_state = MEI_HBM_CLIENT_PROPERTIES; 798 dev->hbm_state = MEI_HBM_CLIENT_PROPERTIES;
827 799
828 /* first property request */ 800 /* first property request */