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 | |
| 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>
| -rw-r--r-- | drivers/ntb/ntb_hw.c | 4 | ||||
| -rw-r--r-- | drivers/ntb/ntb_transport.c | 121 |
2 files changed, 75 insertions, 50 deletions
diff --git a/drivers/ntb/ntb_hw.c b/drivers/ntb/ntb_hw.c index 195cc51ffbf6..2dacd19e1b8a 100644 --- a/drivers/ntb/ntb_hw.c +++ b/drivers/ntb/ntb_hw.c | |||
| @@ -1027,8 +1027,8 @@ static int ntb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1027 | ndev->mw[i].vbase = | 1027 | ndev->mw[i].vbase = |
| 1028 | ioremap_wc(pci_resource_start(pdev, MW_TO_BAR(i)), | 1028 | ioremap_wc(pci_resource_start(pdev, MW_TO_BAR(i)), |
| 1029 | ndev->mw[i].bar_sz); | 1029 | ndev->mw[i].bar_sz); |
| 1030 | dev_info(&pdev->dev, "MW %d size %d\n", i, | 1030 | dev_info(&pdev->dev, "MW %d size %llu\n", i, |
| 1031 | (u32) pci_resource_len(pdev, MW_TO_BAR(i))); | 1031 | pci_resource_len(pdev, MW_TO_BAR(i))); |
| 1032 | if (!ndev->mw[i].vbase) { | 1032 | if (!ndev->mw[i].vbase) { |
| 1033 | dev_warn(&pdev->dev, "Cannot remap BAR %d\n", | 1033 | dev_warn(&pdev->dev, "Cannot remap BAR %d\n", |
| 1034 | MW_TO_BAR(i)); | 1034 | MW_TO_BAR(i)); |
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); |
