2008-02-06 22:47:12

by Adrian McMenamin

[permalink] [raw]
Subject: [PATCH 1/2] - SH/Dreamcast - fix maple bus bugs

This patch is fundamentally about fixing up the whitespace problems introduced by my previous patch (that brought the code into mainline). A second patch will follow that will fix memory leaks. The two need to be applied sequentially.

Signed-off by: Adrian McMenamin <[email protected]>

---

diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c
index 37c0bf7..3f341dc 100644
--- a/drivers/sh/maple/maple.c
+++ b/drivers/sh/maple/maple.c
@@ -56,8 +56,8 @@ static int started, scanning, liststatus;
static struct kmem_cache *maple_queue_cache;

struct maple_device_specify {
- int port;
- int unit;
+ int port;
+ int unit;
};

/**
@@ -67,22 +67,23 @@ struct maple_device_specify {
*/
int maple_driver_register(struct device_driver *drv)
{
- if (!drv)
- return -EINVAL;
- drv->bus = &maple_bus_type;
- return driver_register(drv);
+ if (!drv)
+ return -EINVAL;
+ drv->bus = &maple_bus_type;
+ return driver_register(drv);
}
+
EXPORT_SYMBOL_GPL(maple_driver_register);

/* set hardware registers to enable next round of dma */
static void maplebus_dma_reset(void)
{
- ctrl_outl(MAPLE_MAGIC, MAPLE_RESET);
- /* set trig type to 0 for software trigger, 1 for hardware (VBLANK) */
- ctrl_outl(1, MAPLE_TRIGTYPE);
- ctrl_outl(MAPLE_2MBPS | MAPLE_TIMEOUT(50000), MAPLE_SPEED);
- ctrl_outl(PHYSADDR(maple_sendbuf), MAPLE_DMAADDR);
- ctrl_outl(1, MAPLE_ENABLE);
+ ctrl_outl(MAPLE_MAGIC, MAPLE_RESET);
+ /* set trig type to 0 for software trigger, 1 for hardware (VBLANK) */
+ ctrl_outl(1, MAPLE_TRIGTYPE);
+ ctrl_outl(MAPLE_2MBPS | MAPLE_TIMEOUT(50000), MAPLE_SPEED);
+ ctrl_outl(PHYSADDR(maple_sendbuf), MAPLE_DMAADDR);
+ ctrl_outl(1, MAPLE_ENABLE);
}

/**
@@ -93,27 +94,28 @@ static void maplebus_dma_reset(void)
* @function: the function code for the device
*/
void maple_getcond_callback(struct maple_device *dev,
- void (*callback) (struct mapleq * mq),
- unsigned long interval, unsigned long function)
+ void (*callback) (struct mapleq * mq),
+ unsigned long interval, unsigned long function)
{
- dev->callback = callback;
- dev->interval = interval;
- dev->function = cpu_to_be32(function);
- dev->when = jiffies;
+ dev->callback = callback;
+ dev->interval = interval;
+ dev->function = cpu_to_be32(function);
+ dev->when = jiffies;
}
+
EXPORT_SYMBOL_GPL(maple_getcond_callback);

static int maple_dma_done(void)
{
- return (ctrl_inl(MAPLE_STATE) & 1) == 0;
+ return (ctrl_inl(MAPLE_STATE) & 1) == 0;
}

static void maple_release_device(struct device *dev)
{
- if (dev->type) {
- kfree(dev->type->name);
- kfree(dev->type);
- }
+ if (dev->type) {
+ kfree(dev->type->name);
+ kfree(dev->type);
+ }
}

/**
@@ -122,60 +124,61 @@ static void maple_release_device(struct device *dev)
*/
void maple_add_packet(struct mapleq *mq)
{
- mutex_lock(&maple_list_lock);
- list_add(&mq->list, &maple_waitq);
- mutex_unlock(&maple_list_lock);
+ mutex_lock(&maple_list_lock);
+ list_add(&mq->list, &maple_waitq);
+ mutex_unlock(&maple_list_lock);
}
+
EXPORT_SYMBOL_GPL(maple_add_packet);

static struct mapleq *maple_allocq(struct maple_device *dev)
{
- struct mapleq *mq;
+ struct mapleq *mq;

- mq = kmalloc(sizeof(*mq), GFP_KERNEL);
- if (!mq)
- return NULL;
+ mq = kmalloc(sizeof(*mq), GFP_KERNEL);
+ if (!mq)
+ return NULL;

- mq->dev = dev;
- mq->recvbufdcsp = kmem_cache_zalloc(maple_queue_cache, GFP_KERNEL);
- mq->recvbuf = (void *) P2SEGADDR(mq->recvbufdcsp);
- if (!mq->recvbuf) {
- kfree(mq);
- return NULL;
- }
+ mq->dev = dev;
+ mq->recvbufdcsp = kmem_cache_zalloc(maple_queue_cache, GFP_KERNEL);
+ mq->recvbuf = (void *) P2SEGADDR(mq->recvbufdcsp);
+ if (!mq->recvbuf) {
+ kfree(mq);
+ return NULL;
+ }

- return mq;
+ return mq;
}

static struct maple_device *maple_alloc_dev(int port, int unit)
{
- struct maple_device *dev;
+ struct maple_device *dev;

- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (!dev)
- return NULL;
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return NULL;

- dev->port = port;
- dev->unit = unit;
- dev->mq = maple_allocq(dev);
+ dev->port = port;
+ dev->unit = unit;
+ dev->mq = maple_allocq(dev);

- if (!dev->mq) {
- kfree(dev);
- return NULL;
- }
+ if (!dev->mq) {
+ kfree(dev);
+ return NULL;
+ }

- return dev;
+ return dev;
}

static void maple_free_dev(struct maple_device *mdev)
{
- if (!mdev)
- return;
- if (mdev->mq) {
- kmem_cache_free(maple_queue_cache, mdev->mq->recvbufdcsp);
- kfree(mdev->mq);
- }
- kfree(mdev);
+ if (!mdev)
+ return;
+ if (mdev->mq) {
+ kmem_cache_free(maple_queue_cache, mdev->mq->recvbufdcsp);
+ kfree(mdev->mq);
+ }
+ kfree(mdev);
}

/* process the command queue into a maple command block
@@ -183,153 +186,153 @@ static void maple_free_dev(struct maple_device *mdev)
*/
static void maple_build_block(struct mapleq *mq)
{
- int port, unit, from, to, len;
- unsigned long *lsendbuf = mq->sendbuf;
+ int port, unit, from, to, len;
+ unsigned long *lsendbuf = mq->sendbuf;

- port = mq->dev->port & 3;
- unit = mq->dev->unit;
- len = mq->length;
- from = port << 6;
- to = (port << 6) | (unit > 0 ? (1 << (unit - 1)) & 0x1f : 0x20);
+ port = mq->dev->port & 3;
+ unit = mq->dev->unit;
+ len = mq->length;
+ from = port << 6;
+ to = (port << 6) | (unit > 0 ? (1 << (unit - 1)) & 0x1f : 0x20);

- *maple_lastptr &= 0x7fffffff;
- maple_lastptr = maple_sendptr;
+ *maple_lastptr &= 0x7fffffff;
+ maple_lastptr = maple_sendptr;

- *maple_sendptr++ = (port << 16) | len | 0x80000000;
- *maple_sendptr++ = PHYSADDR(mq->recvbuf);
- *maple_sendptr++ =
- mq->command | (to << 8) | (from << 16) | (len << 24);
+ *maple_sendptr++ = (port << 16) | len | 0x80000000;
+ *maple_sendptr++ = PHYSADDR(mq->recvbuf);
+ *maple_sendptr++ =
+ mq->command | (to << 8) | (from << 16) | (len << 24);

- while (len-- > 0)
- *maple_sendptr++ = *lsendbuf++;
+ while (len-- > 0)
+ *maple_sendptr++ = *lsendbuf++;
}

/* build up command queue */
static void maple_send(void)
{
- int i;
- int maple_packets;
- struct mapleq *mq, *nmq;
-
- if (!list_empty(&maple_sentq))
- return;
- if (list_empty(&maple_waitq) || !maple_dma_done())
- return;
- maple_packets = 0;
- maple_sendptr = maple_lastptr = maple_sendbuf;
- list_for_each_entry_safe(mq, nmq, &maple_waitq, list) {
- maple_build_block(mq);
- list_move(&mq->list, &maple_sentq);
- if (maple_packets++ > MAPLE_MAXPACKETS)
- break;
- }
- if (maple_packets > 0) {
- for (i = 0; i < (1 << MAPLE_DMA_PAGES); i++)
- dma_cache_sync(0, maple_sendbuf + i * PAGE_SIZE,
- PAGE_SIZE, DMA_BIDIRECTIONAL);
- }
+ int i;
+ int maple_packets;
+ struct mapleq *mq, *nmq;
+
+ if (!list_empty(&maple_sentq))
+ return;
+ if (list_empty(&maple_waitq) || !maple_dma_done())
+ return;
+ maple_packets = 0;
+ maple_sendptr = maple_lastptr = maple_sendbuf;
+ list_for_each_entry_safe(mq, nmq, &maple_waitq, list) {
+ maple_build_block(mq);
+ list_move(&mq->list, &maple_sentq);
+ if (maple_packets++ > MAPLE_MAXPACKETS)
+ break;
+ }
+ if (maple_packets > 0) {
+ for (i = 0; i < (1 << MAPLE_DMA_PAGES); i++)
+ dma_cache_sync(0, maple_sendbuf + i * PAGE_SIZE,
+ PAGE_SIZE, DMA_BIDIRECTIONAL);
+ }
}

