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:
Greg Kroah-Hartman 2012-08-27 09:09:07 -07:00
Родитель fea7a08acb 877cdf3949
Коммит 7da59d2fe3
21 изменённых файлов: 409 добавлений и 377 удалений

Просмотреть файл

@ -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 */