@@ -21,6 +21,7 @@
#include <linux/pm_runtime.h>
#include <linux/mutex.h>
#include <linux/of.h>
+#include <linux/slab.h>
#include "hwspinlock_internal.h"
@@ -502,7 +503,6 @@ static struct hwspinlock *hwspin_lock_unregister_single(unsigned int id)
/**
* hwspin_lock_register() - register a new hw spinlock device
- * @bank: the hwspinlock device, which usually provides numerous hw locks
* @dev: the backing device
* @ops: hwspinlock handlers for this device
* @base_id: id of the first hardware spinlock in this bank
@@ -514,21 +514,25 @@ static struct hwspinlock *hwspin_lock_unregister_single(unsigned int id)
*
* Should be called from a process context (might sleep)
*
- * Returns: %0 on success, or an appropriate error code on failure
+ * Returns: a pointer to the device (needed for unregistering), or an
+ * appropriate error pointer on failure
*/
-int hwspin_lock_register(struct hwspinlock_device *bank, struct device *dev,
- const struct hwspinlock_ops *ops, int base_id, int num_locks,
- void *init_data)
+struct hwspinlock_device *hwspin_lock_register(struct device *dev, const struct hwspinlock_ops *ops,
+ int base_id, int num_locks, void *init_data)
{
+ struct hwspinlock_device *bank;
struct hwspinlock *hwlock;
int ret, i;
- if (!bank || !ops || !dev || !num_locks || !ops->trylock ||
- !ops->unlock) {
+ if (!ops || !dev || !num_locks || !ops->trylock || !ops->unlock) {
pr_err("invalid parameters\n");
- return -EINVAL;
+ return ERR_PTR(-EINVAL);
}
+ bank = kzalloc(struct_size(bank, lock, num_locks), GFP_KERNEL);
+ if (!bank)
+ return ERR_PTR(-ENOMEM);
+
bank->dev = dev;
bank->ops = ops;
bank->base_id = base_id;
@@ -553,12 +557,13 @@ int hwspin_lock_register(struct hwspinlock_device *bank, struct device *dev,
goto reg_failed;
}
- return 0;
+ return bank;
reg_failed:
while (--i >= 0)
hwspin_lock_unregister_single(base_id + i);
- return ret;
+ kfree(bank);
+ return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(hwspin_lock_register);
@@ -589,6 +594,8 @@ int hwspin_lock_unregister(struct hwspinlock_device *bank)
WARN_ON(tmp != hwlock);
}
+ kfree(bank);
+
return 0;
}
EXPORT_SYMBOL_GPL(hwspin_lock_unregister);
@@ -639,7 +646,6 @@ EXPORT_SYMBOL_GPL(devm_hwspin_lock_unregister);
* devm_hwspin_lock_register() - register a new hw spinlock device for
* a managed device
* @dev: the backing device
- * @bank: the hwspinlock device, which usually provides numerous hw locks
* @ops: hwspinlock handlers for this device
* @base_id: id of the first hardware spinlock in this bank
* @num_locks: number of hwspinlocks provided by this device
@@ -650,29 +656,27 @@ EXPORT_SYMBOL_GPL(devm_hwspin_lock_unregister);
*
* Should be called from a process context (might sleep)
*
- * Returns: %0 on success, or an appropriate error code on failure
+ * Returns: a pointer to the device (usable for unregistering), or an
+ * appropriate error pointer on failure
*/
-int devm_hwspin_lock_register(struct device *dev,
- struct hwspinlock_device *bank,
- const struct hwspinlock_ops *ops,
- int base_id, int num_locks, void *init_data)
+struct hwspinlock_device *devm_hwspin_lock_register(struct device *dev, const struct hwspinlock_ops *ops,
+ int base_id, int num_locks, void *init_data)
{
- struct hwspinlock_device **ptr;
- int ret;
+ struct hwspinlock_device **ptr, *bank;
ptr = devres_alloc(devm_hwspin_lock_unreg, sizeof(*ptr), GFP_KERNEL);
if (!ptr)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
- ret = hwspin_lock_register(bank, dev, ops, base_id, num_locks, init_data);
- if (!ret) {
+ bank = hwspin_lock_register(dev, ops, base_id, num_locks, init_data);
+ if (!IS_ERR(bank)) {
*ptr = bank;
devres_add(dev, ptr);
} else {
devres_free(ptr);
}
- return ret;
+ return bank;
}
EXPORT_SYMBOL_GPL(devm_hwspin_lock_register);
@@ -80,7 +80,6 @@ static const struct hwspinlock_ops omap_hwspinlock_ops = {
static int omap_hwspinlock_probe(struct platform_device *pdev)
{
- struct hwspinlock_device *bank;
void __iomem *io_base;
int num_locks, i, ret;
/* Only a single hwspinlock block device is supported */
@@ -117,13 +116,8 @@ static int omap_hwspinlock_probe(struct platform_device *pdev)
num_locks = i * 32; /* actual number of locks in this device */
- bank = devm_kzalloc(&pdev->dev, struct_size(bank, lock, num_locks),
- GFP_KERNEL);
- if (!bank)
- return -ENOMEM;
-
- return devm_hwspin_lock_register(&pdev->dev, bank, &omap_hwspinlock_ops,
- base_id, num_locks, io_base + LOCK_BASE_OFFSET);
+ return devm_hwspin_lock_register_errno(&pdev->dev, &omap_hwspinlock_ops, base_id,
+ num_locks, io_base + LOCK_BASE_OFFSET);
}
static const struct of_device_id omap_hwspinlock_of_match[] = {
@@ -223,9 +223,7 @@ static struct regmap *qcom_hwspinlock_probe_mmio(struct platform_device *pdev,
static int qcom_hwspinlock_probe(struct platform_device *pdev)
{
struct qcom_hwspinlock_priv_init_data init;
- struct hwspinlock_device *bank;
struct regmap *regmap;
- size_t array_size;
regmap = qcom_hwspinlock_probe_syscon(pdev, &init.base, &init.stride);
if (IS_ERR(regmap) && PTR_ERR(regmap) == -ENODEV)
@@ -234,16 +232,11 @@ static int qcom_hwspinlock_probe(struct platform_device *pdev)
if (IS_ERR(regmap))
return PTR_ERR(regmap);
- array_size = QCOM_MUTEX_NUM_LOCKS * sizeof(struct hwspinlock);
- bank = devm_kzalloc(&pdev->dev, sizeof(*bank) + array_size, GFP_KERNEL);
- if (!bank)
- return -ENOMEM;
-
init.dev = &pdev->dev;
init.regmap = regmap;
- return devm_hwspin_lock_register(&pdev->dev, bank, &qcom_hwspinlock_ops,
- 0, QCOM_MUTEX_NUM_LOCKS, &init);
+ return devm_hwspin_lock_register_errno(&pdev->dev, &qcom_hwspinlock_ops,
+ 0, QCOM_MUTEX_NUM_LOCKS, &init);
}
static struct platform_driver qcom_hwspinlock_driver = {
@@ -33,15 +33,14 @@
struct sprd_hwspinlock_dev {
void __iomem *base;
struct clk *clk;
- struct hwspinlock_device bank;
};
/* try to lock the hardware spinlock */
static int sprd_hwspinlock_trylock(struct hwspinlock *lock)
{
- struct sprd_hwspinlock_dev *sprd_hwlock =
- dev_get_drvdata(hwspin_lock_get_dev(lock));
void __iomem *addr = hwspin_lock_get_priv(lock);
+ struct device *dev = hwspin_lock_get_dev(lock);
+ struct sprd_hwspinlock_dev *sprd_hwlock = dev_get_drvdata(dev);
int user_id, lock_id;
if (!readl(addr))
@@ -50,8 +49,7 @@ static int sprd_hwspinlock_trylock(struct hwspinlock *lock)
lock_id = hwlock_to_id(lock);
/* get the hardware spinlock master/user id */
user_id = readl(sprd_hwlock->base + HWSPINLOCK_MASTERID(lock_id));
- dev_warn(sprd_hwlock->bank.dev,
- "hwspinlock [%d] lock failed and master/user id = %d!\n",
+ dev_warn(dev, "hwspinlock [%d] lock failed and master/user id = %d!\n",
lock_id, user_id);
return 0;
}
@@ -97,9 +95,7 @@ static int sprd_hwspinlock_probe(struct platform_device *pdev)
if (!pdev->dev.of_node)
return -ENODEV;
- sprd_hwlock = devm_kzalloc(&pdev->dev,
- struct_size(sprd_hwlock, bank.lock, SPRD_HWLOCKS_NUM),
- GFP_KERNEL);
+ sprd_hwlock = devm_kzalloc(&pdev->dev, sizeof(*sprd_hwlock), GFP_KERNEL);
if (!sprd_hwlock)
return -ENOMEM;
@@ -130,9 +126,8 @@ static int sprd_hwspinlock_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, sprd_hwlock);
- return devm_hwspin_lock_register(&pdev->dev, &sprd_hwlock->bank,
- &sprd_hwspinlock_ops, 0,
- SPRD_HWLOCKS_NUM, sprd_hwlock->base);
+ return devm_hwspin_lock_register_errno(&pdev->dev, &sprd_hwspinlock_ops, 0,
+ SPRD_HWLOCKS_NUM, sprd_hwlock->base);
}
static const struct of_device_id sprd_hwspinlock_of_match[] = {
@@ -22,7 +22,6 @@
struct stm32_hwspinlock {
struct clk *clk;
- struct hwspinlock_device bank;
};
static int stm32_hwspinlock_trylock(struct hwspinlock *lock)
@@ -85,7 +84,7 @@ static int stm32_hwspinlock_probe(struct platform_device *pdev)
if (IS_ERR(io_base))
return PTR_ERR(io_base);
- hw = devm_kzalloc(dev, struct_size(hw, bank.lock, STM32_MUTEX_NUM_LOCKS), GFP_KERNEL);
+ hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL);
if (!hw)
return -ENOMEM;
@@ -112,8 +111,8 @@ static int stm32_hwspinlock_probe(struct platform_device *pdev)
return ret;
}
- ret = devm_hwspin_lock_register(dev, &hw->bank, &stm32_hwspinlock_ops,
- 0, STM32_MUTEX_NUM_LOCKS, io_base);
+ ret = devm_hwspin_lock_register_errno(dev, &stm32_hwspinlock_ops,
+ 0, STM32_MUTEX_NUM_LOCKS, io_base);
if (ret)
dev_err(dev, "Failed to register hwspinlock\n");
@@ -27,7 +27,6 @@
#define SPINLOCK_NOTTAKEN 0
struct sun6i_hwspinlock_data {
- struct hwspinlock_device *bank;
struct reset_control *reset;
struct clk *ahb_clk;
struct dentry *debugfs;
@@ -159,13 +158,6 @@ static int sun6i_hwspinlock_probe(struct platform_device *pdev)
goto bank_fail;
}
- priv->bank = devm_kzalloc(&pdev->dev, struct_size(priv->bank, lock, priv->nlocks),
- GFP_KERNEL);
- if (!priv->bank) {
- err = -ENOMEM;
- goto bank_fail;
- }
-
/* failure of debugfs is considered non-fatal */
sun6i_hwspinlock_debugfs_init(priv);
if (IS_ERR(priv->debugfs))
@@ -177,8 +169,8 @@ static int sun6i_hwspinlock_probe(struct platform_device *pdev)
goto bank_fail;
}
- return devm_hwspin_lock_register(&pdev->dev, priv->bank, &sun6i_hwspinlock_ops,
- SPINLOCK_BASE_ID, priv->nlocks, io_base + SPINLOCK_LOCK_REGN);
+ return devm_hwspin_lock_register_errno(&pdev->dev, &sun6i_hwspinlock_ops, SPINLOCK_BASE_ID,
+ priv->nlocks, io_base + SPINLOCK_LOCK_REGN);
bank_fail:
clk_disable_unprepare(priv->ahb_clk);
@@ -29,8 +29,8 @@ struct hwspinlock_ops;
void *hwspin_lock_get_priv(struct hwspinlock *hwlock);
struct device *hwspin_lock_get_dev(struct hwspinlock *hwlock);
-int hwspin_lock_register(struct hwspinlock_device *bank, struct device *dev,
- const struct hwspinlock_ops *ops, int base_id, int num_locks, void *init_data);
+struct hwspinlock_device *hwspin_lock_register(struct device *dev, const struct hwspinlock_ops *ops,
+ int base_id, int num_locks, void *init_data);
int hwspin_lock_unregister(struct hwspinlock_device *bank);
struct hwspinlock *hwspin_lock_request_specific(unsigned int id);
int hwspin_lock_free(struct hwspinlock *hwlock);
@@ -46,10 +46,15 @@ struct hwspinlock *devm_hwspin_lock_request_specific(struct device *dev,
unsigned int id);
int devm_hwspin_lock_unregister(struct device *dev,
struct hwspinlock_device *bank);
-int devm_hwspin_lock_register(struct device *dev,
- struct hwspinlock_device *bank,
- const struct hwspinlock_ops *ops,
- int base_id, int num_locks, void *init_data);
+struct hwspinlock_device *devm_hwspin_lock_register(struct device *dev, const struct hwspinlock_ops *ops,
+ int base_id, int num_locks, void *init_data);
+
+static inline int devm_hwspin_lock_register_errno(struct device *dev,
+ const struct hwspinlock_ops *ops,
+ int base_id, int num_locks, void *init_data)
+{
+ return PTR_ERR_OR_ZERO(devm_hwspin_lock_register(dev, ops, base_id, num_locks, init_data));
+}
#else /* !CONFIG_HWSPINLOCK */