stm class/intel_th: Updates for 4.7
These are: * Intel TH/MSU: improved resource handling and releasing * Intel TH/MSU: rehashed locking around buffer accesses * Intel TH/outputs: better sysfs group handling * Intel TH, STM: various bugfixes and smaller improvements * Intel TH: added a PCI ID for Broxton-M SOC -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iF4EABEIAAYFAlcXeJMACgkQ68X2JGMFV//ycAEAkigLTg5OWwGau0okPUnNn5G8 uzH7mPsA8QtgXNQOJBkA/RVk+FJeOx8yR3oUSl9BSXYGPcr/b2gZrC7SLRP0V5rX =/vz4 -----END PGP SIGNATURE----- Merge tag 'stm-for-greg-20160420' of git://git.kernel.org/pub/scm/linux/kernel/git/ash/stm into char-misc-next Alexander writes: stm class/intel_th: Updates for 4.7 These are: * Intel TH/MSU: improved resource handling and releasing * Intel TH/MSU: rehashed locking around buffer accesses * Intel TH/outputs: better sysfs group handling * Intel TH, STM: various bugfixes and smaller improvements * Intel TH: added a PCI ID for Broxton-M SOC
This commit is contained in:
commit
2fc5ddaa3f
|
@ -9754,6 +9754,7 @@ F: drivers/mmc/host/dw_mmc*
|
||||||
SYSTEM TRACE MODULE CLASS
|
SYSTEM TRACE MODULE CLASS
|
||||||
M: Alexander Shishkin <alexander.shishkin@linux.intel.com>
|
M: Alexander Shishkin <alexander.shishkin@linux.intel.com>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
T: git git://git.kernel.org/pub/scm/linux/kernel/git/ash/stm.git
|
||||||
F: Documentation/trace/stm.txt
|
F: Documentation/trace/stm.txt
|
||||||
F: drivers/hwtracing/stm/
|
F: drivers/hwtracing/stm/
|
||||||
F: include/linux/stm.h
|
F: include/linux/stm.h
|
||||||
|
|
|
@ -71,6 +71,15 @@ static int intel_th_probe(struct device *dev)
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
if (thdrv->attr_group) {
|
||||||
|
ret = sysfs_create_group(&thdev->dev.kobj, thdrv->attr_group);
|
||||||
|
if (ret) {
|
||||||
|
thdrv->remove(thdev);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (thdev->type == INTEL_TH_OUTPUT &&
|
if (thdev->type == INTEL_TH_OUTPUT &&
|
||||||
!intel_th_output_assigned(thdev))
|
!intel_th_output_assigned(thdev))
|
||||||
ret = hubdrv->assign(hub, thdev);
|
ret = hubdrv->assign(hub, thdev);
|
||||||
|
@ -91,6 +100,9 @@ static int intel_th_remove(struct device *dev)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (thdrv->attr_group)
|
||||||
|
sysfs_remove_group(&thdev->dev.kobj, thdrv->attr_group);
|
||||||
|
|
||||||
thdrv->remove(thdev);
|
thdrv->remove(thdev);
|
||||||
|
|
||||||
if (intel_th_output_assigned(thdev)) {
|
if (intel_th_output_assigned(thdev)) {
|
||||||
|
@ -171,7 +183,14 @@ static DEVICE_ATTR_RO(port);
|
||||||
|
|
||||||
static int intel_th_output_activate(struct intel_th_device *thdev)
|
static int intel_th_output_activate(struct intel_th_device *thdev)
|
||||||
{
|
{
|
||||||
struct intel_th_driver *thdrv = to_intel_th_driver(thdev->dev.driver);
|
struct intel_th_driver *thdrv =
|
||||||
|
to_intel_th_driver_or_null(thdev->dev.driver);
|
||||||
|
|
||||||
|
if (!thdrv)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
if (!try_module_get(thdrv->driver.owner))
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
if (thdrv->activate)
|
if (thdrv->activate)
|
||||||
return thdrv->activate(thdev);
|
return thdrv->activate(thdev);
|
||||||
|
@ -183,12 +202,18 @@ static int intel_th_output_activate(struct intel_th_device *thdev)
|
||||||
|
|
||||||
static void intel_th_output_deactivate(struct intel_th_device *thdev)
|
static void intel_th_output_deactivate(struct intel_th_device *thdev)
|
||||||
{
|
{
|
||||||
struct intel_th_driver *thdrv = to_intel_th_driver(thdev->dev.driver);
|
struct intel_th_driver *thdrv =
|
||||||
|
to_intel_th_driver_or_null(thdev->dev.driver);
|
||||||
|
|
||||||
|
if (!thdrv)
|
||||||
|
return;
|
||||||
|
|
||||||
if (thdrv->deactivate)
|
if (thdrv->deactivate)
|
||||||
thdrv->deactivate(thdev);
|
thdrv->deactivate(thdev);
|
||||||
else
|
else
|
||||||
intel_th_trace_disable(thdev);
|
intel_th_trace_disable(thdev);
|
||||||
|
|
||||||
|
module_put(thdrv->driver.owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t active_show(struct device *dev, struct device_attribute *attr,
|
static ssize_t active_show(struct device *dev, struct device_attribute *attr,
|
||||||
|
|
|
@ -115,6 +115,7 @@ intel_th_output_assigned(struct intel_th_device *thdev)
|
||||||
* @enable: enable tracing for a given output device
|
* @enable: enable tracing for a given output device
|
||||||
* @disable: disable tracing for a given output device
|
* @disable: disable tracing for a given output device
|
||||||
* @fops: file operations for device nodes
|
* @fops: file operations for device nodes
|
||||||
|
* @attr_group: attributes provided by the driver
|
||||||
*
|
*
|
||||||
* Callbacks @probe and @remove are required for all device types.
|
* Callbacks @probe and @remove are required for all device types.
|
||||||
* Switch device driver needs to fill in @assign, @enable and @disable
|
* Switch device driver needs to fill in @assign, @enable and @disable
|
||||||
|
@ -139,6 +140,8 @@ struct intel_th_driver {
|
||||||
void (*deactivate)(struct intel_th_device *thdev);
|
void (*deactivate)(struct intel_th_device *thdev);
|
||||||
/* file_operations for those who want a device node */
|
/* file_operations for those who want a device node */
|
||||||
const struct file_operations *fops;
|
const struct file_operations *fops;
|
||||||
|
/* optional attributes */
|
||||||
|
struct attribute_group *attr_group;
|
||||||
|
|
||||||
/* source ops */
|
/* source ops */
|
||||||
int (*set_output)(struct intel_th_device *thdev,
|
int (*set_output)(struct intel_th_device *thdev,
|
||||||
|
@ -148,6 +151,9 @@ struct intel_th_driver {
|
||||||
#define to_intel_th_driver(_d) \
|
#define to_intel_th_driver(_d) \
|
||||||
container_of((_d), struct intel_th_driver, driver)
|
container_of((_d), struct intel_th_driver, driver)
|
||||||
|
|
||||||
|
#define to_intel_th_driver_or_null(_d) \
|
||||||
|
((_d) ? to_intel_th_driver(_d) : NULL)
|
||||||
|
|
||||||
static inline struct intel_th_device *
|
static inline struct intel_th_device *
|
||||||
to_intel_th_hub(struct intel_th_device *thdev)
|
to_intel_th_hub(struct intel_th_device *thdev)
|
||||||
{
|
{
|
||||||
|
|
|
@ -122,7 +122,6 @@ struct msc {
|
||||||
atomic_t mmap_count;
|
atomic_t mmap_count;
|
||||||
struct mutex buf_mutex;
|
struct mutex buf_mutex;
|
||||||
|
|
||||||
struct mutex iter_mutex;
|
|
||||||
struct list_head iter_list;
|
struct list_head iter_list;
|
||||||
|
|
||||||
/* config */
|
/* config */
|
||||||
|
@ -257,23 +256,37 @@ static struct msc_iter *msc_iter_install(struct msc *msc)
|
||||||
|
|
||||||
iter = kzalloc(sizeof(*iter), GFP_KERNEL);
|
iter = kzalloc(sizeof(*iter), GFP_KERNEL);
|
||||||
if (!iter)
|
if (!iter)
|
||||||
return NULL;
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
mutex_lock(&msc->buf_mutex);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reading and tracing are mutually exclusive; if msc is
|
||||||
|
* enabled, open() will fail; otherwise existing readers
|
||||||
|
* will prevent enabling the msc and the rest of fops don't
|
||||||
|
* need to worry about it.
|
||||||
|
*/
|
||||||
|
if (msc->enabled) {
|
||||||
|
kfree(iter);
|
||||||
|
iter = ERR_PTR(-EBUSY);
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
|
||||||
msc_iter_init(iter);
|
msc_iter_init(iter);
|
||||||
iter->msc = msc;
|
iter->msc = msc;
|
||||||
|
|
||||||
mutex_lock(&msc->iter_mutex);
|
|
||||||
list_add_tail(&iter->entry, &msc->iter_list);
|
list_add_tail(&iter->entry, &msc->iter_list);
|
||||||
mutex_unlock(&msc->iter_mutex);
|
unlock:
|
||||||
|
mutex_unlock(&msc->buf_mutex);
|
||||||
|
|
||||||
return iter;
|
return iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void msc_iter_remove(struct msc_iter *iter, struct msc *msc)
|
static void msc_iter_remove(struct msc_iter *iter, struct msc *msc)
|
||||||
{
|
{
|
||||||
mutex_lock(&msc->iter_mutex);
|
mutex_lock(&msc->buf_mutex);
|
||||||
list_del(&iter->entry);
|
list_del(&iter->entry);
|
||||||
mutex_unlock(&msc->iter_mutex);
|
mutex_unlock(&msc->buf_mutex);
|
||||||
|
|
||||||
kfree(iter);
|
kfree(iter);
|
||||||
}
|
}
|
||||||
|
@ -454,7 +467,6 @@ static void msc_buffer_clear_hw_header(struct msc *msc)
|
||||||
{
|
{
|
||||||
struct msc_window *win;
|
struct msc_window *win;
|
||||||
|
|
||||||
mutex_lock(&msc->buf_mutex);
|
|
||||||
list_for_each_entry(win, &msc->win_list, entry) {
|
list_for_each_entry(win, &msc->win_list, entry) {
|
||||||
unsigned int blk;
|
unsigned int blk;
|
||||||
size_t hw_sz = sizeof(struct msc_block_desc) -
|
size_t hw_sz = sizeof(struct msc_block_desc) -
|
||||||
|
@ -466,7 +478,6 @@ static void msc_buffer_clear_hw_header(struct msc *msc)
|
||||||
memset(&bdesc->hw_tag, 0, hw_sz);
|
memset(&bdesc->hw_tag, 0, hw_sz);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mutex_unlock(&msc->buf_mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -474,12 +485,15 @@ static void msc_buffer_clear_hw_header(struct msc *msc)
|
||||||
* @msc: the MSC device to configure
|
* @msc: the MSC device to configure
|
||||||
*
|
*
|
||||||
* Program storage mode, wrapping, burst length and trace buffer address
|
* Program storage mode, wrapping, burst length and trace buffer address
|
||||||
* into a given MSC. If msc::enabled is set, enable the trace, too.
|
* into a given MSC. Then, enable tracing and set msc::enabled.
|
||||||
|
* The latter is serialized on msc::buf_mutex, so make sure to hold it.
|
||||||
*/
|
*/
|
||||||
static int msc_configure(struct msc *msc)
|
static int msc_configure(struct msc *msc)
|
||||||
{
|
{
|
||||||
u32 reg;
|
u32 reg;
|
||||||
|
|
||||||
|
lockdep_assert_held(&msc->buf_mutex);
|
||||||
|
|
||||||
if (msc->mode > MSC_MODE_MULTI)
|
if (msc->mode > MSC_MODE_MULTI)
|
||||||
return -ENOTSUPP;
|
return -ENOTSUPP;
|
||||||
|
|
||||||
|
@ -497,21 +511,19 @@ static int msc_configure(struct msc *msc)
|
||||||
reg = ioread32(msc->reg_base + REG_MSU_MSC0CTL);
|
reg = ioread32(msc->reg_base + REG_MSU_MSC0CTL);
|
||||||
reg &= ~(MSC_MODE | MSC_WRAPEN | MSC_EN | MSC_RD_HDR_OVRD);
|
reg &= ~(MSC_MODE | MSC_WRAPEN | MSC_EN | MSC_RD_HDR_OVRD);
|
||||||
|
|
||||||
|
reg |= MSC_EN;
|
||||||
reg |= msc->mode << __ffs(MSC_MODE);
|
reg |= msc->mode << __ffs(MSC_MODE);
|
||||||
reg |= msc->burst_len << __ffs(MSC_LEN);
|
reg |= msc->burst_len << __ffs(MSC_LEN);
|
||||||
/*if (msc->mode == MSC_MODE_MULTI)
|
|
||||||
reg |= MSC_RD_HDR_OVRD; */
|
|
||||||
if (msc->wrap)
|
if (msc->wrap)
|
||||||
reg |= MSC_WRAPEN;
|
reg |= MSC_WRAPEN;
|
||||||
if (msc->enabled)
|
|
||||||
reg |= MSC_EN;
|
|
||||||
|
|
||||||
iowrite32(reg, msc->reg_base + REG_MSU_MSC0CTL);
|
iowrite32(reg, msc->reg_base + REG_MSU_MSC0CTL);
|
||||||
|
|
||||||
if (msc->enabled) {
|
|
||||||
msc->thdev->output.multiblock = msc->mode == MSC_MODE_MULTI;
|
msc->thdev->output.multiblock = msc->mode == MSC_MODE_MULTI;
|
||||||
intel_th_trace_enable(msc->thdev);
|
intel_th_trace_enable(msc->thdev);
|
||||||
}
|
msc->enabled = 1;
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -521,15 +533,14 @@ static int msc_configure(struct msc *msc)
|
||||||
* @msc: MSC device to disable
|
* @msc: MSC device to disable
|
||||||
*
|
*
|
||||||
* If @msc is enabled, disable tracing on the switch and then disable MSC
|
* If @msc is enabled, disable tracing on the switch and then disable MSC
|
||||||
* storage.
|
* storage. Caller must hold msc::buf_mutex.
|
||||||
*/
|
*/
|
||||||
static void msc_disable(struct msc *msc)
|
static void msc_disable(struct msc *msc)
|
||||||
{
|
{
|
||||||
unsigned long count;
|
unsigned long count;
|
||||||
u32 reg;
|
u32 reg;
|
||||||
|
|
||||||
if (!msc->enabled)
|
lockdep_assert_held(&msc->buf_mutex);
|
||||||
return;
|
|
||||||
|
|
||||||
intel_th_trace_disable(msc->thdev);
|
intel_th_trace_disable(msc->thdev);
|
||||||
|
|
||||||
|
@ -569,34 +580,36 @@ static void msc_disable(struct msc *msc)
|
||||||
static int intel_th_msc_activate(struct intel_th_device *thdev)
|
static int intel_th_msc_activate(struct intel_th_device *thdev)
|
||||||
{
|
{
|
||||||
struct msc *msc = dev_get_drvdata(&thdev->dev);
|
struct msc *msc = dev_get_drvdata(&thdev->dev);
|
||||||
int ret = 0;
|
int ret = -EBUSY;
|
||||||
|
|
||||||
if (!atomic_inc_unless_negative(&msc->user_count))
|
if (!atomic_inc_unless_negative(&msc->user_count))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
mutex_lock(&msc->iter_mutex);
|
mutex_lock(&msc->buf_mutex);
|
||||||
if (!list_empty(&msc->iter_list))
|
|
||||||
ret = -EBUSY;
|
|
||||||
mutex_unlock(&msc->iter_mutex);
|
|
||||||
|
|
||||||
if (ret) {
|
/* if there are readers, refuse */
|
||||||
|
if (list_empty(&msc->iter_list))
|
||||||
|
ret = msc_configure(msc);
|
||||||
|
|
||||||
|
mutex_unlock(&msc->buf_mutex);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
atomic_dec(&msc->user_count);
|
atomic_dec(&msc->user_count);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
msc->enabled = 1;
|
|
||||||
|
|
||||||
return msc_configure(msc);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void intel_th_msc_deactivate(struct intel_th_device *thdev)
|
static void intel_th_msc_deactivate(struct intel_th_device *thdev)
|
||||||
{
|
{
|
||||||
struct msc *msc = dev_get_drvdata(&thdev->dev);
|
struct msc *msc = dev_get_drvdata(&thdev->dev);
|
||||||
|
|
||||||
|
mutex_lock(&msc->buf_mutex);
|
||||||
|
if (msc->enabled) {
|
||||||
msc_disable(msc);
|
msc_disable(msc);
|
||||||
|
|
||||||
atomic_dec(&msc->user_count);
|
atomic_dec(&msc->user_count);
|
||||||
}
|
}
|
||||||
|
mutex_unlock(&msc->buf_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* msc_buffer_contig_alloc() - allocate a contiguous buffer for SINGLE mode
|
* msc_buffer_contig_alloc() - allocate a contiguous buffer for SINGLE mode
|
||||||
|
@ -1035,8 +1048,8 @@ static int intel_th_msc_open(struct inode *inode, struct file *file)
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
iter = msc_iter_install(msc);
|
iter = msc_iter_install(msc);
|
||||||
if (!iter)
|
if (IS_ERR(iter))
|
||||||
return -ENOMEM;
|
return PTR_ERR(iter);
|
||||||
|
|
||||||
file->private_data = iter;
|
file->private_data = iter;
|
||||||
|
|
||||||
|
@ -1101,11 +1114,6 @@ static ssize_t intel_th_msc_read(struct file *file, char __user *buf,
|
||||||
if (!atomic_inc_unless_negative(&msc->user_count))
|
if (!atomic_inc_unless_negative(&msc->user_count))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (msc->enabled) {
|
|
||||||
ret = -EBUSY;
|
|
||||||
goto put_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (msc->mode == MSC_MODE_SINGLE && !msc->single_wrap)
|
if (msc->mode == MSC_MODE_SINGLE && !msc->single_wrap)
|
||||||
size = msc->single_sz;
|
size = msc->single_sz;
|
||||||
else
|
else
|
||||||
|
@ -1245,6 +1253,7 @@ static const struct file_operations intel_th_msc_fops = {
|
||||||
.read = intel_th_msc_read,
|
.read = intel_th_msc_read,
|
||||||
.mmap = intel_th_msc_mmap,
|
.mmap = intel_th_msc_mmap,
|
||||||
.llseek = no_llseek,
|
.llseek = no_llseek,
|
||||||
|
.owner = THIS_MODULE,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int intel_th_msc_init(struct msc *msc)
|
static int intel_th_msc_init(struct msc *msc)
|
||||||
|
@ -1254,8 +1263,6 @@ static int intel_th_msc_init(struct msc *msc)
|
||||||
msc->mode = MSC_MODE_MULTI;
|
msc->mode = MSC_MODE_MULTI;
|
||||||
mutex_init(&msc->buf_mutex);
|
mutex_init(&msc->buf_mutex);
|
||||||
INIT_LIST_HEAD(&msc->win_list);
|
INIT_LIST_HEAD(&msc->win_list);
|
||||||
|
|
||||||
mutex_init(&msc->iter_mutex);
|
|
||||||
INIT_LIST_HEAD(&msc->iter_list);
|
INIT_LIST_HEAD(&msc->iter_list);
|
||||||
|
|
||||||
msc->burst_len =
|
msc->burst_len =
|
||||||
|
@ -1393,6 +1400,11 @@ nr_pages_store(struct device *dev, struct device_attribute *attr,
|
||||||
do {
|
do {
|
||||||
end = memchr(p, ',', len);
|
end = memchr(p, ',', len);
|
||||||
s = kstrndup(p, end ? end - p : len, GFP_KERNEL);
|
s = kstrndup(p, end ? end - p : len, GFP_KERNEL);
|
||||||
|
if (!s) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto free_win;
|
||||||
|
}
|
||||||
|
|
||||||
ret = kstrtoul(s, 10, &val);
|
ret = kstrtoul(s, 10, &val);
|
||||||
kfree(s);
|
kfree(s);
|
||||||
|
|
||||||
|
@ -1473,10 +1485,6 @@ static int intel_th_msc_probe(struct intel_th_device *thdev)
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = sysfs_create_group(&dev->kobj, &msc_output_group);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
dev_set_drvdata(dev, msc);
|
dev_set_drvdata(dev, msc);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1484,7 +1492,18 @@ static int intel_th_msc_probe(struct intel_th_device *thdev)
|
||||||
|
|
||||||
static void intel_th_msc_remove(struct intel_th_device *thdev)
|
static void intel_th_msc_remove(struct intel_th_device *thdev)
|
||||||
{
|
{
|
||||||
sysfs_remove_group(&thdev->dev.kobj, &msc_output_group);
|
struct msc *msc = dev_get_drvdata(&thdev->dev);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
intel_th_msc_deactivate(thdev);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Buffers should not be used at this point except if the
|
||||||
|
* output character device is still open and the parent
|
||||||
|
* device gets detached from its bus, which is a FIXME.
|
||||||
|
*/
|
||||||
|
ret = msc_buffer_free_unless_used(msc);
|
||||||
|
WARN_ON_ONCE(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct intel_th_driver intel_th_msc_driver = {
|
static struct intel_th_driver intel_th_msc_driver = {
|
||||||
|
@ -1493,6 +1512,7 @@ static struct intel_th_driver intel_th_msc_driver = {
|
||||||
.activate = intel_th_msc_activate,
|
.activate = intel_th_msc_activate,
|
||||||
.deactivate = intel_th_msc_deactivate,
|
.deactivate = intel_th_msc_deactivate,
|
||||||
.fops = &intel_th_msc_fops,
|
.fops = &intel_th_msc_fops,
|
||||||
|
.attr_group = &msc_output_group,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "msc",
|
.name = "msc",
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
|
|
|
@ -75,6 +75,11 @@ static const struct pci_device_id intel_th_pci_id_table[] = {
|
||||||
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0a80),
|
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0a80),
|
||||||
.driver_data = (kernel_ulong_t)0,
|
.driver_data = (kernel_ulong_t)0,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
/* Broxton B-step */
|
||||||
|
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x1a8e),
|
||||||
|
.driver_data = (kernel_ulong_t)0,
|
||||||
|
},
|
||||||
{ 0 },
|
{ 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,6 @@ static int intel_th_pti_probe(struct intel_th_device *thdev)
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
struct pti_device *pti;
|
struct pti_device *pti;
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
int ret;
|
|
||||||
|
|
||||||
res = intel_th_device_get_resource(thdev, IORESOURCE_MEM, 0);
|
res = intel_th_device_get_resource(thdev, IORESOURCE_MEM, 0);
|
||||||
if (!res)
|
if (!res)
|
||||||
|
@ -219,10 +218,6 @@ static int intel_th_pti_probe(struct intel_th_device *thdev)
|
||||||
|
|
||||||
read_hw_config(pti);
|
read_hw_config(pti);
|
||||||
|
|
||||||
ret = sysfs_create_group(&dev->kobj, &pti_output_group);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
dev_set_drvdata(dev, pti);
|
dev_set_drvdata(dev, pti);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -237,6 +232,7 @@ static struct intel_th_driver intel_th_pti_driver = {
|
||||||
.remove = intel_th_pti_remove,
|
.remove = intel_th_pti_remove,
|
||||||
.activate = intel_th_pti_activate,
|
.activate = intel_th_pti_activate,
|
||||||
.deactivate = intel_th_pti_deactivate,
|
.deactivate = intel_th_pti_deactivate,
|
||||||
|
.attr_group = &pti_output_group,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "pti",
|
.name = "pti",
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
|
|
|
@ -546,8 +546,6 @@ static int stm_char_policy_set_ioctl(struct stm_file *stmf, void __user *arg)
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err_free;
|
goto err_free;
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
if (stm->data->link)
|
if (stm->data->link)
|
||||||
ret = stm->data->link(stm->data, stmf->output.master,
|
ret = stm->data->link(stm->data, stmf->output.master,
|
||||||
stmf->output.channel);
|
stmf->output.channel);
|
||||||
|
@ -668,6 +666,18 @@ int stm_register_device(struct device *parent, struct stm_data *stm_data,
|
||||||
stm->dev.parent = parent;
|
stm->dev.parent = parent;
|
||||||
stm->dev.release = stm_device_release;
|
stm->dev.release = stm_device_release;
|
||||||
|
|
||||||
|
mutex_init(&stm->link_mutex);
|
||||||
|
spin_lock_init(&stm->link_lock);
|
||||||
|
INIT_LIST_HEAD(&stm->link_list);
|
||||||
|
|
||||||
|
/* initialize the object before it is accessible via sysfs */
|
||||||
|
spin_lock_init(&stm->mc_lock);
|
||||||
|
mutex_init(&stm->policy_mutex);
|
||||||
|
stm->sw_nmasters = nmasters;
|
||||||
|
stm->owner = owner;
|
||||||
|
stm->data = stm_data;
|
||||||
|
stm_data->stm = stm;
|
||||||
|
|
||||||
err = kobject_set_name(&stm->dev.kobj, "%s", stm_data->name);
|
err = kobject_set_name(&stm->dev.kobj, "%s", stm_data->name);
|
||||||
if (err)
|
if (err)
|
||||||
goto err_device;
|
goto err_device;
|
||||||
|
@ -676,20 +686,11 @@ int stm_register_device(struct device *parent, struct stm_data *stm_data,
|
||||||
if (err)
|
if (err)
|
||||||
goto err_device;
|
goto err_device;
|
||||||
|
|
||||||
mutex_init(&stm->link_mutex);
|
|
||||||
spin_lock_init(&stm->link_lock);
|
|
||||||
INIT_LIST_HEAD(&stm->link_list);
|
|
||||||
|
|
||||||
spin_lock_init(&stm->mc_lock);
|
|
||||||
mutex_init(&stm->policy_mutex);
|
|
||||||
stm->sw_nmasters = nmasters;
|
|
||||||
stm->owner = owner;
|
|
||||||
stm->data = stm_data;
|
|
||||||
stm_data->stm = stm;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_device:
|
err_device:
|
||||||
|
unregister_chrdev(stm->major, stm_data->name);
|
||||||
|
|
||||||
/* matches device_initialize() above */
|
/* matches device_initialize() above */
|
||||||
put_device(&stm->dev);
|
put_device(&stm->dev);
|
||||||
err_free:
|
err_free:
|
||||||
|
|
|
@ -46,9 +46,7 @@ static struct stm_data dummy_stm[DUMMY_STM_MAX];
|
||||||
|
|
||||||
static int nr_dummies = 4;
|
static int nr_dummies = 4;
|
||||||
|
|
||||||
module_param(nr_dummies, int, 0600);
|
module_param(nr_dummies, int, 0400);
|
||||||
|
|
||||||
static unsigned int dummy_stm_nr;
|
|
||||||
|
|
||||||
static unsigned int fail_mode;
|
static unsigned int fail_mode;
|
||||||
|
|
||||||
|
@ -65,12 +63,12 @@ static int dummy_stm_link(struct stm_data *data, unsigned int master,
|
||||||
|
|
||||||
static int dummy_stm_init(void)
|
static int dummy_stm_init(void)
|
||||||
{
|
{
|
||||||
int i, ret = -ENOMEM, __nr_dummies = ACCESS_ONCE(nr_dummies);
|
int i, ret = -ENOMEM;
|
||||||
|
|
||||||
if (__nr_dummies < 0 || __nr_dummies > DUMMY_STM_MAX)
|
if (nr_dummies < 0 || nr_dummies > DUMMY_STM_MAX)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
for (i = 0; i < __nr_dummies; i++) {
|
for (i = 0; i < nr_dummies; i++) {
|
||||||
dummy_stm[i].name = kasprintf(GFP_KERNEL, "dummy_stm.%d", i);
|
dummy_stm[i].name = kasprintf(GFP_KERNEL, "dummy_stm.%d", i);
|
||||||
if (!dummy_stm[i].name)
|
if (!dummy_stm[i].name)
|
||||||
goto fail_unregister;
|
goto fail_unregister;
|
||||||
|
@ -86,8 +84,6 @@ static int dummy_stm_init(void)
|
||||||
goto fail_free;
|
goto fail_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
dummy_stm_nr = __nr_dummies;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail_unregister:
|
fail_unregister:
|
||||||
|
@ -105,7 +101,7 @@ static void dummy_stm_exit(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < dummy_stm_nr; i++) {
|
for (i = 0; i < nr_dummies; i++) {
|
||||||
stm_unregister_device(&dummy_stm[i]);
|
stm_unregister_device(&dummy_stm[i]);
|
||||||
kfree(dummy_stm[i].name);
|
kfree(dummy_stm[i].name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
static int nr_devs = 4;
|
static int nr_devs = 4;
|
||||||
static int interval_ms = 10;
|
static int interval_ms = 10;
|
||||||
|
|
||||||
module_param(nr_devs, int, 0600);
|
module_param(nr_devs, int, 0400);
|
||||||
module_param(interval_ms, int, 0600);
|
module_param(interval_ms, int, 0600);
|
||||||
|
|
||||||
static struct stm_heartbeat {
|
static struct stm_heartbeat {
|
||||||
|
@ -35,8 +35,6 @@ static struct stm_heartbeat {
|
||||||
unsigned int active;
|
unsigned int active;
|
||||||
} stm_heartbeat[STM_HEARTBEAT_MAX];
|
} stm_heartbeat[STM_HEARTBEAT_MAX];
|
||||||
|
|
||||||
static unsigned int nr_instances;
|
|
||||||
|
|
||||||
static const char str[] = "heartbeat stm source driver is here to serve you";
|
static const char str[] = "heartbeat stm source driver is here to serve you";
|
||||||
|
|
||||||
static enum hrtimer_restart stm_heartbeat_hrtimer_handler(struct hrtimer *hr)
|
static enum hrtimer_restart stm_heartbeat_hrtimer_handler(struct hrtimer *hr)
|
||||||
|
@ -74,12 +72,12 @@ static void stm_heartbeat_unlink(struct stm_source_data *data)
|
||||||
|
|
||||||
static int stm_heartbeat_init(void)
|
static int stm_heartbeat_init(void)
|
||||||
{
|
{
|
||||||
int i, ret = -ENOMEM, __nr_instances = ACCESS_ONCE(nr_devs);
|
int i, ret = -ENOMEM;
|
||||||
|
|
||||||
if (__nr_instances < 0 || __nr_instances > STM_HEARTBEAT_MAX)
|
if (nr_devs < 0 || nr_devs > STM_HEARTBEAT_MAX)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
for (i = 0; i < __nr_instances; i++) {
|
for (i = 0; i < nr_devs; i++) {
|
||||||
stm_heartbeat[i].data.name =
|
stm_heartbeat[i].data.name =
|
||||||
kasprintf(GFP_KERNEL, "heartbeat.%d", i);
|
kasprintf(GFP_KERNEL, "heartbeat.%d", i);
|
||||||
if (!stm_heartbeat[i].data.name)
|
if (!stm_heartbeat[i].data.name)
|
||||||
|
@ -98,8 +96,6 @@ static int stm_heartbeat_init(void)
|
||||||
goto fail_free;
|
goto fail_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
nr_instances = __nr_instances;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail_unregister:
|
fail_unregister:
|
||||||
|
@ -116,7 +112,7 @@ static void stm_heartbeat_exit(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < nr_instances; i++) {
|
for (i = 0; i < nr_devs; i++) {
|
||||||
stm_source_unregister_device(&stm_heartbeat[i].data);
|
stm_source_unregister_device(&stm_heartbeat[i].data);
|
||||||
kfree(stm_heartbeat[i].data.name);
|
kfree(stm_heartbeat[i].data.name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,8 +107,7 @@ stp_policy_node_masters_store(struct config_item *item, const char *page,
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
|
||||||
/* must be within [sw_start..sw_end], which is an inclusive range */
|
/* must be within [sw_start..sw_end], which is an inclusive range */
|
||||||
if (first > INT_MAX || last > INT_MAX || first > last ||
|
if (first > last || first < stm->data->sw_start ||
|
||||||
first < stm->data->sw_start ||
|
|
||||||
last > stm->data->sw_end) {
|
last > stm->data->sw_end) {
|
||||||
ret = -ERANGE;
|
ret = -ERANGE;
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
@ -342,7 +341,7 @@ stp_policies_make(struct config_group *group, const char *name)
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
*p++ = '\0';
|
*p = '\0';
|
||||||
|
|
||||||
stm = stm_find_device(devname);
|
stm = stm_find_device(devname);
|
||||||
kfree(devname);
|
kfree(devname);
|
||||||
|
|
Loading…
Reference in New Issue