aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/fcoe/libfcoe.c94
1 files changed, 43 insertions, 51 deletions
diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c
index 3865d936dee8..d22275bf57f8 100644
--- a/drivers/scsi/fcoe/libfcoe.c
+++ b/drivers/scsi/fcoe/libfcoe.c
@@ -65,7 +65,7 @@ MODULE_LICENSE("GPL");
65LIST_HEAD(fcoe_hostlist); 65LIST_HEAD(fcoe_hostlist);
66DEFINE_RWLOCK(fcoe_hostlist_lock); 66DEFINE_RWLOCK(fcoe_hostlist_lock);
67DEFINE_TIMER(fcoe_timer, NULL, 0, 0); 67DEFINE_TIMER(fcoe_timer, NULL, 0, 0);
68struct fcoe_percpu_s *fcoe_percpu[NR_CPUS]; 68DEFINE_PER_CPU(struct fcoe_percpu_s, fcoe_percpu);
69 69
70 70
71/* Function Prototyes */ 71/* Function Prototyes */
@@ -226,6 +226,7 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *dev,
226 fr->fr_dev = lp; 226 fr->fr_dev = lp;
227 fr->ptype = ptype; 227 fr->ptype = ptype;
228 cpu_idx = 0; 228 cpu_idx = 0;
229
229#ifdef CONFIG_SMP 230#ifdef CONFIG_SMP
230 /* 231 /*
231 * The incoming frame exchange id(oxid) is ANDed with num of online 232 * The incoming frame exchange id(oxid) is ANDed with num of online
@@ -235,10 +236,12 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *dev,
235 * initialize to first online cpu index. 236 * initialize to first online cpu index.
236 */ 237 */
237 cpu_idx = oxid & (num_online_cpus() - 1); 238 cpu_idx = oxid & (num_online_cpus() - 1);
238 if (!fcoe_percpu[cpu_idx] || !cpu_online(cpu_idx)) 239 if (!cpu_online(cpu_idx))
239 cpu_idx = first_cpu(cpu_online_map); 240 cpu_idx = first_cpu(cpu_online_map);
241
240#endif 242#endif
241 fps = fcoe_percpu[cpu_idx]; 243
244 fps = &per_cpu(fcoe_percpu, cpu_idx);
242 245
243 spin_lock_bh(&fps->fcoe_rx_list.lock); 246 spin_lock_bh(&fps->fcoe_rx_list.lock);
244 __skb_queue_tail(&fps->fcoe_rx_list, skb); 247 __skb_queue_tail(&fps->fcoe_rx_list, skb);
@@ -292,15 +295,13 @@ static int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen)
292{ 295{
293 struct fcoe_percpu_s *fps; 296 struct fcoe_percpu_s *fps;
294 struct page *page; 297 struct page *page;
295 unsigned int cpu_idx;
296 298
297 cpu_idx = get_cpu(); 299 fps = &get_cpu_var(fcoe_percpu);
298 fps = fcoe_percpu[cpu_idx];
299 page = fps->crc_eof_page; 300 page = fps->crc_eof_page;
300 if (!page) { 301 if (!page) {
301 page = alloc_page(GFP_ATOMIC); 302 page = alloc_page(GFP_ATOMIC);
302 if (!page) { 303 if (!page) {
303 put_cpu(); 304 put_cpu_var(fcoe_percpu);
304 return -ENOMEM; 305 return -ENOMEM;
305 } 306 }
306 fps->crc_eof_page = page; 307 fps->crc_eof_page = page;
@@ -320,7 +321,7 @@ static int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen)
320 fps->crc_eof_offset = 0; 321 fps->crc_eof_offset = 0;
321 put_page(page); 322 put_page(page);
322 } 323 }
323 put_cpu(); 324 put_cpu_var(fcoe_percpu);
324 return 0; 325 return 0;
325} 326}
326 327
@@ -1122,30 +1123,28 @@ EXPORT_SYMBOL_GPL(fcoe_link_ok);
1122 */ 1123 */
1123void fcoe_percpu_clean(struct fc_lport *lp) 1124void fcoe_percpu_clean(struct fc_lport *lp)
1124{ 1125{
1125 int idx;
1126 struct fcoe_percpu_s *pp; 1126 struct fcoe_percpu_s *pp;
1127 struct fcoe_rcv_info *fr; 1127 struct fcoe_rcv_info *fr;
1128 struct sk_buff_head *list; 1128 struct sk_buff_head *list;
1129 struct sk_buff *skb, *next; 1129 struct sk_buff *skb, *next;
1130 struct sk_buff *head; 1130 struct sk_buff *head;
1131 unsigned int cpu;
1131 1132
1132 for (idx = 0; idx < NR_CPUS; idx++) { 1133 for_each_possible_cpu(cpu) {
1133 if (fcoe_percpu[idx]) { 1134 pp = &per_cpu(fcoe_percpu, cpu);
1134 pp = fcoe_percpu[idx]; 1135 spin_lock_bh(&pp->fcoe_rx_list.lock);
1135 spin_lock_bh(&pp->fcoe_rx_list.lock); 1136 list = &pp->fcoe_rx_list;
1136 list = &pp->fcoe_rx_list; 1137 head = list->next;
1137 head = list->next; 1138 for (skb = head; skb != (struct sk_buff *)list;
1138 for (skb = head; skb != (struct sk_buff *)list; 1139 skb = next) {
1139 skb = next) { 1140 next = skb->next;
1140 next = skb->next; 1141 fr = fcoe_dev_from_skb(skb);
1141 fr = fcoe_dev_from_skb(skb); 1142 if (fr->fr_dev == lp) {
1142 if (fr->fr_dev == lp) { 1143 __skb_unlink(skb, list);
1143 __skb_unlink(skb, list); 1144 kfree_skb(skb);
1144 kfree_skb(skb);
1145 }
1146 } 1145 }
1147 spin_unlock_bh(&pp->fcoe_rx_list.lock);
1148 } 1146 }
1147 spin_unlock_bh(&pp->fcoe_rx_list.lock);
1149 } 1148 }
1150} 1149}
1151EXPORT_SYMBOL_GPL(fcoe_percpu_clean); 1150EXPORT_SYMBOL_GPL(fcoe_percpu_clean);
@@ -1377,8 +1376,7 @@ static int __init fcoe_init(void)
1377#endif /* CONFIG_HOTPLUG_CPU */ 1376#endif /* CONFIG_HOTPLUG_CPU */
1378 1377
1379 for_each_possible_cpu(cpu) { 1378 for_each_possible_cpu(cpu) {
1380 p = fcoe_percpu[cpu]; 1379 p = &per_cpu(fcoe_percpu, cpu);
1381 p->cpu = cpu;
1382 skb_queue_head_init(&p->fcoe_rx_list); 1380 skb_queue_head_init(&p->fcoe_rx_list);
1383 } 1381 }
1384 1382
@@ -1386,24 +1384,19 @@ static int __init fcoe_init(void)
1386 * initialize per CPU interrupt thread 1384 * initialize per CPU interrupt thread
1387 */ 1385 */
1388 for_each_online_cpu(cpu) { 1386 for_each_online_cpu(cpu) {
1389 p = kzalloc(sizeof(struct fcoe_percpu_s), GFP_KERNEL); 1387 p = &per_cpu(fcoe_percpu, cpu);
1390 if (p) { 1388 p->thread = kthread_create(fcoe_percpu_receive_thread,
1391 p->thread = kthread_create(fcoe_percpu_receive_thread, 1389 (void *)p, "fcoethread/%d", cpu);
1392 (void *)p,
1393 "fcoethread/%d", cpu);
1394 1390
1395 /* 1391 /*
1396 * if there is no error then bind the thread to the cpu 1392 * If there is no error then bind the thread to the CPU
1397 * initialize the semaphore and skb queue head 1393 * and wake it up.
1398 */ 1394 */
1399 if (likely(!IS_ERR(p->thread))) { 1395 if (!IS_ERR(p->thread)) {
1400 fcoe_percpu[cpu] = p; 1396 kthread_bind(p->thread, cpu);
1401 kthread_bind(p->thread, cpu); 1397 wake_up_process(p->thread);
1402 wake_up_process(p->thread); 1398 } else {
1403 } else { 1399 p->thread = NULL;
1404 fcoe_percpu[cpu] = NULL;
1405 kfree(p);
1406 }
1407 } 1400 }
1408 } 1401 }
1409 1402
@@ -1432,7 +1425,7 @@ module_init(fcoe_init);
1432 */ 1425 */
1433static void __exit fcoe_exit(void) 1426static void __exit fcoe_exit(void)
1434{ 1427{
1435 u32 idx; 1428 unsigned int cpu;
1436 struct fcoe_softc *fc, *tmp; 1429 struct fcoe_softc *fc, *tmp;
1437 struct fcoe_percpu_s *p; 1430 struct fcoe_percpu_s *p;
1438 struct sk_buff *skb; 1431 struct sk_buff *skb;
@@ -1454,17 +1447,16 @@ static void __exit fcoe_exit(void)
1454 list_for_each_entry_safe(fc, tmp, &fcoe_hostlist, list) 1447 list_for_each_entry_safe(fc, tmp, &fcoe_hostlist, list)
1455 fcoe_transport_release(fc->real_dev); 1448 fcoe_transport_release(fc->real_dev);
1456 1449
1457 for (idx = 0; idx < NR_CPUS; idx++) { 1450 for_each_possible_cpu(cpu) {
1458 if (fcoe_percpu[idx]) { 1451 p = &per_cpu(fcoe_percpu, cpu);
1459 kthread_stop(fcoe_percpu[idx]->thread); 1452 if (p->thread) {
1460 p = fcoe_percpu[idx]; 1453 kthread_stop(p->thread);
1461 spin_lock_bh(&p->fcoe_rx_list.lock); 1454 spin_lock_bh(&p->fcoe_rx_list.lock);
1462 while ((skb = __skb_dequeue(&p->fcoe_rx_list)) != NULL) 1455 while ((skb = __skb_dequeue(&p->fcoe_rx_list)) != NULL)
1463 kfree_skb(skb); 1456 kfree_skb(skb);
1464 spin_unlock_bh(&p->fcoe_rx_list.lock); 1457 spin_unlock_bh(&p->fcoe_rx_list.lock);
1465 if (fcoe_percpu[idx]->crc_eof_page) 1458 if (p->crc_eof_page)
1466 put_page(fcoe_percpu[idx]->crc_eof_page); 1459 put_page(p->crc_eof_page);
1467 kfree(fcoe_percpu[idx]);
1468 } 1460 }
1469 } 1461 }
1470 1462