diff options
author | Robert Love <robert.w.love@intel.com> | 2009-03-31 18:51:50 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-04-03 10:22:58 -0400 |
commit | 582b45bc577f78b5bfff3db874594ce2d962b846 (patch) | |
tree | b0cfe95b235aeca9b967cba8446db58b8a102533 /drivers | |
parent | 5e5e92df49d4dfbef9ba981297c7f76d189376ac (diff) |
[SCSI] fcoe: Use per-CPU kernel function for dev_stats instead of an array
Remove the hotplug creation of dev_stats, we allocate for all possible CPUs
now when we allocate the lport.
v2: Durring the 2.6.30 merge window, before these patches were comitted,
'percpu_ptr' was renamed 'per_cpu_ptr'. This latest update updates this
patch for the name change.
Signed-off-by: Yi Zou <yi.zou@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/fcoe/fcoe_sw.c | 13 | ||||
-rw-r--r-- | drivers/scsi/fcoe/libfcoe.c | 143 | ||||
-rw-r--r-- | drivers/scsi/libfc/fc_fcp.c | 8 | ||||
-rw-r--r-- | drivers/scsi/libfc/fc_lport.c | 11 |
4 files changed, 31 insertions, 144 deletions
diff --git a/drivers/scsi/fcoe/fcoe_sw.c b/drivers/scsi/fcoe/fcoe_sw.c index 2bbbe3c0cc7b..a6753903fd40 100644 --- a/drivers/scsi/fcoe/fcoe_sw.c +++ b/drivers/scsi/fcoe/fcoe_sw.c | |||
@@ -113,8 +113,6 @@ static struct scsi_host_template fcoe_sw_shost_template = { | |||
113 | */ | 113 | */ |
114 | static int fcoe_sw_lport_config(struct fc_lport *lp) | 114 | static int fcoe_sw_lport_config(struct fc_lport *lp) |
115 | { | 115 | { |
116 | int i = 0; | ||
117 | |||
118 | lp->link_up = 0; | 116 | lp->link_up = 0; |
119 | lp->qfull = 0; | 117 | lp->qfull = 0; |
120 | lp->max_retry_count = 3; | 118 | lp->max_retry_count = 3; |
@@ -123,12 +121,7 @@ static int fcoe_sw_lport_config(struct fc_lport *lp) | |||
123 | lp->service_params = (FCP_SPPF_INIT_FCN | FCP_SPPF_RD_XRDY_DIS | | 121 | lp->service_params = (FCP_SPPF_INIT_FCN | FCP_SPPF_RD_XRDY_DIS | |
124 | FCP_SPPF_RETRY | FCP_SPPF_CONF_COMPL); | 122 | FCP_SPPF_RETRY | FCP_SPPF_CONF_COMPL); |
125 | 123 | ||
126 | /* | 124 | fc_lport_init_stats(lp); |
127 | * allocate per cpu stats block | ||
128 | */ | ||
129 | for_each_online_cpu(i) | ||
130 | lp->dev_stats[i] = kzalloc(sizeof(struct fcoe_dev_stats), | ||
131 | GFP_KERNEL); | ||
132 | 125 | ||
133 | /* lport fc_lport related configuration */ | 126 | /* lport fc_lport related configuration */ |
134 | fc_lport_config(lp); | 127 | fc_lport_config(lp); |
@@ -311,7 +304,6 @@ static inline int fcoe_sw_em_config(struct fc_lport *lp) | |||
311 | */ | 304 | */ |
312 | static int fcoe_sw_destroy(struct net_device *netdev) | 305 | static int fcoe_sw_destroy(struct net_device *netdev) |
313 | { | 306 | { |
314 | int cpu; | ||
315 | struct fc_lport *lp = NULL; | 307 | struct fc_lport *lp = NULL; |
316 | struct fcoe_softc *fc; | 308 | struct fcoe_softc *fc; |
317 | u8 flogi_maddr[ETH_ALEN]; | 309 | u8 flogi_maddr[ETH_ALEN]; |
@@ -363,8 +355,7 @@ static int fcoe_sw_destroy(struct net_device *netdev) | |||
363 | fcoe_clean_pending_queue(lp); | 355 | fcoe_clean_pending_queue(lp); |
364 | 356 | ||
365 | /* Free memory used by statistical counters */ | 357 | /* Free memory used by statistical counters */ |
366 | for_each_online_cpu(cpu) | 358 | fc_lport_free_stats(lp); |
367 | kfree(lp->dev_stats[cpu]); | ||
368 | 359 | ||
369 | /* Release the net_device and Scsi_Host */ | 360 | /* Release the net_device and Scsi_Host */ |
370 | dev_put(fc->real_dev); | 361 | dev_put(fc->real_dev); |
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 */ |
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index a5725f3b7ce1..0997e8b1dcea 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c | |||
@@ -407,10 +407,12 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp) | |||
407 | 407 | ||
408 | if (~crc != le32_to_cpu(fr_crc(fp))) { | 408 | if (~crc != le32_to_cpu(fr_crc(fp))) { |
409 | crc_err: | 409 | crc_err: |
410 | stats = lp->dev_stats[smp_processor_id()]; | 410 | stats = fc_lport_get_stats(lp); |
411 | stats->ErrorFrames++; | 411 | stats->ErrorFrames++; |
412 | /* FIXME - per cpu count, not total count! */ | ||
412 | if (stats->InvalidCRCCount++ < 5) | 413 | if (stats->InvalidCRCCount++ < 5) |
413 | FC_DBG("CRC error on data frame\n"); | 414 | printk(KERN_WARNING "CRC error on data frame for port (%6x)\n", |
415 | fc_host_port_id(lp->host)); | ||
414 | /* | 416 | /* |
415 | * Assume the frame is total garbage. | 417 | * Assume the frame is total garbage. |
416 | * We may have copied it over the good part | 418 | * We may have copied it over the good part |
@@ -1752,7 +1754,7 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *)) | |||
1752 | /* | 1754 | /* |
1753 | * setup the data direction | 1755 | * setup the data direction |
1754 | */ | 1756 | */ |
1755 | stats = lp->dev_stats[smp_processor_id()]; | 1757 | stats = fc_lport_get_stats(lp); |
1756 | if (sc_cmd->sc_data_direction == DMA_FROM_DEVICE) { | 1758 | if (sc_cmd->sc_data_direction == DMA_FROM_DEVICE) { |
1757 | fsp->req_flags = FC_SRB_READ; | 1759 | fsp->req_flags = FC_SRB_READ; |
1758 | stats->InputRequests++; | 1760 | stats->InputRequests++; |
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 7ef44501ecc6..b8178ef398d7 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c | |||
@@ -267,10 +267,10 @@ EXPORT_SYMBOL(fc_get_host_speed); | |||
267 | 267 | ||
268 | struct fc_host_statistics *fc_get_host_stats(struct Scsi_Host *shost) | 268 | struct fc_host_statistics *fc_get_host_stats(struct Scsi_Host *shost) |
269 | { | 269 | { |
270 | int i; | ||
271 | struct fc_host_statistics *fcoe_stats; | 270 | struct fc_host_statistics *fcoe_stats; |
272 | struct fc_lport *lp = shost_priv(shost); | 271 | struct fc_lport *lp = shost_priv(shost); |
273 | struct timespec v0, v1; | 272 | struct timespec v0, v1; |
273 | unsigned int cpu; | ||
274 | 274 | ||
275 | fcoe_stats = &lp->host_stats; | 275 | fcoe_stats = &lp->host_stats; |
276 | memset(fcoe_stats, 0, sizeof(struct fc_host_statistics)); | 276 | memset(fcoe_stats, 0, sizeof(struct fc_host_statistics)); |
@@ -279,10 +279,11 @@ struct fc_host_statistics *fc_get_host_stats(struct Scsi_Host *shost) | |||
279 | jiffies_to_timespec(lp->boot_time, &v1); | 279 | jiffies_to_timespec(lp->boot_time, &v1); |
280 | fcoe_stats->seconds_since_last_reset = (v0.tv_sec - v1.tv_sec); | 280 | fcoe_stats->seconds_since_last_reset = (v0.tv_sec - v1.tv_sec); |
281 | 281 | ||
282 | for_each_online_cpu(i) { | 282 | for_each_possible_cpu(cpu) { |
283 | struct fcoe_dev_stats *stats = lp->dev_stats[i]; | 283 | struct fcoe_dev_stats *stats; |
284 | if (stats == NULL) | 284 | |
285 | continue; | 285 | stats = per_cpu_ptr(lp->dev_stats, cpu); |
286 | |||
286 | fcoe_stats->tx_frames += stats->TxFrames; | 287 | fcoe_stats->tx_frames += stats->TxFrames; |
287 | fcoe_stats->tx_words += stats->TxWords; | 288 | fcoe_stats->tx_words += stats->TxWords; |
288 | fcoe_stats->rx_frames += stats->RxFrames; | 289 | fcoe_stats->rx_frames += stats->RxFrames; |