aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/mei/wd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/mei/wd.c')
-rw-r--r--drivers/misc/mei/wd.c77
1 files changed, 44 insertions, 33 deletions
diff --git a/drivers/misc/mei/wd.c b/drivers/misc/mei/wd.c
index 9299a8c29a6f..2413247fc392 100644
--- a/drivers/misc/mei/wd.c
+++ b/drivers/misc/mei/wd.c
@@ -21,11 +21,13 @@
21#include <linux/sched.h> 21#include <linux/sched.h>
22#include <linux/watchdog.h> 22#include <linux/watchdog.h>
23 23
24#include "mei_dev.h"
25#include "hw.h"
26#include "interface.h"
27#include <linux/mei.h> 24#include <linux/mei.h>
28 25
26#include "mei_dev.h"
27#include "hbm.h"
28#include "hw-me.h"
29#include "client.h"
30
29static const u8 mei_start_wd_params[] = { 0x02, 0x12, 0x13, 0x10 }; 31static const u8 mei_start_wd_params[] = { 0x02, 0x12, 0x13, 0x10 };
30static const u8 mei_stop_wd_params[] = { 0x02, 0x02, 0x14, 0x10 }; 32static const u8 mei_stop_wd_params[] = { 0x02, 0x02, 0x14, 0x10 };
31 33
@@ -62,30 +64,41 @@ static void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout)
62 */ 64 */
63int mei_wd_host_init(struct mei_device *dev) 65int mei_wd_host_init(struct mei_device *dev)
64{ 66{
65 int id; 67 struct mei_cl *cl = &dev->wd_cl;
66 mei_cl_init(&dev->wd_cl, dev); 68 int i;
69 int ret;
70
71 mei_cl_init(cl, dev);
67 72
68 /* look for WD client and connect to it */
69 dev->wd_cl.state = MEI_FILE_DISCONNECTED;
70 dev->wd_timeout = MEI_WD_DEFAULT_TIMEOUT; 73 dev->wd_timeout = MEI_WD_DEFAULT_TIMEOUT;
71 dev->wd_state = MEI_WD_IDLE; 74 dev->wd_state = MEI_WD_IDLE;
72 75
73 /* Connect WD ME client to the host client */
74 id = mei_me_cl_link(dev, &dev->wd_cl,
75 &mei_wd_guid, MEI_WD_HOST_CLIENT_ID);
76 76
77 if (id < 0) { 77 /* check for valid client id */
78 i = mei_me_cl_by_uuid(dev, &mei_wd_guid);
79 if (i < 0) {
78 dev_info(&dev->pdev->dev, "wd: failed to find the client\n"); 80 dev_info(&dev->pdev->dev, "wd: failed to find the client\n");
79 return -ENOENT; 81 return -ENOENT;
80 } 82 }
81 83
82 if (mei_connect(dev, &dev->wd_cl)) { 84 cl->me_client_id = dev->me_clients[i].client_id;
85
86 ret = mei_cl_link(cl, MEI_WD_HOST_CLIENT_ID);
87
88 if (ret < 0) {
89 dev_info(&dev->pdev->dev, "wd: failed link client\n");
90 return -ENOENT;
91 }
92
93 cl->state = MEI_FILE_CONNECTING;
94
95 if (mei_hbm_cl_connect_req(dev, cl)) {
83 dev_err(&dev->pdev->dev, "wd: failed to connect to the client\n"); 96 dev_err(&dev->pdev->dev, "wd: failed to connect to the client\n");
84 dev->wd_cl.state = MEI_FILE_DISCONNECTED; 97 cl->state = MEI_FILE_DISCONNECTED;
85 dev->wd_cl.host_client_id = 0; 98 cl->host_client_id = 0;
86 return -EIO; 99 return -EIO;
87 } 100 }
88 dev->wd_cl.timer_count = MEI_CONNECT_TIMEOUT; 101 cl->timer_count = MEI_CONNECT_TIMEOUT;
89 102
90 return 0; 103 return 0;
91} 104}
@@ -101,22 +114,21 @@ int mei_wd_host_init(struct mei_device *dev)
101 */ 114 */
102int mei_wd_send(struct mei_device *dev) 115int mei_wd_send(struct mei_device *dev)
103{ 116{
104 struct mei_msg_hdr *mei_hdr; 117 struct mei_msg_hdr hdr;
105 118
106 mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0]; 119 hdr.host_addr = dev->wd_cl.host_client_id;
107 mei_hdr->host_addr = dev->wd_cl.host_client_id; 120 hdr.me_addr = dev->wd_cl.me_client_id;
108 mei_hdr->me_addr = dev->wd_cl.me_client_id; 121 hdr.msg_complete = 1;
109 mei_hdr->msg_complete = 1; 122 hdr.reserved = 0;
110 mei_hdr->reserved = 0;
111 123
112 if (!memcmp(dev->wd_data, mei_start_wd_params, MEI_WD_HDR_SIZE)) 124 if (!memcmp(dev->wd_data, mei_start_wd_params, MEI_WD_HDR_SIZE))
113 mei_hdr->length = MEI_WD_START_MSG_SIZE; 125 hdr.length = MEI_WD_START_MSG_SIZE;
114 else if (!memcmp(dev->wd_data, mei_stop_wd_params, MEI_WD_HDR_SIZE)) 126 else if (!memcmp(dev->wd_data, mei_stop_wd_params, MEI_WD_HDR_SIZE))
115 mei_hdr->length = MEI_WD_STOP_MSG_SIZE; 127 hdr.length = MEI_WD_STOP_MSG_SIZE;
116 else 128 else
117 return -EINVAL; 129 return -EINVAL;
118 130
119 return mei_write_message(dev, mei_hdr, dev->wd_data, mei_hdr->length); 131 return mei_write_message(dev, &hdr, dev->wd_data);
120} 132}
121 133
122/** 134/**
@@ -141,16 +153,16 @@ int mei_wd_stop(struct mei_device *dev)
141 153
142 dev->wd_state = MEI_WD_STOPPING; 154 dev->wd_state = MEI_WD_STOPPING;
143 155
144 ret = mei_flow_ctrl_creds(dev, &dev->wd_cl); 156 ret = mei_cl_flow_ctrl_creds(&dev->wd_cl);
145 if (ret < 0) 157 if (ret < 0)
146 goto out; 158 goto out;
147 159
148 if (ret && dev->mei_host_buffer_is_empty) { 160 if (ret && dev->hbuf_is_ready) {
149 ret = 0; 161 ret = 0;
150 dev->mei_host_buffer_is_empty = false; 162 dev->hbuf_is_ready = false;
151 163
152 if (!mei_wd_send(dev)) { 164 if (!mei_wd_send(dev)) {
153 ret = mei_flow_ctrl_reduce(dev, &dev->wd_cl); 165 ret = mei_cl_flow_ctrl_reduce(&dev->wd_cl);
154 if (ret) 166 if (ret)
155 goto out; 167 goto out;
156 } else { 168 } else {
@@ -270,10 +282,9 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
270 dev->wd_state = MEI_WD_RUNNING; 282 dev->wd_state = MEI_WD_RUNNING;
271 283
272 /* Check if we can send the ping to HW*/ 284 /* Check if we can send the ping to HW*/
273 if (dev->mei_host_buffer_is_empty && 285 if (dev->hbuf_is_ready && mei_cl_flow_ctrl_creds(&dev->wd_cl) > 0) {
274 mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) {
275 286
276 dev->mei_host_buffer_is_empty = false; 287 dev->hbuf_is_ready = false;
277 dev_dbg(&dev->pdev->dev, "wd: sending ping\n"); 288 dev_dbg(&dev->pdev->dev, "wd: sending ping\n");
278 289
279 if (mei_wd_send(dev)) { 290 if (mei_wd_send(dev)) {
@@ -282,9 +293,9 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
282 goto end; 293 goto end;
283 } 294 }
284 295
285 if (mei_flow_ctrl_reduce(dev, &dev->wd_cl)) { 296 if (mei_cl_flow_ctrl_reduce(&dev->wd_cl)) {
286 dev_err(&dev->pdev->dev, 297 dev_err(&dev->pdev->dev,
287 "wd: mei_flow_ctrl_reduce() failed.\n"); 298 "wd: mei_cl_flow_ctrl_reduce() failed.\n");
288 ret = -EIO; 299 ret = -EIO;
289 goto end; 300 goto end;
290 } 301 }