diff options
author | Tomas Winkler <tomas.winkler@intel.com> | 2014-08-21 07:29:13 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-09-24 01:57:48 -0400 |
commit | 5ca2d3882d60c040285d0b45df731e11f5da7c64 (patch) | |
tree | 1c66e2f92e47ed378b512034cbc4c2e22eaaddc2 /drivers/misc/mei/hbm.c | |
parent | d320832f64666089a06778782e42fac29abd7bf7 (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.c | 116 |
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 | */ |
78 | void mei_hbm_reset(struct mei_device *dev) | 78 | void 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 | */ | ||
97 | static 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 | |||
250 | static 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) | |||
641 | int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr) | 630 | int 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 */ |