~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/net/xen-netback/interface.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Network-device interface management.
 
3
 *
 
4
 * Copyright (c) 2004-2005, Keir Fraser
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU General Public License version 2
 
8
 * as published by the Free Software Foundation; or, when distributed
 
9
 * separately from the Linux kernel or incorporated into other
 
10
 * software packages, subject to the following license:
 
11
 *
 
12
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 
13
 * of this source file (the "Software"), to deal in the Software without
 
14
 * restriction, including without limitation the rights to use, copy, modify,
 
15
 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
 
16
 * and to permit persons to whom the Software is furnished to do so, subject to
 
17
 * the following conditions:
 
18
 *
 
19
 * The above copyright notice and this permission notice shall be included in
 
20
 * all copies or substantial portions of the Software.
 
21
 *
 
22
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
23
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
24
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
25
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
26
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 
27
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 
28
 * IN THE SOFTWARE.
 
29
 */
 
30
 
 
31
#include "common.h"
 
32
 
 
33
#include <linux/ethtool.h>
 
34
#include <linux/rtnetlink.h>
 
35
#include <linux/if_vlan.h>
 
36
 
 
37
#include <xen/events.h>
 
38
#include <asm/xen/hypercall.h>
 
39
 
 
40
#define XENVIF_QUEUE_LENGTH 32
 
41
 
 
42
void xenvif_get(struct xenvif *vif)
 
43
{
 
44
        atomic_inc(&vif->refcnt);
 
45
}
 
46
 
 
47
void xenvif_put(struct xenvif *vif)
 
48
{
 
49
        if (atomic_dec_and_test(&vif->refcnt))
 
50
                wake_up(&vif->waiting_to_free);
 
51
}
 
52
 
 
53
int xenvif_schedulable(struct xenvif *vif)
 
54
{
 
55
        return netif_running(vif->dev) && netif_carrier_ok(vif->dev);
 
56
}
 
57
 
 
58
static int xenvif_rx_schedulable(struct xenvif *vif)
 
59
{
 
60
        return xenvif_schedulable(vif) && !xen_netbk_rx_ring_full(vif);
 
61
}
 
62
 
 
63
static irqreturn_t xenvif_interrupt(int irq, void *dev_id)
 
64
{
 
65
        struct xenvif *vif = dev_id;
 
66
 
 
67
        if (vif->netbk == NULL)
 
68
                return IRQ_NONE;
 
69
 
 
70
        xen_netbk_schedule_xenvif(vif);
 
71
 
 
72
        if (xenvif_rx_schedulable(vif))
 
73
                netif_wake_queue(vif->dev);
 
74
 
 
75
        return IRQ_HANDLED;
 
76
}
 
77
 
 
78
static int xenvif_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
79
{
 
80
        struct xenvif *vif = netdev_priv(dev);
 
81
 
 
82
        BUG_ON(skb->dev != dev);
 
83
 
 
84
        if (vif->netbk == NULL)
 
85
                goto drop;
 
86
 
 
87
        /* Drop the packet if the target domain has no receive buffers. */
 
88
        if (!xenvif_rx_schedulable(vif))
 
89
                goto drop;
 
90
 
 
91
        /* Reserve ring slots for the worst-case number of fragments. */
 
92
        vif->rx_req_cons_peek += xen_netbk_count_skb_slots(vif, skb);
 
93
        xenvif_get(vif);
 
94
 
 
95
        if (vif->can_queue && xen_netbk_must_stop_queue(vif))
 
96
                netif_stop_queue(dev);
 
97
 
 
98
        xen_netbk_queue_tx_skb(vif, skb);
 
99
 
 
100
        return NETDEV_TX_OK;
 
101
 
 
102
 drop:
 
103
        vif->dev->stats.tx_dropped++;
 
104
        dev_kfree_skb(skb);
 
105
        return NETDEV_TX_OK;
 
106
}
 
107
 
 
108
void xenvif_receive_skb(struct xenvif *vif, struct sk_buff *skb)
 
109
{
 
110
        netif_rx_ni(skb);
 
111
}
 
112
 
 
113
void xenvif_notify_tx_completion(struct xenvif *vif)
 
114
{
 
115
        if (netif_queue_stopped(vif->dev) && xenvif_rx_schedulable(vif))
 
116
                netif_wake_queue(vif->dev);
 
117
}
 
118
 
 
119
static struct net_device_stats *xenvif_get_stats(struct net_device *dev)
 
120
{
 
121
        struct xenvif *vif = netdev_priv(dev);
 
122
        return &vif->dev->stats;
 
123
}
 
124
 
 
125
static void xenvif_up(struct xenvif *vif)
 
126
{
 
127
        xen_netbk_add_xenvif(vif);
 
128
        enable_irq(vif->irq);
 
129
        xen_netbk_check_rx_xenvif(vif);
 
130
}
 
131
 
 
132
static void xenvif_down(struct xenvif *vif)
 
133
{
 
134
        disable_irq(vif->irq);
 
135
        xen_netbk_deschedule_xenvif(vif);
 
136
        xen_netbk_remove_xenvif(vif);
 
137
}
 
138
 
 
139
static int xenvif_open(struct net_device *dev)
 
140
{
 
141
        struct xenvif *vif = netdev_priv(dev);
 
142
        if (netif_carrier_ok(dev))
 
143
                xenvif_up(vif);
 
144
        netif_start_queue(dev);
 
145
        return 0;
 
146
}
 
147
 
 
148
static int xenvif_close(struct net_device *dev)
 
149
{
 
150
        struct xenvif *vif = netdev_priv(dev);
 
151
        if (netif_carrier_ok(dev))
 
152
                xenvif_down(vif);
 
153
        netif_stop_queue(dev);
 
154
        return 0;
 
155
}
 
156
 
 
157
static int xenvif_change_mtu(struct net_device *dev, int mtu)
 
158
{
 
159
        struct xenvif *vif = netdev_priv(dev);
 
160
        int max = vif->can_sg ? 65535 - VLAN_ETH_HLEN : ETH_DATA_LEN;
 
161
 
 
162
        if (mtu > max)
 
163
                return -EINVAL;
 
164
        dev->mtu = mtu;
 
165
        return 0;
 
166
}
 
167
 
 
168
static u32 xenvif_fix_features(struct net_device *dev, u32 features)
 
169
{
 
170
        struct xenvif *vif = netdev_priv(dev);
 
171
 
 
172
        if (!vif->can_sg)
 
173
                features &= ~NETIF_F_SG;
 
174
        if (!vif->gso && !vif->gso_prefix)
 
175
                features &= ~NETIF_F_TSO;
 
176
        if (!vif->csum)
 
177
                features &= ~NETIF_F_IP_CSUM;
 
178
 
 
179
        return features;
 
180
}
 
181
 
 
182
static const struct xenvif_stat {
 
183
        char name[ETH_GSTRING_LEN];
 
184
        u16 offset;
 
185
} xenvif_stats[] = {
 
186
        {
 
187
                "rx_gso_checksum_fixup",
 
188
                offsetof(struct xenvif, rx_gso_checksum_fixup)
 
189
        },
 
190
};
 
191
 
 
192
static int xenvif_get_sset_count(struct net_device *dev, int string_set)
 
193
{
 
194
        switch (string_set) {
 
195
        case ETH_SS_STATS:
 
196
                return ARRAY_SIZE(xenvif_stats);
 
197
        default:
 
198
                return -EINVAL;
 
199
        }
 
200
}
 
201
 
 
202
static void xenvif_get_ethtool_stats(struct net_device *dev,
 
203
                                     struct ethtool_stats *stats, u64 * data)
 
204
{
 
205
        void *vif = netdev_priv(dev);
 
206
        int i;
 
207
 
 
208
        for (i = 0; i < ARRAY_SIZE(xenvif_stats); i++)
 
209
                data[i] = *(unsigned long *)(vif + xenvif_stats[i].offset);
 
210
}
 
211
 
 
212
static void xenvif_get_strings(struct net_device *dev, u32 stringset, u8 * data)
 
213
{
 
214
        int i;
 
215
 
 
216
        switch (stringset) {
 
217
        case ETH_SS_STATS:
 
218
                for (i = 0; i < ARRAY_SIZE(xenvif_stats); i++)
 
219
                        memcpy(data + i * ETH_GSTRING_LEN,
 
220
                               xenvif_stats[i].name, ETH_GSTRING_LEN);
 
221
                break;
 
222
        }
 
223
}
 
224
 
 
225
static struct ethtool_ops xenvif_ethtool_ops = {
 
226
        .get_link       = ethtool_op_get_link,
 
227
 
 
228
        .get_sset_count = xenvif_get_sset_count,
 
229
        .get_ethtool_stats = xenvif_get_ethtool_stats,
 
230
        .get_strings = xenvif_get_strings,
 
231
};
 
232
 
 
233
static struct net_device_ops xenvif_netdev_ops = {
 
234
        .ndo_start_xmit = xenvif_start_xmit,
 
235
        .ndo_get_stats  = xenvif_get_stats,
 
236
        .ndo_open       = xenvif_open,
 
237
        .ndo_stop       = xenvif_close,
 
238
        .ndo_change_mtu = xenvif_change_mtu,
 
239
        .ndo_fix_features = xenvif_fix_features,
 
240
};
 
241
 
 
242
struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
 
243
                            unsigned int handle)
 
