firewire: core: do not DMA-map stack addresses

The DMA mapping API cannot map on-stack addresses, as explained in
Documentation/DMA-mapping.txt. Convert the two cases of on-stack packet
payload buffers in firewire-core (payload of lock requests in the bus
manager work and in iso resource management) to slab-allocated memory.

There are a number on-stack buffers for quadlet write or quadlet read
requests in firewire-core and firewire-sbp2. These are harmless; they
are copied to/ from card driver internal DMA buffers since quadlet
payloads are inlined with packet headers.

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>

+26 -20
+7 -7
drivers/firewire/core-card.c
··· 196 196 { 197 197 int channel, bandwidth = 0; 198 198 199 - fw_iso_resource_manage(card, generation, 1ULL << 31, 200 - &channel, &bandwidth, true); 199 + fw_iso_resource_manage(card, generation, 1ULL << 31, &channel, 200 + &bandwidth, true, card->bm_transaction_data); 201 201 if (channel == 31) { 202 202 card->broadcast_channel_allocated = true; 203 203 device_for_each_child(card->device, (void *)(long)generation, ··· 230 230 bool do_reset = false; 231 231 bool root_device_is_running; 232 232 bool root_device_is_cmc; 233 - __be32 lock_data[2]; 234 233 235 234 spin_lock_irqsave(&card->lock, flags); 236 235 ··· 272 273 goto pick_me; 273 274 } 274 275 275 - lock_data[0] = cpu_to_be32(0x3f); 276 - lock_data[1] = cpu_to_be32(local_id); 276 + card->bm_transaction_data[0] = cpu_to_be32(0x3f); 277 + card->bm_transaction_data[1] = cpu_to_be32(local_id); 277 278 278 279 spin_unlock_irqrestore(&card->lock, flags); 279 280 280 281 rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP, 281 282 irm_id, generation, SCODE_100, 282 283 CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID, 283 - lock_data, sizeof(lock_data)); 284 + card->bm_transaction_data, 285 + sizeof(card->bm_transaction_data)); 284 286 285 287 if (rcode == RCODE_GENERATION) 286 288 /* Another bus reset, BM work has been rescheduled. */ 287 289 goto out; 288 290 289 291 if (rcode == RCODE_COMPLETE && 290 - lock_data[0] != cpu_to_be32(0x3f)) { 292 + card->bm_transaction_data[0] != cpu_to_be32(0x3f)) { 291 293 292 294 /* Somebody else is BM. Only act as IRM. */ 293 295 if (local_id == irm_id)
+3 -1
drivers/firewire/core-cdev.c
··· 125 125 int generation; 126 126 u64 channels; 127 127 s32 bandwidth; 128 + __be32 transaction_data[2]; 128 129 struct iso_resource_event *e_alloc, *e_dealloc; 129 130 }; 130 131 ··· 1050 1049 r->channels, &channel, &bandwidth, 1051 1050 todo == ISO_RES_ALLOC || 1052 1051 todo == ISO_RES_REALLOC || 1053 - todo == ISO_RES_ALLOC_ONCE); 1052 + todo == ISO_RES_ALLOC_ONCE, 1053 + r->transaction_data); 1054 1054 /* 1055 1055 * Is this generation outdated already? As long as this resource sticks 1056 1056 * in the idr, it will be scheduled again for a newer generation or at
+13 -11
drivers/firewire/core-iso.c
··· 177 177 */ 178 178 179 179 static int manage_bandwidth(struct fw_card *card, int irm_id, int generation, 180 - int bandwidth, bool allocate) 180 + int bandwidth, bool allocate, __be32 data[2]) 181 181 { 182 - __be32 data[2]; 183 182 int try, new, old = allocate ? BANDWIDTH_AVAILABLE_INITIAL : 0; 184 183 185 184 /* ··· 214 215 } 215 216 216 217 static int manage_channel(struct fw_card *card, int irm_id, int generation, 217 - u32 channels_mask, u64 offset, bool allocate) 218 + u32 channels_mask, u64 offset, bool allocate, __be32 data[2]) 218 219 { 219 - __be32 data[2], c, all, old; 220 + __be32 c, all, old; 220 221 int i, retry = 5; 221 222 222 223 old = all = allocate ? cpu_to_be32(~0) : 0; ··· 259 260 } 260 261 261 262 static void deallocate_channel(struct fw_card *card, int irm_id, 262 - int generation, int channel) 263 + int generation, int channel, __be32 buffer[2]) 263 264 { 264 265 u32 mask; 265 266 u64 offset; ··· 268 269 offset = channel < 32 ? CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI : 269 270 CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO; 270 271 271 - manage_channel(card, irm_id, generation, mask, offset, false); 272 + manage_channel(card, irm_id, generation, mask, offset, false, buffer); 272 273 } 273 274 274 275 /** ··· 297 298 */ 298 299 void fw_iso_resource_manage(struct fw_card *card, int generation, 299 300 u64 channels_mask, int *channel, int *bandwidth, 300 - bool allocate) 301 + bool allocate, __be32 buffer[2]) 301 302 { 302 303 u32 channels_hi = channels_mask; /* channels 31...0 */ 303 304 u32 channels_lo = channels_mask >> 32; /* channels 63...32 */ ··· 309 310 310 311 if (channels_hi) 311 312 c = manage_channel(card, irm_id, generation, channels_hi, 312 - CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI, allocate); 313 + CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI, 314 + allocate, buffer); 313 315 if (channels_lo && c < 0) { 314 316 c = manage_channel(card, irm_id, generation, channels_lo, 315 - CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO, allocate); 317 + CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO, 318 + allocate, buffer); 316 319 if (c >= 0) 317 320 c += 32; 318 321 } ··· 326 325 if (*bandwidth == 0) 327 326 return; 328 327 329 - ret = manage_bandwidth(card, irm_id, generation, *bandwidth, allocate); 328 + ret = manage_bandwidth(card, irm_id, generation, *bandwidth, 329 + allocate, buffer); 330 330 if (ret < 0) 331 331 *bandwidth = 0; 332 332 333 333 if (allocate && ret < 0 && c >= 0) { 334 - deallocate_channel(card, irm_id, generation, c); 334 + deallocate_channel(card, irm_id, generation, c, buffer); 335 335 *channel = ret; 336 336 } 337 337 }
+2 -1
drivers/firewire/core.h
··· 120 120 121 121 int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma); 122 122 void fw_iso_resource_manage(struct fw_card *card, int generation, 123 - u64 channels_mask, int *channel, int *bandwidth, bool allocate); 123 + u64 channels_mask, int *channel, int *bandwidth, 124 + bool allocate, __be32 buffer[2]); 124 125 125 126 126 127 /* -topology */
+1
include/linux/firewire.h
··· 127 127 struct delayed_work work; 128 128 int bm_retries; 129 129 int bm_generation; 130 + __be32 bm_transaction_data[2]; 130 131 131 132 bool broadcast_channel_allocated; 132 133 u32 broadcast_channel;