Skip to content

Commit

Permalink
Merge branch 'netvsc-bug-fixes-and-cleanups'
Browse files Browse the repository at this point in the history
Stephen Hemminger says:

====================
netvsc: bug fixes and cleanups

These fix NAPI issues and bugs found during testing of shutdown
testing.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Mar 23, 2017
2 parents 6069f3f + ce12b81 commit 4deece6
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 156 deletions.
12 changes: 6 additions & 6 deletions drivers/net/hyperv/hyperv_net.h
Original file line number Diff line number Diff line change
Expand Up @@ -686,7 +686,7 @@ struct net_device_context {
/* point back to our device context */
struct hv_device *device_ctx;
/* netvsc_device */
struct netvsc_device *nvdev;
struct netvsc_device __rcu *nvdev;
/* reconfigure work */
struct delayed_work dwork;
/* last reconfig time */
Expand All @@ -708,9 +708,6 @@ struct net_device_context {
u32 speed;
struct netvsc_ethtool_stats eth_stats;

/* the device is going away */
bool start_remove;

/* State to manage the associated VF interface. */
struct net_device __rcu *vf_netdev;

Expand All @@ -723,6 +720,7 @@ struct net_device_context {
/* Per channel data */
struct netvsc_channel {
struct vmbus_channel *channel;
const struct vmpacket_descriptor *desc;
struct napi_struct napi;
struct multi_send_data msd;
struct multi_recv_comp mrc;
Expand Down Expand Up @@ -763,8 +761,8 @@ struct netvsc_device {

u32 max_chn;
u32 num_chn;
spinlock_t sc_lock; /* Protects num_sc_offered variable */
u32 num_sc_offered;

refcount_t sc_offered;

/* Holds rndis device info */
void *extension;
Expand All @@ -779,6 +777,8 @@ struct netvsc_device {
atomic_t open_cnt;

struct netvsc_channel chan_table[VRSS_CHANNEL_MAX];

struct rcu_head rcu;
};

static inline struct netvsc_device *
Expand Down
70 changes: 32 additions & 38 deletions drivers/net/hyperv/netvsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,10 @@ static struct netvsc_device *alloc_net_device(void)
return net_device;
}

static void free_netvsc_device(struct netvsc_device *nvdev)
static void free_netvsc_device(struct rcu_head *head)
{
struct netvsc_device *nvdev
= container_of(head, struct netvsc_device, rcu);
int i;

for (i = 0; i < VRSS_CHANNEL_MAX; i++)
Expand All @@ -90,6 +92,10 @@ static void free_netvsc_device(struct netvsc_device *nvdev)
kfree(nvdev);
}

static void free_netvsc_device_rcu(struct netvsc_device *nvdev)
{
call_rcu(&nvdev->rcu, free_netvsc_device);
}

static struct netvsc_device *get_outbound_net_device(struct hv_device *device)
{
Expand Down Expand Up @@ -551,7 +557,7 @@ void netvsc_device_remove(struct hv_device *device)

netvsc_disconnect_vsp(device);

net_device_ctx->nvdev = NULL;
RCU_INIT_POINTER(net_device_ctx->nvdev, NULL);

/*
* At this point, no one should be accessing net_device
Expand All @@ -566,7 +572,7 @@ void netvsc_device_remove(struct hv_device *device)
napi_disable(&net_device->chan_table[i].napi);

/* Release all resources */
free_netvsc_device(net_device);
free_netvsc_device_rcu(net_device);
}

#define RING_AVAIL_PERCENT_HIWATER 20
Expand Down Expand Up @@ -599,7 +605,6 @@ static void netvsc_send_tx_complete(struct netvsc_device *net_device,
{
struct sk_buff *skb = (struct sk_buff *)(unsigned long)desc->trans_id;
struct net_device *ndev = hv_get_drvdata(device);
struct net_device_context *net_device_ctx = netdev_priv(ndev);
struct vmbus_channel *channel = device->channel;
u16 q_idx = 0;
int queue_sends;
Expand Down Expand Up @@ -633,7 +638,6 @@ static void netvsc_send_tx_complete(struct netvsc_device *net_device,
wake_up(&net_device->wait_drain);

if (netif_tx_queue_stopped(netdev_get_tx_queue(ndev, q_idx)) &&
!net_device_ctx->start_remove &&
(hv_ringbuf_avail_percent(&channel->outbound) > RING_AVAIL_PERCENT_HIWATER ||
queue_sends < 1))
netif_tx_wake_queue(netdev_get_tx_queue(ndev, q_idx));
Expand Down Expand Up @@ -702,8 +706,7 @@ static u32 netvsc_copy_to_send_buf(struct netvsc_device *net_device,
packet->page_buf_cnt;

/* Add padding */
if (skb && skb->xmit_more && remain &&
!packet->cp_partial) {
if (skb->xmit_more && remain && !packet->cp_partial) {
padding = net_device->pkt_align - remain;
rndis_msg->msg_len += padding;
packet->total_data_buflen += padding;
Expand Down Expand Up @@ -861,9 +864,7 @@ int netvsc_send(struct hv_device *device,
if (msdp->pkt)
msd_len = msdp->pkt->total_data_buflen;

try_batch = (skb != NULL) && msd_len > 0 && msdp->count <
net_device->max_pkt;

try_batch = msd_len > 0 && msdp->count < net_device->max_pkt;
if (try_batch && msd_len + pktlen + net_device->pkt_align <
net_device->send_section_size) {
section_index = msdp->pkt->send_buf_index;
Expand All @@ -873,7 +874,7 @@ int netvsc_send(struct hv_device *device,
section_index = msdp->pkt->send_buf_index;
packet->cp_partial = true;

} else if ((skb != NULL) && pktlen + net_device->pkt_align <
} else if (pktlen + net_device->pkt_align <
net_device->send_section_size) {
section_index = netvsc_get_next_send_section(net_device);
if (section_index != NETVSC_INVALID_INDEX) {
Expand Down Expand Up @@ -1173,7 +1174,6 @@ static int netvsc_process_raw_pkt(struct hv_device *device,
struct vmbus_channel *channel,
struct netvsc_device *net_device,
struct net_device *ndev,
u64 request_id,
const struct vmpacket_descriptor *desc)
{
struct net_device_context *net_device_ctx = netdev_priv(ndev);
Expand All @@ -1195,7 +1195,7 @@ static int netvsc_process_raw_pkt(struct hv_device *device,

default:
netdev_err(ndev, "unhandled packet type %d, tid %llx\n",
desc->type, request_id);
desc->type, desc->trans_id);
break;
}

Expand All @@ -1222,28 +1222,20 @@ int netvsc_poll(struct napi_struct *napi, int budget)
u16 q_idx = channel->offermsg.offer.sub_channel_index;
struct net_device *ndev = hv_get_drvdata(device);
struct netvsc_device *net_device = net_device_to_netvsc_device(ndev);
const struct vmpacket_descriptor *desc;
int work_done = 0;

desc = hv_pkt_iter_first(channel);
while (desc) {
int count;

count = netvsc_process_raw_pkt(device, channel, net_device,
ndev, desc->trans_id, desc);
work_done += count;
desc = __hv_pkt_iter_next(channel, desc);
/* If starting a new interval */
if (!nvchan->desc)
nvchan->desc = hv_pkt_iter_first(channel);

/* If receive packet budget is exhausted, reschedule */
if (work_done >= budget) {
work_done = budget;
break;
}
while (nvchan->desc && work_done < budget) {
work_done += netvsc_process_raw_pkt(device, channel, net_device,
ndev, nvchan->desc);
nvchan->desc = hv_pkt_iter_next(channel, nvchan->desc);
}
hv_pkt_iter_close(channel);

/* If budget was not exhausted and
* not doing busy poll
/* If receive ring was exhausted
* and not doing busy poll
* then re-enable host interrupts
* and reschedule if ring is not empty.
*/
Expand All @@ -1253,7 +1245,9 @@ int netvsc_poll(struct napi_struct *napi, int budget)
napi_reschedule(napi);

netvsc_chk_recv_comp(net_device, channel, q_idx);
return work_done;

/* Driver may overshoot since multiple packets per descriptor */
return min(work_done, budget);
}

/* Call back when data is available in host ring buffer.
Expand All @@ -1263,10 +1257,12 @@ void netvsc_channel_cb(void *context)
{
struct netvsc_channel *nvchan = context;

/* disable interupts from host */
hv_begin_read(&nvchan->channel->inbound);
if (napi_schedule_prep(&nvchan->napi)) {
/* disable interupts from host */
hv_begin_read(&nvchan->channel->inbound);

napi_schedule(&nvchan->napi);
__napi_schedule(&nvchan->napi);
}
}

/*
Expand Down Expand Up @@ -1325,9 +1321,7 @@ int netvsc_device_add(struct hv_device *device,
/* Writing nvdev pointer unlocks netvsc_send(), make sure chn_table is
* populated.
*/
wmb();

net_device_ctx->nvdev = net_device;
rcu_assign_pointer(net_device_ctx->nvdev, net_device);

/* Connect with the NetVsp */
ret = netvsc_connect_vsp(device);
Expand All @@ -1346,7 +1340,7 @@ int netvsc_device_add(struct hv_device *device,
vmbus_close(device->channel);

cleanup:
free_netvsc_device(net_device);
free_netvsc_device(&net_device->rcu);

return ret;
}
Loading

0 comments on commit 4deece6

Please sign in to comment.