244
{
 
245
        int err;
 
246
        struct net_device *dev;
 
247
        struct xenvif *vif;
 
248
        char name[IFNAMSIZ] = {};
 
249
 
 
250
        snprintf(name, IFNAMSIZ - 1, "vif%u.%u", domid, handle);
 
251
        dev = alloc_netdev(sizeof(struct xenvif), name, ether_setup);
 
252
        if (dev == NULL) {
 
253
                pr_warn("Could not allocate netdev\n");
 
254
                return ERR_PTR(-ENOMEM);
 
255
        }
 
256
 
 
257
        SET_NETDEV_DEV(dev, parent);
 
258
 
 
259
        vif = netdev_priv(dev);
 
260
        vif->domid  = domid;
 
261
        vif->handle = handle;
 
262
        vif->netbk  = NULL;
 
263
        vif->can_sg = 1;
 
264
        vif->csum = 1;
 
265
        atomic_set(&vif->refcnt, 1);
 
266
        init_waitqueue_head(&vif->waiting_to_free);
 
267
        vif->dev = dev;
 
268
        INIT_LIST_HEAD(&vif->schedule_list);
 
269
        INIT_LIST_HEAD(&vif->notify_list);
 
270
 
 
271
        vif->credit_bytes = vif->remaining_credit = ~0UL;
 
272
        vif->credit_usec  = 0UL;
 
273
        init_timer(&vif->credit_timeout);
 
274
        /* Initialize 'expires' now: it's used to track the credit window. */
 
275
        vif->credit_timeout.expires = jiffies;
 
276
 
 
277
        dev->netdev_ops = &xenvif_netdev_ops;
 
278
        dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO;
 
279
        dev->features = dev->hw_features;
 
280
        SET_ETHTOOL_OPS(dev, &xenvif_ethtool_ops);
 
281
 
 
282
        dev->tx_queue_len = XENVIF_QUEUE_LENGTH;
 
283
 
 
284
        /*
 
285
         * Initialise a dummy MAC address. We choose the numerically
 
286
         * largest non-broadcast address to prevent the address getting
 
287
         * stolen by an Ethernet bridge for STP purposes.
 
288
         * (FE:FF:FF:FF:FF:FF)
 
289
         */
 
290
        memset(dev->dev_addr, 0xFF, ETH_ALEN);
 
291
        dev->dev_addr[0] &= ~0x01;
 
292
 
 
293
        netif_carrier_off(dev);
 
294
 
 
295
        err = register_netdev(dev);
 
296
        if (err) {
 
297
                netdev_warn(dev, "Could not register device: err=%d\n", err);
 
298
                free_netdev(dev);
 
299
                return ERR_PTR(err);
 
300
        }
 
301
 
 
302
        netdev_dbg(dev, "Successfully created xenvif\n");
 
303
        return vif;
 
304
}
 
305
 
 
306
int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref,
 
307
                   unsigned long rx_ring_ref, unsigned int evtchn)
 
308
{
 
309
        int err = -ENOMEM;
 
310
 
 
311
        /* Already connected through? */
 
312
        if (vif->irq)
 
313
                return 0;
 
314
 
 
315
        err = xen_netbk_map_frontend_rings(vif, tx_ring_ref, rx_ring_ref);
 
316
        if (err < 0)
 
317
                goto err;
 
318
 
 
319
        err = bind_interdomain_evtchn_to_irqhandler(
 
320
                vif->domid, evtchn, xenvif_interrupt, 0,
 
321
                vif->dev->name, vif);
 
322
        if (err < 0)
 
323
                goto err_unmap;
 
324
        vif->irq = err;
 
325
        disable_irq(vif->irq);
 
326
 
 
327
        xenvif_get(vif);
 
328
 
 
329
        rtnl_lock();
 
330
        if (!vif->can_sg && vif->dev->mtu > ETH_DATA_LEN)
 
331
                dev_set_mtu(vif->dev, ETH_DATA_LEN);
 
332
        netdev_update_features(vif->dev);
 
333
        netif_carrier_on(vif->dev);
 
334
        if (netif_running(vif->dev))
 
335
                xenvif_up(vif);
 
336
        rtnl_unlock();
 
337
 
 
338
        return 0;
 
339
err_unmap:
 
340
        xen_netbk_unmap_frontend_rings(vif);
 
341
err:
 
342
        return err;
 
343
}
 
344
 
 
345
void xenvif_disconnect(struct xenvif *vif)
 
346
{
 
347
        struct net_device *dev = vif->dev;
 
348
        if (netif_carrier_ok(dev)) {
 
349
                rtnl_lock();
 
350
                netif_carrier_off(dev); /* discard queued packets */
 
351
                if (netif_running(dev))
 
352
                        xenvif_down(vif);
 
353
                rtnl_unlock();
 
354
                xenvif_put(vif);
 
355
        }
 
356
 
 
357
        atomic_dec(&vif->refcnt);
 
358
        wait_event(vif->waiting_to_free, atomic_read(&vif->refcnt) == 0);
 
359
 
 
360
        del_timer_sync(&vif->credit_timeout);
 
361
 
 
362
        if (vif->irq)
 
363
                unbind_from_irqhandler(vif->irq, vif);
 
364
 
 
365
        unregister_netdev(vif->dev);
 
366
 
 
367
        xen_netbk_unmap_frontend_rings(vif);
 
368
 
 
369
        free_netdev(vif->dev);
 
370
}