static int attach_matching_maple_driver(struct device_driver *driver,
- void *devptr)
+ void *devptr)
{
- struct maple_driver *maple_drv;
- struct maple_device *mdev;
-
- mdev = devptr;
- maple_drv = to_maple_driver(driver);
- if (mdev->devinfo.function & be32_to_cpu(maple_drv->function)) {
- if (maple_drv->connect(mdev) == 0) {
- mdev->driver = maple_drv;
- return 1;
- }
- }
- return 0;
+ struct maple_driver *maple_drv;
+ struct maple_device *mdev;
+
+ mdev = devptr;
+ maple_drv = to_maple_driver(driver);
+ if (mdev->devinfo.function & be32_to_cpu(maple_drv->function)) {
+ if (maple_drv->connect(mdev) == 0) {
+ mdev->driver = maple_drv;
+ return 1;
+ }
+ }
+ return 0;
}

static void maple_detach_driver(struct maple_device *mdev)
{
- if (!mdev)
- return;
- if (mdev->driver) {
- if (mdev->driver->disconnect)
- mdev->driver->disconnect(mdev);
- }
- mdev->driver = NULL;
- if (mdev->registered) {
- maple_release_device(&mdev->dev);
- device_unregister(&mdev->dev);
- }
- mdev->registered = 0;
- maple_free_dev(mdev);
+ if (!mdev)
+ return;
+ if (mdev->driver) {
+ if (mdev->driver->disconnect)
+ mdev->driver->disconnect(mdev);
+ }
+ mdev->driver = NULL;
+ if (mdev->registered) {
+ maple_release_device(&mdev->dev);
+ device_unregister(&mdev->dev);
+ }
+ mdev->registered = 0;
+ maple_free_dev(mdev);
}

/* process initial MAPLE_COMMAND_DEVINFO for each device or port */
static void maple_attach_driver(struct maple_device *dev)
{
- char *p;
-
- char *recvbuf;
- unsigned long function;
- int matched, retval;
-
- recvbuf = dev->mq->recvbuf;
- memcpy(&dev->devinfo, recvbuf + 4, sizeof(dev->devinfo));
- memcpy(dev->product_name, dev->devinfo.product_name, 30);
- memcpy(dev->product_licence, dev->devinfo.product_licence, 60);
- dev->product_name[30] = '\0';
- dev->product_licence[60] = '\0';
-
- for (p = dev->product_name + 29; dev->product_name <= p; p--)
- if (*p == ' ')
- *p = '\0';
- else
- break;
-
- for (p = dev->product_licence + 59; dev->product_licence <= p; p--)
- if (*p == ' ')
- *p = '\0';
- else
- break;
-
- function = be32_to_cpu(dev->devinfo.function);
-
- if (function > 0x200) {
- /* Do this silently - as not a real device */
- function = 0;
- dev->driver = &maple_dummy_driver;
- sprintf(dev->dev.bus_id, "%d:0.port", dev->port);
- } else {
- printk(KERN_INFO
- "Maple bus at (%d, %d): Connected function 0x%lX\n",
- dev->port, dev->unit, function);
-
- matched =
- bus_for_each_drv(&maple_bus_type, NULL, dev,
- attach_matching_maple_driver);
-
- if (matched == 0) {
- /* Driver does not exist yet */
- printk(KERN_INFO
- "No maple driver found for this device\n");
- dev->driver = &maple_dummy_driver;
- }
-
- sprintf(dev->dev.bus_id, "%d:0%d.%lX", dev->port,
- dev->unit, function);
- }
- dev->function = function;
- dev->dev.bus = &maple_bus_type;
- dev->dev.parent = &maple_bus;
- dev->dev.release = &maple_release_device;
- retval = device_register(&dev->dev);
- if (retval) {
- printk(KERN_INFO
- "Maple bus: Attempt to register device (%x, %x) failed.\n",
- dev->port, dev->unit);
- maple_free_dev(dev);
- }
- dev->registered = 1;
+ char *p;
+
+ char *recvbuf;
+ unsigned long function;
+ int matched, retval;
+
+ recvbuf = dev->mq->recvbuf;
+ memcpy(&dev->devinfo, recvbuf + 4, sizeof(dev->devinfo));
+ memcpy(dev->product_name, dev->devinfo.product_name, 30);
+ memcpy(dev->product_licence, dev->devinfo.product_licence, 60);
+ dev->product_name[30] = '\0';
+ dev->product_licence[60] = '\0';
+
+ for (p = dev->product_name + 29; dev->product_name <= p; p--)
+ if (*p == ' ')
+ *p = '\0';
+ else
+ break;
+
+ for (p = dev->product_licence + 59; dev->product_licence <= p; p--)
+ if (*p == ' ')
+ *p = '\0';
+ else
+ break;
+
+ function = be32_to_cpu(dev->devinfo.function);
+
+ if (function > 0x200) {
+ /* Do this silently - as not a real device */
+ function = 0;
+ dev->driver = &maple_dummy_driver;
+ sprintf(dev->dev.bus_id, "%d:0.port", dev->port);
+ } else {
+ printk(KERN_INFO
+ "Maple bus at (%d, %d): Connected function 0x%lX\n",
+ dev->port, dev->unit, function);
+
+ matched =
+ bus_for_each_drv(&maple_bus_type, NULL, dev,
+ attach_matching_maple_driver);
+
+ if (matched == 0) {
+ /* Driver does not exist yet */
+ printk(KERN_INFO
+ "No maple driver found for this device\n");
+ dev->driver = &maple_dummy_driver;
+ }
+
+ sprintf(dev->dev.bus_id, "%d:0%d.%lX", dev->port,
+ dev->unit, function);
+ }
+ dev->function = function;
+ dev->dev.bus = &maple_bus_type;
+ dev->dev.parent = &maple_bus;
+ dev->dev.release = &maple_release_device;
+ retval = device_register(&dev->dev);
+ if (retval) {
+ printk(KERN_INFO
+ "Maple bus: Attempt to register device (%x, %x) failed.\n",
+ dev->port, dev->unit);
+ maple_free_dev(dev);
+ }
+ dev->registered = 1;
}

/*
@@ -339,270 +342,271 @@ static void maple_attach_driver(struct maple_device *dev)
*/
static int detach_maple_device(struct device *device, void *portptr)
{
- struct maple_device_specify *ds;
- struct maple_device *mdev;
-
- ds = portptr;
- mdev = to_maple_dev(device);
- if (mdev->port == ds->port && mdev->unit == ds->unit)
- return 1;
- return 0;
+ struct maple_device_specify *ds;
+ struct maple_device *mdev;
+
+ ds = portptr;
+ mdev = to_maple_dev(device);
+ if (mdev->port == ds->port && mdev->unit == ds->unit)
+ return 1;
+ return 0;
}

static int setup_maple_commands(struct device *device, void *ignored)
{
- struct maple_device *maple_dev = to_maple_dev(device);
-
- if ((maple_dev->interval > 0)
- && time_after(jiffies, maple_dev->when)) {
- maple_dev->when = jiffies + maple_dev->interval;
- maple_dev->mq->command = MAPLE_COMMAND_GETCOND;
- maple_dev->mq->sendbuf = &maple_dev->function;
- maple_dev->mq->length = 1;
- maple_add_packet(maple_dev->mq);
- liststatus++;
- } else {
- if (time_after(jiffies, maple_pnp_time)) {
- maple_dev->mq->command = MAPLE_COMMAND_DEVINFO;
- maple_dev->mq->length = 0;
- maple_add_packet(maple_dev->mq);
- liststatus++;
- }
- }
-
- return 0;
+ struct maple_device *maple_dev = to_maple_dev(device);
+
+ if ((maple_dev->interval > 0)
+ && time_after(jiffies, maple_dev->when)) {
+ maple_dev->when = jiffies + maple_dev->interval;
+ maple_dev->mq->command = MAPLE_COMMAND_GETCOND;
+ maple_dev->mq->sendbuf = &maple_dev->function;
+ maple_dev->mq->length = 1;
+ maple_add_packet(maple_dev->mq);
+ liststatus++;
+ } else {
+ if (time_after(jiffies, maple_pnp_time)) {
+ maple_dev->mq->command = MAPLE_COMMAND_DEVINFO;
+ maple_dev->mq->length = 0;
+ maple_add_packet(maple_dev->mq);
+ liststatus++;
+ }
+ }
+
+ return 0;
}

/* VBLANK bottom half - implemented via workqueue */
static void maple_vblank_handler(struct work_struct *work)
{
- if (!maple_dma_done())
- return;
- if (!list_empty(&maple_sentq))
- return;
- ctrl_outl(0, MAPLE_ENABLE);
- liststatus = 0;
- bus_for_each_dev(&maple_bus_type, NULL, NULL,
- setup_maple_commands);
- if (time_after(jiffies, maple_pnp_time))
- maple_pnp_time = jiffies + MAPLE_PNP_INTERVAL;
- if (liststatus && list_empty(&maple_sentq)) {
- INIT_LIST_HEAD(&maple_sentq);
- maple_send();
- }
- maplebus_dma_reset();
+ if (!maple_dma_done())
+ return;
+ if (!list_empty(&maple_sentq))
+ return;
+ ctrl_outl(0, MAPLE_ENABLE);
+ liststatus = 0;
+ bus_for_each_dev(&maple_bus_type, NULL, NULL,
+ setup_maple_commands);
+ if (time_after(jiffies, maple_pnp_time))
+ maple_pnp_time = jiffies + MAPLE_PNP_INTERVAL;
+ if (liststatus && list_empty(&maple_sentq)) {
+ INIT_LIST_HEAD(&maple_sentq);
+ maple_send();
+ }
+ maplebus_dma_reset();
}

/* handle devices added via hotplugs - placing them on queue for DEVINFO*/
static void maple_map_subunits(struct maple_device *mdev, int submask)
{
- int retval, k, devcheck;
- struct maple_device *mdev_add;
- struct maple_device_specify ds;
-
- for (k = 0; k < 5; k++) {
- ds.port = mdev->port;
- ds.unit = k + 1;
- retval =
- bus_for_each_dev(&maple_bus_type, NULL, &ds,
- detach_maple_device);
- if (retval) {
- submask = submask >> 1;
- continue;
- }
- devcheck = submask & 0x01;
- if (devcheck) {
- mdev_add = maple_alloc_dev(mdev->port, k + 1);
- if (!mdev_add)
- return;
- mdev_add->mq->command = MAPLE_COMMAND_DEVINFO;
- mdev_add->mq->length = 0;
- maple_add_packet(mdev_add->mq);
- scanning = 1;
- }
- submask = submask >> 1;
- }
+ int retval, k, devcheck;
+ struct maple_device *mdev_add;
+ struct maple_device_specify ds;
+
+ for (k = 0; k < 5; k++) {
+ ds.port = mdev->port;
+ ds.unit = k + 1;
+ retval =
+ bus_for_each_dev(&maple_bus_type, NULL, &ds,
+ detach_maple_device);
+ if (retval) {
+ submask = submask >> 1;
+ continue;
+ }
+ devcheck = submask & 0x01;
+ if (devcheck) {
+ mdev_add = maple_alloc_dev(mdev->port, k + 1);
+ if (!mdev_add)
+ return;
+ mdev_add->mq->command = MAPLE_COMMAND_DEVINFO;
+ mdev_add->mq->length = 0;
+ maple_add_packet(mdev_add->mq);
+ scanning = 1;
+ }
+ submask = submask >> 1;
+ }
}

/* mark a device as removed */
static void maple_clean_submap(struct maple_device *mdev)
{
- int killbit;
+ int killbit;

- killbit = (mdev->unit > 0 ? (1 << (mdev->unit - 1)) & 0x1f : 0x20);
- killbit = ~killbit;
- killbit &= 0xFF;
- subdevice_map[mdev->port] = subdevice_map[mdev->port] & killbit;
+ killbit = (mdev->unit > 0 ? (1 << (mdev->unit - 1)) & 0x1f : 0x20);
+ killbit = ~killbit;
+ killbit &= 0xFF;
+ subdevice_map[mdev->port] = subdevice_map[mdev->port] & killbit;
}

/* handle empty port or hotplug removal */
static void maple_response_none(struct maple_device *mdev,
- struct mapleq *mq)
+ struct mapleq *mq)
{
- if (mdev->unit != 0) {
- list_del(&mq->list);
- maple_clean_submap(mdev);
- printk(KERN_INFO
- "Maple bus device detaching at (%d, %d)\n",
- mdev->port, mdev->unit);
- maple_detach_driver(mdev);
- return;
- }
- if (!started) {
- printk(KERN_INFO "No maple devices attached to port %d\n",
- mdev->port);
- return;
- }
- maple_clean_submap(mdev);
+ if (mdev->unit != 0) {
+ list_del(&mq->list);
+ maple_clean_submap(mdev);
+ printk(KERN_INFO
+ "Maple bus device detaching at (%d, %d)\n",
+ mdev->port, mdev->unit);
+ maple_detach_driver(mdev);
+ return;
+ }
+ if (!started) {
+ printk(KERN_INFO "No maple devices attached to port %d\n",
+ mdev->port);
+ return;
+ }
+ maple_clean_submap(mdev);
}

/* preprocess hotplugs or scans */
static void maple_response_devinfo(struct maple_device *mdev,
- char *recvbuf)
+ char *recvbuf)
{
- char submask;
- if ((!started) || (scanning == 2)) {
- maple_attach_driver(mdev);
- return;
- }
- if (mdev->unit == 0) {
- submask = recvbuf[2] & 0x1F;
- if (submask ^ subdevice_map[mdev->port]) {
- maple_map_subunits(mdev, submask);
- subdevice_map[mdev->port] = submask;
- }
- }
+ char submask;
+ if ((!started) || (scanning == 2)) {
+ maple_attach_driver(mdev);
+ return;
+ }
+ if (mdev->unit == 0) {
+ submask = recvbuf[2] & 0x1F;
+ if (submask ^ subdevice_map[mdev->port]) {
+ maple_map_subunits(mdev, submask);
+ subdevice_map[mdev->port] = submask;
+ }
+ }
}

/* maple dma end bottom half - implemented via workqueue */
static void maple_dma_handler(struct work_struct *work)
{
- struct mapleq *mq, *nmq;
- struct maple_device *dev;
- char *recvbuf;
- enum maple_code code;
-
- if (!maple_dma_done())
- return;
- ctrl_outl(0, MAPLE_ENABLE);
- if (!list_empty(&maple_sentq)) {
- list_for_each_entry_safe(mq, nmq, &maple_sentq, list) {
- recvbuf = mq->recvbuf;
- code = recvbuf[0];
- dev = mq->dev;
- switch (code) {
- case MAPLE_RESPONSE_NONE:
- maple_response_none(dev, mq);
- break;
-
- case MAPLE_RESPONSE_DEVINFO:
- maple_response_devinfo(dev, recvbuf);
- break;
-
- case MAPLE_RESPONSE_DATATRF:
- if (dev->callback)
- dev->callback(mq);
- break;
-
- case MAPLE_RESPONSE_FILEERR:
- case MAPLE_RESPONSE_AGAIN:
- case MAPLE_RESPONSE_BADCMD:
- case MAPLE_RESPONSE_BADFUNC:
- printk(KERN_DEBUG
- "Maple non-fatal error 0x%X\n",
- code);
- break;
-
- case MAPLE_RESPONSE_ALLINFO:
- printk(KERN_DEBUG
- "Maple - extended device information not supported\n");
- break;
-
- case MAPLE_RESPONSE_OK:
- break;
-
- default:
- break;
- }
- }
- INIT_LIST_HEAD(&maple_sentq);
- if (scanning == 1) {
- maple_send();
- scanning = 2;
- } else
- scanning = 0;
-
- if (started == 0)
- started = 1;
- }
- maplebus_dma_reset();
+ struct mapleq *mq, *nmq;
+ struct maple_device *dev;
+ char *recvbuf;
+ enum maple_code code;
+
+ if (!maple_dma_done())
+ return;
+ ctrl_outl(0, MAPLE_ENABLE);
+ if (!list_empty(&maple_sentq)) {
+ list_for_each_entry_safe(mq, nmq, &maple_sentq, list) {
+ recvbuf = mq->recvbuf;
+ code = recvbuf[0];
+ dev = mq->dev;
+ switch (code) {
+ case MAPLE_RESPONSE_NONE:
+ maple_response_none(dev, mq);
+ break;
+
+ case MAPLE_RESPONSE_DEVINFO:
+ maple_response_devinfo(dev, recvbuf);
+ break;
+
+ case MAPLE_RESPONSE_DATATRF:
+ if (dev->callback)
+ dev->callback(mq);
+ break;
+
+ case MAPLE_RESPONSE_FILEERR:
+ case MAPLE_RESPONSE_AGAIN:
+ case MAPLE_RESPONSE_BADCMD:
+ case MAPLE_RESPONSE_BADFUNC:
+ printk(KERN_DEBUG
+ "Maple non-fatal error 0x%X\n",
+ code);
+ break;
+
+ case MAPLE_RESPONSE_ALLINFO:
+ printk(KERN_DEBUG
+ "Maple - extended device information not supported\n");
+ break;
+
+ case MAPLE_RESPONSE_OK:
+ break;
+
+ default:
+ break;
+ }
+ }
+ INIT_LIST_HEAD(&maple_sentq);
+ if (scanning == 1) {
+ maple_send();
+ scanning = 2;
+ } else
+ scanning = 0;
+
+ if (started == 0)
+ started = 1;
+ }
+ maplebus_dma_reset();
}

static irqreturn_t maplebus_dma_interrupt(int irq, void *dev_id)
{
- /* Load everything into the bottom half */
- schedule_work(&maple_dma_process);
- return IRQ_HANDLED;
+ /* Load everything into the bottom half */
+ schedule_work(&maple_dma_process);
+ return IRQ_HANDLED;
}

static irqreturn_t maplebus_vblank_interrupt(int irq, void *dev_id)
{
- schedule_work(&maple_vblank_process);
- return IRQ_HANDLED;
+ schedule_work(&maple_vblank_process);
+ return IRQ_HANDLED;
}

static struct irqaction maple_dma_irq = {
- .name = "maple bus DMA handler",
- .handler = maplebus_dma_interrupt,
- .flags = IRQF_SHARED,
+ .name = "maple bus DMA handler",
+ .handler = maplebus_dma_interrupt,
+ .flags = IRQF_SHARED,
};

static struct irqaction maple_vblank_irq = {
- .name = "maple bus VBLANK handler",
- .handler = maplebus_vblank_interrupt,
- .flags = IRQF_SHARED,
+ .name = "maple bus VBLANK handler",
+ .handler = maplebus_vblank_interrupt,
+ .flags = IRQF_SHARED,
};

static int maple_set_dma_interrupt_handler(void)
{
- return setup_irq(HW_EVENT_MAPLE_DMA, &maple_dma_irq);
+ return setup_irq(HW_EVENT_MAPLE_DMA, &maple_dma_irq);
}

static int maple_set_vblank_interrupt_handler(void)
{
- return setup_irq(HW_EVENT_VSYNC, &maple_vblank_irq);
+ return setup_irq(HW_EVENT_VSYNC, &maple_vblank_irq);
}

static int maple_get_dma_buffer(void)
{
- maple_sendbuf =
- (void *) __get_free_pages(GFP_KERNEL | __GFP_ZERO,
- MAPLE_DMA_PAGES);
- if (!maple_sendbuf)
- return -ENOMEM;
- return 0;
+ maple_sendbuf =
+ (void *) __get_free_pages(GFP_KERNEL | __GFP_ZERO,
+ MAPLE_DMA_PAGES);
+ if (!maple_sendbuf)
+ return -ENOMEM;
+ return 0;
}

static int match_maple_bus_driver(struct device *devptr,
- struct device_driver *drvptr)
+ struct device_driver *drvptr)
{
- struct maple_driver *maple_drv;
- struct maple_device *maple_dev;
-
- maple_drv = container_of(drvptr, struct maple_driver, drv);
- maple_dev = container_of(devptr, struct maple_device, dev);
- /* Trap empty port case */
- if (maple_dev->devinfo.function == 0xFFFFFFFF)
- return 0;
- else if (maple_dev->devinfo.function &
- be32_to_cpu(maple_drv->function))
- return 1;
- return 0;
+ struct maple_driver *maple_drv;
+ struct maple_device *maple_dev;
+
+ maple_drv = container_of(drvptr, struct maple_driver, drv);
+ maple_dev = container_of(devptr, struct maple_device, dev);
+ /* Trap empty port case */
+ if (maple_dev->devinfo.function == 0xFFFFFFFF)
+ return 0;
+ else if (maple_dev->devinfo.function &
+ be32_to_cpu(maple_drv->function))
+ return 1;
+ return 0;
}

-static int maple_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
+static int maple_bus_uevent(struct device *dev,
+ struct kobj_uevent_env *env)
{
- return 0;
+ return 0;
}

static void maple_bus_release(struct device *dev)
@@ -610,124 +614,126 @@ static void maple_bus_release(struct device *dev)
}

static struct maple_driver maple_dummy_driver = {
- .drv = {
- .name = "maple_dummy_driver",
- .bus = &maple_bus_type,
- },
+ .drv = {
+ .name = "maple_dummy_driver",
+ .bus = &maple_bus_type,
+ },
};

struct bus_type maple_bus_type = {
- .name = "maple",
- .match = match_maple_bus_driver,
- .uevent = maple_bus_uevent,
+ .name = "maple",
+ .match = match_maple_bus_driver,
+ .uevent = maple_bus_uevent,
};
+
EXPORT_SYMBOL_GPL(maple_bus_type);

static struct device maple_bus = {
- .bus_id = "maple",
- .release = maple_bus_release,
+ .bus_id = "maple",
+ .release = maple_bus_release,
};

static int __init maple_bus_init(void)
{
- int retval, i;
- struct maple_device *mdev[MAPLE_PORTS];
- ctrl_outl(0, MAPLE_STATE);
-
- retval = device_register(&maple_bus);
- if (retval)
- goto cleanup;
-
- retval = bus_register(&maple_bus_type);
- if (retval)
- goto cleanup_device;
-
- retval = driver_register(&maple_dummy_driver.drv);
-
- if (retval)
- goto cleanup_bus;
-
- /* allocate memory for maple bus dma */
- retval = maple_get_dma_buffer();
- if (retval) {
- printk(KERN_INFO
- "Maple bus: Failed to allocate Maple DMA buffers\n");
- goto cleanup_basic;
- }
-
- /* set up DMA interrupt handler */
- retval = maple_set_dma_interrupt_handler();
- if (retval) {
- printk(KERN_INFO
- "Maple bus: Failed to grab maple DMA IRQ\n");
- goto cleanup_dma;
- }
-
- /* set up VBLANK interrupt handler */
- retval = maple_set_vblank_interrupt_handler();
- if (retval) {
- printk(KERN_INFO "Maple bus: Failed to grab VBLANK IRQ\n");
- goto cleanup_irq;
- }
-
- maple_queue_cache =
- kmem_cache_create("maple_queue_cache", 0x400, 0,
- SLAB_HWCACHE_ALIGN, NULL);
-
- if (!maple_queue_cache)
- goto cleanup_bothirqs;
-
- /* setup maple ports */
- for (i = 0; i < MAPLE_PORTS; i++) {
- mdev[i] = maple_alloc_dev(i, 0);
- if (!mdev[i]) {
- while (i-- > 0)
- maple_free_dev(mdev[i]);
- goto cleanup_cache;
- }
- mdev[i]->registered = 0;
- mdev[i]->mq->command = MAPLE_COMMAND_DEVINFO;
- mdev[i]->mq->length = 0;
- maple_attach_driver(mdev[i]);
- maple_add_packet(mdev[i]->mq);
- subdevice_map[i] = 0;
- }
-
- /* setup maplebus hardware */
- maplebus_dma_reset();
-
- /* initial detection */
- maple_send();
-
- maple_pnp_time = jiffies;
-
- printk(KERN_INFO "Maple bus core now registered.\n");
-
- return 0;
-
-cleanup_cache:
- kmem_cache_destroy(maple_queue_cache);
-
-cleanup_bothirqs:
- free_irq(HW_EVENT_VSYNC, 0);
-
-cleanup_irq:
- free_irq(HW_EVENT_MAPLE_DMA, 0);
-
-cleanup_dma:
- free_pages((unsigned long) maple_sendbuf, MAPLE_DMA_PAGES);
-
-cleanup_basic:
- driver_unregister(&maple_dummy_driver.drv);
-
-cleanup_bus:
- bus_unregister(&maple_bus_type);
-
-cleanup_device:
- device_unregister(&maple_bus);
-
-cleanup:
- printk(KERN_INFO "Maple bus registration failed\n");
- return retval;
+ int retval, i;
+ struct maple_device *mdev[MAPLE_PORTS];
+ ctrl_outl(0, MAPLE_STATE);
+
+ retval = device_register(&maple_bus);
+ if (retval)
+ goto cleanup;
+
+ retval = bus_register(&maple_bus_type);
+ if (retval)
+ goto cleanup_device;
+
+ retval = driver_register(&maple_dummy_driver.drv);
+
+ if (retval)
+ goto cleanup_bus;
+
+ /* allocate memory for maple bus dma */
+ retval = maple_get_dma_buffer();
+ if (retval) {
+ printk(KERN_INFO
+ "Maple bus: Failed to allocate Maple DMA buffers\n");
+ goto cleanup_basic;
+ }
+
+ /* set up DMA interrupt handler */
+ retval = maple_set_dma_interrupt_handler();
+ if (retval) {
+ printk(KERN_INFO
+ "Maple bus: Failed to grab maple DMA IRQ\n");
+ goto cleanup_dma;
+ }
+
+ /* set up VBLANK interrupt handler */
+ retval = maple_set_vblank_interrupt_handler();
+ if (retval) {
+ printk(KERN_INFO "Maple bus: Failed to grab VBLANK IRQ\n");
+ goto cleanup_irq;
+ }
+
+ maple_queue_cache =
+ kmem_cache_create("maple_queue_cache", 0x400, 0,
+ SLAB_HWCACHE_ALIGN, NULL);
+
+ if (!maple_queue_cache)
+ goto cleanup_bothirqs;
+
+ /* setup maple ports */
+ for (i = 0; i < MAPLE_PORTS; i++) {
+ mdev[i] = maple_alloc_dev(i, 0);
+ if (!mdev[i]) {
+ while (i-- > 0)
+ maple_free_dev(mdev[i]);
+ goto cleanup_cache;
+ }
+ mdev[i]->registered = 0;
+ mdev[i]->mq->command = MAPLE_COMMAND_DEVINFO;
+ mdev[i]->mq->length = 0;
+ maple_attach_driver(mdev[i]);
+ maple_add_packet(mdev[i]->mq);
+ subdevice_map[i] = 0;
+ }
+
+ /* setup maplebus hardware */
+ maplebus_dma_reset();
+
+ /* initial detection */
+ maple_send();
+
+ maple_pnp_time = jiffies;
+
+ printk(KERN_INFO "Maple bus core now registered.\n");
+
+ return 0;
+
+ cleanup_cache:
+ kmem_cache_destroy(maple_queue_cache);
+
+ cleanup_bothirqs:
+ free_irq(HW_EVENT_VSYNC, 0);
+
+ cleanup_irq:
+ free_irq(HW_EVENT_MAPLE_DMA, 0);
+
+ cleanup_dma:
+ free_pages((unsigned long) maple_sendbuf, MAPLE_DMA_PAGES);
+
+ cleanup_basic:
+ driver_unregister(&maple_dummy_driver.drv);
+
+ cleanup_bus:
+ bus_unregister(&maple_bus_type);
+
+ cleanup_device:
+ device_unregister(&maple_bus);
+
+ cleanup:
+ printk(KERN_INFO "Maple bus registration failed\n");
+ return retval;
}
+
subsys_initcall(maple_bus_init);
diff --git a/include/linux/maple.h b/include/linux/maple.h
index bad9a7b..f82c17b 100644
--- a/include/linux/maple.h
+++ b/include/linux/maple.h
@@ -7,74 +7,75 @@ extern struct bus_type maple_bus_type;

