0001
0002
0003
0004 #include "fw_reset.h"
0005 #include "diag/fw_tracer.h"
0006 #include "lib/tout.h"
0007
0008 enum {
0009 MLX5_FW_RESET_FLAGS_RESET_REQUESTED,
0010 MLX5_FW_RESET_FLAGS_NACK_RESET_REQUEST,
0011 MLX5_FW_RESET_FLAGS_PENDING_COMP,
0012 MLX5_FW_RESET_FLAGS_DROP_NEW_REQUESTS
0013 };
0014
0015 struct mlx5_fw_reset {
0016 struct mlx5_core_dev *dev;
0017 struct mlx5_nb nb;
0018 struct workqueue_struct *wq;
0019 struct work_struct fw_live_patch_work;
0020 struct work_struct reset_request_work;
0021 struct work_struct reset_reload_work;
0022 struct work_struct reset_now_work;
0023 struct work_struct reset_abort_work;
0024 unsigned long reset_flags;
0025 struct timer_list timer;
0026 struct completion done;
0027 int ret;
0028 };
0029
0030 void mlx5_fw_reset_enable_remote_dev_reset_set(struct mlx5_core_dev *dev, bool enable)
0031 {
0032 struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset;
0033
0034 if (enable)
0035 clear_bit(MLX5_FW_RESET_FLAGS_NACK_RESET_REQUEST, &fw_reset->reset_flags);
0036 else
0037 set_bit(MLX5_FW_RESET_FLAGS_NACK_RESET_REQUEST, &fw_reset->reset_flags);
0038 }
0039
0040 bool mlx5_fw_reset_enable_remote_dev_reset_get(struct mlx5_core_dev *dev)
0041 {
0042 struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset;
0043
0044 return !test_bit(MLX5_FW_RESET_FLAGS_NACK_RESET_REQUEST, &fw_reset->reset_flags);
0045 }
0046
0047 static int mlx5_reg_mfrl_set(struct mlx5_core_dev *dev, u8 reset_level,
0048 u8 reset_type_sel, u8 sync_resp, bool sync_start)
0049 {
0050 u32 out[MLX5_ST_SZ_DW(mfrl_reg)] = {};
0051 u32 in[MLX5_ST_SZ_DW(mfrl_reg)] = {};
0052
0053 MLX5_SET(mfrl_reg, in, reset_level, reset_level);
0054 MLX5_SET(mfrl_reg, in, rst_type_sel, reset_type_sel);
0055 MLX5_SET(mfrl_reg, in, pci_sync_for_fw_update_resp, sync_resp);
0056 MLX5_SET(mfrl_reg, in, pci_sync_for_fw_update_start, sync_start);
0057
0058 return mlx5_core_access_reg(dev, in, sizeof(in), out, sizeof(out), MLX5_REG_MFRL, 0, 1);
0059 }
0060
0061 static int mlx5_reg_mfrl_query(struct mlx5_core_dev *dev, u8 *reset_level,
0062 u8 *reset_type, u8 *reset_state)
0063 {
0064 u32 out[MLX5_ST_SZ_DW(mfrl_reg)] = {};
0065 u32 in[MLX5_ST_SZ_DW(mfrl_reg)] = {};
0066 int err;
0067
0068 err = mlx5_core_access_reg(dev, in, sizeof(in), out, sizeof(out), MLX5_REG_MFRL, 0, 0);
0069 if (err)
0070 return err;
0071
0072 if (reset_level)
0073 *reset_level = MLX5_GET(mfrl_reg, out, reset_level);
0074 if (reset_type)
0075 *reset_type = MLX5_GET(mfrl_reg, out, reset_type);
0076 if (reset_state)
0077 *reset_state = MLX5_GET(mfrl_reg, out, reset_state);
0078
0079 return 0;
0080 }
0081
0082 int mlx5_fw_reset_query(struct mlx5_core_dev *dev, u8 *reset_level, u8 *reset_type)
0083 {
0084 return mlx5_reg_mfrl_query(dev, reset_level, reset_type, NULL);
0085 }
0086
0087 static int mlx5_fw_reset_get_reset_state_err(struct mlx5_core_dev *dev,
0088 struct netlink_ext_ack *extack)
0089 {
0090 u8 reset_state;
0091
0092 if (mlx5_reg_mfrl_query(dev, NULL, NULL, &reset_state))
0093 goto out;
0094
0095 switch (reset_state) {
0096 case MLX5_MFRL_REG_RESET_STATE_IN_NEGOTIATION:
0097 case MLX5_MFRL_REG_RESET_STATE_RESET_IN_PROGRESS:
0098 NL_SET_ERR_MSG_MOD(extack, "Sync reset was already triggered");
0099 return -EBUSY;
0100 case MLX5_MFRL_REG_RESET_STATE_TIMEOUT:
0101 NL_SET_ERR_MSG_MOD(extack, "Sync reset got timeout");
0102 return -ETIMEDOUT;
0103 case MLX5_MFRL_REG_RESET_STATE_NACK:
0104 NL_SET_ERR_MSG_MOD(extack, "One of the hosts disabled reset");
0105 return -EPERM;
0106 }
0107
0108 out:
0109 NL_SET_ERR_MSG_MOD(extack, "Sync reset failed");
0110 return -EIO;
0111 }
0112
0113 int mlx5_fw_reset_set_reset_sync(struct mlx5_core_dev *dev, u8 reset_type_sel,
0114 struct netlink_ext_ack *extack)
0115 {
0116 struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset;
0117 u32 out[MLX5_ST_SZ_DW(mfrl_reg)] = {};
0118 u32 in[MLX5_ST_SZ_DW(mfrl_reg)] = {};
0119 int err;
0120
0121 set_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags);
0122
0123 MLX5_SET(mfrl_reg, in, reset_level, MLX5_MFRL_REG_RESET_LEVEL3);
0124 MLX5_SET(mfrl_reg, in, rst_type_sel, reset_type_sel);
0125 MLX5_SET(mfrl_reg, in, pci_sync_for_fw_update_start, 1);
0126 err = mlx5_access_reg(dev, in, sizeof(in), out, sizeof(out),
0127 MLX5_REG_MFRL, 0, 1, false);
0128 if (!err)
0129 return 0;
0130
0131 clear_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags);
0132 if (err == -EREMOTEIO && MLX5_CAP_MCAM_FEATURE(dev, reset_state))
0133 return mlx5_fw_reset_get_reset_state_err(dev, extack);
0134
0135 NL_SET_ERR_MSG_MOD(extack, "Sync reset command failed");
0136 return mlx5_cmd_check(dev, err, in, out);
0137 }
0138
0139 int mlx5_fw_reset_set_live_patch(struct mlx5_core_dev *dev)
0140 {
0141 return mlx5_reg_mfrl_set(dev, MLX5_MFRL_REG_RESET_LEVEL0, 0, 0, false);
0142 }
0143
0144 static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev)
0145 {
0146 struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset;
0147
0148
0149 if (test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags)) {
0150 complete(&fw_reset->done);
0151 } else {
0152 mlx5_unload_one(dev);
0153 if (mlx5_health_wait_pci_up(dev))
0154 mlx5_core_err(dev, "reset reload flow aborted, PCI reads still not working\n");
0155 mlx5_load_one(dev, false);
0156 devlink_remote_reload_actions_performed(priv_to_devlink(dev), 0,
0157 BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT) |
0158 BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE));
0159 }
0160 }
0161
0162 static void mlx5_stop_sync_reset_poll(struct mlx5_core_dev *dev)
0163 {
0164 struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset;
0165
0166 del_timer_sync(&fw_reset->timer);
0167 }
0168
0169 static int mlx5_sync_reset_clear_reset_requested(struct mlx5_core_dev *dev, bool poll_health)
0170 {
0171 struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset;
0172
0173 if (!test_and_clear_bit(MLX5_FW_RESET_FLAGS_RESET_REQUESTED, &fw_reset->reset_flags)) {
0174 mlx5_core_warn(dev, "Reset request was already cleared\n");
0175 return -EALREADY;
0176 }
0177
0178 mlx5_stop_sync_reset_poll(dev);
0179 if (poll_health)
0180 mlx5_start_health_poll(dev);
0181 return 0;
0182 }
0183
0184 static void mlx5_sync_reset_reload_work(struct work_struct *work)
0185 {
0186 struct mlx5_fw_reset *fw_reset = container_of(work, struct mlx5_fw_reset,
0187 reset_reload_work);
0188 struct mlx5_core_dev *dev = fw_reset->dev;
0189
0190 mlx5_sync_reset_clear_reset_requested(dev, false);
0191 mlx5_enter_error_state(dev, true);
0192 mlx5_fw_reset_complete_reload(dev);
0193 }
0194
0195 #define MLX5_RESET_POLL_INTERVAL (HZ / 10)
0196 static void poll_sync_reset(struct timer_list *t)
0197 {
0198 struct mlx5_fw_reset *fw_reset = from_timer(fw_reset, t, timer);
0199 struct mlx5_core_dev *dev = fw_reset->dev;
0200 u32 fatal_error;
0201
0202 if (!test_bit(MLX5_FW_RESET_FLAGS_RESET_REQUESTED, &fw_reset->reset_flags))
0203 return;
0204
0205 fatal_error = mlx5_health_check_fatal_sensors(dev);
0206
0207 if (fatal_error) {
0208 mlx5_core_warn(dev, "Got Device Reset\n");
0209 if (!test_bit(MLX5_FW_RESET_FLAGS_DROP_NEW_REQUESTS, &fw_reset->reset_flags))
0210 queue_work(fw_reset->wq, &fw_reset->reset_reload_work);
0211 else
0212 mlx5_core_err(dev, "Device is being removed, Drop new reset work\n");
0213 return;
0214 }
0215
0216 mod_timer(&fw_reset->timer, round_jiffies(jiffies + MLX5_RESET_POLL_INTERVAL));
0217 }
0218
0219 static void mlx5_start_sync_reset_poll(struct mlx5_core_dev *dev)
0220 {
0221 struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset;
0222
0223 timer_setup(&fw_reset->timer, poll_sync_reset, 0);
0224 fw_reset->timer.expires = round_jiffies(jiffies + MLX5_RESET_POLL_INTERVAL);
0225 add_timer(&fw_reset->timer);
0226 }
0227
0228 static int mlx5_fw_reset_set_reset_sync_ack(struct mlx5_core_dev *dev)
0229 {
0230 return mlx5_reg_mfrl_set(dev, MLX5_MFRL_REG_RESET_LEVEL3, 0, 1, false);
0231 }
0232
0233 static int mlx5_fw_reset_set_reset_sync_nack(struct mlx5_core_dev *dev)
0234 {
0235 return mlx5_reg_mfrl_set(dev, MLX5_MFRL_REG_RESET_LEVEL3, 0, 2, false);
0236 }
0237
0238 static int mlx5_sync_reset_set_reset_requested(struct mlx5_core_dev *dev)
0239 {
0240 struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset;
0241
0242 if (test_and_set_bit(MLX5_FW_RESET_FLAGS_RESET_REQUESTED, &fw_reset->reset_flags)) {
0243 mlx5_core_warn(dev, "Reset request was already set\n");
0244 return -EALREADY;
0245 }
0246 mlx5_stop_health_poll(dev, true);
0247 mlx5_start_sync_reset_poll(dev);
0248 return 0;
0249 }
0250
0251 static void mlx5_fw_live_patch_event(struct work_struct *work)
0252 {
0253 struct mlx5_fw_reset *fw_reset = container_of(work, struct mlx5_fw_reset,
0254 fw_live_patch_work);
0255 struct mlx5_core_dev *dev = fw_reset->dev;
0256
0257 mlx5_core_info(dev, "Live patch updated firmware version: %d.%d.%d\n", fw_rev_maj(dev),
0258 fw_rev_min(dev), fw_rev_sub(dev));
0259
0260 if (mlx5_fw_tracer_reload(dev->tracer))
0261 mlx5_core_err(dev, "Failed to reload FW tracer\n");
0262 }
0263
0264 static void mlx5_sync_reset_request_event(struct work_struct *work)
0265 {
0266 struct mlx5_fw_reset *fw_reset = container_of(work, struct mlx5_fw_reset,
0267 reset_request_work);
0268 struct mlx5_core_dev *dev = fw_reset->dev;
0269 int err;
0270
0271 if (test_bit(MLX5_FW_RESET_FLAGS_NACK_RESET_REQUEST, &fw_reset->reset_flags)) {
0272 err = mlx5_fw_reset_set_reset_sync_nack(dev);
0273 mlx5_core_warn(dev, "PCI Sync FW Update Reset Nack %s",
0274 err ? "Failed" : "Sent");
0275 return;
0276 }
0277 if (mlx5_sync_reset_set_reset_requested(dev))
0278 return;
0279
0280 err = mlx5_fw_reset_set_reset_sync_ack(dev);
0281 if (err)
0282 mlx5_core_warn(dev, "PCI Sync FW Update Reset Ack Failed. Error code: %d\n", err);
0283 else
0284 mlx5_core_warn(dev, "PCI Sync FW Update Reset Ack. Device reset is expected.\n");
0285 }
0286
0287 static int mlx5_pci_link_toggle(struct mlx5_core_dev *dev)
0288 {
0289 struct pci_bus *bridge_bus = dev->pdev->bus;
0290 struct pci_dev *bridge = bridge_bus->self;
0291 u16 reg16, dev_id, sdev_id;
0292 unsigned long timeout;
0293 struct pci_dev *sdev;
0294 int cap, err;
0295 u32 reg32;
0296
0297
0298
0299
0300 err = pci_read_config_word(dev->pdev, PCI_DEVICE_ID, &dev_id);
0301 if (err)
0302 return err;
0303 list_for_each_entry(sdev, &bridge_bus->devices, bus_list) {
0304 err = pci_read_config_word(sdev, PCI_DEVICE_ID, &sdev_id);
0305 if (err)
0306 return err;
0307 if (sdev_id != dev_id)
0308 return -EPERM;
0309 }
0310
0311 cap = pci_find_capability(bridge, PCI_CAP_ID_EXP);
0312 if (!cap)
0313 return -EOPNOTSUPP;
0314
0315 list_for_each_entry(sdev, &bridge_bus->devices, bus_list) {
0316 pci_save_state(sdev);
0317 pci_cfg_access_lock(sdev);
0318 }
0319
0320 err = pci_read_config_word(bridge, cap + PCI_EXP_LNKCTL, ®16);
0321 if (err)
0322 return err;
0323 reg16 |= PCI_EXP_LNKCTL_LD;
0324 err = pci_write_config_word(bridge, cap + PCI_EXP_LNKCTL, reg16);
0325 if (err)
0326 return err;
0327 msleep(500);
0328 reg16 &= ~PCI_EXP_LNKCTL_LD;
0329 err = pci_write_config_word(bridge, cap + PCI_EXP_LNKCTL, reg16);
0330 if (err)
0331 return err;
0332
0333
0334 err = pci_read_config_dword(bridge, cap + PCI_EXP_LNKCAP, ®32);
0335 if (err)
0336 return err;
0337 if (!(reg32 & PCI_EXP_LNKCAP_DLLLARC)) {
0338 mlx5_core_warn(dev, "No PCI link reporting capability (0x%08x)\n", reg32);
0339 msleep(1000);
0340 goto restore;
0341 }
0342
0343 timeout = jiffies + msecs_to_jiffies(mlx5_tout_ms(dev, PCI_TOGGLE));
0344 do {
0345 err = pci_read_config_word(bridge, cap + PCI_EXP_LNKSTA, ®16);
0346 if (err)
0347 return err;
0348 if (reg16 & PCI_EXP_LNKSTA_DLLLA)
0349 break;
0350 msleep(20);
0351 } while (!time_after(jiffies, timeout));
0352
0353 if (reg16 & PCI_EXP_LNKSTA_DLLLA) {
0354 mlx5_core_info(dev, "PCI Link up\n");
0355 } else {
0356 mlx5_core_err(dev, "PCI link not ready (0x%04x) after %llu ms\n",
0357 reg16, mlx5_tout_ms(dev, PCI_TOGGLE));
0358 err = -ETIMEDOUT;
0359 }
0360
0361 restore:
0362 list_for_each_entry(sdev, &bridge_bus->devices, bus_list) {
0363 pci_cfg_access_unlock(sdev);
0364 pci_restore_state(sdev);
0365 }
0366
0367 return err;
0368 }
0369
0370 static void mlx5_sync_reset_now_event(struct work_struct *work)
0371 {
0372 struct mlx5_fw_reset *fw_reset = container_of(work, struct mlx5_fw_reset,
0373 reset_now_work);
0374 struct mlx5_core_dev *dev = fw_reset->dev;
0375 int err;
0376
0377 if (mlx5_sync_reset_clear_reset_requested(dev, false))
0378 return;
0379
0380 mlx5_core_warn(dev, "Sync Reset now. Device is going to reset.\n");
0381
0382 err = mlx5_cmd_fast_teardown_hca(dev);
0383 if (err) {
0384 mlx5_core_warn(dev, "Fast teardown failed, no reset done, err %d\n", err);
0385 goto done;
0386 }
0387
0388 err = mlx5_pci_link_toggle(dev);
0389 if (err) {
0390 mlx5_core_warn(dev, "mlx5_pci_link_toggle failed, no reset done, err %d\n", err);
0391 goto done;
0392 }
0393
0394 mlx5_enter_error_state(dev, true);
0395 done:
0396 fw_reset->ret = err;
0397 mlx5_fw_reset_complete_reload(dev);
0398 }
0399
0400 static void mlx5_sync_reset_abort_event(struct work_struct *work)
0401 {
0402 struct mlx5_fw_reset *fw_reset = container_of(work, struct mlx5_fw_reset,
0403 reset_abort_work);
0404 struct mlx5_core_dev *dev = fw_reset->dev;
0405
0406 if (mlx5_sync_reset_clear_reset_requested(dev, true))
0407 return;
0408 mlx5_core_warn(dev, "PCI Sync FW Update Reset Aborted.\n");
0409 }
0410
0411 static void mlx5_sync_reset_events_handle(struct mlx5_fw_reset *fw_reset, struct mlx5_eqe *eqe)
0412 {
0413 struct mlx5_eqe_sync_fw_update *sync_fw_update_eqe;
0414 u8 sync_event_rst_type;
0415
0416 sync_fw_update_eqe = &eqe->data.sync_fw_update;
0417 sync_event_rst_type = sync_fw_update_eqe->sync_rst_state & SYNC_RST_STATE_MASK;
0418 switch (sync_event_rst_type) {
0419 case MLX5_SYNC_RST_STATE_RESET_REQUEST:
0420 queue_work(fw_reset->wq, &fw_reset->reset_request_work);
0421 break;
0422 case MLX5_SYNC_RST_STATE_RESET_NOW:
0423 queue_work(fw_reset->wq, &fw_reset->reset_now_work);
0424 break;
0425 case MLX5_SYNC_RST_STATE_RESET_ABORT:
0426 queue_work(fw_reset->wq, &fw_reset->reset_abort_work);
0427 break;
0428 }
0429 }
0430
0431 static int fw_reset_event_notifier(struct notifier_block *nb, unsigned long action, void *data)
0432 {
0433 struct mlx5_fw_reset *fw_reset = mlx5_nb_cof(nb, struct mlx5_fw_reset, nb);
0434 struct mlx5_eqe *eqe = data;
0435
0436 if (test_bit(MLX5_FW_RESET_FLAGS_DROP_NEW_REQUESTS, &fw_reset->reset_flags))
0437 return NOTIFY_DONE;
0438
0439 switch (eqe->sub_type) {
0440 case MLX5_GENERAL_SUBTYPE_FW_LIVE_PATCH_EVENT:
0441 queue_work(fw_reset->wq, &fw_reset->fw_live_patch_work);
0442 break;
0443 case MLX5_GENERAL_SUBTYPE_PCI_SYNC_FOR_FW_UPDATE_EVENT:
0444 mlx5_sync_reset_events_handle(fw_reset, eqe);
0445 break;
0446 default:
0447 return NOTIFY_DONE;
0448 }
0449
0450 return NOTIFY_OK;
0451 }
0452
0453 int mlx5_fw_reset_wait_reset_done(struct mlx5_core_dev *dev)
0454 {
0455 unsigned long pci_sync_update_timeout = mlx5_tout_ms(dev, PCI_SYNC_UPDATE);
0456 unsigned long timeout = msecs_to_jiffies(pci_sync_update_timeout);
0457 struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset;
0458 int err;
0459
0460 if (!wait_for_completion_timeout(&fw_reset->done, timeout)) {
0461 mlx5_core_warn(dev, "FW sync reset timeout after %lu seconds\n",
0462 pci_sync_update_timeout / 1000);
0463 err = -ETIMEDOUT;
0464 goto out;
0465 }
0466 err = fw_reset->ret;
0467 out:
0468 clear_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags);
0469 return err;
0470 }
0471
0472 void mlx5_fw_reset_events_start(struct mlx5_core_dev *dev)
0473 {
0474 struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset;
0475
0476 MLX5_NB_INIT(&fw_reset->nb, fw_reset_event_notifier, GENERAL_EVENT);
0477 mlx5_eq_notifier_register(dev, &fw_reset->nb);
0478 }
0479
0480 void mlx5_fw_reset_events_stop(struct mlx5_core_dev *dev)
0481 {
0482 mlx5_eq_notifier_unregister(dev, &dev->priv.fw_reset->nb);
0483 }
0484
0485 void mlx5_drain_fw_reset(struct mlx5_core_dev *dev)
0486 {
0487 struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset;
0488
0489 set_bit(MLX5_FW_RESET_FLAGS_DROP_NEW_REQUESTS, &fw_reset->reset_flags);
0490 cancel_work_sync(&fw_reset->fw_live_patch_work);
0491 cancel_work_sync(&fw_reset->reset_request_work);
0492 cancel_work_sync(&fw_reset->reset_reload_work);
0493 cancel_work_sync(&fw_reset->reset_now_work);
0494 cancel_work_sync(&fw_reset->reset_abort_work);
0495 }
0496
0497 int mlx5_fw_reset_init(struct mlx5_core_dev *dev)
0498 {
0499 struct mlx5_fw_reset *fw_reset = kzalloc(sizeof(*fw_reset), GFP_KERNEL);
0500
0501 if (!fw_reset)
0502 return -ENOMEM;
0503 fw_reset->wq = create_singlethread_workqueue("mlx5_fw_reset_events");
0504 if (!fw_reset->wq) {
0505 kfree(fw_reset);
0506 return -ENOMEM;
0507 }
0508
0509 fw_reset->dev = dev;
0510 dev->priv.fw_reset = fw_reset;
0511
0512 INIT_WORK(&fw_reset->fw_live_patch_work, mlx5_fw_live_patch_event);
0513 INIT_WORK(&fw_reset->reset_request_work, mlx5_sync_reset_request_event);
0514 INIT_WORK(&fw_reset->reset_reload_work, mlx5_sync_reset_reload_work);
0515 INIT_WORK(&fw_reset->reset_now_work, mlx5_sync_reset_now_event);
0516 INIT_WORK(&fw_reset->reset_abort_work, mlx5_sync_reset_abort_event);
0517
0518 init_completion(&fw_reset->done);
0519 return 0;
0520 }
0521
0522 void mlx5_fw_reset_cleanup(struct mlx5_core_dev *dev)
0523 {
0524 struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset;
0525
0526 destroy_workqueue(fw_reset->wq);
0527 kfree(dev->priv.fw_reset);
0528 }