From 07b509b7943e5594f3f228e5b62a49cf6a033709 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Mon, 23 Jul 2012 14:05:39 +0300 Subject: mei: revamp me client search function me client search functions returns index into me_client array according me client id or me client uuid. 1. Add common prefix for the functions mei_me_cl_<> 2. create new function mei_me_cl_by_id that wraps open coded loops scattered over the code 3. rename mei_find_me_client_index to mei_me_cl_by_uuid 4. rename mei_find_me_client_update_filext to mei_me_cl_update_filext and updates its parameter names Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/init.c | 38 ++++++++++++++++---------------- drivers/misc/mei/iorw.c | 55 +++++++++++++++++++++++++--------------------- drivers/misc/mei/main.c | 31 +++++--------------------- drivers/misc/mei/mei_dev.h | 8 +++---- drivers/misc/mei/wd.c | 2 +- 5 files changed, 60 insertions(+), 74 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index e77f86e69fb..58b3bf47c8e 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c @@ -522,12 +522,12 @@ void mei_cl_init(struct mei_cl *priv, struct mei_device *dev) priv->dev = dev; } -int mei_find_me_client_index(const struct mei_device *dev, uuid_le cuuid) +int mei_me_cl_by_uuid(const struct mei_device *dev, const uuid_le *cuuid) { - int i, res = -1; + int i, res = -ENOENT; for (i = 0; i < dev->me_clients_num; ++i) - if (uuid_le_cmp(cuuid, + if (uuid_le_cmp(*cuuid, dev->me_clients[i].props.protocol_name) == 0) { res = i; break; @@ -538,35 +538,35 @@ int mei_find_me_client_index(const struct mei_device *dev, uuid_le cuuid) /** - * mei_find_me_client_update_filext - searches for ME client guid + * mei_me_cl_update_filext - searches for ME client guid * sets client_id in mei_file_private if found * @dev: the device structure - * @priv: private file structure to set client_id in - * @cguid: searched guid of ME client + * @cl: private file structure to set client_id in + * @cuuid: searched uuid of ME client * @client_id: id of host client to be set in file private structure * * returns ME client index */ -u8 mei_find_me_client_update_filext(struct mei_device *dev, struct mei_cl *priv, - const uuid_le *cguid, u8 client_id) +int mei_me_cl_update_filext(struct mei_device *dev, struct mei_cl *cl, + const uuid_le *cuuid, u8 host_cl_id) { int i; - if (!dev || !priv || !cguid) - return 0; + if (!dev || !cl || !cuuid) + return -EINVAL; /* check for valid client id */ - i = mei_find_me_client_index(dev, *cguid); + i = mei_me_cl_by_uuid(dev, cuuid); if (i >= 0) { - priv->me_client_id = dev->me_clients[i].client_id; - priv->state = MEI_FILE_CONNECTING; - priv->host_client_id = client_id; + cl->me_client_id = dev->me_clients[i].client_id; + cl->state = MEI_FILE_CONNECTING; + cl->host_client_id = host_cl_id; - list_add_tail(&priv->link, &dev->file_list); + list_add_tail(&cl->link, &dev->file_list); return (u8)i; } - return 0; + return -ENOENT; } /** @@ -577,16 +577,16 @@ u8 mei_find_me_client_update_filext(struct mei_device *dev, struct mei_cl *priv, */ void mei_host_init_iamthif(struct mei_device *dev) { - u8 i; + int i; unsigned char *msg_buf; mei_cl_init(&dev->iamthif_cl, dev); dev->iamthif_cl.state = MEI_FILE_DISCONNECTED; /* find ME amthi client */ - i = mei_find_me_client_update_filext(dev, &dev->iamthif_cl, + i = mei_me_cl_update_filext(dev, &dev->iamthif_cl, &mei_amthi_guid, MEI_IAMTHIF_HOST_CLIENT_ID); - if (dev->iamthif_cl.state != MEI_FILE_CONNECTING) { + if (i < 0) { dev_dbg(&dev->pdev->dev, "failed to find iamthif client.\n"); return; } diff --git a/drivers/misc/mei/iorw.c b/drivers/misc/mei/iorw.c index 50f52e21f58..9187d852ef9 100644 --- a/drivers/misc/mei/iorw.c +++ b/drivers/misc/mei/iorw.c @@ -38,7 +38,31 @@ #include #include "interface.h" +/** + * mei_me_cl_by_id return index to me_clients for client_id + * + * @dev: the device structure + * @client_id: me client id + * + * Locking: called under "dev->device_lock" lock + * + * returns index on success, -ENOENT on failure. + */ +int mei_me_cl_by_id(struct mei_device *dev, u8 client_id) +{ + int i; + for (i = 0; i < dev->me_clients_num; i++) + if (dev->me_clients[i].client_id == client_id) + break; + if (WARN_ON(dev->me_clients[i].client_id != client_id)) + return -ENOENT; + + if (i == dev->me_clients_num) + return -ENOENT; + + return i; +} /** * mei_ioctl_connect_client - the connect to fw client IOCTL function @@ -95,7 +119,7 @@ int mei_ioctl_connect_client(struct file *file, } /* find ME client we're trying to connect to */ - i = mei_find_me_client_index(dev, data->in_client_uuid); + i = mei_me_cl_by_uuid(dev, &data->in_client_uuid); if (i >= 0 && !dev->me_clients[i].props.fixed_address) { cl->me_client_id = dev->me_clients[i].client_id; cl->state = MEI_FILE_CONNECTING; @@ -273,19 +297,12 @@ int amthi_read(struct mei_device *dev, struct file *file, return -ETIMEDOUT; } - for (i = 0; i < dev->me_clients_num; i++) { - if (dev->me_clients[i].client_id == - dev->iamthif_cl.me_client_id) - break; - } + i = mei_me_cl_by_id(dev, dev->iamthif_cl.me_client_id); - if (i == dev->me_clients_num) { + if (i < 0) { dev_dbg(&dev->pdev->dev, "amthi client not found.\n"); return -ENODEV; } - if (WARN_ON(dev->me_clients[i].client_id != cl->me_client_id)) - return -ENODEV; - dev_dbg(&dev->pdev->dev, "checking amthi data\n"); cb = find_amthi_read_list_entry(dev, file); @@ -316,8 +333,7 @@ int amthi_read(struct mei_device *dev, struct file *file, dev->iamthif_timer = 0; if (cb) { - timeout = cb->read_time + - msecs_to_jiffies(IAMTHIF_READ_TIMER); + timeout = cb->read_time + msecs_to_jiffies(IAMTHIF_READ_TIMER); dev_dbg(&dev->pdev->dev, "amthi timeout = %lud\n", timeout); @@ -401,19 +417,8 @@ int mei_start_read(struct mei_device *dev, struct mei_cl *cl) dev_dbg(&dev->pdev->dev, "allocation call back successful. host client = %d, ME client = %d\n", cl->host_client_id, cl->me_client_id); - - for (i = 0; i < dev->me_clients_num; i++) { - if (dev->me_clients[i].client_id == cl->me_client_id) - break; - - } - - if (WARN_ON(dev->me_clients[i].client_id != cl->me_client_id)) { - rets = -ENODEV; - goto unlock; - } - - if (i == dev->me_clients_num) { + i = mei_me_cl_by_id(dev, cl->me_client_id); + if (i < 0) { rets = -ENODEV; goto unlock; } diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 09233020886..b0903bd44bf 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -393,10 +393,9 @@ static ssize_t mei_read(struct file *file, char __user *ubuf, if ((cl->sm_state & MEI_WD_STATE_INDEPENDENCE_MSG_SENT) == 0) { /* Do not allow to read watchdog client */ - i = mei_find_me_client_index(dev, mei_wd_guid); + i = mei_me_cl_by_uuid(dev, &mei_wd_guid); if (i >= 0) { struct mei_me_client *me_client = &dev->me_clients[i]; - if (cl->me_client_id == me_client->client_id) { rets = -EBADF; goto out; @@ -620,22 +619,12 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf, rets = -ENODEV; goto unlock_dev; } - for (i = 0; i < dev->me_clients_num; i++) { - if (dev->me_clients[i].client_id == - dev->iamthif_cl.me_client_id) - break; - } - - if (WARN_ON(dev->me_clients[i].client_id != cl->me_client_id)) { + i = mei_me_cl_by_id(dev, dev->iamthif_cl.me_client_id); + if (i < 0) { rets = -ENODEV; goto unlock_dev; } - if (i == dev->me_clients_num || - (dev->me_clients[i].client_id != - dev->iamthif_cl.me_client_id)) { - rets = -ENODEV; - goto unlock_dev; - } else if (length > dev->me_clients[i].props.max_msg_length || + if (length > dev->me_clients[i].props.max_msg_length || length <= 0) { rets = -EMSGSIZE; goto unlock_dev; @@ -688,16 +677,8 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf, cl->me_client_id); goto unlock_dev; } - for (i = 0; i < dev->me_clients_num; i++) { - if (dev->me_clients[i].client_id == - cl->me_client_id) - break; - } - if (WARN_ON(dev->me_clients[i].client_id != cl->me_client_id)) { - rets = -ENODEV; - goto unlock_dev; - } - if (i == dev->me_clients_num) { + i = mei_me_cl_by_id(dev, cl->me_client_id); + if (i < 0) { rets = -ENODEV; goto unlock_dev; } diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index d61c4ddfc80..1ff1fc678fb 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -279,9 +279,10 @@ void mei_host_init_iamthif(struct mei_device *dev); void mei_allocate_me_clients_storage(struct mei_device *dev); -u8 mei_find_me_client_update_filext(struct mei_device *dev, - struct mei_cl *priv, - const uuid_le *cguid, u8 client_id); +int mei_me_cl_update_filext(struct mei_device *dev, struct mei_cl *cl, + const uuid_le *cguid, u8 host_client_id); +int mei_me_cl_by_uuid(const struct mei_device *dev, const uuid_le *cuuid); +int mei_me_cl_by_id(struct mei_device *dev, u8 client_id); /* * MEI IO List Functions @@ -348,7 +349,6 @@ void mei_run_next_iamthif_cmd(struct mei_device *dev); void mei_free_cb_private(struct mei_cl_cb *priv_cb); -int mei_find_me_client_index(const struct mei_device *dev, uuid_le cuuid); /* * Register Access Function diff --git a/drivers/misc/mei/wd.c b/drivers/misc/mei/wd.c index 5133fd77b91..912319e4fa9 100644 --- a/drivers/misc/mei/wd.c +++ b/drivers/misc/mei/wd.c @@ -69,7 +69,7 @@ int mei_wd_host_init(struct mei_device *dev) dev->wd_timeout = AMT_WD_DEFAULT_TIMEOUT; /* find ME WD client */ - mei_find_me_client_update_filext(dev, &dev->wd_cl, + mei_me_cl_update_filext(dev, &dev->wd_cl, &mei_wd_guid, MEI_WD_HOST_CLIENT_ID); dev_dbg(&dev->pdev->dev, "wd: check client\n"); -- cgit v1.2.3 From 9a123f19832702753805afe0e93db26799b91b07 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Mon, 6 Aug 2012 15:23:55 +0300 Subject: mei: add mei_quirk_probe function The main purpose of this function is to exclude ME devices without support for MEI/HECI interface from binding Currently affected systems are C600/X79 based servers that expose PCI device even though it doesn't supported ME Interface. MEI driver accessing such nonfunctional device can corrupt the system. Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/main.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index b0903bd44bf..86b73e59626 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -905,6 +905,27 @@ static struct miscdevice mei_misc_device = { .minor = MISC_DYNAMIC_MINOR, }; +/** + * mei_quirk_probe - probe for devices that doesn't valid ME interface + * @pdev: PCI device structure + * @ent: entry into pci_device_table + * + * returns true if ME Interface is valid, false otherwise + */ +static bool __devinit mei_quirk_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + u32 reg; + if (ent->device == MEI_DEV_ID_PBG_1) { + pci_read_config_dword(pdev, 0x48, ®); + /* make sure that bit 9 is up and bit 10 is down */ + if ((reg & 0x600) == 0x200) { + dev_info(&pdev->dev, "Device doesn't have valid ME Interface\n"); + return false; + } + } + return true; +} /** * mei_probe - Device Initialization Routine * @@ -920,6 +941,12 @@ static int __devinit mei_probe(struct pci_dev *pdev, int err; mutex_lock(&mei_mutex); + + if (!mei_quirk_probe(pdev, ent)) { + err = -ENODEV; + goto end; + } + if (mei_device) { err = -EEXIST; goto end; -- cgit v1.2.3 From 068c0ae9667ea2ae4c2269307ecfde9a9460e641 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 7 Aug 2012 00:03:54 +0300 Subject: mei: use KBUILD_MODNAME when allocating resources from the OS Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/main.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 86b73e59626..dea65c2c920 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -41,8 +41,6 @@ #include #include "interface.h" -static const char mei_driver_name[] = "mei"; - /* The device pointer */ /* Currently this driver works as long as there is only a single AMT device. */ struct pci_dev *mei_device; @@ -960,7 +958,7 @@ static int __devinit mei_probe(struct pci_dev *pdev, /* set PCI host mastering */ pci_set_master(pdev); /* pci request regions for mei driver */ - err = pci_request_regions(pdev, mei_driver_name); + err = pci_request_regions(pdev, KBUILD_MODNAME); if (err) { dev_err(&pdev->dev, "failed to get pci regions.\n"); goto disable_device; @@ -985,12 +983,12 @@ static int __devinit mei_probe(struct pci_dev *pdev, err = request_threaded_irq(pdev->irq, NULL, mei_interrupt_thread_handler, - IRQF_ONESHOT, mei_driver_name, dev); + IRQF_ONESHOT, KBUILD_MODNAME, dev); else err = request_threaded_irq(pdev->irq, mei_interrupt_quick_handler, mei_interrupt_thread_handler, - IRQF_SHARED, mei_driver_name, dev); + IRQF_SHARED, KBUILD_MODNAME, dev); if (err) { dev_err(&pdev->dev, "request_threaded_irq failure. irq = %d\n", @@ -1150,12 +1148,12 @@ static int mei_pci_resume(struct device *device) err = request_threaded_irq(pdev->irq, NULL, mei_interrupt_thread_handler, - IRQF_ONESHOT, mei_driver_name, dev); + IRQF_ONESHOT, KBUILD_MODNAME, dev); else err = request_threaded_irq(pdev->irq, mei_interrupt_quick_handler, mei_interrupt_thread_handler, - IRQF_SHARED, mei_driver_name, dev); + IRQF_SHARED, KBUILD_MODNAME, dev); if (err) { dev_err(&pdev->dev, "request_threaded_irq failed: irq = %d.\n", @@ -1182,7 +1180,7 @@ static SIMPLE_DEV_PM_OPS(mei_pm_ops, mei_pci_suspend, mei_pci_resume); * PCI driver structure */ static struct pci_driver mei_driver = { - .name = mei_driver_name, + .name = KBUILD_MODNAME, .id_table = mei_pci_tbl, .probe = mei_probe, .remove = __devexit_p(mei_remove), -- cgit v1.2.3 From 6ddf3aea42ba20eadc8ff362926c947ac43c9401 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 7 Aug 2012 00:03:55 +0300 Subject: mei: style : reformat PCI device IDs 1. reformat PCI ids list in hw.h for better readability 2. update some code and brand names Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hw.h | 79 +++++++++++++++++++++++++-------------------------- 1 file changed, 39 insertions(+), 40 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/hw.h b/drivers/misc/mei/hw.h index 24c4c962819..b3b4c6dcbaa 100644 --- a/drivers/misc/mei/hw.h +++ b/drivers/misc/mei/hw.h @@ -40,46 +40,45 @@ /* * MEI device IDs */ -#define MEI_DEV_ID_82946GZ 0x2974 /* 82946GZ/GL */ -#define MEI_DEV_ID_82G35 0x2984 /* 82G35 Express */ -#define MEI_DEV_ID_82Q965 0x2994 /* 82Q963/Q965 */ -#define MEI_DEV_ID_82G965 0x29A4 /* 82P965/G965 */ - -#define MEI_DEV_ID_82GM965 0x2A04 /* Mobile PM965/GM965 */ -#define MEI_DEV_ID_82GME965 0x2A14 /* Mobile GME965/GLE960 */ - -#define MEI_DEV_ID_ICH9_82Q35 0x29B4 /* 82Q35 Express */ -#define MEI_DEV_ID_ICH9_82G33 0x29C4 /* 82G33/G31/P35/P31 Express */ -#define MEI_DEV_ID_ICH9_82Q33 0x29D4 /* 82Q33 Express */ -#define MEI_DEV_ID_ICH9_82X38 0x29E4 /* 82X38/X48 Express */ -#define MEI_DEV_ID_ICH9_3200 0x29F4 /* 3200/3210 Server */ - -#define MEI_DEV_ID_ICH9_6 0x28B4 /* Bearlake */ -#define MEI_DEV_ID_ICH9_7 0x28C4 /* Bearlake */ -#define MEI_DEV_ID_ICH9_8 0x28D4 /* Bearlake */ -#define MEI_DEV_ID_ICH9_9 0x28E4 /* Bearlake */ -#define MEI_DEV_ID_ICH9_10 0x28F4 /* Bearlake */ - -#define MEI_DEV_ID_ICH9M_1 0x2A44 /* Cantiga */ -#define MEI_DEV_ID_ICH9M_2 0x2A54 /* Cantiga */ -#define MEI_DEV_ID_ICH9M_3 0x2A64 /* Cantiga */ -#define MEI_DEV_ID_ICH9M_4 0x2A74 /* Cantiga */ - -#define MEI_DEV_ID_ICH10_1 0x2E04 /* Eaglelake */ -#define MEI_DEV_ID_ICH10_2 0x2E14 /* Eaglelake */ -#define MEI_DEV_ID_ICH10_3 0x2E24 /* Eaglelake */ -#define MEI_DEV_ID_ICH10_4 0x2E34 /* Eaglelake */ - -#define MEI_DEV_ID_IBXPK_1 0x3B64 /* Calpella */ -#define MEI_DEV_ID_IBXPK_2 0x3B65 /* Calpella */ - -#define MEI_DEV_ID_CPT_1 0x1C3A /* Cougerpoint */ -#define MEI_DEV_ID_PBG_1 0x1D3A /* PBG */ - -#define MEI_DEV_ID_PPT_1 0x1E3A /* Pantherpoint PPT */ -#define MEI_DEV_ID_PPT_2 0x1CBA /* Pantherpoint PPT */ -#define MEI_DEV_ID_PPT_3 0x1DBA /* Pantherpoint PPT */ - +#define MEI_DEV_ID_82946GZ 0x2974 /* 82946GZ/GL */ +#define MEI_DEV_ID_82G35 0x2984 /* 82G35 Express */ +#define MEI_DEV_ID_82Q965 0x2994 /* 82Q963/Q965 */ +#define MEI_DEV_ID_82G965 0x29A4 /* 82P965/G965 */ + +#define MEI_DEV_ID_82GM965 0x2A04 /* Mobile PM965/GM965 */ +#define MEI_DEV_ID_82GME965 0x2A14 /* Mobile GME965/GLE960 */ + +#define MEI_DEV_ID_ICH9_82Q35 0x29B4 /* 82Q35 Express */ +#define MEI_DEV_ID_ICH9_82G33 0x29C4 /* 82G33/G31/P35/P31 Express */ +#define MEI_DEV_ID_ICH9_82Q33 0x29D4 /* 82Q33 Express */ +#define MEI_DEV_ID_ICH9_82X38 0x29E4 /* 82X38/X48 Express */ +#define MEI_DEV_ID_ICH9_3200 0x29F4 /* 3200/3210 Server */ + +#define MEI_DEV_ID_ICH9_6 0x28B4 /* Bearlake */ +#define MEI_DEV_ID_ICH9_7 0x28C4 /* Bearlake */ +#define MEI_DEV_ID_ICH9_8 0x28D4 /* Bearlake */ +#define MEI_DEV_ID_ICH9_9 0x28E4 /* Bearlake */ +#define MEI_DEV_ID_ICH9_10 0x28F4 /* Bearlake */ + +#define MEI_DEV_ID_ICH9M_1 0x2A44 /* Cantiga */ +#define MEI_DEV_ID_ICH9M_2 0x2A54 /* Cantiga */ +#define MEI_DEV_ID_ICH9M_3 0x2A64 /* Cantiga */ +#define MEI_DEV_ID_ICH9M_4 0x2A74 /* Cantiga */ + +#define MEI_DEV_ID_ICH10_1 0x2E04 /* Eaglelake */ +#define MEI_DEV_ID_ICH10_2 0x2E14 /* Eaglelake */ +#define MEI_DEV_ID_ICH10_3 0x2E24 /* Eaglelake */ +#define MEI_DEV_ID_ICH10_4 0x2E34 /* Eaglelake */ + +#define MEI_DEV_ID_IBXPK_1 0x3B64 /* Calpella */ +#define MEI_DEV_ID_IBXPK_2 0x3B65 /* Calpella */ + +#define MEI_DEV_ID_CPT_1 0x1C3A /* Couger Point */ +#define MEI_DEV_ID_PBG_1 0x1D3A /* C600/X79 Patsburg */ + +#define MEI_DEV_ID_PPT_1 0x1E3A /* Panther Point */ +#define MEI_DEV_ID_PPT_2 0x1CBA /* Panther Point */ +#define MEI_DEV_ID_PPT_3 0x1DBA /* Panther Point */ /* * MEI HW Section -- cgit v1.2.3 From b210d7506f416e7250eb52c314e5ed08928639dd Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 7 Aug 2012 00:03:56 +0300 Subject: mei: name space for mei device state 1. add MEI_DEV_ prefix for mei device state enums 2. rename mei_state to dev_state 3. add constant to string translation for debug purposes Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/init.c | 54 ++++++++++++++++++++++++++++++-------------- drivers/misc/mei/interrupt.c | 22 +++++++++--------- drivers/misc/mei/iorw.c | 4 ++-- drivers/misc/mei/main.c | 24 ++++++++++---------- drivers/misc/mei/mei_dev.h | 22 ++++++++++-------- drivers/misc/mei/wd.c | 6 ++--- 6 files changed, 77 insertions(+), 55 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index 58b3bf47c8e..cd6a7f1ff91 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c @@ -24,6 +24,25 @@ #include "interface.h" #include +const char *mei_dev_state_str(int state) +{ +#define MEI_DEV_STATE(state) case MEI_DEV_##state: return #state + switch (state) { + MEI_DEV_STATE(INITIALIZING); + MEI_DEV_STATE(INIT_CLIENTS); + MEI_DEV_STATE(ENABLED); + MEI_DEV_STATE(RESETING); + MEI_DEV_STATE(DISABLED); + MEI_DEV_STATE(RECOVERING_FROM_RESET); + MEI_DEV_STATE(POWER_DOWN); + MEI_DEV_STATE(POWER_UP); + default: + return "unkown"; + } +#undef MEI_DEV_STATE +} + + const uuid_le mei_amthi_guid = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, 0xac, 0xa8, 0x46, 0xe0, 0xff, 0x65, 0x81, 0x4c); @@ -123,7 +142,7 @@ struct mei_device *mei_device_init(struct pci_dev *pdev) mutex_init(&dev->device_lock); init_waitqueue_head(&dev->wait_recvd_msg); init_waitqueue_head(&dev->wait_stop_wd); - dev->mei_state = MEI_INITIALIZING; + dev->dev_state = MEI_DEV_INITIALIZING; dev->iamthif_state = MEI_IAMTHIF_IDLE; dev->wd_interface_reg = false; @@ -182,7 +201,7 @@ int mei_hw_init(struct mei_device *dev) } if (err <= 0 && !dev->recvd_msg) { - dev->mei_state = MEI_DISABLED; + dev->dev_state = MEI_DEV_DISABLED; dev_dbg(&dev->pdev->dev, "wait_event_interruptible_timeout failed" "on wait for ME to turn on ME_RDY.\n"); @@ -192,7 +211,7 @@ int mei_hw_init(struct mei_device *dev) if (!(((dev->host_hw_state & H_RDY) == H_RDY) && ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA))) { - dev->mei_state = MEI_DISABLED; + dev->dev_state = MEI_DEV_DISABLED; dev_dbg(&dev->pdev->dev, "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", dev->host_hw_state, dev->me_hw_state); @@ -258,15 +277,15 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) struct mei_cl_cb *cb_next = NULL; bool unexpected; - if (dev->mei_state == MEI_RECOVERING_FROM_RESET) { + if (dev->dev_state == MEI_DEV_RECOVERING_FROM_RESET) { dev->need_reset = true; return; } - unexpected = (dev->mei_state != MEI_INITIALIZING && - dev->mei_state != MEI_DISABLED && - dev->mei_state != MEI_POWER_DOWN && - dev->mei_state != MEI_POWER_UP); + unexpected = (dev->dev_state != MEI_DEV_INITIALIZING && + dev->dev_state != MEI_DEV_DISABLED && + dev->dev_state != MEI_DEV_POWER_DOWN && + dev->dev_state != MEI_DEV_POWER_UP); dev->host_hw_state = mei_hcsr_read(dev); @@ -285,10 +304,10 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) dev->need_reset = false; - if (dev->mei_state != MEI_INITIALIZING) { - if (dev->mei_state != MEI_DISABLED && - dev->mei_state != MEI_POWER_DOWN) - dev->mei_state = MEI_RESETING; + if (dev->dev_state != MEI_DEV_INITIALIZING) { + if (dev->dev_state != MEI_DEV_DISABLED && + dev->dev_state != MEI_DEV_POWER_DOWN) + dev->dev_state = MEI_DEV_RESETING; list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) { @@ -322,7 +341,8 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) dev->host_hw_state, dev->me_hw_state); if (unexpected) - dev_warn(&dev->pdev->dev, "unexpected reset.\n"); + dev_warn(&dev->pdev->dev, "unexpected reset: dev_state = %s\n", + mei_dev_state_str(dev->dev_state)); /* Wake up all readings so they can be interrupted */ list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) { @@ -371,7 +391,7 @@ void mei_host_start_message(struct mei_device *dev) if (mei_write_message(dev, mei_hdr, (unsigned char *)host_start_req, mei_hdr->length)) { dev_dbg(&dev->pdev->dev, "write send version message to FW fail.\n"); - dev->mei_state = MEI_RESETING; + dev->dev_state = MEI_DEV_RESETING; mei_reset(dev, 1); } dev->init_clients_state = MEI_START_MESSAGE; @@ -403,7 +423,7 @@ void mei_host_enum_clients_message(struct mei_device *dev) host_enum_req->hbm_cmd = HOST_ENUM_REQ_CMD; if (mei_write_message(dev, mei_hdr, (unsigned char *)host_enum_req, mei_hdr->length)) { - dev->mei_state = MEI_RESETING; + dev->dev_state = MEI_DEV_RESETING; dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n"); mei_reset(dev, 1); } @@ -444,7 +464,7 @@ void mei_allocate_me_clients_storage(struct mei_device *dev) sizeof(struct mei_me_client), GFP_KERNEL); if (!clients) { dev_dbg(&dev->pdev->dev, "memory allocation for ME clients failed.\n"); - dev->mei_state = MEI_RESETING; + dev->dev_state = MEI_DEV_RESETING; mei_reset(dev, 1); return ; } @@ -490,7 +510,7 @@ int mei_host_client_properties(struct mei_device *dev) if (mei_write_message(dev, mei_header, (unsigned char *)host_cli_req, mei_header->length)) { - dev->mei_state = MEI_RESETING; + dev->dev_state = MEI_DEV_RESETING; dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n"); mei_reset(dev, 1); return -EIO; diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index c6ffbbe5a6c..94370d26ed4 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -633,7 +633,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev, if (version_res->host_version_supported) { dev->version.major_version = HBM_MAJOR_VERSION; dev->version.minor_version = HBM_MINOR_VERSION; - if (dev->mei_state == MEI_INIT_CLIENTS && + if (dev->dev_state == MEI_DEV_INIT_CLIENTS && dev->init_clients_state == MEI_START_MESSAGE) { dev->init_clients_timer = 0; mei_host_enum_clients_message(dev); @@ -707,7 +707,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev, dev->me_clients[dev->me_client_presentation_num].props = props_res->client_properties; - if (dev->mei_state == MEI_INIT_CLIENTS && + if (dev->dev_state == MEI_DEV_INIT_CLIENTS && dev->init_clients_state == MEI_CLIENT_PROPERTIES_MESSAGE) { dev->me_client_index++; @@ -734,7 +734,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev, * Client ID 2 - Reserved for AMTHI */ bitmap_set(dev->host_clients_map, 0, 3); - dev->mei_state = MEI_ENABLED; + dev->dev_state = MEI_DEV_ENABLED; /* if wd initialization fails, initialization the AMTHI client, * otherwise the AMTHI client will be initialized after the WD client connect response @@ -759,7 +759,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev, case HOST_ENUM_RES_CMD: enum_res = (struct hbm_host_enum_response *) mei_msg; memcpy(dev->me_clients_map, enum_res->valid_addresses, 32); - if (dev->mei_state == MEI_INIT_CLIENTS && + if (dev->dev_state == MEI_DEV_INIT_CLIENTS && dev->init_clients_state == MEI_ENUM_CLIENTS_MESSAGE) { dev->init_clients_timer = 0; dev->me_client_presentation_num = 0; @@ -776,7 +776,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev, break; case HOST_STOP_RES_CMD: - dev->mei_state = MEI_DISABLED; + dev->dev_state = MEI_DEV_DISABLED; dev_dbg(&dev->pdev->dev, "resetting because of FW stop response.\n"); mei_reset(dev, 1); break; @@ -1240,7 +1240,7 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list, *slots -= dev->extra_write_index; dev->extra_write_index = 0; } - if (dev->mei_state == MEI_ENABLED) { + if (dev->dev_state == MEI_DEV_ENABLED) { if (dev->wd_pending && mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) { if (mei_wd_send(dev)) @@ -1361,8 +1361,8 @@ void mei_timer(struct work_struct *work) mutex_lock(&dev->device_lock); - if (dev->mei_state != MEI_ENABLED) { - if (dev->mei_state == MEI_INIT_CLIENTS) { + if (dev->dev_state != MEI_DEV_ENABLED) { + if (dev->dev_state == MEI_DEV_INIT_CLIENTS) { if (dev->init_clients_timer) { if (--dev->init_clients_timer == 0) { dev_dbg(&dev->pdev->dev, "IMEI reset due to init clients timeout ,init clients state = %d.\n", @@ -1484,8 +1484,8 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id) /* check if ME wants a reset */ if ((dev->me_hw_state & ME_RDY_HRA) == 0 && - dev->mei_state != MEI_RESETING && - dev->mei_state != MEI_INITIALIZING) { + dev->dev_state != MEI_DEV_RESETING && + dev->dev_state != MEI_DEV_INITIALIZING) { dev_dbg(&dev->pdev->dev, "FW not ready.\n"); mei_reset(dev, 1); mutex_unlock(&dev->device_lock); @@ -1498,7 +1498,7 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id) dev_dbg(&dev->pdev->dev, "we need to start the dev.\n"); dev->host_hw_state |= (H_IE | H_IG | H_RDY); mei_hcsr_set(dev); - dev->mei_state = MEI_INIT_CLIENTS; + dev->dev_state = MEI_DEV_INIT_CLIENTS; dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n"); /* link is established * start sending messages. diff --git a/drivers/misc/mei/iorw.c b/drivers/misc/mei/iorw.c index 9187d852ef9..fcba98eb892 100644 --- a/drivers/misc/mei/iorw.c +++ b/drivers/misc/mei/iorw.c @@ -108,7 +108,7 @@ int mei_ioctl_connect_client(struct file *file, cb->major_file_operations = MEI_IOCTL; - if (dev->mei_state != MEI_ENABLED) { + if (dev->dev_state != MEI_DEV_ENABLED) { rets = -ENODEV; goto end; } @@ -402,7 +402,7 @@ int mei_start_read(struct mei_device *dev, struct mei_cl *cl) if (cl->state != MEI_FILE_CONNECTED) return -ENODEV; - if (dev->mei_state != MEI_ENABLED) + if (dev->dev_state != MEI_DEV_ENABLED) return -ENODEV; dev_dbg(&dev->pdev->dev, "check if read is pending.\n"); diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index dea65c2c920..5c557dd129d 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -232,9 +232,9 @@ static int mei_open(struct inode *inode, struct file *file) goto out_unlock; err = -ENODEV; - if (dev->mei_state != MEI_ENABLED) { - dev_dbg(&dev->pdev->dev, "mei_state != MEI_ENABLED mei_state= %d\n", - dev->mei_state); + if (dev->dev_state != MEI_DEV_ENABLED) { + dev_dbg(&dev->pdev->dev, "dev_state != MEI_ENABLED dev_state = %s\n", + mei_dev_state_str(dev->dev_state)); goto out_unlock; } err = -EMFILE; @@ -384,7 +384,7 @@ static ssize_t mei_read(struct file *file, char __user *ubuf, dev = cl->dev; mutex_lock(&dev->device_lock); - if (dev->mei_state != MEI_ENABLED) { + if (dev->dev_state != MEI_DEV_ENABLED) { rets = -ENODEV; goto out; } @@ -538,7 +538,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf, mutex_lock(&dev->device_lock); - if (dev->mei_state != MEI_ENABLED) { + if (dev->dev_state != MEI_DEV_ENABLED) { mutex_unlock(&dev->device_lock); return -ENODEV; } @@ -613,7 +613,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf, rets = -ENOMEM; goto unlock_dev; } - if (dev->mei_state != MEI_ENABLED) { + if (dev->dev_state != MEI_DEV_ENABLED) { rets = -ENODEV; goto unlock_dev; } @@ -769,7 +769,7 @@ static long mei_ioctl(struct file *file, unsigned int cmd, unsigned long data) dev_dbg(&dev->pdev->dev, "IOCTL cmd = 0x%x", cmd); mutex_lock(&dev->device_lock); - if (dev->mei_state != MEI_ENABLED) { + if (dev->dev_state != MEI_DEV_ENABLED) { rets = -ENODEV; goto out; } @@ -848,7 +848,7 @@ static unsigned int mei_poll(struct file *file, poll_table *wait) mutex_lock(&dev->device_lock); - if (dev->mei_state != MEI_ENABLED) + if (dev->dev_state != MEI_DEV_ENABLED) goto out; @@ -1118,9 +1118,9 @@ static int mei_pci_suspend(struct device *device) /* Stop watchdog if exists */ err = mei_wd_stop(dev, true); /* Set new mei state */ - if (dev->mei_state == MEI_ENABLED || - dev->mei_state == MEI_RECOVERING_FROM_RESET) { - dev->mei_state = MEI_POWER_DOWN; + if (dev->dev_state == MEI_DEV_ENABLED || + dev->dev_state == MEI_DEV_RECOVERING_FROM_RESET) { + dev->dev_state = MEI_DEV_POWER_DOWN; mei_reset(dev, 0); } mutex_unlock(&dev->device_lock); @@ -1162,7 +1162,7 @@ static int mei_pci_resume(struct device *device) } mutex_lock(&dev->device_lock); - dev->mei_state = MEI_POWER_UP; + dev->dev_state = MEI_DEV_POWER_UP; mei_reset(dev, 1); mutex_unlock(&dev->device_lock); diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 1ff1fc678fb..35d0538a597 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -78,17 +78,19 @@ enum file_state { }; /* MEI device states */ -enum mei_states { - MEI_INITIALIZING = 0, - MEI_INIT_CLIENTS, - MEI_ENABLED, - MEI_RESETING, - MEI_DISABLED, - MEI_RECOVERING_FROM_RESET, - MEI_POWER_DOWN, - MEI_POWER_UP +enum mei_dev_state { + MEI_DEV_INITIALIZING = 0, + MEI_DEV_INIT_CLIENTS, + MEI_DEV_ENABLED, + MEI_DEV_RESETING, + MEI_DEV_DISABLED, + MEI_DEV_RECOVERING_FROM_RESET, + MEI_DEV_POWER_DOWN, + MEI_DEV_POWER_UP }; +const char *mei_dev_state_str(int state); + /* init clients states*/ enum mei_init_clients_states { MEI_START_MESSAGE = 0, @@ -218,7 +220,7 @@ struct mei_device { /* * mei device states */ - enum mei_states mei_state; + enum mei_dev_state dev_state; enum mei_init_clients_states init_clients_state; u16 init_clients_timer; bool stop; diff --git a/drivers/misc/mei/wd.c b/drivers/misc/mei/wd.c index 912319e4fa9..3006cca34b1 100644 --- a/drivers/misc/mei/wd.c +++ b/drivers/misc/mei/wd.c @@ -202,10 +202,10 @@ static int mei_wd_ops_start(struct watchdog_device *wd_dev) mutex_lock(&dev->device_lock); - if (dev->mei_state != MEI_ENABLED) { + if (dev->dev_state != MEI_DEV_ENABLED) { dev_dbg(&dev->pdev->dev, - "wd: mei_state != MEI_ENABLED mei_state = %d\n", - dev->mei_state); + "wd: dev_state != MEI_DEV_ENABLED dev_state = %s\n", + mei_dev_state_str(dev->dev_state)); goto end_unlock; } -- cgit v1.2.3 From 9bb3a5897e22bf6af82bc451db9458b1d794f627 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 16 Aug 2012 16:25:33 +0300 Subject: mei: fix device stall after wd is stopped After watchdog was disabled the driver would stall due to wrong calculation of credits reduction The cat&paste bug was introduced in the commit 7bdf72d3d8059a50214069ea4b87c2174645f40f mei: introduce mei_data2slots wrapper Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/interrupt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 94370d26ed4..7d9a91298ec 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -1253,7 +1253,7 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list, if (dev->wd_timeout) *slots -= mei_data2slots(MEI_START_WD_DATA_SIZE); else - *slots -= mei_data2slots(MEI_START_WD_DATA_SIZE); + *slots -= mei_data2slots(MEI_WD_PARAMS_SIZE); } } if (dev->stop) -- cgit v1.2.3 From c8df72920c9cd8e43899a5660ee54a46ac2588a6 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 16 Aug 2012 19:39:41 +0300 Subject: mei: wd: add option WDIOF_SETTIMEOUT According watchdog-kernel-api.txt WDIOF_SETTIMEOUT should be set if the driver supplies set_timeout function Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/wd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/wd.c b/drivers/misc/mei/wd.c index 3006cca34b1..94f2c0a12d9 100644 --- a/drivers/misc/mei/wd.c +++ b/drivers/misc/mei/wd.c @@ -341,7 +341,9 @@ static const struct watchdog_ops wd_ops = { }; static const struct watchdog_info wd_info = { .identity = INTEL_AMT_WATCHDOG_ID, - .options = WDIOF_KEEPALIVEPING | WDIOF_ALARMONLY, + .options = WDIOF_KEEPALIVEPING | + WDIOF_SETTIMEOUT | + WDIOF_ALARMONLY, }; static struct watchdog_device amt_wd_dev = { -- cgit v1.2.3 From 248ffdf7c95726a8dae76e25fdb037899c5b77fa Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 16 Aug 2012 19:39:42 +0300 Subject: mei: wd: rename watchdog constants to be more descriptive 1. rename defines to more be descriptive 2. remove duplicated defines from interface.h 3. add common prefix MEI_ Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/interface.h | 8 -------- drivers/misc/mei/interrupt.c | 4 ++-- drivers/misc/mei/mei_dev.h | 13 +++++++++---- drivers/misc/mei/wd.c | 24 ++++++++++++------------ 4 files changed, 23 insertions(+), 26 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/interface.h b/drivers/misc/mei/interface.h index fb5c7db4723..c1988f564aa 100644 --- a/drivers/misc/mei/interface.h +++ b/drivers/misc/mei/interface.h @@ -23,14 +23,6 @@ #include "mei_dev.h" -#define AMT_WD_DEFAULT_TIMEOUT 120 /* seconds */ -#define AMT_WD_MIN_TIMEOUT 120 /* seconds */ -#define AMT_WD_MAX_TIMEOUT 65535 /* seconds */ - -#define MEI_WATCHDOG_DATA_SIZE 16 -#define MEI_START_WD_DATA_SIZE 20 -#define MEI_WD_PARAMS_SIZE 4 - void mei_read_slots(struct mei_device *dev, unsigned char *buffer, diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 7d9a91298ec..0f25cee6ab8 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -1251,9 +1251,9 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list, dev->wd_pending = false; if (dev->wd_timeout) - *slots -= mei_data2slots(MEI_START_WD_DATA_SIZE); + *slots -= mei_data2slots(MEI_WD_START_MSG_SIZE); else - *slots -= mei_data2slots(MEI_WD_PARAMS_SIZE); + *slots -= mei_data2slots(MEI_WD_STOP_MSG_SIZE); } } if (dev->stop) diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 35d0538a597..64a4f17893e 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -25,9 +25,14 @@ /* * watch dog definition */ -#define MEI_WATCHDOG_DATA_SIZE 16 -#define MEI_START_WD_DATA_SIZE 20 -#define MEI_WD_PARAMS_SIZE 4 +#define MEI_WD_HDR_SIZE 4 +#define MEI_WD_STOP_MSG_SIZE MEI_WD_HDR_SIZE +#define MEI_WD_START_MSG_SIZE (MEI_WD_HDR_SIZE + 16) + +#define MEI_WD_DEFAULT_TIMEOUT 120 /* seconds */ +#define MEI_WD_MIN_TIMEOUT 120 /* seconds */ +#define MEI_WD_MAX_TIMEOUT 65535 /* seconds */ + #define MEI_WD_STATE_INDEPENDENCE_MSG_SENT (1 << 0) #define MEI_RD_MSG_BUF_SIZE (128 * sizeof(u32)) @@ -248,7 +253,7 @@ struct mei_device { bool wd_stopped; bool wd_bypass; /* if false, don't refresh watchdog ME client */ u16 wd_timeout; /* seconds ((wd_data[1] << 8) + wd_data[0]) */ - unsigned char wd_data[MEI_START_WD_DATA_SIZE]; + unsigned char wd_data[MEI_WD_START_MSG_SIZE]; struct file *iamthif_file_object; diff --git a/drivers/misc/mei/wd.c b/drivers/misc/mei/wd.c index 94f2c0a12d9..755a58305a7 100644 --- a/drivers/misc/mei/wd.c +++ b/drivers/misc/mei/wd.c @@ -48,8 +48,8 @@ const uuid_le mei_wd_guid = UUID_LE(0x05B79A6F, 0x4628, 0x4D7F, 0x89, static void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout) { dev_dbg(&dev->pdev->dev, "wd: set timeout=%d.\n", timeout); - memcpy(dev->wd_data, mei_start_wd_params, MEI_WD_PARAMS_SIZE); - memcpy(dev->wd_data + MEI_WD_PARAMS_SIZE, &timeout, sizeof(u16)); + memcpy(dev->wd_data, mei_start_wd_params, MEI_WD_HDR_SIZE); + memcpy(dev->wd_data + MEI_WD_HDR_SIZE, &timeout, sizeof(u16)); } /** @@ -66,7 +66,7 @@ int mei_wd_host_init(struct mei_device *dev) /* look for WD client and connect to it */ dev->wd_cl.state = MEI_FILE_DISCONNECTED; - dev->wd_timeout = AMT_WD_DEFAULT_TIMEOUT; + dev->wd_timeout = MEI_WD_DEFAULT_TIMEOUT; /* find ME WD client */ mei_me_cl_update_filext(dev, &dev->wd_cl, @@ -108,10 +108,10 @@ int mei_wd_send(struct mei_device *dev) mei_hdr->msg_complete = 1; mei_hdr->reserved = 0; - if (!memcmp(dev->wd_data, mei_start_wd_params, MEI_WD_PARAMS_SIZE)) - mei_hdr->length = MEI_START_WD_DATA_SIZE; - else if (!memcmp(dev->wd_data, mei_stop_wd_params, MEI_WD_PARAMS_SIZE)) - mei_hdr->length = MEI_WD_PARAMS_SIZE; + if (!memcmp(dev->wd_data, mei_start_wd_params, MEI_WD_HDR_SIZE)) + mei_hdr->length = MEI_WD_START_MSG_SIZE; + else if (!memcmp(dev->wd_data, mei_stop_wd_params, MEI_WD_HDR_SIZE)) + mei_hdr->length = MEI_WD_STOP_MSG_SIZE; else return -EINVAL; @@ -138,7 +138,7 @@ int mei_wd_stop(struct mei_device *dev, bool preserve) return 0; dev->wd_timeout = 0; - memcpy(dev->wd_data, mei_stop_wd_params, MEI_WD_PARAMS_SIZE); + memcpy(dev->wd_data, mei_stop_wd_params, MEI_WD_STOP_MSG_SIZE); dev->stop = true; ret = mei_flow_ctrl_creds(dev, &dev->wd_cl); @@ -315,7 +315,7 @@ static int mei_wd_ops_set_timeout(struct watchdog_device *wd_dev, unsigned int t return -ENODEV; /* Check Timeout value */ - if (timeout < AMT_WD_MIN_TIMEOUT || timeout > AMT_WD_MAX_TIMEOUT) + if (timeout < MEI_WD_MIN_TIMEOUT || timeout > MEI_WD_MAX_TIMEOUT) return -EINVAL; mutex_lock(&dev->device_lock); @@ -349,9 +349,9 @@ static const struct watchdog_info wd_info = { static struct watchdog_device amt_wd_dev = { .info = &wd_info, .ops = &wd_ops, - .timeout = AMT_WD_DEFAULT_TIMEOUT, - .min_timeout = AMT_WD_MIN_TIMEOUT, - .max_timeout = AMT_WD_MAX_TIMEOUT, + .timeout = MEI_WD_DEFAULT_TIMEOUT, + .min_timeout = MEI_WD_MIN_TIMEOUT, + .max_timeout = MEI_WD_MAX_TIMEOUT, }; -- cgit v1.2.3 From c216fdeb2e7371554c56ba457c374cce9c77f91a Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 16 Aug 2012 19:39:43 +0300 Subject: mei: wd: decouple and revamp watchdog state machine Before ME watchdog was exported through standard watchdog interface it was closed and started together with the mei device. The major issue is that closing ME watchdog disabled also MEI device, to fix this the watchdog state machine has to be independent from MEI state machine. Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/init.c | 1 - drivers/misc/mei/interface.h | 2 +- drivers/misc/mei/interrupt.c | 9 +++------ drivers/misc/mei/main.c | 9 +++++++-- drivers/misc/mei/mei_dev.h | 14 ++++++++++---- drivers/misc/mei/wd.c | 26 +++++++++++++------------- 6 files changed, 34 insertions(+), 27 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index cd6a7f1ff91..98f1430e3e1 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c @@ -330,7 +330,6 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) dev->me_clients_num = 0; dev->rd_msg_hdr = 0; - dev->stop = false; dev->wd_pending = false; /* update the state of the registers after reset */ diff --git a/drivers/misc/mei/interface.h b/drivers/misc/mei/interface.h index c1988f564aa..ec6c785a396 100644 --- a/drivers/misc/mei/interface.h +++ b/drivers/misc/mei/interface.h @@ -56,7 +56,7 @@ int mei_flow_ctrl_creds(struct mei_device *dev, struct mei_cl *cl); int mei_wd_send(struct mei_device *dev); -int mei_wd_stop(struct mei_device *dev, bool preserve); +int mei_wd_stop(struct mei_device *dev); int mei_wd_host_init(struct mei_device *dev); /* * mei_watchdog_register - Registering watchdog interface diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 0f25cee6ab8..0900a711bad 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -1224,10 +1224,9 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list, } } - if (dev->stop && !dev->wd_pending) { - dev->wd_stopped = true; + if (dev->wd_state == MEI_WD_STOPPING) { + dev->wd_state = MEI_WD_IDLE; wake_up_interruptible(&dev->wait_stop_wd); - return 0; } if (dev->extra_write_index) { @@ -1250,14 +1249,12 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list, dev->wd_pending = false; - if (dev->wd_timeout) + if (dev->wd_state == MEI_WD_RUNNING) *slots -= mei_data2slots(MEI_WD_START_MSG_SIZE); else *slots -= mei_data2slots(MEI_WD_STOP_MSG_SIZE); } } - if (dev->stop) - return -ENODEV; /* complete control write list CB */ dev_dbg(&dev->pdev->dev, "complete control write list cb.\n"); diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 5c557dd129d..9a595338ae1 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -1060,7 +1060,9 @@ static void __devexit mei_remove(struct pci_dev *pdev) mutex_lock(&dev->device_lock); - mei_wd_stop(dev, false); + cancel_delayed_work(&dev->timer_work); + + mei_wd_stop(dev); mei_device = NULL; @@ -1115,8 +1117,11 @@ static int mei_pci_suspend(struct device *device) if (!dev) return -ENODEV; mutex_lock(&dev->device_lock); + + cancel_delayed_work(&dev->timer_work); + /* Stop watchdog if exists */ - err = mei_wd_stop(dev, true); + err = mei_wd_stop(dev); /* Set new mei state */ if (dev->dev_state == MEI_DEV_ENABLED || dev->dev_state == MEI_DEV_RECOVERING_FROM_RESET) { diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 64a4f17893e..c8660c0eb1c 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -33,6 +33,8 @@ #define MEI_WD_MIN_TIMEOUT 120 /* seconds */ #define MEI_WD_MAX_TIMEOUT 65535 /* seconds */ +#define MEI_WD_STOP_TIMEOUT 10 /* msecs */ + #define MEI_WD_STATE_INDEPENDENCE_MSG_SENT (1 << 0) #define MEI_RD_MSG_BUF_SIZE (128 * sizeof(u32)) @@ -120,6 +122,12 @@ enum mei_file_transaction_states { MEI_READ_COMPLETE }; +enum mei_wd_states { + MEI_WD_IDLE, + MEI_WD_RUNNING, + MEI_WD_STOPPING, +}; + /* MEI CB */ enum mei_cb_major_types { MEI_READ = 0, @@ -228,7 +236,6 @@ struct mei_device { enum mei_dev_state dev_state; enum mei_init_clients_states init_clients_state; u16 init_clients_timer; - bool stop; bool need_reset; u32 extra_write_index; @@ -248,11 +255,10 @@ struct mei_device { bool mei_host_buffer_is_empty; struct mei_cl wd_cl; + enum mei_wd_states wd_state; bool wd_interface_reg; bool wd_pending; - bool wd_stopped; - bool wd_bypass; /* if false, don't refresh watchdog ME client */ - u16 wd_timeout; /* seconds ((wd_data[1] << 8) + wd_data[0]) */ + u16 wd_timeout; unsigned char wd_data[MEI_WD_START_MSG_SIZE]; diff --git a/drivers/misc/mei/wd.c b/drivers/misc/mei/wd.c index 755a58305a7..0824166a730 100644 --- a/drivers/misc/mei/wd.c +++ b/drivers/misc/mei/wd.c @@ -67,6 +67,7 @@ int mei_wd_host_init(struct mei_device *dev) /* look for WD client and connect to it */ dev->wd_cl.state = MEI_FILE_DISCONNECTED; dev->wd_timeout = MEI_WD_DEFAULT_TIMEOUT; + dev->wd_state = MEI_WD_IDLE; /* find ME WD client */ mei_me_cl_update_filext(dev, &dev->wd_cl, @@ -128,18 +129,17 @@ int mei_wd_send(struct mei_device *dev) * -EIO when message send fails * -EINVAL when invalid message is to be sent */ -int mei_wd_stop(struct mei_device *dev, bool preserve) +int mei_wd_stop(struct mei_device *dev) { int ret; - u16 wd_timeout = dev->wd_timeout; - cancel_delayed_work(&dev->timer_work); - if (dev->wd_cl.state != MEI_FILE_CONNECTED || !dev->wd_timeout) + if (dev->wd_cl.state != MEI_FILE_CONNECTED || + dev->wd_state != MEI_WD_RUNNING) return 0; - dev->wd_timeout = 0; memcpy(dev->wd_data, mei_stop_wd_params, MEI_WD_STOP_MSG_SIZE); - dev->stop = true; + + dev->wd_state = MEI_WD_STOPPING; ret = mei_flow_ctrl_creds(dev, &dev->wd_cl); if (ret < 0) @@ -161,13 +161,14 @@ int mei_wd_stop(struct mei_device *dev, bool preserve) } else { dev->wd_pending = true; } - dev->wd_stopped = false; + mutex_unlock(&dev->device_lock); ret = wait_event_interruptible_timeout(dev->wait_stop_wd, - dev->wd_stopped, 10 * HZ); + dev->wd_state == MEI_WD_IDLE, + msecs_to_jiffies(MEI_WD_STOP_TIMEOUT)); mutex_lock(&dev->device_lock); - if (dev->wd_stopped) { + if (dev->wd_state == MEI_WD_IDLE) { dev_dbg(&dev->pdev->dev, "wd: stop completed ret=%d.\n", ret); ret = 0; } else { @@ -177,9 +178,6 @@ int mei_wd_stop(struct mei_device *dev, bool preserve) "wd: stop failed to complete ret=%d.\n", ret); } - if (preserve) - dev->wd_timeout = wd_timeout; - out: return ret; } @@ -239,7 +237,7 @@ static int mei_wd_ops_stop(struct watchdog_device *wd_dev) return -ENODEV; mutex_lock(&dev->device_lock); - mei_wd_stop(dev, false); + mei_wd_stop(dev); mutex_unlock(&dev->device_lock); return 0; @@ -269,6 +267,8 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev) goto end; } + dev->wd_state = MEI_WD_RUNNING; + /* Check if we can send the ping to HW*/ if (dev->mei_host_buffer_is_empty && mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) { -- cgit v1.2.3 From 09649a85adfedde99b47b6ccef3fea696fad72be Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 16 Aug 2012 19:39:44 +0300 Subject: mei: wd: use watchdog_set/get_drvdata for passing mei_device use watchdog_set/get_drvdata for passing mei_device to watchdog_ops handlers instead of using global mei_device Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/wd.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/wd.c b/drivers/misc/mei/wd.c index 0824166a730..d96c537f046 100644 --- a/drivers/misc/mei/wd.c +++ b/drivers/misc/mei/wd.c @@ -194,7 +194,7 @@ static int mei_wd_ops_start(struct watchdog_device *wd_dev) int err = -ENODEV; struct mei_device *dev; - dev = pci_get_drvdata(mei_device); + dev = watchdog_get_drvdata(wd_dev); if (!dev) return -ENODEV; @@ -231,8 +231,8 @@ end_unlock: static int mei_wd_ops_stop(struct watchdog_device *wd_dev) { struct mei_device *dev; - dev = pci_get_drvdata(mei_device); + dev = watchdog_get_drvdata(wd_dev); if (!dev) return -ENODEV; @@ -254,8 +254,8 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev) { int ret = 0; struct mei_device *dev; - dev = pci_get_drvdata(mei_device); + dev = watchdog_get_drvdata(wd_dev); if (!dev) return -ENODEV; @@ -309,8 +309,8 @@ end: static int mei_wd_ops_set_timeout(struct watchdog_device *wd_dev, unsigned int timeout) { struct mei_device *dev; - dev = pci_get_drvdata(mei_device); + dev = watchdog_get_drvdata(wd_dev); if (!dev) return -ENODEV; @@ -355,25 +355,28 @@ static struct watchdog_device amt_wd_dev = { }; -void mei_watchdog_register(struct mei_device *dev) +void mei_watchdog_register(struct mei_device *dev) { - dev_dbg(&dev->pdev->dev, "dev->wd_timeout =%d.\n", dev->wd_timeout); - if (watchdog_register_device(&amt_wd_dev)) { dev_err(&dev->pdev->dev, "wd: unable to register watchdog device.\n"); dev->wd_interface_reg = false; - } else { - dev_dbg(&dev->pdev->dev, - "wd: successfully register watchdog interface.\n"); - dev->wd_interface_reg = true; + return; } + + dev_dbg(&dev->pdev->dev, + "wd: successfully register watchdog interface.\n"); + dev->wd_interface_reg = true; + watchdog_set_drvdata(&amt_wd_dev, dev); } void mei_watchdog_unregister(struct mei_device *dev) { - if (dev->wd_interface_reg) - watchdog_unregister_device(&amt_wd_dev); + if (!dev->wd_interface_reg) + return; + + watchdog_set_drvdata(&amt_wd_dev, NULL); + watchdog_unregister_device(&amt_wd_dev); dev->wd_interface_reg = false; } -- cgit v1.2.3 From 73ac0e9eafe8d04a3cdb39b7c7c1e3f4154676b5 Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Sun, 29 Jul 2012 17:08:29 +0545 Subject: pch_phub: fix sparse warning sparse warns about using 0 as NULL pointer, drivers/misc/pch_phub.c:702:44: warning: Using plain integer as NULL pointer Signed-off-by: Devendra Naga Signed-off-by: Greg Kroah-Hartman --- drivers/misc/pch_phub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/misc') diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c index 9fbcacd703d..e2c066e510f 100644 --- a/drivers/misc/pch_phub.c +++ b/drivers/misc/pch_phub.c @@ -699,7 +699,7 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev, chip->pch_phub_base_address = pci_iomap(pdev, 1, 0); - if (chip->pch_phub_base_address == 0) { + if (chip->pch_phub_base_address == NULL) { dev_err(&pdev->dev, "%s : pci_iomap FAILED", __func__); ret = -ENOMEM; goto err_pci_iomap; -- cgit v1.2.3 From cfeb28525faa855b7f0bd06a330a6961f4c5127e Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Sun, 29 Jul 2012 17:08:30 +0545 Subject: pch_phub: use module_pci_driver this driver's pch_phub_pci_init, and pch_phub_pci_exit functions with the module_init and module_exit calls can be replaced with module_pci_driver Signed-off-by: Devendra Naga Signed-off-by: Greg Kroah-Hartman --- drivers/misc/pch_phub.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c index e2c066e510f..c9f20dae185 100644 --- a/drivers/misc/pch_phub.c +++ b/drivers/misc/pch_phub.c @@ -893,18 +893,7 @@ static struct pci_driver pch_phub_driver = { .resume = pch_phub_resume }; -static int __init pch_phub_pci_init(void) -{ - return pci_register_driver(&pch_phub_driver); -} - -static void __exit pch_phub_pci_exit(void) -{ - pci_unregister_driver(&pch_phub_driver); -} - -module_init(pch_phub_pci_init); -module_exit(pch_phub_pci_exit); +module_pci_driver(pch_phub_driver); MODULE_DESCRIPTION("Intel EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7223) PHUB"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 567fd1d4a66a2d6e5599be0ada582e0a3dbd23d4 Mon Sep 17 00:00:00 2001 From: Qiang Liu Date: Thu, 9 Aug 2012 16:23:31 +0800 Subject: carma: remove unnecessary DMA_INTERRUPT capability These drivers set the DMA_INTERRUPT capability bit when requesting a DMA controller channel. This was historical, and is no longer needed. Recent changes to the drivers/dma/fsldma.c driver have removed support for this flag. This makes the carma drivers unable to find a DMA channel with the required capabilities. Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Signed-off-by: Ira W. Snyder Signed-off-by: Greg Kroah-Hartman --- drivers/misc/carma/carma-fpga-program.c | 1 - drivers/misc/carma/carma-fpga.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/carma/carma-fpga-program.c b/drivers/misc/carma/carma-fpga-program.c index a2d25e4857e..eaddfe9db14 100644 --- a/drivers/misc/carma/carma-fpga-program.c +++ b/drivers/misc/carma/carma-fpga-program.c @@ -978,7 +978,6 @@ static int fpga_of_probe(struct platform_device *op) dev_set_drvdata(priv->dev, priv); dma_cap_zero(mask); dma_cap_set(DMA_MEMCPY, mask); - dma_cap_set(DMA_INTERRUPT, mask); dma_cap_set(DMA_SLAVE, mask); dma_cap_set(DMA_SG, mask); diff --git a/drivers/misc/carma/carma-fpga.c b/drivers/misc/carma/carma-fpga.c index 8c279da0741..0c43297ed9a 100644 --- a/drivers/misc/carma/carma-fpga.c +++ b/drivers/misc/carma/carma-fpga.c @@ -666,7 +666,7 @@ static int data_submit_dma(struct fpga_device *priv, struct data_buf *buf) src = SYS_FPGA_BLOCK; tx = chan->device->device_prep_dma_memcpy(chan, dst, src, REG_BLOCK_SIZE, - DMA_PREP_INTERRUPT); + 0); if (!tx) { dev_err(priv->dev, "unable to prep SYS-FPGA DMA\n"); return -ENOMEM; -- cgit v1.2.3 From 4eb64ee135af6b477ff149a2072bcfa3118afb94 Mon Sep 17 00:00:00 2001 From: Sourav Poddar Date: Mon, 6 Aug 2012 14:58:44 +0530 Subject: driver: misc: bmp085: remove "of_match_table" property. There is an automatic binding done for I2C devices in the of_i2c core code. So, DT will be able to bind to any I2C device using the already existing table: MODULE_DEVICE_TABLE(i2c, bmp085_id). Tested on omap5430 evm. Signed-off-by: Sourav Poddar Cc: Benoit Cousson Cc: Santosh Shilimkar Acked-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/misc/bmp085-i2c.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/bmp085-i2c.c b/drivers/misc/bmp085-i2c.c index 9943971c13e..a4f33c995ea 100644 --- a/drivers/misc/bmp085-i2c.c +++ b/drivers/misc/bmp085-i2c.c @@ -57,12 +57,6 @@ static int bmp085_i2c_remove(struct i2c_client *client) return bmp085_remove(&client->dev); } -static const struct of_device_id bmp085_of_match[] = { - { .compatible = "bosch,bmp085", }, - { }, -}; -MODULE_DEVICE_TABLE(of, bmp085_of_match); - static const struct i2c_device_id bmp085_id[] = { { BMP085_NAME, 0 }, { "bmp180", 0 }, @@ -74,7 +68,6 @@ static struct i2c_driver bmp085_i2c_driver = { .driver = { .owner = THIS_MODULE, .name = BMP085_NAME, - .of_match_table = bmp085_of_match }, .id_table = bmp085_id, .probe = bmp085_i2c_probe, -- cgit v1.2.3 From eccf2979b2c034b516e01b8a104c3739f7ef07d1 Mon Sep 17 00:00:00 2001 From: Pavan Savoy Date: Fri, 3 Aug 2012 14:49:39 -0500 Subject: drivers/misc/ti-st: remove gpio handling A platform hook to enable/disable the chip was introduced to perform specific activities to power-up and power-down the WL chip. Moving the power-up/down sequence also there makes more sense, since different platforms have begun to have their own ways to power-up/down the chip. This patch removes all of the gpio handling done by the driver in st_kim_start/st_kim_stop & any of the gpio request done in the probe function. Signed-off-by: Pavan Savoy Signed-off-by: Greg Kroah-Hartman --- drivers/misc/ti-st/st_kim.c | 37 +------------------------------------ 1 file changed, 1 insertion(+), 36 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c index 7c14f8fd98d..5c99995f4ea 100644 --- a/drivers/misc/ti-st/st_kim.c +++ b/drivers/misc/ti-st/st_kim.c @@ -454,11 +454,6 @@ long st_kim_start(void *kim_data) if (pdata->chip_enable) pdata->chip_enable(kim_gdata); - /* Configure BT nShutdown to HIGH state */ - gpio_set_value(kim_gdata->nshutdown, GPIO_LOW); - mdelay(5); /* FIXME: a proper toggle */ - gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH); - mdelay(100); /* re-initialize the completion */ INIT_COMPLETION(kim_gdata->ldisc_installed); /* send notification to UIM */ @@ -500,8 +495,7 @@ long st_kim_start(void *kim_data) * (b) upon failure to either install ldisc or download firmware. * The function is responsible to (a) notify UIM about un-installation, * (b) flush UART if the ldisc was installed. - * (c) reset BT_EN - pull down nshutdown at the end. - * (d) invoke platform's chip disabling routine. + * (c) invoke platform's chip disabling routine. */ long st_kim_stop(void *kim_data) { @@ -533,13 +527,6 @@ long st_kim_stop(void *kim_data) return -ETIMEDOUT; } - /* By default configure BT nShutdown to LOW state */ - gpio_set_value(kim_gdata->nshutdown, GPIO_LOW); - mdelay(1); - gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH); - mdelay(1); - gpio_set_value(kim_gdata->nshutdown, GPIO_LOW); - /* platform specific disable */ if (pdata->chip_disable) pdata->chip_disable(kim_gdata); @@ -731,20 +718,6 @@ static int kim_probe(struct platform_device *pdev) /* refer to itself */ kim_gdata->core_data->kim_data = kim_gdata; - /* Claim the chip enable nShutdown gpio from the system */ - kim_gdata->nshutdown = pdata->nshutdown_gpio; - status = gpio_request(kim_gdata->nshutdown, "kim"); - if (unlikely(status)) { - pr_err(" gpio %ld request failed ", kim_gdata->nshutdown); - return status; - } - - /* Configure nShutdown GPIO as output=0 */ - status = gpio_direction_output(kim_gdata->nshutdown, 0); - if (unlikely(status)) { - pr_err(" unable to configure gpio %ld", kim_gdata->nshutdown); - return status; - } /* get reference of pdev for request_firmware */ kim_gdata->kim_pdev = pdev; @@ -780,18 +753,10 @@ static int kim_probe(struct platform_device *pdev) static int kim_remove(struct platform_device *pdev) { - /* free the GPIOs requested */ - struct ti_st_plat_data *pdata = pdev->dev.platform_data; struct kim_data_s *kim_gdata; kim_gdata = dev_get_drvdata(&pdev->dev); - /* Free the Bluetooth/FM/GPIO - * nShutdown gpio from the system - */ - gpio_free(pdata->nshutdown_gpio); - pr_info("nshutdown GPIO Freed"); - debugfs_remove_recursive(kim_debugfs_dir); sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp); pr_info("sysfs entries removed"); -- cgit v1.2.3 From 27712b3928bec9b1a889d7f60d718a35ca6c23b3 Mon Sep 17 00:00:00 2001 From: Pavan Savoy Date: Fri, 3 Aug 2012 14:49:40 -0500 Subject: drivers/misc/ti-st: remove sparse warnings remove sparse warnings by assigning right storage specifiers to functions and also clean-up the declarations in the include/linux/ti_wilink_st.h Signed-off-by: Pavan Savoy Signed-off-by: Greg Kroah-Hartman --- drivers/misc/ti-st/st_core.c | 12 +++++++----- drivers/misc/ti-st/st_kim.c | 12 ++++++------ 2 files changed, 13 insertions(+), 11 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/ti-st/st_core.c b/drivers/misc/ti-st/st_core.c index acfaeeb9e01..46937b10726 100644 --- a/drivers/misc/ti-st/st_core.c +++ b/drivers/misc/ti-st/st_core.c @@ -30,11 +30,13 @@ #include +extern void st_kim_recv(void *, const unsigned char *, long); +void st_int_recv(void *, const unsigned char *, long); /* function pointer pointing to either, * st_kim_recv during registration to receive fw download responses * st_int_recv after registration to receive proto stack responses */ -void (*st_recv) (void*, const unsigned char*, long); +static void (*st_recv) (void *, const unsigned char *, long); /********************************************************************/ static void add_channel_to_table(struct st_data_s *st_gdata, @@ -100,7 +102,7 @@ int st_int_write(struct st_data_s *st_gdata, * push the skb received to relevant * protocol stacks */ -void st_send_frame(unsigned char chnl_id, struct st_data_s *st_gdata) +static void st_send_frame(unsigned char chnl_id, struct st_data_s *st_gdata) { pr_debug(" %s(prot:%d) ", __func__, chnl_id); @@ -140,7 +142,7 @@ void st_send_frame(unsigned char chnl_id, struct st_data_s *st_gdata) * This function is being called with spin lock held, protocol drivers are * only expected to complete their waits and do nothing more than that. */ -void st_reg_complete(struct st_data_s *st_gdata, char err) +static void st_reg_complete(struct st_data_s *st_gdata, char err) { unsigned char i = 0; pr_info(" %s ", __func__); @@ -379,7 +381,7 @@ done: * completely, return that skb which has the pending data. * In normal cases, return top of txq. */ -struct sk_buff *st_int_dequeue(struct st_data_s *st_gdata) +static struct sk_buff *st_int_dequeue(struct st_data_s *st_gdata) { struct sk_buff *returning_skb; @@ -401,7 +403,7 @@ struct sk_buff *st_int_dequeue(struct st_data_s *st_gdata) * txq and waitq needs protection since the other contexts * may be sending data, waking up chip. */ -void st_int_enqueue(struct st_data_s *st_gdata, struct sk_buff *skb) +static void st_int_enqueue(struct st_data_s *st_gdata, struct sk_buff *skb) { unsigned long flags = 0; diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c index 5c99995f4ea..847406abd0f 100644 --- a/drivers/misc/ti-st/st_kim.c +++ b/drivers/misc/ti-st/st_kim.c @@ -63,7 +63,7 @@ static struct platform_device *st_get_plat_device(int id) * in case of error don't complete so that waiting for proper * response times out */ -void validate_firmware_response(struct kim_data_s *kim_gdata) +static void validate_firmware_response(struct kim_data_s *kim_gdata) { struct sk_buff *skb = kim_gdata->rx_skb; if (unlikely(skb->data[5] != 0)) { @@ -119,7 +119,7 @@ static inline int kim_check_data_len(struct kim_data_s *kim_gdata, int len) * have been observed to come in bursts of different * tty_receive and hence the logic */ -void kim_int_recv(struct kim_data_s *kim_gdata, +static void kim_int_recv(struct kim_data_s *kim_gdata, const unsigned char *data, long count) { const unsigned char *ptr; @@ -236,7 +236,7 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name) return 0; } -void skip_change_remote_baud(unsigned char **ptr, long *len) +static void skip_change_remote_baud(unsigned char **ptr, long *len) { unsigned char *nxt_action, *cur_action; cur_action = *ptr; @@ -688,7 +688,7 @@ static const struct file_operations list_debugfs_fops = { * board-*.c file */ -struct dentry *kim_debugfs_dir; +static struct dentry *kim_debugfs_dir; static int kim_probe(struct platform_device *pdev) { long status; @@ -769,7 +769,7 @@ static int kim_remove(struct platform_device *pdev) return 0; } -int kim_suspend(struct platform_device *pdev, pm_message_t state) +static int kim_suspend(struct platform_device *pdev, pm_message_t state) { struct ti_st_plat_data *pdata = pdev->dev.platform_data; @@ -779,7 +779,7 @@ int kim_suspend(struct platform_device *pdev, pm_message_t state) return -EOPNOTSUPP; } -int kim_resume(struct platform_device *pdev) +static int kim_resume(struct platform_device *pdev) { struct ti_st_plat_data *pdata = pdev->dev.platform_data; -- cgit v1.2.3 From b64365a52625e6ec5cf05dd984fba0fa69b24623 Mon Sep 17 00:00:00 2001 From: Pavan Savoy Date: Fri, 3 Aug 2012 14:49:41 -0500 Subject: drivers/misc/ti-st: chip_disable on timeout If the communication with the WiLink breaks down for whatever reasons & the ti-st driver is unable to un-install the line-discipline during clean-up in st_kim_stop, the GPIO should be held low (BT_EN=0) & the platform's chip disable hook shall also be called. Signed-off-by: Pavan Savoy Signed-off-by: Greg Kroah-Hartman --- drivers/misc/ti-st/st_kim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/misc') diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c index 847406abd0f..54ff644aa56 100644 --- a/drivers/misc/ti-st/st_kim.c +++ b/drivers/misc/ti-st/st_kim.c @@ -524,7 +524,7 @@ long st_kim_stop(void *kim_data) msecs_to_jiffies(LDISC_TIME)); if (!err) { /* timeout */ pr_err(" timed out waiting for ldisc to be un-installed"); - return -ETIMEDOUT; + err = -ETIMEDOUT; } /* platform specific disable */ -- cgit v1.2.3 From 537023580d2de09fed3c3ebdca7025572a4ad083 Mon Sep 17 00:00:00 2001 From: Pavan Savoy Date: Fri, 3 Aug 2012 14:49:42 -0500 Subject: drivers/misc/ti-st: use cpu friendly completions Be nice to CPU and don't hog the resources, use a nice wait_for_interruptible timeout for completions instead of wait_for_timeout which is non-interruptible. Signed-off-by: Pavan Savoy Signed-off-by: Greg Kroah-Hartman --- drivers/misc/ti-st/st_kim.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c index 54ff644aa56..0f36db3aa40 100644 --- a/drivers/misc/ti-st/st_kim.c +++ b/drivers/misc/ti-st/st_kim.c @@ -207,8 +207,8 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name) return -EIO; } - if (!wait_for_completion_timeout - (&kim_gdata->kim_rcvd, msecs_to_jiffies(CMD_RESP_TIME))) { + if (!wait_for_completion_interruptible_timeout( + &kim_gdata->kim_rcvd, msecs_to_jiffies(CMD_RESP_TIME))) { pr_err(" waiting for ver info- timed out "); return -ETIMEDOUT; } @@ -370,9 +370,9 @@ static long download_firmware(struct kim_data_s *kim_gdata) break; case ACTION_WAIT_EVENT: /* wait */ pr_debug("W"); - if (!wait_for_completion_timeout - (&kim_gdata->kim_rcvd, - msecs_to_jiffies(CMD_RESP_TIME))) { + if (!wait_for_completion_interruptible_timeout( + &kim_gdata->kim_rcvd, + msecs_to_jiffies(CMD_RESP_TIME))) { pr_err("response timeout during fw download "); /* timed out */ release_firmware(kim_gdata->fw_entry); @@ -462,8 +462,8 @@ long st_kim_start(void *kim_data) sysfs_notify(&kim_gdata->kim_pdev->dev.kobj, NULL, "install"); /* wait for ldisc to be installed */ - err = wait_for_completion_timeout(&kim_gdata->ldisc_installed, - msecs_to_jiffies(LDISC_TIME)); + err = wait_for_completion_interruptible_timeout( + &kim_gdata->ldisc_installed, msecs_to_jiffies(LDISC_TIME)); if (!err) { /* ldisc installation timeout, * flush uart, power cycle BT_EN */ @@ -520,8 +520,8 @@ long st_kim_stop(void *kim_data) sysfs_notify(&kim_gdata->kim_pdev->dev.kobj, NULL, "install"); /* wait for ldisc to be un-installed */ - err = wait_for_completion_timeout(&kim_gdata->ldisc_installed, - msecs_to_jiffies(LDISC_TIME)); + err = wait_for_completion_interruptible_timeout( + &kim_gdata->ldisc_installed, msecs_to_jiffies(LDISC_TIME)); if (!err) { /* timeout */ pr_err(" timed out waiting for ldisc to be un-installed"); err = -ETIMEDOUT; -- cgit v1.2.3 From 8565adbc821487accbabe82a03c40daf7a3b92ca Mon Sep 17 00:00:00 2001 From: Pavan Savoy Date: Fri, 3 Aug 2012 14:49:43 -0500 Subject: drivers/misc/ti-st: fix read fw version cmd If the read firmware version response from the chip is split into multiple frames of UART buffer being received by the host, the TI-ST driver as of today is unable to put the pieces of response together unlike other responses. Signed-off-by: Pavan Savoy Signed-off-by: Greg Kroah-Hartman --- drivers/misc/ti-st/st_kim.c | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c index 0f36db3aa40..04a819944f6 100644 --- a/drivers/misc/ti-st/st_kim.c +++ b/drivers/misc/ti-st/st_kim.c @@ -66,7 +66,24 @@ static struct platform_device *st_get_plat_device(int id) static void validate_firmware_response(struct kim_data_s *kim_gdata) { struct sk_buff *skb = kim_gdata->rx_skb; - if (unlikely(skb->data[5] != 0)) { + if (!skb) + return; + + /* these magic numbers are the position in the response buffer which + * allows us to distinguish whether the response is for the read + * version info. command + */ + if (skb->data[2] == 0x01 && skb->data[3] == 0x01 && + skb->data[4] == 0x10 && skb->data[5] == 0x00) { + /* fw version response */ + memcpy(kim_gdata->resp_buffer, + kim_gdata->rx_skb->data, + kim_gdata->rx_skb->len); + complete_all(&kim_gdata->kim_rcvd); + kim_gdata->rx_state = ST_W4_PACKET_TYPE; + kim_gdata->rx_skb = NULL; + kim_gdata->rx_count = 0; + } else if (unlikely(skb->data[5] != 0)) { pr_err("no proper response during fw download"); pr_err("data6 %x", skb->data[5]); kfree_skb(skb); @@ -213,10 +230,13 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name) return -ETIMEDOUT; } INIT_COMPLETION(kim_gdata->kim_rcvd); + /* the positions 12 & 13 in the response buffer provide with the + * chip, major & minor numbers + */ version = - MAKEWORD(kim_gdata->resp_buffer[13], - kim_gdata->resp_buffer[14]); + MAKEWORD(kim_gdata->resp_buffer[12], + kim_gdata->resp_buffer[13]); chip = (version & 0x7C00) >> 10; min_ver = (version & 0x007F); maj_ver = (version & 0x0380) >> 7; @@ -410,16 +430,10 @@ void st_kim_recv(void *disc_data, const unsigned char *data, long count) struct st_data_s *st_gdata = (struct st_data_s *)disc_data; struct kim_data_s *kim_gdata = st_gdata->kim_data; - /* copy to local buffer */ - if (unlikely(data[4] == 0x01 && data[5] == 0x10 && data[0] == 0x04)) { - /* must be the read_ver_cmd */ - memcpy(kim_gdata->resp_buffer, data, count); - complete_all(&kim_gdata->kim_rcvd); - return; - } else { - kim_int_recv(kim_gdata, data, count); - /* either completes or times out */ - } + /* proceed to gather all data and distinguish read fw version response + * from other fw responses when data gathering is complete + */ + kim_int_recv(kim_gdata, data, count); return; } -- cgit v1.2.3 From 877cdf3949cc67d00677a1dfb913001f324ac40d Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Fri, 3 Aug 2012 14:49:44 -0500 Subject: drivers/misc/ti-st: check chip_awake NULL check Before calling on any of the platform hooks, shared transport driver checks for the validity of the platform hooks as to whether it is provided or not. A wrong function was being checked for, before the chip_awake hook was called by the HCI-LL sleep logic handler. This patch corrects the check. Signed-off-by: Pavan Savoy Signed-off-by: Matthias Kaehlcke Signed-off-by: Greg Kroah-Hartman --- drivers/misc/ti-st/st_ll.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/misc') diff --git a/drivers/misc/ti-st/st_ll.c b/drivers/misc/ti-st/st_ll.c index 1ff460a8e9c..93b4d67cc4a 100644 --- a/drivers/misc/ti-st/st_ll.c +++ b/drivers/misc/ti-st/st_ll.c @@ -87,7 +87,7 @@ static void ll_device_want_to_wakeup(struct st_data_s *st_data) /* communicate to platform about chip wakeup */ kim_data = st_data->kim_data; pdata = kim_data->kim_pdev->dev.platform_data; - if (pdata->chip_asleep) + if (pdata->chip_awake) pdata->chip_awake(NULL); } -- cgit v1.2.3