diff options
Diffstat (limited to 'drivers/scsi/fnic/fnic_main.c')
-rw-r--r-- | drivers/scsi/fnic/fnic_main.c | 71 |
1 files changed, 42 insertions, 29 deletions
diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c index 018cc427504a..0333c7f52e66 100644 --- a/drivers/scsi/fnic/fnic_main.c +++ b/drivers/scsi/fnic/fnic_main.c | |||
@@ -25,6 +25,8 @@ | |||
25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | #include <linux/spinlock.h> | 26 | #include <linux/spinlock.h> |
27 | #include <linux/workqueue.h> | 27 | #include <linux/workqueue.h> |
28 | #include <linux/if_ether.h> | ||
29 | #include <scsi/fc/fc_fip.h> | ||
28 | #include <scsi/scsi_host.h> | 30 | #include <scsi/scsi_host.h> |
29 | #include <scsi/scsi_transport.h> | 31 | #include <scsi/scsi_transport.h> |
30 | #include <scsi/scsi_transport_fc.h> | 32 | #include <scsi/scsi_transport_fc.h> |
@@ -68,6 +70,7 @@ MODULE_PARM_DESC(fnic_log_level, "bit mask of fnic logging levels"); | |||
68 | 70 | ||
69 | static struct libfc_function_template fnic_transport_template = { | 71 | static struct libfc_function_template fnic_transport_template = { |
70 | .frame_send = fnic_send, | 72 | .frame_send = fnic_send, |
73 | .lport_set_port_id = fnic_set_port_id, | ||
71 | .fcp_abort_io = fnic_empty_scsi_cleanup, | 74 | .fcp_abort_io = fnic_empty_scsi_cleanup, |
72 | .fcp_cleanup = fnic_empty_scsi_cleanup, | 75 | .fcp_cleanup = fnic_empty_scsi_cleanup, |
73 | .exch_mgr_reset = fnic_exch_mgr_reset | 76 | .exch_mgr_reset = fnic_exch_mgr_reset |
@@ -324,9 +327,6 @@ static int fnic_cleanup(struct fnic *fnic) | |||
324 | { | 327 | { |
325 | unsigned int i; | 328 | unsigned int i; |
326 | int err; | 329 | int err; |
327 | unsigned long flags; | ||
328 | struct fc_frame *flogi = NULL; | ||
329 | struct fc_frame *flogi_resp = NULL; | ||
330 | 330 | ||
331 | vnic_dev_disable(fnic->vdev); | 331 | vnic_dev_disable(fnic->vdev); |
332 | for (i = 0; i < fnic->intr_count; i++) | 332 | for (i = 0; i < fnic->intr_count; i++) |
@@ -367,24 +367,6 @@ static int fnic_cleanup(struct fnic *fnic) | |||
367 | for (i = 0; i < fnic->intr_count; i++) | 367 | for (i = 0; i < fnic->intr_count; i++) |
368 | vnic_intr_clean(&fnic->intr[i]); | 368 | vnic_intr_clean(&fnic->intr[i]); |
369 | 369 | ||
370 | /* | ||
371 | * Remove cached flogi and flogi resp frames if any | ||
372 | * These frames are not in any queue, and therefore queue | ||
373 | * cleanup does not clean them. So clean them explicitly | ||
374 | */ | ||
375 | spin_lock_irqsave(&fnic->fnic_lock, flags); | ||
376 | flogi = fnic->flogi; | ||
377 | fnic->flogi = NULL; | ||
378 | flogi_resp = fnic->flogi_resp; | ||
379 | fnic->flogi_resp = NULL; | ||
380 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | ||
381 | |||
382 | if (flogi) | ||
383 | dev_kfree_skb(fp_skb(flogi)); | ||
384 | |||
385 | if (flogi_resp) | ||
386 | dev_kfree_skb(fp_skb(flogi_resp)); | ||
387 | |||
388 | mempool_destroy(fnic->io_req_pool); | 370 | mempool_destroy(fnic->io_req_pool); |
389 | for (i = 0; i < FNIC_SGL_NUM_CACHES; i++) | 371 | for (i = 0; i < FNIC_SGL_NUM_CACHES; i++) |
390 | mempool_destroy(fnic->io_sgl_pool[i]); | 372 | mempool_destroy(fnic->io_sgl_pool[i]); |
@@ -409,6 +391,17 @@ static void *fnic_alloc_slab_dma(gfp_t gfp_mask, void *pool_data) | |||
409 | return kmem_cache_alloc(mem, gfp_mask | GFP_ATOMIC | GFP_DMA); | 391 | return kmem_cache_alloc(mem, gfp_mask | GFP_ATOMIC | GFP_DMA); |
410 | } | 392 | } |
411 | 393 | ||
394 | /** | ||
395 | * fnic_get_mac() - get assigned data MAC address for FIP code. | ||
396 | * @lport: local port. | ||
397 | */ | ||
398 | static u8 *fnic_get_mac(struct fc_lport *lport) | ||
399 | { | ||
400 | struct fnic *fnic = lport_priv(lport); | ||
401 | |||
402 | return fnic->data_src_addr; | ||
403 | } | ||
404 | |||
412 | static int __devinit fnic_probe(struct pci_dev *pdev, | 405 | static int __devinit fnic_probe(struct pci_dev *pdev, |
413 | const struct pci_device_id *ent) | 406 | const struct pci_device_id *ent) |
414 | { | 407 | { |
@@ -433,6 +426,7 @@ static int __devinit fnic_probe(struct pci_dev *pdev, | |||
433 | host = lp->host; | 426 | host = lp->host; |
434 | fnic = lport_priv(lp); | 427 | fnic = lport_priv(lp); |
435 | fnic->lport = lp; | 428 | fnic->lport = lp; |
429 | fnic->ctlr.lp = lp; | ||
436 | 430 | ||
437 | snprintf(fnic->name, sizeof(fnic->name) - 1, "%s%d", DRV_NAME, | 431 | snprintf(fnic->name, sizeof(fnic->name) - 1, "%s%d", DRV_NAME, |
438 | host->host_no); | 432 | host->host_no); |
@@ -541,12 +535,14 @@ static int __devinit fnic_probe(struct pci_dev *pdev, | |||
541 | goto err_out_dev_close; | 535 | goto err_out_dev_close; |
542 | } | 536 | } |
543 | 537 | ||
544 | err = vnic_dev_mac_addr(fnic->vdev, fnic->mac_addr); | 538 | err = vnic_dev_mac_addr(fnic->vdev, fnic->ctlr.ctl_src_addr); |
545 | if (err) { | 539 | if (err) { |
546 | shost_printk(KERN_ERR, fnic->lport->host, | 540 | shost_printk(KERN_ERR, fnic->lport->host, |
547 | "vNIC get MAC addr failed \n"); | 541 | "vNIC get MAC addr failed \n"); |
548 | goto err_out_dev_close; | 542 | goto err_out_dev_close; |
549 | } | 543 | } |
544 | /* set data_src for point-to-point mode and to keep it non-zero */ | ||
545 | memcpy(fnic->data_src_addr, fnic->ctlr.ctl_src_addr, ETH_ALEN); | ||
550 | 546 | ||
551 | /* Get vNIC configuration */ | 547 | /* Get vNIC configuration */ |
552 | err = fnic_get_vnic_config(fnic); | 548 | err = fnic_get_vnic_config(fnic); |
@@ -615,9 +611,21 @@ static int __devinit fnic_probe(struct pci_dev *pdev, | |||
615 | fnic->vlan_hw_insert = 1; | 611 | fnic->vlan_hw_insert = 1; |
616 | fnic->vlan_id = 0; | 612 | fnic->vlan_id = 0; |
617 | 613 | ||
618 | fnic->flogi_oxid = FC_XID_UNKNOWN; | 614 | /* Initialize the FIP fcoe_ctrl struct */ |
619 | fnic->flogi = NULL; | 615 | fnic->ctlr.send = fnic_eth_send; |
620 | fnic->flogi_resp = NULL; | 616 | fnic->ctlr.update_mac = fnic_update_mac; |
617 | fnic->ctlr.get_src_addr = fnic_get_mac; | ||
618 | fcoe_ctlr_init(&fnic->ctlr); | ||
619 | if (fnic->config.flags & VFCF_FIP_CAPABLE) { | ||
620 | shost_printk(KERN_INFO, fnic->lport->host, | ||
621 | "firmware supports FIP\n"); | ||
622 | vnic_dev_add_addr(fnic->vdev, FIP_ALL_ENODE_MACS); | ||
623 | vnic_dev_add_addr(fnic->vdev, fnic->ctlr.ctl_src_addr); | ||
624 | } else { | ||
625 | shost_printk(KERN_INFO, fnic->lport->host, | ||
626 | "firmware uses non-FIP mode\n"); | ||
627 | fnic->ctlr.mode = FIP_ST_NON_FIP; | ||
628 | } | ||
621 | fnic->state = FNIC_IN_FC_MODE; | 629 | fnic->state = FNIC_IN_FC_MODE; |
622 | 630 | ||
623 | /* Enable hardware stripping of vlan header on ingress */ | 631 | /* Enable hardware stripping of vlan header on ingress */ |
@@ -708,6 +716,7 @@ static int __devinit fnic_probe(struct pci_dev *pdev, | |||
708 | INIT_WORK(&fnic->link_work, fnic_handle_link); | 716 | INIT_WORK(&fnic->link_work, fnic_handle_link); |
709 | INIT_WORK(&fnic->frame_work, fnic_handle_frame); | 717 | INIT_WORK(&fnic->frame_work, fnic_handle_frame); |
710 | skb_queue_head_init(&fnic->frame_queue); | 718 | skb_queue_head_init(&fnic->frame_queue); |
719 | skb_queue_head_init(&fnic->tx_queue); | ||
711 | 720 | ||
712 | /* Enable all queues */ | 721 | /* Enable all queues */ |
713 | for (i = 0; i < fnic->raw_wq_count; i++) | 722 | for (i = 0; i < fnic->raw_wq_count; i++) |
@@ -738,8 +747,8 @@ static int __devinit fnic_probe(struct pci_dev *pdev, | |||
738 | err_out_free_exch_mgr: | 747 | err_out_free_exch_mgr: |
739 | fc_exch_mgr_free(lp); | 748 | fc_exch_mgr_free(lp); |
740 | err_out_remove_scsi_host: | 749 | err_out_remove_scsi_host: |
741 | fc_remove_host(fnic->lport->host); | 750 | fc_remove_host(lp->host); |
742 | scsi_remove_host(fnic->lport->host); | 751 | scsi_remove_host(lp->host); |
743 | err_out_free_rq_buf: | 752 | err_out_free_rq_buf: |
744 | for (i = 0; i < fnic->rq_count; i++) | 753 | for (i = 0; i < fnic->rq_count; i++) |
745 | vnic_rq_clean(&fnic->rq[i], fnic_free_rq_buf); | 754 | vnic_rq_clean(&fnic->rq[i], fnic_free_rq_buf); |
@@ -773,6 +782,7 @@ err_out: | |||
773 | static void __devexit fnic_remove(struct pci_dev *pdev) | 782 | static void __devexit fnic_remove(struct pci_dev *pdev) |
774 | { | 783 | { |
775 | struct fnic *fnic = pci_get_drvdata(pdev); | 784 | struct fnic *fnic = pci_get_drvdata(pdev); |
785 | struct fc_lport *lp = fnic->lport; | ||
776 | unsigned long flags; | 786 | unsigned long flags; |
777 | 787 | ||
778 | /* | 788 | /* |
@@ -794,6 +804,7 @@ static void __devexit fnic_remove(struct pci_dev *pdev) | |||
794 | */ | 804 | */ |
795 | flush_workqueue(fnic_event_queue); | 805 | flush_workqueue(fnic_event_queue); |
796 | skb_queue_purge(&fnic->frame_queue); | 806 | skb_queue_purge(&fnic->frame_queue); |
807 | skb_queue_purge(&fnic->tx_queue); | ||
797 | 808 | ||
798 | /* | 809 | /* |
799 | * Log off the fabric. This stops all remote ports, dns port, | 810 | * Log off the fabric. This stops all remote ports, dns port, |
@@ -806,7 +817,8 @@ static void __devexit fnic_remove(struct pci_dev *pdev) | |||
806 | fnic->in_remove = 1; | 817 | fnic->in_remove = 1; |
807 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | 818 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); |
808 | 819 | ||
809 | fc_lport_destroy(fnic->lport); | 820 | fcoe_ctlr_destroy(&fnic->ctlr); |
821 | fc_lport_destroy(lp); | ||
810 | 822 | ||
811 | /* | 823 | /* |
812 | * This stops the fnic device, masks all interrupts. Completed | 824 | * This stops the fnic device, masks all interrupts. Completed |
@@ -816,6 +828,7 @@ static void __devexit fnic_remove(struct pci_dev *pdev) | |||
816 | fnic_cleanup(fnic); | 828 | fnic_cleanup(fnic); |
817 | 829 | ||
818 | BUG_ON(!skb_queue_empty(&fnic->frame_queue)); | 830 | BUG_ON(!skb_queue_empty(&fnic->frame_queue)); |
831 | BUG_ON(!skb_queue_empty(&fnic->tx_queue)); | ||
819 | 832 | ||
820 | spin_lock_irqsave(&fnic_list_lock, flags); | 833 | spin_lock_irqsave(&fnic_list_lock, flags); |
821 | list_del(&fnic->list); | 834 | list_del(&fnic->list); |
@@ -834,7 +847,7 @@ static void __devexit fnic_remove(struct pci_dev *pdev) | |||
834 | pci_release_regions(pdev); | 847 | pci_release_regions(pdev); |
835 | pci_disable_device(pdev); | 848 | pci_disable_device(pdev); |
836 | pci_set_drvdata(pdev, NULL); | 849 | pci_set_drvdata(pdev, NULL); |
837 | scsi_host_put(fnic->lport->host); | 850 | scsi_host_put(lp->host); |
838 | } | 851 | } |
839 | 852 | ||
840 | static struct pci_driver fnic_driver = { | 853 | static struct pci_driver fnic_driver = { |