diff options
author | Jon Mason <jon.mason@intel.com> | 2013-01-30 13:40:52 -0500 |
---|---|---|
committer | Jon Mason <jon.mason@intel.com> | 2013-05-15 13:57:40 -0400 |
commit | 113fc505b83b2d16e820ca74fa07f99a34877b1d (patch) | |
tree | b128844cff7e10850abcb8fa363999c8c1d09b22 /drivers/ntb/ntb_transport.c | |
parent | cc0f868d8adef7bdc12cda132654870086d766bc (diff) |
NTB: Handle 64bit BAR sizes
64bit BAR sizes are permissible with an NTB device. To support them
various modifications and clean-ups were required, most significantly
using 2 32bit scratch pad registers for each BAR.
Also, modify the driver to allow more than 2 Memory Windows.
Signed-off-by: Jon Mason <jon.mason@intel.com>
Diffstat (limited to 'drivers/ntb/ntb_transport.c')
-rw-r--r-- | drivers/ntb/ntb_transport.c | 121 |
1 files changed, 73 insertions, 48 deletions
diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c index 00f5e80dee35..79a3203eccd9 100644 --- a/drivers/ntb/ntb_transport.c +++ b/drivers/ntb/ntb_transport.c | |||
@@ -58,7 +58,7 @@ | |||
58 | #include <linux/ntb.h> | 58 | #include <linux/ntb.h> |
59 | #include "ntb_hw.h" | 59 | #include "ntb_hw.h" |
60 | 60 | ||
61 | #define NTB_TRANSPORT_VERSION 2 | 61 | #define NTB_TRANSPORT_VERSION 3 |
62 | 62 | ||
63 | static unsigned int transport_mtu = 0x401E; | 63 | static unsigned int transport_mtu = 0x401E; |
64 | module_param(transport_mtu, uint, 0644); | 64 | module_param(transport_mtu, uint, 0644); |
@@ -173,10 +173,13 @@ struct ntb_payload_header { | |||
173 | 173 | ||
174 | enum { | 174 | enum { |
175 | VERSION = 0, | 175 | VERSION = 0, |
176 | MW0_SZ, | ||
177 | MW1_SZ, | ||
178 | NUM_QPS, | ||
179 | QP_LINKS, | 176 | QP_LINKS, |
177 | NUM_QPS, | ||
178 | NUM_MWS, | ||
179 | MW0_SZ_HIGH, | ||
180 | MW0_SZ_LOW, | ||
181 | MW1_SZ_HIGH, | ||
182 | MW1_SZ_LOW, | ||
180 | MAX_SPAD, | 183 | MAX_SPAD, |
181 | }; | 184 | }; |
182 | 185 | ||
@@ -526,6 +529,18 @@ static int ntb_set_mw(struct ntb_transport *nt, int num_mw, unsigned int size) | |||
526 | return 0; | 529 | return 0; |
527 | } | 530 | } |
528 | 531 | ||
532 | static void ntb_free_mw(struct ntb_transport *nt, int num_mw) | ||
533 | { | ||
534 | struct ntb_transport_mw *mw = &nt->mw[num_mw]; | ||
535 | struct pci_dev *pdev = ntb_query_pdev(nt->ndev); | ||
536 | |||
537 | if (!mw->virt_addr) | ||
538 | return; | ||
539 | |||
540 | dma_free_coherent(&pdev->dev, mw->size, mw->virt_addr, mw->dma_addr); | ||
541 | mw->virt_addr = NULL; | ||
542 | } | ||
543 | |||
529 | static void ntb_qp_link_cleanup(struct work_struct *work) | 544 | static void ntb_qp_link_cleanup(struct work_struct *work) |
530 | { | 545 | { |
531 | struct ntb_transport_qp *qp = container_of(work, | 546 | struct ntb_transport_qp *qp = container_of(work, |
@@ -604,25 +619,31 @@ static void ntb_transport_link_work(struct work_struct *work) | |||
604 | u32 val; | 619 | u32 val; |
605 | int rc, i; | 620 | int rc, i; |
606 | 621 | ||
607 | /* send the local info */ | 622 | /* send the local info, in the opposite order of the way we read it */ |
608 | rc = ntb_write_remote_spad(ndev, VERSION, NTB_TRANSPORT_VERSION); | 623 | for (i = 0; i < NTB_NUM_MW; i++) { |
609 | if (rc) { | 624 | rc = ntb_write_remote_spad(ndev, MW0_SZ_HIGH + (i * 2), |
610 | dev_err(&pdev->dev, "Error writing %x to remote spad %d\n", | 625 | ntb_get_mw_size(ndev, i) >> 32); |
611 | 0, VERSION); | 626 | if (rc) { |
612 | goto out; | 627 | dev_err(&pdev->dev, "Error writing %u to remote spad %d\n", |
613 | } | 628 | (u32)(ntb_get_mw_size(ndev, i) >> 32), |
629 | MW0_SZ_HIGH + (i * 2)); | ||
630 | goto out; | ||
631 | } | ||
614 | 632 | ||
615 | rc = ntb_write_remote_spad(ndev, MW0_SZ, ntb_get_mw_size(ndev, 0)); | 633 | rc = ntb_write_remote_spad(ndev, MW0_SZ_LOW + (i * 2), |
616 | if (rc) { | 634 | (u32) ntb_get_mw_size(ndev, i)); |
617 | dev_err(&pdev->dev, "Error writing %x to remote spad %d\n", | 635 | if (rc) { |
618 | (u32) ntb_get_mw_size(ndev, 0), MW0_SZ); | 636 | dev_err(&pdev->dev, "Error writing %u to remote spad %d\n", |
619 | goto out; | 637 | (u32) ntb_get_mw_size(ndev, i), |
638 | MW0_SZ_LOW + (i * 2)); | ||
639 | goto out; | ||
640 | } | ||
620 | } | 641 | } |
621 | 642 | ||
622 | rc = ntb_write_remote_spad(ndev, MW1_SZ, ntb_get_mw_size(ndev, 1)); | 643 | rc = ntb_write_remote_spad(ndev, NUM_MWS, NTB_NUM_MW); |
623 | if (rc) { | 644 | if (rc) { |
624 | dev_err(&pdev->dev, "Error writing %x to remote spad %d\n", | 645 | dev_err(&pdev->dev, "Error writing %x to remote spad %d\n", |
625 | (u32) ntb_get_mw_size(ndev, 1), MW1_SZ); | 646 | NTB_NUM_MW, NUM_MWS); |
626 | goto out; | 647 | goto out; |
627 | } | 648 | } |
628 | 649 | ||
@@ -633,16 +654,10 @@ static void ntb_transport_link_work(struct work_struct *work) | |||
633 | goto out; | 654 | goto out; |
634 | } | 655 | } |
635 | 656 | ||
636 | rc = ntb_read_local_spad(nt->ndev, QP_LINKS, &val); | 657 | rc = ntb_write_remote_spad(ndev, VERSION, NTB_TRANSPORT_VERSION); |
637 | if (rc) { | ||
638 | dev_err(&pdev->dev, "Error reading spad %d\n", QP_LINKS); | ||
639 | goto out; | ||
640 | } | ||
641 | |||
642 | rc = ntb_write_remote_spad(ndev, QP_LINKS, val); | ||
643 | if (rc) { | 658 | if (rc) { |
644 | dev_err(&pdev->dev, "Error writing %x to remote spad %d\n", | 659 | dev_err(&pdev->dev, "Error writing %x to remote spad %d\n", |
645 | val, QP_LINKS); | 660 | NTB_TRANSPORT_VERSION, VERSION); |
646 | goto out; | 661 | goto out; |
647 | } | 662 | } |
648 | 663 | ||
@@ -667,33 +682,43 @@ static void ntb_transport_link_work(struct work_struct *work) | |||
667 | goto out; | 682 | goto out; |
668 | dev_dbg(&pdev->dev, "Remote max number of qps = %d\n", val); | 683 | dev_dbg(&pdev->dev, "Remote max number of qps = %d\n", val); |
669 | 684 | ||
670 | rc = ntb_read_remote_spad(ndev, MW0_SZ, &val); | 685 | rc = ntb_read_remote_spad(ndev, NUM_MWS, &val); |
671 | if (rc) { | 686 | if (rc) { |
672 | dev_err(&pdev->dev, "Error reading remote spad %d\n", MW0_SZ); | 687 | dev_err(&pdev->dev, "Error reading remote spad %d\n", NUM_MWS); |
673 | goto out; | 688 | goto out; |
674 | } | 689 | } |
675 | 690 | ||
676 | if (!val) | 691 | if (val != NTB_NUM_MW) |
677 | goto out; | 692 | goto out; |
678 | dev_dbg(&pdev->dev, "Remote MW0 size = %d\n", val); | 693 | dev_dbg(&pdev->dev, "Remote number of mws = %d\n", val); |
679 | 694 | ||
680 | rc = ntb_set_mw(nt, 0, val); | 695 | for (i = 0; i < NTB_NUM_MW; i++) { |
681 | if (rc) | 696 | u64 val64; |
682 | goto out; | ||
683 | 697 | ||
684 | rc = ntb_read_remote_spad(ndev, MW1_SZ, &val); | 698 | rc = ntb_read_remote_spad(ndev, MW0_SZ_HIGH + (i * 2), &val); |
685 | if (rc) { | 699 | if (rc) { |
686 | dev_err(&pdev->dev, "Error reading remote spad %d\n", MW1_SZ); | 700 | dev_err(&pdev->dev, "Error reading remote spad %d\n", |
687 | goto out; | 701 | MW0_SZ_HIGH + (i * 2)); |
688 | } | 702 | goto out1; |
703 | } | ||
689 | 704 | ||
690 | if (!val) | 705 | val64 = (u64) val << 32; |
691 | goto out; | ||
692 | dev_dbg(&pdev->dev, "Remote MW1 size = %d\n", val); | ||
693 | 706 | ||
694 | rc = ntb_set_mw(nt, 1, val); | 707 | rc = ntb_read_remote_spad(ndev, MW0_SZ_LOW + (i * 2), &val); |
695 | if (rc) | 708 | if (rc) { |
696 | goto out; | 709 | dev_err(&pdev->dev, "Error reading remote spad %d\n", |
710 | MW0_SZ_LOW + (i * 2)); | ||
711 | goto out1; | ||
712 | } | ||
713 | |||
714 | val64 |= val; | ||
715 | |||
716 | dev_dbg(&pdev->dev, "Remote MW%d size = %llu\n", i, val64); | ||
717 | |||
718 | rc = ntb_set_mw(nt, i, val64); | ||
719 | if (rc) | ||
720 | goto out1; | ||
721 | } | ||
697 | 722 | ||
698 | nt->transport_link = NTB_LINK_UP; | 723 | nt->transport_link = NTB_LINK_UP; |
699 | 724 | ||
@@ -708,6 +733,9 @@ static void ntb_transport_link_work(struct work_struct *work) | |||
708 | 733 | ||
709 | return; | 734 | return; |
710 | 735 | ||
736 | out1: | ||
737 | for (i = 0; i < NTB_NUM_MW; i++) | ||
738 | ntb_free_mw(nt, i); | ||
711 | out: | 739 | out: |
712 | if (ntb_hw_link_status(ndev)) | 740 | if (ntb_hw_link_status(ndev)) |
713 | schedule_delayed_work(&nt->link_work, | 741 | schedule_delayed_work(&nt->link_work, |
@@ -897,10 +925,7 @@ void ntb_transport_free(void *transport) | |||
897 | pdev = ntb_query_pdev(nt->ndev); | 925 | pdev = ntb_query_pdev(nt->ndev); |
898 | 926 | ||
899 | for (i = 0; i < NTB_NUM_MW; i++) | 927 | for (i = 0; i < NTB_NUM_MW; i++) |
900 | if (nt->mw[i].virt_addr) | 928 | ntb_free_mw(nt, i); |
901 | dma_free_coherent(&pdev->dev, nt->mw[i].size, | ||
902 | nt->mw[i].virt_addr, | ||
903 | nt->mw[i].dma_addr); | ||
904 | 929 | ||
905 | kfree(nt->qps); | 930 | kfree(nt->qps); |
906 | ntb_unregister_transport(nt->ndev); | 931 | ntb_unregister_transport(nt->ndev); |