diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/firewire/core-card.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/firewire/core-card.c')
-rw-r--r-- | drivers/firewire/core-card.c | 104 |
1 files changed, 56 insertions, 48 deletions
diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index e4864e894e4f..5045156c5313 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c | |||
@@ -38,15 +38,14 @@ | |||
38 | 38 | ||
39 | #include "core.h" | 39 | #include "core.h" |
40 | 40 | ||
41 | int fw_compute_block_crc(u32 *block) | 41 | int fw_compute_block_crc(__be32 *block) |
42 | { | 42 | { |
43 | __be32 be32_block[256]; | 43 | int length; |
44 | int i, length; | 44 | u16 crc; |
45 | 45 | ||
46 | length = (*block >> 16) & 0xff; | 46 | length = (be32_to_cpu(block[0]) >> 16) & 0xff; |
47 | for (i = 0; i < length; i++) | 47 | crc = crc_itu_t(0, (u8 *)&block[1], length * 4); |
48 | be32_block[i] = cpu_to_be32(block[i + 1]); | 48 | *block |= cpu_to_be32(crc); |
49 | *block |= crc_itu_t(0, (u8 *) be32_block, length * 4); | ||
50 | 49 | ||
51 | return length; | 50 | return length; |
52 | } | 51 | } |
@@ -57,6 +56,10 @@ static LIST_HEAD(card_list); | |||
57 | static LIST_HEAD(descriptor_list); | 56 | static LIST_HEAD(descriptor_list); |
58 | static int descriptor_count; | 57 | static int descriptor_count; |
59 | 58 | ||
59 | static __be32 tmp_config_rom[256]; | ||
60 | /* ROM header, bus info block, root dir header, capabilities = 7 quadlets */ | ||
61 | static size_t config_rom_length = 1 + 4 + 1 + 1; | ||
62 | |||
60 | #define BIB_CRC(v) ((v) << 0) | 63 | #define BIB_CRC(v) ((v) << 0) |
61 | #define BIB_CRC_LENGTH(v) ((v) << 16) | 64 | #define BIB_CRC_LENGTH(v) ((v) << 16) |
62 | #define BIB_INFO_LENGTH(v) ((v) << 24) | 65 | #define BIB_INFO_LENGTH(v) ((v) << 24) |
@@ -72,11 +75,10 @@ static int descriptor_count; | |||
72 | #define BIB_CMC ((1) << 30) | 75 | #define BIB_CMC ((1) << 30) |
73 | #define BIB_IMC ((1) << 31) | 76 | #define BIB_IMC ((1) << 31) |
74 | 77 | ||
75 | static u32 *generate_config_rom(struct fw_card *card, size_t *config_rom_length) | 78 | static void generate_config_rom(struct fw_card *card, __be32 *config_rom) |
76 | { | 79 | { |
77 | struct fw_descriptor *desc; | 80 | struct fw_descriptor *desc; |
78 | static u32 config_rom[256]; | 81 | int i, j, k, length; |
79 | int i, j, length; | ||
80 | 82 | ||
81 | /* | 83 | /* |
82 | * Initialize contents of config rom buffer. On the OHCI | 84 | * Initialize contents of config rom buffer. On the OHCI |
@@ -87,40 +89,39 @@ static u32 *generate_config_rom(struct fw_card *card, size_t *config_rom_length) | |||
87 | * the version stored in the OHCI registers. | 89 | * the version stored in the OHCI registers. |
88 | */ | 90 | */ |
89 | 91 | ||
90 | memset(config_rom, 0, sizeof(config_rom)); | 92 | config_rom[0] = cpu_to_be32( |
91 | config_rom[0] = BIB_CRC_LENGTH(4) | BIB_INFO_LENGTH(4) | BIB_CRC(0); | 93 | BIB_CRC_LENGTH(4) | BIB_INFO_LENGTH(4) | BIB_CRC(0)); |
92 | config_rom[1] = 0x31333934; | 94 | config_rom[1] = cpu_to_be32(0x31333934); |
93 | 95 | config_rom[2] = cpu_to_be32( | |
94 | config_rom[2] = | ||
95 | BIB_LINK_SPEED(card->link_speed) | | 96 | BIB_LINK_SPEED(card->link_speed) | |
96 | BIB_GENERATION(card->config_rom_generation++ % 14 + 2) | | 97 | BIB_GENERATION(card->config_rom_generation++ % 14 + 2) | |
97 | BIB_MAX_ROM(2) | | 98 | BIB_MAX_ROM(2) | |
98 | BIB_MAX_RECEIVE(card->max_receive) | | 99 | BIB_MAX_RECEIVE(card->max_receive) | |
99 | BIB_BMC | BIB_ISC | BIB_CMC | BIB_IMC; | 100 | BIB_BMC | BIB_ISC | BIB_CMC | BIB_IMC); |
100 | config_rom[3] = card->guid >> 32; | 101 | config_rom[3] = cpu_to_be32(card->guid >> 32); |
101 | config_rom[4] = card->guid; | 102 | config_rom[4] = cpu_to_be32(card->guid); |
102 | 103 | ||
103 | /* Generate root directory. */ | 104 | /* Generate root directory. */ |
104 | i = 5; | 105 | config_rom[6] = cpu_to_be32(0x0c0083c0); /* node capabilities */ |
105 | config_rom[i++] = 0; | 106 | i = 7; |
106 | config_rom[i++] = 0x0c0083c0; /* node capabilities */ | 107 | j = 7 + descriptor_count; |
107 | j = i + descriptor_count; | ||
108 | 108 | ||
109 | /* Generate root directory entries for descriptors. */ | 109 | /* Generate root directory entries for descriptors. */ |
110 | list_for_each_entry (desc, &descriptor_list, link) { | 110 | list_for_each_entry (desc, &descriptor_list, link) { |
111 | if (desc->immediate > 0) | 111 | if (desc->immediate > 0) |
112 | config_rom[i++] = desc->immediate; | 112 | config_rom[i++] = cpu_to_be32(desc->immediate); |
113 | config_rom[i] = desc->key | (j - i); | 113 | config_rom[i] = cpu_to_be32(desc->key | (j - i)); |
114 | i++; | 114 | i++; |
115 | j += desc->length; | 115 | j += desc->length; |
116 | } | 116 | } |
117 | 117 | ||
118 | /* Update root directory length. */ | 118 | /* Update root directory length. */ |
119 | config_rom[5] = (i - 5 - 1) << 16; | 119 | config_rom[5] = cpu_to_be32((i - 5 - 1) << 16); |
120 | 120 | ||
121 | /* End of root directory, now copy in descriptors. */ | 121 | /* End of root directory, now copy in descriptors. */ |
122 | list_for_each_entry (desc, &descriptor_list, link) { | 122 | list_for_each_entry (desc, &descriptor_list, link) { |
123 | memcpy(&config_rom[i], desc->data, desc->length * 4); | 123 | for (k = 0; k < desc->length; k++) |
124 | config_rom[i + k] = cpu_to_be32(desc->data[k]); | ||
124 | i += desc->length; | 125 | i += desc->length; |
125 | } | 126 | } |
126 | 127 | ||
@@ -131,26 +132,30 @@ static u32 *generate_config_rom(struct fw_card *card, size_t *config_rom_length) | |||
131 | for (i = 0; i < j; i += length + 1) | 132 | for (i = 0; i < j; i += length + 1) |
132 | length = fw_compute_block_crc(config_rom + i); | 133 | length = fw_compute_block_crc(config_rom + i); |
133 | 134 | ||
134 | *config_rom_length = j; | 135 | WARN_ON(j != config_rom_length); |
135 | |||
136 | return config_rom; | ||
137 | } | 136 | } |
138 | 137 | ||
139 | static void update_config_roms(void) | 138 | static void update_config_roms(void) |
140 | { | 139 | { |
141 | struct fw_card *card; | 140 | struct fw_card *card; |
142 | u32 *config_rom; | ||
143 | size_t length; | ||
144 | 141 | ||
145 | list_for_each_entry (card, &card_list, link) { | 142 | list_for_each_entry (card, &card_list, link) { |
146 | config_rom = generate_config_rom(card, &length); | 143 | generate_config_rom(card, tmp_config_rom); |
147 | card->driver->set_config_rom(card, config_rom, length); | 144 | card->driver->set_config_rom(card, tmp_config_rom, |
145 | config_rom_length); | ||
148 | } | 146 | } |
149 | } | 147 | } |
150 | 148 | ||
149 | static size_t required_space(struct fw_descriptor *desc) | ||
150 | { | ||
151 | /* descriptor + entry into root dir + optional immediate entry */ | ||
152 | return desc->length + 1 + (desc->immediate > 0 ? 1 : 0); | ||
153 | } | ||
154 | |||
151 | int fw_core_add_descriptor(struct fw_descriptor *desc) | 155 | int fw_core_add_descriptor(struct fw_descriptor *desc) |
152 | { | 156 | { |
153 | size_t i; | 157 | size_t i; |
158 | int ret; | ||
154 | 159 | ||
155 | /* | 160 | /* |
156 | * Check descriptor is valid; the length of all blocks in the | 161 | * Check descriptor is valid; the length of all blocks in the |
@@ -166,15 +171,21 @@ int fw_core_add_descriptor(struct fw_descriptor *desc) | |||
166 | 171 | ||
167 | mutex_lock(&card_mutex); | 172 | mutex_lock(&card_mutex); |
168 | 173 | ||
169 | list_add_tail(&desc->link, &descriptor_list); | 174 | if (config_rom_length + required_space(desc) > 256) { |
170 | descriptor_count++; | 175 | ret = -EBUSY; |
171 | if (desc->immediate > 0) | 176 | } else { |
177 | list_add_tail(&desc->link, &descriptor_list); | ||
178 | config_rom_length += required_space(desc); | ||
172 | descriptor_count++; | 179 | descriptor_count++; |
173 | update_config_roms(); | 180 | if (desc->immediate > 0) |
181 | descriptor_count++; | ||
182 | update_config_roms(); | ||
183 | ret = 0; | ||
184 | } | ||
174 | 185 | ||
175 | mutex_unlock(&card_mutex); | 186 | mutex_unlock(&card_mutex); |
176 | 187 | ||
177 | return 0; | 188 | return ret; |
178 | } | 189 | } |
179 | EXPORT_SYMBOL(fw_core_add_descriptor); | 190 | EXPORT_SYMBOL(fw_core_add_descriptor); |
180 | 191 | ||
@@ -183,6 +194,7 @@ void fw_core_remove_descriptor(struct fw_descriptor *desc) | |||
183 | mutex_lock(&card_mutex); | 194 | mutex_lock(&card_mutex); |
184 | 195 | ||
185 | list_del(&desc->link); | 196 | list_del(&desc->link); |
197 | config_rom_length -= required_space(desc); | ||
186 | descriptor_count--; | 198 | descriptor_count--; |
187 | if (desc->immediate > 0) | 199 | if (desc->immediate > 0) |
188 | descriptor_count--; | 200 | descriptor_count--; |
@@ -211,11 +223,8 @@ static const char gap_count_table[] = { | |||
211 | 223 | ||
212 | void fw_schedule_bm_work(struct fw_card *card, unsigned long delay) | 224 | void fw_schedule_bm_work(struct fw_card *card, unsigned long delay) |
213 | { | 225 | { |
214 | int scheduled; | ||
215 | |||
216 | fw_card_get(card); | 226 | fw_card_get(card); |
217 | scheduled = schedule_delayed_work(&card->work, delay); | 227 | if (!schedule_delayed_work(&card->work, delay)) |
218 | if (!scheduled) | ||
219 | fw_card_put(card); | 228 | fw_card_put(card); |
220 | } | 229 | } |
221 | 230 | ||
@@ -435,8 +444,6 @@ EXPORT_SYMBOL(fw_card_initialize); | |||
435 | int fw_card_add(struct fw_card *card, | 444 | int fw_card_add(struct fw_card *card, |
436 | u32 max_receive, u32 link_speed, u64 guid) | 445 | u32 max_receive, u32 link_speed, u64 guid) |
437 | { | 446 | { |
438 | u32 *config_rom; | ||
439 | size_t length; | ||
440 | int ret; | 447 | int ret; |
441 | 448 | ||
442 | card->max_receive = max_receive; | 449 | card->max_receive = max_receive; |
@@ -445,8 +452,8 @@ int fw_card_add(struct fw_card *card, | |||
445 | 452 | ||
446 | mutex_lock(&card_mutex); | 453 | mutex_lock(&card_mutex); |
447 | 454 | ||
448 | config_rom = generate_config_rom(card, &length); | 455 | generate_config_rom(card, tmp_config_rom); |
449 | ret = card->driver->enable(card, config_rom, length); | 456 | ret = card->driver->enable(card, tmp_config_rom, config_rom_length); |
450 | if (ret == 0) | 457 | if (ret == 0) |
451 | list_add_tail(&card->link, &card_list); | 458 | list_add_tail(&card->link, &card_list); |
452 | 459 | ||
@@ -465,7 +472,8 @@ EXPORT_SYMBOL(fw_card_add); | |||
465 | * shutdown still need to be provided by the card driver. | 472 | * shutdown still need to be provided by the card driver. |
466 | */ | 473 | */ |
467 | 474 | ||
468 | static int dummy_enable(struct fw_card *card, u32 *config_rom, size_t length) | 475 | static int dummy_enable(struct fw_card *card, |
476 | const __be32 *config_rom, size_t length) | ||
469 | { | 477 | { |
470 | BUG(); | 478 | BUG(); |
471 | return -1; | 479 | return -1; |
@@ -478,7 +486,7 @@ static int dummy_update_phy_reg(struct fw_card *card, int address, | |||
478 | } | 486 | } |
479 | 487 | ||
480 | static int dummy_set_config_rom(struct fw_card *card, | 488 | static int dummy_set_config_rom(struct fw_card *card, |
481 | u32 *config_rom, size_t length) | 489 | const __be32 *config_rom, size_t length) |
482 | { | 490 | { |
483 | /* | 491 | /* |
484 | * We take the card out of card_list before setting the dummy | 492 | * We take the card out of card_list before setting the dummy |