aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ieee1394/highlevel.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ieee1394/highlevel.c')
-rw-r--r--drivers/ieee1394/highlevel.c415
1 files changed, 182 insertions, 233 deletions
diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c
index d255d407e064..25b22609e793 100644
--- a/drivers/ieee1394/highlevel.c
+++ b/drivers/ieee1394/highlevel.c
@@ -53,7 +53,7 @@ static struct hpsb_address_serve dummy_zero_addr, dummy_max_addr;
53 53
54 54
55static struct hl_host_info *hl_get_hostinfo(struct hpsb_highlevel *hl, 55static struct hl_host_info *hl_get_hostinfo(struct hpsb_highlevel *hl,
56 struct hpsb_host *host) 56 struct hpsb_host *host)
57{ 57{
58 struct hl_host_info *hi = NULL; 58 struct hl_host_info *hi = NULL;
59 59
@@ -68,24 +68,18 @@ static struct hl_host_info *hl_get_hostinfo(struct hpsb_highlevel *hl,
68 } 68 }
69 } 69 }
70 read_unlock(&hl->host_info_lock); 70 read_unlock(&hl->host_info_lock);
71
72 return NULL; 71 return NULL;
73} 72}
74 73
75
76/* Returns a per host/driver data structure that was previously stored by 74/* Returns a per host/driver data structure that was previously stored by
77 * hpsb_create_hostinfo. */ 75 * hpsb_create_hostinfo. */
78void *hpsb_get_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host) 76void *hpsb_get_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host)
79{ 77{
80 struct hl_host_info *hi = hl_get_hostinfo(hl, host); 78 struct hl_host_info *hi = hl_get_hostinfo(hl, host);
81 79
82 if (hi) 80 return hi ? hi->data : NULL;
83 return hi->data;
84
85 return NULL;
86} 81}
87 82
88
89/* If size is zero, then the return here is only valid for error checking */ 83/* If size is zero, then the return here is only valid for error checking */
90void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host, 84void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
91 size_t data_size) 85 size_t data_size)
@@ -96,8 +90,8 @@ void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
96 90
97 hi = hl_get_hostinfo(hl, host); 91 hi = hl_get_hostinfo(hl, host);
98 if (hi) { 92 if (hi) {
99 HPSB_ERR("%s called hpsb_create_hostinfo when hostinfo already exists", 93 HPSB_ERR("%s called hpsb_create_hostinfo when hostinfo already"
100 hl->name); 94 " exists", hl->name);
101 return NULL; 95 return NULL;
102 } 96 }
103 97
@@ -120,7 +114,6 @@ void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
120 return data; 114 return data;
121} 115}
122 116
123
124int hpsb_set_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host, 117int hpsb_set_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
125 void *data) 118 void *data)
126{ 119{
@@ -132,16 +125,14 @@ int hpsb_set_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
132 hi->data = data; 125 hi->data = data;
133 return 0; 126 return 0;
134 } else 127 } else
135 HPSB_ERR("%s called hpsb_set_hostinfo when hostinfo already has data", 128 HPSB_ERR("%s called hpsb_set_hostinfo when hostinfo "
136 hl->name); 129 "already has data", hl->name);
137 } else 130 } else
138 HPSB_ERR("%s called hpsb_set_hostinfo when no hostinfo exists", 131 HPSB_ERR("%s called hpsb_set_hostinfo when no hostinfo exists",
139 hl->name); 132 hl->name);
140
141 return -EINVAL; 133 return -EINVAL;
142} 134}
143 135
144
145void hpsb_destroy_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host) 136void hpsb_destroy_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host)
146{ 137{
147 struct hl_host_info *hi; 138 struct hl_host_info *hi;
@@ -154,23 +145,20 @@ void hpsb_destroy_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host)
154 write_unlock_irqrestore(&hl->host_info_lock, flags); 145 write_unlock_irqrestore(&hl->host_info_lock, flags);
155 kfree(hi); 146 kfree(hi);
156 } 147 }
157
158 return; 148 return;
159} 149}
160 150
161 151void hpsb_set_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host,
162void hpsb_set_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host, unsigned long key) 152 unsigned long key)
163{ 153{
164 struct hl_host_info *hi; 154 struct hl_host_info *hi;
165 155
166 hi = hl_get_hostinfo(hl, host); 156 hi = hl_get_hostinfo(hl, host);
167 if (hi) 157 if (hi)
168 hi->key = key; 158 hi->key = key;
169
170 return; 159 return;
171} 160}
172 161
173
174void *hpsb_get_hostinfo_bykey(struct hpsb_highlevel *hl, unsigned long key) 162void *hpsb_get_hostinfo_bykey(struct hpsb_highlevel *hl, unsigned long key)
175{ 163{
176 struct hl_host_info *hi; 164 struct hl_host_info *hi;
@@ -187,24 +175,18 @@ void *hpsb_get_hostinfo_bykey(struct hpsb_highlevel *hl, unsigned long key)
187 } 175 }
188 } 176 }
189 read_unlock(&hl->host_info_lock); 177 read_unlock(&hl->host_info_lock);
190
191 return data; 178 return data;
192} 179}
193 180
194
195static int highlevel_for_each_host_reg(struct hpsb_host *host, void *__data) 181static int highlevel_for_each_host_reg(struct hpsb_host *host, void *__data)
196{ 182{
197 struct hpsb_highlevel *hl = __data; 183 struct hpsb_highlevel *hl = __data;
198 184
199 hl->add_host(host); 185 hl->add_host(host);
200 186
201 if (host->update_config_rom) { 187 if (host->update_config_rom && hpsb_update_config_rom_image(host) < 0)
202 if (hpsb_update_config_rom_image(host) < 0) { 188 HPSB_ERR("Failed to generate Configuration ROM image for host "
203 HPSB_ERR("Failed to generate Configuration ROM image for host " 189 "%s-%d", hl->name, host->id);
204 "%s-%d", hl->name, host->id);
205 }
206 }
207
208 return 0; 190 return 0;
209} 191}
210 192
@@ -212,13 +194,13 @@ void hpsb_register_highlevel(struct hpsb_highlevel *hl)
212{ 194{
213 unsigned long flags; 195 unsigned long flags;
214 196
215 INIT_LIST_HEAD(&hl->addr_list); 197 INIT_LIST_HEAD(&hl->addr_list);
216 INIT_LIST_HEAD(&hl->host_info_list); 198 INIT_LIST_HEAD(&hl->host_info_list);
217 199
218 rwlock_init(&hl->host_info_lock); 200 rwlock_init(&hl->host_info_lock);
219 201
220 down_write(&hl_drivers_sem); 202 down_write(&hl_drivers_sem);
221 list_add_tail(&hl->hl_list, &hl_drivers); 203 list_add_tail(&hl->hl_list, &hl_drivers);
222 up_write(&hl_drivers_sem); 204 up_write(&hl_drivers_sem);
223 205
224 write_lock_irqsave(&hl_irqs_lock, flags); 206 write_lock_irqsave(&hl_irqs_lock, flags);
@@ -227,8 +209,7 @@ void hpsb_register_highlevel(struct hpsb_highlevel *hl)
227 209
228 if (hl->add_host) 210 if (hl->add_host)
229 nodemgr_for_each_host(hl, highlevel_for_each_host_reg); 211 nodemgr_for_each_host(hl, highlevel_for_each_host_reg);
230 212 return;
231 return;
232} 213}
233 214
234static void __delete_addr(struct hpsb_address_serve *as) 215static void __delete_addr(struct hpsb_address_serve *as)
@@ -238,7 +219,8 @@ static void __delete_addr(struct hpsb_address_serve *as)
238 kfree(as); 219 kfree(as);
239} 220}
240 221
241static void __unregister_host(struct hpsb_highlevel *hl, struct hpsb_host *host, int update_cr) 222static void __unregister_host(struct hpsb_highlevel *hl, struct hpsb_host *host,
223 int update_cr)
242{ 224{
243 unsigned long flags; 225 unsigned long flags;
244 struct list_head *lh, *next; 226 struct list_head *lh, *next;
@@ -253,7 +235,6 @@ static void __unregister_host(struct hpsb_highlevel *hl, struct hpsb_host *host,
253 write_lock_irqsave(&addr_space_lock, flags); 235 write_lock_irqsave(&addr_space_lock, flags);
254 list_for_each_safe (lh, next, &hl->addr_list) { 236 list_for_each_safe (lh, next, &hl->addr_list) {
255 as = list_entry(lh, struct hpsb_address_serve, hl_list); 237 as = list_entry(lh, struct hpsb_address_serve, hl_list);
256
257 if (as->host == host) 238 if (as->host == host)
258 __delete_addr(as); 239 __delete_addr(as);
259 } 240 }
@@ -261,15 +242,12 @@ static void __unregister_host(struct hpsb_highlevel *hl, struct hpsb_host *host,
261 242
262 /* Now update the config-rom to reflect anything removed by the 243 /* Now update the config-rom to reflect anything removed by the
263 * highlevel driver. */ 244 * highlevel driver. */
264 if (update_cr && host->update_config_rom) { 245 if (update_cr && host->update_config_rom &&
265 if (hpsb_update_config_rom_image(host) < 0) { 246 hpsb_update_config_rom_image(host) < 0)
266 HPSB_ERR("Failed to generate Configuration ROM image for host " 247 HPSB_ERR("Failed to generate Configuration ROM image for host "
267 "%s-%d", hl->name, host->id); 248 "%s-%d", hl->name, host->id);
268 }
269 }
270 249
271 /* And finally, remove all the host info associated between these 250 /* Finally remove all the host info associated between these two. */
272 * two. */
273 hpsb_destroy_hostinfo(hl, host); 251 hpsb_destroy_hostinfo(hl, host);
274} 252}
275 253
@@ -278,7 +256,6 @@ static int highlevel_for_each_host_unreg(struct hpsb_host *host, void *__data)
278 struct hpsb_highlevel *hl = __data; 256 struct hpsb_highlevel *hl = __data;
279 257
280 __unregister_host(hl, host, 1); 258 __unregister_host(hl, host, 1);
281
282 return 0; 259 return 0;
283} 260}
284 261
@@ -291,7 +268,7 @@ void hpsb_unregister_highlevel(struct hpsb_highlevel *hl)
291 write_unlock_irqrestore(&hl_irqs_lock, flags); 268 write_unlock_irqrestore(&hl_irqs_lock, flags);
292 269
293 down_write(&hl_drivers_sem); 270 down_write(&hl_drivers_sem);
294 list_del(&hl->hl_list); 271 list_del(&hl->hl_list);
295 up_write(&hl_drivers_sem); 272 up_write(&hl_drivers_sem);
296 273
297 nodemgr_for_each_host(hl, highlevel_for_each_host_unreg); 274 nodemgr_for_each_host(hl, highlevel_for_each_host_unreg);
@@ -324,9 +301,11 @@ u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl,
324 end = CSR1212_ALL_SPACE_END; 301 end = CSR1212_ALL_SPACE_END;
325 } 302 }
326 303
327 if (((start|end) & ~align_mask) || (start >= end) || (end > 0x1000000000000ULL)) { 304 if (((start|end) & ~align_mask) || (start >= end) ||
328 HPSB_ERR("%s called with invalid addresses (start = %012Lx end = %012Lx)", 305 (end > CSR1212_ALL_SPACE_END)) {
329 __FUNCTION__, (unsigned long long)start, (unsigned long long)end); 306 HPSB_ERR("%s called with invalid addresses "
307 "(start = %012Lx end = %012Lx)", __FUNCTION__,
308 (unsigned long long)start,(unsigned long long)end);
330 return retval; 309 return retval;
331 } 310 }
332 311
@@ -340,20 +319,21 @@ u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl,
340 as->host = host; 319 as->host = host;
341 320
342 write_lock_irqsave(&addr_space_lock, flags); 321 write_lock_irqsave(&addr_space_lock, flags);
343
344 list_for_each(entry, &host->addr_space) { 322 list_for_each(entry, &host->addr_space) {
345 u64 a1sa, a1ea; 323 u64 a1sa, a1ea;
346 u64 a2sa, a2ea; 324 u64 a2sa, a2ea;
347 325
348 a1 = list_entry(entry, struct hpsb_address_serve, host_list); 326 a1 = list_entry(entry, struct hpsb_address_serve, host_list);
349 a2 = list_entry(entry->next, struct hpsb_address_serve, host_list); 327 a2 = list_entry(entry->next, struct hpsb_address_serve,
328 host_list);
350 329
351 a1sa = a1->start & align_mask; 330 a1sa = a1->start & align_mask;
352 a1ea = (a1->end + alignment -1) & align_mask; 331 a1ea = (a1->end + alignment -1) & align_mask;
353 a2sa = a2->start & align_mask; 332 a2sa = a2->start & align_mask;
354 a2ea = (a2->end + alignment -1) & align_mask; 333 a2ea = (a2->end + alignment -1) & align_mask;
355 334
356 if ((a2sa - a1ea >= size) && (a2sa - start >= size) && (a2sa > start)) { 335 if ((a2sa - a1ea >= size) && (a2sa - start >= size) &&
336 (a2sa > start)) {
357 as->start = max(start, a1ea); 337 as->start = max(start, a1ea);
358 as->end = as->start + size; 338 as->end = as->start + size;
359 list_add(&as->host_list, entry); 339 list_add(&as->host_list, entry);
@@ -362,47 +342,45 @@ u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl,
362 break; 342 break;
363 } 343 }
364 } 344 }
365
366 write_unlock_irqrestore(&addr_space_lock, flags); 345 write_unlock_irqrestore(&addr_space_lock, flags);
367 346
368 if (retval == CSR1212_INVALID_ADDR_SPACE) { 347 if (retval == CSR1212_INVALID_ADDR_SPACE)
369 kfree(as); 348 kfree(as);
370 }
371
372 return retval; 349 return retval;
373} 350}
374 351
375int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host, 352int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
376 struct hpsb_address_ops *ops, u64 start, u64 end) 353 struct hpsb_address_ops *ops, u64 start, u64 end)
377{ 354{
378 struct hpsb_address_serve *as; 355 struct hpsb_address_serve *as;
379 struct list_head *lh; 356 struct list_head *lh;
380 int retval = 0; 357 int retval = 0;
381 unsigned long flags; 358 unsigned long flags;
382 359
383 if (((start|end) & 3) || (start >= end) || (end > 0x1000000000000ULL)) { 360 if (((start|end) & 3) || (start >= end) ||
384 HPSB_ERR("%s called with invalid addresses", __FUNCTION__); 361 (end > CSR1212_ALL_SPACE_END)) {
385 return 0; 362 HPSB_ERR("%s called with invalid addresses", __FUNCTION__);
386 } 363 return 0;
364 }
387 365
388 as = kmalloc(sizeof(*as), GFP_ATOMIC); 366 as = kmalloc(sizeof(*as), GFP_ATOMIC);
389 if (!as) 367 if (!as)
390 return 0; 368 return 0;
391 369
392 INIT_LIST_HEAD(&as->host_list); 370 INIT_LIST_HEAD(&as->host_list);
393 INIT_LIST_HEAD(&as->hl_list); 371 INIT_LIST_HEAD(&as->hl_list);
394 as->op = ops; 372 as->op = ops;
395 as->start = start; 373 as->start = start;
396 as->end = end; 374 as->end = end;
397 as->host = host; 375 as->host = host;
398 376
399 write_lock_irqsave(&addr_space_lock, flags); 377 write_lock_irqsave(&addr_space_lock, flags);
400
401 list_for_each(lh, &host->addr_space) { 378 list_for_each(lh, &host->addr_space) {
402 struct hpsb_address_serve *as_this = 379 struct hpsb_address_serve *as_this =
403 list_entry(lh, struct hpsb_address_serve, host_list); 380 list_entry(lh, struct hpsb_address_serve, host_list);
404 struct hpsb_address_serve *as_next = 381 struct hpsb_address_serve *as_next =
405 list_entry(lh->next, struct hpsb_address_serve, host_list); 382 list_entry(lh->next, struct hpsb_address_serve,
383 host_list);
406 384
407 if (as_this->end > as->start) 385 if (as_this->end > as->start)
408 break; 386 break;
@@ -418,60 +396,51 @@ int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
418 396
419 if (retval == 0) 397 if (retval == 0)
420 kfree(as); 398 kfree(as);
421 399 return retval;
422 return retval;
423} 400}
424 401
425int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host, 402int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
426 u64 start) 403 u64 start)
427{ 404{
428 int retval = 0; 405 int retval = 0;
429 struct hpsb_address_serve *as; 406 struct hpsb_address_serve *as;
430 struct list_head *lh, *next; 407 struct list_head *lh, *next;
431 unsigned long flags; 408 unsigned long flags;
432
433 write_lock_irqsave(&addr_space_lock, flags);
434 409
410 write_lock_irqsave(&addr_space_lock, flags);
435 list_for_each_safe (lh, next, &hl->addr_list) { 411 list_for_each_safe (lh, next, &hl->addr_list) {
436 as = list_entry(lh, struct hpsb_address_serve, hl_list); 412 as = list_entry(lh, struct hpsb_address_serve, hl_list);
437 if (as->start == start && as->host == host) { 413 if (as->start == start && as->host == host) {
438 __delete_addr(as); 414 __delete_addr(as);
439 retval = 1; 415 retval = 1;
440 break; 416 break;
441 } 417 }
442 } 418 }
443 419 write_unlock_irqrestore(&addr_space_lock, flags);
444 write_unlock_irqrestore(&addr_space_lock, flags); 420 return retval;
445
446 return retval;
447} 421}
448 422
449int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, 423int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
450 unsigned int channel) 424 unsigned int channel)
451{ 425{
452 if (channel > 63) { 426 if (channel > 63) {
453 HPSB_ERR("%s called with invalid channel", __FUNCTION__); 427 HPSB_ERR("%s called with invalid channel", __FUNCTION__);
454 return -EINVAL; 428 return -EINVAL;
455 } 429 }
456 430 if (host->iso_listen_count[channel]++ == 0)
457 if (host->iso_listen_count[channel]++ == 0) { 431 return host->driver->devctl(host, ISO_LISTEN_CHANNEL, channel);
458 return host->driver->devctl(host, ISO_LISTEN_CHANNEL, channel);
459 }
460
461 return 0; 432 return 0;
462} 433}
463 434
464void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, 435void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
465 unsigned int channel) 436 unsigned int channel)
466{ 437{
467 if (channel > 63) { 438 if (channel > 63) {
468 HPSB_ERR("%s called with invalid channel", __FUNCTION__); 439 HPSB_ERR("%s called with invalid channel", __FUNCTION__);
469 return; 440 return;
470 } 441 }
471 442 if (--host->iso_listen_count[channel] == 0)
472 if (--host->iso_listen_count[channel] == 0) { 443 host->driver->devctl(host, ISO_UNLISTEN_CHANNEL, channel);
473 host->driver->devctl(host, ISO_UNLISTEN_CHANNEL, channel);
474 }
475} 444}
476 445
477static void init_hpsb_highlevel(struct hpsb_host *host) 446static void init_hpsb_highlevel(struct hpsb_host *host)
@@ -492,26 +461,24 @@ static void init_hpsb_highlevel(struct hpsb_host *host)
492 461
493void highlevel_add_host(struct hpsb_host *host) 462void highlevel_add_host(struct hpsb_host *host)
494{ 463{
495 struct hpsb_highlevel *hl; 464 struct hpsb_highlevel *hl;
496 465
497 init_hpsb_highlevel(host); 466 init_hpsb_highlevel(host);
498 467
499 down_read(&hl_drivers_sem); 468 down_read(&hl_drivers_sem);
500 list_for_each_entry(hl, &hl_drivers, hl_list) { 469 list_for_each_entry(hl, &hl_drivers, hl_list) {
501 if (hl->add_host) 470 if (hl->add_host)
502 hl->add_host(host); 471 hl->add_host(host);
503 }
504 up_read(&hl_drivers_sem);
505 if (host->update_config_rom) {
506 if (hpsb_update_config_rom_image(host) < 0)
507 HPSB_ERR("Failed to generate Configuration ROM image for "
508 "host %s-%d", hl->name, host->id);
509 } 472 }
473 up_read(&hl_drivers_sem);
474 if (host->update_config_rom && hpsb_update_config_rom_image(host) < 0)
475 HPSB_ERR("Failed to generate Configuration ROM image for host "
476 "%s-%d", hl->name, host->id);
510} 477}
511 478
512void highlevel_remove_host(struct hpsb_host *host) 479void highlevel_remove_host(struct hpsb_host *host)
513{ 480{
514 struct hpsb_highlevel *hl; 481 struct hpsb_highlevel *hl;
515 482
516 down_read(&hl_drivers_sem); 483 down_read(&hl_drivers_sem);
517 list_for_each_entry(hl, &hl_drivers, hl_list) 484 list_for_each_entry(hl, &hl_drivers, hl_list)
@@ -522,186 +489,168 @@ void highlevel_remove_host(struct hpsb_host *host)
522void highlevel_host_reset(struct hpsb_host *host) 489void highlevel_host_reset(struct hpsb_host *host)
523{ 490{
524 unsigned long flags; 491 unsigned long flags;
525 struct hpsb_highlevel *hl; 492 struct hpsb_highlevel *hl;
526 493
527 read_lock_irqsave(&hl_irqs_lock, flags); 494 read_lock_irqsave(&hl_irqs_lock, flags);
528 list_for_each_entry(hl, &hl_irqs, irq_list) { 495 list_for_each_entry(hl, &hl_irqs, irq_list) {
529 if (hl->host_reset) 496 if (hl->host_reset)
530 hl->host_reset(host); 497 hl->host_reset(host);
531 } 498 }
532 read_unlock_irqrestore(&hl_irqs_lock, flags); 499 read_unlock_irqrestore(&hl_irqs_lock, flags);
533} 500}
534 501
535void highlevel_iso_receive(struct hpsb_host *host, void *data, size_t length) 502void highlevel_iso_receive(struct hpsb_host *host, void *data, size_t length)
536{ 503{
537 unsigned long flags; 504 unsigned long flags;
538 struct hpsb_highlevel *hl; 505 struct hpsb_highlevel *hl;
539 int channel = (((quadlet_t *)data)[0] >> 8) & 0x3f; 506 int channel = (((quadlet_t *)data)[0] >> 8) & 0x3f;
540 507
541 read_lock_irqsave(&hl_irqs_lock, flags); 508 read_lock_irqsave(&hl_irqs_lock, flags);
542 list_for_each_entry(hl, &hl_irqs, irq_list) { 509 list_for_each_entry(hl, &hl_irqs, irq_list) {
543 if (hl->iso_receive) 510 if (hl->iso_receive)
544 hl->iso_receive(host, channel, data, length); 511 hl->iso_receive(host, channel, data, length);
545 } 512 }
546 read_unlock_irqrestore(&hl_irqs_lock, flags); 513 read_unlock_irqrestore(&hl_irqs_lock, flags);
547} 514}
548 515
549void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction, 516void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction,
550 void *data, size_t length) 517 void *data, size_t length)
551{ 518{
552 unsigned long flags; 519 unsigned long flags;
553 struct hpsb_highlevel *hl; 520 struct hpsb_highlevel *hl;
554 int cts = ((quadlet_t *)data)[0] >> 4; 521 int cts = ((quadlet_t *)data)[0] >> 4;
555 522
556 read_lock_irqsave(&hl_irqs_lock, flags); 523 read_lock_irqsave(&hl_irqs_lock, flags);
557 list_for_each_entry(hl, &hl_irqs, irq_list) { 524 list_for_each_entry(hl, &hl_irqs, irq_list) {
558 if (hl->fcp_request) 525 if (hl->fcp_request)
559 hl->fcp_request(host, nodeid, direction, cts, data, 526 hl->fcp_request(host, nodeid, direction, cts, data,
560 length); 527 length);
561 } 528 }
562 read_unlock_irqrestore(&hl_irqs_lock, flags); 529 read_unlock_irqrestore(&hl_irqs_lock, flags);
563} 530}
564 531
565int highlevel_read(struct hpsb_host *host, int nodeid, void *data, 532int highlevel_read(struct hpsb_host *host, int nodeid, void *data, u64 addr,
566 u64 addr, unsigned int length, u16 flags) 533 unsigned int length, u16 flags)
567{ 534{
568 struct hpsb_address_serve *as; 535 struct hpsb_address_serve *as;
569 unsigned int partlength; 536 unsigned int partlength;
570 int rcode = RCODE_ADDRESS_ERROR; 537 int rcode = RCODE_ADDRESS_ERROR;
571
572 read_lock(&addr_space_lock);
573 538
539 read_lock(&addr_space_lock);
574 list_for_each_entry(as, &host->addr_space, host_list) { 540 list_for_each_entry(as, &host->addr_space, host_list) {
575 if (as->start > addr) 541 if (as->start > addr)
576 break; 542 break;
577 543
578 if (as->end > addr) { 544 if (as->end > addr) {
579 partlength = min(as->end - addr, (u64) length); 545 partlength = min(as->end - addr, (u64) length);
580 546
581 if (as->op->read) { 547 if (as->op->read)
582 rcode = as->op->read(host, nodeid, data, 548 rcode = as->op->read(host, nodeid, data,
583 addr, partlength, flags); 549 addr, partlength, flags);
584 } else { 550 else
585 rcode = RCODE_TYPE_ERROR; 551 rcode = RCODE_TYPE_ERROR;
586 }
587 552
588 data += partlength; 553 data += partlength;
589 length -= partlength; 554 length -= partlength;
590 addr += partlength; 555 addr += partlength;
591 556
592 if ((rcode != RCODE_COMPLETE) || !length) { 557 if ((rcode != RCODE_COMPLETE) || !length)
593 break; 558 break;
594 } 559 }
595 } 560 }
596 } 561 read_unlock(&addr_space_lock);
597
598 read_unlock(&addr_space_lock);
599
600 if (length && (rcode == RCODE_COMPLETE)) {
601 rcode = RCODE_ADDRESS_ERROR;
602 }
603 562
604 return rcode; 563 if (length && (rcode == RCODE_COMPLETE))
564 rcode = RCODE_ADDRESS_ERROR;
565 return rcode;
605} 566}
606 567
607int highlevel_write(struct hpsb_host *host, int nodeid, int destid, 568int highlevel_write(struct hpsb_host *host, int nodeid, int destid, void *data,
608 void *data, u64 addr, unsigned int length, u16 flags) 569 u64 addr, unsigned int length, u16 flags)
609{ 570{
610 struct hpsb_address_serve *as; 571 struct hpsb_address_serve *as;
611 unsigned int partlength; 572 unsigned int partlength;
612 int rcode = RCODE_ADDRESS_ERROR; 573 int rcode = RCODE_ADDRESS_ERROR;
613
614 read_lock(&addr_space_lock);
615 574
575 read_lock(&addr_space_lock);
616 list_for_each_entry(as, &host->addr_space, host_list) { 576 list_for_each_entry(as, &host->addr_space, host_list) {
617 if (as->start > addr) 577 if (as->start > addr)
618 break; 578 break;
619 579
620 if (as->end > addr) { 580 if (as->end > addr) {
621 partlength = min(as->end - addr, (u64) length); 581 partlength = min(as->end - addr, (u64) length);
622 582
623 if (as->op->write) { 583 if (as->op->write)
624 rcode = as->op->write(host, nodeid, destid, 584 rcode = as->op->write(host, nodeid, destid,
625 data, addr, partlength, flags); 585 data, addr, partlength,
626 } else { 586 flags);
627 rcode = RCODE_TYPE_ERROR; 587 else
628 } 588 rcode = RCODE_TYPE_ERROR;
629 589
630 data += partlength; 590 data += partlength;
631 length -= partlength; 591 length -= partlength;
632 addr += partlength; 592 addr += partlength;
633 593
634 if ((rcode != RCODE_COMPLETE) || !length) { 594 if ((rcode != RCODE_COMPLETE) || !length)
635 break; 595 break;
636 } 596 }
637 } 597 }
638 } 598 read_unlock(&addr_space_lock);
639
640 read_unlock(&addr_space_lock);
641
642 if (length && (rcode == RCODE_COMPLETE)) {
643 rcode = RCODE_ADDRESS_ERROR;
644 }
645 599
646 return rcode; 600 if (length && (rcode == RCODE_COMPLETE))
601 rcode = RCODE_ADDRESS_ERROR;
602 return rcode;
647} 603}
648 604
649
650int highlevel_lock(struct hpsb_host *host, int nodeid, quadlet_t *store, 605int highlevel_lock(struct hpsb_host *host, int nodeid, quadlet_t *store,
651 u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, u16 flags) 606 u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode,
607 u16 flags)
652{ 608{
653 struct hpsb_address_serve *as; 609 struct hpsb_address_serve *as;
654 int rcode = RCODE_ADDRESS_ERROR; 610 int rcode = RCODE_ADDRESS_ERROR;
655
656 read_lock(&addr_space_lock);
657 611
612 read_lock(&addr_space_lock);
658 list_for_each_entry(as, &host->addr_space, host_list) { 613 list_for_each_entry(as, &host->addr_space, host_list) {
659 if (as->start > addr) 614 if (as->start > addr)
660 break; 615 break;
661 616
662 if (as->end > addr) { 617 if (as->end > addr) {
663 if (as->op->lock) { 618 if (as->op->lock)
664 rcode = as->op->lock(host, nodeid, store, addr, 619 rcode = as->op->lock(host, nodeid, store, addr,
665 data, arg, ext_tcode, flags); 620 data, arg, ext_tcode,
666 } else { 621 flags);
667 rcode = RCODE_TYPE_ERROR; 622 else
668 } 623 rcode = RCODE_TYPE_ERROR;
669 624 break;
670 break; 625 }
671 } 626 }
672 } 627 read_unlock(&addr_space_lock);
673 628 return rcode;
674 read_unlock(&addr_space_lock);
675
676 return rcode;
677} 629}
678 630
679int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store, 631int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store,
680 u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u16 flags) 632 u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
633 u16 flags)
681{ 634{
682 struct hpsb_address_serve *as; 635 struct hpsb_address_serve *as;
683 int rcode = RCODE_ADDRESS_ERROR; 636 int rcode = RCODE_ADDRESS_ERROR;
684 637
685 read_lock(&addr_space_lock); 638 read_lock(&addr_space_lock);
686 639
687 list_for_each_entry(as, &host->addr_space, host_list) { 640 list_for_each_entry(as, &host->addr_space, host_list) {
688 if (as->start > addr) 641 if (as->start > addr)
689 break; 642 break;
690 643
691 if (as->end > addr) { 644 if (as->end > addr) {
692 if (as->op->lock64) { 645 if (as->op->lock64)
693 rcode = as->op->lock64(host, nodeid, store, 646 rcode = as->op->lock64(host, nodeid, store,
694 addr, data, arg, 647 addr, data, arg,
695 ext_tcode, flags); 648 ext_tcode, flags);
696 } else { 649 else
697 rcode = RCODE_TYPE_ERROR; 650 rcode = RCODE_TYPE_ERROR;
698 } 651 break;
699 652 }
700 break; 653 }
701 } 654 read_unlock(&addr_space_lock);
702 } 655 return rcode;
703
704 read_unlock(&addr_space_lock);
705
706 return rcode;
707} 656}