diff options
Diffstat (limited to 'drivers/staging/hv/rndis_filter.c')
-rw-r--r-- | drivers/staging/hv/rndis_filter.c | 189 |
1 files changed, 55 insertions, 134 deletions
diff --git a/drivers/staging/hv/rndis_filter.c b/drivers/staging/hv/rndis_filter.c index e7189cd324ca..60ebdb1b6082 100644 --- a/drivers/staging/hv/rndis_filter.c +++ b/drivers/staging/hv/rndis_filter.c @@ -25,17 +25,11 @@ #include <linux/slab.h> #include <linux/io.h> #include <linux/if_ether.h> +#include <linux/netdevice.h> -#include "logging.h" -#include "hv_api.h" -#include "netvsc_api.h" -#include "rndis_filter.h" +#include "hyperv.h" +#include "hyperv_net.h" -/* Data types */ -struct rndis_filter_driver_object { - /* The original driver */ - struct netvsc_driver inner_drv; -}; enum rndis_device_state { RNDIS_DEV_UNINITIALIZED = 0, @@ -59,8 +53,7 @@ struct rndis_device { struct rndis_request { struct list_head list_ent; - int wait_condition; - wait_queue_head_t wait_event; + struct completion wait_event; /* * FIXME: We assumed a fixed size response here. If we do ever need to @@ -76,31 +69,11 @@ struct rndis_request { struct rndis_message request_msg; }; - -struct rndis_filter_packet { - void *completion_ctx; - void (*completion)(void *context); - struct rndis_message msg; -}; - - -static int rndis_filte_device_add(struct hv_device *dev, - void *additional_info); - -static int rndis_filter_device_remove(struct hv_device *dev); - -static void rndis_filter_cleanup(struct hv_driver *drv); - -static int rndis_filter_send(struct hv_device *dev, - struct hv_netvsc_packet *pkt); - static void rndis_filter_send_completion(void *ctx); static void rndis_filter_send_request_completion(void *ctx); -/* The one and only */ -static struct rndis_filter_driver_object rndis_filter; static struct rndis_device *get_rndis_device(void) { @@ -132,7 +105,7 @@ static struct rndis_request *get_rndis_request(struct rndis_device *dev, if (!request) return NULL; - init_waitqueue_head(&request->wait_event); + init_completion(&request->wait_event); rndis_msg = &request->request_msg; rndis_msg->ndis_msg_type = msg_type; @@ -264,7 +237,7 @@ static int rndis_filter_send_request(struct rndis_device *dev, rndis_filter_send_request_completion; packet->completion.send.send_completion_tid = (unsigned long)dev; - ret = rndis_filter.inner_drv.send(dev->net_dev->dev, packet); + ret = netvsc_send(dev->net_dev->dev, packet); return ret; } @@ -283,14 +256,6 @@ static void rndis_filter_receive_response(struct rndis_device *dev, */ if (request->request_msg.msg.init_req.req_id == resp->msg.init_complete.req_id) { - DPRINT_DBG(NETVSC, "found rndis request for " - "this response (id 0x%x req type 0x%x res " - "type 0x%x)", - request->request_msg.msg. - init_req.req_id, - request->request_msg.ndis_msg_type, - resp->ndis_msg_type); - found = true; break; } @@ -302,10 +267,11 @@ static void rndis_filter_receive_response(struct rndis_device *dev, memcpy(&request->response_msg, resp, resp->msg_len); } else { - DPRINT_ERR(NETVSC, "rndis response buffer overflow " - "detected (size %u max %zu)", - resp->msg_len, - sizeof(struct rndis_filter_packet)); + dev_err(&dev->net_dev->dev->device, + "rndis response buffer overflow " + "detected (size %u max %zu)\n", + resp->msg_len, + sizeof(struct rndis_filter_packet)); if (resp->ndis_msg_type == REMOTE_NDIS_RESET_CMPLT) { @@ -319,13 +285,13 @@ static void rndis_filter_receive_response(struct rndis_device *dev, } } - request->wait_condition = 1; - wake_up(&request->wait_event); + complete(&request->wait_event); } else { - DPRINT_ERR(NETVSC, "no rndis request found for this response " - "(id 0x%x res type 0x%x)", - resp->msg.init_complete.req_id, - resp->ndis_msg_type); + dev_err(&dev->net_dev->dev->device, + "no rndis request found for this response " + "(id 0x%x res type 0x%x)\n", + resp->msg.init_complete.req_id, + resp->ndis_msg_type); } } @@ -336,10 +302,10 @@ static void rndis_filter_receive_indicate_status(struct rndis_device *dev, &resp->msg.indicate_status; if (indicate->status == RNDIS_STATUS_MEDIA_CONNECT) { - rndis_filter.inner_drv.link_status_change( + netvsc_linkstatus_callback( dev->net_dev->dev, 1); } else if (indicate->status == RNDIS_STATUS_MEDIA_DISCONNECT) { - rndis_filter.inner_drv.link_status_change( + netvsc_linkstatus_callback( dev->net_dev->dev, 0); } else { /* @@ -371,11 +337,10 @@ static void rndis_filter_receive_data(struct rndis_device *dev, pkt->is_data_pkt = true; - rndis_filter.inner_drv.recv_cb(dev->net_dev->dev, - pkt); + netvsc_recv_callback(dev->net_dev->dev, pkt); } -static int rndis_filter_receive(struct hv_device *dev, +int rndis_filter_receive(struct hv_device *dev, struct hv_netvsc_packet *pkt) { struct netvsc_device *net_dev = dev->ext; @@ -388,15 +353,15 @@ static int rndis_filter_receive(struct hv_device *dev, /* Make sure the rndis device state is initialized */ if (!net_dev->extension) { - DPRINT_ERR(NETVSC, "got rndis message but no rndis device..." - "dropping this message!"); + dev_err(&dev->device, "got rndis message but no rndis device - " + "dropping this message!\n"); return -1; } rndis_dev = (struct rndis_device *)net_dev->extension; if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) { - DPRINT_ERR(NETVSC, "got rndis message but rndis device " - "uninitialized...dropping this message!"); + dev_err(&dev->device, "got rndis message but rndis device " + "uninitialized...dropping this message!\n"); return -1; } @@ -417,8 +382,8 @@ static int rndis_filter_receive(struct hv_device *dev, kunmap_atomic(rndis_hdr - pkt->page_buf[0].offset, KM_IRQ0); - DPRINT_ERR(NETVSC, "invalid rndis message? (expected %u " - "bytes got %u)...dropping this message!", + dev_err(&dev->device, "invalid rndis message? (expected %u " + "bytes got %u)...dropping this message!\n", rndis_hdr->msg_len, pkt->total_data_buflen); return -1; @@ -427,8 +392,8 @@ static int rndis_filter_receive(struct hv_device *dev, if ((rndis_hdr->ndis_msg_type != REMOTE_NDIS_PACKET_MSG) && (rndis_hdr->msg_len > sizeof(struct rndis_message))) { - DPRINT_ERR(NETVSC, "incoming rndis message buffer overflow " - "detected (got %u, max %zu)...marking it an error!", + dev_err(&dev->device, "incoming rndis message buffer overflow " + "detected (got %u, max %zu)..marking it an error!\n", rndis_hdr->msg_len, sizeof(struct rndis_message)); } @@ -460,7 +425,8 @@ static int rndis_filter_receive(struct hv_device *dev, rndis_filter_receive_indicate_status(rndis_dev, &rndis_msg); break; default: - DPRINT_ERR(NETVSC, "unhandled rndis message (type %u len %u)", + dev_err(&dev->device, + "unhandled rndis message (type %u len %u)\n", rndis_msg.ndis_msg_type, rndis_msg.msg_len); break; @@ -477,6 +443,7 @@ static int rndis_filter_query_device(struct rndis_device *dev, u32 oid, struct rndis_query_request *query; struct rndis_query_complete *query_complete; int ret = 0; + int t; if (!result) return -EINVAL; @@ -496,14 +463,12 @@ static int rndis_filter_query_device(struct rndis_device *dev, u32 oid, query->info_buflen = 0; query->dev_vc_handle = 0; - request->wait_condition = 0; ret = rndis_filter_send_request(dev, request); if (ret != 0) goto Cleanup; - wait_event_timeout(request->wait_event, request->wait_condition, - msecs_to_jiffies(1000)); - if (request->wait_condition == 0) { + t = wait_for_completion_timeout(&request->wait_event, HZ); + if (t == 0) { ret = -ETIMEDOUT; goto Cleanup; } @@ -555,7 +520,7 @@ static int rndis_filter_set_packet_filter(struct rndis_device *dev, struct rndis_set_request *set; struct rndis_set_complete *set_complete; u32 status; - int ret; + int ret, t; request = get_rndis_request(dev, REMOTE_NDIS_SET_MSG, RNDIS_MESSAGE_SIZE(struct rndis_set_request) + @@ -574,18 +539,18 @@ static int rndis_filter_set_packet_filter(struct rndis_device *dev, memcpy((void *)(unsigned long)set + sizeof(struct rndis_set_request), &new_filter, sizeof(u32)); - request->wait_condition = 0; ret = rndis_filter_send_request(dev, request); if (ret != 0) goto Cleanup; - wait_event_timeout(request->wait_event, request->wait_condition, - msecs_to_jiffies(2000)); - if (request->wait_condition == 0) { + t = wait_for_completion_timeout(&request->wait_event, HZ); + + if (t == 0) { ret = -1; - DPRINT_ERR(NETVSC, "timeout before we got a set response..."); + dev_err(&dev->net_dev->dev->device, + "timeout before we got a set response...\n"); /* - * We cant deallocate the request since we may still receive a + * We can't deallocate the request since we may still receive a * send completion for it. */ goto Exit; @@ -603,42 +568,6 @@ Exit: return ret; } -int rndis_filter_init(struct netvsc_driver *drv) -{ - DPRINT_DBG(NETVSC, "sizeof(struct rndis_filter_packet) == %zd", - sizeof(struct rndis_filter_packet)); - - drv->req_ext_size = sizeof(struct rndis_filter_packet); - - /* Driver->Context = rndisDriver; */ - - memset(&rndis_filter, 0, sizeof(struct rndis_filter_driver_object)); - - /*rndisDriver->Driver = Driver; - - ASSERT(Driver->OnLinkStatusChanged); - rndisDriver->OnLinkStatusChanged = Driver->OnLinkStatusChanged;*/ - - /* Save the original dispatch handlers before we override it */ - rndis_filter.inner_drv.base.dev_add = drv->base.dev_add; - rndis_filter.inner_drv.base.dev_rm = - drv->base.dev_rm; - rndis_filter.inner_drv.base.cleanup = drv->base.cleanup; - - rndis_filter.inner_drv.send = drv->send; - rndis_filter.inner_drv.recv_cb = drv->recv_cb; - rndis_filter.inner_drv.link_status_change = - drv->link_status_change; - - /* Override */ - drv->base.dev_add = rndis_filte_device_add; - drv->base.dev_rm = rndis_filter_device_remove; - drv->base.cleanup = rndis_filter_cleanup; - drv->send = rndis_filter_send; - drv->recv_cb = rndis_filter_receive; - - return 0; -} static int rndis_filter_init_device(struct rndis_device *dev) { @@ -646,7 +575,7 @@ static int rndis_filter_init_device(struct rndis_device *dev) struct rndis_initialize_request *init; struct rndis_initialize_complete *init_complete; u32 status; - int ret; + int ret, t; request = get_rndis_request(dev, REMOTE_NDIS_INITIALIZE_MSG, RNDIS_MESSAGE_SIZE(struct rndis_initialize_request)); @@ -664,7 +593,6 @@ static int rndis_filter_init_device(struct rndis_device *dev) dev->state = RNDIS_DEV_INITIALIZING; - request->wait_condition = 0; ret = rndis_filter_send_request(dev, request); if (ret != 0) { dev->state = RNDIS_DEV_UNINITIALIZED; @@ -672,9 +600,9 @@ static int rndis_filter_init_device(struct rndis_device *dev) } - wait_event_timeout(request->wait_event, request->wait_condition, - msecs_to_jiffies(1000)); - if (request->wait_condition == 0) { + t = wait_for_completion_timeout(&request->wait_event, HZ); + + if (t == 0) { ret = -ETIMEDOUT; goto Cleanup; } @@ -753,7 +681,7 @@ static int rndis_filter_close_device(struct rndis_device *dev) return ret; } -static int rndis_filte_device_add(struct hv_device *dev, +int rndis_filte_device_add(struct hv_device *dev, void *additional_info) { int ret; @@ -765,14 +693,12 @@ static int rndis_filte_device_add(struct hv_device *dev, if (!rndisDevice) return -1; - DPRINT_DBG(NETVSC, "rndis device object allocated - %p", rndisDevice); - /* * Let the inner driver handle this first to create the netvsc channel * NOTE! Once the channel is created, we may get a receive callback * (RndisFilterOnReceive()) before this call is completed */ - ret = rndis_filter.inner_drv.base.dev_add(dev, additional_info); + ret = netvsc_device_add(dev, additional_info); if (ret != 0) { kfree(rndisDevice); return ret; @@ -802,21 +728,20 @@ static int rndis_filte_device_add(struct hv_device *dev, */ } - DPRINT_INFO(NETVSC, "Device 0x%p mac addr %pM", - rndisDevice, rndisDevice->hw_mac_adr); - memcpy(deviceInfo->mac_adr, rndisDevice->hw_mac_adr, ETH_ALEN); rndis_filter_query_device_link_status(rndisDevice); deviceInfo->link_state = rndisDevice->link_stat; - DPRINT_INFO(NETVSC, "Device 0x%p link state %s", rndisDevice, - ((deviceInfo->link_state) ? ("down") : ("up"))); + + dev_info(&dev->device, "Device MAC %pM link state %s", + rndisDevice->hw_mac_adr, + ((deviceInfo->link_state) ? ("down\n") : ("up\n"))); return ret; } -static int rndis_filter_device_remove(struct hv_device *dev) +int rndis_filter_device_remove(struct hv_device *dev) { struct netvsc_device *net_dev = dev->ext; struct rndis_device *rndis_dev = net_dev->extension; @@ -827,15 +752,11 @@ static int rndis_filter_device_remove(struct hv_device *dev) kfree(rndis_dev); net_dev->extension = NULL; - /* Pass control to inner driver to remove the device */ - rndis_filter.inner_drv.base.dev_rm(dev); + netvsc_device_remove(dev); return 0; } -static void rndis_filter_cleanup(struct hv_driver *drv) -{ -} int rndis_filter_open(struct hv_device *dev) { @@ -857,7 +778,7 @@ int rndis_filter_close(struct hv_device *dev) return rndis_filter_close_device(netDevice->extension); } -static int rndis_filter_send(struct hv_device *dev, +int rndis_filter_send(struct hv_device *dev, struct hv_netvsc_packet *pkt) { int ret; @@ -897,7 +818,7 @@ static int rndis_filter_send(struct hv_device *dev, pkt->completion.send.send_completion = rndis_filter_send_completion; pkt->completion.send.send_completion_ctx = filterPacket; - ret = rndis_filter.inner_drv.send(dev, pkt); + ret = netvsc_send(dev, pkt); if (ret != 0) { /* * Reset the completion to originals to allow retries from |