Merge branch 'hv_netvsc-Fix-send-indirection-table-offset'
Haiyang Zhang says: ==================== hv_netvsc: Fix send indirection table offset Fix send indirection table offset issues related to guest and host bugs. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>alistair/sunxi64-5.4-dsi
commit
d814b67e50
|
@ -609,7 +609,8 @@ struct nvsp_5_send_indirect_table {
|
||||||
/* The number of entries in the send indirection table */
|
/* The number of entries in the send indirection table */
|
||||||
u32 count;
|
u32 count;
|
||||||
|
|
||||||
/* The offset of the send indirection table from top of this struct.
|
/* The offset of the send indirection table from the beginning of
|
||||||
|
* struct nvsp_message.
|
||||||
* The send indirection table tells which channel to put the send
|
* The send indirection table tells which channel to put the send
|
||||||
* traffic on. Each entry is a channel number.
|
* traffic on. Each entry is a channel number.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1178,20 +1178,39 @@ static int netvsc_receive(struct net_device *ndev,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void netvsc_send_table(struct net_device *ndev,
|
static void netvsc_send_table(struct net_device *ndev,
|
||||||
const struct nvsp_message *nvmsg)
|
struct netvsc_device *nvscdev,
|
||||||
|
const struct nvsp_message *nvmsg,
|
||||||
|
u32 msglen)
|
||||||
{
|
{
|
||||||
struct net_device_context *net_device_ctx = netdev_priv(ndev);
|
struct net_device_context *net_device_ctx = netdev_priv(ndev);
|
||||||
u32 count, *tab;
|
u32 count, offset, *tab;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
count = nvmsg->msg.v5_msg.send_table.count;
|
count = nvmsg->msg.v5_msg.send_table.count;
|
||||||
|
offset = nvmsg->msg.v5_msg.send_table.offset;
|
||||||
|
|
||||||
if (count != VRSS_SEND_TAB_SIZE) {
|
if (count != VRSS_SEND_TAB_SIZE) {
|
||||||
netdev_err(ndev, "Received wrong send-table size:%u\n", count);
|
netdev_err(ndev, "Received wrong send-table size:%u\n", count);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tab = (u32 *)((unsigned long)&nvmsg->msg.v5_msg.send_table +
|
/* If negotiated version <= NVSP_PROTOCOL_VERSION_6, the offset may be
|
||||||
nvmsg->msg.v5_msg.send_table.offset);
|
* wrong due to a host bug. So fix the offset here.
|
||||||
|
*/
|
||||||
|
if (nvscdev->nvsp_version <= NVSP_PROTOCOL_VERSION_6 &&
|
||||||
|
msglen >= sizeof(struct nvsp_message_header) +
|
||||||
|
sizeof(union nvsp_6_message_uber) + count * sizeof(u32))
|
||||||
|
offset = sizeof(struct nvsp_message_header) +
|
||||||
|
sizeof(union nvsp_6_message_uber);
|
||||||
|
|
||||||
|
/* Boundary check for all versions */
|
||||||
|
if (offset > msglen - count * sizeof(u32)) {
|
||||||
|
netdev_err(ndev, "Received send-table offset too big:%u\n",
|
||||||
|
offset);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tab = (void *)nvmsg + offset;
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < count; i++)
|
||||||
net_device_ctx->tx_table[i] = tab[i];
|
net_device_ctx->tx_table[i] = tab[i];
|
||||||
|
@ -1209,12 +1228,14 @@ static void netvsc_send_vf(struct net_device *ndev,
|
||||||
net_device_ctx->vf_alloc ? "added" : "removed");
|
net_device_ctx->vf_alloc ? "added" : "removed");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void netvsc_receive_inband(struct net_device *ndev,
|
static void netvsc_receive_inband(struct net_device *ndev,
|
||||||
const struct nvsp_message *nvmsg)
|
struct netvsc_device *nvscdev,
|
||||||
|
const struct nvsp_message *nvmsg,
|
||||||
|
u32 msglen)
|
||||||
{
|
{
|
||||||
switch (nvmsg->hdr.msg_type) {
|
switch (nvmsg->hdr.msg_type) {
|
||||||
case NVSP_MSG5_TYPE_SEND_INDIRECTION_TABLE:
|
case NVSP_MSG5_TYPE_SEND_INDIRECTION_TABLE:
|
||||||
netvsc_send_table(ndev, nvmsg);
|
netvsc_send_table(ndev, nvscdev, nvmsg, msglen);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NVSP_MSG4_TYPE_SEND_VF_ASSOCIATION:
|
case NVSP_MSG4_TYPE_SEND_VF_ASSOCIATION:
|
||||||
|
@ -1232,6 +1253,7 @@ static int netvsc_process_raw_pkt(struct hv_device *device,
|
||||||
{
|
{
|
||||||
struct vmbus_channel *channel = nvchan->channel;
|
struct vmbus_channel *channel = nvchan->channel;
|
||||||
const struct nvsp_message *nvmsg = hv_pkt_data(desc);
|
const struct nvsp_message *nvmsg = hv_pkt_data(desc);
|
||||||
|
u32 msglen = hv_pkt_datalen(desc);
|
||||||
|
|
||||||
trace_nvsp_recv(ndev, channel, nvmsg);
|
trace_nvsp_recv(ndev, channel, nvmsg);
|
||||||
|
|
||||||
|
@ -1247,7 +1269,7 @@ static int netvsc_process_raw_pkt(struct hv_device *device,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VM_PKT_DATA_INBAND:
|
case VM_PKT_DATA_INBAND:
|
||||||
netvsc_receive_inband(ndev, nvmsg);
|
netvsc_receive_inband(ndev, net_device, nvmsg, msglen);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
Loading…
Reference in New Issue