diff options
author | Sony Chacko <sony.chacko@qlogic.com> | 2012-12-03 22:33:56 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-12-04 13:00:12 -0500 |
commit | bff57d8e1de3510bb8845f639631b6fced211801 (patch) | |
tree | 23eee74bbc38e185faccdede63f0ec2b68a2ec19 | |
parent | 229997989bdb7742cf5d21cdc6754017dab1e2db (diff) |
qlcnic: update NIC partition interface routines
Refactor 82xx driver to support new adapter
Update routines to support variable number of NIC partitions
Signed-off-by: Rajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: Sony Chacko <sony.chacko@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c | 39 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 97 |
3 files changed, 89 insertions, 48 deletions
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index 4d85c709af95..537902479689 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | |||
@@ -1051,6 +1051,7 @@ struct qlcnic_npar_info { | |||
1051 | u8 mac_anti_spoof; | 1051 | u8 mac_anti_spoof; |
1052 | u8 promisc_mode; | 1052 | u8 promisc_mode; |
1053 | u8 offload_flags; | 1053 | u8 offload_flags; |
1054 | u8 pci_func; | ||
1054 | }; | 1055 | }; |
1055 | 1056 | ||
1056 | struct qlcnic_eswitch { | 1057 | struct qlcnic_eswitch { |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c index c5cfbaa832a8..58f094ca052e 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c | |||
@@ -7,6 +7,18 @@ | |||
7 | 7 | ||
8 | #include "qlcnic.h" | 8 | #include "qlcnic.h" |
9 | 9 | ||
10 | static int qlcnic_is_valid_nic_func(struct qlcnic_adapter *adapter, u8 pci_func) | ||
11 | { | ||
12 | int i; | ||
13 | |||
14 | for (i = 0; i < adapter->ahw->act_pci_func; i++) { | ||
15 | if (adapter->npars[i].pci_func == pci_func) | ||
16 | return i; | ||
17 | } | ||
18 | |||
19 | return -1; | ||
20 | } | ||
21 | |||
10 | static u32 | 22 | static u32 |
11 | qlcnic_poll_rsp(struct qlcnic_adapter *adapter) | 23 | qlcnic_poll_rsp(struct qlcnic_adapter *adapter) |
12 | { | 24 | { |
@@ -817,11 +829,14 @@ int qlcnic_get_pci_info(struct qlcnic_adapter *adapter, | |||
817 | qlcnic_issue_cmd(adapter, &cmd); | 829 | qlcnic_issue_cmd(adapter, &cmd); |
818 | err = cmd.rsp.cmd; | 830 | err = cmd.rsp.cmd; |
819 | 831 | ||
832 | adapter->ahw->act_pci_func = 0; | ||
820 | if (err == QLCNIC_RCODE_SUCCESS) { | 833 | if (err == QLCNIC_RCODE_SUCCESS) { |
821 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++, npar++, pci_info++) { | 834 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++, npar++, pci_info++) { |
822 | pci_info->id = le16_to_cpu(npar->id); | 835 | pci_info->id = le16_to_cpu(npar->id); |
823 | pci_info->active = le16_to_cpu(npar->active); | 836 | pci_info->active = le16_to_cpu(npar->active); |
824 | pci_info->type = le16_to_cpu(npar->type); | 837 | pci_info->type = le16_to_cpu(npar->type); |
838 | if (pci_info->type == QLCNIC_TYPE_NIC) | ||
839 | adapter->ahw->act_pci_func++; | ||
825 | pci_info->default_port = | 840 | pci_info->default_port = |
826 | le16_to_cpu(npar->default_port); | 841 | le16_to_cpu(npar->default_port); |
827 | pci_info->tx_min_bw = | 842 | pci_info->tx_min_bw = |
@@ -1016,12 +1031,13 @@ int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch, | |||
1016 | esw_stats->numbytes = QLCNIC_STATS_NOT_AVAIL; | 1031 | esw_stats->numbytes = QLCNIC_STATS_NOT_AVAIL; |
1017 | esw_stats->context_id = eswitch; | 1032 | esw_stats->context_id = eswitch; |
1018 | 1033 | ||
1019 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { | 1034 | for (i = 0; i < adapter->ahw->act_pci_func; i++) { |
1020 | if (adapter->npars[i].phy_port != eswitch) | 1035 | if (adapter->npars[i].phy_port != eswitch) |
1021 | continue; | 1036 | continue; |
1022 | 1037 | ||
1023 | memset(&port_stats, 0, sizeof(struct __qlcnic_esw_statistics)); | 1038 | memset(&port_stats, 0, sizeof(struct __qlcnic_esw_statistics)); |
1024 | if (qlcnic_get_port_stats(adapter, i, rx_tx, &port_stats)) | 1039 | if (qlcnic_get_port_stats(adapter, adapter->npars[i].pci_func, |
1040 | rx_tx, &port_stats)) | ||
1025 | continue; | 1041 | continue; |
1026 | 1042 | ||
1027 | esw_stats->size = port_stats.size; | 1043 | esw_stats->size = port_stats.size; |
@@ -1120,7 +1136,7 @@ op_type = 1 for port vlan_id | |||
1120 | int qlcnic_config_switch_port(struct qlcnic_adapter *adapter, | 1136 | int qlcnic_config_switch_port(struct qlcnic_adapter *adapter, |
1121 | struct qlcnic_esw_func_cfg *esw_cfg) | 1137 | struct qlcnic_esw_func_cfg *esw_cfg) |
1122 | { | 1138 | { |
1123 | int err = -EIO; | 1139 | int err = -EIO, index; |
1124 | u32 arg1, arg2 = 0; | 1140 | u32 arg1, arg2 = 0; |
1125 | struct qlcnic_cmd_args cmd; | 1141 | struct qlcnic_cmd_args cmd; |
1126 | u8 pci_func; | 1142 | u8 pci_func; |
@@ -1128,7 +1144,10 @@ int qlcnic_config_switch_port(struct qlcnic_adapter *adapter, | |||
1128 | if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) | 1144 | if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) |
1129 | return err; | 1145 | return err; |
1130 | pci_func = esw_cfg->pci_func; | 1146 | pci_func = esw_cfg->pci_func; |
1131 | arg1 = (adapter->npars[pci_func].phy_port & BIT_0); | 1147 | index = qlcnic_is_valid_nic_func(adapter, pci_func); |
1148 | if (index < 0) | ||
1149 | return err; | ||
1150 | arg1 = (adapter->npars[index].phy_port & BIT_0); | ||
1132 | arg1 |= (pci_func << 8); | 1151 | arg1 |= (pci_func << 8); |
1133 | 1152 | ||
1134 | if (__qlcnic_get_eswitch_port_config(adapter, &arg1, &arg2)) | 1153 | if (__qlcnic_get_eswitch_port_config(adapter, &arg1, &arg2)) |
@@ -1192,11 +1211,17 @@ qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter, | |||
1192 | struct qlcnic_esw_func_cfg *esw_cfg) | 1211 | struct qlcnic_esw_func_cfg *esw_cfg) |
1193 | { | 1212 | { |
1194 | u32 arg1, arg2; | 1213 | u32 arg1, arg2; |
1214 | int index; | ||
1195 | u8 phy_port; | 1215 | u8 phy_port; |
1196 | if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC) | 1216 | |
1197 | phy_port = adapter->npars[esw_cfg->pci_func].phy_port; | 1217 | if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC) { |
1198 | else | 1218 | index = qlcnic_is_valid_nic_func(adapter, esw_cfg->pci_func); |
1219 | if (index < 0) | ||
1220 | return -EIO; | ||
1221 | phy_port = adapter->npars[index].phy_port; | ||
1222 | } else { | ||
1199 | phy_port = adapter->ahw->physical_port; | 1223 | phy_port = adapter->ahw->physical_port; |
1224 | } | ||
1200 | arg1 = phy_port; | 1225 | arg1 = phy_port; |
1201 | arg1 |= (esw_cfg->pci_func << 8); | 1226 | arg1 |= (esw_cfg->pci_func << 8); |
1202 | if (__qlcnic_get_eswitch_port_config(adapter, &arg1, &arg2)) | 1227 | if (__qlcnic_get_eswitch_port_config(adapter, &arg1, &arg2)) |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 85adf0def3bd..88084a3bec34 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | |||
@@ -91,6 +91,9 @@ static void qlcnic_set_netdev_features(struct qlcnic_adapter *, | |||
91 | static int qlcnic_vlan_rx_add(struct net_device *, u16); | 91 | static int qlcnic_vlan_rx_add(struct net_device *, u16); |
92 | static int qlcnic_vlan_rx_del(struct net_device *, u16); | 92 | static int qlcnic_vlan_rx_del(struct net_device *, u16); |
93 | 93 | ||
94 | #define QLCNIC_IS_TSO_CAPABLE(adapter) \ | ||
95 | ((adapter)->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO) | ||
96 | |||
94 | /* PCI Device ID Table */ | 97 | /* PCI Device ID Table */ |
95 | #define ENTRY(device) \ | 98 | #define ENTRY(device) \ |
96 | {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, (device)), \ | 99 | {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, (device)), \ |
@@ -369,19 +372,25 @@ qlcnic_cleanup_pci_map(struct qlcnic_adapter *adapter) | |||
369 | iounmap(adapter->ahw->pci_base0); | 372 | iounmap(adapter->ahw->pci_base0); |
370 | } | 373 | } |
371 | 374 | ||
372 | static int | 375 | static int qlcnic_init_pci_info(struct qlcnic_adapter *adapter) |
373 | qlcnic_init_pci_info(struct qlcnic_adapter *adapter) | ||
374 | { | 376 | { |
375 | struct qlcnic_pci_info *pci_info; | 377 | struct qlcnic_pci_info *pci_info; |
376 | int i, ret = 0; | 378 | int i, ret = 0, j = 0; |
379 | u16 act_pci_func; | ||
377 | u8 pfn; | 380 | u8 pfn; |
378 | 381 | ||
379 | pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL); | 382 | pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL); |
380 | if (!pci_info) | 383 | if (!pci_info) |
381 | return -ENOMEM; | 384 | return -ENOMEM; |
382 | 385 | ||
386 | ret = qlcnic_get_pci_info(adapter, pci_info); | ||
387 | if (ret) | ||
388 | goto err_pci_info; | ||
389 | |||
390 | act_pci_func = adapter->ahw->act_pci_func; | ||
391 | |||
383 | adapter->npars = kzalloc(sizeof(struct qlcnic_npar_info) * | 392 | adapter->npars = kzalloc(sizeof(struct qlcnic_npar_info) * |
384 | QLCNIC_MAX_PCI_FUNC, GFP_KERNEL); | 393 | act_pci_func, GFP_KERNEL); |
385 | if (!adapter->npars) { | 394 | if (!adapter->npars) { |
386 | ret = -ENOMEM; | 395 | ret = -ENOMEM; |
387 | goto err_pci_info; | 396 | goto err_pci_info; |
@@ -394,21 +403,25 @@ qlcnic_init_pci_info(struct qlcnic_adapter *adapter) | |||
394 | goto err_npars; | 403 | goto err_npars; |
395 | } | 404 | } |
396 | 405 | ||
397 | ret = qlcnic_get_pci_info(adapter, pci_info); | ||
398 | if (ret) | ||
399 | goto err_eswitch; | ||
400 | |||
401 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { | 406 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { |
402 | pfn = pci_info[i].id; | 407 | pfn = pci_info[i].id; |
408 | |||
403 | if (pfn >= QLCNIC_MAX_PCI_FUNC) { | 409 | if (pfn >= QLCNIC_MAX_PCI_FUNC) { |
404 | ret = QL_STATUS_INVALID_PARAM; | 410 | ret = QL_STATUS_INVALID_PARAM; |
405 | goto err_eswitch; | 411 | goto err_eswitch; |
406 | } | 412 | } |
407 | adapter->npars[pfn].active = (u8)pci_info[i].active; | 413 | |
408 | adapter->npars[pfn].type = (u8)pci_info[i].type; | 414 | if (!pci_info[i].active || |
409 | adapter->npars[pfn].phy_port = (u8)pci_info[i].default_port; | 415 | (pci_info[i].type != QLCNIC_TYPE_NIC)) |
410 | adapter->npars[pfn].min_bw = pci_info[i].tx_min_bw; | 416 | continue; |
411 | adapter->npars[pfn].max_bw = pci_info[i].tx_max_bw; | 417 | |
418 | adapter->npars[j].pci_func = pfn; | ||
419 | adapter->npars[j].active = (u8)pci_info[i].active; | ||
420 | adapter->npars[j].type = (u8)pci_info[i].type; | ||
421 | adapter->npars[j].phy_port = (u8)pci_info[i].default_port; | ||
422 | adapter->npars[j].min_bw = pci_info[i].tx_min_bw; | ||
423 | adapter->npars[j].max_bw = pci_info[i].tx_max_bw; | ||
424 | j++; | ||
412 | } | 425 | } |
413 | 426 | ||
414 | for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++) | 427 | for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++) |
@@ -436,7 +449,7 @@ qlcnic_set_function_modes(struct qlcnic_adapter *adapter) | |||
436 | u32 ref_count; | 449 | u32 ref_count; |
437 | int i, ret = 1; | 450 | int i, ret = 1; |
438 | u32 data = QLCNIC_MGMT_FUNC; | 451 | u32 data = QLCNIC_MGMT_FUNC; |
439 | void __iomem *priv_op = adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE; | 452 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
440 | 453 | ||
441 | /* If other drivers are not in use set their privilege level */ | 454 | /* If other drivers are not in use set their privilege level */ |
442 | ref_count = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE); | 455 | ref_count = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE); |
@@ -445,21 +458,20 @@ qlcnic_set_function_modes(struct qlcnic_adapter *adapter) | |||
445 | goto err_lock; | 458 | goto err_lock; |
446 | 459 | ||
447 | if (qlcnic_config_npars) { | 460 | if (qlcnic_config_npars) { |
448 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { | 461 | for (i = 0; i < ahw->act_pci_func; i++) { |
449 | id = i; | 462 | id = adapter->npars[i].pci_func; |
450 | if (adapter->npars[i].type != QLCNIC_TYPE_NIC || | 463 | if (id == ahw->pci_func) |
451 | id == adapter->ahw->pci_func) | ||
452 | continue; | 464 | continue; |
453 | data |= (qlcnic_config_npars & | 465 | data |= (qlcnic_config_npars & |
454 | QLC_DEV_SET_DRV(0xf, id)); | 466 | QLC_DEV_SET_DRV(0xf, id)); |
455 | } | 467 | } |
456 | } else { | 468 | } else { |
457 | data = readl(priv_op); | 469 | data = QLCRD32(adapter, QLCNIC_DRV_OP_MODE); |
458 | data = (data & ~QLC_DEV_SET_DRV(0xf, adapter->ahw->pci_func)) | | 470 | data = (data & ~QLC_DEV_SET_DRV(0xf, ahw->pci_func)) | |
459 | (QLC_DEV_SET_DRV(QLCNIC_MGMT_FUNC, | 471 | (QLC_DEV_SET_DRV(QLCNIC_MGMT_FUNC, |
460 | adapter->ahw->pci_func)); | 472 | ahw->pci_func)); |
461 | } | 473 | } |
462 | writel(data, priv_op); | 474 | QLCWR32(adapter, QLCNIC_DRV_OP_MODE, data); |
463 | qlcnic_api_unlock(adapter); | 475 | qlcnic_api_unlock(adapter); |
464 | err_lock: | 476 | err_lock: |
465 | return ret; | 477 | return ret; |
@@ -632,6 +644,7 @@ qlcnic_initialize_nic(struct qlcnic_adapter *adapter) | |||
632 | int err; | 644 | int err; |
633 | struct qlcnic_info nic_info; | 645 | struct qlcnic_info nic_info; |
634 | 646 | ||
647 | memset(&nic_info, 0, sizeof(struct qlcnic_info)); | ||
635 | err = qlcnic_get_nic_info(adapter, &nic_info, adapter->ahw->pci_func); | 648 | err = qlcnic_get_nic_info(adapter, &nic_info, adapter->ahw->pci_func); |
636 | if (err) | 649 | if (err) |
637 | return err; | 650 | return err; |
@@ -798,8 +811,7 @@ qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter) | |||
798 | return err; | 811 | return err; |
799 | } | 812 | } |
800 | 813 | ||
801 | static int | 814 | static int qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter) |
802 | qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter) | ||
803 | { | 815 | { |
804 | struct qlcnic_esw_func_cfg esw_cfg; | 816 | struct qlcnic_esw_func_cfg esw_cfg; |
805 | struct qlcnic_npar_info *npar; | 817 | struct qlcnic_npar_info *npar; |
@@ -808,16 +820,16 @@ qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter) | |||
808 | if (adapter->need_fw_reset) | 820 | if (adapter->need_fw_reset) |
809 | return 0; | 821 | return 0; |
810 | 822 | ||
811 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { | 823 | for (i = 0; i < adapter->ahw->act_pci_func; i++) { |
812 | if (adapter->npars[i].type != QLCNIC_TYPE_NIC) | ||
813 | continue; | ||
814 | memset(&esw_cfg, 0, sizeof(struct qlcnic_esw_func_cfg)); | 824 | memset(&esw_cfg, 0, sizeof(struct qlcnic_esw_func_cfg)); |
815 | esw_cfg.pci_func = i; | 825 | esw_cfg.pci_func = adapter->npars[i].pci_func; |
816 | esw_cfg.offload_flags = BIT_0; | ||
817 | esw_cfg.mac_override = BIT_0; | 826 | esw_cfg.mac_override = BIT_0; |
818 | esw_cfg.promisc_mode = BIT_0; | 827 | esw_cfg.promisc_mode = BIT_0; |
819 | if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO) | 828 | if (qlcnic_82xx_check(adapter)) { |
820 | esw_cfg.offload_flags |= (BIT_1 | BIT_2); | 829 | esw_cfg.offload_flags = BIT_0; |
830 | if (QLCNIC_IS_TSO_CAPABLE(adapter)) | ||
831 | esw_cfg.offload_flags |= (BIT_1 | BIT_2); | ||
832 | } | ||
821 | if (qlcnic_config_switch_port(adapter, &esw_cfg)) | 833 | if (qlcnic_config_switch_port(adapter, &esw_cfg)) |
822 | return -EIO; | 834 | return -EIO; |
823 | npar = &adapter->npars[i]; | 835 | npar = &adapter->npars[i]; |
@@ -855,22 +867,24 @@ qlcnic_reset_eswitch_config(struct qlcnic_adapter *adapter, | |||
855 | return 0; | 867 | return 0; |
856 | } | 868 | } |
857 | 869 | ||
858 | static int | 870 | static int qlcnic_reset_npar_config(struct qlcnic_adapter *adapter) |
859 | qlcnic_reset_npar_config(struct qlcnic_adapter *adapter) | ||
860 | { | 871 | { |
861 | int i, err; | 872 | int i, err; |
862 | struct qlcnic_npar_info *npar; | 873 | struct qlcnic_npar_info *npar; |
863 | struct qlcnic_info nic_info; | 874 | struct qlcnic_info nic_info; |
875 | u8 pci_func; | ||
864 | 876 | ||
865 | if (!adapter->need_fw_reset) | 877 | if (qlcnic_82xx_check(adapter)) |
866 | return 0; | 878 | if (!adapter->need_fw_reset) |
879 | return 0; | ||
867 | 880 | ||
868 | /* Set the NPAR config data after FW reset */ | 881 | /* Set the NPAR config data after FW reset */ |
869 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { | 882 | for (i = 0; i < adapter->ahw->act_pci_func; i++) { |
870 | npar = &adapter->npars[i]; | 883 | npar = &adapter->npars[i]; |
871 | if (npar->type != QLCNIC_TYPE_NIC) | 884 | pci_func = npar->pci_func; |
872 | continue; | 885 | memset(&nic_info, 0, sizeof(struct qlcnic_info)); |
873 | err = qlcnic_get_nic_info(adapter, &nic_info, i); | 886 | err = qlcnic_get_nic_info(adapter, |
887 | &nic_info, pci_func); | ||
874 | if (err) | 888 | if (err) |
875 | return err; | 889 | return err; |
876 | nic_info.min_tx_bw = npar->min_bw; | 890 | nic_info.min_tx_bw = npar->min_bw; |
@@ -881,11 +895,12 @@ qlcnic_reset_npar_config(struct qlcnic_adapter *adapter) | |||
881 | 895 | ||
882 | if (npar->enable_pm) { | 896 | if (npar->enable_pm) { |
883 | err = qlcnic_config_port_mirroring(adapter, | 897 | err = qlcnic_config_port_mirroring(adapter, |
884 | npar->dest_npar, 1, i); | 898 | npar->dest_npar, 1, |
899 | pci_func); | ||
885 | if (err) | 900 | if (err) |
886 | return err; | 901 | return err; |
887 | } | 902 | } |
888 | err = qlcnic_reset_eswitch_config(adapter, npar, i); | 903 | err = qlcnic_reset_eswitch_config(adapter, npar, pci_func); |
889 | if (err) | 904 | if (err) |
890 | return err; | 905 | return err; |
891 | } | 906 | } |