|
@@ -57,6 +57,7 @@ int hns_get_gid_index(struct hns_roce_dev *hr_dev, u8 port, int gid_index)
|
|
|
{
|
|
|
return gid_index * hr_dev->caps.num_ports + port;
|
|
|
}
|
|
|
+EXPORT_SYMBOL_GPL(hns_get_gid_index);
|
|
|
|
|
|
static void hns_roce_set_mac(struct hns_roce_dev *hr_dev, u8 port, u8 *addr)
|
|
|
{
|
|
@@ -174,8 +175,9 @@ static int hns_roce_setup_mtu_mac(struct hns_roce_dev *hr_dev)
|
|
|
u8 i;
|
|
|
|
|
|
for (i = 0; i < hr_dev->caps.num_ports; i++) {
|
|
|
- hr_dev->hw->set_mtu(hr_dev, hr_dev->iboe.phy_port[i],
|
|
|
- hr_dev->caps.max_mtu);
|
|
|
+ if (hr_dev->hw->set_mtu)
|
|
|
+ hr_dev->hw->set_mtu(hr_dev, hr_dev->iboe.phy_port[i],
|
|
|
+ hr_dev->caps.max_mtu);
|
|
|
hns_roce_set_mac(hr_dev, i, hr_dev->iboe.netdevs[i]->dev_addr);
|
|
|
}
|
|
|
|
|
@@ -531,169 +533,6 @@ error_failed_setup_mtu_mac:
|
|
|
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 *net_node;
|
|
|
- struct net_device *netdev = NULL;
|
|
|
- struct platform_device *pdev = NULL;
|
|
|
- struct resource *res;
|
|
|
-
|
|
|
- /* 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, "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);
|
|
|
-
|
|
|
- /* read the node_guid of IB device from the DT or ACPI */
|
|
|
- ret = device_property_read_u8_array(dev, "node-guid",
|
|
|
- (u8 *)&hr_dev->ib_dev.node_guid,
|
|
|
- GUID_LEN);
|
|
|
- if (ret) {
|
|
|
- dev_err(dev, "couldn't get node_guid from DT or ACPI!\n");
|
|
|
- return ret;
|
|
|
- }
|
|
|
-
|
|
|
- /* get the RoCE associated ethernet ports or netdevices */
|
|
|
- for (i = 0; i < HNS_ROCE_MAX_PORTS; i++) {
|
|
|
- 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++;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (port_cnt == 0) {
|
|
|
- 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 */
|
|
|
- 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, "platform get of irq[=%d] failed!\n", i);
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
static int hns_roce_init_hem(struct hns_roce_dev *hr_dev)
|
|
|
{
|
|
|
int ret;
|
|
@@ -826,42 +665,17 @@ err_uar_table_free:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * hns_roce_probe - RoCE driver entrance
|
|
|
- * @pdev: pointer to platform device
|
|
|
- * Return : int
|
|
|
- *
|
|
|
- */
|
|
|
-static int hns_roce_probe(struct platform_device *pdev)
|
|
|
+int hns_roce_init(struct hns_roce_dev *hr_dev)
|
|
|
{
|
|
|
int ret;
|
|
|
- struct hns_roce_dev *hr_dev;
|
|
|
- struct device *dev = &pdev->dev;
|
|
|
-
|
|
|
- hr_dev = (struct hns_roce_dev *)ib_alloc_device(sizeof(*hr_dev));
|
|
|
- if (!hr_dev)
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
- hr_dev->pdev = pdev;
|
|
|
- platform_set_drvdata(pdev, hr_dev);
|
|
|
-
|
|
|
- if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64ULL)) &&
|
|
|
- dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32ULL))) {
|
|
|
- dev_err(dev, "Not usable DMA addressing mode\n");
|
|
|
- ret = -EIO;
|
|
|
- goto error_failed_get_cfg;
|
|
|
- }
|
|
|
-
|
|
|
- ret = hns_roce_get_cfg(hr_dev);
|
|
|
- if (ret) {
|
|
|
- dev_err(dev, "Get Configuration failed!\n");
|
|
|
- goto error_failed_get_cfg;
|
|
|
- }
|
|
|
+ struct device *dev = &hr_dev->pdev->dev;
|
|
|
|
|
|
- ret = hr_dev->hw->reset(hr_dev, true);
|
|
|
- if (ret) {
|
|
|
- dev_err(dev, "Reset RoCE engine failed!\n");
|
|
|
- goto error_failed_get_cfg;
|
|
|
+ if (hr_dev->hw->reset) {
|
|
|
+ ret = hr_dev->hw->reset(hr_dev, true);
|
|
|
+ if (ret) {
|
|
|
+ dev_err(dev, "Reset RoCE engine failed!\n");
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
hr_dev->hw->hw_profile(hr_dev);
|
|
@@ -872,10 +686,12 @@ static int hns_roce_probe(struct platform_device *pdev)
|
|
|
goto error_failed_cmd_init;
|
|
|
}
|
|
|
|
|
|
- ret = hns_roce_init_eq_table(hr_dev);
|
|
|
- if (ret) {
|
|
|
- dev_err(dev, "eq init failed!\n");
|
|
|
- goto error_failed_eq_table;
|
|
|
+ if (hr_dev->cmd_mod) {
|
|
|
+ ret = hns_roce_init_eq_table(hr_dev);
|
|
|
+ if (ret) {
|
|
|
+ dev_err(dev, "eq init failed!\n");
|
|
|
+ goto error_failed_eq_table;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
if (hr_dev->cmd_mod) {
|
|
@@ -898,10 +714,12 @@ static int hns_roce_probe(struct platform_device *pdev)
|
|
|
goto error_failed_setup_hca;
|
|
|
}
|
|
|
|
|
|
- ret = hr_dev->hw->hw_init(hr_dev);
|
|
|
- if (ret) {
|
|
|
- dev_err(dev, "hw_init failed!\n");
|
|
|
- goto error_failed_engine_init;
|
|
|
+ if (hr_dev->hw->hw_init) {
|
|
|
+ ret = hr_dev->hw->hw_init(hr_dev);
|
|
|
+ if (ret) {
|
|
|
+ dev_err(dev, "hw_init failed!\n");
|
|
|
+ goto error_failed_engine_init;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
ret = hns_roce_register_device(hr_dev);
|
|
@@ -911,7 +729,8 @@ static int hns_roce_probe(struct platform_device *pdev)
|
|
|
return 0;
|
|
|
|
|
|
error_failed_register_device:
|
|
|
- hr_dev->hw->hw_exit(hr_dev);
|
|
|
+ if (hr_dev->hw->hw_exit)
|
|
|
+ hr_dev->hw->hw_exit(hr_dev);
|
|
|
|
|
|
error_failed_engine_init:
|
|
|
hns_roce_cleanup_bitmap(hr_dev);
|
|
@@ -924,58 +743,41 @@ error_failed_init_hem:
|
|
|
hns_roce_cmd_use_polling(hr_dev);
|
|
|
|
|
|
error_failed_use_event:
|
|
|
- hns_roce_cleanup_eq_table(hr_dev);
|
|
|
+ if (hr_dev->cmd_mod)
|
|
|
+ hns_roce_cleanup_eq_table(hr_dev);
|
|
|
|
|
|
error_failed_eq_table:
|
|
|
hns_roce_cmd_cleanup(hr_dev);
|
|
|
|
|
|
error_failed_cmd_init:
|
|
|
- ret = hr_dev->hw->reset(hr_dev, false);
|
|
|
- if (ret)
|
|
|
- dev_err(&hr_dev->pdev->dev, "roce_engine reset fail\n");
|
|
|
-
|
|
|
-error_failed_get_cfg:
|
|
|
- ib_dealloc_device(&hr_dev->ib_dev);
|
|
|
+ if (hr_dev->hw->reset) {
|
|
|
+ ret = hr_dev->hw->reset(hr_dev, false);
|
|
|
+ if (ret)
|
|
|
+ dev_err(dev, "Dereset RoCE engine failed!\n");
|
|
|
+ }
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
|
+EXPORT_SYMBOL_GPL(hns_roce_init);
|
|
|
|
|
|
-/**
|
|
|
- * hns_roce_remove - remove RoCE device
|
|
|
- * @pdev: pointer to platform device
|
|
|
- */
|
|
|
-static int hns_roce_remove(struct platform_device *pdev)
|
|
|
+void hns_roce_exit(struct hns_roce_dev *hr_dev)
|
|
|
{
|
|
|
- struct hns_roce_dev *hr_dev = platform_get_drvdata(pdev);
|
|
|
-
|
|
|
hns_roce_unregister_device(hr_dev);
|
|
|
- hr_dev->hw->hw_exit(hr_dev);
|
|
|
+ if (hr_dev->hw->hw_exit)
|
|
|
+ hr_dev->hw->hw_exit(hr_dev);
|
|
|
hns_roce_cleanup_bitmap(hr_dev);
|
|
|
hns_roce_cleanup_hem(hr_dev);
|
|
|
|
|
|
if (hr_dev->cmd_mod)
|
|
|
hns_roce_cmd_use_polling(hr_dev);
|
|
|
|
|
|
- hns_roce_cleanup_eq_table(hr_dev);
|
|
|
+ if (hr_dev->cmd_mod)
|
|
|
+ hns_roce_cleanup_eq_table(hr_dev);
|
|
|
hns_roce_cmd_cleanup(hr_dev);
|
|
|
- hr_dev->hw->reset(hr_dev, false);
|
|
|
-
|
|
|
- ib_dealloc_device(&hr_dev->ib_dev);
|
|
|
-
|
|
|
- return 0;
|
|
|
+ if (hr_dev->hw->reset)
|
|
|
+ hr_dev->hw->reset(hr_dev, false);
|
|
|
}
|
|
|
-
|
|
|
-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),
|
|
|
- },
|
|
|
-};
|
|
|
-
|
|
|
-module_platform_driver(hns_roce_driver);
|
|
|
+EXPORT_SYMBOL_GPL(hns_roce_exit);
|
|
|
|
|
|
MODULE_LICENSE("Dual BSD/GPL");
|
|
|
MODULE_AUTHOR("Wei Hu <xavier.huwei@huawei.com>");
|