ieee1394: fix list corruption (reported at module removal)

If there is more than one FireWire controller present, dummy_zero_addr
and dummy_max_addr were added multiple times to different lists, thus
corrupting the lists.  Fix this by allocating them dynamically per host
instead of just once globally.

(Perhaps a better address space allocation algorithm could rid us of the
two dummy address spaces.)

Fixes http://bugzilla.kernel.org/show_bug.cgi?id=10129 .

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
This commit is contained in:
Stefan Richter 2008-11-26 01:34:25 +01:00
parent 031bb27c4b
commit e47c1feb17
2 changed files with 16 additions and 13 deletions

View File

@ -46,10 +46,6 @@ static DEFINE_RWLOCK(hl_irqs_lock);
static DEFINE_RWLOCK(addr_space_lock); static DEFINE_RWLOCK(addr_space_lock);
/* addr_space list will have zero and max already included as bounds */
static struct hpsb_address_ops dummy_ops = { NULL, NULL, NULL, NULL };
static struct hpsb_address_serve dummy_zero_addr, dummy_max_addr;
static struct hl_host_info *hl_get_hostinfo(struct hpsb_highlevel *hl, static struct hl_host_info *hl_get_hostinfo(struct hpsb_highlevel *hl,
struct hpsb_host *host) struct hpsb_host *host)
@ -481,20 +477,23 @@ int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
return retval; return retval;
} }
static struct hpsb_address_ops dummy_ops;
/* dummy address spaces as lower and upper bounds of the host's a.s. list */
static void init_hpsb_highlevel(struct hpsb_host *host) static void init_hpsb_highlevel(struct hpsb_host *host)
{ {
INIT_LIST_HEAD(&dummy_zero_addr.host_list); INIT_LIST_HEAD(&host->dummy_zero_addr.host_list);
INIT_LIST_HEAD(&dummy_zero_addr.hl_list); INIT_LIST_HEAD(&host->dummy_zero_addr.hl_list);
INIT_LIST_HEAD(&dummy_max_addr.host_list); INIT_LIST_HEAD(&host->dummy_max_addr.host_list);
INIT_LIST_HEAD(&dummy_max_addr.hl_list); INIT_LIST_HEAD(&host->dummy_max_addr.hl_list);
dummy_zero_addr.op = dummy_max_addr.op = &dummy_ops; host->dummy_zero_addr.op = host->dummy_max_addr.op = &dummy_ops;
dummy_zero_addr.start = dummy_zero_addr.end = 0; host->dummy_zero_addr.start = host->dummy_zero_addr.end = 0;
dummy_max_addr.start = dummy_max_addr.end = ((u64) 1) << 48; host->dummy_max_addr.start = host->dummy_max_addr.end = ((u64) 1) << 48;
list_add_tail(&dummy_zero_addr.host_list, &host->addr_space); list_add_tail(&host->dummy_zero_addr.host_list, &host->addr_space);
list_add_tail(&dummy_max_addr.host_list, &host->addr_space); list_add_tail(&host->dummy_max_addr.host_list, &host->addr_space);
} }
void highlevel_add_host(struct hpsb_host *host) void highlevel_add_host(struct hpsb_host *host)

View File

@ -13,6 +13,7 @@ struct module;
#include "ieee1394_types.h" #include "ieee1394_types.h"
#include "csr.h" #include "csr.h"
#include "highlevel.h"
struct hpsb_packet; struct hpsb_packet;
struct hpsb_iso; struct hpsb_iso;
@ -72,6 +73,9 @@ struct hpsb_host {
struct { DECLARE_BITMAP(map, 64); } tl_pool[ALL_NODES]; struct { DECLARE_BITMAP(map, 64); } tl_pool[ALL_NODES];
struct csr_control csr; struct csr_control csr;
struct hpsb_address_serve dummy_zero_addr;
struct hpsb_address_serve dummy_max_addr;
}; };
enum devctl_cmd { enum devctl_cmd {