Commit 26a3e565 authored by Ben Collins's avatar Ben Collins

ieee1394: CSR1212 Extended ROM bug fixes

  - Use vmalloc instead of kmalloc
  - Change delayed_reset_bus() to operate in a work_queue instead of a timer
    interrupt.
  - Fix hpsb_allocate_and_register_addrspace() to not allocate space on top
    of already allocated space.
  - Fix problems in csr1212.c filling ConfigROM images when extend ROMs are
    present.
Signed-off-by: default avatarSteve Kinneberg <kberg@linux1394.org>
Signed-off-by: default avatarBen Collins <bcollins@debian.org>
parent bd8f3917
......@@ -1061,6 +1061,10 @@ void csr1212_fill_cache(struct csr1212_csr_rom_cache *cache)
}
nkv = kv->next;
if (kv->prev)
kv->prev->next = NULL;
if (kv->next)
kv->next->prev = NULL;
kv->prev = NULL;
kv->next = NULL;
}
......@@ -1134,7 +1138,7 @@ int csr1212_generate_csr_image(struct csr1212_csr *csr)
/* Make sure the Extended ROM leaf is a multiple of
* max_rom in size. */
leaf_size = (cache->len + (csr->max_rom - 1)) &
(csr->max_rom - 1);
~(csr->max_rom - 1);
/* Zero out the unused ROM region */
memset(cache->data + bytes_to_quads(cache->len), 0x00,
......
......@@ -38,9 +38,11 @@
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/vmalloc.h>
#include <asm/pgalloc.h>
#define CSR1212_MALLOC(size) kmalloc((size), in_interrupt() ? GFP_ATOMIC : GFP_KERNEL)
#define CSR1212_FREE(ptr) kfree(ptr)
#define CSR1212_MALLOC(size) vmalloc((size))
#define CSR1212_FREE(ptr) vfree(ptr)
#define CSR1212_BE16_TO_CPU(quad) be16_to_cpu(quad)
#define CSR1212_CPU_TO_BE16(quad) cpu_to_be16(quad)
#define CSR1212_BE32_TO_CPU(quad) be32_to_cpu(quad)
......
......@@ -383,7 +383,7 @@ u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl,
a2sa = a2->start & align_mask;
a2ea = (a2->end + alignment -1) & align_mask;
if ((a2sa - a1ea >= size) && (a2sa - start >= size) && (end - a1ea >= size)) {
if ((a2sa - a1ea >= size) && (a2sa - start >= size) && (a2sa > start)) {
as->start = max(start, a1ea);
as->end = as->start + size;
list_add(&as->host_list, entry);
......
......@@ -30,7 +30,7 @@
#include "config_roms.h"
static void delayed_reset_bus(unsigned long __reset_info)
static void delayed_reset_bus(void * __reset_info)
{
struct hpsb_host *host = (struct hpsb_host*)__reset_info;
int generation = host->csr.generation + 1;
......@@ -129,9 +129,6 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
skb_queue_head_init(&h->pending_packet_queue);
INIT_LIST_HEAD(&h->addr_space);
init_timer(&h->delayed_reset);
h->delayed_reset.function = delayed_reset_bus;
h->delayed_reset.data = (unsigned long)h;
for (i = 2; i < 16; i++)
h->csr.gen_timestamp[i] = jiffies - 60 * HZ;
......@@ -140,6 +137,8 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
atomic_set(&h->generation, 0);
INIT_WORK(&h->delayed_reset, delayed_reset_bus, h);
init_timer(&h->timeout);
h->timeout.data = (unsigned long) h;
h->timeout.function = abort_timedouts;
......@@ -188,7 +187,8 @@ void hpsb_remove_host(struct hpsb_host *host)
{
host->is_shutdown = 1;
del_timer_sync(&host->delayed_reset);
cancel_delayed_work(&host->delayed_reset);
flush_scheduled_work();
host->driver = &dummy_driver;
......@@ -202,7 +202,7 @@ void hpsb_remove_host(struct hpsb_host *host)
int hpsb_update_config_rom_image(struct hpsb_host *host)
{
unsigned long reset_time;
unsigned long reset_delay;
int next_gen = host->csr.generation + 1;
if (!host->update_config_rom)
......@@ -213,21 +213,21 @@ int hpsb_update_config_rom_image(struct hpsb_host *host)
/* Stop the delayed interrupt, we're about to change the config rom and
* it would be a waste to do a bus reset twice. */
del_timer_sync(&host->delayed_reset);
cancel_delayed_work(&host->delayed_reset);
/* IEEE 1394a-2000 prohibits using the same generation number
* twice in a 60 second period. */
if (jiffies - host->csr.gen_timestamp[next_gen] < 60 * HZ)
/* Wait 60 seconds from the last time this generation number was
* used. */
reset_time = (60 * HZ) + host->csr.gen_timestamp[next_gen];
reset_delay = (60 * HZ) + host->csr.gen_timestamp[next_gen] - jiffies;
else
/* Wait 1 second in case some other code wants to change the
* Config ROM in the near future. */
reset_time = jiffies + HZ;
reset_delay = HZ;
/* This will add the timer as well as modify it */
mod_timer(&host->delayed_reset, reset_time);
PREPARE_WORK(&host->delayed_reset, delayed_reset_bus, host);
schedule_delayed_work(&host->delayed_reset, reset_delay);
return 0;
}
......@@ -66,7 +66,7 @@ struct hpsb_host {
struct class_device class_dev;
int update_config_rom;
struct timer_list delayed_reset;
struct work_struct delayed_reset;
unsigned int config_roms;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment