diff options
Diffstat (limited to 'net/core/dev.c')
-rw-r--r-- | net/core/dev.c | 185 |
1 files changed, 113 insertions, 72 deletions
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); |