diff options
Diffstat (limited to 'drivers/scsi/fcoe/libfcoe.c')
-rw-r--r-- | drivers/scsi/fcoe/libfcoe.c | 143 |
1 files changed, 18 insertions, 125 deletions
diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index d22275bf57f8..648a2fc04271 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c | |||
@@ -71,9 +71,6 @@ DEFINE_PER_CPU(struct fcoe_percpu_s, fcoe_percpu); | |||
71 | /* Function Prototyes */ | 71 | /* Function Prototyes */ |
72 | static int fcoe_check_wait_queue(struct fc_lport *); | 72 | static int fcoe_check_wait_queue(struct fc_lport *); |
73 | static void fcoe_recv_flogi(struct fcoe_softc *, struct fc_frame *, u8 *); | 73 | static void fcoe_recv_flogi(struct fcoe_softc *, struct fc_frame *, u8 *); |
74 | #ifdef CONFIG_HOTPLUG_CPU | ||
75 | static int fcoe_cpu_callback(struct notifier_block *, ulong, void *); | ||
76 | #endif /* CONFIG_HOTPLUG_CPU */ | ||
77 | static int fcoe_device_notification(struct notifier_block *, ulong, void *); | 74 | static int fcoe_device_notification(struct notifier_block *, ulong, void *); |
78 | static void fcoe_dev_setup(void); | 75 | static void fcoe_dev_setup(void); |
79 | static void fcoe_dev_cleanup(void); | 76 | static void fcoe_dev_cleanup(void); |
@@ -83,87 +80,6 @@ static struct notifier_block fcoe_notifier = { | |||
83 | .notifier_call = fcoe_device_notification, | 80 | .notifier_call = fcoe_device_notification, |
84 | }; | 81 | }; |
85 | 82 | ||
86 | |||
87 | #ifdef CONFIG_HOTPLUG_CPU | ||
88 | static struct notifier_block fcoe_cpu_notifier = { | ||
89 | .notifier_call = fcoe_cpu_callback, | ||
90 | }; | ||
91 | |||
92 | /** | ||
93 | * fcoe_create_percpu_data() - creates the associated cpu data | ||
94 | * @cpu: index for the cpu where fcoe cpu data will be created | ||
95 | * | ||
96 | * create percpu stats block, from cpu add notifier | ||
97 | * | ||
98 | * Returns: none | ||
99 | */ | ||
100 | static void fcoe_create_percpu_data(unsigned int cpu) | ||
101 | { | ||
102 | struct fc_lport *lp; | ||
103 | struct fcoe_softc *fc; | ||
104 | |||
105 | write_lock_bh(&fcoe_hostlist_lock); | ||
106 | list_for_each_entry(fc, &fcoe_hostlist, list) { | ||
107 | lp = fc->lp; | ||
108 | if (lp->dev_stats[cpu] == NULL) | ||
109 | lp->dev_stats[cpu] = | ||
110 | kzalloc(sizeof(struct fcoe_dev_stats), | ||
111 | GFP_KERNEL); | ||
112 | } | ||
113 | write_unlock_bh(&fcoe_hostlist_lock); | ||
114 | } | ||
115 | |||
116 | /** | ||
117 | * fcoe_destroy_percpu_data() - destroys the associated cpu data | ||
118 | * @cpu: index for the cpu where fcoe cpu data will destroyed | ||
119 | * | ||
120 | * destroy percpu stats block called by cpu add/remove notifier | ||
121 | * | ||
122 | * Retuns: none | ||
123 | */ | ||
124 | static void fcoe_destroy_percpu_data(unsigned int cpu) | ||
125 | { | ||
126 | struct fc_lport *lp; | ||
127 | struct fcoe_softc *fc; | ||
128 | |||
129 | write_lock_bh(&fcoe_hostlist_lock); | ||
130 | list_for_each_entry(fc, &fcoe_hostlist, list) { | ||
131 | lp = fc->lp; | ||
132 | kfree(lp->dev_stats[cpu]); | ||
133 | lp->dev_stats[cpu] = NULL; | ||
134 | } | ||
135 | write_unlock_bh(&fcoe_hostlist_lock); | ||
136 | } | ||
137 | |||
138 | /** | ||
139 | * fcoe_cpu_callback() - fcoe cpu hotplug event callback | ||
140 | * @nfb: callback data block | ||
141 | * @action: event triggering the callback | ||
142 | * @hcpu: index for the cpu of this event | ||
143 | * | ||
144 | * this creates or destroys per cpu data for fcoe | ||
145 | * | ||
146 | * Returns NOTIFY_OK always. | ||
147 | */ | ||
148 | static int fcoe_cpu_callback(struct notifier_block *nfb, unsigned long action, | ||
149 | void *hcpu) | ||
150 | { | ||
151 | unsigned int cpu = (unsigned long)hcpu; | ||
152 | |||
153 | switch (action) { | ||
154 | case CPU_ONLINE: | ||
155 | fcoe_create_percpu_data(cpu); | ||
156 | break; | ||
157 | case CPU_DEAD: | ||
158 | fcoe_destroy_percpu_data(cpu); | ||
159 | break; | ||
160 | default: | ||
161 | break; | ||
162 | } | ||
163 | return NOTIFY_OK; | ||
164 | } | ||
165 | #endif /* CONFIG_HOTPLUG_CPU */ | ||
166 | |||
167 | /** | 83 | /** |
168 | * fcoe_rcv() - this is the fcoe receive function called by NET_RX_SOFTIRQ | 84 | * fcoe_rcv() - this is the fcoe receive function called by NET_RX_SOFTIRQ |
169 | * @skb: the receive skb | 85 | * @skb: the receive skb |
@@ -181,7 +97,6 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *dev, | |||
181 | struct fc_lport *lp; | 97 | struct fc_lport *lp; |
182 | struct fcoe_rcv_info *fr; | 98 | struct fcoe_rcv_info *fr; |
183 | struct fcoe_softc *fc; | 99 | struct fcoe_softc *fc; |
184 | struct fcoe_dev_stats *stats; | ||
185 | struct fc_frame_header *fh; | 100 | struct fc_frame_header *fh; |
186 | struct fcoe_percpu_s *fps; | 101 | struct fcoe_percpu_s *fps; |
187 | unsigned short oxid; | 102 | unsigned short oxid; |
@@ -252,13 +167,7 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *dev, | |||
252 | 167 | ||
253 | return 0; | 168 | return 0; |
254 | err: | 169 | err: |
255 | #ifdef CONFIG_SMP | 170 | fc_lport_get_stats(lp)->ErrorFrames++; |
256 | stats = lp->dev_stats[smp_processor_id()]; | ||
257 | #else | ||
258 | stats = lp->dev_stats[0]; | ||
259 | #endif | ||
260 | if (stats) | ||
261 | stats->ErrorFrames++; | ||
262 | 171 | ||
263 | err2: | 172 | err2: |
264 | kfree_skb(skb); | 173 | kfree_skb(skb); |
@@ -495,11 +404,9 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) | |||
495 | } | 404 | } |
496 | #endif | 405 | #endif |
497 | /* update tx stats: regardless if LLD fails */ | 406 | /* update tx stats: regardless if LLD fails */ |
498 | stats = lp->dev_stats[smp_processor_id()]; | 407 | stats = fc_lport_get_stats(lp); |
499 | if (stats) { | 408 | stats->TxFrames++; |
500 | stats->TxFrames++; | 409 | stats->TxWords += wlen; |
501 | stats->TxWords += wlen; | ||
502 | } | ||
503 | 410 | ||
504 | /* send down to lld */ | 411 | /* send down to lld */ |
505 | fr_dev(fp) = lp; | 412 | fr_dev(fp) = lp; |
@@ -565,8 +472,6 @@ int fcoe_percpu_receive_thread(void *arg) | |||
565 | continue; | 472 | continue; |
566 | } | 473 | } |
567 | 474 | ||
568 | stats = lp->dev_stats[smp_processor_id()]; | ||
569 | |||
570 | if (unlikely(debug_fcoe)) { | 475 | if (unlikely(debug_fcoe)) { |
571 | FC_DBG("skb_info: len:%d data_len:%d head:%p data:%p " | 476 | FC_DBG("skb_info: len:%d data_len:%d head:%p data:%p " |
572 | "tail:%p end:%p sum:%d dev:%s", | 477 | "tail:%p end:%p sum:%d dev:%s", |
@@ -593,13 +498,16 @@ int fcoe_percpu_receive_thread(void *arg) | |||
593 | hp = (struct fcoe_hdr *) skb_network_header(skb); | 498 | hp = (struct fcoe_hdr *) skb_network_header(skb); |
594 | fh = (struct fc_frame_header *) skb_transport_header(skb); | 499 | fh = (struct fc_frame_header *) skb_transport_header(skb); |
595 | 500 | ||
501 | stats = fc_lport_get_stats(lp); | ||
596 | if (unlikely(FC_FCOE_DECAPS_VER(hp) != FC_FCOE_VER)) { | 502 | if (unlikely(FC_FCOE_DECAPS_VER(hp) != FC_FCOE_VER)) { |
597 | if (stats) { | 503 | if (stats->ErrorFrames < 5) |
598 | if (stats->ErrorFrames < 5) | 504 | printk(KERN_WARNING "FCoE version " |
599 | FC_DBG("unknown FCoE version %x", | 505 | "mismatch: The frame has " |
600 | FC_FCOE_DECAPS_VER(hp)); | 506 | "version %x, but the " |
601 | stats->ErrorFrames++; | 507 | "initiator supports version " |
602 | } | 508 | "%x\n", FC_FCOE_DECAPS_VER(hp), |
509 | FC_FCOE_VER); | ||
510 | stats->ErrorFrames++; | ||
603 | kfree_skb(skb); | 511 | kfree_skb(skb); |
604 | continue; | 512 | continue; |
605 | } | 513 | } |
@@ -607,10 +515,8 @@ int fcoe_percpu_receive_thread(void *arg) | |||
607 | skb_pull(skb, sizeof(struct fcoe_hdr)); | 515 | skb_pull(skb, sizeof(struct fcoe_hdr)); |
608 | fr_len = skb->len - sizeof(struct fcoe_crc_eof); | 516 | fr_len = skb->len - sizeof(struct fcoe_crc_eof); |
609 | 517 | ||
610 | if (stats) { | 518 | stats->RxFrames++; |
611 | stats->RxFrames++; | 519 | stats->RxWords += fr_len / FCOE_WORD_TO_BYTE; |
612 | stats->RxWords += fr_len / FCOE_WORD_TO_BYTE; | ||
613 | } | ||
614 | 520 | ||
615 | fp = (struct fc_frame *)skb; | 521 | fp = (struct fc_frame *)skb; |
616 | fc_frame_init(fp); | 522 | fc_frame_init(fp); |
@@ -885,9 +791,8 @@ static int fcoe_device_notification(struct notifier_block *notifier, | |||
885 | if (new_link_up) | 791 | if (new_link_up) |
886 | fc_linkup(lp); | 792 | fc_linkup(lp); |
887 | else { | 793 | else { |
888 | stats = lp->dev_stats[smp_processor_id()]; | 794 | stats = fc_lport_get_stats(lp); |
889 | if (stats) | 795 | stats->LinkFailureCount++; |
890 | stats->LinkFailureCount++; | ||
891 | fc_linkdown(lp); | 796 | fc_linkdown(lp); |
892 | fcoe_clean_pending_queue(lp); | 797 | fcoe_clean_pending_queue(lp); |
893 | } | 798 | } |
@@ -1371,10 +1276,6 @@ static int __init fcoe_init(void) | |||
1371 | INIT_LIST_HEAD(&fcoe_hostlist); | 1276 | INIT_LIST_HEAD(&fcoe_hostlist); |
1372 | rwlock_init(&fcoe_hostlist_lock); | 1277 | rwlock_init(&fcoe_hostlist_lock); |
1373 | 1278 | ||
1374 | #ifdef CONFIG_HOTPLUG_CPU | ||
1375 | register_cpu_notifier(&fcoe_cpu_notifier); | ||
1376 | #endif /* CONFIG_HOTPLUG_CPU */ | ||
1377 | |||
1378 | for_each_possible_cpu(cpu) { | 1279 | for_each_possible_cpu(cpu) { |
1379 | p = &per_cpu(fcoe_percpu, cpu); | 1280 | p = &per_cpu(fcoe_percpu, cpu); |
1380 | skb_queue_head_init(&p->fcoe_rx_list); | 1281 | skb_queue_head_init(&p->fcoe_rx_list); |
@@ -1430,17 +1331,9 @@ static void __exit fcoe_exit(void) | |||
1430 | struct fcoe_percpu_s *p; | 1331 | struct fcoe_percpu_s *p; |
1431 | struct sk_buff *skb; | 1332 | struct sk_buff *skb; |
1432 | 1333 | ||
1433 | /* | ||
1434 | * Stop all call back interfaces | ||
1435 | */ | ||
1436 | #ifdef CONFIG_HOTPLUG_CPU | ||
1437 | unregister_cpu_notifier(&fcoe_cpu_notifier); | ||
1438 | #endif /* CONFIG_HOTPLUG_CPU */ | ||
1439 | fcoe_dev_cleanup(); | 1334 | fcoe_dev_cleanup(); |
1440 | 1335 | ||
1441 | /* | 1336 | /* Stop the timer */ |
1442 | * stop timer | ||
1443 | */ | ||
1444 | del_timer_sync(&fcoe_timer); | 1337 | del_timer_sync(&fcoe_timer); |
1445 | 1338 | ||
1446 | /* releases the associated fcoe transport for each lport */ | 1339 | /* releases the associated fcoe transport for each lport */ |