aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSalil <salil.mehta@huawei.com>2016-08-23 16:44:50 -0400
committerDoug Ledford <dledford@redhat.com>2016-08-25 10:05:10 -0400
commit528f1deb16e5b82e9fe161ebd8caa5983766f0f0 (patch)
treee491e9ea31baec5c606cc0f5bf69b2bfcbf6f857
parentd605916b76593417340397fe281acd2e8a953706 (diff)
IB/hns: Add support of ACPI to the Hisilicon RoCE driver
This patch is meant to add support of ACPI to the Hisilicon RoCE driver. Changes done are primarily meant to detect the type and then either use DT specific or ACPI spcific functions. Where ever possible, this patch tries to make use of Unified Device Property Interface APIs to support both DT and ACPI through single interface. This patch depends upon HNS ethernet driver to Reset RoCE. This function within HNS ethernet driver has also been enhanced to support ACPI and is part of other accompanying patch with this patch-set. NOTE: The changes in this patch are done over below branch, https://github.com/dledford/linux/tree/hns-roce Signed-off-by: Salil Mehta <salil.mehta@huawei.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_device.h2
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_eq.c2
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_hw_v1.c37
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_hw_v1.h2
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_main.c127
5 files changed, 136 insertions, 34 deletions
diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h
index 00f01be1ffa5..ea735800eb18 100644
--- a/drivers/infiniband/hw/hns/hns_roce_device.h
+++ b/drivers/infiniband/hw/hns/hns_roce_device.h
@@ -531,7 +531,7 @@ struct hns_roce_dev {
531 struct ib_device ib_dev; 531 struct ib_device ib_dev;
532 struct platform_device *pdev; 532 struct platform_device *pdev;
533 struct hns_roce_uar priv_uar; 533 struct hns_roce_uar priv_uar;
534 const char *irq_names; 534 const char *irq_names[HNS_ROCE_MAX_IRQ_NUM];
535 spinlock_t sm_lock; 535 spinlock_t sm_lock;
536 spinlock_t cq_db_lock; 536 spinlock_t cq_db_lock;
537 spinlock_t bt_cmd_lock; 537 spinlock_t bt_cmd_lock;
diff --git a/drivers/infiniband/hw/hns/hns_roce_eq.c b/drivers/infiniband/hw/hns/hns_roce_eq.c
index 5febbb4b68e7..98af7fecf2f1 100644
--- a/drivers/infiniband/hw/hns/hns_roce_eq.c
+++ b/drivers/infiniband/hw/hns/hns_roce_eq.c
@@ -713,7 +713,7 @@ int hns_roce_init_eq_table(struct hns_roce_dev *hr_dev)
713 713
714 for (j = 0; j < eq_num; j++) { 714 for (j = 0; j < eq_num; j++) {
715 ret = request_irq(eq_table->eq[j].irq, hns_roce_msi_x_interrupt, 715 ret = request_irq(eq_table->eq[j].irq, hns_roce_msi_x_interrupt,
716 0, hr_dev->irq_names, eq_table->eq + j); 716 0, hr_dev->irq_names[j], eq_table->eq + j);
717 if (ret) { 717 if (ret) {
718 dev_err(dev, "request irq error!\n"); 718 dev_err(dev, "request irq error!\n");
719 goto err_request_irq_fail; 719 goto err_request_irq_fail;
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v1.c b/drivers/infiniband/hw/hns/hns_roce_hw_v1.c
index b52f3badf855..399f5dedaf2d 100644
--- a/drivers/infiniband/hw/hns/hns_roce_hw_v1.c
+++ b/drivers/infiniband/hw/hns/hns_roce_hw_v1.c
@@ -31,6 +31,7 @@
31 */ 31 */
32 32
33#include <linux/platform_device.h> 33#include <linux/platform_device.h>
34#include <linux/acpi.h>
34#include <rdma/ib_umem.h> 35#include <rdma/ib_umem.h>
35#include "hns_roce_common.h" 36#include "hns_roce_common.h"
36#include "hns_roce_device.h" 37#include "hns_roce_device.h"
@@ -794,29 +795,47 @@ static void hns_roce_port_enable(struct hns_roce_dev *hr_dev, int enable_flag)
794 * @enable: true -- drop reset, false -- reset 795 * @enable: true -- drop reset, false -- reset
795 * return 0 - success , negative --fail 796 * return 0 - success , negative --fail
796 */ 797 */
797int hns_roce_v1_reset(struct hns_roce_dev *hr_dev, bool enable) 798int hns_roce_v1_reset(struct hns_roce_dev *hr_dev, bool dereset)
798{ 799{
799 struct device_node *dsaf_node; 800 struct device_node *dsaf_node;
800 struct device *dev = &hr_dev->pdev->dev; 801 struct device *dev = &hr_dev->pdev->dev;
801 struct device_node *np = dev->of_node; 802 struct device_node *np = dev->of_node;
803 struct fwnode_handle *fwnode;
802 int ret; 804 int ret;
803 805
804 dsaf_node = of_parse_phandle(np, "dsaf-handle", 0); 806 /* check if this is DT/ACPI case */
805 if (!dsaf_node) { 807 if (dev_of_node(dev)) {
806 dev_err(dev, "Unable to get dsaf node by dsaf-handle!\n"); 808 dsaf_node = of_parse_phandle(np, "dsaf-handle", 0);
807 return -EINVAL; 809 if (!dsaf_node) {
810 dev_err(dev, "could not find dsaf-handle\n");
811 return -EINVAL;
812 }
813 fwnode = &dsaf_node->fwnode;
814 } else if (is_acpi_device_node(dev->fwnode)) {
815 struct acpi_reference_args args;
816
817 ret = acpi_node_get_property_reference(dev->fwnode,
818 "dsaf-handle", 0, &args);
819 if (ret) {
820 dev_err(dev, "could not find dsaf-handle\n");
821 return ret;
822 }
823 fwnode = acpi_fwnode_handle(args.adev);
824 } else {
825 dev_err(dev, "cannot read data from DT or ACPI\n");
826 return -ENXIO;
808 } 827 }
809 828
810 ret = hns_dsaf_roce_reset(&dsaf_node->fwnode, false); 829 ret = hns_dsaf_roce_reset(fwnode, false);
811 if (ret) 830 if (ret)
812 return ret; 831 return ret;
813 832
814 if (enable) { 833 if (dereset) {
815 msleep(SLEEP_TIME_INTERVAL); 834 msleep(SLEEP_TIME_INTERVAL);
816 return hns_dsaf_roce_reset(&dsaf_node->fwnode, true); 835 ret = hns_dsaf_roce_reset(fwnode, true);
817 } 836 }
818 837
819 return 0; 838 return ret;
820} 839}
821 840
822void hns_roce_v1_profile(struct hns_roce_dev *hr_dev) 841void hns_roce_v1_profile(struct hns_roce_dev *hr_dev)
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v1.h b/drivers/infiniband/hw/hns/hns_roce_hw_v1.h
index 2b3bf212570b..316b592b1636 100644
--- a/drivers/infiniband/hw/hns/hns_roce_hw_v1.h
+++ b/drivers/infiniband/hw/hns/hns_roce_hw_v1.h
@@ -976,6 +976,6 @@ struct hns_roce_v1_priv {
976 struct hns_roce_raq_table raq_table; 976 struct hns_roce_raq_table raq_table;
977}; 977};
978 978
979int hns_dsaf_roce_reset(struct fwnode_handle *dsaf_fwnode, bool enable); 979int hns_dsaf_roce_reset(struct fwnode_handle *dsaf_fwnode, bool dereset);
980 980
981#endif 981#endif
diff --git a/drivers/infiniband/hw/hns/hns_roce_main.c b/drivers/infiniband/hw/hns/hns_roce_main.c
index 6ead671966bd..f64f0dde9a88 100644
--- a/drivers/infiniband/hw/hns/hns_roce_main.c
+++ b/drivers/infiniband/hw/hns/hns_roce_main.c
@@ -30,7 +30,7 @@
30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31 * SOFTWARE. 31 * SOFTWARE.
32 */ 32 */
33 33#include <linux/acpi.h>
34#include <linux/of_platform.h> 34#include <linux/of_platform.h>
35#include <rdma/ib_addr.h> 35#include <rdma/ib_addr.h>
36#include <rdma/ib_smi.h> 36#include <rdma/ib_smi.h>
@@ -694,40 +694,122 @@ error_failed_setup_mtu_gids:
694 return ret; 694 return ret;
695} 695}
696 696
697static const struct of_device_id hns_roce_of_match[] = {
698 { .compatible = "hisilicon,hns-roce-v1", .data = &hns_roce_hw_v1, },
699 {},
700};
701MODULE_DEVICE_TABLE(of, hns_roce_of_match);
702
703static const struct acpi_device_id hns_roce_acpi_match[] = {
704 { "HISI00D1", (kernel_ulong_t)&hns_roce_hw_v1 },
705 {},
706};
707MODULE_DEVICE_TABLE(acpi, hns_roce_acpi_match);
708
709static int hns_roce_node_match(struct device *dev, void *fwnode)
710{
711 return dev->fwnode == fwnode;
712}
713
714static struct
715platform_device *hns_roce_find_pdev(struct fwnode_handle *fwnode)
716{
717 struct device *dev;
718
719 /* get the 'device'corresponding to matching 'fwnode' */
720 dev = bus_find_device(&platform_bus_type, NULL,
721 fwnode, hns_roce_node_match);
722 /* get the platform device */
723 return dev ? to_platform_device(dev) : NULL;
724}
725
697static int hns_roce_get_cfg(struct hns_roce_dev *hr_dev) 726static int hns_roce_get_cfg(struct hns_roce_dev *hr_dev)
698{ 727{
699 int i; 728 int i;
729 int ret;
700 u8 phy_port; 730 u8 phy_port;
701 int port_cnt = 0; 731 int port_cnt = 0;
702 struct device *dev = &hr_dev->pdev->dev; 732 struct device *dev = &hr_dev->pdev->dev;
703 struct device_node *np = dev->of_node;
704 struct device_node *net_node; 733 struct device_node *net_node;
705 struct net_device *netdev = NULL; 734 struct net_device *netdev = NULL;
706 struct platform_device *pdev = NULL; 735 struct platform_device *pdev = NULL;
707 struct resource *res; 736 struct resource *res;
708 737
709 if (of_device_is_compatible(np, "hisilicon,hns-roce-v1")) { 738 /* check if we are compatible with the underlying SoC */
710 hr_dev->hw = &hns_roce_hw_v1; 739 if (dev_of_node(dev)) {
740 const struct of_device_id *of_id;
741
742 of_id = of_match_node(hns_roce_of_match, dev->of_node);
743 if (!of_id) {
744 dev_err(dev, "device is not compatible!\n");
745 return -ENXIO;
746 }
747 hr_dev->hw = (struct hns_roce_hw *)of_id->data;
748 if (!hr_dev->hw) {
749 dev_err(dev, "couldn't get H/W specific DT data!\n");
750 return -ENXIO;
751 }
752 } else if (is_acpi_device_node(dev->fwnode)) {
753 const struct acpi_device_id *acpi_id;
754
755 acpi_id = acpi_match_device(hns_roce_acpi_match, dev);
756 if (!acpi_id) {
757 dev_err(dev, "device is not compatible!\n");
758 return -ENXIO;
759 }
760 hr_dev->hw = (struct hns_roce_hw *) acpi_id->driver_data;
761 if (!hr_dev->hw) {
762 dev_err(dev, "couldn't get H/W specific ACPI data!\n");
763 return -ENXIO;
764 }
711 } else { 765 } else {
712 dev_err(dev, "device no compatible!\n"); 766 dev_err(dev, "can't read compatibility data from DT or ACPI\n");
713 return -EINVAL; 767 return -ENXIO;
714 } 768 }
715 769
770 /* get the mapped register base address */
716 res = platform_get_resource(hr_dev->pdev, IORESOURCE_MEM, 0); 771 res = platform_get_resource(hr_dev->pdev, IORESOURCE_MEM, 0);
772 if (!res) {
773 dev_err(dev, "memory resource not found!\n");
774 return -EINVAL;
775 }
717 hr_dev->reg_base = devm_ioremap_resource(dev, res); 776 hr_dev->reg_base = devm_ioremap_resource(dev, res);
718 if (IS_ERR(hr_dev->reg_base)) 777 if (IS_ERR(hr_dev->reg_base))
719 return PTR_ERR(hr_dev->reg_base); 778 return PTR_ERR(hr_dev->reg_base);
720 779
780 /* get the RoCE associated ethernet ports or netdevices */
721 for (i = 0; i < HNS_ROCE_MAX_PORTS; i++) { 781 for (i = 0; i < HNS_ROCE_MAX_PORTS; i++) {
722 net_node = of_parse_phandle(np, "eth-handle", i); 782 if (dev_of_node(dev)) {
723 if (net_node) { 783 net_node = of_parse_phandle(dev->of_node, "eth-handle",
784 i);
785 if (!net_node)
786 continue;
724 pdev = of_find_device_by_node(net_node); 787 pdev = of_find_device_by_node(net_node);
788 } else if (is_acpi_device_node(dev->fwnode)) {
789 struct acpi_reference_args args;
790 struct fwnode_handle *fwnode;
791
792 ret = acpi_node_get_property_reference(dev->fwnode,
793 "eth-handle",
794 i, &args);
795 if (ret)
796 continue;
797 fwnode = acpi_fwnode_handle(args.adev);
798 pdev = hns_roce_find_pdev(fwnode);
799 } else {
800 dev_err(dev, "cannot read data from DT or ACPI\n");
801 return -ENXIO;
802 }
803
804 if (pdev) {
725 netdev = platform_get_drvdata(pdev); 805 netdev = platform_get_drvdata(pdev);
726 phy_port = (u8)i; 806 phy_port = (u8)i;
727 if (netdev) { 807 if (netdev) {
728 hr_dev->iboe.netdevs[port_cnt] = netdev; 808 hr_dev->iboe.netdevs[port_cnt] = netdev;
729 hr_dev->iboe.phy_port[port_cnt] = phy_port; 809 hr_dev->iboe.phy_port[port_cnt] = phy_port;
730 } else { 810 } else {
811 dev_err(dev, "no netdev found with pdev %s\n",
812 pdev->name);
731 return -ENODEV; 813 return -ENODEV;
732 } 814 }
733 port_cnt++; 815 port_cnt++;
@@ -735,26 +817,32 @@ static int hns_roce_get_cfg(struct hns_roce_dev *hr_dev)
735 } 817 }
736 818
737 if (port_cnt == 0) { 819 if (port_cnt == 0) {
738 dev_err(dev, "Unable to get available port by eth-handle!\n"); 820 dev_err(dev, "unable to get eth-handle for available ports!\n");
739 return -EINVAL; 821 return -EINVAL;
740 } 822 }
741 823
742 hr_dev->caps.num_ports = port_cnt; 824 hr_dev->caps.num_ports = port_cnt;
743 825
744 /* Cmd issue mode: 0 is poll, 1 is event */ 826 /* cmd issue mode: 0 is poll, 1 is event */
745 hr_dev->cmd_mod = 1; 827 hr_dev->cmd_mod = 1;
746 hr_dev->loop_idc = 0; 828 hr_dev->loop_idc = 0;
747 829
830 /* read the interrupt names from the DT or ACPI */
831 ret = device_property_read_string_array(dev, "interrupt-names",
832 hr_dev->irq_names,
833 HNS_ROCE_MAX_IRQ_NUM);
834 if (ret < 0) {
835 dev_err(dev, "couldn't get interrupt names from DT or ACPI!\n");
836 return ret;
837 }
838
839 /* fetch the interrupt numbers */
748 for (i = 0; i < HNS_ROCE_MAX_IRQ_NUM; i++) { 840 for (i = 0; i < HNS_ROCE_MAX_IRQ_NUM; i++) {
749 hr_dev->irq[i] = platform_get_irq(hr_dev->pdev, i); 841 hr_dev->irq[i] = platform_get_irq(hr_dev->pdev, i);
750 if (hr_dev->irq[i] <= 0) { 842 if (hr_dev->irq[i] <= 0) {
751 dev_err(dev, "Get No.%d irq resource failed!\n", i); 843 dev_err(dev, "platform get of irq[=%d] failed!\n", i);
752 return -EINVAL; 844 return -EINVAL;
753 } 845 }
754
755 if (of_property_read_string_index(np, "interrupt-names", i,
756 &hr_dev->irq_names))
757 return -EINVAL;
758 } 846 }
759 847
760 return 0; 848 return 0;
@@ -917,7 +1005,7 @@ static int hns_roce_probe(struct platform_device *pdev)
917 1005
918 if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64ULL)) && 1006 if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64ULL)) &&
919 dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32ULL))) { 1007 dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32ULL))) {
920 dev_err(dev, "No usable DMA addressing mode\n"); 1008 dev_err(dev, "Not usable DMA addressing mode\n");
921 ret = -EIO; 1009 ret = -EIO;
922 goto error_failed_get_cfg; 1010 goto error_failed_get_cfg;
923 } 1011 }
@@ -1035,18 +1123,13 @@ static int hns_roce_remove(struct platform_device *pdev)
1035 return 0; 1123 return 0;
1036} 1124}
1037 1125
1038static const struct of_device_id hns_roce_of_match[] = {
1039 { .compatible = "hisilicon,hns-roce-v1",},
1040 {},
1041};
1042MODULE_DEVICE_TABLE(of, hns_roce_of_match);
1043
1044static struct platform_driver hns_roce_driver = { 1126static struct platform_driver hns_roce_driver = {
1045 .probe = hns_roce_probe, 1127 .probe = hns_roce_probe,
1046 .remove = hns_roce_remove, 1128 .remove = hns_roce_remove,
1047 .driver = { 1129 .driver = {
1048 .name = DRV_NAME, 1130 .name = DRV_NAME,
1049 .of_match_table = hns_roce_of_match, 1131 .of_match_table = hns_roce_of_match,
1132 .acpi_match_table = ACPI_PTR(hns_roce_acpi_match),
1050 }, 1133 },
1051}; 1134};
1052 1135