mirror of https://gitee.com/openkylin/linux.git
staging: gasket: interrupt: remove static function forward declarations
Remove forward declarations of static functions, move code to avoid forward references, for kernel style. Signed-off-by: Todd Poynor <toddpoynor@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
ea174ccd2a
commit
d821f8eb92
|
@ -70,32 +70,259 @@ struct gasket_interrupt_data {
|
|||
int irq;
|
||||
};
|
||||
|
||||
/* Function definitions. */
|
||||
static ssize_t interrupt_sysfs_show(
|
||||
struct device *device, struct device_attribute *attr, char *buf);
|
||||
|
||||
static irqreturn_t gasket_msix_interrupt_handler(int irq, void *dev_id);
|
||||
|
||||
/* Structures to display interrupt counts in sysfs. */
|
||||
enum interrupt_sysfs_attribute_type {
|
||||
ATTR_INTERRUPT_COUNTS,
|
||||
};
|
||||
|
||||
/* Set up device registers for interrupt handling. */
|
||||
static void gasket_interrupt_setup(struct gasket_dev *gasket_dev)
|
||||
{
|
||||
int i;
|
||||
int pack_shift;
|
||||
ulong mask;
|
||||
ulong value;
|
||||
struct gasket_interrupt_data *interrupt_data =
|
||||
gasket_dev->interrupt_data;
|
||||
|
||||
if (!interrupt_data) {
|
||||
dev_dbg(gasket_dev->dev, "Interrupt data is not initialized\n");
|
||||
return;
|
||||
}
|
||||
|
||||
dev_dbg(gasket_dev->dev, "Running interrupt setup\n");
|
||||
|
||||
if (interrupt_data->type == PLATFORM_WIRE ||
|
||||
interrupt_data->type == PCI_MSI) {
|
||||
/* Nothing needs to be done for platform or PCI devices. */
|
||||
return;
|
||||
}
|
||||
|
||||
if (interrupt_data->type != PCI_MSIX) {
|
||||
dev_dbg(gasket_dev->dev,
|
||||
"Cannot handle unsupported interrupt type %d\n",
|
||||
interrupt_data->type);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Setup the MSIX table. */
|
||||
|
||||
for (i = 0; i < interrupt_data->num_interrupts; i++) {
|
||||
/*
|
||||
* If the interrupt is not packed, we can write the index into
|
||||
* the register directly. If not, we need to deal with a read-
|
||||
* modify-write and shift based on the packing index.
|
||||
*/
|
||||
dev_dbg(gasket_dev->dev,
|
||||
"Setting up interrupt index %d with index 0x%llx and "
|
||||
"packing %d\n",
|
||||
interrupt_data->interrupts[i].index,
|
||||
interrupt_data->interrupts[i].reg,
|
||||
interrupt_data->interrupts[i].packing);
|
||||
if (interrupt_data->interrupts[i].packing == UNPACKED) {
|
||||
value = interrupt_data->interrupts[i].index;
|
||||
} else {
|
||||
switch (interrupt_data->interrupts[i].packing) {
|
||||
case PACK_0:
|
||||
pack_shift = 0;
|
||||
break;
|
||||
case PACK_1:
|
||||
pack_shift = interrupt_data->pack_width;
|
||||
break;
|
||||
case PACK_2:
|
||||
pack_shift = 2 * interrupt_data->pack_width;
|
||||
break;
|
||||
case PACK_3:
|
||||
pack_shift = 3 * interrupt_data->pack_width;
|
||||
break;
|
||||
default:
|
||||
dev_dbg(gasket_dev->dev,
|
||||
"Found interrupt description with "
|
||||
"unknown enum %d\n",
|
||||
interrupt_data->interrupts[i].packing);
|
||||
return;
|
||||
}
|
||||
|
||||
mask = ~(0xFFFF << pack_shift);
|
||||
value = gasket_dev_read_64(
|
||||
gasket_dev,
|
||||
interrupt_data->interrupt_bar_index,
|
||||
interrupt_data->interrupts[i].reg) &
|
||||
mask;
|
||||
value |= interrupt_data->interrupts[i].index
|
||||
<< pack_shift;
|
||||
}
|
||||
gasket_dev_write_64(gasket_dev, value,
|
||||
interrupt_data->interrupt_bar_index,
|
||||
interrupt_data->interrupts[i].reg);
|
||||
}
|
||||
}
|
||||
|
||||
static irqreturn_t gasket_msix_interrupt_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct eventfd_ctx *ctx;
|
||||
struct gasket_interrupt_data *interrupt_data = dev_id;
|
||||
int interrupt = -1;
|
||||
int i;
|
||||
|
||||
/* If this linear lookup is a problem, we can maintain a map/hash. */
|
||||
for (i = 0; i < interrupt_data->num_interrupts; i++) {
|
||||
if (interrupt_data->msix_entries[i].vector == irq) {
|
||||
interrupt = interrupt_data->msix_entries[i].entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (interrupt == -1) {
|
||||
pr_err("Received unknown irq %d\n", irq);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
trace_gasket_interrupt_event(interrupt_data->name, interrupt);
|
||||
|
||||
ctx = interrupt_data->eventfd_ctxs[interrupt];
|
||||
if (ctx)
|
||||
eventfd_signal(ctx, 1);
|
||||
|
||||
++(interrupt_data->interrupt_counts[interrupt]);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int gasket_interrupt_msix_init(
|
||||
struct gasket_interrupt_data *interrupt_data)
|
||||
{
|
||||
int ret = 1;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < interrupt_data->num_interrupts; i++) {
|
||||
interrupt_data->msix_entries[i].entry = i;
|
||||
interrupt_data->msix_entries[i].vector = 0;
|
||||
interrupt_data->eventfd_ctxs[i] = NULL;
|
||||
}
|
||||
|
||||
/* Retry MSIX_RETRY_COUNT times if not enough IRQs are available. */
|
||||
for (i = 0; i < MSIX_RETRY_COUNT && ret > 0; i++)
|
||||
ret = pci_enable_msix_exact(interrupt_data->pci_dev,
|
||||
interrupt_data->msix_entries,
|
||||
interrupt_data->num_interrupts);
|
||||
|
||||
if (ret)
|
||||
return ret > 0 ? -EBUSY : ret;
|
||||
interrupt_data->msix_configured = 1;
|
||||
|
||||
for (i = 0; i < interrupt_data->num_interrupts; i++) {
|
||||
ret = request_irq(
|
||||
interrupt_data->msix_entries[i].vector,
|
||||
gasket_msix_interrupt_handler, 0, interrupt_data->name,
|
||||
interrupt_data);
|
||||
|
||||
if (ret) {
|
||||
dev_err(&interrupt_data->pci_dev->dev,
|
||||
"Cannot get IRQ for interrupt %d, vector %d; "
|
||||
"%d\n",
|
||||
i, interrupt_data->msix_entries[i].vector, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
interrupt_data->num_configured++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* On QCM DragonBoard, we exit gasket_interrupt_msix_init() and kernel interrupt
|
||||
* setup code with MSIX vectors masked. This is wrong because nothing else in
|
||||
* the driver will normally touch the MSIX vectors.
|
||||
*
|
||||
* As a temporary hack, force unmasking there.
|
||||
*
|
||||
* TODO: Figure out why QCM kernel doesn't unmask the MSIX vectors, after
|
||||
* gasket_interrupt_msix_init(), and remove this code.
|
||||
*/
|
||||
static void force_msix_interrupt_unmasking(struct gasket_dev *gasket_dev)
|
||||
{
|
||||
int i;
|
||||
#define MSIX_VECTOR_SIZE 16
|
||||
#define MSIX_MASK_BIT_OFFSET 12
|
||||
#define APEX_BAR2_REG_KERNEL_HIB_MSIX_TABLE 0x46800
|
||||
for (i = 0; i < gasket_dev->interrupt_data->num_configured; i++) {
|
||||
/* Check if the MSIX vector is unmasked */
|
||||
ulong location = APEX_BAR2_REG_KERNEL_HIB_MSIX_TABLE +
|
||||
MSIX_MASK_BIT_OFFSET + i * MSIX_VECTOR_SIZE;
|
||||
u32 mask =
|
||||
gasket_dev_read_32(
|
||||
gasket_dev,
|
||||
gasket_dev->interrupt_data->interrupt_bar_index,
|
||||
location);
|
||||
if (!(mask & 1))
|
||||
continue;
|
||||
/* Unmask the msix vector (clear 32 bits) */
|
||||
gasket_dev_write_32(
|
||||
gasket_dev, 0,
|
||||
gasket_dev->interrupt_data->interrupt_bar_index,
|
||||
location);
|
||||
}
|
||||
#undef MSIX_VECTOR_SIZE
|
||||
#undef MSIX_MASK_BIT_OFFSET
|
||||
#undef APEX_BAR2_REG_KERNEL_HIB_MSIX_TABLE
|
||||
}
|
||||
|
||||
static ssize_t interrupt_sysfs_show(
|
||||
struct device *device, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int i, ret;
|
||||
ssize_t written = 0, total_written = 0;
|
||||
struct gasket_interrupt_data *interrupt_data;
|
||||
struct gasket_dev *gasket_dev;
|
||||
struct gasket_sysfs_attribute *gasket_attr;
|
||||
enum interrupt_sysfs_attribute_type sysfs_type;
|
||||
|
||||
gasket_dev = gasket_sysfs_get_device_data(device);
|
||||
if (!gasket_dev) {
|
||||
dev_dbg(device, "No sysfs mapping found for device\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
gasket_attr = gasket_sysfs_get_attr(device, attr);
|
||||
if (!gasket_attr) {
|
||||
dev_dbg(device, "No sysfs attr data found for device\n");
|
||||
gasket_sysfs_put_device_data(device, gasket_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sysfs_type = (enum interrupt_sysfs_attribute_type)
|
||||
gasket_attr->data.attr_type;
|
||||
interrupt_data = gasket_dev->interrupt_data;
|
||||
switch (sysfs_type) {
|
||||
case ATTR_INTERRUPT_COUNTS:
|
||||
for (i = 0; i < interrupt_data->num_interrupts; ++i) {
|
||||
written =
|
||||
scnprintf(buf, PAGE_SIZE - total_written,
|
||||
"0x%02x: %ld\n", i,
|
||||
interrupt_data->interrupt_counts[i]);
|
||||
total_written += written;
|
||||
buf += written;
|
||||
}
|
||||
ret = total_written;
|
||||
break;
|
||||
default:
|
||||
dev_dbg(gasket_dev->dev, "Unknown attribute: %s\n",
|
||||
attr->attr.name);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
gasket_sysfs_put_attr(device, gasket_attr);
|
||||
gasket_sysfs_put_device_data(device, gasket_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct gasket_sysfs_attribute interrupt_sysfs_attrs[] = {
|
||||
GASKET_SYSFS_RO(
|
||||
interrupt_counts, interrupt_sysfs_show, ATTR_INTERRUPT_COUNTS),
|
||||
GASKET_END_OF_ATTR_ARRAY,
|
||||
};
|
||||
|
||||
static void gasket_interrupt_setup(struct gasket_dev *gasket_dev);
|
||||
|
||||
/* MSIX init and cleanup. */
|
||||
static int gasket_interrupt_msix_init(
|
||||
struct gasket_interrupt_data *interrupt_data);
|
||||
static void gasket_interrupt_msix_cleanup(
|
||||
struct gasket_interrupt_data *interrupt_data);
|
||||
static void force_msix_interrupt_unmasking(struct gasket_dev *gasket_dev);
|
||||
|
||||
int gasket_interrupt_init(
|
||||
struct gasket_dev *gasket_dev, const char *name, int type,
|
||||
const struct gasket_interrupt_desc *interrupts,
|
||||
|
@ -181,48 +408,6 @@ int gasket_interrupt_init(
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int gasket_interrupt_msix_init(
|
||||
struct gasket_interrupt_data *interrupt_data)
|
||||
{
|
||||
int ret = 1;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < interrupt_data->num_interrupts; i++) {
|
||||
interrupt_data->msix_entries[i].entry = i;
|
||||
interrupt_data->msix_entries[i].vector = 0;
|
||||
interrupt_data->eventfd_ctxs[i] = NULL;
|
||||
}
|
||||
|
||||
/* Retry MSIX_RETRY_COUNT times if not enough IRQs are available. */
|
||||
for (i = 0; i < MSIX_RETRY_COUNT && ret > 0; i++)
|
||||
ret = pci_enable_msix_exact(interrupt_data->pci_dev,
|
||||
interrupt_data->msix_entries,
|
||||
interrupt_data->num_interrupts);
|
||||
|
||||
if (ret)
|
||||
return ret > 0 ? -EBUSY : ret;
|
||||
interrupt_data->msix_configured = 1;
|
||||
|
||||
for (i = 0; i < interrupt_data->num_interrupts; i++) {
|
||||
ret = request_irq(
|
||||
interrupt_data->msix_entries[i].vector,
|
||||
gasket_msix_interrupt_handler, 0, interrupt_data->name,
|
||||
interrupt_data);
|
||||
|
||||
if (ret) {
|
||||
dev_err(&interrupt_data->pci_dev->dev,
|
||||
"Cannot get IRQ for interrupt %d, vector %d; "
|
||||
"%d\n",
|
||||
i, interrupt_data->msix_entries[i].vector, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
interrupt_data->num_configured++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gasket_interrupt_msix_cleanup(
|
||||
struct gasket_interrupt_data *interrupt_data)
|
||||
{
|
||||
|
@ -238,44 +423,6 @@ static void gasket_interrupt_msix_cleanup(
|
|||
interrupt_data->msix_configured = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* On QCM DragonBoard, we exit gasket_interrupt_msix_init() and kernel interrupt
|
||||
* setup code with MSIX vectors masked. This is wrong because nothing else in
|
||||
* the driver will normally touch the MSIX vectors.
|
||||
*
|
||||
* As a temporary hack, force unmasking there.
|
||||
*
|
||||
* TODO: Figure out why QCM kernel doesn't unmask the MSIX vectors, after
|
||||
* gasket_interrupt_msix_init(), and remove this code.
|
||||
*/
|
||||
static void force_msix_interrupt_unmasking(struct gasket_dev *gasket_dev)
|
||||
{
|
||||
int i;
|
||||
#define MSIX_VECTOR_SIZE 16
|
||||
#define MSIX_MASK_BIT_OFFSET 12
|
||||
#define APEX_BAR2_REG_KERNEL_HIB_MSIX_TABLE 0x46800
|
||||
for (i = 0; i < gasket_dev->interrupt_data->num_configured; i++) {
|
||||
/* Check if the MSIX vector is unmasked */
|
||||
ulong location = APEX_BAR2_REG_KERNEL_HIB_MSIX_TABLE +
|
||||
MSIX_MASK_BIT_OFFSET + i * MSIX_VECTOR_SIZE;
|
||||
u32 mask =
|
||||
gasket_dev_read_32(
|
||||
gasket_dev,
|
||||
gasket_dev->interrupt_data->interrupt_bar_index,
|
||||
location);
|
||||
if (!(mask & 1))
|
||||
continue;
|
||||
/* Unmask the msix vector (clear 32 bits) */
|
||||
gasket_dev_write_32(
|
||||
gasket_dev, 0,
|
||||
gasket_dev->interrupt_data->interrupt_bar_index,
|
||||
location);
|
||||
}
|
||||
#undef MSIX_VECTOR_SIZE
|
||||
#undef MSIX_MASK_BIT_OFFSET
|
||||
#undef APEX_BAR2_REG_KERNEL_HIB_MSIX_TABLE
|
||||
}
|
||||
|
||||
int gasket_interrupt_reinit(struct gasket_dev *gasket_dev)
|
||||
{
|
||||
int ret;
|
||||
|
@ -327,89 +474,6 @@ int gasket_interrupt_reset_counts(struct gasket_dev *gasket_dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Set up device registers for interrupt handling. */
|
||||
static void gasket_interrupt_setup(struct gasket_dev *gasket_dev)
|
||||
{
|
||||
int i;
|
||||
int pack_shift;
|
||||
ulong mask;
|
||||
ulong value;
|
||||
struct gasket_interrupt_data *interrupt_data =
|
||||
gasket_dev->interrupt_data;
|
||||
|
||||
if (!interrupt_data) {
|
||||
dev_dbg(gasket_dev->dev, "Interrupt data is not initialized\n");
|
||||
return;
|
||||
}
|
||||
|
||||
dev_dbg(gasket_dev->dev, "Running interrupt setup\n");
|
||||
|
||||
if (interrupt_data->type == PLATFORM_WIRE ||
|
||||
interrupt_data->type == PCI_MSI) {
|
||||
/* Nothing needs to be done for platform or PCI devices. */
|
||||
return;
|
||||
}
|
||||
|
||||
if (interrupt_data->type != PCI_MSIX) {
|
||||
dev_dbg(gasket_dev->dev,
|
||||
"Cannot handle unsupported interrupt type %d\n",
|
||||
interrupt_data->type);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Setup the MSIX table. */
|
||||
|
||||
for (i = 0; i < interrupt_data->num_interrupts; i++) {
|
||||
/*
|
||||
* If the interrupt is not packed, we can write the index into
|
||||
* the register directly. If not, we need to deal with a read-
|
||||
* modify-write and shift based on the packing index.
|
||||
*/
|
||||
dev_dbg(gasket_dev->dev,
|
||||
"Setting up interrupt index %d with index 0x%llx and "
|
||||
"packing %d\n",
|
||||
interrupt_data->interrupts[i].index,
|
||||
interrupt_data->interrupts[i].reg,
|
||||
interrupt_data->interrupts[i].packing);
|
||||
if (interrupt_data->interrupts[i].packing == UNPACKED) {
|
||||
value = interrupt_data->interrupts[i].index;
|
||||
} else {
|
||||
switch (interrupt_data->interrupts[i].packing) {
|
||||
case PACK_0:
|
||||
pack_shift = 0;
|
||||
break;
|
||||
case PACK_1:
|
||||
pack_shift = interrupt_data->pack_width;
|
||||
break;
|
||||
case PACK_2:
|
||||
pack_shift = 2 * interrupt_data->pack_width;
|
||||
break;
|
||||
case PACK_3:
|
||||
pack_shift = 3 * interrupt_data->pack_width;
|
||||
break;
|
||||
default:
|
||||
dev_dbg(gasket_dev->dev,
|
||||
"Found interrupt description with "
|
||||
"unknown enum %d\n",
|
||||
interrupt_data->interrupts[i].packing);
|
||||
return;
|
||||
}
|
||||
|
||||
mask = ~(0xFFFF << pack_shift);
|
||||
value = gasket_dev_read_64(
|
||||
gasket_dev,
|
||||
interrupt_data->interrupt_bar_index,
|
||||
interrupt_data->interrupts[i].reg) &
|
||||
mask;
|
||||
value |= interrupt_data->interrupts[i].index
|
||||
<< pack_shift;
|
||||
}
|
||||
gasket_dev_write_64(gasket_dev, value,
|
||||
interrupt_data->interrupt_bar_index,
|
||||
interrupt_data->interrupts[i].reg);
|
||||
}
|
||||
}
|
||||
|
||||
/* See gasket_interrupt.h for description. */
|
||||
void gasket_interrupt_cleanup(struct gasket_dev *gasket_dev)
|
||||
{
|
||||
|
@ -489,82 +553,3 @@ int gasket_interrupt_clear_eventfd(
|
|||
interrupt_data->eventfd_ctxs[interrupt] = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t interrupt_sysfs_show(
|
||||
struct device *device, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int i, ret;
|
||||
ssize_t written = 0, total_written = 0;
|
||||
struct gasket_interrupt_data *interrupt_data;
|
||||
struct gasket_dev *gasket_dev;
|
||||
struct gasket_sysfs_attribute *gasket_attr;
|
||||
enum interrupt_sysfs_attribute_type sysfs_type;
|
||||
|
||||
gasket_dev = gasket_sysfs_get_device_data(device);
|
||||
if (!gasket_dev) {
|
||||
dev_dbg(device, "No sysfs mapping found for device\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
gasket_attr = gasket_sysfs_get_attr(device, attr);
|
||||
if (!gasket_attr) {
|
||||
dev_dbg(device, "No sysfs attr data found for device\n");
|
||||
gasket_sysfs_put_device_data(device, gasket_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sysfs_type = (enum interrupt_sysfs_attribute_type)
|
||||
gasket_attr->data.attr_type;
|
||||
interrupt_data = gasket_dev->interrupt_data;
|
||||
switch (sysfs_type) {
|
||||
case ATTR_INTERRUPT_COUNTS:
|
||||
for (i = 0; i < interrupt_data->num_interrupts; ++i) {
|
||||
written =
|
||||
scnprintf(buf, PAGE_SIZE - total_written,
|
||||
"0x%02x: %ld\n", i,
|
||||
interrupt_data->interrupt_counts[i]);
|
||||
total_written += written;
|
||||
buf += written;
|
||||
}
|
||||
ret = total_written;
|
||||
break;
|
||||
default:
|
||||
dev_dbg(gasket_dev->dev, "Unknown attribute: %s\n",
|
||||
attr->attr.name);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
gasket_sysfs_put_attr(device, gasket_attr);
|
||||
gasket_sysfs_put_device_data(device, gasket_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static irqreturn_t gasket_msix_interrupt_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct eventfd_ctx *ctx;
|
||||
struct gasket_interrupt_data *interrupt_data = dev_id;
|
||||
int interrupt = -1;
|
||||
int i;
|
||||
|
||||
/* If this linear lookup is a problem, we can maintain a map/hash. */
|
||||
for (i = 0; i < interrupt_data->num_interrupts; i++) {
|
||||
if (interrupt_data->msix_entries[i].vector == irq) {
|
||||
interrupt = interrupt_data->msix_entries[i].entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (interrupt == -1) {
|
||||
pr_err("Received unknown irq %d\n", irq);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
trace_gasket_interrupt_event(interrupt_data->name, interrupt);
|
||||
|
||||
ctx = interrupt_data->eventfd_ctxs[interrupt];
|
||||
if (ctx)
|
||||
eventfd_signal(ctx, 1);
|
||||
|
||||
++(interrupt_data->interrupt_counts[interrupt]);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue