Commit 041b499b authored by John W. Linville's avatar John W. Linville
parents d5aedd7e 3c5da7ee
...@@ -67,8 +67,8 @@ ...@@ -67,8 +67,8 @@
#include "iwl-agn-hw.h" #include "iwl-agn-hw.h"
/* Highest firmware API version supported */ /* Highest firmware API version supported */
#define IWL7260_UCODE_API_MAX 7 #define IWL7260_UCODE_API_MAX 8
#define IWL3160_UCODE_API_MAX 7 #define IWL3160_UCODE_API_MAX 8
/* Oldest version we won't warn about */ /* Oldest version we won't warn about */
#define IWL7260_UCODE_API_OK 7 #define IWL7260_UCODE_API_OK 7
...@@ -130,6 +130,7 @@ const struct iwl_cfg iwl7260_2ac_cfg = { ...@@ -130,6 +130,7 @@ const struct iwl_cfg iwl7260_2ac_cfg = {
.ht_params = &iwl7000_ht_params, .ht_params = &iwl7000_ht_params,
.nvm_ver = IWL7260_NVM_VERSION, .nvm_ver = IWL7260_NVM_VERSION,
.nvm_calib_ver = IWL7260_TX_POWER_VERSION, .nvm_calib_ver = IWL7260_TX_POWER_VERSION,
.host_interrupt_operation_mode = true,
}; };
const struct iwl_cfg iwl7260_2ac_cfg_high_temp = { const struct iwl_cfg iwl7260_2ac_cfg_high_temp = {
...@@ -140,6 +141,7 @@ const struct iwl_cfg iwl7260_2ac_cfg_high_temp = { ...@@ -140,6 +141,7 @@ const struct iwl_cfg iwl7260_2ac_cfg_high_temp = {
.nvm_ver = IWL7260_NVM_VERSION, .nvm_ver = IWL7260_NVM_VERSION,
.nvm_calib_ver = IWL7260_TX_POWER_VERSION, .nvm_calib_ver = IWL7260_TX_POWER_VERSION,
.high_temp = true, .high_temp = true,
.host_interrupt_operation_mode = true,
}; };
const struct iwl_cfg iwl7260_2n_cfg = { const struct iwl_cfg iwl7260_2n_cfg = {
...@@ -149,6 +151,7 @@ const struct iwl_cfg iwl7260_2n_cfg = { ...@@ -149,6 +151,7 @@ const struct iwl_cfg iwl7260_2n_cfg = {
.ht_params = &iwl7000_ht_params, .ht_params = &iwl7000_ht_params,
.nvm_ver = IWL7260_NVM_VERSION, .nvm_ver = IWL7260_NVM_VERSION,
.nvm_calib_ver = IWL7260_TX_POWER_VERSION, .nvm_calib_ver = IWL7260_TX_POWER_VERSION,
.host_interrupt_operation_mode = true,
}; };
const struct iwl_cfg iwl7260_n_cfg = { const struct iwl_cfg iwl7260_n_cfg = {
...@@ -158,6 +161,7 @@ const struct iwl_cfg iwl7260_n_cfg = { ...@@ -158,6 +161,7 @@ const struct iwl_cfg iwl7260_n_cfg = {
.ht_params = &iwl7000_ht_params, .ht_params = &iwl7000_ht_params,
.nvm_ver = IWL7260_NVM_VERSION, .nvm_ver = IWL7260_NVM_VERSION,
.nvm_calib_ver = IWL7260_TX_POWER_VERSION, .nvm_calib_ver = IWL7260_TX_POWER_VERSION,
.host_interrupt_operation_mode = true,
}; };
const struct iwl_cfg iwl3160_2ac_cfg = { const struct iwl_cfg iwl3160_2ac_cfg = {
...@@ -167,6 +171,7 @@ const struct iwl_cfg iwl3160_2ac_cfg = { ...@@ -167,6 +171,7 @@ const struct iwl_cfg iwl3160_2ac_cfg = {
.ht_params = &iwl7000_ht_params, .ht_params = &iwl7000_ht_params,
.nvm_ver = IWL3160_NVM_VERSION, .nvm_ver = IWL3160_NVM_VERSION,
.nvm_calib_ver = IWL3160_TX_POWER_VERSION, .nvm_calib_ver = IWL3160_TX_POWER_VERSION,
.host_interrupt_operation_mode = true,
}; };
const struct iwl_cfg iwl3160_2n_cfg = { const struct iwl_cfg iwl3160_2n_cfg = {
...@@ -176,6 +181,7 @@ const struct iwl_cfg iwl3160_2n_cfg = { ...@@ -176,6 +181,7 @@ const struct iwl_cfg iwl3160_2n_cfg = {
.ht_params = &iwl7000_ht_params, .ht_params = &iwl7000_ht_params,
.nvm_ver = IWL3160_NVM_VERSION, .nvm_ver = IWL3160_NVM_VERSION,
.nvm_calib_ver = IWL3160_TX_POWER_VERSION, .nvm_calib_ver = IWL3160_TX_POWER_VERSION,
.host_interrupt_operation_mode = true,
}; };
const struct iwl_cfg iwl3160_n_cfg = { const struct iwl_cfg iwl3160_n_cfg = {
...@@ -185,6 +191,7 @@ const struct iwl_cfg iwl3160_n_cfg = { ...@@ -185,6 +191,7 @@ const struct iwl_cfg iwl3160_n_cfg = {
.ht_params = &iwl7000_ht_params, .ht_params = &iwl7000_ht_params,
.nvm_ver = IWL3160_NVM_VERSION, .nvm_ver = IWL3160_NVM_VERSION,
.nvm_calib_ver = IWL3160_TX_POWER_VERSION, .nvm_calib_ver = IWL3160_TX_POWER_VERSION,
.host_interrupt_operation_mode = true,
}; };
const struct iwl_cfg iwl7265_2ac_cfg = { const struct iwl_cfg iwl7265_2ac_cfg = {
...@@ -196,5 +203,23 @@ const struct iwl_cfg iwl7265_2ac_cfg = { ...@@ -196,5 +203,23 @@ const struct iwl_cfg iwl7265_2ac_cfg = {
.nvm_calib_ver = IWL7265_TX_POWER_VERSION, .nvm_calib_ver = IWL7265_TX_POWER_VERSION,
}; };
const struct iwl_cfg iwl7265_2n_cfg = {
.name = "Intel(R) Dual Band Wireless N 7265",
.fw_name_pre = IWL7265_FW_PRE,
IWL_DEVICE_7000,
.ht_params = &iwl7000_ht_params,
.nvm_ver = IWL7265_NVM_VERSION,
.nvm_calib_ver = IWL7265_TX_POWER_VERSION,
};
const struct iwl_cfg iwl7265_n_cfg = {
.name = "Intel(R) Wireless N 7265",
.fw_name_pre = IWL7265_FW_PRE,
IWL_DEVICE_7000,
.ht_params = &iwl7000_ht_params,
.nvm_ver = IWL7265_NVM_VERSION,
.nvm_calib_ver = IWL7265_TX_POWER_VERSION,
};
MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL3160_UCODE_API_OK)); MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL3160_UCODE_API_OK));
...@@ -207,6 +207,8 @@ struct iwl_eeprom_params { ...@@ -207,6 +207,8 @@ struct iwl_eeprom_params {
* @rx_with_siso_diversity: 1x1 device with rx antenna diversity * @rx_with_siso_diversity: 1x1 device with rx antenna diversity
* @internal_wimax_coex: internal wifi/wimax combo device * @internal_wimax_coex: internal wifi/wimax combo device
* @high_temp: Is this NIC is designated to be in high temperature. * @high_temp: Is this NIC is designated to be in high temperature.
* @host_interrupt_operation_mode: device needs host interrupt operation
* mode set
* *
* We enable the driver to be backward compatible wrt. hardware features. * We enable the driver to be backward compatible wrt. hardware features.
* API differences in uCode shouldn't be handled here but through TLVs * API differences in uCode shouldn't be handled here but through TLVs
...@@ -235,6 +237,7 @@ struct iwl_cfg { ...@@ -235,6 +237,7 @@ struct iwl_cfg {
enum iwl_led_mode led_mode; enum iwl_led_mode led_mode;
const bool rx_with_siso_diversity; const bool rx_with_siso_diversity;
const bool internal_wimax_coex; const bool internal_wimax_coex;
const bool host_interrupt_operation_mode;
bool high_temp; bool high_temp;
}; };
...@@ -294,6 +297,8 @@ extern const struct iwl_cfg iwl3160_2ac_cfg; ...@@ -294,6 +297,8 @@ extern const struct iwl_cfg iwl3160_2ac_cfg;
extern const struct iwl_cfg iwl3160_2n_cfg; extern const struct iwl_cfg iwl3160_2n_cfg;
extern const struct iwl_cfg iwl3160_n_cfg; extern const struct iwl_cfg iwl3160_n_cfg;
extern const struct iwl_cfg iwl7265_2ac_cfg; extern const struct iwl_cfg iwl7265_2ac_cfg;
extern const struct iwl_cfg iwl7265_2n_cfg;
extern const struct iwl_cfg iwl7265_n_cfg;
#endif /* CONFIG_IWLMVM */ #endif /* CONFIG_IWLMVM */
#endif /* __IWL_CONFIG_H__ */ #endif /* __IWL_CONFIG_H__ */
...@@ -495,14 +495,11 @@ enum secure_load_status_reg { ...@@ -495,14 +495,11 @@ enum secure_load_status_reg {
* the CSR_INT_COALESCING is an 8 bit register in 32-usec unit * the CSR_INT_COALESCING is an 8 bit register in 32-usec unit
* *
* default interrupt coalescing timer is 64 x 32 = 2048 usecs * default interrupt coalescing timer is 64 x 32 = 2048 usecs
* default interrupt coalescing calibration timer is 16 x 32 = 512 usecs
*/ */
#define IWL_HOST_INT_TIMEOUT_MAX (0xFF) #define IWL_HOST_INT_TIMEOUT_MAX (0xFF)
#define IWL_HOST_INT_TIMEOUT_DEF (0x40) #define IWL_HOST_INT_TIMEOUT_DEF (0x40)
#define IWL_HOST_INT_TIMEOUT_MIN (0x0) #define IWL_HOST_INT_TIMEOUT_MIN (0x0)
#define IWL_HOST_INT_CALIB_TIMEOUT_MAX (0xFF) #define IWL_HOST_INT_OPER_MODE BIT(31)
#define IWL_HOST_INT_CALIB_TIMEOUT_DEF (0x10)
#define IWL_HOST_INT_CALIB_TIMEOUT_MIN (0x0)
/***************************************************************************** /*****************************************************************************
* 7000/3000 series SHR DTS addresses * * 7000/3000 series SHR DTS addresses *
......
...@@ -391,7 +391,6 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm) ...@@ -391,7 +391,6 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
BT_VALID_LUT | BT_VALID_LUT |
BT_VALID_WIFI_RX_SW_PRIO_BOOST | BT_VALID_WIFI_RX_SW_PRIO_BOOST |
BT_VALID_WIFI_TX_SW_PRIO_BOOST | BT_VALID_WIFI_TX_SW_PRIO_BOOST |
BT_VALID_MULTI_PRIO_LUT |
BT_VALID_CORUN_LUT_20 | BT_VALID_CORUN_LUT_20 |
BT_VALID_CORUN_LUT_40 | BT_VALID_CORUN_LUT_40 |
BT_VALID_ANT_ISOLATION | BT_VALID_ANT_ISOLATION |
...@@ -842,6 +841,11 @@ static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac, ...@@ -842,6 +841,11 @@ static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac,
sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id], sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id],
lockdep_is_held(&mvm->mutex)); lockdep_is_held(&mvm->mutex));
/* This can happen if the station has been removed right now */
if (IS_ERR_OR_NULL(sta))
return;
mvmsta = (void *)sta->drv_priv; mvmsta = (void *)sta->drv_priv;
data->num_bss_ifaces++; data->num_bss_ifaces++;
......
...@@ -895,7 +895,7 @@ static int iwl_mvm_get_last_nonqos_seq(struct iwl_mvm *mvm, ...@@ -895,7 +895,7 @@ static int iwl_mvm_get_last_nonqos_seq(struct iwl_mvm *mvm,
/* new API returns next, not last-used seqno */ /* new API returns next, not last-used seqno */
if (mvm->fw->ucode_capa.flags & if (mvm->fw->ucode_capa.flags &
IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API) IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API)
err -= 0x10; err = (u16) (err - 0x10);
} }
iwl_free_resp(&cmd); iwl_free_resp(&cmd);
...@@ -1549,7 +1549,7 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm, ...@@ -1549,7 +1549,7 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
if (gtkdata.unhandled_cipher) if (gtkdata.unhandled_cipher)
return false; return false;
if (!gtkdata.num_keys) if (!gtkdata.num_keys)
return true; goto out;
if (!gtkdata.last_gtk) if (!gtkdata.last_gtk)
return false; return false;
...@@ -1600,6 +1600,7 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm, ...@@ -1600,6 +1600,7 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
(void *)&replay_ctr, GFP_KERNEL); (void *)&replay_ctr, GFP_KERNEL);
} }
out:
mvmvif->seqno_valid = true; mvmvif->seqno_valid = true;
/* +0x10 because the set API expects next-to-use, not last-used */ /* +0x10 because the set API expects next-to-use, not last-used */
mvmvif->seqno = le16_to_cpu(status->non_qos_seq_ctr) + 0x10; mvmvif->seqno = le16_to_cpu(status->non_qos_seq_ctr) + 0x10;
......
...@@ -119,6 +119,10 @@ static ssize_t iwl_dbgfs_sta_drain_write(struct file *file, ...@@ -119,6 +119,10 @@ static ssize_t iwl_dbgfs_sta_drain_write(struct file *file,
if (sscanf(buf, "%d %d", &sta_id, &drain) != 2) if (sscanf(buf, "%d %d", &sta_id, &drain) != 2)
return -EINVAL; return -EINVAL;
if (sta_id < 0 || sta_id >= IWL_MVM_STATION_COUNT)
return -EINVAL;
if (drain < 0 || drain > 1)
return -EINVAL;
mutex_lock(&mvm->mutex); mutex_lock(&mvm->mutex);
......
...@@ -176,8 +176,11 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm, ...@@ -176,8 +176,11 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
* P2P Device discoveribility, while there are other higher priority * P2P Device discoveribility, while there are other higher priority
* events in the system). * events in the system).
*/ */
if (WARN_ONCE(!le32_to_cpu(notif->status), if (!le32_to_cpu(notif->status)) {
"Failed to schedule time event\n")) { bool start = le32_to_cpu(notif->action) &
TE_V2_NOTIF_HOST_EVENT_START;
IWL_WARN(mvm, "Time Event %s notification failure\n",
start ? "start" : "end");
if (iwl_mvm_te_check_disconnect(mvm, te_data->vif, NULL)) { if (iwl_mvm_te_check_disconnect(mvm, te_data->vif, NULL)) {
iwl_mvm_te_clear_data(mvm, te_data); iwl_mvm_te_clear_data(mvm, te_data);
return; return;
......
...@@ -353,6 +353,27 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { ...@@ -353,6 +353,27 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
/* 7265 Series */ /* 7265 Series */
{IWL_PCI_DEVICE(0x095A, 0x5010, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x5010, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x5110, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095B, 0x5310, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095B, 0x5302, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095B, 0x5210, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095B, 0x5012, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095B, 0x500A, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x5410, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x1010, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x5000, iwl7265_2n_cfg)},
{IWL_PCI_DEVICE(0x095B, 0x5200, iwl7265_2n_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x5002, iwl7265_n_cfg)},
{IWL_PCI_DEVICE(0x095B, 0x5202, iwl7265_n_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x9010, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x9210, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x9410, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x5020, iwl7265_2n_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x502A, iwl7265_2n_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x5420, iwl7265_2n_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x5090, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095B, 0x5290, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x5490, iwl7265_2ac_cfg)},
#endif /* CONFIG_IWLMVM */ #endif /* CONFIG_IWLMVM */
{0} {0}
......
...@@ -477,4 +477,12 @@ static inline bool iwl_is_rfkill_set(struct iwl_trans *trans) ...@@ -477,4 +477,12 @@ static inline bool iwl_is_rfkill_set(struct iwl_trans *trans)
CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW); CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
} }
static inline void iwl_nic_error(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
set_bit(STATUS_FW_ERROR, &trans_pcie->status);
iwl_op_mode_nic_error(trans->op_mode);
}
#endif /* __iwl_trans_int_pcie_h__ */ #endif /* __iwl_trans_int_pcie_h__ */
...@@ -489,6 +489,10 @@ static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq) ...@@ -489,6 +489,10 @@ static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq)
/* Set interrupt coalescing timer to default (2048 usecs) */ /* Set interrupt coalescing timer to default (2048 usecs) */
iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF);
/* W/A for interrupt coalescing bug in 7260 and 3160 */
if (trans->cfg->host_interrupt_operation_mode)
iwl_set_bit(trans, CSR_INT_COALESCING, IWL_HOST_INT_OPER_MODE);
} }
static void iwl_pcie_rx_init_rxb_lists(struct iwl_rxq *rxq) static void iwl_pcie_rx_init_rxb_lists(struct iwl_rxq *rxq)
...@@ -796,12 +800,13 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans) ...@@ -796,12 +800,13 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans)
iwl_pcie_dump_csr(trans); iwl_pcie_dump_csr(trans);
iwl_dump_fh(trans, NULL); iwl_dump_fh(trans, NULL);
/* set the ERROR bit before we wake up the caller */
set_bit(STATUS_FW_ERROR, &trans_pcie->status); set_bit(STATUS_FW_ERROR, &trans_pcie->status);
clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status); clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status);
wake_up(&trans_pcie->wait_command_queue); wake_up(&trans_pcie->wait_command_queue);
local_bh_disable(); local_bh_disable();
iwl_op_mode_nic_error(trans->op_mode); iwl_nic_error(trans);
local_bh_enable(); local_bh_enable();
} }
......
...@@ -279,9 +279,6 @@ static int iwl_pcie_nic_init(struct iwl_trans *trans) ...@@ -279,9 +279,6 @@ static int iwl_pcie_nic_init(struct iwl_trans *trans)
spin_lock_irqsave(&trans_pcie->irq_lock, flags); spin_lock_irqsave(&trans_pcie->irq_lock, flags);
iwl_pcie_apm_init(trans); iwl_pcie_apm_init(trans);
/* Set interrupt coalescing calibration timer to default (512 usecs) */
iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF);
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
iwl_pcie_set_pwr(trans, false); iwl_pcie_set_pwr(trans, false);
......
...@@ -207,7 +207,7 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data) ...@@ -207,7 +207,7 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data)
IWL_ERR(trans, "scratch %d = 0x%08x\n", i, IWL_ERR(trans, "scratch %d = 0x%08x\n", i,
le32_to_cpu(txq->scratchbufs[i].scratch)); le32_to_cpu(txq->scratchbufs[i].scratch));
iwl_op_mode_nic_error(trans->op_mode); iwl_nic_error(trans);
} }
/* /*
...@@ -1023,7 +1023,7 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx) ...@@ -1023,7 +1023,7 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx)
if (nfreed++ > 0) { if (nfreed++ > 0) {
IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n", IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n",
idx, q->write_ptr, q->read_ptr); idx, q->write_ptr, q->read_ptr);
iwl_op_mode_nic_error(trans->op_mode); iwl_nic_error(trans);
} }
} }
...@@ -1562,7 +1562,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, ...@@ -1562,7 +1562,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
get_cmd_string(trans_pcie, cmd->id)); get_cmd_string(trans_pcie, cmd->id));
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
iwl_op_mode_nic_error(trans->op_mode); iwl_nic_error(trans);
goto cancel; goto cancel;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment