Merge v3.6-rc3 into 'char-misc-next'
This resolves a conflict in: drivers/misc/mei/interrupt.c Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Коммит
7da59d2fe3
|
@ -0,0 +1,22 @@
|
||||||
|
w1-gpio devicetree bindings
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
|
||||||
|
- compatible: "w1-gpio"
|
||||||
|
- gpios: one or two GPIO specs:
|
||||||
|
- the first one is used as data I/O pin
|
||||||
|
- the second one is optional. If specified, it is used as
|
||||||
|
enable pin for an external pin pullup.
|
||||||
|
|
||||||
|
Optional properties:
|
||||||
|
|
||||||
|
- linux,open-drain: if specified, the data pin is considered in
|
||||||
|
open-drain mode.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
onewire@0 {
|
||||||
|
compatible = "w1-gpio";
|
||||||
|
gpios = <&gpio 126 0>, <&gpio 105 0>;
|
||||||
|
};
|
||||||
|
|
|
@ -784,8 +784,10 @@ static int __init tlclk_init(void)
|
||||||
}
|
}
|
||||||
tlclk_major = ret;
|
tlclk_major = ret;
|
||||||
alarm_events = kzalloc( sizeof(struct tlclk_alarms), GFP_KERNEL);
|
alarm_events = kzalloc( sizeof(struct tlclk_alarms), GFP_KERNEL);
|
||||||
if (!alarm_events)
|
if (!alarm_events) {
|
||||||
|
ret = -ENOMEM;
|
||||||
goto out1;
|
goto out1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Read telecom clock IRQ number (Set by BIOS) */
|
/* Read telecom clock IRQ number (Set by BIOS) */
|
||||||
if (!request_region(TLCLK_BASE, 8, "telco_clock")) {
|
if (!request_region(TLCLK_BASE, 8, "telco_clock")) {
|
||||||
|
|
|
@ -57,12 +57,6 @@ static int bmp085_i2c_remove(struct i2c_client *client)
|
||||||
return bmp085_remove(&client->dev);
|
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[] = {
|
static const struct i2c_device_id bmp085_id[] = {
|
||||||
{ BMP085_NAME, 0 },
|
{ BMP085_NAME, 0 },
|
||||||
{ "bmp180", 0 },
|
{ "bmp180", 0 },
|
||||||
|
@ -74,7 +68,6 @@ static struct i2c_driver bmp085_i2c_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.name = BMP085_NAME,
|
.name = BMP085_NAME,
|
||||||
.of_match_table = bmp085_of_match
|
|
||||||
},
|
},
|
||||||
.id_table = bmp085_id,
|
.id_table = bmp085_id,
|
||||||
.probe = bmp085_i2c_probe,
|
.probe = bmp085_i2c_probe,
|
||||||
|
|
|
@ -978,7 +978,6 @@ static int fpga_of_probe(struct platform_device *op)
|
||||||
dev_set_drvdata(priv->dev, priv);
|
dev_set_drvdata(priv->dev, priv);
|
||||||
dma_cap_zero(mask);
|
dma_cap_zero(mask);
|
||||||
dma_cap_set(DMA_MEMCPY, mask);
|
dma_cap_set(DMA_MEMCPY, mask);
|
||||||
dma_cap_set(DMA_INTERRUPT, mask);
|
|
||||||
dma_cap_set(DMA_SLAVE, mask);
|
dma_cap_set(DMA_SLAVE, mask);
|
||||||
dma_cap_set(DMA_SG, mask);
|
dma_cap_set(DMA_SG, mask);
|
||||||
|
|
||||||
|
|
|
@ -666,7 +666,7 @@ static int data_submit_dma(struct fpga_device *priv, struct data_buf *buf)
|
||||||
src = SYS_FPGA_BLOCK;
|
src = SYS_FPGA_BLOCK;
|
||||||
tx = chan->device->device_prep_dma_memcpy(chan, dst, src,
|
tx = chan->device->device_prep_dma_memcpy(chan, dst, src,
|
||||||
REG_BLOCK_SIZE,
|
REG_BLOCK_SIZE,
|
||||||
DMA_PREP_INTERRUPT);
|
0);
|
||||||
if (!tx) {
|
if (!tx) {
|
||||||
dev_err(priv->dev, "unable to prep SYS-FPGA DMA\n");
|
dev_err(priv->dev, "unable to prep SYS-FPGA DMA\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
|
@ -40,46 +40,45 @@
|
||||||
/*
|
/*
|
||||||
* MEI device IDs
|
* MEI device IDs
|
||||||
*/
|
*/
|
||||||
#define MEI_DEV_ID_82946GZ 0x2974 /* 82946GZ/GL */
|
#define MEI_DEV_ID_82946GZ 0x2974 /* 82946GZ/GL */
|
||||||
#define MEI_DEV_ID_82G35 0x2984 /* 82G35 Express */
|
#define MEI_DEV_ID_82G35 0x2984 /* 82G35 Express */
|
||||||
#define MEI_DEV_ID_82Q965 0x2994 /* 82Q963/Q965 */
|
#define MEI_DEV_ID_82Q965 0x2994 /* 82Q963/Q965 */
|
||||||
#define MEI_DEV_ID_82G965 0x29A4 /* 82P965/G965 */
|
#define MEI_DEV_ID_82G965 0x29A4 /* 82P965/G965 */
|
||||||
|
|
||||||
#define MEI_DEV_ID_82GM965 0x2A04 /* Mobile PM965/GM965 */
|
#define MEI_DEV_ID_82GM965 0x2A04 /* Mobile PM965/GM965 */
|
||||||
#define MEI_DEV_ID_82GME965 0x2A14 /* Mobile GME965/GLE960 */
|
#define MEI_DEV_ID_82GME965 0x2A14 /* Mobile GME965/GLE960 */
|
||||||
|
|
||||||
#define MEI_DEV_ID_ICH9_82Q35 0x29B4 /* 82Q35 Express */
|
#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_82G33 0x29C4 /* 82G33/G31/P35/P31 Express */
|
||||||
#define MEI_DEV_ID_ICH9_82Q33 0x29D4 /* 82Q33 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_82X38 0x29E4 /* 82X38/X48 Express */
|
||||||
#define MEI_DEV_ID_ICH9_3200 0x29F4 /* 3200/3210 Server */
|
#define MEI_DEV_ID_ICH9_3200 0x29F4 /* 3200/3210 Server */
|
||||||
|
|
||||||
#define MEI_DEV_ID_ICH9_6 0x28B4 /* Bearlake */
|
#define MEI_DEV_ID_ICH9_6 0x28B4 /* Bearlake */
|
||||||
#define MEI_DEV_ID_ICH9_7 0x28C4 /* Bearlake */
|
#define MEI_DEV_ID_ICH9_7 0x28C4 /* Bearlake */
|
||||||
#define MEI_DEV_ID_ICH9_8 0x28D4 /* Bearlake */
|
#define MEI_DEV_ID_ICH9_8 0x28D4 /* Bearlake */
|
||||||
#define MEI_DEV_ID_ICH9_9 0x28E4 /* Bearlake */
|
#define MEI_DEV_ID_ICH9_9 0x28E4 /* Bearlake */
|
||||||
#define MEI_DEV_ID_ICH9_10 0x28F4 /* Bearlake */
|
#define MEI_DEV_ID_ICH9_10 0x28F4 /* Bearlake */
|
||||||
|
|
||||||
#define MEI_DEV_ID_ICH9M_1 0x2A44 /* Cantiga */
|
#define MEI_DEV_ID_ICH9M_1 0x2A44 /* Cantiga */
|
||||||
#define MEI_DEV_ID_ICH9M_2 0x2A54 /* Cantiga */
|
#define MEI_DEV_ID_ICH9M_2 0x2A54 /* Cantiga */
|
||||||
#define MEI_DEV_ID_ICH9M_3 0x2A64 /* Cantiga */
|
#define MEI_DEV_ID_ICH9M_3 0x2A64 /* Cantiga */
|
||||||
#define MEI_DEV_ID_ICH9M_4 0x2A74 /* Cantiga */
|
#define MEI_DEV_ID_ICH9M_4 0x2A74 /* Cantiga */
|
||||||
|
|
||||||
#define MEI_DEV_ID_ICH10_1 0x2E04 /* Eaglelake */
|
#define MEI_DEV_ID_ICH10_1 0x2E04 /* Eaglelake */
|
||||||
#define MEI_DEV_ID_ICH10_2 0x2E14 /* Eaglelake */
|
#define MEI_DEV_ID_ICH10_2 0x2E14 /* Eaglelake */
|
||||||
#define MEI_DEV_ID_ICH10_3 0x2E24 /* Eaglelake */
|
#define MEI_DEV_ID_ICH10_3 0x2E24 /* Eaglelake */
|
||||||
#define MEI_DEV_ID_ICH10_4 0x2E34 /* Eaglelake */
|
#define MEI_DEV_ID_ICH10_4 0x2E34 /* Eaglelake */
|
||||||
|
|
||||||
#define MEI_DEV_ID_IBXPK_1 0x3B64 /* Calpella */
|
#define MEI_DEV_ID_IBXPK_1 0x3B64 /* Calpella */
|
||||||
#define MEI_DEV_ID_IBXPK_2 0x3B65 /* Calpella */
|
#define MEI_DEV_ID_IBXPK_2 0x3B65 /* Calpella */
|
||||||
|
|
||||||
#define MEI_DEV_ID_CPT_1 0x1C3A /* Cougerpoint */
|
#define MEI_DEV_ID_CPT_1 0x1C3A /* Couger Point */
|
||||||
#define MEI_DEV_ID_PBG_1 0x1D3A /* PBG */
|
#define MEI_DEV_ID_PBG_1 0x1D3A /* C600/X79 Patsburg */
|
||||||
|
|
||||||
#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_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
|
* MEI HW Section
|
||||||
|
|
|
@ -24,6 +24,25 @@
|
||||||
#include "interface.h"
|
#include "interface.h"
|
||||||
#include <linux/mei.h>
|
#include <linux/mei.h>
|
||||||
|
|
||||||
|
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,
|
const uuid_le mei_amthi_guid = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, 0xac,
|
||||||
0xa8, 0x46, 0xe0, 0xff, 0x65,
|
0xa8, 0x46, 0xe0, 0xff, 0x65,
|
||||||
0x81, 0x4c);
|
0x81, 0x4c);
|
||||||
|
@ -123,7 +142,7 @@ struct mei_device *mei_device_init(struct pci_dev *pdev)
|
||||||
mutex_init(&dev->device_lock);
|
mutex_init(&dev->device_lock);
|
||||||
init_waitqueue_head(&dev->wait_recvd_msg);
|
init_waitqueue_head(&dev->wait_recvd_msg);
|
||||||
init_waitqueue_head(&dev->wait_stop_wd);
|
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->iamthif_state = MEI_IAMTHIF_IDLE;
|
||||||
dev->wd_interface_reg = false;
|
dev->wd_interface_reg = false;
|
||||||
|
|
||||||
|
@ -182,7 +201,7 @@ int mei_hw_init(struct mei_device *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err <= 0 && !dev->recvd_msg) {
|
if (err <= 0 && !dev->recvd_msg) {
|
||||||
dev->mei_state = MEI_DISABLED;
|
dev->dev_state = MEI_DEV_DISABLED;
|
||||||
dev_dbg(&dev->pdev->dev,
|
dev_dbg(&dev->pdev->dev,
|
||||||
"wait_event_interruptible_timeout failed"
|
"wait_event_interruptible_timeout failed"
|
||||||
"on wait for ME to turn on ME_RDY.\n");
|
"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) &&
|
if (!(((dev->host_hw_state & H_RDY) == H_RDY) &&
|
||||||
((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA))) {
|
((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,
|
dev_dbg(&dev->pdev->dev,
|
||||||
"host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
|
"host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
|
||||||
dev->host_hw_state, dev->me_hw_state);
|
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;
|
struct mei_cl_cb *cb_next = NULL;
|
||||||
bool unexpected;
|
bool unexpected;
|
||||||
|
|
||||||
if (dev->mei_state == MEI_RECOVERING_FROM_RESET) {
|
if (dev->dev_state == MEI_DEV_RECOVERING_FROM_RESET) {
|
||||||
dev->need_reset = true;
|
dev->need_reset = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
unexpected = (dev->mei_state != MEI_INITIALIZING &&
|
unexpected = (dev->dev_state != MEI_DEV_INITIALIZING &&
|
||||||
dev->mei_state != MEI_DISABLED &&
|
dev->dev_state != MEI_DEV_DISABLED &&
|
||||||
dev->mei_state != MEI_POWER_DOWN &&
|
dev->dev_state != MEI_DEV_POWER_DOWN &&
|
||||||
dev->mei_state != MEI_POWER_UP);
|
dev->dev_state != MEI_DEV_POWER_UP);
|
||||||
|
|
||||||
dev->host_hw_state = mei_hcsr_read(dev);
|
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;
|
dev->need_reset = false;
|
||||||
|
|
||||||
if (dev->mei_state != MEI_INITIALIZING) {
|
if (dev->dev_state != MEI_DEV_INITIALIZING) {
|
||||||
if (dev->mei_state != MEI_DISABLED &&
|
if (dev->dev_state != MEI_DEV_DISABLED &&
|
||||||
dev->mei_state != MEI_POWER_DOWN)
|
dev->dev_state != MEI_DEV_POWER_DOWN)
|
||||||
dev->mei_state = MEI_RESETING;
|
dev->dev_state = MEI_DEV_RESETING;
|
||||||
|
|
||||||
list_for_each_entry_safe(cl_pos,
|
list_for_each_entry_safe(cl_pos,
|
||||||
cl_next, &dev->file_list, link) {
|
cl_next, &dev->file_list, link) {
|
||||||
|
@ -311,7 +330,6 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
|
||||||
|
|
||||||
dev->me_clients_num = 0;
|
dev->me_clients_num = 0;
|
||||||
dev->rd_msg_hdr = 0;
|
dev->rd_msg_hdr = 0;
|
||||||
dev->stop = false;
|
|
||||||
dev->wd_pending = false;
|
dev->wd_pending = false;
|
||||||
|
|
||||||
/* update the state of the registers after reset */
|
/* update the state of the registers after reset */
|
||||||
|
@ -322,7 +340,8 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
|
||||||
dev->host_hw_state, dev->me_hw_state);
|
dev->host_hw_state, dev->me_hw_state);
|
||||||
|
|
||||||
if (unexpected)
|
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 */
|
/* Wake up all readings so they can be interrupted */
|
||||||
list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) {
|
list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) {
|
||||||
|
@ -371,7 +390,7 @@ void mei_host_start_message(struct mei_device *dev)
|
||||||
if (mei_write_message(dev, mei_hdr, (unsigned char *)host_start_req,
|
if (mei_write_message(dev, mei_hdr, (unsigned char *)host_start_req,
|
||||||
mei_hdr->length)) {
|
mei_hdr->length)) {
|
||||||
dev_dbg(&dev->pdev->dev, "write send version message to FW fail.\n");
|
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);
|
mei_reset(dev, 1);
|
||||||
}
|
}
|
||||||
dev->init_clients_state = MEI_START_MESSAGE;
|
dev->init_clients_state = MEI_START_MESSAGE;
|
||||||
|
@ -403,7 +422,7 @@ void mei_host_enum_clients_message(struct mei_device *dev)
|
||||||
host_enum_req->hbm_cmd = HOST_ENUM_REQ_CMD;
|
host_enum_req->hbm_cmd = HOST_ENUM_REQ_CMD;
|
||||||
if (mei_write_message(dev, mei_hdr, (unsigned char *)host_enum_req,
|
if (mei_write_message(dev, mei_hdr, (unsigned char *)host_enum_req,
|
||||||
mei_hdr->length)) {
|
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");
|
dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n");
|
||||||
mei_reset(dev, 1);
|
mei_reset(dev, 1);
|
||||||
}
|
}
|
||||||
|
@ -444,7 +463,7 @@ void mei_allocate_me_clients_storage(struct mei_device *dev)
|
||||||
sizeof(struct mei_me_client), GFP_KERNEL);
|
sizeof(struct mei_me_client), GFP_KERNEL);
|
||||||
if (!clients) {
|
if (!clients) {
|
||||||
dev_dbg(&dev->pdev->dev, "memory allocation for ME clients failed.\n");
|
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);
|
mei_reset(dev, 1);
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
@ -490,7 +509,7 @@ int mei_host_client_properties(struct mei_device *dev)
|
||||||
if (mei_write_message(dev, mei_header,
|
if (mei_write_message(dev, mei_header,
|
||||||
(unsigned char *)host_cli_req,
|
(unsigned char *)host_cli_req,
|
||||||
mei_header->length)) {
|
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");
|
dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n");
|
||||||
mei_reset(dev, 1);
|
mei_reset(dev, 1);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
@ -522,12 +541,12 @@ void mei_cl_init(struct mei_cl *priv, struct mei_device *dev)
|
||||||
priv->dev = 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)
|
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) {
|
dev->me_clients[i].props.protocol_name) == 0) {
|
||||||
res = i;
|
res = i;
|
||||||
break;
|
break;
|
||||||
|
@ -538,35 +557,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
|
* sets client_id in mei_file_private if found
|
||||||
* @dev: the device structure
|
* @dev: the device structure
|
||||||
* @priv: private file structure to set client_id in
|
* @cl: private file structure to set client_id in
|
||||||
* @cguid: searched guid of ME client
|
* @cuuid: searched uuid of ME client
|
||||||
* @client_id: id of host client to be set in file private structure
|
* @client_id: id of host client to be set in file private structure
|
||||||
*
|
*
|
||||||
* returns ME client index
|
* returns ME client index
|
||||||
*/
|
*/
|
||||||
u8 mei_find_me_client_update_filext(struct mei_device *dev, struct mei_cl *priv,
|
int mei_me_cl_update_filext(struct mei_device *dev, struct mei_cl *cl,
|
||||||
const uuid_le *cguid, u8 client_id)
|
const uuid_le *cuuid, u8 host_cl_id)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!dev || !priv || !cguid)
|
if (!dev || !cl || !cuuid)
|
||||||
return 0;
|
return -EINVAL;
|
||||||
|
|
||||||
/* check for valid client id */
|
/* check for valid client id */
|
||||||
i = mei_find_me_client_index(dev, *cguid);
|
i = mei_me_cl_by_uuid(dev, cuuid);
|
||||||
if (i >= 0) {
|
if (i >= 0) {
|
||||||
priv->me_client_id = dev->me_clients[i].client_id;
|
cl->me_client_id = dev->me_clients[i].client_id;
|
||||||
priv->state = MEI_FILE_CONNECTING;
|
cl->state = MEI_FILE_CONNECTING;
|
||||||
priv->host_client_id = client_id;
|
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 (u8)i;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -577,16 +596,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)
|
void mei_host_init_iamthif(struct mei_device *dev)
|
||||||
{
|
{
|
||||||
u8 i;
|
int i;
|
||||||
unsigned char *msg_buf;
|
unsigned char *msg_buf;
|
||||||
|
|
||||||
mei_cl_init(&dev->iamthif_cl, dev);
|
mei_cl_init(&dev->iamthif_cl, dev);
|
||||||
dev->iamthif_cl.state = MEI_FILE_DISCONNECTED;
|
dev->iamthif_cl.state = MEI_FILE_DISCONNECTED;
|
||||||
|
|
||||||
/* find ME amthi client */
|
/* 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);
|
&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");
|
dev_dbg(&dev->pdev->dev, "failed to find iamthif client.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,14 +23,6 @@
|
||||||
#include "mei_dev.h"
|
#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,
|
void mei_read_slots(struct mei_device *dev,
|
||||||
unsigned char *buffer,
|
unsigned char *buffer,
|
||||||
|
@ -64,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_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);
|
int mei_wd_host_init(struct mei_device *dev);
|
||||||
/*
|
/*
|
||||||
* mei_watchdog_register - Registering watchdog interface
|
* mei_watchdog_register - Registering watchdog interface
|
||||||
|
|
|
@ -633,7 +633,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
|
||||||
if (version_res->host_version_supported) {
|
if (version_res->host_version_supported) {
|
||||||
dev->version.major_version = HBM_MAJOR_VERSION;
|
dev->version.major_version = HBM_MAJOR_VERSION;
|
||||||
dev->version.minor_version = HBM_MINOR_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_state == MEI_START_MESSAGE) {
|
||||||
dev->init_clients_timer = 0;
|
dev->init_clients_timer = 0;
|
||||||
mei_host_enum_clients_message(dev);
|
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
|
dev->me_clients[dev->me_client_presentation_num].props
|
||||||
= props_res->client_properties;
|
= props_res->client_properties;
|
||||||
|
|
||||||
if (dev->mei_state == MEI_INIT_CLIENTS &&
|
if (dev->dev_state == MEI_DEV_INIT_CLIENTS &&
|
||||||
dev->init_clients_state ==
|
dev->init_clients_state ==
|
||||||
MEI_CLIENT_PROPERTIES_MESSAGE) {
|
MEI_CLIENT_PROPERTIES_MESSAGE) {
|
||||||
dev->me_client_index++;
|
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
|
* Client ID 2 - Reserved for AMTHI
|
||||||
*/
|
*/
|
||||||
bitmap_set(dev->host_clients_map, 0, 3);
|
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,
|
/* if wd initialization fails, initialization the AMTHI client,
|
||||||
* otherwise the AMTHI client will be initialized after the WD client connect response
|
* 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:
|
case HOST_ENUM_RES_CMD:
|
||||||
enum_res = (struct hbm_host_enum_response *) mei_msg;
|
enum_res = (struct hbm_host_enum_response *) mei_msg;
|
||||||
memcpy(dev->me_clients_map, enum_res->valid_addresses, 32);
|
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_state == MEI_ENUM_CLIENTS_MESSAGE) {
|
||||||
dev->init_clients_timer = 0;
|
dev->init_clients_timer = 0;
|
||||||
dev->me_client_presentation_num = 0;
|
dev->me_client_presentation_num = 0;
|
||||||
|
@ -776,7 +776,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HOST_STOP_RES_CMD:
|
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");
|
dev_dbg(&dev->pdev->dev, "resetting because of FW stop response.\n");
|
||||||
mei_reset(dev, 1);
|
mei_reset(dev, 1);
|
||||||
break;
|
break;
|
||||||
|
@ -1224,10 +1224,9 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev->stop && !dev->wd_pending) {
|
if (dev->wd_state == MEI_WD_STOPPING) {
|
||||||
dev->wd_stopped = true;
|
dev->wd_state = MEI_WD_IDLE;
|
||||||
wake_up_interruptible(&dev->wait_stop_wd);
|
wake_up_interruptible(&dev->wait_stop_wd);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev->extra_write_index) {
|
if (dev->extra_write_index) {
|
||||||
|
@ -1240,7 +1239,7 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
|
||||||
*slots -= dev->extra_write_index;
|
*slots -= dev->extra_write_index;
|
||||||
dev->extra_write_index = 0;
|
dev->extra_write_index = 0;
|
||||||
}
|
}
|
||||||
if (dev->mei_state == MEI_ENABLED) {
|
if (dev->dev_state == MEI_DEV_ENABLED) {
|
||||||
if (dev->wd_pending &&
|
if (dev->wd_pending &&
|
||||||
mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) {
|
mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) {
|
||||||
if (mei_wd_send(dev))
|
if (mei_wd_send(dev))
|
||||||
|
@ -1250,14 +1249,12 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
|
||||||
|
|
||||||
dev->wd_pending = false;
|
dev->wd_pending = false;
|
||||||
|
|
||||||
if (dev->wd_timeout)
|
if (dev->wd_state == MEI_WD_RUNNING)
|
||||||
*slots -= mei_data2slots(MEI_START_WD_DATA_SIZE);
|
*slots -= mei_data2slots(MEI_WD_START_MSG_SIZE);
|
||||||
else
|
else
|
||||||
*slots -= mei_data2slots(MEI_WD_PARAMS_SIZE);
|
*slots -= mei_data2slots(MEI_WD_STOP_MSG_SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dev->stop)
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
/* complete control write list CB */
|
/* complete control write list CB */
|
||||||
dev_dbg(&dev->pdev->dev, "complete control write list cb.\n");
|
dev_dbg(&dev->pdev->dev, "complete control write list cb.\n");
|
||||||
|
@ -1361,8 +1358,8 @@ void mei_timer(struct work_struct *work)
|
||||||
|
|
||||||
|
|
||||||
mutex_lock(&dev->device_lock);
|
mutex_lock(&dev->device_lock);
|
||||||
if (dev->mei_state != MEI_ENABLED) {
|
if (dev->dev_state != MEI_DEV_ENABLED) {
|
||||||
if (dev->mei_state == MEI_INIT_CLIENTS) {
|
if (dev->dev_state == MEI_DEV_INIT_CLIENTS) {
|
||||||
if (dev->init_clients_timer) {
|
if (dev->init_clients_timer) {
|
||||||
if (--dev->init_clients_timer == 0) {
|
if (--dev->init_clients_timer == 0) {
|
||||||
dev_dbg(&dev->pdev->dev, "IMEI reset due to init clients timeout ,init clients state = %d.\n",
|
dev_dbg(&dev->pdev->dev, "IMEI reset due to init clients timeout ,init clients state = %d.\n",
|
||||||
|
@ -1484,8 +1481,8 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id)
|
||||||
|
|
||||||
/* check if ME wants a reset */
|
/* check if ME wants a reset */
|
||||||
if ((dev->me_hw_state & ME_RDY_HRA) == 0 &&
|
if ((dev->me_hw_state & ME_RDY_HRA) == 0 &&
|
||||||
dev->mei_state != MEI_RESETING &&
|
dev->dev_state != MEI_DEV_RESETING &&
|
||||||
dev->mei_state != MEI_INITIALIZING) {
|
dev->dev_state != MEI_DEV_INITIALIZING) {
|
||||||
dev_dbg(&dev->pdev->dev, "FW not ready.\n");
|
dev_dbg(&dev->pdev->dev, "FW not ready.\n");
|
||||||
mei_reset(dev, 1);
|
mei_reset(dev, 1);
|
||||||
mutex_unlock(&dev->device_lock);
|
mutex_unlock(&dev->device_lock);
|
||||||
|
@ -1498,7 +1495,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_dbg(&dev->pdev->dev, "we need to start the dev.\n");
|
||||||
dev->host_hw_state |= (H_IE | H_IG | H_RDY);
|
dev->host_hw_state |= (H_IE | H_IG | H_RDY);
|
||||||
mei_hcsr_set(dev);
|
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");
|
dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n");
|
||||||
/* link is established
|
/* link is established
|
||||||
* start sending messages.
|
* start sending messages.
|
||||||
|
|
|
@ -38,7 +38,31 @@
|
||||||
#include <linux/mei.h>
|
#include <linux/mei.h>
|
||||||
#include "interface.h"
|
#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
|
* mei_ioctl_connect_client - the connect to fw client IOCTL function
|
||||||
|
@ -84,7 +108,7 @@ int mei_ioctl_connect_client(struct file *file,
|
||||||
|
|
||||||
cb->major_file_operations = MEI_IOCTL;
|
cb->major_file_operations = MEI_IOCTL;
|
||||||
|
|
||||||
if (dev->mei_state != MEI_ENABLED) {
|
if (dev->dev_state != MEI_DEV_ENABLED) {
|
||||||
rets = -ENODEV;
|
rets = -ENODEV;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
@ -95,7 +119,7 @@ int mei_ioctl_connect_client(struct file *file,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* find ME client we're trying to connect to */
|
/* 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) {
|
if (i >= 0 && !dev->me_clients[i].props.fixed_address) {
|
||||||
cl->me_client_id = dev->me_clients[i].client_id;
|
cl->me_client_id = dev->me_clients[i].client_id;
|
||||||
cl->state = MEI_FILE_CONNECTING;
|
cl->state = MEI_FILE_CONNECTING;
|
||||||
|
@ -273,19 +297,12 @@ int amthi_read(struct mei_device *dev, struct file *file,
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < dev->me_clients_num; i++) {
|
i = mei_me_cl_by_id(dev, dev->iamthif_cl.me_client_id);
|
||||||
if (dev->me_clients[i].client_id ==
|
|
||||||
dev->iamthif_cl.me_client_id)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == dev->me_clients_num) {
|
if (i < 0) {
|
||||||
dev_dbg(&dev->pdev->dev, "amthi client not found.\n");
|
dev_dbg(&dev->pdev->dev, "amthi client not found.\n");
|
||||||
return -ENODEV;
|
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");
|
dev_dbg(&dev->pdev->dev, "checking amthi data\n");
|
||||||
cb = find_amthi_read_list_entry(dev, file);
|
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;
|
dev->iamthif_timer = 0;
|
||||||
|
|
||||||
if (cb) {
|
if (cb) {
|
||||||
timeout = cb->read_time +
|
timeout = cb->read_time + msecs_to_jiffies(IAMTHIF_READ_TIMER);
|
||||||
msecs_to_jiffies(IAMTHIF_READ_TIMER);
|
|
||||||
dev_dbg(&dev->pdev->dev, "amthi timeout = %lud\n",
|
dev_dbg(&dev->pdev->dev, "amthi timeout = %lud\n",
|
||||||
timeout);
|
timeout);
|
||||||
|
|
||||||
|
@ -386,7 +402,7 @@ int mei_start_read(struct mei_device *dev, struct mei_cl *cl)
|
||||||
if (cl->state != MEI_FILE_CONNECTED)
|
if (cl->state != MEI_FILE_CONNECTED)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
if (dev->mei_state != MEI_ENABLED)
|
if (dev->dev_state != MEI_DEV_ENABLED)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
dev_dbg(&dev->pdev->dev, "check if read is pending.\n");
|
dev_dbg(&dev->pdev->dev, "check if read is pending.\n");
|
||||||
|
@ -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",
|
dev_dbg(&dev->pdev->dev, "allocation call back successful. host client = %d, ME client = %d\n",
|
||||||
cl->host_client_id, cl->me_client_id);
|
cl->host_client_id, cl->me_client_id);
|
||||||
|
i = mei_me_cl_by_id(dev, cl->me_client_id);
|
||||||
for (i = 0; i < dev->me_clients_num; i++) {
|
if (i < 0) {
|
||||||
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) {
|
|
||||||
rets = -ENODEV;
|
rets = -ENODEV;
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,8 +41,6 @@
|
||||||
#include <linux/mei.h>
|
#include <linux/mei.h>
|
||||||
#include "interface.h"
|
#include "interface.h"
|
||||||
|
|
||||||
static const char mei_driver_name[] = "mei";
|
|
||||||
|
|
||||||
/* The device pointer */
|
/* The device pointer */
|
||||||
/* Currently this driver works as long as there is only a single AMT device. */
|
/* Currently this driver works as long as there is only a single AMT device. */
|
||||||
struct pci_dev *mei_device;
|
struct pci_dev *mei_device;
|
||||||
|
@ -234,9 +232,9 @@ static int mei_open(struct inode *inode, struct file *file)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
err = -ENODEV;
|
err = -ENODEV;
|
||||||
if (dev->mei_state != MEI_ENABLED) {
|
if (dev->dev_state != MEI_DEV_ENABLED) {
|
||||||
dev_dbg(&dev->pdev->dev, "mei_state != MEI_ENABLED mei_state= %d\n",
|
dev_dbg(&dev->pdev->dev, "dev_state != MEI_ENABLED dev_state = %s\n",
|
||||||
dev->mei_state);
|
mei_dev_state_str(dev->dev_state));
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
err = -EMFILE;
|
err = -EMFILE;
|
||||||
|
@ -386,17 +384,16 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
|
||||||
dev = cl->dev;
|
dev = cl->dev;
|
||||||
|
|
||||||
mutex_lock(&dev->device_lock);
|
mutex_lock(&dev->device_lock);
|
||||||
if (dev->mei_state != MEI_ENABLED) {
|
if (dev->dev_state != MEI_DEV_ENABLED) {
|
||||||
rets = -ENODEV;
|
rets = -ENODEV;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((cl->sm_state & MEI_WD_STATE_INDEPENDENCE_MSG_SENT) == 0) {
|
if ((cl->sm_state & MEI_WD_STATE_INDEPENDENCE_MSG_SENT) == 0) {
|
||||||
/* Do not allow to read watchdog client */
|
/* 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) {
|
if (i >= 0) {
|
||||||
struct mei_me_client *me_client = &dev->me_clients[i];
|
struct mei_me_client *me_client = &dev->me_clients[i];
|
||||||
|
|
||||||
if (cl->me_client_id == me_client->client_id) {
|
if (cl->me_client_id == me_client->client_id) {
|
||||||
rets = -EBADF;
|
rets = -EBADF;
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -541,7 +538,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
|
||||||
|
|
||||||
mutex_lock(&dev->device_lock);
|
mutex_lock(&dev->device_lock);
|
||||||
|
|
||||||
if (dev->mei_state != MEI_ENABLED) {
|
if (dev->dev_state != MEI_DEV_ENABLED) {
|
||||||
mutex_unlock(&dev->device_lock);
|
mutex_unlock(&dev->device_lock);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
@ -616,26 +613,16 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
|
||||||
rets = -ENOMEM;
|
rets = -ENOMEM;
|
||||||
goto unlock_dev;
|
goto unlock_dev;
|
||||||
}
|
}
|
||||||
if (dev->mei_state != MEI_ENABLED) {
|
if (dev->dev_state != MEI_DEV_ENABLED) {
|
||||||
rets = -ENODEV;
|
rets = -ENODEV;
|
||||||
goto unlock_dev;
|
goto unlock_dev;
|
||||||
}
|
}
|
||||||
for (i = 0; i < dev->me_clients_num; i++) {
|
i = mei_me_cl_by_id(dev, dev->iamthif_cl.me_client_id);
|
||||||
if (dev->me_clients[i].client_id ==
|
if (i < 0) {
|
||||||
dev->iamthif_cl.me_client_id)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (WARN_ON(dev->me_clients[i].client_id != cl->me_client_id)) {
|
|
||||||
rets = -ENODEV;
|
rets = -ENODEV;
|
||||||
goto unlock_dev;
|
goto unlock_dev;
|
||||||
}
|
}
|
||||||
if (i == dev->me_clients_num ||
|
if (length > dev->me_clients[i].props.max_msg_length ||
|
||||||
(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 ||
|
|
||||||
length <= 0) {
|
length <= 0) {
|
||||||
rets = -EMSGSIZE;
|
rets = -EMSGSIZE;
|
||||||
goto unlock_dev;
|
goto unlock_dev;
|
||||||
|
@ -688,16 +675,8 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
|
||||||
cl->me_client_id);
|
cl->me_client_id);
|
||||||
goto unlock_dev;
|
goto unlock_dev;
|
||||||
}
|
}
|
||||||
for (i = 0; i < dev->me_clients_num; i++) {
|
i = mei_me_cl_by_id(dev, cl->me_client_id);
|
||||||
if (dev->me_clients[i].client_id ==
|
if (i < 0) {
|
||||||
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) {
|
|
||||||
rets = -ENODEV;
|
rets = -ENODEV;
|
||||||
goto unlock_dev;
|
goto unlock_dev;
|
||||||
}
|
}
|
||||||
|
@ -790,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);
|
dev_dbg(&dev->pdev->dev, "IOCTL cmd = 0x%x", cmd);
|
||||||
|
|
||||||
mutex_lock(&dev->device_lock);
|
mutex_lock(&dev->device_lock);
|
||||||
if (dev->mei_state != MEI_ENABLED) {
|
if (dev->dev_state != MEI_DEV_ENABLED) {
|
||||||
rets = -ENODEV;
|
rets = -ENODEV;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -869,7 +848,7 @@ static unsigned int mei_poll(struct file *file, poll_table *wait)
|
||||||
|
|
||||||
mutex_lock(&dev->device_lock);
|
mutex_lock(&dev->device_lock);
|
||||||
|
|
||||||
if (dev->mei_state != MEI_ENABLED)
|
if (dev->dev_state != MEI_DEV_ENABLED)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
|
||||||
|
@ -979,7 +958,7 @@ static int __devinit mei_probe(struct pci_dev *pdev,
|
||||||
/* set PCI host mastering */
|
/* set PCI host mastering */
|
||||||
pci_set_master(pdev);
|
pci_set_master(pdev);
|
||||||
/* pci request regions for mei driver */
|
/* pci request regions for mei driver */
|
||||||
err = pci_request_regions(pdev, mei_driver_name);
|
err = pci_request_regions(pdev, KBUILD_MODNAME);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(&pdev->dev, "failed to get pci regions.\n");
|
dev_err(&pdev->dev, "failed to get pci regions.\n");
|
||||||
goto disable_device;
|
goto disable_device;
|
||||||
|
@ -1004,12 +983,12 @@ static int __devinit mei_probe(struct pci_dev *pdev,
|
||||||
err = request_threaded_irq(pdev->irq,
|
err = request_threaded_irq(pdev->irq,
|
||||||
NULL,
|
NULL,
|
||||||
mei_interrupt_thread_handler,
|
mei_interrupt_thread_handler,
|
||||||
IRQF_ONESHOT, mei_driver_name, dev);
|
IRQF_ONESHOT, KBUILD_MODNAME, dev);
|
||||||
else
|
else
|
||||||
err = request_threaded_irq(pdev->irq,
|
err = request_threaded_irq(pdev->irq,
|
||||||
mei_interrupt_quick_handler,
|
mei_interrupt_quick_handler,
|
||||||
mei_interrupt_thread_handler,
|
mei_interrupt_thread_handler,
|
||||||
IRQF_SHARED, mei_driver_name, dev);
|
IRQF_SHARED, KBUILD_MODNAME, dev);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(&pdev->dev, "request_threaded_irq failure. irq = %d\n",
|
dev_err(&pdev->dev, "request_threaded_irq failure. irq = %d\n",
|
||||||
|
@ -1081,7 +1060,9 @@ static void __devexit mei_remove(struct pci_dev *pdev)
|
||||||
|
|
||||||
mutex_lock(&dev->device_lock);
|
mutex_lock(&dev->device_lock);
|
||||||
|
|
||||||
mei_wd_stop(dev, false);
|
cancel_delayed_work(&dev->timer_work);
|
||||||
|
|
||||||
|
mei_wd_stop(dev);
|
||||||
|
|
||||||
mei_device = NULL;
|
mei_device = NULL;
|
||||||
|
|
||||||
|
@ -1136,12 +1117,15 @@ static int mei_pci_suspend(struct device *device)
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
mutex_lock(&dev->device_lock);
|
mutex_lock(&dev->device_lock);
|
||||||
|
|
||||||
|
cancel_delayed_work(&dev->timer_work);
|
||||||
|
|
||||||
/* Stop watchdog if exists */
|
/* Stop watchdog if exists */
|
||||||
err = mei_wd_stop(dev, true);
|
err = mei_wd_stop(dev);
|
||||||
/* Set new mei state */
|
/* Set new mei state */
|
||||||
if (dev->mei_state == MEI_ENABLED ||
|
if (dev->dev_state == MEI_DEV_ENABLED ||
|
||||||
dev->mei_state == MEI_RECOVERING_FROM_RESET) {
|
dev->dev_state == MEI_DEV_RECOVERING_FROM_RESET) {
|
||||||
dev->mei_state = MEI_POWER_DOWN;
|
dev->dev_state = MEI_DEV_POWER_DOWN;
|
||||||
mei_reset(dev, 0);
|
mei_reset(dev, 0);
|
||||||
}
|
}
|
||||||
mutex_unlock(&dev->device_lock);
|
mutex_unlock(&dev->device_lock);
|
||||||
|
@ -1169,12 +1153,12 @@ static int mei_pci_resume(struct device *device)
|
||||||
err = request_threaded_irq(pdev->irq,
|
err = request_threaded_irq(pdev->irq,
|
||||||
NULL,
|
NULL,
|
||||||
mei_interrupt_thread_handler,
|
mei_interrupt_thread_handler,
|
||||||
IRQF_ONESHOT, mei_driver_name, dev);
|
IRQF_ONESHOT, KBUILD_MODNAME, dev);
|
||||||
else
|
else
|
||||||
err = request_threaded_irq(pdev->irq,
|
err = request_threaded_irq(pdev->irq,
|
||||||
mei_interrupt_quick_handler,
|
mei_interrupt_quick_handler,
|
||||||
mei_interrupt_thread_handler,
|
mei_interrupt_thread_handler,
|
||||||
IRQF_SHARED, mei_driver_name, dev);
|
IRQF_SHARED, KBUILD_MODNAME, dev);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(&pdev->dev, "request_threaded_irq failed: irq = %d.\n",
|
dev_err(&pdev->dev, "request_threaded_irq failed: irq = %d.\n",
|
||||||
|
@ -1183,7 +1167,7 @@ static int mei_pci_resume(struct device *device)
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_lock(&dev->device_lock);
|
mutex_lock(&dev->device_lock);
|
||||||
dev->mei_state = MEI_POWER_UP;
|
dev->dev_state = MEI_DEV_POWER_UP;
|
||||||
mei_reset(dev, 1);
|
mei_reset(dev, 1);
|
||||||
mutex_unlock(&dev->device_lock);
|
mutex_unlock(&dev->device_lock);
|
||||||
|
|
||||||
|
@ -1201,7 +1185,7 @@ static SIMPLE_DEV_PM_OPS(mei_pm_ops, mei_pci_suspend, mei_pci_resume);
|
||||||
* PCI driver structure
|
* PCI driver structure
|
||||||
*/
|
*/
|
||||||
static struct pci_driver mei_driver = {
|
static struct pci_driver mei_driver = {
|
||||||
.name = mei_driver_name,
|
.name = KBUILD_MODNAME,
|
||||||
.id_table = mei_pci_tbl,
|
.id_table = mei_pci_tbl,
|
||||||
.probe = mei_probe,
|
.probe = mei_probe,
|
||||||
.remove = __devexit_p(mei_remove),
|
.remove = __devexit_p(mei_remove),
|
||||||
|
|
|
@ -25,9 +25,16 @@
|
||||||
/*
|
/*
|
||||||
* watch dog definition
|
* watch dog definition
|
||||||
*/
|
*/
|
||||||
#define MEI_WATCHDOG_DATA_SIZE 16
|
#define MEI_WD_HDR_SIZE 4
|
||||||
#define MEI_START_WD_DATA_SIZE 20
|
#define MEI_WD_STOP_MSG_SIZE MEI_WD_HDR_SIZE
|
||||||
#define MEI_WD_PARAMS_SIZE 4
|
#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_STOP_TIMEOUT 10 /* msecs */
|
||||||
|
|
||||||
#define MEI_WD_STATE_INDEPENDENCE_MSG_SENT (1 << 0)
|
#define MEI_WD_STATE_INDEPENDENCE_MSG_SENT (1 << 0)
|
||||||
|
|
||||||
#define MEI_RD_MSG_BUF_SIZE (128 * sizeof(u32))
|
#define MEI_RD_MSG_BUF_SIZE (128 * sizeof(u32))
|
||||||
|
@ -78,17 +85,19 @@ enum file_state {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* MEI device states */
|
/* MEI device states */
|
||||||
enum mei_states {
|
enum mei_dev_state {
|
||||||
MEI_INITIALIZING = 0,
|
MEI_DEV_INITIALIZING = 0,
|
||||||
MEI_INIT_CLIENTS,
|
MEI_DEV_INIT_CLIENTS,
|
||||||
MEI_ENABLED,
|
MEI_DEV_ENABLED,
|
||||||
MEI_RESETING,
|
MEI_DEV_RESETING,
|
||||||
MEI_DISABLED,
|
MEI_DEV_DISABLED,
|
||||||
MEI_RECOVERING_FROM_RESET,
|
MEI_DEV_RECOVERING_FROM_RESET,
|
||||||
MEI_POWER_DOWN,
|
MEI_DEV_POWER_DOWN,
|
||||||
MEI_POWER_UP
|
MEI_DEV_POWER_UP
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const char *mei_dev_state_str(int state);
|
||||||
|
|
||||||
/* init clients states*/
|
/* init clients states*/
|
||||||
enum mei_init_clients_states {
|
enum mei_init_clients_states {
|
||||||
MEI_START_MESSAGE = 0,
|
MEI_START_MESSAGE = 0,
|
||||||
|
@ -113,6 +122,12 @@ enum mei_file_transaction_states {
|
||||||
MEI_READ_COMPLETE
|
MEI_READ_COMPLETE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum mei_wd_states {
|
||||||
|
MEI_WD_IDLE,
|
||||||
|
MEI_WD_RUNNING,
|
||||||
|
MEI_WD_STOPPING,
|
||||||
|
};
|
||||||
|
|
||||||
/* MEI CB */
|
/* MEI CB */
|
||||||
enum mei_cb_major_types {
|
enum mei_cb_major_types {
|
||||||
MEI_READ = 0,
|
MEI_READ = 0,
|
||||||
|
@ -218,10 +233,9 @@ struct mei_device {
|
||||||
/*
|
/*
|
||||||
* mei device states
|
* mei device states
|
||||||
*/
|
*/
|
||||||
enum mei_states mei_state;
|
enum mei_dev_state dev_state;
|
||||||
enum mei_init_clients_states init_clients_state;
|
enum mei_init_clients_states init_clients_state;
|
||||||
u16 init_clients_timer;
|
u16 init_clients_timer;
|
||||||
bool stop;
|
|
||||||
bool need_reset;
|
bool need_reset;
|
||||||
|
|
||||||
u32 extra_write_index;
|
u32 extra_write_index;
|
||||||
|
@ -241,12 +255,11 @@ struct mei_device {
|
||||||
bool mei_host_buffer_is_empty;
|
bool mei_host_buffer_is_empty;
|
||||||
|
|
||||||
struct mei_cl wd_cl;
|
struct mei_cl wd_cl;
|
||||||
|
enum mei_wd_states wd_state;
|
||||||
bool wd_interface_reg;
|
bool wd_interface_reg;
|
||||||
bool wd_pending;
|
bool wd_pending;
|
||||||
bool wd_stopped;
|
u16 wd_timeout;
|
||||||
bool wd_bypass; /* if false, don't refresh watchdog ME client */
|
unsigned char wd_data[MEI_WD_START_MSG_SIZE];
|
||||||
u16 wd_timeout; /* seconds ((wd_data[1] << 8) + wd_data[0]) */
|
|
||||||
unsigned char wd_data[MEI_START_WD_DATA_SIZE];
|
|
||||||
|
|
||||||
|
|
||||||
struct file *iamthif_file_object;
|
struct file *iamthif_file_object;
|
||||||
|
@ -279,9 +292,10 @@ void mei_host_init_iamthif(struct mei_device *dev);
|
||||||
void mei_allocate_me_clients_storage(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,
|
int mei_me_cl_update_filext(struct mei_device *dev, struct mei_cl *cl,
|
||||||
struct mei_cl *priv,
|
const uuid_le *cguid, u8 host_client_id);
|
||||||
const uuid_le *cguid, u8 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
|
* MEI IO List Functions
|
||||||
|
@ -348,7 +362,6 @@ void mei_run_next_iamthif_cmd(struct mei_device *dev);
|
||||||
|
|
||||||
void mei_free_cb_private(struct mei_cl_cb *priv_cb);
|
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
|
* Register Access Function
|
||||||
|
|
|
@ -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)
|
static void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout)
|
||||||
{
|
{
|
||||||
dev_dbg(&dev->pdev->dev, "wd: set timeout=%d.\n", 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_start_wd_params, MEI_WD_HDR_SIZE);
|
||||||
memcpy(dev->wd_data + MEI_WD_PARAMS_SIZE, &timeout, sizeof(u16));
|
memcpy(dev->wd_data + MEI_WD_HDR_SIZE, &timeout, sizeof(u16));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -66,10 +66,11 @@ int mei_wd_host_init(struct mei_device *dev)
|
||||||
|
|
||||||
/* look for WD client and connect to it */
|
/* look for WD client and connect to it */
|
||||||
dev->wd_cl.state = MEI_FILE_DISCONNECTED;
|
dev->wd_cl.state = MEI_FILE_DISCONNECTED;
|
||||||
dev->wd_timeout = AMT_WD_DEFAULT_TIMEOUT;
|
dev->wd_timeout = MEI_WD_DEFAULT_TIMEOUT;
|
||||||
|
dev->wd_state = MEI_WD_IDLE;
|
||||||
|
|
||||||
/* find ME WD client */
|
/* 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);
|
&mei_wd_guid, MEI_WD_HOST_CLIENT_ID);
|
||||||
|
|
||||||
dev_dbg(&dev->pdev->dev, "wd: check client\n");
|
dev_dbg(&dev->pdev->dev, "wd: check client\n");
|
||||||
|
@ -108,10 +109,10 @@ int mei_wd_send(struct mei_device *dev)
|
||||||
mei_hdr->msg_complete = 1;
|
mei_hdr->msg_complete = 1;
|
||||||
mei_hdr->reserved = 0;
|
mei_hdr->reserved = 0;
|
||||||
|
|
||||||
if (!memcmp(dev->wd_data, mei_start_wd_params, MEI_WD_PARAMS_SIZE))
|
if (!memcmp(dev->wd_data, mei_start_wd_params, MEI_WD_HDR_SIZE))
|
||||||
mei_hdr->length = MEI_START_WD_DATA_SIZE;
|
mei_hdr->length = MEI_WD_START_MSG_SIZE;
|
||||||
else if (!memcmp(dev->wd_data, mei_stop_wd_params, MEI_WD_PARAMS_SIZE))
|
else if (!memcmp(dev->wd_data, mei_stop_wd_params, MEI_WD_HDR_SIZE))
|
||||||
mei_hdr->length = MEI_WD_PARAMS_SIZE;
|
mei_hdr->length = MEI_WD_STOP_MSG_SIZE;
|
||||||
else
|
else
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
@ -128,18 +129,17 @@ int mei_wd_send(struct mei_device *dev)
|
||||||
* -EIO when message send fails
|
* -EIO when message send fails
|
||||||
* -EINVAL when invalid message is to be sent
|
* -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;
|
int ret;
|
||||||
u16 wd_timeout = dev->wd_timeout;
|
|
||||||
|
|
||||||
cancel_delayed_work(&dev->timer_work);
|
if (dev->wd_cl.state != MEI_FILE_CONNECTED ||
|
||||||
if (dev->wd_cl.state != MEI_FILE_CONNECTED || !dev->wd_timeout)
|
dev->wd_state != MEI_WD_RUNNING)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
dev->wd_timeout = 0;
|
memcpy(dev->wd_data, mei_stop_wd_params, MEI_WD_STOP_MSG_SIZE);
|
||||||
memcpy(dev->wd_data, mei_stop_wd_params, MEI_WD_PARAMS_SIZE);
|
|
||||||
dev->stop = true;
|
dev->wd_state = MEI_WD_STOPPING;
|
||||||
|
|
||||||
ret = mei_flow_ctrl_creds(dev, &dev->wd_cl);
|
ret = mei_flow_ctrl_creds(dev, &dev->wd_cl);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
@ -161,13 +161,14 @@ int mei_wd_stop(struct mei_device *dev, bool preserve)
|
||||||
} else {
|
} else {
|
||||||
dev->wd_pending = true;
|
dev->wd_pending = true;
|
||||||
}
|
}
|
||||||
dev->wd_stopped = false;
|
|
||||||
mutex_unlock(&dev->device_lock);
|
mutex_unlock(&dev->device_lock);
|
||||||
|
|
||||||
ret = wait_event_interruptible_timeout(dev->wait_stop_wd,
|
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);
|
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);
|
dev_dbg(&dev->pdev->dev, "wd: stop completed ret=%d.\n", ret);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -177,9 +178,6 @@ int mei_wd_stop(struct mei_device *dev, bool preserve)
|
||||||
"wd: stop failed to complete ret=%d.\n", ret);
|
"wd: stop failed to complete ret=%d.\n", ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preserve)
|
|
||||||
dev->wd_timeout = wd_timeout;
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -196,16 +194,16 @@ static int mei_wd_ops_start(struct watchdog_device *wd_dev)
|
||||||
int err = -ENODEV;
|
int err = -ENODEV;
|
||||||
struct mei_device *dev;
|
struct mei_device *dev;
|
||||||
|
|
||||||
dev = pci_get_drvdata(mei_device);
|
dev = watchdog_get_drvdata(wd_dev);
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
mutex_lock(&dev->device_lock);
|
mutex_lock(&dev->device_lock);
|
||||||
|
|
||||||
if (dev->mei_state != MEI_ENABLED) {
|
if (dev->dev_state != MEI_DEV_ENABLED) {
|
||||||
dev_dbg(&dev->pdev->dev,
|
dev_dbg(&dev->pdev->dev,
|
||||||
"wd: mei_state != MEI_ENABLED mei_state = %d\n",
|
"wd: dev_state != MEI_DEV_ENABLED dev_state = %s\n",
|
||||||
dev->mei_state);
|
mei_dev_state_str(dev->dev_state));
|
||||||
goto end_unlock;
|
goto end_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,13 +231,13 @@ end_unlock:
|
||||||
static int mei_wd_ops_stop(struct watchdog_device *wd_dev)
|
static int mei_wd_ops_stop(struct watchdog_device *wd_dev)
|
||||||
{
|
{
|
||||||
struct mei_device *dev;
|
struct mei_device *dev;
|
||||||
dev = pci_get_drvdata(mei_device);
|
|
||||||
|
|
||||||
|
dev = watchdog_get_drvdata(wd_dev);
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
mutex_lock(&dev->device_lock);
|
mutex_lock(&dev->device_lock);
|
||||||
mei_wd_stop(dev, false);
|
mei_wd_stop(dev);
|
||||||
mutex_unlock(&dev->device_lock);
|
mutex_unlock(&dev->device_lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -256,8 +254,8 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct mei_device *dev;
|
struct mei_device *dev;
|
||||||
dev = pci_get_drvdata(mei_device);
|
|
||||||
|
|
||||||
|
dev = watchdog_get_drvdata(wd_dev);
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
|
@ -269,6 +267,8 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dev->wd_state = MEI_WD_RUNNING;
|
||||||
|
|
||||||
/* Check if we can send the ping to HW*/
|
/* Check if we can send the ping to HW*/
|
||||||
if (dev->mei_host_buffer_is_empty &&
|
if (dev->mei_host_buffer_is_empty &&
|
||||||
mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) {
|
mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) {
|
||||||
|
@ -309,13 +309,13 @@ end:
|
||||||
static int mei_wd_ops_set_timeout(struct watchdog_device *wd_dev, unsigned int timeout)
|
static int mei_wd_ops_set_timeout(struct watchdog_device *wd_dev, unsigned int timeout)
|
||||||
{
|
{
|
||||||
struct mei_device *dev;
|
struct mei_device *dev;
|
||||||
dev = pci_get_drvdata(mei_device);
|
|
||||||
|
|
||||||
|
dev = watchdog_get_drvdata(wd_dev);
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
/* Check Timeout value */
|
/* 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;
|
return -EINVAL;
|
||||||
|
|
||||||
mutex_lock(&dev->device_lock);
|
mutex_lock(&dev->device_lock);
|
||||||
|
@ -341,37 +341,42 @@ static const struct watchdog_ops wd_ops = {
|
||||||
};
|
};
|
||||||
static const struct watchdog_info wd_info = {
|
static const struct watchdog_info wd_info = {
|
||||||
.identity = INTEL_AMT_WATCHDOG_ID,
|
.identity = INTEL_AMT_WATCHDOG_ID,
|
||||||
.options = WDIOF_KEEPALIVEPING | WDIOF_ALARMONLY,
|
.options = WDIOF_KEEPALIVEPING |
|
||||||
|
WDIOF_SETTIMEOUT |
|
||||||
|
WDIOF_ALARMONLY,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct watchdog_device amt_wd_dev = {
|
static struct watchdog_device amt_wd_dev = {
|
||||||
.info = &wd_info,
|
.info = &wd_info,
|
||||||
.ops = &wd_ops,
|
.ops = &wd_ops,
|
||||||
.timeout = AMT_WD_DEFAULT_TIMEOUT,
|
.timeout = MEI_WD_DEFAULT_TIMEOUT,
|
||||||
.min_timeout = AMT_WD_MIN_TIMEOUT,
|
.min_timeout = MEI_WD_MIN_TIMEOUT,
|
||||||
.max_timeout = AMT_WD_MAX_TIMEOUT,
|
.max_timeout = MEI_WD_MAX_TIMEOUT,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
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)) {
|
if (watchdog_register_device(&amt_wd_dev)) {
|
||||||
dev_err(&dev->pdev->dev,
|
dev_err(&dev->pdev->dev,
|
||||||
"wd: unable to register watchdog device.\n");
|
"wd: unable to register watchdog device.\n");
|
||||||
dev->wd_interface_reg = false;
|
dev->wd_interface_reg = false;
|
||||||
} else {
|
return;
|
||||||
dev_dbg(&dev->pdev->dev,
|
|
||||||
"wd: successfully register watchdog interface.\n");
|
|
||||||
dev->wd_interface_reg = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
void mei_watchdog_unregister(struct mei_device *dev)
|
||||||
{
|
{
|
||||||
if (dev->wd_interface_reg)
|
if (!dev->wd_interface_reg)
|
||||||
watchdog_unregister_device(&amt_wd_dev);
|
return;
|
||||||
|
|
||||||
|
watchdog_set_drvdata(&amt_wd_dev, NULL);
|
||||||
|
watchdog_unregister_device(&amt_wd_dev);
|
||||||
dev->wd_interface_reg = false;
|
dev->wd_interface_reg = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -699,7 +699,7 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,
|
||||||
chip->pch_phub_base_address = pci_iomap(pdev, 1, 0);
|
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__);
|
dev_err(&pdev->dev, "%s : pci_iomap FAILED", __func__);
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto err_pci_iomap;
|
goto err_pci_iomap;
|
||||||
|
@ -893,18 +893,7 @@ static struct pci_driver pch_phub_driver = {
|
||||||
.resume = pch_phub_resume
|
.resume = pch_phub_resume
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init pch_phub_pci_init(void)
|
module_pci_driver(pch_phub_driver);
|
||||||
{
|
|
||||||
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_DESCRIPTION("Intel EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7223) PHUB");
|
MODULE_DESCRIPTION("Intel EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7223) PHUB");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -30,11 +30,13 @@
|
||||||
|
|
||||||
#include <linux/ti_wilink_st.h>
|
#include <linux/ti_wilink_st.h>
|
||||||
|
|
||||||
|
extern void st_kim_recv(void *, const unsigned char *, long);
|
||||||
|
void st_int_recv(void *, const unsigned char *, long);
|
||||||
/* function pointer pointing to either,
|
/* function pointer pointing to either,
|
||||||
* st_kim_recv during registration to receive fw download responses
|
* st_kim_recv during registration to receive fw download responses
|
||||||
* st_int_recv after registration to receive proto stack 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,
|
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
|
* push the skb received to relevant
|
||||||
* protocol stacks
|
* 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);
|
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
|
* This function is being called with spin lock held, protocol drivers are
|
||||||
* only expected to complete their waits and do nothing more than that.
|
* 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;
|
unsigned char i = 0;
|
||||||
pr_info(" %s ", __func__);
|
pr_info(" %s ", __func__);
|
||||||
|
@ -379,7 +381,7 @@ done:
|
||||||
* completely, return that skb which has the pending data.
|
* completely, return that skb which has the pending data.
|
||||||
* In normal cases, return top of txq.
|
* 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;
|
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
|
* txq and waitq needs protection since the other contexts
|
||||||
* may be sending data, waking up chip.
|
* 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;
|
unsigned long flags = 0;
|
||||||
|
|
||||||
|
|
|
@ -63,10 +63,27 @@ static struct platform_device *st_get_plat_device(int id)
|
||||||
* in case of error don't complete so that waiting for proper
|
* in case of error don't complete so that waiting for proper
|
||||||
* response times out
|
* 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;
|
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("no proper response during fw download");
|
||||||
pr_err("data6 %x", skb->data[5]);
|
pr_err("data6 %x", skb->data[5]);
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
|
@ -119,7 +136,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
|
* have been observed to come in bursts of different
|
||||||
* tty_receive and hence the logic
|
* 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 *data, long count)
|
||||||
{
|
{
|
||||||
const unsigned char *ptr;
|
const unsigned char *ptr;
|
||||||
|
@ -207,16 +224,19 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!wait_for_completion_timeout
|
if (!wait_for_completion_interruptible_timeout(
|
||||||
(&kim_gdata->kim_rcvd, msecs_to_jiffies(CMD_RESP_TIME))) {
|
&kim_gdata->kim_rcvd, msecs_to_jiffies(CMD_RESP_TIME))) {
|
||||||
pr_err(" waiting for ver info- timed out ");
|
pr_err(" waiting for ver info- timed out ");
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
}
|
}
|
||||||
INIT_COMPLETION(kim_gdata->kim_rcvd);
|
INIT_COMPLETION(kim_gdata->kim_rcvd);
|
||||||
|
/* the positions 12 & 13 in the response buffer provide with the
|
||||||
|
* chip, major & minor numbers
|
||||||
|
*/
|
||||||
|
|
||||||
version =
|
version =
|
||||||
MAKEWORD(kim_gdata->resp_buffer[13],
|
MAKEWORD(kim_gdata->resp_buffer[12],
|
||||||
kim_gdata->resp_buffer[14]);
|
kim_gdata->resp_buffer[13]);
|
||||||
chip = (version & 0x7C00) >> 10;
|
chip = (version & 0x7C00) >> 10;
|
||||||
min_ver = (version & 0x007F);
|
min_ver = (version & 0x007F);
|
||||||
maj_ver = (version & 0x0380) >> 7;
|
maj_ver = (version & 0x0380) >> 7;
|
||||||
|
@ -236,7 +256,7 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name)
|
||||||
return 0;
|
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;
|
unsigned char *nxt_action, *cur_action;
|
||||||
cur_action = *ptr;
|
cur_action = *ptr;
|
||||||
|
@ -370,9 +390,9 @@ static long download_firmware(struct kim_data_s *kim_gdata)
|
||||||
break;
|
break;
|
||||||
case ACTION_WAIT_EVENT: /* wait */
|
case ACTION_WAIT_EVENT: /* wait */
|
||||||
pr_debug("W");
|
pr_debug("W");
|
||||||
if (!wait_for_completion_timeout
|
if (!wait_for_completion_interruptible_timeout(
|
||||||
(&kim_gdata->kim_rcvd,
|
&kim_gdata->kim_rcvd,
|
||||||
msecs_to_jiffies(CMD_RESP_TIME))) {
|
msecs_to_jiffies(CMD_RESP_TIME))) {
|
||||||
pr_err("response timeout during fw download ");
|
pr_err("response timeout during fw download ");
|
||||||
/* timed out */
|
/* timed out */
|
||||||
release_firmware(kim_gdata->fw_entry);
|
release_firmware(kim_gdata->fw_entry);
|
||||||
|
@ -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 st_data_s *st_gdata = (struct st_data_s *)disc_data;
|
||||||
struct kim_data_s *kim_gdata = st_gdata->kim_data;
|
struct kim_data_s *kim_gdata = st_gdata->kim_data;
|
||||||
|
|
||||||
/* copy to local buffer */
|
/* proceed to gather all data and distinguish read fw version response
|
||||||
if (unlikely(data[4] == 0x01 && data[5] == 0x10 && data[0] == 0x04)) {
|
* from other fw responses when data gathering is complete
|
||||||
/* must be the read_ver_cmd */
|
*/
|
||||||
memcpy(kim_gdata->resp_buffer, data, count);
|
kim_int_recv(kim_gdata, data, count);
|
||||||
complete_all(&kim_gdata->kim_rcvd);
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
kim_int_recv(kim_gdata, data, count);
|
|
||||||
/* either completes or times out */
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -454,11 +468,6 @@ long st_kim_start(void *kim_data)
|
||||||
if (pdata->chip_enable)
|
if (pdata->chip_enable)
|
||||||
pdata->chip_enable(kim_gdata);
|
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 */
|
/* re-initialize the completion */
|
||||||
INIT_COMPLETION(kim_gdata->ldisc_installed);
|
INIT_COMPLETION(kim_gdata->ldisc_installed);
|
||||||
/* send notification to UIM */
|
/* send notification to UIM */
|
||||||
|
@ -467,8 +476,8 @@ long st_kim_start(void *kim_data)
|
||||||
sysfs_notify(&kim_gdata->kim_pdev->dev.kobj,
|
sysfs_notify(&kim_gdata->kim_pdev->dev.kobj,
|
||||||
NULL, "install");
|
NULL, "install");
|
||||||
/* wait for ldisc to be installed */
|
/* wait for ldisc to be installed */
|
||||||
err = wait_for_completion_timeout(&kim_gdata->ldisc_installed,
|
err = wait_for_completion_interruptible_timeout(
|
||||||
msecs_to_jiffies(LDISC_TIME));
|
&kim_gdata->ldisc_installed, msecs_to_jiffies(LDISC_TIME));
|
||||||
if (!err) {
|
if (!err) {
|
||||||
/* ldisc installation timeout,
|
/* ldisc installation timeout,
|
||||||
* flush uart, power cycle BT_EN */
|
* flush uart, power cycle BT_EN */
|
||||||
|
@ -500,8 +509,7 @@ long st_kim_start(void *kim_data)
|
||||||
* (b) upon failure to either install ldisc or download firmware.
|
* (b) upon failure to either install ldisc or download firmware.
|
||||||
* The function is responsible to (a) notify UIM about un-installation,
|
* The function is responsible to (a) notify UIM about un-installation,
|
||||||
* (b) flush UART if the ldisc was installed.
|
* (b) flush UART if the ldisc was installed.
|
||||||
* (c) reset BT_EN - pull down nshutdown at the end.
|
* (c) invoke platform's chip disabling routine.
|
||||||
* (d) invoke platform's chip disabling routine.
|
|
||||||
*/
|
*/
|
||||||
long st_kim_stop(void *kim_data)
|
long st_kim_stop(void *kim_data)
|
||||||
{
|
{
|
||||||
|
@ -526,20 +534,13 @@ long st_kim_stop(void *kim_data)
|
||||||
sysfs_notify(&kim_gdata->kim_pdev->dev.kobj, NULL, "install");
|
sysfs_notify(&kim_gdata->kim_pdev->dev.kobj, NULL, "install");
|
||||||
|
|
||||||
/* wait for ldisc to be un-installed */
|
/* wait for ldisc to be un-installed */
|
||||||
err = wait_for_completion_timeout(&kim_gdata->ldisc_installed,
|
err = wait_for_completion_interruptible_timeout(
|
||||||
msecs_to_jiffies(LDISC_TIME));
|
&kim_gdata->ldisc_installed, msecs_to_jiffies(LDISC_TIME));
|
||||||
if (!err) { /* timeout */
|
if (!err) { /* timeout */
|
||||||
pr_err(" timed out waiting for ldisc to be un-installed");
|
pr_err(" timed out waiting for ldisc to be un-installed");
|
||||||
return -ETIMEDOUT;
|
err = -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 */
|
/* platform specific disable */
|
||||||
if (pdata->chip_disable)
|
if (pdata->chip_disable)
|
||||||
pdata->chip_disable(kim_gdata);
|
pdata->chip_disable(kim_gdata);
|
||||||
|
@ -701,7 +702,7 @@ static const struct file_operations list_debugfs_fops = {
|
||||||
* board-*.c file
|
* board-*.c file
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct dentry *kim_debugfs_dir;
|
static struct dentry *kim_debugfs_dir;
|
||||||
static int kim_probe(struct platform_device *pdev)
|
static int kim_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
long status;
|
long status;
|
||||||
|
@ -731,20 +732,6 @@ static int kim_probe(struct platform_device *pdev)
|
||||||
/* refer to itself */
|
/* refer to itself */
|
||||||
kim_gdata->core_data->kim_data = kim_gdata;
|
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
|
/* get reference of pdev for request_firmware
|
||||||
*/
|
*/
|
||||||
kim_gdata->kim_pdev = pdev;
|
kim_gdata->kim_pdev = pdev;
|
||||||
|
@ -780,18 +767,10 @@ static int kim_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
static int kim_remove(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;
|
struct kim_data_s *kim_gdata;
|
||||||
|
|
||||||
kim_gdata = dev_get_drvdata(&pdev->dev);
|
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);
|
debugfs_remove_recursive(kim_debugfs_dir);
|
||||||
sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp);
|
sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp);
|
||||||
pr_info("sysfs entries removed");
|
pr_info("sysfs entries removed");
|
||||||
|
@ -804,7 +783,7 @@ static int kim_remove(struct platform_device *pdev)
|
||||||
return 0;
|
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;
|
struct ti_st_plat_data *pdata = pdev->dev.platform_data;
|
||||||
|
|
||||||
|
@ -814,7 +793,7 @@ int kim_suspend(struct platform_device *pdev, pm_message_t state)
|
||||||
return -EOPNOTSUPP;
|
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;
|
struct ti_st_plat_data *pdata = pdev->dev.platform_data;
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,6 @@ config W1_MASTER_GPIO
|
||||||
|
|
||||||
config HDQ_MASTER_OMAP
|
config HDQ_MASTER_OMAP
|
||||||
tristate "OMAP HDQ driver"
|
tristate "OMAP HDQ driver"
|
||||||
depends on ARCH_OMAP2PLUS
|
|
||||||
help
|
help
|
||||||
Say Y here if you want support for the 1-wire or HDQ Interface
|
Say Y here if you want support for the 1-wire or HDQ Interface
|
||||||
on an OMAP processor.
|
on an OMAP processor.
|
||||||
|
|
|
@ -18,9 +18,6 @@
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
|
|
||||||
#include <asm/irq.h>
|
|
||||||
#include <mach/hardware.h>
|
|
||||||
|
|
||||||
#include "../w1.h"
|
#include "../w1.h"
|
||||||
#include "../w1_int.h"
|
#include "../w1_int.h"
|
||||||
|
|
||||||
|
@ -73,11 +70,11 @@ struct hdq_data {
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __devinit omap_hdq_probe(struct platform_device *pdev);
|
static int __devinit omap_hdq_probe(struct platform_device *pdev);
|
||||||
static int omap_hdq_remove(struct platform_device *pdev);
|
static int __devexit omap_hdq_remove(struct platform_device *pdev);
|
||||||
|
|
||||||
static struct platform_driver omap_hdq_driver = {
|
static struct platform_driver omap_hdq_driver = {
|
||||||
.probe = omap_hdq_probe,
|
.probe = omap_hdq_probe,
|
||||||
.remove = omap_hdq_remove,
|
.remove = __devexit_p(omap_hdq_remove),
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "omap_hdq",
|
.name = "omap_hdq",
|
||||||
},
|
},
|
||||||
|
@ -538,39 +535,35 @@ static void omap_w1_write_byte(void *_hdq, u8 byte)
|
||||||
hdq_data->init_trans = 0;
|
hdq_data->init_trans = 0;
|
||||||
mutex_unlock(&hdq_data->hdq_mutex);
|
mutex_unlock(&hdq_data->hdq_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __devinit omap_hdq_probe(struct platform_device *pdev)
|
static int __devinit omap_hdq_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
struct hdq_data *hdq_data;
|
struct hdq_data *hdq_data;
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
int ret, irq;
|
int ret, irq;
|
||||||
u8 rev;
|
u8 rev;
|
||||||
|
|
||||||
hdq_data = kmalloc(sizeof(*hdq_data), GFP_KERNEL);
|
hdq_data = devm_kzalloc(dev, sizeof(*hdq_data), GFP_KERNEL);
|
||||||
if (!hdq_data) {
|
if (!hdq_data) {
|
||||||
dev_dbg(&pdev->dev, "unable to allocate memory\n");
|
dev_dbg(&pdev->dev, "unable to allocate memory\n");
|
||||||
ret = -ENOMEM;
|
return -ENOMEM;
|
||||||
goto err_kmalloc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hdq_data->dev = &pdev->dev;
|
hdq_data->dev = dev;
|
||||||
platform_set_drvdata(pdev, hdq_data);
|
platform_set_drvdata(pdev, hdq_data);
|
||||||
|
|
||||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
if (!res) {
|
if (!res) {
|
||||||
dev_dbg(&pdev->dev, "unable to get resource\n");
|
dev_dbg(&pdev->dev, "unable to get resource\n");
|
||||||
ret = -ENXIO;
|
return -ENXIO;
|
||||||
goto err_resource;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hdq_data->hdq_base = ioremap(res->start, SZ_4K);
|
hdq_data->hdq_base = devm_request_and_ioremap(dev, res);
|
||||||
if (!hdq_data->hdq_base) {
|
if (!hdq_data->hdq_base) {
|
||||||
dev_dbg(&pdev->dev, "ioremap failed\n");
|
dev_dbg(&pdev->dev, "ioremap failed\n");
|
||||||
ret = -EINVAL;
|
return -ENOMEM;
|
||||||
goto err_ioremap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hdq_data->hdq_usecount = 0;
|
hdq_data->hdq_usecount = 0;
|
||||||
|
@ -591,7 +584,8 @@ static int __devinit omap_hdq_probe(struct platform_device *pdev)
|
||||||
goto err_irq;
|
goto err_irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = request_irq(irq, hdq_isr, IRQF_DISABLED, "omap_hdq", hdq_data);
|
ret = devm_request_irq(dev, irq, hdq_isr, IRQF_DISABLED,
|
||||||
|
"omap_hdq", hdq_data);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_dbg(&pdev->dev, "could not request irq\n");
|
dev_dbg(&pdev->dev, "could not request irq\n");
|
||||||
goto err_irq;
|
goto err_irq;
|
||||||
|
@ -616,19 +610,10 @@ err_irq:
|
||||||
err_w1:
|
err_w1:
|
||||||
pm_runtime_disable(&pdev->dev);
|
pm_runtime_disable(&pdev->dev);
|
||||||
|
|
||||||
iounmap(hdq_data->hdq_base);
|
|
||||||
|
|
||||||
err_ioremap:
|
|
||||||
err_resource:
|
|
||||||
platform_set_drvdata(pdev, NULL);
|
|
||||||
kfree(hdq_data);
|
|
||||||
|
|
||||||
err_kmalloc:
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int omap_hdq_remove(struct platform_device *pdev)
|
static int __devexit omap_hdq_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct hdq_data *hdq_data = platform_get_drvdata(pdev);
|
struct hdq_data *hdq_data = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
|
@ -644,27 +629,11 @@ static int omap_hdq_remove(struct platform_device *pdev)
|
||||||
|
|
||||||
/* remove module dependency */
|
/* remove module dependency */
|
||||||
pm_runtime_disable(&pdev->dev);
|
pm_runtime_disable(&pdev->dev);
|
||||||
free_irq(INT_24XX_HDQ_IRQ, hdq_data);
|
|
||||||
platform_set_drvdata(pdev, NULL);
|
|
||||||
iounmap(hdq_data->hdq_base);
|
|
||||||
kfree(hdq_data);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init
|
module_platform_driver(omap_hdq_driver);
|
||||||
omap_hdq_init(void)
|
|
||||||
{
|
|
||||||
return platform_driver_register(&omap_hdq_driver);
|
|
||||||
}
|
|
||||||
module_init(omap_hdq_init);
|
|
||||||
|
|
||||||
static void __exit
|
|
||||||
omap_hdq_exit(void)
|
|
||||||
{
|
|
||||||
platform_driver_unregister(&omap_hdq_driver);
|
|
||||||
}
|
|
||||||
module_exit(omap_hdq_exit);
|
|
||||||
|
|
||||||
module_param(w1_id, int, S_IRUSR);
|
module_param(w1_id, int, S_IRUSR);
|
||||||
MODULE_PARM_DESC(w1_id, "1-wire id for the slave detection");
|
MODULE_PARM_DESC(w1_id, "1-wire id for the slave detection");
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/w1-gpio.h>
|
#include <linux/w1-gpio.h>
|
||||||
#include <linux/gpio.h>
|
#include <linux/gpio.h>
|
||||||
|
#include <linux/of_platform.h>
|
||||||
|
#include <linux/of_gpio.h>
|
||||||
|
|
||||||
#include "../w1.h"
|
#include "../w1.h"
|
||||||
#include "../w1_int.h"
|
#include "../w1_int.h"
|
||||||
|
@ -42,12 +44,55 @@ static u8 w1_gpio_read_bit(void *data)
|
||||||
return gpio_get_value(pdata->pin) ? 1 : 0;
|
return gpio_get_value(pdata->pin) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_OF
|
||||||
|
static struct of_device_id w1_gpio_dt_ids[] = {
|
||||||
|
{ .compatible = "w1-gpio" },
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, w1_gpio_dt_ids);
|
||||||
|
|
||||||
|
static int w1_gpio_probe_dt(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
|
||||||
|
struct device_node *np = pdev->dev.of_node;
|
||||||
|
const struct of_device_id *of_id =
|
||||||
|
of_match_device(w1_gpio_dt_ids, &pdev->dev);
|
||||||
|
|
||||||
|
if (!of_id)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
|
||||||
|
if (!pdata)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
if (of_get_property(np, "linux,open-drain", NULL))
|
||||||
|
pdata->is_open_drain = 1;
|
||||||
|
|
||||||
|
pdata->pin = of_get_gpio(np, 0);
|
||||||
|
pdata->ext_pullup_enable_pin = of_get_gpio(np, 1);
|
||||||
|
pdev->dev.platform_data = pdata;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static int w1_gpio_probe_dt(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int __init w1_gpio_probe(struct platform_device *pdev)
|
static int __init w1_gpio_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct w1_bus_master *master;
|
struct w1_bus_master *master;
|
||||||
struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
|
struct w1_gpio_platform_data *pdata;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
err = w1_gpio_probe_dt(pdev);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
pdata = pdev->dev.platform_data;
|
||||||
|
|
||||||
if (!pdata)
|
if (!pdata)
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
|
|
||||||
|
@ -59,6 +104,13 @@ static int __init w1_gpio_probe(struct platform_device *pdev)
|
||||||
if (err)
|
if (err)
|
||||||
goto free_master;
|
goto free_master;
|
||||||
|
|
||||||
|
if (gpio_is_valid(pdata->ext_pullup_enable_pin)) {
|
||||||
|
err = gpio_request_one(pdata->ext_pullup_enable_pin,
|
||||||
|
GPIOF_INIT_LOW, "w1 pullup");
|
||||||
|
if (err < 0)
|
||||||
|
goto free_gpio;
|
||||||
|
}
|
||||||
|
|
||||||
master->data = pdata;
|
master->data = pdata;
|
||||||
master->read_bit = w1_gpio_read_bit;
|
master->read_bit = w1_gpio_read_bit;
|
||||||
|
|
||||||
|
@ -72,15 +124,21 @@ static int __init w1_gpio_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
err = w1_add_master_device(master);
|
err = w1_add_master_device(master);
|
||||||
if (err)
|
if (err)
|
||||||
goto free_gpio;
|
goto free_gpio_ext_pu;
|
||||||
|
|
||||||
if (pdata->enable_external_pullup)
|
if (pdata->enable_external_pullup)
|
||||||
pdata->enable_external_pullup(1);
|
pdata->enable_external_pullup(1);
|
||||||
|
|
||||||
|
if (gpio_is_valid(pdata->ext_pullup_enable_pin))
|
||||||
|
gpio_set_value(pdata->ext_pullup_enable_pin, 1);
|
||||||
|
|
||||||
platform_set_drvdata(pdev, master);
|
platform_set_drvdata(pdev, master);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
free_gpio_ext_pu:
|
||||||
|
if (gpio_is_valid(pdata->ext_pullup_enable_pin))
|
||||||
|
gpio_free(pdata->ext_pullup_enable_pin);
|
||||||
free_gpio:
|
free_gpio:
|
||||||
gpio_free(pdata->pin);
|
gpio_free(pdata->pin);
|
||||||
free_master:
|
free_master:
|
||||||
|
@ -97,6 +155,9 @@ static int __exit w1_gpio_remove(struct platform_device *pdev)
|
||||||
if (pdata->enable_external_pullup)
|
if (pdata->enable_external_pullup)
|
||||||
pdata->enable_external_pullup(0);
|
pdata->enable_external_pullup(0);
|
||||||
|
|
||||||
|
if (gpio_is_valid(pdata->ext_pullup_enable_pin))
|
||||||
|
gpio_set_value(pdata->ext_pullup_enable_pin, 0);
|
||||||
|
|
||||||
w1_remove_master_device(master);
|
w1_remove_master_device(master);
|
||||||
gpio_free(pdata->pin);
|
gpio_free(pdata->pin);
|
||||||
kfree(master);
|
kfree(master);
|
||||||
|
@ -135,6 +196,7 @@ static struct platform_driver w1_gpio_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "w1-gpio",
|
.name = "w1-gpio",
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
|
.of_match_table = of_match_ptr(w1_gpio_dt_ids),
|
||||||
},
|
},
|
||||||
.remove = __exit_p(w1_gpio_remove),
|
.remove = __exit_p(w1_gpio_remove),
|
||||||
.suspend = w1_gpio_suspend,
|
.suspend = w1_gpio_suspend,
|
||||||
|
|
|
@ -281,9 +281,10 @@ struct kim_data_s {
|
||||||
long st_kim_start(void *);
|
long st_kim_start(void *);
|
||||||
long st_kim_stop(void *);
|
long st_kim_stop(void *);
|
||||||
|
|
||||||
void st_kim_recv(void *, const unsigned char *, long count);
|
|
||||||
void st_kim_complete(void *);
|
void st_kim_complete(void *);
|
||||||
void kim_st_list_protocols(struct st_data_s *, void *);
|
void kim_st_list_protocols(struct st_data_s *, void *);
|
||||||
|
void st_kim_recv(void *, const unsigned char *, long);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* BTS headers
|
* BTS headers
|
||||||
|
|
|
@ -19,6 +19,7 @@ struct w1_gpio_platform_data {
|
||||||
unsigned int pin;
|
unsigned int pin;
|
||||||
unsigned int is_open_drain:1;
|
unsigned int is_open_drain:1;
|
||||||
void (*enable_external_pullup)(int enable);
|
void (*enable_external_pullup)(int enable);
|
||||||
|
unsigned int ext_pullup_enable_pin;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _LINUX_W1_GPIO_H */
|
#endif /* _LINUX_W1_GPIO_H */
|
||||||
|
|
Загрузка…
Ссылка в новой задаче