* [PATCH v2 1/5] intel_scu_ipc: fix error path by turning to devm_* / pcim_*
2015-10-12 11:19 [PATCH v2 0/5] intel_scu_ipc: bug fixes and amendments Andy Shevchenko
@ 2015-10-12 11:19 ` Andy Shevchenko
2015-10-12 11:19 ` [PATCH v2 2/5] intel_scu_ipc: propagate pointer to struct intel_scu_ipc_dev Andy Shevchenko
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Andy Shevchenko @ 2015-10-12 11:19 UTC (permalink / raw)
To: platform-driver-x86, Darren Hart, linux-kernel; +Cc: Andy Shevchenko
The error handling is broken right now since it leaves resources unfreed.
Convert the code to use managed resources to fix the error handling.
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
drivers/platform/x86/intel_scu_ipc.c | 26 ++++++++------------------
1 file changed, 8 insertions(+), 18 deletions(-)
diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c
index 187d108..7148535 100644
--- a/drivers/platform/x86/intel_scu_ipc.c
+++ b/drivers/platform/x86/intel_scu_ipc.c
@@ -563,7 +563,6 @@ static int ipc_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
int err;
struct intel_scu_ipc_pdata_t *pdata;
- resource_size_t base;
if (ipcdev.pdev) /* We support only one SCU */
return -EBUSY;
@@ -573,32 +572,26 @@ static int ipc_probe(struct pci_dev *dev, const struct pci_device_id *id)
ipcdev.pdev = pci_dev_get(dev);
ipcdev.irq_mode = pdata->irq_mode;
- err = pci_enable_device(dev);
+ err = pcim_enable_device(dev);
if (err)
return err;
- err = pci_request_regions(dev, "intel_scu_ipc");
+ err = pcim_iomap_regions(dev, 1 << 0, pci_name(dev));
if (err)
return err;
- base = pci_resource_start(dev, 0);
- if (!base)
- return -ENOMEM;
-
init_completion(&ipcdev.cmd_complete);
- if (request_irq(dev->irq, ioc, 0, "intel_scu_ipc", &ipcdev))
- return -EBUSY;
+ err = devm_request_irq(&dev->dev, dev->irq, ioc, 0, "intel_scu_ipc",
+ &ipcdev);
+ if (err)
+ return err;
- ipcdev.ipc_base = ioremap_nocache(base, pci_resource_len(dev, 0));
- if (!ipcdev.ipc_base)
- return -ENOMEM;
+ ipcdev.ipc_base = pcim_iomap_table(dev)[0];
ipcdev.i2c_base = ioremap_nocache(pdata->i2c_base, pdata->i2c_len);
- if (!ipcdev.i2c_base) {
- iounmap(ipcdev.ipc_base);
+ if (!ipcdev.i2c_base)
return -ENOMEM;
- }
intel_scu_devices_create();
@@ -617,10 +610,7 @@ static int ipc_probe(struct pci_dev *dev, const struct pci_device_id *id)
*/
static void ipc_remove(struct pci_dev *pdev)
{
- free_irq(pdev->irq, &ipcdev);
- pci_release_regions(pdev);
pci_dev_put(ipcdev.pdev);
- iounmap(ipcdev.ipc_base);
iounmap(ipcdev.i2c_base);
ipcdev.pdev = NULL;
intel_scu_devices_destroy();
--
2.5.3
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v2 2/5] intel_scu_ipc: propagate pointer to struct intel_scu_ipc_dev
2015-10-12 11:19 [PATCH v2 0/5] intel_scu_ipc: bug fixes and amendments Andy Shevchenko
2015-10-12 11:19 ` [PATCH v2 1/5] intel_scu_ipc: fix error path by turning to devm_* / pcim_* Andy Shevchenko
@ 2015-10-12 11:19 ` Andy Shevchenko
2015-10-12 11:19 ` [PATCH v2 3/5] intel_scu_ipc: convert to use struct device * Andy Shevchenko
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Andy Shevchenko @ 2015-10-12 11:19 UTC (permalink / raw)
To: platform-driver-x86, Darren Hart, linux-kernel; +Cc: Andy Shevchenko
As much as poosible propagate a pointer to struct intel_scu_ipc_dev.
There is no functional change.
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
drivers/platform/x86/intel_scu_ipc.c | 134 +++++++++++++++++++----------------
1 file changed, 74 insertions(+), 60 deletions(-)
diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c
index 7148535..6c9367f 100644
--- a/drivers/platform/x86/intel_scu_ipc.c
+++ b/drivers/platform/x86/intel_scu_ipc.c
@@ -118,28 +118,30 @@ static struct intel_scu_ipc_dev ipcdev; /* Only one for now */
static DEFINE_MUTEX(ipclock); /* lock used to prevent multiple call to SCU */
/*
+ * Send ipc command
* Command Register (Write Only):
* A write to this register results in an interrupt to the SCU core processor
* Format:
* |rfu2(8) | size(8) | command id(4) | rfu1(3) | ioc(1) | command(8)|
*/
-static inline void ipc_command(u32 cmd) /* Send ipc command */
+static inline void ipc_command(struct intel_scu_ipc_dev *scu, u32 cmd)
{
- if (ipcdev.irq_mode) {
- reinit_completion(&ipcdev.cmd_complete);
- writel(cmd | IPC_IOC, ipcdev.ipc_base);
+ if (scu->irq_mode) {
+ reinit_completion(&scu->cmd_complete);
+ writel(cmd | IPC_IOC, scu->ipc_base);
}
- writel(cmd, ipcdev.ipc_base);
+ writel(cmd, scu->ipc_base);
}
/*
+ * Write ipc data
* IPC Write Buffer (Write Only):
* 16-byte buffer for sending data associated with IPC command to
* SCU. Size of the data is specified in the IPC_COMMAND_REG register
*/
-static inline void ipc_data_writel(u32 data, u32 offset) /* Write ipc data */
+static inline void ipc_data_writel(struct intel_scu_ipc_dev *scu, u32 data, u32 offset)
{
- writel(data, ipcdev.ipc_base + 0x80 + offset);
+ writel(data, scu->ipc_base + 0x80 + offset);
}
/*
@@ -149,35 +151,37 @@ static inline void ipc_data_writel(u32 data, u32 offset) /* Write ipc data */
* Format:
* |rfu3(8)|error code(8)|initiator id(8)|cmd id(4)|rfu1(2)|error(1)|busy(1)|
*/
-static inline u8 ipc_read_status(void)
+static inline u8 ipc_read_status(struct intel_scu_ipc_dev *scu)
{
- return __raw_readl(ipcdev.ipc_base + 0x04);
+ return __raw_readl(scu->ipc_base + 0x04);
}
-static inline u8 ipc_data_readb(u32 offset) /* Read ipc byte data */
+/* Read ipc byte data */
+static inline u8 ipc_data_readb(struct intel_scu_ipc_dev *scu, u32 offset)
{
- return readb(ipcdev.ipc_base + IPC_READ_BUFFER + offset);
+ return readb(scu->ipc_base + IPC_READ_BUFFER + offset);
}
-static inline u32 ipc_data_readl(u32 offset) /* Read ipc u32 data */
+/* Read ipc u32 data */
+static inline u32 ipc_data_readl(struct intel_scu_ipc_dev *scu, u32 offset)
{
- return readl(ipcdev.ipc_base + IPC_READ_BUFFER + offset);
+ return readl(scu->ipc_base + IPC_READ_BUFFER + offset);
}
/* Wait till scu status is busy */
-static inline int busy_loop(void)
+static inline int busy_loop(struct intel_scu_ipc_dev *scu)
{
- u32 status = ipc_read_status();
+ u32 status = ipc_read_status(scu);
u32 loop_count = 100000;
/* break if scu doesn't reset busy bit after huge retry */
while ((status & BIT(0)) && --loop_count) {
udelay(1); /* scu processing time is in few u secods */
- status = ipc_read_status();
+ status = ipc_read_status(scu);
}
if (status & BIT(0)) {
- dev_err(&ipcdev.pdev->dev, "IPC timed out");
+ dev_err(&scu->pdev->dev, "IPC timed out");
return -ETIMEDOUT;
}
@@ -188,31 +192,32 @@ static inline int busy_loop(void)
}
/* Wait till ipc ioc interrupt is received or timeout in 3 HZ */
-static inline int ipc_wait_for_interrupt(void)
+static inline int ipc_wait_for_interrupt(struct intel_scu_ipc_dev *scu)
{
int status;
- if (!wait_for_completion_timeout(&ipcdev.cmd_complete, 3 * HZ)) {
- struct device *dev = &ipcdev.pdev->dev;
+ if (!wait_for_completion_timeout(&scu->cmd_complete, 3 * HZ)) {
+ struct device *dev = &scu->pdev->dev;
dev_err(dev, "IPC timed out\n");
return -ETIMEDOUT;
}
- status = ipc_read_status();
+ status = ipc_read_status(scu);
if (status & BIT(1))
return -EIO;
return 0;
}
-static int intel_scu_ipc_check_status(void)
+static int intel_scu_ipc_check_status(struct intel_scu_ipc_dev *scu)
{
- return ipcdev.irq_mode ? ipc_wait_for_interrupt() : busy_loop();
+ return scu->irq_mode ? ipc_wait_for_interrupt(scu) : busy_loop(scu);
}
/* Read/Write power control(PMIC in Langwell, MSIC in PenWell) registers */
static int pwr_reg_rdwr(u16 *addr, u8 *data, u32 count, u32 op, u32 id)
{
+ struct intel_scu_ipc_dev *scu = &ipcdev;
int nc;
u32 offset = 0;
int err;
@@ -223,7 +228,7 @@ static int pwr_reg_rdwr(u16 *addr, u8 *data, u32 count, u32 op, u32 id)
mutex_lock(&ipclock);
- if (ipcdev.pdev == NULL) {
+ if (scu->pdev == NULL) {
mutex_unlock(&ipclock);
return -ENODEV;
}
@@ -235,27 +240,27 @@ static int pwr_reg_rdwr(u16 *addr, u8 *data, u32 count, u32 op, u32 id)
if (id == IPC_CMD_PCNTRL_R) {
for (nc = 0, offset = 0; nc < count; nc++, offset += 4)
- ipc_data_writel(wbuf[nc], offset);
- ipc_command((count * 2) << 16 | id << 12 | 0 << 8 | op);
+ ipc_data_writel(scu, wbuf[nc], offset);
+ ipc_command(scu, (count * 2) << 16 | id << 12 | 0 << 8 | op);
} else if (id == IPC_CMD_PCNTRL_W) {
for (nc = 0; nc < count; nc++, offset += 1)
cbuf[offset] = data[nc];
for (nc = 0, offset = 0; nc < count; nc++, offset += 4)
- ipc_data_writel(wbuf[nc], offset);
- ipc_command((count * 3) << 16 | id << 12 | 0 << 8 | op);
+ ipc_data_writel(scu, wbuf[nc], offset);
+ ipc_command(scu, (count * 3) << 16 | id << 12 | 0 << 8 | op);
} else if (id == IPC_CMD_PCNTRL_M) {
cbuf[offset] = data[0];
cbuf[offset + 1] = data[1];
- ipc_data_writel(wbuf[0], 0); /* Write wbuff */
- ipc_command(4 << 16 | id << 12 | 0 << 8 | op);
+ ipc_data_writel(scu, wbuf[0], 0); /* Write wbuff */
+ ipc_command(scu, 4 << 16 | id << 12 | 0 << 8 | op);
}
- err = intel_scu_ipc_check_status();
+ err = intel_scu_ipc_check_status(scu);
if (!err && id == IPC_CMD_PCNTRL_R) { /* Read rbuf */
/* Workaround: values are read as 0 without memcpy_fromio */
- memcpy_fromio(cbuf, ipcdev.ipc_base + 0x90, 16);
+ memcpy_fromio(cbuf, scu->ipc_base + 0x90, 16);
for (nc = 0; nc < count; nc++)
- data[nc] = ipc_data_readb(nc);
+ data[nc] = ipc_data_readb(scu, nc);
}
mutex_unlock(&ipclock);
return err;
@@ -436,15 +441,16 @@ EXPORT_SYMBOL(intel_scu_ipc_update_register);
*/
int intel_scu_ipc_simple_command(int cmd, int sub)
{
+ struct intel_scu_ipc_dev *scu = &ipcdev;
int err;
mutex_lock(&ipclock);
- if (ipcdev.pdev == NULL) {
+ if (scu->pdev == NULL) {
mutex_unlock(&ipclock);
return -ENODEV;
}
- ipc_command(sub << 12 | cmd);
- err = intel_scu_ipc_check_status();
+ ipc_command(scu, sub << 12 | cmd);
+ err = intel_scu_ipc_check_status(scu);
mutex_unlock(&ipclock);
return err;
}
@@ -465,23 +471,24 @@ EXPORT_SYMBOL(intel_scu_ipc_simple_command);
int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen,
u32 *out, int outlen)
{
+ struct intel_scu_ipc_dev *scu = &ipcdev;
int i, err;
mutex_lock(&ipclock);
- if (ipcdev.pdev == NULL) {
+ if (scu->pdev == NULL) {
mutex_unlock(&ipclock);
return -ENODEV;
}
for (i = 0; i < inlen; i++)
- ipc_data_writel(*in++, 4 * i);
+ ipc_data_writel(scu, *in++, 4 * i);
- ipc_command((inlen << 16) | (sub << 12) | cmd);
- err = intel_scu_ipc_check_status();
+ ipc_command(scu, (inlen << 16) | (sub << 12) | cmd);
+ err = intel_scu_ipc_check_status(scu);
if (!err) {
for (i = 0; i < outlen; i++)
- *out++ = ipc_data_readl(4 * i);
+ *out++ = ipc_data_readl(scu, 4 * i);
}
mutex_unlock(&ipclock);
@@ -507,25 +514,26 @@ EXPORT_SYMBOL(intel_scu_ipc_command);
*/
int intel_scu_ipc_i2c_cntrl(u32 addr, u32 *data)
{
+ struct intel_scu_ipc_dev *scu = &ipcdev;
u32 cmd = 0;
mutex_lock(&ipclock);
- if (ipcdev.pdev == NULL) {
+ if (scu->pdev == NULL) {
mutex_unlock(&ipclock);
return -ENODEV;
}
cmd = (addr >> 24) & 0xFF;
if (cmd == IPC_I2C_READ) {
- writel(addr, ipcdev.i2c_base + IPC_I2C_CNTRL_ADDR);
+ writel(addr, scu->i2c_base + IPC_I2C_CNTRL_ADDR);
/* Write not getting updated without delay */
mdelay(1);
- *data = readl(ipcdev.i2c_base + I2C_DATA_ADDR);
+ *data = readl(scu->i2c_base + I2C_DATA_ADDR);
} else if (cmd == IPC_I2C_WRITE) {
- writel(*data, ipcdev.i2c_base + I2C_DATA_ADDR);
+ writel(*data, scu->i2c_base + I2C_DATA_ADDR);
mdelay(1);
- writel(addr, ipcdev.i2c_base + IPC_I2C_CNTRL_ADDR);
+ writel(addr, scu->i2c_base + IPC_I2C_CNTRL_ADDR);
} else {
- dev_err(&ipcdev.pdev->dev,
+ dev_err(&scu->pdev->dev,
"intel_scu_ipc: I2C INVALID_CMD = 0x%x\n", cmd);
mutex_unlock(&ipclock);
@@ -545,8 +553,10 @@ EXPORT_SYMBOL(intel_scu_ipc_i2c_cntrl);
*/
static irqreturn_t ioc(int irq, void *dev_id)
{
- if (ipcdev.irq_mode)
- complete(&ipcdev.cmd_complete);
+ struct intel_scu_ipc_dev *scu = dev_id;
+
+ if (scu->irq_mode)
+ complete(&scu->cmd_complete);
return IRQ_HANDLED;
}
@@ -562,15 +572,16 @@ static irqreturn_t ioc(int irq, void *dev_id)
static int ipc_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
int err;
+ struct intel_scu_ipc_dev *scu = &ipcdev;
struct intel_scu_ipc_pdata_t *pdata;
- if (ipcdev.pdev) /* We support only one SCU */
+ if (scu->pdev) /* We support only one SCU */
return -EBUSY;
pdata = (struct intel_scu_ipc_pdata_t *)id->driver_data;
- ipcdev.pdev = pci_dev_get(dev);
- ipcdev.irq_mode = pdata->irq_mode;
+ scu->pdev = pci_dev_get(dev);
+ scu->irq_mode = pdata->irq_mode;
err = pcim_enable_device(dev);
if (err)
@@ -580,21 +591,22 @@ static int ipc_probe(struct pci_dev *dev, const struct pci_device_id *id)
if (err)
return err;
- init_completion(&ipcdev.cmd_complete);
+ init_completion(&scu->cmd_complete);
err = devm_request_irq(&dev->dev, dev->irq, ioc, 0, "intel_scu_ipc",
- &ipcdev);
+ scu);
if (err)
return err;
- ipcdev.ipc_base = pcim_iomap_table(dev)[0];
+ scu->ipc_base = pcim_iomap_table(dev)[0];
- ipcdev.i2c_base = ioremap_nocache(pdata->i2c_base, pdata->i2c_len);
- if (!ipcdev.i2c_base)
+ scu->i2c_base = ioremap_nocache(pdata->i2c_base, pdata->i2c_len);
+ if (!scu->i2c_base)
return -ENOMEM;
intel_scu_devices_create();
+ pci_set_drvdata(dev, scu);
return 0;
}
@@ -610,9 +622,11 @@ static int ipc_probe(struct pci_dev *dev, const struct pci_device_id *id)
*/
static void ipc_remove(struct pci_dev *pdev)
{
- pci_dev_put(ipcdev.pdev);
- iounmap(ipcdev.i2c_base);
- ipcdev.pdev = NULL;
+ struct intel_scu_ipc_dev *scu = pci_get_drvdata(pdev);
+
+ pci_dev_put(scu->pdev);
+ scu->pdev = NULL;
+ iounmap(scu->i2c_base);
intel_scu_devices_destroy();
}
--
2.5.3
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v2 3/5] intel_scu_ipc: convert to use struct device *
2015-10-12 11:19 [PATCH v2 0/5] intel_scu_ipc: bug fixes and amendments Andy Shevchenko
2015-10-12 11:19 ` [PATCH v2 1/5] intel_scu_ipc: fix error path by turning to devm_* / pcim_* Andy Shevchenko
2015-10-12 11:19 ` [PATCH v2 2/5] intel_scu_ipc: propagate pointer to struct intel_scu_ipc_dev Andy Shevchenko
@ 2015-10-12 11:19 ` Andy Shevchenko
2015-10-12 11:19 ` [PATCH v2 4/5] intel_scu_ipc: switch to use module_pci_driver() macro Andy Shevchenko
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Andy Shevchenko @ 2015-10-12 11:19 UTC (permalink / raw)
To: platform-driver-x86, Darren Hart, linux-kernel; +Cc: Andy Shevchenko
Switch the code to use struct device * instead of struct pci_dev * since there
is no reason to access PCI related features in the driver.
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
drivers/platform/x86/intel_scu_ipc.c | 41 ++++++++++++++++--------------------
1 file changed, 18 insertions(+), 23 deletions(-)
diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c
index 6c9367f..5087485 100644
--- a/drivers/platform/x86/intel_scu_ipc.c
+++ b/drivers/platform/x86/intel_scu_ipc.c
@@ -92,11 +92,8 @@ static struct intel_scu_ipc_pdata_t intel_scu_ipc_tangier_pdata = {
.irq_mode = 0,
};
-static int ipc_probe(struct pci_dev *dev, const struct pci_device_id *id);
-static void ipc_remove(struct pci_dev *pdev);
-
struct intel_scu_ipc_dev {
- struct pci_dev *pdev;
+ struct device *dev;
void __iomem *ipc_base;
void __iomem *i2c_base;
struct completion cmd_complete;
@@ -181,7 +178,7 @@ static inline int busy_loop(struct intel_scu_ipc_dev *scu)
}
if (status & BIT(0)) {
- dev_err(&scu->pdev->dev, "IPC timed out");
+ dev_err(scu->dev, "IPC timed out");
return -ETIMEDOUT;
}
@@ -197,8 +194,7 @@ static inline int ipc_wait_for_interrupt(struct intel_scu_ipc_dev *scu)
int status;
if (!wait_for_completion_timeout(&scu->cmd_complete, 3 * HZ)) {
- struct device *dev = &scu->pdev->dev;
- dev_err(dev, "IPC timed out\n");
+ dev_err(scu->dev, "IPC timed out\n");
return -ETIMEDOUT;
}
@@ -228,7 +224,7 @@ static int pwr_reg_rdwr(u16 *addr, u8 *data, u32 count, u32 op, u32 id)
mutex_lock(&ipclock);
- if (scu->pdev == NULL) {
+ if (scu->dev == NULL) {
mutex_unlock(&ipclock);
return -ENODEV;
}
@@ -445,7 +441,7 @@ int intel_scu_ipc_simple_command(int cmd, int sub)
int err;
mutex_lock(&ipclock);
- if (scu->pdev == NULL) {
+ if (scu->dev == NULL) {
mutex_unlock(&ipclock);
return -ENODEV;
}
@@ -475,7 +471,7 @@ int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen,
int i, err;
mutex_lock(&ipclock);
- if (scu->pdev == NULL) {
+ if (scu->dev == NULL) {
mutex_unlock(&ipclock);
return -ENODEV;
}
@@ -518,7 +514,7 @@ int intel_scu_ipc_i2c_cntrl(u32 addr, u32 *data)
u32 cmd = 0;
mutex_lock(&ipclock);
- if (scu->pdev == NULL) {
+ if (scu->dev == NULL) {
mutex_unlock(&ipclock);
return -ENODEV;
}
@@ -533,7 +529,7 @@ int intel_scu_ipc_i2c_cntrl(u32 addr, u32 *data)
mdelay(1);
writel(addr, scu->i2c_base + IPC_I2C_CNTRL_ADDR);
} else {
- dev_err(&scu->pdev->dev,
+ dev_err(scu->dev,
"intel_scu_ipc: I2C INVALID_CMD = 0x%x\n", cmd);
mutex_unlock(&ipclock);
@@ -563,42 +559,42 @@ static irqreturn_t ioc(int irq, void *dev_id)
/**
* ipc_probe - probe an Intel SCU IPC
- * @dev: the PCI device matching
+ * @pdev: the PCI device matching
* @id: entry in the match table
*
* Enable and install an intel SCU IPC. This appears in the PCI space
* but uses some hard coded addresses as well.
*/
-static int ipc_probe(struct pci_dev *dev, const struct pci_device_id *id)
+static int ipc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
int err;
struct intel_scu_ipc_dev *scu = &ipcdev;
struct intel_scu_ipc_pdata_t *pdata;
- if (scu->pdev) /* We support only one SCU */
+ if (scu->dev) /* We support only one SCU */
return -EBUSY;
pdata = (struct intel_scu_ipc_pdata_t *)id->driver_data;
- scu->pdev = pci_dev_get(dev);
+ scu->dev = &pdev->dev;
scu->irq_mode = pdata->irq_mode;
- err = pcim_enable_device(dev);
+ err = pcim_enable_device(pdev);
if (err)
return err;
- err = pcim_iomap_regions(dev, 1 << 0, pci_name(dev));
+ err = pcim_iomap_regions(pdev, 1 << 0, pci_name(pdev));
if (err)
return err;
init_completion(&scu->cmd_complete);
- err = devm_request_irq(&dev->dev, dev->irq, ioc, 0, "intel_scu_ipc",
+ err = devm_request_irq(&pdev->dev, pdev->irq, ioc, 0, "intel_scu_ipc",
scu);
if (err)
return err;
- scu->ipc_base = pcim_iomap_table(dev)[0];
+ scu->ipc_base = pcim_iomap_table(pdev)[0];
scu->i2c_base = ioremap_nocache(pdata->i2c_base, pdata->i2c_len);
if (!scu->i2c_base)
@@ -606,7 +602,7 @@ static int ipc_probe(struct pci_dev *dev, const struct pci_device_id *id)
intel_scu_devices_create();
- pci_set_drvdata(dev, scu);
+ pci_set_drvdata(pdev, scu);
return 0;
}
@@ -624,8 +620,7 @@ static void ipc_remove(struct pci_dev *pdev)
{
struct intel_scu_ipc_dev *scu = pci_get_drvdata(pdev);
- pci_dev_put(scu->pdev);
- scu->pdev = NULL;
+ scu->dev = NULL;
iounmap(scu->i2c_base);
intel_scu_devices_destroy();
}
--
2.5.3
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v2 4/5] intel_scu_ipc: switch to use module_pci_driver() macro
2015-10-12 11:19 [PATCH v2 0/5] intel_scu_ipc: bug fixes and amendments Andy Shevchenko
` (2 preceding siblings ...)
2015-10-12 11:19 ` [PATCH v2 3/5] intel_scu_ipc: convert to use struct device * Andy Shevchenko
@ 2015-10-12 11:19 ` Andy Shevchenko
2015-10-12 11:19 ` [PATCH v2 5/5] intel_scu_ipc: protect dev member assignment on ->remove() Andy Shevchenko
2015-10-15 4:44 ` [PATCH v2 0/5] intel_scu_ipc: bug fixes and amendments Darren Hart
5 siblings, 0 replies; 7+ messages in thread
From: Andy Shevchenko @ 2015-10-12 11:19 UTC (permalink / raw)
To: platform-driver-x86, Darren Hart, linux-kernel; +Cc: Andy Shevchenko
Eliminate some boilerplate code by using module_pci_driver() instead of
init/exit, moving the salient bits from init into probe.
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
drivers/platform/x86/intel_scu_ipc.c | 23 ++++++-----------------
1 file changed, 6 insertions(+), 17 deletions(-)
diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c
index 5087485..9de2029 100644
--- a/drivers/platform/x86/intel_scu_ipc.c
+++ b/drivers/platform/x86/intel_scu_ipc.c
@@ -567,10 +567,15 @@ static irqreturn_t ioc(int irq, void *dev_id)
*/
static int ipc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
+ int platform; /* Platform type */
int err;
struct intel_scu_ipc_dev *scu = &ipcdev;
struct intel_scu_ipc_pdata_t *pdata;
+ platform = intel_mid_identify_cpu();
+ if (platform == 0)
+ return -ENODEV;
+
if (scu->dev) /* We support only one SCU */
return -EBUSY;
@@ -651,24 +656,8 @@ static struct pci_driver ipc_driver = {
.remove = ipc_remove,
};
-static int __init intel_scu_ipc_init(void)
-{
- int platform; /* Platform type */
-
- platform = intel_mid_identify_cpu();
- if (platform == 0)
- return -ENODEV;
- return pci_register_driver(&ipc_driver);
-}
-
-static void __exit intel_scu_ipc_exit(void)
-{
- pci_unregister_driver(&ipc_driver);
-}
+module_pci_driver(ipc_driver);
MODULE_AUTHOR("Sreedhara DS <sreedhara.ds@intel.com>");
MODULE_DESCRIPTION("Intel SCU IPC driver");
MODULE_LICENSE("GPL");
-
-module_init(intel_scu_ipc_init);
-module_exit(intel_scu_ipc_exit);
--
2.5.3
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v2 5/5] intel_scu_ipc: protect dev member assignment on ->remove()
2015-10-12 11:19 [PATCH v2 0/5] intel_scu_ipc: bug fixes and amendments Andy Shevchenko
` (3 preceding siblings ...)
2015-10-12 11:19 ` [PATCH v2 4/5] intel_scu_ipc: switch to use module_pci_driver() macro Andy Shevchenko
@ 2015-10-12 11:19 ` Andy Shevchenko
2015-10-15 4:44 ` [PATCH v2 0/5] intel_scu_ipc: bug fixes and amendments Darren Hart
5 siblings, 0 replies; 7+ messages in thread
From: Andy Shevchenko @ 2015-10-12 11:19 UTC (permalink / raw)
To: platform-driver-x86, Darren Hart, linux-kernel; +Cc: Andy Shevchenko
Protect the dev member assignment in ->remove() since user may potentially call
unbind from a sysfs even if the driver is built-in. The latter might be racy
with ongoing SCU communication.
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
drivers/platform/x86/intel_scu_ipc.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c
index 9de2029..f94b730 100644
--- a/drivers/platform/x86/intel_scu_ipc.c
+++ b/drivers/platform/x86/intel_scu_ipc.c
@@ -625,7 +625,10 @@ static void ipc_remove(struct pci_dev *pdev)
{
struct intel_scu_ipc_dev *scu = pci_get_drvdata(pdev);
+ mutex_lock(&ipclock);
scu->dev = NULL;
+ mutex_unlock(&ipclock);
+
iounmap(scu->i2c_base);
intel_scu_devices_destroy();
}
--
2.5.3
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH v2 0/5] intel_scu_ipc: bug fixes and amendments
2015-10-12 11:19 [PATCH v2 0/5] intel_scu_ipc: bug fixes and amendments Andy Shevchenko
` (4 preceding siblings ...)
2015-10-12 11:19 ` [PATCH v2 5/5] intel_scu_ipc: protect dev member assignment on ->remove() Andy Shevchenko
@ 2015-10-15 4:44 ` Darren Hart
5 siblings, 0 replies; 7+ messages in thread
From: Darren Hart @ 2015-10-15 4:44 UTC (permalink / raw)
To: Andy Shevchenko; +Cc: platform-driver-x86, linux-kernel
On Mon, Oct 12, 2015 at 02:19:43PM +0300, Andy Shevchenko wrote:
> There are couple of bugfixes (patches 1 & 5) and amendments to the driver.
>
> Patch series has been tested on Intel Medfield and Intel Edison (Merrifield)
> boards.
>
> Changes v2:
> - improve patch 4 commit message (suggested by Darren)
> - leave only fix of a potential bug in patch 5
Thank you Andy, queued to testing.
--
Darren Hart
Intel Open Source Technology Center
^ permalink raw reply [flat|nested] 7+ messages in thread