diff options
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/Makefile | 1 | ||||
-rw-r--r-- | net/core/dev.c | 185 | ||||
-rw-r--r-- | net/core/dev_mcast.c | 28 | ||||
-rw-r--r-- | net/core/ethtool.c | 9 | ||||
-rw-r--r-- | net/core/netpoll.c | 9 | ||||
-rw-r--r-- | net/core/pktgen.c | 4 | ||||
-rw-r--r-- | net/core/skbuff.c | 10 | ||||
-rw-r--r-- | net/core/sock.c | 6 | ||||
-rw-r--r-- | net/core/user_dma.c | 131 |
9 files changed, 278 insertions, 105 deletions
diff --git a/net/core/Makefile b/net/core/Makefile index 79fe12cced27..e9bd2467d5a9 100644 --- a/net/core/Makefile +++ b/net/core/Makefile | |||
@@ -16,3 +16,4 @@ obj-$(CONFIG_NET_DIVERT) += dv.o | |||
16 | obj-$(CONFIG_NET_PKTGEN) += pktgen.o | 16 | obj-$(CONFIG_NET_PKTGEN) += pktgen.o |
17 | obj-$(CONFIG_WIRELESS_EXT) += wireless.o | 17 | obj-$(CONFIG_WIRELESS_EXT) += wireless.o |
18 | obj-$(CONFIG_NETPOLL) += netpoll.o | 18 | obj-$(CONFIG_NETPOLL) += netpoll.o |
19 | obj-$(CONFIG_NET_DMA) += user_dma.o | ||
diff --git a/net/core/dev.c b/net/core/dev.c index 4fba549caf29..ab39fe17cb58 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -115,6 +115,7 @@ | |||
115 | #include <net/iw_handler.h> | 115 | #include <net/iw_handler.h> |
116 | #include <asm/current.h> | 116 | #include <asm/current.h> |
117 | #include <linux/audit.h> | 117 | #include <linux/audit.h> |
118 | #include <linux/dmaengine.h> | ||
118 | 119 | ||
119 | /* | 120 | /* |
120 | * The list of packet types we will receive (as opposed to discard) | 121 | * The list of packet types we will receive (as opposed to discard) |
@@ -148,6 +149,12 @@ static DEFINE_SPINLOCK(ptype_lock); | |||
148 | static struct list_head ptype_base[16]; /* 16 way hashed list */ | 149 | static struct list_head ptype_base[16]; /* 16 way hashed list */ |
149 | static struct list_head ptype_all; /* Taps */ | 150 | static struct list_head ptype_all; /* Taps */ |
150 | 151 | ||
152 | #ifdef CONFIG_NET_DMA | ||
153 | static struct dma_client *net_dma_client; | ||
154 | static unsigned int net_dma_count; | ||
155 | static spinlock_t net_dma_event_lock; | ||
156 | #endif | ||
157 | |||
151 | /* | 158 | /* |
152 | * The @dev_base list is protected by @dev_base_lock and the rtnl | 159 | * The @dev_base list is protected by @dev_base_lock and the rtnl |
153 | * semaphore. | 160 | * semaphore. |
@@ -1215,75 +1222,15 @@ static inline int illegal_highdma(struct net_device *dev, struct sk_buff *skb) | |||
1215 | #define illegal_highdma(dev, skb) (0) | 1222 | #define illegal_highdma(dev, skb) (0) |
1216 | #endif | 1223 | #endif |
1217 | 1224 | ||
1218 | /* Keep head the same: replace data */ | ||
1219 | int __skb_linearize(struct sk_buff *skb, gfp_t gfp_mask) | ||
1220 | { | ||
1221 | unsigned int size; | ||
1222 | u8 *data; | ||
1223 | long offset; | ||
1224 | struct skb_shared_info *ninfo; | ||
1225 | int headerlen = skb->data - skb->head; | ||
1226 | int expand = (skb->tail + skb->data_len) - skb->end; | ||
1227 | |||
1228 | if (skb_shared(skb)) | ||
1229 | BUG(); | ||
1230 | |||
1231 | if (expand <= 0) | ||
1232 | expand = 0; | ||
1233 | |||
1234 | size = skb->end - skb->head + expand; | ||
1235 | size = SKB_DATA_ALIGN(size); | ||
1236 | data = kmalloc(size + sizeof(struct skb_shared_info), gfp_mask); | ||
1237 | if (!data) | ||
1238 | return -ENOMEM; | ||
1239 | |||
1240 | /* Copy entire thing */ | ||
1241 | if (skb_copy_bits(skb, -headerlen, data, headerlen + skb->len)) | ||
1242 | BUG(); | ||
1243 | |||
1244 | /* Set up shinfo */ | ||
1245 | ninfo = (struct skb_shared_info*)(data + size); | ||
1246 | atomic_set(&ninfo->dataref, 1); | ||
1247 | ninfo->tso_size = skb_shinfo(skb)->tso_size; | ||
1248 | ninfo->tso_segs = skb_shinfo(skb)->tso_segs; | ||
1249 | ninfo->nr_frags = 0; | ||
1250 | ninfo->frag_list = NULL; | ||
1251 | |||
1252 | /* Offset between the two in bytes */ | ||
1253 | offset = data - skb->head; | ||
1254 | |||
1255 | /* Free old data. */ | ||
1256 | skb_release_data(skb); | ||
1257 | |||
1258 | skb->head = data; | ||
1259 | skb->end = data + size; | ||
1260 | |||
1261 | /* Set up new pointers */ | ||
1262 | skb->h.raw += offset; | ||
1263 | skb->nh.raw += offset; | ||
1264 | skb->mac.raw += offset; | ||
1265 | skb->tail += offset; | ||
1266 | skb->data += offset; | ||
1267 | |||
1268 | /* We are no longer a clone, even if we were. */ | ||
1269 | skb->cloned = 0; | ||
1270 | |||
1271 | skb->tail += skb->data_len; | ||
1272 | skb->data_len = 0; | ||
1273 | return 0; | ||
1274 | } | ||
1275 | |||
1276 | #define HARD_TX_LOCK(dev, cpu) { \ | 1225 | #define HARD_TX_LOCK(dev, cpu) { \ |
1277 | if ((dev->features & NETIF_F_LLTX) == 0) { \ | 1226 | if ((dev->features & NETIF_F_LLTX) == 0) { \ |
1278 | spin_lock(&dev->xmit_lock); \ | 1227 | netif_tx_lock(dev); \ |
1279 | dev->xmit_lock_owner = cpu; \ | ||
1280 | } \ | 1228 | } \ |
1281 | } | 1229 | } |
1282 | 1230 | ||
1283 | #define HARD_TX_UNLOCK(dev) { \ | 1231 | #define HARD_TX_UNLOCK(dev) { \ |
1284 | if ((dev->features & NETIF_F_LLTX) == 0) { \ | 1232 | if ((dev->features & NETIF_F_LLTX) == 0) { \ |
1285 | dev->xmit_lock_owner = -1; \ | 1233 | netif_tx_unlock(dev); \ |
1286 | spin_unlock(&dev->xmit_lock); \ | ||
1287 | } \ | 1234 | } \ |
1288 | } | 1235 | } |
1289 | 1236 | ||
@@ -1321,7 +1268,7 @@ int dev_queue_xmit(struct sk_buff *skb) | |||
1321 | 1268 | ||
1322 | if (skb_shinfo(skb)->frag_list && | 1269 | if (skb_shinfo(skb)->frag_list && |
1323 | !(dev->features & NETIF_F_FRAGLIST) && | 1270 | !(dev->features & NETIF_F_FRAGLIST) && |
1324 | __skb_linearize(skb, GFP_ATOMIC)) | 1271 | __skb_linearize(skb)) |
1325 | goto out_kfree_skb; | 1272 | goto out_kfree_skb; |
1326 | 1273 | ||
1327 | /* Fragmented skb is linearized if device does not support SG, | 1274 | /* Fragmented skb is linearized if device does not support SG, |
@@ -1330,14 +1277,14 @@ int dev_queue_xmit(struct sk_buff *skb) | |||
1330 | */ | 1277 | */ |
1331 | if (skb_shinfo(skb)->nr_frags && | 1278 | if (skb_shinfo(skb)->nr_frags && |
1332 | (!(dev->features & NETIF_F_SG) || illegal_highdma(dev, skb)) && | 1279 | (!(dev->features & NETIF_F_SG) || illegal_highdma(dev, skb)) && |
1333 | __skb_linearize(skb, GFP_ATOMIC)) | 1280 | __skb_linearize(skb)) |
1334 | goto out_kfree_skb; | 1281 | goto out_kfree_skb; |
1335 | 1282 | ||
1336 | /* If packet is not checksummed and device does not support | 1283 | /* If packet is not checksummed and device does not support |
1337 | * checksumming for this protocol, complete checksumming here. | 1284 | * checksumming for this protocol, complete checksumming here. |
1338 | */ | 1285 | */ |
1339 | if (skb->ip_summed == CHECKSUM_HW && | 1286 | if (skb->ip_summed == CHECKSUM_HW && |
1340 | (!(dev->features & (NETIF_F_HW_CSUM | NETIF_F_NO_CSUM)) && | 1287 | (!(dev->features & NETIF_F_GEN_CSUM) && |
1341 | (!(dev->features & NETIF_F_IP_CSUM) || | 1288 | (!(dev->features & NETIF_F_IP_CSUM) || |
1342 | skb->protocol != htons(ETH_P_IP)))) | 1289 | skb->protocol != htons(ETH_P_IP)))) |
1343 | if (skb_checksum_help(skb, 0)) | 1290 | if (skb_checksum_help(skb, 0)) |
@@ -1382,8 +1329,8 @@ int dev_queue_xmit(struct sk_buff *skb) | |||
1382 | /* The device has no queue. Common case for software devices: | 1329 | /* The device has no queue. Common case for software devices: |
1383 | loopback, all the sorts of tunnels... | 1330 | loopback, all the sorts of tunnels... |
1384 | 1331 | ||
1385 | Really, it is unlikely that xmit_lock protection is necessary here. | 1332 | Really, it is unlikely that netif_tx_lock protection is necessary |
1386 | (f.e. loopback and IP tunnels are clean ignoring statistics | 1333 | here. (f.e. loopback and IP tunnels are clean ignoring statistics |
1387 | counters.) | 1334 | counters.) |
1388 | However, it is possible, that they rely on protection | 1335 | However, it is possible, that they rely on protection |
1389 | made by us here. | 1336 | made by us here. |
@@ -1846,6 +1793,19 @@ static void net_rx_action(struct softirq_action *h) | |||
1846 | } | 1793 | } |
1847 | } | 1794 | } |
1848 | out: | 1795 | out: |
1796 | #ifdef CONFIG_NET_DMA | ||
1797 | /* | ||
1798 | * There may not be any more sk_buffs coming right now, so push | ||
1799 | * any pending DMA copies to hardware | ||
1800 | */ | ||
1801 | if (net_dma_client) { | ||
1802 | struct dma_chan *chan; | ||
1803 | rcu_read_lock(); | ||
1804 | list_for_each_entry_rcu(chan, &net_dma_client->channels, client_node) | ||
1805 | dma_async_memcpy_issue_pending(chan); | ||
1806 | rcu_read_unlock(); | ||
1807 | } | ||
1808 | #endif | ||
1849 | local_irq_enable(); | 1809 | local_irq_enable(); |
1850 | return; | 1810 | return; |
1851 | 1811 | ||
@@ -2785,7 +2745,7 @@ int register_netdevice(struct net_device *dev) | |||
2785 | BUG_ON(dev->reg_state != NETREG_UNINITIALIZED); | 2745 | BUG_ON(dev->reg_state != NETREG_UNINITIALIZED); |
2786 | 2746 | ||
2787 | spin_lock_init(&dev->queue_lock); | 2747 | spin_lock_init(&dev->queue_lock); |
2788 | spin_lock_init(&dev->xmit_lock); | 2748 | spin_lock_init(&dev->_xmit_lock); |
2789 | dev->xmit_lock_owner = -1; | 2749 | dev->xmit_lock_owner = -1; |
2790 | #ifdef CONFIG_NET_CLS_ACT | 2750 | #ifdef CONFIG_NET_CLS_ACT |
2791 | spin_lock_init(&dev->ingress_lock); | 2751 | spin_lock_init(&dev->ingress_lock); |
@@ -2829,9 +2789,7 @@ int register_netdevice(struct net_device *dev) | |||
2829 | 2789 | ||
2830 | /* Fix illegal SG+CSUM combinations. */ | 2790 | /* Fix illegal SG+CSUM combinations. */ |
2831 | if ((dev->features & NETIF_F_SG) && | 2791 | if ((dev->features & NETIF_F_SG) && |
2832 | !(dev->features & (NETIF_F_IP_CSUM | | 2792 | !(dev->features & NETIF_F_ALL_CSUM)) { |
2833 | NETIF_F_NO_CSUM | | ||
2834 | NETIF_F_HW_CSUM))) { | ||
2835 | printk("%s: Dropping NETIF_F_SG since no checksum feature.\n", | 2793 | printk("%s: Dropping NETIF_F_SG since no checksum feature.\n", |
2836 | dev->name); | 2794 | dev->name); |
2837 | dev->features &= ~NETIF_F_SG; | 2795 | dev->features &= ~NETIF_F_SG; |
@@ -3300,6 +3258,88 @@ static int dev_cpu_callback(struct notifier_block *nfb, | |||
3300 | } | 3258 | } |
3301 | #endif /* CONFIG_HOTPLUG_CPU */ | 3259 | #endif /* CONFIG_HOTPLUG_CPU */ |
3302 | 3260 | ||
3261 | #ifdef CONFIG_NET_DMA | ||
3262 | /** | ||
3263 | * net_dma_rebalance - | ||
3264 | * This is called when the number of channels allocated to the net_dma_client | ||
3265 | * changes. The net_dma_client tries to have one DMA channel per CPU. | ||
3266 | */ | ||
3267 | static void net_dma_rebalance(void) | ||
3268 | { | ||
3269 | unsigned int cpu, i, n; | ||
3270 | struct dma_chan *chan; | ||
3271 | |||
3272 | lock_cpu_hotplug(); | ||
3273 | |||
3274 | if (net_dma_count == 0) { | ||
3275 | for_each_online_cpu(cpu) | ||
3276 | rcu_assign_pointer(per_cpu(softnet_data.net_dma, cpu), NULL); | ||
3277 | unlock_cpu_hotplug(); | ||
3278 | return; | ||
3279 | } | ||
3280 | |||
3281 | i = 0; | ||
3282 | cpu = first_cpu(cpu_online_map); | ||
3283 | |||
3284 | rcu_read_lock(); | ||
3285 | list_for_each_entry(chan, &net_dma_client->channels, client_node) { | ||
3286 | n = ((num_online_cpus() / net_dma_count) | ||
3287 | + (i < (num_online_cpus() % net_dma_count) ? 1 : 0)); | ||
3288 | |||
3289 | while(n) { | ||
3290 | per_cpu(softnet_data.net_dma, cpu) = chan; | ||
3291 | cpu = next_cpu(cpu, cpu_online_map); | ||
3292 | n--; | ||
3293 | } | ||
3294 | i++; | ||
3295 | } | ||
3296 | rcu_read_unlock(); | ||
3297 | |||
3298 | unlock_cpu_hotplug(); | ||
3299 | } | ||
3300 | |||
3301 | /** | ||
3302 | * netdev_dma_event - event callback for the net_dma_client | ||
3303 | * @client: should always be net_dma_client | ||
3304 | * @chan: | ||
3305 | * @event: | ||
3306 | */ | ||
3307 | static void netdev_dma_event(struct dma_client *client, struct dma_chan *chan, | ||
3308 | enum dma_event event) | ||
3309 | { | ||
3310 | spin_lock(&net_dma_event_lock); | ||
3311 | switch (event) { | ||
3312 | case DMA_RESOURCE_ADDED: | ||
3313 | net_dma_count++; | ||
3314 | net_dma_rebalance(); | ||
3315 | break; | ||
3316 | case DMA_RESOURCE_REMOVED: | ||
3317 | net_dma_count--; | ||
3318 | net_dma_rebalance(); | ||
3319 | break; | ||
3320 | default: | ||
3321 | break; | ||
3322 | } | ||
3323 | spin_unlock(&net_dma_event_lock); | ||
3324 | } | ||
3325 | |||
3326 | /** | ||
3327 | * netdev_dma_regiser - register the networking subsystem as a DMA client | ||
3328 | */ | ||
3329 | static int __init netdev_dma_register(void) | ||
3330 | { | ||
3331 | spin_lock_init(&net_dma_event_lock); | ||
3332 | net_dma_client = dma_async_client_register(netdev_dma_event); | ||
3333 | if (net_dma_client == NULL) | ||
3334 | return -ENOMEM; | ||
3335 | |||
3336 | dma_async_client_chan_request(net_dma_client, num_online_cpus()); | ||
3337 | return 0; | ||
3338 | } | ||
3339 | |||
3340 | #else | ||
3341 | static int __init netdev_dma_register(void) { return -ENODEV; } | ||
3342 | #endif /* CONFIG_NET_DMA */ | ||
3303 | 3343 | ||
3304 | /* | 3344 | /* |
3305 | * Initialize the DEV module. At boot time this walks the device list and | 3345 | * Initialize the DEV module. At boot time this walks the device list and |
@@ -3353,6 +3393,8 @@ static int __init net_dev_init(void) | |||
3353 | atomic_set(&queue->backlog_dev.refcnt, 1); | 3393 | atomic_set(&queue->backlog_dev.refcnt, 1); |
3354 | } | 3394 | } |
3355 | 3395 | ||
3396 | netdev_dma_register(); | ||
3397 | |||
3356 | dev_boot_phase = 0; | 3398 | dev_boot_phase = 0; |
3357 | 3399 | ||
3358 | open_softirq(NET_TX_SOFTIRQ, net_tx_action, NULL); | 3400 | open_softirq(NET_TX_SOFTIRQ, net_tx_action, NULL); |
@@ -3371,7 +3413,6 @@ subsys_initcall(net_dev_init); | |||
3371 | EXPORT_SYMBOL(__dev_get_by_index); | 3413 | EXPORT_SYMBOL(__dev_get_by_index); |
3372 | EXPORT_SYMBOL(__dev_get_by_name); | 3414 | EXPORT_SYMBOL(__dev_get_by_name); |
3373 | EXPORT_SYMBOL(__dev_remove_pack); | 3415 | EXPORT_SYMBOL(__dev_remove_pack); |
3374 | EXPORT_SYMBOL(__skb_linearize); | ||
3375 | EXPORT_SYMBOL(dev_valid_name); | 3416 | EXPORT_SYMBOL(dev_valid_name); |
3376 | EXPORT_SYMBOL(dev_add_pack); | 3417 | EXPORT_SYMBOL(dev_add_pack); |
3377 | EXPORT_SYMBOL(dev_alloc_name); | 3418 | EXPORT_SYMBOL(dev_alloc_name); |
diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c index 05d60850840e..c57d887da2ef 100644 --- a/net/core/dev_mcast.c +++ b/net/core/dev_mcast.c | |||
@@ -62,7 +62,7 @@ | |||
62 | * Device mc lists are changed by bh at least if IPv6 is enabled, | 62 | * Device mc lists are changed by bh at least if IPv6 is enabled, |
63 | * so that it must be bh protected. | 63 | * so that it must be bh protected. |
64 | * | 64 | * |
65 | * We block accesses to device mc filters with dev->xmit_lock. | 65 | * We block accesses to device mc filters with netif_tx_lock. |
66 | */ | 66 | */ |
67 | 67 | ||
68 | /* | 68 | /* |
@@ -93,9 +93,9 @@ static void __dev_mc_upload(struct net_device *dev) | |||
93 | 93 | ||
94 | void dev_mc_upload(struct net_device *dev) | 94 | void dev_mc_upload(struct net_device *dev) |
95 | { | 95 | { |
96 | spin_lock_bh(&dev->xmit_lock); | 96 | netif_tx_lock_bh(dev); |
97 | __dev_mc_upload(dev); | 97 | __dev_mc_upload(dev); |
98 | spin_unlock_bh(&dev->xmit_lock); | 98 | netif_tx_unlock_bh(dev); |
99 | } | 99 | } |
100 | 100 | ||
101 | /* | 101 | /* |
@@ -107,7 +107,7 @@ int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl) | |||
107 | int err = 0; | 107 | int err = 0; |
108 | struct dev_mc_list *dmi, **dmip; | 108 | struct dev_mc_list *dmi, **dmip; |
109 | 109 | ||
110 | spin_lock_bh(&dev->xmit_lock); | 110 | netif_tx_lock_bh(dev); |
111 | 111 | ||
112 | for (dmip = &dev->mc_list; (dmi = *dmip) != NULL; dmip = &dmi->next) { | 112 | for (dmip = &dev->mc_list; (dmi = *dmip) != NULL; dmip = &dmi->next) { |
113 | /* | 113 | /* |
@@ -139,13 +139,13 @@ int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl) | |||
139 | */ | 139 | */ |
140 | __dev_mc_upload(dev); | 140 | __dev_mc_upload(dev); |
141 | 141 | ||
142 | spin_unlock_bh(&dev->xmit_lock); | 142 | netif_tx_unlock_bh(dev); |
143 | return 0; | 143 | return 0; |
144 | } | 144 | } |
145 | } | 145 | } |
146 | err = -ENOENT; | 146 | err = -ENOENT; |
147 | done: | 147 | done: |
148 | spin_unlock_bh(&dev->xmit_lock); | 148 | netif_tx_unlock_bh(dev); |
149 | return err; | 149 | return err; |
150 | } | 150 | } |
151 | 151 | ||
@@ -160,7 +160,7 @@ int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl) | |||
160 | 160 | ||
161 | dmi1 = kmalloc(sizeof(*dmi), GFP_ATOMIC); | 161 | dmi1 = kmalloc(sizeof(*dmi), GFP_ATOMIC); |
162 | 162 | ||
163 | spin_lock_bh(&dev->xmit_lock); | 163 | netif_tx_lock_bh(dev); |
164 | for (dmi = dev->mc_list; dmi != NULL; dmi = dmi->next) { | 164 | for (dmi = dev->mc_list; dmi != NULL; dmi = dmi->next) { |
165 | if (memcmp(dmi->dmi_addr, addr, dmi->dmi_addrlen) == 0 && | 165 | if (memcmp(dmi->dmi_addr, addr, dmi->dmi_addrlen) == 0 && |
166 | dmi->dmi_addrlen == alen) { | 166 | dmi->dmi_addrlen == alen) { |
@@ -176,7 +176,7 @@ int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl) | |||
176 | } | 176 | } |
177 | 177 | ||
178 | if ((dmi = dmi1) == NULL) { | 178 | if ((dmi = dmi1) == NULL) { |
179 | spin_unlock_bh(&dev->xmit_lock); | 179 | netif_tx_unlock_bh(dev); |
180 | return -ENOMEM; | 180 | return -ENOMEM; |
181 | } | 181 | } |
182 | memcpy(dmi->dmi_addr, addr, alen); | 182 | memcpy(dmi->dmi_addr, addr, alen); |
@@ -189,11 +189,11 @@ int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl) | |||
189 | 189 | ||
190 | __dev_mc_upload(dev); | 190 | __dev_mc_upload(dev); |
191 | 191 | ||
192 | spin_unlock_bh(&dev->xmit_lock); | 192 | netif_tx_unlock_bh(dev); |
193 | return 0; | 193 | return 0; |
194 | 194 | ||
195 | done: | 195 | done: |
196 | spin_unlock_bh(&dev->xmit_lock); | 196 | netif_tx_unlock_bh(dev); |
197 | kfree(dmi1); | 197 | kfree(dmi1); |
198 | return err; | 198 | return err; |
199 | } | 199 | } |
@@ -204,7 +204,7 @@ done: | |||
204 | 204 | ||
205 | void dev_mc_discard(struct net_device *dev) | 205 | void dev_mc_discard(struct net_device *dev) |
206 | { | 206 | { |
207 | spin_lock_bh(&dev->xmit_lock); | 207 | netif_tx_lock_bh(dev); |
208 | 208 | ||
209 | while (dev->mc_list != NULL) { | 209 | while (dev->mc_list != NULL) { |
210 | struct dev_mc_list *tmp = dev->mc_list; | 210 | struct dev_mc_list *tmp = dev->mc_list; |
@@ -215,7 +215,7 @@ void dev_mc_discard(struct net_device *dev) | |||
215 | } | 215 | } |
216 | dev->mc_count = 0; | 216 | dev->mc_count = 0; |
217 | 217 | ||
218 | spin_unlock_bh(&dev->xmit_lock); | 218 | netif_tx_unlock_bh(dev); |
219 | } | 219 | } |
220 | 220 | ||
221 | #ifdef CONFIG_PROC_FS | 221 | #ifdef CONFIG_PROC_FS |
@@ -250,7 +250,7 @@ static int dev_mc_seq_show(struct seq_file *seq, void *v) | |||
250 | struct dev_mc_list *m; | 250 | struct dev_mc_list *m; |
251 | struct net_device *dev = v; | 251 | struct net_device *dev = v; |
252 | 252 | ||
253 | spin_lock_bh(&dev->xmit_lock); | 253 | netif_tx_lock_bh(dev); |
254 | for (m = dev->mc_list; m; m = m->next) { | 254 | for (m = dev->mc_list; m; m = m->next) { |
255 | int i; | 255 | int i; |
256 | 256 | ||
@@ -262,7 +262,7 @@ static int dev_mc_seq_show(struct seq_file *seq, void *v) | |||
262 | 262 | ||
263 | seq_putc(seq, '\n'); | 263 | seq_putc(seq, '\n'); |
264 | } | 264 | } |
265 | spin_unlock_bh(&dev->xmit_lock); | 265 | netif_tx_unlock_bh(dev); |
266 | return 0; | 266 | return 0; |
267 | } | 267 | } |
268 | 268 | ||
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index e6f76106a99b..33ce7ed6afc6 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
@@ -30,7 +30,7 @@ u32 ethtool_op_get_link(struct net_device *dev) | |||
30 | 30 | ||
31 | u32 ethtool_op_get_tx_csum(struct net_device *dev) | 31 | u32 ethtool_op_get_tx_csum(struct net_device *dev) |
32 | { | 32 | { |
33 | return (dev->features & (NETIF_F_IP_CSUM | NETIF_F_HW_CSUM)) != 0; | 33 | return (dev->features & NETIF_F_ALL_CSUM) != 0; |
34 | } | 34 | } |
35 | 35 | ||
36 | int ethtool_op_set_tx_csum(struct net_device *dev, u32 data) | 36 | int ethtool_op_set_tx_csum(struct net_device *dev, u32 data) |
@@ -551,9 +551,7 @@ static int ethtool_set_sg(struct net_device *dev, char __user *useraddr) | |||
551 | return -EFAULT; | 551 | return -EFAULT; |
552 | 552 | ||
553 | if (edata.data && | 553 | if (edata.data && |
554 | !(dev->features & (NETIF_F_IP_CSUM | | 554 | !(dev->features & NETIF_F_ALL_CSUM)) |
555 | NETIF_F_NO_CSUM | | ||
556 | NETIF_F_HW_CSUM))) | ||
557 | return -EINVAL; | 555 | return -EINVAL; |
558 | 556 | ||
559 | return __ethtool_set_sg(dev, edata.data); | 557 | return __ethtool_set_sg(dev, edata.data); |
@@ -591,7 +589,7 @@ static int ethtool_set_tso(struct net_device *dev, char __user *useraddr) | |||
591 | 589 | ||
592 | static int ethtool_get_ufo(struct net_device *dev, char __user *useraddr) | 590 | static int ethtool_get_ufo(struct net_device *dev, char __user *useraddr) |
593 | { | 591 | { |
594 | struct ethtool_value edata = { ETHTOOL_GTSO }; | 592 | struct ethtool_value edata = { ETHTOOL_GUFO }; |
595 | 593 | ||
596 | if (!dev->ethtool_ops->get_ufo) | 594 | if (!dev->ethtool_ops->get_ufo) |
597 | return -EOPNOTSUPP; | 595 | return -EOPNOTSUPP; |
@@ -600,6 +598,7 @@ static int ethtool_get_ufo(struct net_device *dev, char __user *useraddr) | |||
600 | return -EFAULT; | 598 | return -EFAULT; |
601 | return 0; | 599 | return 0; |
602 | } | 600 | } |
601 | |||
603 | static int ethtool_set_ufo(struct net_device *dev, char __user *useraddr) | 602 | static int ethtool_set_ufo(struct net_device *dev, char __user *useraddr) |
604 | { | 603 | { |
605 | struct ethtool_value edata; | 604 | struct ethtool_value edata; |
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index e8e05cebd95a..9cb781830380 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
@@ -273,24 +273,21 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) | |||
273 | 273 | ||
274 | do { | 274 | do { |
275 | npinfo->tries--; | 275 | npinfo->tries--; |
276 | spin_lock(&np->dev->xmit_lock); | 276 | netif_tx_lock(np->dev); |
277 | np->dev->xmit_lock_owner = smp_processor_id(); | ||
278 | 277 | ||
279 | /* | 278 | /* |
280 | * network drivers do not expect to be called if the queue is | 279 | * network drivers do not expect to be called if the queue is |
281 | * stopped. | 280 | * stopped. |
282 | */ | 281 | */ |
283 | if (netif_queue_stopped(np->dev)) { | 282 | if (netif_queue_stopped(np->dev)) { |
284 | np->dev->xmit_lock_owner = -1; | 283 | netif_tx_unlock(np->dev); |
285 | spin_unlock(&np->dev->xmit_lock); | ||
286 | netpoll_poll(np); | 284 | netpoll_poll(np); |
287 | udelay(50); | 285 | udelay(50); |
288 | continue; | 286 | continue; |
289 | } | 287 | } |
290 | 288 | ||
291 | status = np->dev->hard_start_xmit(skb, np->dev); | 289 | status = np->dev->hard_start_xmit(skb, np->dev); |
292 | np->dev->xmit_lock_owner = -1; | 290 | netif_tx_unlock(np->dev); |
293 | spin_unlock(&np->dev->xmit_lock); | ||
294 | 291 | ||
295 | /* success */ | 292 | /* success */ |
296 | if(!status) { | 293 | if(!status) { |
diff --git a/net/core/pktgen.c b/net/core/pktgen.c index c23e9c06ee23..67ed14ddabd2 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c | |||
@@ -2897,7 +2897,7 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev) | |||
2897 | } | 2897 | } |
2898 | } | 2898 | } |
2899 | 2899 | ||
2900 | spin_lock_bh(&odev->xmit_lock); | 2900 | netif_tx_lock_bh(odev); |
2901 | if (!netif_queue_stopped(odev)) { | 2901 | if (!netif_queue_stopped(odev)) { |
2902 | 2902 | ||
2903 | atomic_inc(&(pkt_dev->skb->users)); | 2903 | atomic_inc(&(pkt_dev->skb->users)); |
@@ -2942,7 +2942,7 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev) | |||
2942 | pkt_dev->next_tx_ns = 0; | 2942 | pkt_dev->next_tx_ns = 0; |
2943 | } | 2943 | } |
2944 | 2944 | ||
2945 | spin_unlock_bh(&odev->xmit_lock); | 2945 | netif_tx_unlock_bh(odev); |
2946 | 2946 | ||
2947 | /* If pkt_dev->count is zero, then run forever */ | 2947 | /* If pkt_dev->count is zero, then run forever */ |
2948 | if ((pkt_dev->count != 0) && (pkt_dev->sofar >= pkt_dev->count)) { | 2948 | if ((pkt_dev->count != 0) && (pkt_dev->sofar >= pkt_dev->count)) { |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index fb3770f9c094..bb7210f4005e 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -464,7 +464,7 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) | |||
464 | n->tc_verd = CLR_TC_MUNGED(n->tc_verd); | 464 | n->tc_verd = CLR_TC_MUNGED(n->tc_verd); |
465 | C(input_dev); | 465 | C(input_dev); |
466 | #endif | 466 | #endif |
467 | 467 | skb_copy_secmark(n, skb); | |
468 | #endif | 468 | #endif |
469 | C(truesize); | 469 | C(truesize); |
470 | atomic_set(&n->users, 1); | 470 | atomic_set(&n->users, 1); |
@@ -526,6 +526,7 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old) | |||
526 | #endif | 526 | #endif |
527 | new->tc_index = old->tc_index; | 527 | new->tc_index = old->tc_index; |
528 | #endif | 528 | #endif |
529 | skb_copy_secmark(new, old); | ||
529 | atomic_set(&new->users, 1); | 530 | atomic_set(&new->users, 1); |
530 | skb_shinfo(new)->tso_size = skb_shinfo(old)->tso_size; | 531 | skb_shinfo(new)->tso_size = skb_shinfo(old)->tso_size; |
531 | skb_shinfo(new)->tso_segs = skb_shinfo(old)->tso_segs; | 532 | skb_shinfo(new)->tso_segs = skb_shinfo(old)->tso_segs; |
@@ -800,12 +801,10 @@ struct sk_buff *skb_pad(struct sk_buff *skb, int pad) | |||
800 | return nskb; | 801 | return nskb; |
801 | } | 802 | } |
802 | 803 | ||
803 | /* Trims skb to length len. It can change skb pointers, if "realloc" is 1. | 804 | /* Trims skb to length len. It can change skb pointers. |
804 | * If realloc==0 and trimming is impossible without change of data, | ||
805 | * it is BUG(). | ||
806 | */ | 805 | */ |
807 | 806 | ||
808 | int ___pskb_trim(struct sk_buff *skb, unsigned int len, int realloc) | 807 | int ___pskb_trim(struct sk_buff *skb, unsigned int len) |
809 | { | 808 | { |
810 | int offset = skb_headlen(skb); | 809 | int offset = skb_headlen(skb); |
811 | int nfrags = skb_shinfo(skb)->nr_frags; | 810 | int nfrags = skb_shinfo(skb)->nr_frags; |
@@ -815,7 +814,6 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len, int realloc) | |||
815 | int end = offset + skb_shinfo(skb)->frags[i].size; | 814 | int end = offset + skb_shinfo(skb)->frags[i].size; |
816 | if (end > len) { | 815 | if (end > len) { |
817 | if (skb_cloned(skb)) { | 816 | if (skb_cloned(skb)) { |
818 | BUG_ON(!realloc); | ||
819 | if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) | 817 | if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) |
820 | return -ENOMEM; | 818 | return -ENOMEM; |
821 | } | 819 | } |
diff --git a/net/core/sock.c b/net/core/sock.c index ed2afdb9ea2d..5d820c376653 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -832,6 +832,9 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority) | |||
832 | atomic_set(&newsk->sk_omem_alloc, 0); | 832 | atomic_set(&newsk->sk_omem_alloc, 0); |
833 | skb_queue_head_init(&newsk->sk_receive_queue); | 833 | skb_queue_head_init(&newsk->sk_receive_queue); |
834 | skb_queue_head_init(&newsk->sk_write_queue); | 834 | skb_queue_head_init(&newsk->sk_write_queue); |
835 | #ifdef CONFIG_NET_DMA | ||
836 | skb_queue_head_init(&newsk->sk_async_wait_queue); | ||
837 | #endif | ||
835 | 838 | ||
836 | rwlock_init(&newsk->sk_dst_lock); | 839 | rwlock_init(&newsk->sk_dst_lock); |
837 | rwlock_init(&newsk->sk_callback_lock); | 840 | rwlock_init(&newsk->sk_callback_lock); |
@@ -1383,6 +1386,9 @@ void sock_init_data(struct socket *sock, struct sock *sk) | |||
1383 | skb_queue_head_init(&sk->sk_receive_queue); | 1386 | skb_queue_head_init(&sk->sk_receive_queue); |
1384 | skb_queue_head_init(&sk->sk_write_queue); | 1387 | skb_queue_head_init(&sk->sk_write_queue); |
1385 | skb_queue_head_init(&sk->sk_error_queue); | 1388 | skb_queue_head_init(&sk->sk_error_queue); |
1389 | #ifdef CONFIG_NET_DMA | ||
1390 | skb_queue_head_init(&sk->sk_async_wait_queue); | ||
1391 | #endif | ||
1386 | 1392 | ||
1387 | sk->sk_send_head = NULL; | 1393 | sk->sk_send_head = NULL; |
1388 | 1394 | ||
diff --git a/net/core/user_dma.c b/net/core/user_dma.c new file mode 100644 index 000000000000..b7c98dbcdb81 --- /dev/null +++ b/net/core/user_dma.c | |||
@@ -0,0 +1,131 @@ | |||
1 | /* | ||
2 | * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved. | ||
3 | * Portions based on net/core/datagram.c and copyrighted by their authors. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the Free | ||
7 | * Software Foundation; either version 2 of the License, or (at your option) | ||
8 | * any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License along with | ||
16 | * this program; if not, write to the Free Software Foundation, Inc., 59 | ||
17 | * Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
18 | * | ||
19 | * The full GNU General Public License is included in this distribution in the | ||
20 | * file called COPYING. | ||
21 | */ | ||
22 | |||
23 | /* | ||
24 | * This code allows the net stack to make use of a DMA engine for | ||
25 | * skb to iovec copies. | ||
26 | */ | ||
27 | |||
28 | #include <linux/dmaengine.h> | ||
29 | #include <linux/socket.h> | ||
30 | #include <linux/rtnetlink.h> /* for BUG_TRAP */ | ||
31 | #include <net/tcp.h> | ||
32 | |||
33 | #define NET_DMA_DEFAULT_COPYBREAK 4096 | ||
34 | |||
35 | int sysctl_tcp_dma_copybreak = NET_DMA_DEFAULT_COPYBREAK; | ||
36 | |||
37 | /** | ||
38 | * dma_skb_copy_datagram_iovec - Copy a datagram to an iovec. | ||
39 | * @skb - buffer to copy | ||
40 | * @offset - offset in the buffer to start copying from | ||
41 | * @iovec - io vector to copy to | ||
42 | * @len - amount of data to copy from buffer to iovec | ||
43 | * @pinned_list - locked iovec buffer data | ||
44 | * | ||
45 | * Note: the iovec is modified during the copy. | ||
46 | */ | ||
47 | int dma_skb_copy_datagram_iovec(struct dma_chan *chan, | ||
48 | struct sk_buff *skb, int offset, struct iovec *to, | ||
49 | size_t len, struct dma_pinned_list *pinned_list) | ||
50 | { | ||
51 | int start = skb_headlen(skb); | ||
52 | int i, copy = start - offset; | ||
53 | dma_cookie_t cookie = 0; | ||
54 | |||
55 | /* Copy header. */ | ||
56 | if (copy > 0) { | ||
57 | if (copy > len) | ||
58 | copy = len; | ||
59 | cookie = dma_memcpy_to_iovec(chan, to, pinned_list, | ||
60 | skb->data + offset, copy); | ||
61 | if (cookie < 0) | ||
62 | goto fault; | ||
63 | len -= copy; | ||
64 | if (len == 0) | ||
65 | goto end; | ||
66 | offset += copy; | ||
67 | } | ||
68 | |||
69 | /* Copy paged appendix. Hmm... why does this look so complicated? */ | ||
70 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { | ||
71 | int end; | ||
72 | |||
73 | BUG_TRAP(start <= offset + len); | ||
74 | |||
75 | end = start + skb_shinfo(skb)->frags[i].size; | ||
76 | copy = end - offset; | ||
77 | if ((copy = end - offset) > 0) { | ||
78 | skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; | ||
79 | struct page *page = frag->page; | ||
80 | |||
81 | if (copy > len) | ||
82 | copy = len; | ||
83 | |||
84 | cookie = dma_memcpy_pg_to_iovec(chan, to, pinned_list, page, | ||
85 | frag->page_offset + offset - start, copy); | ||
86 | if (cookie < 0) | ||
87 | goto fault; | ||
88 | len -= copy; | ||
89 | if (len == 0) | ||
90 | goto end; | ||
91 | offset += copy; | ||
92 | } | ||
93 | start = end; | ||
94 | } | ||
95 | |||
96 | if (skb_shinfo(skb)->frag_list) { | ||
97 | struct sk_buff *list = skb_shinfo(skb)->frag_list; | ||
98 | |||
99 | for (; list; list = list->next) { | ||
100 | int end; | ||
101 | |||
102 | BUG_TRAP(start <= offset + len); | ||
103 | |||
104 | end = start + list->len; | ||
105 | copy = end - offset; | ||
106 | if (copy > 0) { | ||
107 | if (copy > len) | ||
108 | copy = len; | ||
109 | cookie = dma_skb_copy_datagram_iovec(chan, list, | ||
110 | offset - start, to, copy, | ||
111 | pinned_list); | ||
112 | if (cookie < 0) | ||
113 | goto fault; | ||
114 | len -= copy; | ||
115 | if (len == 0) | ||
116 | goto end; | ||
117 | offset += copy; | ||
118 | } | ||
119 | start = end; | ||
120 | } | ||
121 | } | ||
122 | |||
123 | end: | ||
124 | if (!len) { | ||
125 | skb->dma_cookie = cookie; | ||
126 | return cookie; | ||
127 | } | ||
128 | |||
129 | fault: | ||
130 | return -EFAULT; | ||
131 | } | ||