Hi Andrew, Today's linux-next merge of the akpm-current tree got a conflict in drivers/misc/mei/init.c between commit 33ec08263147 ("mei: revamp mei reset state machine") from the char-misc tree and commit dd045dab2999 ("drivers/misc/mei: ratelimit several error messages") from the akpm-current tree. I fixed it up (see below) and can carry the fix as necessary (no action is required). -- Cheers, Stephen Rothwell sfr@xxxxxxxxxxxxxxxx diff --cc drivers/misc/mei/init.c index cdd31c2a2a2b,edd3bb6a5df9..000000000000 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c @@@ -43,119 -43,41 +43,119 @@@ const char *mei_dev_state_str(int state #undef MEI_DEV_STATE } -void mei_device_init(struct mei_device *dev) -{ - /* setup our list array */ - INIT_LIST_HEAD(&dev->file_list); - INIT_LIST_HEAD(&dev->device_list); - mutex_init(&dev->device_lock); - init_waitqueue_head(&dev->wait_hw_ready); - init_waitqueue_head(&dev->wait_recvd_msg); - init_waitqueue_head(&dev->wait_stop_wd); - dev->dev_state = MEI_DEV_INITIALIZING; - mei_io_list_init(&dev->read_list); - mei_io_list_init(&dev->write_list); - mei_io_list_init(&dev->write_waiting_list); - mei_io_list_init(&dev->ctrl_wr_list); - mei_io_list_init(&dev->ctrl_rd_list); +/** + * mei_cancel_work. Cancel mei background jobs + * + * @dev: the device structure + * + * returns 0 on success or < 0 if the reset hasn't succeeded + */ +void mei_cancel_work(struct mei_device *dev) +{ + cancel_work_sync(&dev->init_work); + cancel_work_sync(&dev->reset_work); - INIT_DELAYED_WORK(&dev->timer_work, mei_timer); - INIT_WORK(&dev->init_work, mei_host_client_init); + cancel_delayed_work(&dev->timer_work); +} +EXPORT_SYMBOL_GPL(mei_cancel_work); - INIT_LIST_HEAD(&dev->wd_cl.link); - INIT_LIST_HEAD(&dev->iamthif_cl.link); - mei_io_list_init(&dev->amthif_cmd_list); - mei_io_list_init(&dev->amthif_rd_complete_list); +/** + * mei_reset - resets host and fw. + * + * @dev: the device structure + */ +int mei_reset(struct mei_device *dev) +{ + enum mei_dev_state state = dev->dev_state; + bool interrupts_enabled; + int ret; - bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX); - dev->open_handle_count = 0; + if (state != MEI_DEV_INITIALIZING && + state != MEI_DEV_DISABLED && + state != MEI_DEV_POWER_DOWN && + state != MEI_DEV_POWER_UP) - dev_warn(&dev->pdev->dev, "unexpected reset: dev_state = %s\n", ++ dev_warn_ratelimited(&dev->pdev->dev, "unexpected reset: dev_state = %s\n", + mei_dev_state_str(state)); - /* - * Reserving the first client ID - * 0: Reserved for MEI Bus Message communications + /* we're already in reset, cancel the init timer + * if the reset was called due the hbm protocol error + * we need to call it before hw start + * so the hbm watchdog won't kick in */ - bitmap_set(dev->host_clients_map, 0, 1); + mei_hbm_idle(dev); + + /* enter reset flow */ + interrupts_enabled = state != MEI_DEV_POWER_DOWN; + dev->dev_state = MEI_DEV_RESETTING; + + dev->reset_count++; + if (dev->reset_count > MEI_MAX_CONSEC_RESET) { + dev_err(&dev->pdev->dev, "reset: reached maximal consecutive resets: disabling the device\n"); + dev->dev_state = MEI_DEV_DISABLED; + return -ENODEV; + } + + ret = mei_hw_reset(dev, interrupts_enabled); + /* fall through and remove the sw state even if hw reset has failed */ + + /* no need to clean up software state in case of power up */ + if (state != MEI_DEV_INITIALIZING && + state != MEI_DEV_POWER_UP) { + + /* remove all waiting requests */ + mei_cl_all_write_clear(dev); + + mei_cl_all_disconnect(dev); + + /* wake up all readers and writers so they can be interrupted */ + mei_cl_all_wakeup(dev); + + /* remove entry if already in list */ + dev_dbg(&dev->pdev->dev, "remove iamthif and wd from the file list.\n"); + mei_cl_unlink(&dev->wd_cl); + mei_cl_unlink(&dev->iamthif_cl); + mei_amthif_reset_params(dev); + memset(&dev->wr_ext_msg, 0, sizeof(dev->wr_ext_msg)); + } + + + dev->me_clients_num = 0; + dev->rd_msg_hdr = 0; + dev->wd_pending = false; + + if (ret) { + dev_err(&dev->pdev->dev, "hw_reset failed ret = %d\n", ret); + dev->dev_state = MEI_DEV_DISABLED; + return ret; + } + + if (state == MEI_DEV_POWER_DOWN) { + dev_dbg(&dev->pdev->dev, "powering down: end of reset\n"); + dev->dev_state = MEI_DEV_DISABLED; + return 0; + } + + ret = mei_hw_start(dev); + if (ret) { + dev_err(&dev->pdev->dev, "hw_start failed ret = %d\n", ret); + dev->dev_state = MEI_DEV_DISABLED; + return ret; + } + + dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n"); + + dev->dev_state = MEI_DEV_INIT_CLIENTS; + ret = mei_hbm_start_req(dev); + if (ret) { + dev_err(&dev->pdev->dev, "hbm_start failed ret = %d\n", ret); + dev->dev_state = MEI_DEV_DISABLED; + return ret; + } + + return 0; } -EXPORT_SYMBOL_GPL(mei_device_init); +EXPORT_SYMBOL_GPL(mei_reset); /** * mei_start - initializes host and fw to start work.
Attachment:
pgpZEBq_19qMt.pgp
Description: PGP signature