PageRenderTime 6435ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 1ms

/SPECS/linux/0008-Drivers-hv-vmbus-Use-all-supported-IC-versions-to-ne.patch

https://gitlab.com/unofficial-mirrors/vmware-photon
Patch | 492 lines | 455 code | 37 blank | 0 comment | 0 complexity | e44632561d786c98eef5e8a2d587c413 MD5 | raw file
  1. From 66955115f0d8764a93c4ec9291d917d4a8be3e8f Mon Sep 17 00:00:00 2001
  2. From: Alex Ng <alexng@messages.microsoft.com>
  3. Date: Sat, 28 Jan 2017 12:37:17 -0700
  4. Subject: [PATCH 08/13] Drivers: hv: vmbus: Use all supported IC versions to
  5. negotiate
  6. Previously, we were assuming that each IC protocol version was tied to a
  7. specific host version. For example, some Windows 10 preview hosts only
  8. support v3 TimeSync even though driver assumes v4 is supported by all
  9. Windows 10 hosts.
  10. The guest will stop trying to negotiate even though older supported
  11. versions may still be offered by the host.
  12. Make IC version negotiation more robust by going through all versions
  13. that are supported by the guest.
  14. Fixes: 3da0401b4d0e ("Drivers: hv: utils: Fix the mapping between host
  15. version and protocol to use")
  16. Reported-by: Rolf Neugebauer <rolf.neugebauer@docker.com>
  17. Signed-off-by: Alex Ng <alexng@messages.microsoft.com>
  18. Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
  19. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  20. Origin: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
  21. (cherry picked from commit a1656454131880980bc3a5313c8bf66ef5990c91)
  22. ---
  23. drivers/hv/channel_mgmt.c | 80 +++++++++++++++++++++++++++-------------
  24. drivers/hv/hv_fcopy.c | 20 +++++++---
  25. drivers/hv/hv_kvp.c | 41 +++++++++------------
  26. drivers/hv/hv_snapshot.c | 18 +++++++--
  27. drivers/hv/hv_util.c | 94 +++++++++++++++++++++++++----------------------
  28. include/linux/hyperv.h | 7 ++--
  29. 6 files changed, 154 insertions(+), 106 deletions(-)
  30. diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
  31. index 8df02f3ca0b2..e7949b64bfbc 100644
  32. --- a/drivers/hv/channel_mgmt.c
  33. +++ b/drivers/hv/channel_mgmt.c
  34. @@ -202,33 +202,34 @@ static u16 hv_get_dev_type(const struct vmbus_channel *channel)
  35. * @buf: Raw buffer channel data
  36. *
  37. * @icmsghdrp is of type &struct icmsg_hdr.
  38. - * @negop is of type &struct icmsg_negotiate.
  39. * Set up and fill in default negotiate response message.
  40. *
  41. - * The fw_version specifies the framework version that
  42. - * we can support and srv_version specifies the service
  43. - * version we can support.
  44. + * The fw_version and fw_vercnt specifies the framework version that
  45. + * we can support.
  46. + *
  47. + * The srv_version and srv_vercnt specifies the service
  48. + * versions we can support.
  49. + *
  50. + * Versions are given in decreasing order.
  51. + *
  52. + * nego_fw_version and nego_srv_version store the selected protocol versions.
  53. *
  54. * Mainly used by Hyper-V drivers.
  55. */
  56. bool vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp,
  57. - struct icmsg_negotiate *negop, u8 *buf,
  58. - int fw_version, int srv_version)
  59. + u8 *buf, const int *fw_version, int fw_vercnt,
  60. + const int *srv_version, int srv_vercnt,
  61. + int *nego_fw_version, int *nego_srv_version)
  62. {
  63. int icframe_major, icframe_minor;
  64. int icmsg_major, icmsg_minor;
  65. int fw_major, fw_minor;
  66. int srv_major, srv_minor;
  67. - int i;
  68. + int i, j;
  69. bool found_match = false;
  70. + struct icmsg_negotiate *negop;
  71. icmsghdrp->icmsgsize = 0x10;
  72. - fw_major = (fw_version >> 16);
  73. - fw_minor = (fw_version & 0xFFFF);
  74. -
  75. - srv_major = (srv_version >> 16);
  76. - srv_minor = (srv_version & 0xFFFF);
  77. -
  78. negop = (struct icmsg_negotiate *)&buf[
  79. sizeof(struct vmbuspipe_hdr) +
  80. sizeof(struct icmsg_hdr)];
  81. @@ -244,13 +245,22 @@ bool vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp,
  82. * support.
  83. */
  84. - for (i = 0; i < negop->icframe_vercnt; i++) {
  85. - if ((negop->icversion_data[i].major == fw_major) &&
  86. - (negop->icversion_data[i].minor == fw_minor)) {
  87. - icframe_major = negop->icversion_data[i].major;
  88. - icframe_minor = negop->icversion_data[i].minor;
  89. - found_match = true;
  90. + for (i = 0; i < fw_vercnt; i++) {
  91. + fw_major = (fw_version[i] >> 16);
  92. + fw_minor = (fw_version[i] & 0xFFFF);
  93. +
  94. + for (j = 0; j < negop->icframe_vercnt; j++) {
  95. + if ((negop->icversion_data[j].major == fw_major) &&
  96. + (negop->icversion_data[j].minor == fw_minor)) {
  97. + icframe_major = negop->icversion_data[j].major;
  98. + icframe_minor = negop->icversion_data[j].minor;
  99. + found_match = true;
  100. + break;
  101. + }
  102. }
  103. +
  104. + if (found_match)
  105. + break;
  106. }
  107. if (!found_match)
  108. @@ -258,14 +268,26 @@ bool vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp,
  109. found_match = false;
  110. - for (i = negop->icframe_vercnt;
  111. - (i < negop->icframe_vercnt + negop->icmsg_vercnt); i++) {
  112. - if ((negop->icversion_data[i].major == srv_major) &&
  113. - (negop->icversion_data[i].minor == srv_minor)) {
  114. - icmsg_major = negop->icversion_data[i].major;
  115. - icmsg_minor = negop->icversion_data[i].minor;
  116. - found_match = true;
  117. + for (i = 0; i < srv_vercnt; i++) {
  118. + srv_major = (srv_version[i] >> 16);
  119. + srv_minor = (srv_version[i] & 0xFFFF);
  120. +
  121. + for (j = negop->icframe_vercnt;
  122. + (j < negop->icframe_vercnt + negop->icmsg_vercnt);
  123. + j++) {
  124. +
  125. + if ((negop->icversion_data[j].major == srv_major) &&
  126. + (negop->icversion_data[j].minor == srv_minor)) {
  127. +
  128. + icmsg_major = negop->icversion_data[j].major;
  129. + icmsg_minor = negop->icversion_data[j].minor;
  130. + found_match = true;
  131. + break;
  132. + }
  133. }
  134. +
  135. + if (found_match)
  136. + break;
  137. }
  138. /*
  139. @@ -282,6 +304,12 @@ bool vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp,
  140. negop->icmsg_vercnt = 1;
  141. }
  142. + if (nego_fw_version)
  143. + *nego_fw_version = (icframe_major << 16) | icframe_minor;
  144. +
  145. + if (nego_srv_version)
  146. + *nego_srv_version = (icmsg_major << 16) | icmsg_minor;
  147. +
  148. negop->icversion_data[0].major = icframe_major;
  149. negop->icversion_data[0].minor = icframe_minor;
  150. negop->icversion_data[1].major = icmsg_major;
  151. diff --git a/drivers/hv/hv_fcopy.c b/drivers/hv/hv_fcopy.c
  152. index e47d8c9db03a..0a315e6aa589 100644
  153. --- a/drivers/hv/hv_fcopy.c
  154. +++ b/drivers/hv/hv_fcopy.c
  155. @@ -31,6 +31,16 @@
  156. #define WIN8_SRV_MINOR 1
  157. #define WIN8_SRV_VERSION (WIN8_SRV_MAJOR << 16 | WIN8_SRV_MINOR)
  158. +#define FCOPY_VER_COUNT 1
  159. +static const int fcopy_versions[] = {
  160. + WIN8_SRV_VERSION
  161. +};
  162. +
  163. +#define FW_VER_COUNT 1
  164. +static const int fw_versions[] = {
  165. + UTIL_FW_VERSION
  166. +};
  167. +
  168. /*
  169. * Global state maintained for transaction that is being processed.
  170. * For a class of integration services, including the "file copy service",
  171. @@ -228,8 +238,6 @@ void hv_fcopy_onchannelcallback(void *context)
  172. u64 requestid;
  173. struct hv_fcopy_hdr *fcopy_msg;
  174. struct icmsg_hdr *icmsghdr;
  175. - struct icmsg_negotiate *negop = NULL;
  176. - int util_fw_version;
  177. int fcopy_srv_version;
  178. if (fcopy_transaction.state > HVUTIL_READY)
  179. @@ -243,10 +251,10 @@ void hv_fcopy_onchannelcallback(void *context)
  180. icmsghdr = (struct icmsg_hdr *)&recv_buffer[
  181. sizeof(struct vmbuspipe_hdr)];
  182. if (icmsghdr->icmsgtype == ICMSGTYPE_NEGOTIATE) {
  183. - util_fw_version = UTIL_FW_VERSION;
  184. - fcopy_srv_version = WIN8_SRV_VERSION;
  185. - vmbus_prep_negotiate_resp(icmsghdr, negop, recv_buffer,
  186. - util_fw_version, fcopy_srv_version);
  187. + vmbus_prep_negotiate_resp(icmsghdr, recv_buffer,
  188. + fw_versions, FW_VER_COUNT,
  189. + fcopy_versions, FCOPY_VER_COUNT,
  190. + NULL, &fcopy_srv_version);
  191. } else {
  192. fcopy_msg = (struct hv_fcopy_hdr *)&recv_buffer[
  193. sizeof(struct vmbuspipe_hdr) +
  194. diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
  195. index 3abfc5983c97..2cc670442f6c 100644
  196. --- a/drivers/hv/hv_kvp.c
  197. +++ b/drivers/hv/hv_kvp.c
  198. @@ -46,6 +46,19 @@
  199. #define WIN8_SRV_MINOR 0
  200. #define WIN8_SRV_VERSION (WIN8_SRV_MAJOR << 16 | WIN8_SRV_MINOR)
  201. +#define KVP_VER_COUNT 3
  202. +static const int kvp_versions[] = {
  203. + WIN8_SRV_VERSION,
  204. + WIN7_SRV_VERSION,
  205. + WS2008_SRV_VERSION
  206. +};
  207. +
  208. +#define FW_VER_COUNT 2
  209. +static const int fw_versions[] = {
  210. + UTIL_FW_VERSION,
  211. + UTIL_WS2K8_FW_VERSION
  212. +};
  213. +
  214. /*
  215. * Global state maintained for transaction that is being processed. For a class
  216. * of integration services, including the "KVP service", the specified protocol
  217. @@ -610,8 +623,6 @@ void hv_kvp_onchannelcallback(void *context)
  218. struct hv_kvp_msg *kvp_msg;
  219. struct icmsg_hdr *icmsghdrp;
  220. - struct icmsg_negotiate *negop = NULL;
  221. - int util_fw_version;
  222. int kvp_srv_version;
  223. static enum {NEGO_NOT_STARTED,
  224. NEGO_IN_PROGRESS,
  225. @@ -640,28 +651,10 @@ void hv_kvp_onchannelcallback(void *context)
  226. sizeof(struct vmbuspipe_hdr)];
  227. if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
  228. - /*
  229. - * Based on the host, select appropriate
  230. - * framework and service versions we will
  231. - * negotiate.
  232. - */
  233. - switch (vmbus_proto_version) {
  234. - case (VERSION_WS2008):
  235. - util_fw_version = UTIL_WS2K8_FW_VERSION;
  236. - kvp_srv_version = WS2008_SRV_VERSION;
  237. - break;
  238. - case (VERSION_WIN7):
  239. - util_fw_version = UTIL_FW_VERSION;
  240. - kvp_srv_version = WIN7_SRV_VERSION;
  241. - break;
  242. - default:
  243. - util_fw_version = UTIL_FW_VERSION;
  244. - kvp_srv_version = WIN8_SRV_VERSION;
  245. - }
  246. - vmbus_prep_negotiate_resp(icmsghdrp, negop,
  247. - recv_buffer, util_fw_version,
  248. - kvp_srv_version);
  249. -
  250. + vmbus_prep_negotiate_resp(icmsghdrp,
  251. + recv_buffer, fw_versions, FW_VER_COUNT,
  252. + kvp_versions, KVP_VER_COUNT,
  253. + NULL, &kvp_srv_version);
  254. } else {
  255. kvp_msg = (struct hv_kvp_msg *)&recv_buffer[
  256. sizeof(struct vmbuspipe_hdr) +
  257. diff --git a/drivers/hv/hv_snapshot.c b/drivers/hv/hv_snapshot.c
  258. index 4e543dbb731a..d14f10b924a0 100644
  259. --- a/drivers/hv/hv_snapshot.c
  260. +++ b/drivers/hv/hv_snapshot.c
  261. @@ -31,6 +31,16 @@
  262. #define VSS_MINOR 0
  263. #define VSS_VERSION (VSS_MAJOR << 16 | VSS_MINOR)
  264. +#define VSS_VER_COUNT 1
  265. +static const int vss_versions[] = {
  266. + VSS_VERSION
  267. +};
  268. +
  269. +#define FW_VER_COUNT 1
  270. +static const int fw_versions[] = {
  271. + UTIL_FW_VERSION
  272. +};
  273. +
  274. /*
  275. * Timeout values are based on expecations from host
  276. */
  277. @@ -297,7 +307,6 @@ void hv_vss_onchannelcallback(void *context)
  278. struct icmsg_hdr *icmsghdrp;
  279. - struct icmsg_negotiate *negop = NULL;
  280. if (vss_transaction.state > HVUTIL_READY)
  281. return;
  282. @@ -310,9 +319,10 @@ void hv_vss_onchannelcallback(void *context)
  283. sizeof(struct vmbuspipe_hdr)];
  284. if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
  285. - vmbus_prep_negotiate_resp(icmsghdrp, negop,
  286. - recv_buffer, UTIL_FW_VERSION,
  287. - VSS_VERSION);
  288. + vmbus_prep_negotiate_resp(icmsghdrp,
  289. + recv_buffer, fw_versions, FW_VER_COUNT,
  290. + vss_versions, VSS_VER_COUNT,
  291. + NULL, NULL);
  292. } else {
  293. vss_msg = (struct hv_vss_msg *)&recv_buffer[
  294. sizeof(struct vmbuspipe_hdr) +
  295. diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c
  296. index e7707747f56d..f3797c07be10 100644
  297. --- a/drivers/hv/hv_util.c
  298. +++ b/drivers/hv/hv_util.c
  299. @@ -57,7 +57,31 @@
  300. static int sd_srv_version;
  301. static int ts_srv_version;
  302. static int hb_srv_version;
  303. -static int util_fw_version;
  304. +
  305. +#define SD_VER_COUNT 2
  306. +static const int sd_versions[] = {
  307. + SD_VERSION,
  308. + SD_VERSION_1
  309. +};
  310. +
  311. +#define TS_VER_COUNT 3
  312. +static const int ts_versions[] = {
  313. + TS_VERSION,
  314. + TS_VERSION_3,
  315. + TS_VERSION_1
  316. +};
  317. +
  318. +#define HB_VER_COUNT 2
  319. +static const int hb_versions[] = {
  320. + HB_VERSION,
  321. + HB_VERSION_1
  322. +};
  323. +
  324. +#define FW_VER_COUNT 2
  325. +static const int fw_versions[] = {
  326. + UTIL_FW_VERSION,
  327. + UTIL_WS2K8_FW_VERSION
  328. +};
  329. static void shutdown_onchannelcallback(void *context);
  330. static struct hv_util_service util_shutdown = {
  331. @@ -118,7 +142,6 @@ static void shutdown_onchannelcallback(void *context)
  332. struct shutdown_msg_data *shutdown_msg;
  333. struct icmsg_hdr *icmsghdrp;
  334. - struct icmsg_negotiate *negop = NULL;
  335. vmbus_recvpacket(channel, shut_txf_buf,
  336. PAGE_SIZE, &recvlen, &requestid);
  337. @@ -128,9 +151,14 @@ static void shutdown_onchannelcallback(void *context)
  338. sizeof(struct vmbuspipe_hdr)];
  339. if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
  340. - vmbus_prep_negotiate_resp(icmsghdrp, negop,
  341. - shut_txf_buf, util_fw_version,
  342. - sd_srv_version);
  343. + if (vmbus_prep_negotiate_resp(icmsghdrp, shut_txf_buf,
  344. + fw_versions, FW_VER_COUNT,
  345. + sd_versions, SD_VER_COUNT,
  346. + NULL, &sd_srv_version)) {
  347. + pr_info("Shutdown IC version %d.%d\n",
  348. + sd_srv_version >> 16,
  349. + sd_srv_version & 0xFFFF);
  350. + }
  351. } else {
  352. shutdown_msg =
  353. (struct shutdown_msg_data *)&shut_txf_buf[
  354. @@ -253,7 +281,6 @@ static void timesync_onchannelcallback(void *context)
  355. struct ictimesync_data *timedatap;
  356. struct ictimesync_ref_data *refdata;
  357. u8 *time_txf_buf = util_timesynch.recv_buffer;
  358. - struct icmsg_negotiate *negop = NULL;
  359. vmbus_recvpacket(channel, time_txf_buf,
  360. PAGE_SIZE, &recvlen, &requestid);
  361. @@ -263,12 +290,14 @@ static void timesync_onchannelcallback(void *context)
  362. sizeof(struct vmbuspipe_hdr)];
  363. if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
  364. - vmbus_prep_negotiate_resp(icmsghdrp, negop,
  365. - time_txf_buf,
  366. - util_fw_version,
  367. - ts_srv_version);
  368. - pr_info("Using TimeSync version %d.%d\n",
  369. - ts_srv_version >> 16, ts_srv_version & 0xFFFF);
  370. + if (vmbus_prep_negotiate_resp(icmsghdrp, time_txf_buf,
  371. + fw_versions, FW_VER_COUNT,
  372. + ts_versions, TS_VER_COUNT,
  373. + NULL, &ts_srv_version)) {
  374. + pr_info("TimeSync version %d.%d\n",
  375. + ts_srv_version >> 16,
  376. + ts_srv_version & 0xFFFF);
  377. + }
  378. } else {
  379. if (ts_srv_version > TS_VERSION_3) {
  380. refdata = (struct ictimesync_ref_data *)
  381. @@ -312,7 +341,6 @@ static void heartbeat_onchannelcallback(void *context)
  382. struct icmsg_hdr *icmsghdrp;
  383. struct heartbeat_msg_data *heartbeat_msg;
  384. u8 *hbeat_txf_buf = util_heartbeat.recv_buffer;
  385. - struct icmsg_negotiate *negop = NULL;
  386. while (1) {
  387. @@ -326,9 +354,16 @@ static void heartbeat_onchannelcallback(void *context)
  388. sizeof(struct vmbuspipe_hdr)];
  389. if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
  390. - vmbus_prep_negotiate_resp(icmsghdrp, negop,
  391. - hbeat_txf_buf, util_fw_version,
  392. - hb_srv_version);
  393. + if (vmbus_prep_negotiate_resp(icmsghdrp,
  394. + hbeat_txf_buf,
  395. + fw_versions, FW_VER_COUNT,
  396. + hb_versions, HB_VER_COUNT,
  397. + NULL, &hb_srv_version)) {
  398. +
  399. + pr_info("Heartbeat version %d.%d\n",
  400. + hb_srv_version >> 16,
  401. + hb_srv_version & 0xFFFF);
  402. + }
  403. } else {
  404. heartbeat_msg =
  405. (struct heartbeat_msg_data *)&hbeat_txf_buf[
  406. @@ -378,33 +413,6 @@ static int util_probe(struct hv_device *dev,
  407. hv_set_drvdata(dev, srv);
  408. - /*
  409. - * Based on the host; initialize the framework and
  410. - * service version numbers we will negotiate.
  411. - */
  412. - switch (vmbus_proto_version) {
  413. - case (VERSION_WS2008):
  414. - util_fw_version = UTIL_WS2K8_FW_VERSION;
  415. - sd_srv_version = SD_VERSION_1;
  416. - ts_srv_version = TS_VERSION_1;
  417. - hb_srv_version = HB_VERSION_1;
  418. - break;
  419. - case VERSION_WIN7:
  420. - case VERSION_WIN8:
  421. - case VERSION_WIN8_1:
  422. - util_fw_version = UTIL_FW_VERSION;
  423. - sd_srv_version = SD_VERSION;
  424. - ts_srv_version = TS_VERSION_3;
  425. - hb_srv_version = HB_VERSION;
  426. - break;
  427. - case VERSION_WIN10:
  428. - default:
  429. - util_fw_version = UTIL_FW_VERSION;
  430. - sd_srv_version = SD_VERSION;
  431. - ts_srv_version = TS_VERSION;
  432. - hb_srv_version = HB_VERSION;
  433. - }
  434. -
  435. ret = vmbus_open(dev->channel, 4 * PAGE_SIZE, 4 * PAGE_SIZE, NULL, 0,
  436. srv->util_cb, dev->channel);
  437. if (ret)
  438. diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
  439. index 489ad74c1e6e..956acfc93487 100644
  440. --- a/include/linux/hyperv.h
  441. +++ b/include/linux/hyperv.h
  442. @@ -1453,9 +1453,10 @@ struct hyperv_service_callback {
  443. };
  444. #define MAX_SRV_VER 0x7ffffff
  445. -extern bool vmbus_prep_negotiate_resp(struct icmsg_hdr *,
  446. - struct icmsg_negotiate *, u8 *, int,
  447. - int);
  448. +extern bool vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, u8 *buf,
  449. + const int *fw_version, int fw_vercnt,
  450. + const int *srv_version, int srv_vercnt,
  451. + int *nego_fw_version, int *nego_srv_version);
  452. void hv_event_tasklet_disable(struct vmbus_channel *channel);
  453. void hv_event_tasklet_enable(struct vmbus_channel *channel);
  454. --
  455. 2.13.0