/* Maple Bus command and response codes */
enum maple_code {
- MAPLE_RESPONSE_FILEERR = -5,
- MAPLE_RESPONSE_AGAIN = -4, /* request should be retransmitted */
- MAPLE_RESPONSE_BADCMD = -3,
- MAPLE_RESPONSE_BADFUNC = -2,
- MAPLE_RESPONSE_NONE = -1, /* unit didn't respond at all */
- MAPLE_COMMAND_DEVINFO = 1,
- MAPLE_COMMAND_ALLINFO = 2,
- MAPLE_COMMAND_RESET = 3,
- MAPLE_COMMAND_KILL = 4,
- MAPLE_RESPONSE_DEVINFO = 5,
- MAPLE_RESPONSE_ALLINFO = 6,
- MAPLE_RESPONSE_OK = 7,
- MAPLE_RESPONSE_DATATRF = 8,
- MAPLE_COMMAND_GETCOND = 9,
- MAPLE_COMMAND_GETMINFO = 10,
- MAPLE_COMMAND_BREAD = 11,
- MAPLE_COMMAND_BWRITE = 12,
- MAPLE_COMMAND_SETCOND = 14
+ MAPLE_RESPONSE_FILEERR = -5,
+ MAPLE_RESPONSE_AGAIN = -4, /* request should be retransmitted */
+ MAPLE_RESPONSE_BADCMD = -3,
+ MAPLE_RESPONSE_BADFUNC = -2,
+ MAPLE_RESPONSE_NONE = -1, /* unit didn't respond at all */
+ MAPLE_COMMAND_DEVINFO = 1,
+ MAPLE_COMMAND_ALLINFO = 2,
+ MAPLE_COMMAND_RESET = 3,
+ MAPLE_COMMAND_KILL = 4,
+ MAPLE_RESPONSE_DEVINFO = 5,
+ MAPLE_RESPONSE_ALLINFO = 6,
+ MAPLE_RESPONSE_OK = 7,
+ MAPLE_RESPONSE_DATATRF = 8,
+ MAPLE_COMMAND_GETCOND = 9,
+ MAPLE_COMMAND_GETMINFO = 10,
+ MAPLE_COMMAND_BREAD = 11,
+ MAPLE_COMMAND_BWRITE = 12,
+ MAPLE_COMMAND_SETCOND = 14
};

struct mapleq {
- struct list_head list;
- struct maple_device *dev;
- void *sendbuf, *recvbuf, *recvbufdcsp;
- unsigned char length;
- enum maple_code command;
+ struct list_head list;
+ struct maple_device *dev;
+ void *sendbuf, *recvbuf, *recvbufdcsp;
+ unsigned char length;
+ enum maple_code command;
};

struct maple_devinfo {
- unsigned long function;
- unsigned long function_data[3];
- unsigned char area_code;
- unsigned char connector_directon;
- char product_name[31];
- char product_licence[61];
- unsigned short standby_power;
- unsigned short max_power;
+ unsigned long function;
+ unsigned long function_data[3];
+ unsigned char area_code;
+ unsigned char connector_directon;
+ char product_name[31];
+ char product_licence[61];
+ unsigned short standby_power;
+ unsigned short max_power;
};

struct maple_device {
- struct maple_driver *driver;
- struct mapleq *mq;
- void *private_data;
- void (*callback) (struct mapleq * mq);
- unsigned long when, interval, function;
- struct maple_devinfo devinfo;
- unsigned char port, unit;
- char product_name[32];
- char product_licence[64];
- int registered;
- struct device dev;
+ struct maple_driver *driver;
+ struct mapleq *mq;
+ void *private_data;
+ void (*callback) (struct mapleq * mq);
+ unsigned long when, interval, function;
+ struct maple_devinfo devinfo;
+ unsigned char port, unit;
+ char product_name[32];
+ char product_licence[64];
+ int registered;
+ struct device dev;
};

struct maple_driver {
- unsigned long function;
- int (*connect) (struct maple_device * dev);
- void (*disconnect) (struct maple_device * dev);
- struct device_driver drv;
+ unsigned long function;
+ int (*connect) (struct maple_device * dev);
+ void (*disconnect) (struct maple_device * dev);
+ struct device_driver drv;
+ int registered;
};

void maple_getcond_callback(struct maple_device *dev,
- void (*callback) (struct mapleq * mq),
- unsigned long interval,
- unsigned long function);
+ void (*callback) (struct mapleq * mq),
+ unsigned long interval,
+ unsigned long function);
int maple_driver_register(struct device_driver *drv);
void maple_add_packet(struct mapleq *mq);

#define to_maple_dev(n) container_of(n, struct maple_device, dev)
#define to_maple_driver(n) container_of(n, struct maple_driver, drv)

-#endif /* __LINUX_MAPLE_H */
+#endif /* __LINUX_MAPLE_H */


2008-02-06 22:54:44

by Adrian McMenamin

[permalink] [raw]
Subject: [PATCH 2/2] - SH/Dreamcast - fix maple bus bugs

This patch fixes up memory leaks and, by delaying initialisation, makes
device detection more robust.

It also makes clearer the difference between struct maple_device and
struct device, as well as cleaning up the interrupt request code
(without changing its function in any way).

Signed-off by: Adrian McMenamin <[email protected]>
----

diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c
index 3f341dc..60eeb92 100644
--- a/drivers/sh/maple/maple.c
+++ b/drivers/sh/maple/maple.c
@@ -30,6 +30,7 @@
#include <asm/mach/dma.h>
#include <asm/mach/sysasic.h>
#include <asm/mach/maple.h>
+#include <linux/delay.h>

MODULE_AUTHOR("Yaegshi Takeshi, Paul Mundt, M.R. Brown, Adrian McMenamin");
MODULE_DESCRIPTION("Maple bus driver for Dreamcast");
@@ -52,7 +53,7 @@ static struct device maple_bus;
static int subdevice_map[MAPLE_PORTS];
static unsigned long *maple_sendbuf, *maple_sendptr, *maple_lastptr;
static unsigned long maple_pnp_time;
-static int started, scanning, liststatus;
+static int started, scanning, liststatus, realscan;
static struct kmem_cache *maple_queue_cache;

struct maple_device_specify {
@@ -72,7 +73,6 @@ int maple_driver_register(struct device_driver *drv)
drv->bus = &maple_bus_type;
return driver_register(drv);
}
-
EXPORT_SYMBOL_GPL(maple_driver_register);

/* set hardware registers to enable next round of dma */
@@ -94,15 +94,14 @@ static void maplebus_dma_reset(void)
* @function: the function code for the device
*/
void maple_getcond_callback(struct maple_device *dev,
- void (*callback) (struct mapleq * mq),
- unsigned long interval, unsigned long function)
+ void (*callback) (struct mapleq *mq),
+ unsigned long interval, unsigned long function)
{
dev->callback = callback;
dev->interval = interval;
dev->function = cpu_to_be32(function);
dev->when = jiffies;
}
-
EXPORT_SYMBOL_GPL(maple_getcond_callback);

static int maple_dma_done(void)
@@ -112,10 +111,19 @@ static int maple_dma_done(void)

