diff options
Diffstat (limited to 'drivers/scsi/fnic/fnic_main.c')
-rw-r--r-- | drivers/scsi/fnic/fnic_main.c | 145 |
1 files changed, 132 insertions, 13 deletions
diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c index 42e15ee6e1bb..bbf81ea3a252 100644 --- a/drivers/scsi/fnic/fnic_main.c +++ b/drivers/scsi/fnic/fnic_main.c | |||
@@ -74,6 +74,10 @@ module_param(fnic_trace_max_pages, uint, S_IRUGO|S_IWUSR); | |||
74 | MODULE_PARM_DESC(fnic_trace_max_pages, "Total allocated memory pages " | 74 | MODULE_PARM_DESC(fnic_trace_max_pages, "Total allocated memory pages " |
75 | "for fnic trace buffer"); | 75 | "for fnic trace buffer"); |
76 | 76 | ||
77 | static unsigned int fnic_max_qdepth = FNIC_DFLT_QUEUE_DEPTH; | ||
78 | module_param(fnic_max_qdepth, uint, S_IRUGO|S_IWUSR); | ||
79 | MODULE_PARM_DESC(fnic_max_qdepth, "Queue depth to report for each LUN"); | ||
80 | |||
77 | static struct libfc_function_template fnic_transport_template = { | 81 | static struct libfc_function_template fnic_transport_template = { |
78 | .frame_send = fnic_send, | 82 | .frame_send = fnic_send, |
79 | .lport_set_port_id = fnic_set_port_id, | 83 | .lport_set_port_id = fnic_set_port_id, |
@@ -91,7 +95,7 @@ static int fnic_slave_alloc(struct scsi_device *sdev) | |||
91 | if (!rport || fc_remote_port_chkready(rport)) | 95 | if (!rport || fc_remote_port_chkready(rport)) |
92 | return -ENXIO; | 96 | return -ENXIO; |
93 | 97 | ||
94 | scsi_activate_tcq(sdev, FNIC_DFLT_QUEUE_DEPTH); | 98 | scsi_activate_tcq(sdev, fnic_max_qdepth); |
95 | return 0; | 99 | return 0; |
96 | } | 100 | } |
97 | 101 | ||
@@ -126,6 +130,7 @@ fnic_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout) | |||
126 | static void fnic_get_host_speed(struct Scsi_Host *shost); | 130 | static void fnic_get_host_speed(struct Scsi_Host *shost); |
127 | static struct scsi_transport_template *fnic_fc_transport; | 131 | static struct scsi_transport_template *fnic_fc_transport; |
128 | static struct fc_host_statistics *fnic_get_stats(struct Scsi_Host *); | 132 | static struct fc_host_statistics *fnic_get_stats(struct Scsi_Host *); |
133 | static void fnic_reset_host_stats(struct Scsi_Host *); | ||
129 | 134 | ||
130 | static struct fc_function_template fnic_fc_functions = { | 135 | static struct fc_function_template fnic_fc_functions = { |
131 | 136 | ||
@@ -153,6 +158,7 @@ static struct fc_function_template fnic_fc_functions = { | |||
153 | .set_rport_dev_loss_tmo = fnic_set_rport_dev_loss_tmo, | 158 | .set_rport_dev_loss_tmo = fnic_set_rport_dev_loss_tmo, |
154 | .issue_fc_host_lip = fnic_reset, | 159 | .issue_fc_host_lip = fnic_reset, |
155 | .get_fc_host_stats = fnic_get_stats, | 160 | .get_fc_host_stats = fnic_get_stats, |
161 | .reset_fc_host_stats = fnic_reset_host_stats, | ||
156 | .dd_fcrport_size = sizeof(struct fc_rport_libfc_priv), | 162 | .dd_fcrport_size = sizeof(struct fc_rport_libfc_priv), |
157 | .terminate_rport_io = fnic_terminate_rport_io, | 163 | .terminate_rport_io = fnic_terminate_rport_io, |
158 | .bsg_request = fc_lport_bsg_request, | 164 | .bsg_request = fc_lport_bsg_request, |
@@ -206,13 +212,116 @@ static struct fc_host_statistics *fnic_get_stats(struct Scsi_Host *host) | |||
206 | stats->error_frames = vs->tx.tx_errors + vs->rx.rx_errors; | 212 | stats->error_frames = vs->tx.tx_errors + vs->rx.rx_errors; |
207 | stats->dumped_frames = vs->tx.tx_drops + vs->rx.rx_drop; | 213 | stats->dumped_frames = vs->tx.tx_drops + vs->rx.rx_drop; |
208 | stats->invalid_crc_count = vs->rx.rx_crc_errors; | 214 | stats->invalid_crc_count = vs->rx.rx_crc_errors; |
209 | stats->seconds_since_last_reset = (jiffies - lp->boot_time) / HZ; | 215 | stats->seconds_since_last_reset = |
216 | (jiffies - fnic->stats_reset_time) / HZ; | ||
210 | stats->fcp_input_megabytes = div_u64(fnic->fcp_input_bytes, 1000000); | 217 | stats->fcp_input_megabytes = div_u64(fnic->fcp_input_bytes, 1000000); |
211 | stats->fcp_output_megabytes = div_u64(fnic->fcp_output_bytes, 1000000); | 218 | stats->fcp_output_megabytes = div_u64(fnic->fcp_output_bytes, 1000000); |
212 | 219 | ||
213 | return stats; | 220 | return stats; |
214 | } | 221 | } |
215 | 222 | ||
223 | /* | ||
224 | * fnic_dump_fchost_stats | ||
225 | * note : dumps fc_statistics into system logs | ||
226 | */ | ||
227 | void fnic_dump_fchost_stats(struct Scsi_Host *host, | ||
228 | struct fc_host_statistics *stats) | ||
229 | { | ||
230 | FNIC_MAIN_NOTE(KERN_NOTICE, host, | ||
231 | "fnic: seconds since last reset = %llu\n", | ||
232 | stats->seconds_since_last_reset); | ||
233 | FNIC_MAIN_NOTE(KERN_NOTICE, host, | ||
234 | "fnic: tx frames = %llu\n", | ||
235 | stats->tx_frames); | ||
236 | FNIC_MAIN_NOTE(KERN_NOTICE, host, | ||
237 | "fnic: tx words = %llu\n", | ||
238 | stats->tx_words); | ||
239 | FNIC_MAIN_NOTE(KERN_NOTICE, host, | ||
240 | "fnic: rx frames = %llu\n", | ||
241 | stats->rx_frames); | ||
242 | FNIC_MAIN_NOTE(KERN_NOTICE, host, | ||
243 | "fnic: rx words = %llu\n", | ||
244 | stats->rx_words); | ||
245 | FNIC_MAIN_NOTE(KERN_NOTICE, host, | ||
246 | "fnic: lip count = %llu\n", | ||
247 | stats->lip_count); | ||
248 | FNIC_MAIN_NOTE(KERN_NOTICE, host, | ||
249 | "fnic: nos count = %llu\n", | ||
250 | stats->nos_count); | ||
251 | FNIC_MAIN_NOTE(KERN_NOTICE, host, | ||
252 | "fnic: error frames = %llu\n", | ||
253 | stats->error_frames); | ||
254 | FNIC_MAIN_NOTE(KERN_NOTICE, host, | ||
255 | "fnic: dumped frames = %llu\n", | ||
256 | stats->dumped_frames); | ||
257 | FNIC_MAIN_NOTE(KERN_NOTICE, host, | ||
258 | "fnic: link failure count = %llu\n", | ||
259 | stats->link_failure_count); | ||
260 | FNIC_MAIN_NOTE(KERN_NOTICE, host, | ||
261 | "fnic: loss of sync count = %llu\n", | ||
262 | stats->loss_of_sync_count); | ||
263 | FNIC_MAIN_NOTE(KERN_NOTICE, host, | ||
264 | "fnic: loss of signal count = %llu\n", | ||
265 | stats->loss_of_signal_count); | ||
266 | FNIC_MAIN_NOTE(KERN_NOTICE, host, | ||
267 | "fnic: prim seq protocol err count = %llu\n", | ||
268 | stats->prim_seq_protocol_err_count); | ||
269 | FNIC_MAIN_NOTE(KERN_NOTICE, host, | ||
270 | "fnic: invalid tx word count= %llu\n", | ||
271 | stats->invalid_tx_word_count); | ||
272 | FNIC_MAIN_NOTE(KERN_NOTICE, host, | ||
273 | "fnic: invalid crc count = %llu\n", | ||
274 | stats->invalid_crc_count); | ||
275 | FNIC_MAIN_NOTE(KERN_NOTICE, host, | ||
276 | "fnic: fcp input requests = %llu\n", | ||
277 | stats->fcp_input_requests); | ||
278 | FNIC_MAIN_NOTE(KERN_NOTICE, host, | ||
279 | "fnic: fcp output requests = %llu\n", | ||
280 | stats->fcp_output_requests); | ||
281 | FNIC_MAIN_NOTE(KERN_NOTICE, host, | ||
282 | "fnic: fcp control requests = %llu\n", | ||
283 | stats->fcp_control_requests); | ||
284 | FNIC_MAIN_NOTE(KERN_NOTICE, host, | ||
285 | "fnic: fcp input megabytes = %llu\n", | ||
286 | stats->fcp_input_megabytes); | ||
287 | FNIC_MAIN_NOTE(KERN_NOTICE, host, | ||
288 | "fnic: fcp output megabytes = %llu\n", | ||
289 | stats->fcp_output_megabytes); | ||
290 | return; | ||
291 | } | ||
292 | |||
293 | /* | ||
294 | * fnic_reset_host_stats : clears host stats | ||
295 | * note : called when reset_statistics set under sysfs dir | ||
296 | */ | ||
297 | static void fnic_reset_host_stats(struct Scsi_Host *host) | ||
298 | { | ||
299 | int ret; | ||
300 | struct fc_lport *lp = shost_priv(host); | ||
301 | struct fnic *fnic = lport_priv(lp); | ||
302 | struct fc_host_statistics *stats; | ||
303 | unsigned long flags; | ||
304 | |||
305 | /* dump current stats, before clearing them */ | ||
306 | stats = fnic_get_stats(host); | ||
307 | fnic_dump_fchost_stats(host, stats); | ||
308 | |||
309 | spin_lock_irqsave(&fnic->fnic_lock, flags); | ||
310 | ret = vnic_dev_stats_clear(fnic->vdev); | ||
311 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | ||
312 | |||
313 | if (ret) { | ||
314 | FNIC_MAIN_DBG(KERN_DEBUG, fnic->lport->host, | ||
315 | "fnic: Reset vnic stats failed" | ||
316 | " 0x%x", ret); | ||
317 | return; | ||
318 | } | ||
319 | fnic->stats_reset_time = jiffies; | ||
320 | memset(stats, 0, sizeof(*stats)); | ||
321 | |||
322 | return; | ||
323 | } | ||
324 | |||
216 | void fnic_log_q_error(struct fnic *fnic) | 325 | void fnic_log_q_error(struct fnic *fnic) |
217 | { | 326 | { |
218 | unsigned int i; | 327 | unsigned int i; |
@@ -447,13 +556,6 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
447 | 556 | ||
448 | host->transportt = fnic_fc_transport; | 557 | host->transportt = fnic_fc_transport; |
449 | 558 | ||
450 | err = scsi_init_shared_tag_map(host, FNIC_MAX_IO_REQ); | ||
451 | if (err) { | ||
452 | shost_printk(KERN_ERR, fnic->lport->host, | ||
453 | "Unable to alloc shared tag map\n"); | ||
454 | goto err_out_free_hba; | ||
455 | } | ||
456 | |||
457 | /* Setup PCI resources */ | 559 | /* Setup PCI resources */ |
458 | pci_set_drvdata(pdev, fnic); | 560 | pci_set_drvdata(pdev, fnic); |
459 | 561 | ||
@@ -476,10 +578,10 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
476 | pci_set_master(pdev); | 578 | pci_set_master(pdev); |
477 | 579 | ||
478 | /* Query PCI controller on system for DMA addressing | 580 | /* Query PCI controller on system for DMA addressing |
479 | * limitation for the device. Try 40-bit first, and | 581 | * limitation for the device. Try 64-bit first, and |
480 | * fail to 32-bit. | 582 | * fail to 32-bit. |
481 | */ | 583 | */ |
482 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(40)); | 584 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); |
483 | if (err) { | 585 | if (err) { |
484 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); | 586 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); |
485 | if (err) { | 587 | if (err) { |
@@ -496,10 +598,10 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
496 | goto err_out_release_regions; | 598 | goto err_out_release_regions; |
497 | } | 599 | } |
498 | } else { | 600 | } else { |
499 | err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(40)); | 601 | err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); |
500 | if (err) { | 602 | if (err) { |
501 | shost_printk(KERN_ERR, fnic->lport->host, | 603 | shost_printk(KERN_ERR, fnic->lport->host, |
502 | "Unable to obtain 40-bit DMA " | 604 | "Unable to obtain 64-bit DMA " |
503 | "for consistent allocations, aborting.\n"); | 605 | "for consistent allocations, aborting.\n"); |
504 | goto err_out_release_regions; | 606 | goto err_out_release_regions; |
505 | } | 607 | } |
@@ -566,6 +668,22 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
566 | "aborting.\n"); | 668 | "aborting.\n"); |
567 | goto err_out_dev_close; | 669 | goto err_out_dev_close; |
568 | } | 670 | } |
671 | |||
672 | /* Configure Maximum Outstanding IO reqs*/ | ||
673 | if (fnic->config.io_throttle_count != FNIC_UCSM_DFLT_THROTTLE_CNT_BLD) { | ||
674 | host->can_queue = min_t(u32, FNIC_MAX_IO_REQ, | ||
675 | max_t(u32, FNIC_MIN_IO_REQ, | ||
676 | fnic->config.io_throttle_count)); | ||
677 | } | ||
678 | fnic->fnic_max_tag_id = host->can_queue; | ||
679 | |||
680 | err = scsi_init_shared_tag_map(host, fnic->fnic_max_tag_id); | ||
681 | if (err) { | ||
682 | shost_printk(KERN_ERR, fnic->lport->host, | ||
683 | "Unable to alloc shared tag map\n"); | ||
684 | goto err_out_dev_close; | ||
685 | } | ||
686 | |||
569 | host->max_lun = fnic->config.luns_per_tgt; | 687 | host->max_lun = fnic->config.luns_per_tgt; |
570 | host->max_id = FNIC_MAX_FCP_TARGET; | 688 | host->max_id = FNIC_MAX_FCP_TARGET; |
571 | host->max_cmd_len = FCOE_MAX_CMD_LEN; | 689 | host->max_cmd_len = FCOE_MAX_CMD_LEN; |
@@ -719,6 +837,7 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
719 | } | 837 | } |
720 | 838 | ||
721 | fc_lport_init_stats(lp); | 839 | fc_lport_init_stats(lp); |
840 | fnic->stats_reset_time = jiffies; | ||
722 | 841 | ||
723 | fc_lport_config(lp); | 842 | fc_lport_config(lp); |
724 | 843 | ||