diff options
Diffstat (limited to 'drivers/staging/hv/rndis_filter.c')
-rw-r--r-- | drivers/staging/hv/rndis_filter.c | 146 |
1 files changed, 85 insertions, 61 deletions
diff --git a/drivers/staging/hv/rndis_filter.c b/drivers/staging/hv/rndis_filter.c index dbb52019975..bafccb36004 100644 --- a/drivers/staging/hv/rndis_filter.c +++ b/drivers/staging/hv/rndis_filter.c @@ -27,7 +27,6 @@ #include <linux/if_ether.h> #include <linux/netdevice.h> -#include "hyperv.h" #include "hyperv_net.h" @@ -42,7 +41,7 @@ struct rndis_device { struct netvsc_device *net_dev; enum rndis_device_state state; - u32 link_stat; + bool link_state; atomic_t new_req_id; spinlock_t request_lock; @@ -142,7 +141,11 @@ static void put_rndis_request(struct rndis_device *dev, static void dump_rndis_message(struct hv_device *hv_dev, struct rndis_message *rndis_msg) { - struct net_device *netdev = dev_get_drvdata(&hv_dev->device); + struct net_device *netdev; + struct netvsc_device *net_device; + + net_device = hv_get_drvdata(hv_dev); + netdev = net_device->ndev; switch (rndis_msg->ndis_msg_type) { case REMOTE_NDIS_PACKET_MSG: @@ -250,6 +253,9 @@ static void rndis_filter_receive_response(struct rndis_device *dev, struct rndis_request *request = NULL; bool found = false; unsigned long flags; + struct net_device *ndev; + + ndev = dev->net_dev->ndev; spin_lock_irqsave(&dev->request_lock, flags); list_for_each_entry(request, &dev->req_list, list_ent) { @@ -270,7 +276,7 @@ static void rndis_filter_receive_response(struct rndis_device *dev, memcpy(&request->response_msg, resp, resp->msg_len); } else { - dev_err(&dev->net_dev->dev->device, + netdev_err(ndev, "rndis response buffer overflow " "detected (size %u max %zu)\n", resp->msg_len, @@ -290,7 +296,7 @@ static void rndis_filter_receive_response(struct rndis_device *dev, complete(&request->wait_event); } else { - dev_err(&dev->net_dev->dev->device, + netdev_err(ndev, "no rndis request found for this response " "(id 0x%x res type 0x%x)\n", resp->msg.init_complete.req_id, @@ -323,6 +329,7 @@ static void rndis_filter_receive_data(struct rndis_device *dev, { struct rndis_packet *rndis_pkt; u32 data_offset; + int i; rndis_pkt = &msg->msg.pkt; @@ -338,6 +345,15 @@ static void rndis_filter_receive_data(struct rndis_device *dev, pkt->page_buf[0].offset += data_offset; pkt->page_buf[0].len -= data_offset; + /* Drop the 0th page, if rndis data go beyond page boundary */ + if (pkt->page_buf[0].offset >= PAGE_SIZE) { + pkt->page_buf[1].offset = pkt->page_buf[0].offset - PAGE_SIZE; + pkt->page_buf[1].len -= pkt->page_buf[1].offset; + pkt->page_buf_cnt--; + for (i = 0; i < pkt->page_buf_cnt; i++) + pkt->page_buf[i] = pkt->page_buf[i+1]; + } + pkt->is_data_pkt = true; netvsc_recv_callback(dev->net_dev->dev, pkt); @@ -346,26 +362,29 @@ static void rndis_filter_receive_data(struct rndis_device *dev, int rndis_filter_receive(struct hv_device *dev, struct hv_netvsc_packet *pkt) { - struct netvsc_device *net_dev = dev->ext; + struct netvsc_device *net_dev = hv_get_drvdata(dev); struct rndis_device *rndis_dev; struct rndis_message rndis_msg; struct rndis_message *rndis_hdr; + struct net_device *ndev; if (!net_dev) return -EINVAL; + ndev = net_dev->ndev; + /* Make sure the rndis device state is initialized */ if (!net_dev->extension) { - dev_err(&dev->device, "got rndis message but no rndis device - " + netdev_err(ndev, "got rndis message but no rndis device - " "dropping this message!\n"); - return -1; + return -ENODEV; } rndis_dev = (struct rndis_device *)net_dev->extension; if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) { - dev_err(&dev->device, "got rndis message but rndis device " + netdev_err(ndev, "got rndis message but rndis device " "uninitialized...dropping this message!\n"); - return -1; + return -ENODEV; } rndis_hdr = (struct rndis_message *)kmap_atomic( @@ -377,7 +396,7 @@ int rndis_filter_receive(struct hv_device *dev, /* Make sure we got a valid rndis message */ if ((rndis_hdr->ndis_msg_type != REMOTE_NDIS_PACKET_MSG) && (rndis_hdr->msg_len > sizeof(struct rndis_message))) { - dev_err(&dev->device, "incoming rndis message buffer overflow " + netdev_err(ndev, "incoming rndis message buffer overflow " "detected (got %u, max %zu)..marking it an error!\n", rndis_hdr->msg_len, sizeof(struct rndis_message)); @@ -410,7 +429,7 @@ int rndis_filter_receive(struct hv_device *dev, rndis_filter_receive_indicate_status(rndis_dev, &rndis_msg); break; default: - dev_err(&dev->device, + netdev_err(ndev, "unhandled rndis message (type %u len %u)\n", rndis_msg.ndis_msg_type, rndis_msg.msg_len); @@ -437,8 +456,8 @@ static int rndis_filter_query_device(struct rndis_device *dev, u32 oid, request = get_rndis_request(dev, REMOTE_NDIS_QUERY_MSG, RNDIS_MESSAGE_SIZE(struct rndis_query_request)); if (!request) { - ret = -1; - goto Cleanup; + ret = -ENOMEM; + goto cleanup; } /* Setup the rndis query */ @@ -450,12 +469,12 @@ static int rndis_filter_query_device(struct rndis_device *dev, u32 oid, ret = rndis_filter_send_request(dev, request); if (ret != 0) - goto Cleanup; + goto cleanup; t = wait_for_completion_timeout(&request->wait_event, 5*HZ); if (t == 0) { ret = -ETIMEDOUT; - goto Cleanup; + goto cleanup; } /* Copy the response back */ @@ -463,7 +482,7 @@ static int rndis_filter_query_device(struct rndis_device *dev, u32 oid, if (query_complete->info_buflen > inresult_size) { ret = -1; - goto Cleanup; + goto cleanup; } memcpy(result, @@ -473,7 +492,7 @@ static int rndis_filter_query_device(struct rndis_device *dev, u32 oid, *result_size = query_complete->info_buflen; -Cleanup: +cleanup: if (request) put_rndis_request(dev, request); @@ -492,10 +511,15 @@ static int rndis_filter_query_device_mac(struct rndis_device *dev) static int rndis_filter_query_device_link_status(struct rndis_device *dev) { u32 size = sizeof(u32); + u32 link_status; + int ret; - return rndis_filter_query_device(dev, + ret = rndis_filter_query_device(dev, RNDIS_OID_GEN_MEDIA_CONNECT_STATUS, - &dev->link_stat, &size); + &link_status, &size); + dev->link_state = (link_status != 0) ? true : false; + + return ret; } static int rndis_filter_set_packet_filter(struct rndis_device *dev, @@ -506,13 +530,16 @@ static int rndis_filter_set_packet_filter(struct rndis_device *dev, struct rndis_set_complete *set_complete; u32 status; int ret, t; + struct net_device *ndev; + + ndev = dev->net_dev->ndev; request = get_rndis_request(dev, REMOTE_NDIS_SET_MSG, RNDIS_MESSAGE_SIZE(struct rndis_set_request) + sizeof(u32)); if (!request) { - ret = -1; - goto Cleanup; + ret = -ENOMEM; + goto cleanup; } /* Setup the rndis set */ @@ -526,30 +553,27 @@ static int rndis_filter_set_packet_filter(struct rndis_device *dev, ret = rndis_filter_send_request(dev, request); if (ret != 0) - goto Cleanup; + goto cleanup; t = wait_for_completion_timeout(&request->wait_event, 5*HZ); if (t == 0) { - ret = -1; - dev_err(&dev->net_dev->dev->device, + netdev_err(ndev, "timeout before we got a set response...\n"); /* * We can't deallocate the request since we may still receive a * send completion for it. */ - goto Exit; + goto exit; } else { - if (ret > 0) - ret = 0; set_complete = &request->response_msg.msg.set_complete; status = set_complete->status; } -Cleanup: +cleanup: if (request) put_rndis_request(dev, request); -Exit: +exit: return ret; } @@ -565,8 +589,8 @@ static int rndis_filter_init_device(struct rndis_device *dev) request = get_rndis_request(dev, REMOTE_NDIS_INITIALIZE_MSG, RNDIS_MESSAGE_SIZE(struct rndis_initialize_request)); if (!request) { - ret = -1; - goto Cleanup; + ret = -ENOMEM; + goto cleanup; } /* Setup the rndis set */ @@ -581,7 +605,7 @@ static int rndis_filter_init_device(struct rndis_device *dev) ret = rndis_filter_send_request(dev, request); if (ret != 0) { dev->state = RNDIS_DEV_UNINITIALIZED; - goto Cleanup; + goto cleanup; } @@ -589,7 +613,7 @@ static int rndis_filter_init_device(struct rndis_device *dev) if (t == 0) { ret = -ETIMEDOUT; - goto Cleanup; + goto cleanup; } init_complete = &request->response_msg.msg.init_complete; @@ -599,10 +623,10 @@ static int rndis_filter_init_device(struct rndis_device *dev) ret = 0; } else { dev->state = RNDIS_DEV_UNINITIALIZED; - ret = -1; + ret = -EINVAL; } -Cleanup: +cleanup: if (request) put_rndis_request(dev, request); @@ -618,7 +642,7 @@ static void rndis_filter_halt_device(struct rndis_device *dev) request = get_rndis_request(dev, REMOTE_NDIS_HALT_MSG, RNDIS_MESSAGE_SIZE(struct rndis_halt_request)); if (!request) - goto Cleanup; + goto cleanup; /* Setup the rndis set */ halt = &request->request_msg.msg.halt_req; @@ -629,7 +653,7 @@ static void rndis_filter_halt_device(struct rndis_device *dev) dev->state = RNDIS_DEV_UNINITIALIZED; -Cleanup: +cleanup: if (request) put_rndis_request(dev, request); return; @@ -670,13 +694,13 @@ int rndis_filter_device_add(struct hv_device *dev, void *additional_info) { int ret; - struct netvsc_device *netDevice; - struct rndis_device *rndisDevice; - struct netvsc_device_info *deviceInfo = additional_info; + struct netvsc_device *net_device; + struct rndis_device *rndis_device; + struct netvsc_device_info *device_info = additional_info; - rndisDevice = get_rndis_device(); - if (!rndisDevice) - return -1; + rndis_device = get_rndis_device(); + if (!rndis_device) + return -ENODEV; /* * Let the inner driver handle this first to create the netvsc channel @@ -685,19 +709,19 @@ int rndis_filter_device_add(struct hv_device *dev, */ ret = netvsc_device_add(dev, additional_info); if (ret != 0) { - kfree(rndisDevice); + kfree(rndis_device); return ret; } /* Initialize the rndis device */ - netDevice = dev->ext; + net_device = hv_get_drvdata(dev); - netDevice->extension = rndisDevice; - rndisDevice->net_dev = netDevice; + net_device->extension = rndis_device; + rndis_device->net_dev = net_device; /* Send the rndis initialization message */ - ret = rndis_filter_init_device(rndisDevice); + ret = rndis_filter_init_device(rndis_device); if (ret != 0) { /* * TODO: If rndis init failed, we will need to shut down the @@ -706,29 +730,29 @@ int rndis_filter_device_add(struct hv_device *dev, } /* Get the mac address */ - ret = rndis_filter_query_device_mac(rndisDevice); + ret = rndis_filter_query_device_mac(rndis_device); if (ret != 0) { /* * TODO: shutdown rndis device and the channel */ } - memcpy(deviceInfo->mac_adr, rndisDevice->hw_mac_adr, ETH_ALEN); + memcpy(device_info->mac_adr, rndis_device->hw_mac_adr, ETH_ALEN); - rndis_filter_query_device_link_status(rndisDevice); + rndis_filter_query_device_link_status(rndis_device); - deviceInfo->link_state = rndisDevice->link_stat; + device_info->link_state = rndis_device->link_state; - dev_info(&dev->device, "Device MAC %pM link state %s", - rndisDevice->hw_mac_adr, - ((deviceInfo->link_state) ? ("down\n") : ("up\n"))); + dev_info(&dev->device, "Device MAC %pM link state %s\n", + rndis_device->hw_mac_adr, + device_info->link_state ? "down" : "up"); return ret; } void rndis_filter_device_remove(struct hv_device *dev) { - struct netvsc_device *net_dev = dev->ext; + struct netvsc_device *net_dev = hv_get_drvdata(dev); struct rndis_device *rndis_dev = net_dev->extension; /* Halt and release the rndis device */ @@ -743,17 +767,17 @@ void rndis_filter_device_remove(struct hv_device *dev) int rndis_filter_open(struct hv_device *dev) { - struct netvsc_device *netDevice = dev->ext; + struct netvsc_device *net_device = hv_get_drvdata(dev); - if (!netDevice) + if (!net_device) return -EINVAL; - return rndis_filter_open_device(netDevice->extension); + return rndis_filter_open_device(net_device->extension); } int rndis_filter_close(struct hv_device *dev) { - struct netvsc_device *netDevice = dev->ext; + struct netvsc_device *netDevice = hv_get_drvdata(dev); if (!netDevice) return -EINVAL; |