aboutsummaryrefslogtreecommitdiff
path: root/drivers/staging/hv/rndis_filter.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/hv/rndis_filter.c')
-rw-r--r--drivers/staging/hv/rndis_filter.c146
1 files changed, 85 insertions, 61 deletions
diff --git a/drivers/staging/hv/rndis_filter.c b/drivers/staging/hv/rndis_filter.c
index dbb520199756..bafccb360041 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;