static void maple_release_device(struct device *dev)
{
- if (dev->type) {
- kfree(dev->type->name);
- kfree(dev->type);
+ struct maple_device *mdev;
+ struct mapleq *mq;
+ if (!dev)
+ return;
+ mdev = to_maple_dev(dev);
+ mq = mdev->mq;
+ if (mq) {
+ if (mq->recvbufdcsp)
+ kmem_cache_free(maple_queue_cache, mq->recvbufdcsp);
+ kfree(mq);
+ mq = NULL;
}
+ kfree(mdev);
}

/**
@@ -128,10 +136,9 @@ void maple_add_packet(struct mapleq *mq)
list_add(&mq->list, &maple_waitq);
mutex_unlock(&maple_list_lock);
}
-
EXPORT_SYMBOL_GPL(maple_add_packet);

-static struct mapleq *maple_allocq(struct maple_device *dev)
+static struct mapleq *maple_allocq(struct maple_device *mdev)
{
struct mapleq *mq;

@@ -139,7 +146,7 @@ static struct mapleq *maple_allocq(struct maple_device *dev)
if (!mq)
return NULL;

- mq->dev = dev;
+ mq->dev = mdev;
mq->recvbufdcsp = kmem_cache_zalloc(maple_queue_cache, GFP_KERNEL);
mq->recvbuf = (void *) P2SEGADDR(mq->recvbufdcsp);
if (!mq->recvbuf) {
@@ -152,22 +159,24 @@ static struct mapleq *maple_allocq(struct maple_device *dev)

static struct maple_device *maple_alloc_dev(int port, int unit)
{
- struct maple_device *dev;
+ struct maple_device *mdev;

- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (!dev)
+ mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
+ if (!mdev)
return NULL;

- dev->port = port;
- dev->unit = unit;
- dev->mq = maple_allocq(dev);
+ mdev->port = port;
+ mdev->unit = unit;
+ mdev->mq = maple_allocq(mdev);

- if (!dev->mq) {
- kfree(dev);
+ if (!mdev->mq) {
+ kfree(mdev);
return NULL;
}
-
- return dev;
+ mdev->dev.bus = &maple_bus_type;
+ mdev->dev.parent = &maple_bus;
+ mdev->function = 0;
+ return mdev;
}

static void maple_free_dev(struct maple_device *mdev)
@@ -175,7 +184,9 @@ static void maple_free_dev(struct maple_device *mdev)
if (!mdev)
return;
if (mdev->mq) {
- kmem_cache_free(maple_queue_cache, mdev->mq->recvbufdcsp);
+ if (mdev->mq->recvbufdcsp)
+ kmem_cache_free(maple_queue_cache,
+ mdev->mq->recvbufdcsp);
kfree(mdev->mq);
}
kfree(mdev);
@@ -259,80 +270,93 @@ static void maple_detach_driver(struct maple_device *mdev)
mdev->driver->disconnect(mdev);
}
mdev->driver = NULL;
- if (mdev->registered) {
- maple_release_device(&mdev->dev);
+ if (mdev->registered)
device_unregister(&mdev->dev);
- }
- mdev->registered = 0;
- maple_free_dev(mdev);
+ mdev = NULL;
}

/* process initial MAPLE_COMMAND_DEVINFO for each device or port */
-static void maple_attach_driver(struct maple_device *dev)
+static void maple_attach_driver(struct maple_device *mdev)
{
- char *p;
-
- char *recvbuf;
+ char *p, *recvbuf;
unsigned long function;
int matched, retval;

- recvbuf = dev->mq->recvbuf;
- memcpy(&dev->devinfo, recvbuf + 4, sizeof(dev->devinfo));
- memcpy(dev->product_name, dev->devinfo.product_name, 30);
- memcpy(dev->product_licence, dev->devinfo.product_licence, 60);
- dev->product_name[30] = '\0';
- dev->product_licence[60] = '\0';
-
- for (p = dev->product_name + 29; dev->product_name <= p; p--)
+ recvbuf = mdev->mq->recvbuf;
+ /* copy the data as individual elements in
+ * case of memory optimisation */
+ memcpy(&mdev->devinfo.function, recvbuf + 4, 4);
+ memcpy(&mdev->devinfo.function_data[0], recvbuf + 8, 12);
+ memcpy(&mdev->devinfo.area_code, recvbuf + 20, 1);
+ memcpy(&mdev->devinfo.connector_direction, recvbuf + 21, 1);
+ memcpy(&mdev->devinfo.product_name[0], recvbuf + 22, 30);
+ memcpy(&mdev->devinfo.product_licence[0], recvbuf + 52, 60);
+ memcpy(&mdev->devinfo.standby_power, recvbuf + 112, 2);
+ memcpy(&mdev->devinfo.max_power, recvbuf + 114, 2);
+ memcpy(mdev->product_name, mdev->devinfo.product_name, 30);
+ mdev->product_name[30] = '\0';
+ memcpy(mdev->product_licence, mdev->devinfo.product_licence, 60);
+ mdev->product_licence[60] = '\0';
+
+ for (p = mdev->product_name + 29; mdev->product_name <= p; p--)
if (*p == ' ')
*p = '\0';
else
break;
-
- for (p = dev->product_licence + 59; dev->product_licence <= p; p--)
+ for (p = mdev->product_licence + 59; mdev->product_licence <= p; p--)
if (*p == ' ')
*p = '\0';
else
break;

- function = be32_to_cpu(dev->devinfo.function);
+ if (realscan) {
+ printk(KERN_INFO "Maple device detected: %s\n",
+ mdev->product_name);
+ printk(KERN_INFO "Maple device: %s\n", mdev->product_licence);
+ }
+
+ function = be32_to_cpu(mdev->devinfo.function);

if (function > 0x200) {
/* Do this silently - as not a real device */
function = 0;
- dev->driver = &maple_dummy_driver;
- sprintf(dev->dev.bus_id, "%d:0.port", dev->port);
+ mdev->driver = &maple_dummy_driver;
+ sprintf(mdev->dev.bus_id, "%d:0.port", mdev->port);
} else {
- printk(KERN_INFO
- "Maple bus at (%d, %d): Connected function 0x%lX\n",
- dev->port, dev->unit, function);
+ if (realscan)
+ printk(KERN_INFO
+ "Maple bus at (%d, %d): Function 0x%lX\n",
+ mdev->port, mdev->unit, function);

matched =
- bus_for_each_drv(&maple_bus_type, NULL, dev,
+ bus_for_each_drv(&maple_bus_type, NULL, mdev,
attach_matching_maple_driver);

if (matched == 0) {
/* Driver does not exist yet */
- printk(KERN_INFO
- "No maple driver found for this device\n");
- dev->driver = &maple_dummy_driver;
+ if (realscan)
+ printk(KERN_INFO
+ "No maple driver found.\n");
+ mdev->driver = &maple_dummy_driver;
}
-
- sprintf(dev->dev.bus_id, "%d:0%d.%lX", dev->port,
- dev->unit, function);
+ sprintf(mdev->dev.bus_id, "%d:0%d.%lX", mdev->port,
+ mdev->unit, function);
}
- dev->function = function;
- dev->dev.bus = &maple_bus_type;
- dev->dev.parent = &maple_bus;
- dev->dev.release = &maple_release_device;
- retval = device_register(&dev->dev);
- if (retval) {
- printk(KERN_INFO
- "Maple bus: Attempt to register device (%x, %x) failed.\n",
- dev->port, dev->unit);
- maple_free_dev(dev);
+ mdev->function = function;
+ mdev->dev.release = &maple_release_device;
+ if (mdev->registered == 0) {
+ retval = device_register(&mdev->dev);
+ if (retval) {
+ printk(KERN_INFO
+ "Maple bus: Attempt to register device"
+ " (%x, %x) failed.\n",
+ mdev->port, mdev->unit);
+ maple_free_dev(mdev);
+ mdev = NULL;
+ return;
+ }
+ mdev->registered = 1;
}
- dev->registered = 1;
}

/*
@@ -518,7 +542,8 @@ static void maple_dma_handler(struct work_struct *work)

case MAPLE_RESPONSE_ALLINFO:
printk(KERN_DEBUG
- "Maple - extended device information not supported\n");
+ "Maple - extended device information"
+ " not supported\n");
break;

case MAPLE_RESPONSE_OK:
@@ -554,26 +579,16 @@ static irqreturn_t maplebus_vblank_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}

-static struct irqaction maple_dma_irq = {
- .name = "maple bus DMA handler",
- .handler = maplebus_dma_interrupt,
- .flags = IRQF_SHARED,
-};
-
-static struct irqaction maple_vblank_irq = {
- .name = "maple bus VBLANK handler",
- .handler = maplebus_vblank_interrupt,
- .flags = IRQF_SHARED,
-};
-
static int maple_set_dma_interrupt_handler(void)
{
- return setup_irq(HW_EVENT_MAPLE_DMA, &maple_dma_irq);
+ return request_irq(HW_EVENT_MAPLE_DMA, maplebus_dma_interrupt,
+ IRQF_SHARED, "maple bus DMA", &maple_dummy_driver);
}

static int maple_set_vblank_interrupt_handler(void)
{
- return setup_irq(HW_EVENT_VSYNC, &maple_vblank_irq);
+ return request_irq(HW_EVENT_VSYNC, maplebus_vblank_interrupt,
+ IRQF_SHARED, "maple bus VBLANK", &maple_dummy_driver);
}

static int maple_get_dma_buffer(void)
@@ -617,7 +632,7 @@ static struct maple_driver maple_dummy_driver = {
.drv = {
.name = "maple_dummy_driver",
.bus = &maple_bus_type,
- },
+ },
};

struct bus_type maple_bus_type = {
@@ -625,7 +640,6 @@ struct bus_type maple_bus_type = {
.match = match_maple_bus_driver,
.uevent = maple_bus_uevent,
};
-
EXPORT_SYMBOL_GPL(maple_bus_type);

static struct device maple_bus = {
@@ -677,7 +691,7 @@ static int __init maple_bus_init(void)

maple_queue_cache =
kmem_cache_create("maple_queue_cache", 0x400, 0,
- SLAB_HWCACHE_ALIGN, NULL);
+ SLAB_POISON|SLAB_HWCACHE_ALIGN, NULL);

if (!maple_queue_cache)
goto cleanup_bothirqs;
@@ -693,47 +707,46 @@ static int __init maple_bus_init(void)
mdev[i]->registered = 0;
mdev[i]->mq->command = MAPLE_COMMAND_DEVINFO;
mdev[i]->mq->length = 0;
- maple_attach_driver(mdev[i]);
maple_add_packet(mdev[i]->mq);
+ /* delay aids hardware detection */
+ udelay(20);
subdevice_map[i] = 0;
}

+ realscan = 1;
/* setup maplebus hardware */
maplebus_dma_reset();
-
/* initial detection */
maple_send();
-
maple_pnp_time = jiffies;
-
printk(KERN_INFO "Maple bus core now registered.\n");

return 0;

- cleanup_cache:
+cleanup_cache:
kmem_cache_destroy(maple_queue_cache);

- cleanup_bothirqs:
+cleanup_bothirqs:
free_irq(HW_EVENT_VSYNC, 0);

- cleanup_irq:
+cleanup_irq:
free_irq(HW_EVENT_MAPLE_DMA, 0);

- cleanup_dma:
+cleanup_dma:
free_pages((unsigned long) maple_sendbuf, MAPLE_DMA_PAGES);

- cleanup_basic:
+cleanup_basic:
driver_unregister(&maple_dummy_driver.drv);

- cleanup_bus:
+cleanup_bus:
bus_unregister(&maple_bus_type);

- cleanup_device:
+cleanup_device:
device_unregister(&maple_bus);

- cleanup:
+cleanup:
printk(KERN_INFO "Maple bus registration failed\n");
return retval;
}
-
-subsys_initcall(maple_bus_init);
+/* Push init to later to ensure hardware gets detected */
+fs_initcall(maple_bus_init);

2008-02-06 23:03:29

by Greg KH

[permalink] [raw]
Subject: Re: [PATCH 2/2] - SH/Dreamcast - fix maple bus bugs

On Wed, Feb 06, 2008 at 10:53:51PM +0000, Adrian McMenamin wrote:
> - dev->function = function;
> - dev->dev.bus = &maple_bus_type;
> - dev->dev.parent = &maple_bus;
> - dev->dev.release = &maple_release_device;
> - retval = device_register(&dev->dev);
> - if (retval) {
> - printk(KERN_INFO
> - "Maple bus: Attempt to register device (%x, %x) failed.\n",
> - dev->port, dev->unit);
> - maple_free_dev(dev);
> + mdev->function = function;
> + mdev->dev.release = &maple_release_device;
> + if (mdev->registered == 0) {
> + retval = device_register(&mdev->dev);
> + if (retval) {
> + printk(KERN_INFO
> + "Maple bus: Attempt to register device"
> + " (%x, %x) failed.\n",
> + mdev->port, mdev->unit);
> + maple_free_dev(mdev);
> + mdev = NULL;
> + return;
> + }
> + mdev->registered = 1;
> }
> - dev->registered = 1;

I think you are still papering over the real problem here of trying to
register a device twice. That's something you should never be doing,
and your bus walking logic must be incorrect...

thanks,

greg k-h

2008-02-06 23:08:48

by Adrian McMenamin

[permalink] [raw]
Subject: Re: [PATCH 2/2] - SH/Dreamcast - fix maple bus bugs


On Wed, 2008-02-06 at 15:01 -0800, Greg KH wrote:
> On Wed, Feb 06, 2008 at 10:53:51PM +0000, Adrian McMenamin wrote:
> > - dev->function = function;
> > - dev->dev.bus = &maple_bus_type;
> > - dev->dev.parent = &maple_bus;
> > - dev->dev.release = &maple_release_device;
> > - retval = device_register(&dev->dev);
> > - if (retval) {
> > - printk(KERN_INFO
> > - "Maple bus: Attempt to register device (%x, %x) failed.\n",
> > - dev->port, dev->unit);
> > - maple_free_dev(dev);
> > + mdev->function = function;
> > + mdev->dev.release = &maple_release_device;
> > + if (mdev->registered == 0) {
> > + retval = device_register(&mdev->dev);
> > + if (retval) {
> > + printk(KERN_INFO
> > + "Maple bus: Attempt to register device"
> > + " (%x, %x) failed.\n",
> > + mdev->port, mdev->unit);
> > + maple_free_dev(mdev);
> > + mdev = NULL;
> > + return;
> > + }
> > + mdev->registered = 1;
> > }
> > - dev->registered = 1;
>
> I think you are still papering over the real problem here of trying to
> register a device twice. That's something you should never be doing,
> and your bus walking logic must be incorrect...
>
I just left that in as a sanity check. It should never be acted on. I
can remove it if you prefer.

2008-02-06 23:26:48

by Greg KH

[permalink] [raw]
Subject: Re: [PATCH 2/2] - SH/Dreamcast - fix maple bus bugs

On Wed, Feb 06, 2008 at 11:05:14PM +0000, Adrian McMenamin wrote:
>
> On Wed, 2008-02-06 at 15:01 -0800, Greg KH wrote:
> > On Wed, Feb 06, 2008 at 10:53:51PM +0000, Adrian McMenamin wrote:
> > > - dev->function = function;
> > > - dev->dev.bus = &maple_bus_type;
> > > - dev->dev.parent = &maple_bus;
> > > - dev->dev.release = &maple_release_device;
> > > - retval = device_register(&dev->dev);
> > > - if (retval) {
> > > - printk(KERN_INFO
> > > - "Maple bus: Attempt to register device (%x, %x) failed.\n",
> > > - dev->port, dev->unit);
> > > - maple_free_dev(dev);
> > > + mdev->function = function;
> > > + mdev->dev.release = &maple_release_device;
> > > + if (mdev->registered == 0) {
> > > + retval = device_register(&mdev->dev);
> > > + if (retval) {
> > > + printk(KERN_INFO
> > > + "Maple bus: Attempt to register device"
> > > + " (%x, %x) failed.\n",
> > > + mdev->port, mdev->unit);
> > > + maple_free_dev(mdev);
> > > + mdev = NULL;
> > > + return;
> > > + }
> > > + mdev->registered = 1;
> > > }
> > > - dev->registered = 1;
> >
> > I think you are still papering over the real problem here of trying to
> > register a device twice. That's something you should never be doing,
> > and your bus walking logic must be incorrect...
> >
> I just left that in as a sanity check. It should never be acted on. I
> can remove it if you prefer.

Please do, that way, and real problems will show up with that warning
you were getting that started all of this work :)

thanks,

greg k-h

2008-02-06 23:51:53

by Adrian McMenamin

[permalink] [raw]
Subject: Re: [PATCH 2/2] - SH/Dreamcast - fix maple bus bugs

Replacement second-in-series patch:

This patch fixes up memory leaks and, by delaying initialisation, makes
device detection more robust.

It also makes clearer the difference between struct maple_device and
struct device, as well as cleaning up the interrupt request code
(without changing its function in any way).

Also now removes redundant registration checking.

Signed-off by: Adrian McMenamin <[email protected]>

----

diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c
index 3f341dc..fbca7f8 100644
--- a/drivers/sh/maple/maple.c
+++ b/drivers/sh/maple/maple.c
@@ -30,6 +30,7 @@
#include <asm/mach/dma.h>
#include <asm/mach/sysasic.h>
#include <asm/mach/maple.h>
+#include <linux/delay.h>

MODULE_AUTHOR("Yaegshi Takeshi, Paul Mundt, M.R. Brown, Adrian McMenamin");
MODULE_DESCRIPTION("Maple bus driver for Dreamcast");
@@ -52,7 +53,7 @@ static struct device maple_bus;
static int subdevice_map[MAPLE_PORTS];
static unsigned long *maple_sendbuf, *maple_sendptr, *maple_lastptr;
static unsigned long maple_pnp_time;
-static int started, scanning, liststatus;
+static int started, scanning, liststatus, realscan;
static struct kmem_cache *maple_queue_cache;

struct maple_device_specify {
@@ -72,7 +73,6 @@ int maple_driver_register(struct device_driver *drv)
drv->bus = &maple_bus_type;
return driver_register(drv);
}
-
EXPORT_SYMBOL_GPL(maple_driver_register);

/* set hardware registers to enable next round of dma */
@@ -94,15 +94,14 @@ static void maplebus_dma_reset(void)
* @function: the function code for the device
*/
void maple_getcond_callback(struct maple_device *dev,
- void (*callback) (struct mapleq * mq),
- unsigned long interval, unsigned long function)
+ void (*callback) (struct mapleq *mq),
+ unsigned long interval, unsigned long function)
{
dev->callback = callback;
dev->interval = interval;
dev->function = cpu_to_be32(function);
dev->when = jiffies;
}
-
EXPORT_SYMBOL_GPL(maple_getcond_callback);

static int maple_dma_done(void)
@@ -112,10 +111,19 @@ static int maple_dma_done(void)

static void maple_release_device(struct device *dev)
{
- if (dev->type) {
- kfree(dev->type->name);
- kfree(dev->type);
+ struct maple_device *mdev;
+ struct mapleq *mq;
+ if (!dev)
+ return;
+ mdev = to_maple_dev(dev);
+ mq = mdev->mq;
+ if (mq) {
+ if (mq->recvbufdcsp)
+ kmem_cache_free(maple_queue_cache, mq->recvbufdcsp);
+ kfree(mq);
+ mq = NULL;
}
+ kfree(mdev);
}

/**
@@ -128,10 +136,9 @@ void maple_add_packet(struct mapleq *mq)
list_add(&mq->list, &maple_waitq);
mutex_unlock(&maple_list_lock);
}
-
EXPORT_SYMBOL_GPL(maple_add_packet);

-static struct mapleq *maple_allocq(struct maple_device *dev)
+static struct mapleq *maple_allocq(struct maple_device *mdev)
{
struct mapleq *mq;

@@ -139,7 +146,7 @@ static struct mapleq *maple_allocq(struct maple_device *dev)
if (!mq)
return NULL;

- mq->dev = dev;
+ mq->dev = mdev;
mq->recvbufdcsp = kmem_cache_zalloc(maple_queue_cache, GFP_KERNEL);
mq->recvbuf = (void *) P2SEGADDR(mq->recvbufdcsp);
if (!mq->recvbuf) {
@@ -152,22 +159,24 @@ static struct mapleq *maple_allocq(struct maple_device *dev)

static struct maple_device *maple_alloc_dev(int port, int unit)
{
- struct maple_device *dev;
+ struct maple_device *mdev;

- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (!dev)
+ mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
+ if (!mdev)
return NULL;

- dev->port = port;
- dev->unit = unit;
- dev->mq = maple_allocq(dev);
+ mdev->port = port;
+ mdev->unit = unit;
+ mdev->mq = maple_allocq(mdev);

- if (!dev->mq) {
- kfree(dev);
+ if (!mdev->mq) {
+ kfree(mdev);
return NULL;
}
-
- return dev;
+ mdev->dev.bus = &maple_bus_type;
+ mdev->dev.parent = &maple_bus;
+ mdev->function = 0;
+ return mdev;
}

static void maple_free_dev(struct maple_device *mdev)
@@ -175,7 +184,9 @@ static void maple_free_dev(struct maple_device *mdev)
if (!mdev)
return;
if (mdev->mq) {
- kmem_cache_free(maple_queue_cache, mdev->mq->recvbufdcsp);
+ if (mdev->mq->recvbufdcsp)
+ kmem_cache_free(maple_queue_cache,
+ mdev->mq->recvbufdcsp);
kfree(mdev->mq);
}
kfree(mdev);
@@ -259,80 +270,89 @@ static void maple_detach_driver(struct maple_device *mdev)
mdev->driver->disconnect(mdev);
}
mdev->driver = NULL;
- if (mdev->registered) {
- maple_release_device(&mdev->dev);
- device_unregister(&mdev->dev);
- }
- mdev->registered = 0;
- maple_free_dev(mdev);
+ device_unregister(&mdev->dev);
+ mdev = NULL;
}

/* process initial MAPLE_COMMAND_DEVINFO for each device or port */
-static void maple_attach_driver(struct maple_device *dev)
+static void maple_attach_driver(struct maple_device *mdev)
{
- char *p;
-
- char *recvbuf;
+ char *p, *recvbuf;
unsigned long function;
int matched, retval;

- recvbuf = dev->mq->recvbuf;
- memcpy(&dev->devinfo, recvbuf + 4, sizeof(dev->devinfo));
- memcpy(dev->product_name, dev->devinfo.product_name, 30);
- memcpy(dev->product_licence, dev->devinfo.product_licence, 60);
- dev->product_name[30] = '\0';
- dev->product_licence[60] = '\0';
-
- for (p = dev->product_name + 29; dev->product_name <= p; p--)
+ recvbuf = mdev->mq->recvbuf;
+ /* copy the data as individual elements in
+ * case of memory optimisation */
+ memcpy(&mdev->devinfo.function, recvbuf + 4, 4);
+ memcpy(&mdev->devinfo.function_data[0], recvbuf + 8, 12);
+ memcpy(&mdev->devinfo.area_code, recvbuf + 20, 1);
+ memcpy(&mdev->devinfo.connector_direction, recvbuf + 21, 1);
+ memcpy(&mdev->devinfo.product_name[0], recvbuf + 22, 30);
+ memcpy(&mdev->devinfo.product_licence[0], recvbuf + 52, 60);
+ memcpy(&mdev->devinfo.standby_power, recvbuf + 112, 2);
+ memcpy(&mdev->devinfo.max_power, recvbuf + 114, 2);
+ memcpy(mdev->product_name, mdev->devinfo.product_name, 30);
+ mdev->product_name[30] = '\0';
+ memcpy(mdev->product_licence, mdev->devinfo.product_licence, 60);
+ mdev->product_licence[60] = '\0';
+
+ for (p = mdev->product_name + 29; mdev->product_name <= p; p--)
if (*p == ' ')
*p = '\0';
else
break;
-
- for (p = dev->product_licence + 59; dev->product_licence <= p; p--)
+ for (p = mdev->product_licence + 59; mdev->product_licence <= p; p--)
if (*p == ' ')
*p = '\0';
else
break;

- function = be32_to_cpu(dev->devinfo.function);
+ if (realscan) {
+ printk(KERN_INFO "Maple device detected: %s\n",
+ mdev->product_name);
+ printk(KERN_INFO "Maple device: %s\n", mdev->product_licence);
+ }
+
+ function = be32_to_cpu(mdev->devinfo.function);

if (function > 0x200) {
/* Do this silently - as not a real device */
function = 0;
- dev->driver = &maple_dummy_driver;
- sprintf(dev->dev.bus_id, "%d:0.port", dev->port);
+ mdev->driver = &maple_dummy_driver;
+ sprintf(mdev->dev.bus_id, "%d:0.port", mdev->port);
} else {
- printk(KERN_INFO
- "Maple bus at (%d, %d): Connected function 0x%lX\n",
- dev->port, dev->unit, function);
+ if (realscan)
+ printk(KERN_INFO
+ "Maple bus at (%d, %d): Function 0x%lX\n",
+ mdev->port, mdev->unit, function);

matched =
- bus_for_each_drv(&maple_bus_type, NULL, dev,
+ bus_for_each_drv(&maple_bus_type, NULL, mdev,
attach_matching_maple_driver);

if (matched == 0) {
/* Driver does not exist yet */
- printk(KERN_INFO
- "No maple driver found for this device\n");
- dev->driver = &maple_dummy_driver;
+ if (realscan)
+ printk(KERN_INFO
+ "No maple driver found.\n");
+ mdev->driver = &maple_dummy_driver;
}
-
- sprintf(dev->dev.bus_id, "%d:0%d.%lX", dev->port,
- dev->unit, function);
+ sprintf(mdev->dev.bus_id, "%d:0%d.%lX", mdev->port,
+ mdev->unit, function);
}
- dev->function = function;
- dev->dev.bus = &maple_bus_type;
- dev->dev.parent = &maple_bus;
- dev->dev.release = &maple_release_device;
- retval = device_register(&dev->dev);
+ mdev->function = function;
+ mdev->dev.release = &maple_release_device;
+ retval = device_register(&mdev->dev);
if (retval) {
printk(KERN_INFO
- "Maple bus: Attempt to register device (%x, %x) failed.\n",
- dev->port, dev->unit);
- maple_free_dev(dev);
+ "Maple bus: Attempt to register device"
+ " (%x, %x) failed.\n",
+ mdev->port, mdev->unit);
+ maple_free_dev(mdev);
+ mdev = NULL;
+ return;
}
- dev->registered = 1;
}

/*
@@ -518,7 +538,8 @@ static void maple_dma_handler(struct work_struct *work)

case MAPLE_RESPONSE_ALLINFO:
printk(KERN_DEBUG
- "Maple - extended device information not supported\n");
+ "Maple - extended device information"
+ " not supported\n");
break;

case MAPLE_RESPONSE_OK:
@@ -554,26 +575,16 @@ static irqreturn_t maplebus_vblank_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}

-static struct irqaction maple_dma_irq = {
- .name = "maple bus DMA handler",
- .handler = maplebus_dma_interrupt,
- .flags = IRQF_SHARED,
-};
-
-static struct irqaction maple_vblank_irq = {
- .name = "maple bus VBLANK handler",
- .handler = maplebus_vblank_interrupt,
- .flags = IRQF_SHARED,
-};
-
static int maple_set_dma_interrupt_handler(void)
{
- return setup_irq(HW_EVENT_MAPLE_DMA, &maple_dma_irq);
+ return request_irq(HW_EVENT_MAPLE_DMA, maplebus_dma_interrupt,
+ IRQF_SHARED, "maple bus DMA", &maple_dummy_driver);
}

static int maple_set_vblank_interrupt_handler(void)
{
- return setup_irq(HW_EVENT_VSYNC, &maple_vblank_irq);
+ return request_irq(HW_EVENT_VSYNC, maplebus_vblank_interrupt,
+ IRQF_SHARED, "maple bus VBLANK", &maple_dummy_driver);
}

static int maple_get_dma_buffer(void)
@@ -617,7 +628,7 @@ static struct maple_driver maple_dummy_driver = {
.drv = {
.name = "maple_dummy_driver",
.bus = &maple_bus_type,
- },
+ },
};

struct bus_type maple_bus_type = {
@@ -625,7 +636,6 @@ struct bus_type maple_bus_type = {
.match = match_maple_bus_driver,
.uevent = maple_bus_uevent,
};
-
EXPORT_SYMBOL_GPL(maple_bus_type);

static struct device maple_bus = {
@@ -677,7 +687,7 @@ static int __init maple_bus_init(void)

maple_queue_cache =
kmem_cache_create("maple_queue_cache", 0x400, 0,
- SLAB_HWCACHE_ALIGN, NULL);
+ SLAB_POISON|SLAB_HWCACHE_ALIGN, NULL);

if (!maple_queue_cache)
goto cleanup_bothirqs;
@@ -690,50 +700,48 @@ static int __init maple_bus_init(void)
maple_free_dev(mdev[i]);
goto cleanup_cache;
}
- mdev[i]->registered = 0;
mdev[i]->mq->command = MAPLE_COMMAND_DEVINFO;
mdev[i]->mq->length = 0;
- maple_attach_driver(mdev[i]);
maple_add_packet(mdev[i]->mq);
+ /* delay aids hardware detection */
+ udelay(20);
subdevice_map[i] = 0;
}

+ realscan = 1;
/* setup maplebus hardware */
maplebus_dma_reset();
-
/* initial detection */
maple_send();
-
maple_pnp_time = jiffies;
-
printk(KERN_INFO "Maple bus core now registered.\n");

return 0;

- cleanup_cache:
+cleanup_cache:
kmem_cache_destroy(maple_queue_cache);

- cleanup_bothirqs:
+cleanup_bothirqs:
free_irq(HW_EVENT_VSYNC, 0);

- cleanup_irq:
+cleanup_irq:
free_irq(HW_EVENT_MAPLE_DMA, 0);

- cleanup_dma:
+cleanup_dma:
free_pages((unsigned long) maple_sendbuf, MAPLE_DMA_PAGES);

- cleanup_basic:
+cleanup_basic:
driver_unregister(&maple_dummy_driver.drv);

- cleanup_bus:
+cleanup_bus:
bus_unregister(&maple_bus_type);

- cleanup_device:
+cleanup_device:
device_unregister(&maple_bus);

- cleanup:
+cleanup:
printk(KERN_INFO "Maple bus registration failed\n");
return retval;
}
-
-subsys_initcall(maple_bus_init);
+/* Push init to later to ensure hardware gets detected */
+fs_initcall(maple_bus_init);

2008-02-07 00:30:57

by Adrian McMenamin

[permalink] [raw]
Subject: [PATCH] - SH/Dreamcast - additional patch to maple.h

This patch removes the now unneeded registration check variable from
struct maple_device. (This patch assumes the include/linux/maple.h file
has already been patched for whitespace errors by
http://lkml.org/lkml/2008/2/6/327)

Signed-off by: Adrian McMenamin <[email protected]>


diff --git a/include/linux/maple.h b/include/linux/maple.h
index 1334062..3f01e2b 100644
--- a/include/linux/maple.h
+++ b/include/linux/maple.h
@@ -56,7 +56,6 @@ struct maple_device {
unsigned char port, unit;
char product_name[32];
char product_licence[64];
- int registered;
struct device dev;
};

2008-02-07 00:35:41

by Greg KH

[permalink] [raw]
Subject: Re: [PATCH 2/2] - SH/Dreamcast - fix maple bus bugs

On Wed, Feb 06, 2008 at 11:51:21PM +0000, Adrian McMenamin wrote:
> Replacement second-in-series patch:
>
> This patch fixes up memory leaks and, by delaying initialisation, makes
> device detection more robust.
>
> It also makes clearer the difference between struct maple_device and
> struct device, as well as cleaning up the interrupt request code
> (without changing its function in any way).
>
> Also now removes redundant registration checking.

Thanks for changing this.

greg k-h

2008-02-07 02:36:36

by Paul Mundt

[permalink] [raw]
Subject: Re: [PATCH 1/2] - SH/Dreamcast - fix maple bus bugs

On Wed, Feb 06, 2008 at 10:46:21PM +0000, Adrian McMenamin wrote:
> This patch is fundamentally about fixing up the whitespace problems introduced by my previous patch (that brought the code into mainline). A second patch will follow that will fix memory leaks. The two need to be applied sequentially.
>
Please do not linewrap, this ends up going directly in to the commit.

> Signed-off by: Adrian McMenamin <[email protected]>
>
Signed-off-by, please.

Also, please use a more helpful subject. Something like:
'maple: <short description of meaningful change>'. I've had to make
something up arbitrarily for this entire series based off of your
comments.

After some munging, git-am finally took it, so the series is now applied.