|
@@ -30,7 +30,7 @@
|
|
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
* SOFTWARE.
|
|
|
*/
|
|
|
-
|
|
|
+#include <linux/acpi.h>
|
|
|
#include <linux/of_platform.h>
|
|
|
#include <rdma/ib_addr.h>
|
|
|
#include <rdma/ib_smi.h>
|
|
@@ -694,40 +694,122 @@ error_failed_setup_mtu_gids:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+static const struct of_device_id hns_roce_of_match[] = {
|
|
|
+ { .compatible = "hisilicon,hns-roce-v1", .data = &hns_roce_hw_v1, },
|
|
|
+ {},
|
|
|
+};
|
|
|
+MODULE_DEVICE_TABLE(of, hns_roce_of_match);
|
|
|
+
|
|
|
+static const struct acpi_device_id hns_roce_acpi_match[] = {
|
|
|
+ { "HISI00D1", (kernel_ulong_t)&hns_roce_hw_v1 },
|
|
|
+ {},
|
|
|
+};
|
|
|
+MODULE_DEVICE_TABLE(acpi, hns_roce_acpi_match);
|
|
|
+
|
|
|
+static int hns_roce_node_match(struct device *dev, void *fwnode)
|
|
|
+{
|
|
|
+ return dev->fwnode == fwnode;
|
|
|
+}
|
|
|
+
|
|
|
+static struct
|
|
|
+platform_device *hns_roce_find_pdev(struct fwnode_handle *fwnode)
|
|
|
+{
|
|
|
+ struct device *dev;
|
|
|
+
|
|
|
+ /* get the 'device'corresponding to matching 'fwnode' */
|
|
|
+ dev = bus_find_device(&platform_bus_type, NULL,
|
|
|
+ fwnode, hns_roce_node_match);
|
|
|
+ /* get the platform device */
|
|
|
+ return dev ? to_platform_device(dev) : NULL;
|
|
|
+}
|
|
|
+
|
|
|
static int hns_roce_get_cfg(struct hns_roce_dev *hr_dev)
|
|
|
{
|
|
|
int i;
|
|
|
+ int ret;
|
|
|
u8 phy_port;
|
|
|
int port_cnt = 0;
|
|
|
struct device *dev = &hr_dev->pdev->dev;
|
|
|
- struct device_node *np = dev->of_node;
|
|
|
struct device_node *net_node;
|
|
|
struct net_device *netdev = NULL;
|
|
|
struct platform_device *pdev = NULL;
|
|
|
struct resource *res;
|
|
|
|
|
|
- if (of_device_is_compatible(np, "hisilicon,hns-roce-v1")) {
|
|
|
- hr_dev->hw = &hns_roce_hw_v1;
|
|
|
+ /* check if we are compatible with the underlying SoC */
|
|
|
+ if (dev_of_node(dev)) {
|
|
|
+ const struct of_device_id *of_id;
|
|
|
+
|
|
|
+ of_id = of_match_node(hns_roce_of_match, dev->of_node);
|
|
|
+ if (!of_id) {
|
|
|
+ dev_err(dev, "device is not compatible!\n");
|
|
|
+ return -ENXIO;
|
|
|
+ }
|
|
|
+ hr_dev->hw = (struct hns_roce_hw *)of_id->data;
|
|
|
+ if (!hr_dev->hw) {
|
|
|
+ dev_err(dev, "couldn't get H/W specific DT data!\n");
|
|
|
+ return -ENXIO;
|
|
|
+ }
|
|
|
+ } else if (is_acpi_device_node(dev->fwnode)) {
|
|
|
+ const struct acpi_device_id *acpi_id;
|
|
|
+
|
|
|
+ acpi_id = acpi_match_device(hns_roce_acpi_match, dev);
|
|
|
+ if (!acpi_id) {
|
|
|
+ dev_err(dev, "device is not compatible!\n");
|
|
|
+ return -ENXIO;
|
|
|
+ }
|
|
|
+ hr_dev->hw = (struct hns_roce_hw *) acpi_id->driver_data;
|
|
|
+ if (!hr_dev->hw) {
|
|
|
+ dev_err(dev, "couldn't get H/W specific ACPI data!\n");
|
|
|
+ return -ENXIO;
|
|
|
+ }
|
|
|
} else {
|
|
|
- dev_err(dev, "device no compatible!\n");
|
|
|
- return -EINVAL;
|
|
|
+ dev_err(dev, "can't read compatibility data from DT or ACPI\n");
|
|
|
+ return -ENXIO;
|
|
|
}
|
|
|
|
|
|
+ /* get the mapped register base address */
|
|
|
res = platform_get_resource(hr_dev->pdev, IORESOURCE_MEM, 0);
|
|
|
+ if (!res) {
|
|
|
+ dev_err(dev, "memory resource not found!\n");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
hr_dev->reg_base = devm_ioremap_resource(dev, res);
|
|
|
if (IS_ERR(hr_dev->reg_base))
|
|
|
return PTR_ERR(hr_dev->reg_base);
|
|
|
|
|
|
+ /* get the RoCE associated ethernet ports or netdevices */
|
|
|
for (i = 0; i < HNS_ROCE_MAX_PORTS; i++) {
|
|
|
- net_node = of_parse_phandle(np, "eth-handle", i);
|
|
|
- if (net_node) {
|
|
|
+ if (dev_of_node(dev)) {
|
|
|
+ net_node = of_parse_phandle(dev->of_node, "eth-handle",
|
|
|
+ i);
|
|
|
+ if (!net_node)
|
|
|
+ continue;
|
|
|
pdev = of_find_device_by_node(net_node);
|
|
|
+ } else if (is_acpi_device_node(dev->fwnode)) {
|
|
|
+ struct acpi_reference_args args;
|
|
|
+ struct fwnode_handle *fwnode;
|
|
|
+
|
|
|
+ ret = acpi_node_get_property_reference(dev->fwnode,
|
|
|
+ "eth-handle",
|
|
|
+ i, &args);
|
|
|
+ if (ret)
|
|
|
+ continue;
|
|
|
+ fwnode = acpi_fwnode_handle(args.adev);
|
|
|
+ pdev = hns_roce_find_pdev(fwnode);
|
|
|
+ } else {
|
|
|
+ dev_err(dev, "cannot read data from DT or ACPI\n");
|
|
|
+ return -ENXIO;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (pdev) {
|
|
|
netdev = platform_get_drvdata(pdev);
|
|
|
phy_port = (u8)i;
|
|
|
if (netdev) {
|
|
|
hr_dev->iboe.netdevs[port_cnt] = netdev;
|
|
|
hr_dev->iboe.phy_port[port_cnt] = phy_port;
|
|
|
} else {
|
|
|
+ dev_err(dev, "no netdev found with pdev %s\n",
|
|
|
+ pdev->name);
|
|
|
return -ENODEV;
|
|
|
}
|
|
|
port_cnt++;
|
|
@@ -735,26 +817,32 @@ static int hns_roce_get_cfg(struct hns_roce_dev *hr_dev)
|
|
|
}
|
|
|
|
|
|
if (port_cnt == 0) {
|
|
|
- dev_err(dev, "Unable to get available port by eth-handle!\n");
|
|
|
+ dev_err(dev, "unable to get eth-handle for available ports!\n");
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
hr_dev->caps.num_ports = port_cnt;
|
|
|
|
|
|
- /* Cmd issue mode: 0 is poll, 1 is event */
|
|
|
+ /* cmd issue mode: 0 is poll, 1 is event */
|
|
|
hr_dev->cmd_mod = 1;
|
|
|
hr_dev->loop_idc = 0;
|
|
|
|
|
|
+ /* read the interrupt names from the DT or ACPI */
|
|
|
+ ret = device_property_read_string_array(dev, "interrupt-names",
|
|
|
+ hr_dev->irq_names,
|
|
|
+ HNS_ROCE_MAX_IRQ_NUM);
|
|
|
+ if (ret < 0) {
|
|
|
+ dev_err(dev, "couldn't get interrupt names from DT or ACPI!\n");
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* fetch the interrupt numbers */
|
|
|
for (i = 0; i < HNS_ROCE_MAX_IRQ_NUM; i++) {
|
|
|
hr_dev->irq[i] = platform_get_irq(hr_dev->pdev, i);
|
|
|
if (hr_dev->irq[i] <= 0) {
|
|
|
- dev_err(dev, "Get No.%d irq resource failed!\n", i);
|
|
|
+ dev_err(dev, "platform get of irq[=%d] failed!\n", i);
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
-
|
|
|
- if (of_property_read_string_index(np, "interrupt-names", i,
|
|
|
- &hr_dev->irq_names))
|
|
|
- return -EINVAL;
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
@@ -917,7 +1005,7 @@ static int hns_roce_probe(struct platform_device *pdev)
|
|
|
|
|
|
if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64ULL)) &&
|
|
|
dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32ULL))) {
|
|
|
- dev_err(dev, "No usable DMA addressing mode\n");
|
|
|
+ dev_err(dev, "Not usable DMA addressing mode\n");
|
|
|
ret = -EIO;
|
|
|
goto error_failed_get_cfg;
|
|
|
}
|
|
@@ -1035,18 +1123,13 @@ static int hns_roce_remove(struct platform_device *pdev)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static const struct of_device_id hns_roce_of_match[] = {
|
|
|
- { .compatible = "hisilicon,hns-roce-v1",},
|
|
|
- {},
|
|
|
-};
|
|
|
-MODULE_DEVICE_TABLE(of, hns_roce_of_match);
|
|
|
-
|
|
|
static struct platform_driver hns_roce_driver = {
|
|
|
.probe = hns_roce_probe,
|
|
|
.remove = hns_roce_remove,
|
|
|
.driver = {
|
|
|
.name = DRV_NAME,
|
|
|
.of_match_table = hns_roce_of_match,
|
|
|
+ .acpi_match_table = ACPI_PTR(hns_roce_acpi_match),
|
|
|
},
|
|
|
};
|
|
|
|