aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire
diff options
context:
space:
mode:
authorStefan Richter <stefanr@s5r6.in-berlin.de>2008-03-24 15:54:28 -0400
committerStefan Richter <stefanr@s5r6.in-berlin.de>2008-04-18 11:55:36 -0400
commitc9755e14a01987ada4063e8b4c50c2b6738d879e (patch)
tree41a593c4b9ac10ccc4ad031510438e4551e51b5b /drivers/firewire
parent1dadff71d6356ebb804c3f4f1d3049247e16111c (diff)
firewire: reread config ROM when device reset the bus
When a device changes its configuration ROM, it announces this with a bus reset. firewire-core has to check which node initiated a bus reset and whether any unit directories went away or were added on this node. Tested with an IOI FWB-IDE01AB which has its link-on bit set if bus power is available but does not respond to ROM read requests if self power is off. This implements - recognition of the units if self power is switched on after fw-core gave up the initial attempt to read the config ROM, - shutdown of the units when self power is switched off. Also tested with a second PC running Linux/ieee1394. When the eth1394 driver is inserted and removed on that node, fw-core now notices the addition and removal of the IPv4 unit on the ieee1394 node. Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire')
-rw-r--r--drivers/firewire/fw-card.c2
-rw-r--r--drivers/firewire/fw-cdev.c13
-rw-r--r--drivers/firewire/fw-device.c222
-rw-r--r--drivers/firewire/fw-device.h11
-rw-r--r--drivers/firewire/fw-sbp2.c8
-rw-r--r--drivers/firewire/fw-topology.c3
-rw-r--r--drivers/firewire/fw-topology.h11
7 files changed, 223 insertions, 47 deletions
diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c
index 140b34d477de..7e4012db6ad2 100644
--- a/drivers/firewire/fw-card.c
+++ b/drivers/firewire/fw-card.c
@@ -331,7 +331,7 @@ fw_card_bm_work(struct work_struct *work)
331 */ 331 */
332 spin_unlock_irqrestore(&card->lock, flags); 332 spin_unlock_irqrestore(&card->lock, flags);
333 goto out; 333 goto out;
334 } else if (root_device->config_rom[2] & BIB_CMC) { 334 } else if (root_device->cmc) {
335 /* 335 /*
336 * FIXME: I suppose we should set the cmstr bit in the 336 * FIXME: I suppose we should set the cmstr bit in the
337 * STATE_CLEAR register of this node, as described in 337 * STATE_CLEAR register of this node, as described in
diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c
index 46bc197a047f..4a541921a14a 100644
--- a/drivers/firewire/fw-cdev.c
+++ b/drivers/firewire/fw-cdev.c
@@ -269,21 +269,28 @@ static int ioctl_get_info(struct client *client, void *buffer)
269{ 269{
270 struct fw_cdev_get_info *get_info = buffer; 270 struct fw_cdev_get_info *get_info = buffer;
271 struct fw_cdev_event_bus_reset bus_reset; 271 struct fw_cdev_event_bus_reset bus_reset;
272 unsigned long ret = 0;
272 273
273 client->version = get_info->version; 274 client->version = get_info->version;
274 get_info->version = FW_CDEV_VERSION; 275 get_info->version = FW_CDEV_VERSION;
275 276
277 down_read(&fw_device_rwsem);
278
276 if (get_info->rom != 0) { 279 if (get_info->rom != 0) {
277 void __user *uptr = u64_to_uptr(get_info->rom); 280 void __user *uptr = u64_to_uptr(get_info->rom);
278 size_t want = get_info->rom_length; 281 size_t want = get_info->rom_length;
279 size_t have = client->device->config_rom_length * 4; 282 size_t have = client->device->config_rom_length * 4;
280 283
281 if (copy_to_user(uptr, client->device->config_rom, 284 ret = copy_to_user(uptr, client->device->config_rom,
282 min(want, have))) 285 min(want, have));
283 return -EFAULT;
284 } 286 }
285 get_info->rom_length = client->device->config_rom_length * 4; 287 get_info->rom_length = client->device->config_rom_length * 4;
286 288
289 up_read(&fw_device_rwsem);
290
291 if (ret != 0)
292 return -EFAULT;
293
287 client->bus_reset_closure = get_info->bus_reset_closure; 294 client->bus_reset_closure = get_info->bus_reset_closure;
288 if (get_info->bus_reset != 0) { 295 if (get_info->bus_reset != 0) {
289 void __user *uptr = u64_to_uptr(get_info->bus_reset); 296 void __user *uptr = u64_to_uptr(get_info->bus_reset);
diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c
index 20ac9a5afc37..75365cd0008a 100644
--- a/drivers/firewire/fw-device.c
+++ b/drivers/firewire/fw-device.c
@@ -25,7 +25,7 @@
25#include <linux/device.h> 25#include <linux/device.h>
26#include <linux/delay.h> 26#include <linux/delay.h>
27#include <linux/idr.h> 27#include <linux/idr.h>
28#include <linux/rwsem.h> 28#include <linux/string.h>
29#include <asm/semaphore.h> 29#include <asm/semaphore.h>
30#include <asm/system.h> 30#include <asm/system.h>
31#include <linux/ctype.h> 31#include <linux/ctype.h>
@@ -160,9 +160,9 @@ static void fw_device_release(struct device *dev)
160 * Take the card lock so we don't set this to NULL while a 160 * Take the card lock so we don't set this to NULL while a
161 * FW_NODE_UPDATED callback is being handled. 161 * FW_NODE_UPDATED callback is being handled.
162 */ 162 */
163 spin_lock_irqsave(&device->card->lock, flags); 163 spin_lock_irqsave(&card->lock, flags);
164 device->node->data = NULL; 164 device->node->data = NULL;
165 spin_unlock_irqrestore(&device->card->lock, flags); 165 spin_unlock_irqrestore(&card->lock, flags);
166 166
167 fw_node_put(device->node); 167 fw_node_put(device->node);
168 kfree(device->config_rom); 168 kfree(device->config_rom);
@@ -195,7 +195,9 @@ show_immediate(struct device *dev, struct device_attribute *dattr, char *buf)
195 container_of(dattr, struct config_rom_attribute, attr); 195 container_of(dattr, struct config_rom_attribute, attr);
196 struct fw_csr_iterator ci; 196 struct fw_csr_iterator ci;
197 u32 *dir; 197 u32 *dir;
198 int key, value; 198 int key, value, ret = -ENOENT;
199
200 down_read(&fw_device_rwsem);
199 201
200 if (is_fw_unit(dev)) 202 if (is_fw_unit(dev))
201 dir = fw_unit(dev)->directory; 203 dir = fw_unit(dev)->directory;
@@ -204,11 +206,15 @@ show_immediate(struct device *dev, struct device_attribute *dattr, char *buf)
204 206
205 fw_csr_iterator_init(&ci, dir); 207 fw_csr_iterator_init(&ci, dir);
206 while (fw_csr_iterator_next(&ci, &key, &value)) 208 while (fw_csr_iterator_next(&ci, &key, &value))
207 if (attr->key == key) 209 if (attr->key == key) {
208 return snprintf(buf, buf ? PAGE_SIZE : 0, 210 ret = snprintf(buf, buf ? PAGE_SIZE : 0,
209 "0x%06x\n", value); 211 "0x%06x\n", value);
212 break;
213 }
214
215 up_read(&fw_device_rwsem);
210 216
211 return -ENOENT; 217 return ret;
212} 218}
213 219
214#define IMMEDIATE_ATTR(name, key) \ 220#define IMMEDIATE_ATTR(name, key) \
@@ -221,9 +227,11 @@ show_text_leaf(struct device *dev, struct device_attribute *dattr, char *buf)
221 container_of(dattr, struct config_rom_attribute, attr); 227 container_of(dattr, struct config_rom_attribute, attr);
222 struct fw_csr_iterator ci; 228 struct fw_csr_iterator ci;
223 u32 *dir, *block = NULL, *p, *end; 229 u32 *dir, *block = NULL, *p, *end;
224 int length, key, value, last_key = 0; 230 int length, key, value, last_key = 0, ret = -ENOENT;
225 char *b; 231 char *b;
226 232
233 down_read(&fw_device_rwsem);
234
227 if (is_fw_unit(dev)) 235 if (is_fw_unit(dev))
228 dir = fw_unit(dev)->directory; 236 dir = fw_unit(dev)->directory;
229 else 237 else
@@ -238,18 +246,20 @@ show_text_leaf(struct device *dev, struct device_attribute *dattr, char *buf)
238 } 246 }
239 247
240 if (block == NULL) 248 if (block == NULL)
241 return -ENOENT; 249 goto out;
242 250
243 length = min(block[0] >> 16, 256U); 251 length = min(block[0] >> 16, 256U);
244 if (length < 3) 252 if (length < 3)
245 return -ENOENT; 253 goto out;
246 254
247 if (block[1] != 0 || block[2] != 0) 255 if (block[1] != 0 || block[2] != 0)
248 /* Unknown encoding. */ 256 /* Unknown encoding. */
249 return -ENOENT; 257 goto out;
250 258
251 if (buf == NULL) 259 if (buf == NULL) {
252 return length * 4; 260 ret = length * 4;
261 goto out;
262 }
253 263
254 b = buf; 264 b = buf;
255 end = &block[length + 1]; 265 end = &block[length + 1];
@@ -259,8 +269,11 @@ show_text_leaf(struct device *dev, struct device_attribute *dattr, char *buf)
259 /* Strip trailing whitespace and add newline. */ 269 /* Strip trailing whitespace and add newline. */
260 while (b--, (isspace(*b) || *b == '\0') && b > buf); 270 while (b--, (isspace(*b) || *b == '\0') && b > buf);
261 strcpy(b + 1, "\n"); 271 strcpy(b + 1, "\n");
272 ret = b + 2 - buf;
273 out:
274 up_read(&fw_device_rwsem);
262 275
263 return b + 2 - buf; 276 return ret;
264} 277}
265 278
266#define TEXT_LEAF_ATTR(name, key) \ 279#define TEXT_LEAF_ATTR(name, key) \
@@ -337,19 +350,28 @@ static ssize_t
337config_rom_show(struct device *dev, struct device_attribute *attr, char *buf) 350config_rom_show(struct device *dev, struct device_attribute *attr, char *buf)
338{ 351{
339 struct fw_device *device = fw_device(dev); 352 struct fw_device *device = fw_device(dev);
353 size_t length;
340 354
341 memcpy(buf, device->config_rom, device->config_rom_length * 4); 355 down_read(&fw_device_rwsem);
356 length = device->config_rom_length * 4;
357 memcpy(buf, device->config_rom, length);
358 up_read(&fw_device_rwsem);
342 359
343 return device->config_rom_length * 4; 360 return length;
344} 361}
345 362
346static ssize_t 363static ssize_t
347guid_show(struct device *dev, struct device_attribute *attr, char *buf) 364guid_show(struct device *dev, struct device_attribute *attr, char *buf)
348{ 365{
349 struct fw_device *device = fw_device(dev); 366 struct fw_device *device = fw_device(dev);
367 int ret;
368
369 down_read(&fw_device_rwsem);
370 ret = snprintf(buf, PAGE_SIZE, "0x%08x%08x\n",
371 device->config_rom[3], device->config_rom[4]);
372 up_read(&fw_device_rwsem);
350 373
351 return snprintf(buf, PAGE_SIZE, "0x%08x%08x\n", 374 return ret;
352 device->config_rom[3], device->config_rom[4]);
353} 375}
354 376
355static struct device_attribute fw_device_attributes[] = { 377static struct device_attribute fw_device_attributes[] = {
@@ -412,7 +434,7 @@ read_rom(struct fw_device *device, int generation, int index, u32 *data)
412 */ 434 */
413static int read_bus_info_block(struct fw_device *device, int generation) 435static int read_bus_info_block(struct fw_device *device, int generation)
414{ 436{
415 u32 *rom, *stack; 437 u32 *rom, *stack, *old_rom, *new_rom;
416 u32 sp, key; 438 u32 sp, key;
417 int i, end, length, ret = -1; 439 int i, end, length, ret = -1;
418 440
@@ -527,12 +549,19 @@ static int read_bus_info_block(struct fw_device *device, int generation)
527 length = i; 549 length = i;
528 } 550 }
529 551
530 device->config_rom = kmalloc(length * 4, GFP_KERNEL); 552 old_rom = device->config_rom;
531 if (device->config_rom == NULL) 553 new_rom = kmemdup(rom, length * 4, GFP_KERNEL);
554 if (new_rom == NULL)
532 goto out; 555 goto out;
533 memcpy(device->config_rom, rom, length * 4); 556
557 down_write(&fw_device_rwsem);
558 device->config_rom = new_rom;
534 device->config_rom_length = length; 559 device->config_rom_length = length;
560 up_write(&fw_device_rwsem);
561
562 kfree(old_rom);
535 ret = 0; 563 ret = 0;
564 device->cmc = rom[2] & 1 << 30;
536 out: 565 out:
537 kfree(rom); 566 kfree(rom);
538 567
@@ -605,7 +634,14 @@ static int shutdown_unit(struct device *device, void *data)
605 return 0; 634 return 0;
606} 635}
607 636
608static DECLARE_RWSEM(idr_rwsem); 637/*
638 * fw_device_rwsem acts as dual purpose mutex:
639 * - serializes accesses to fw_device_idr,
640 * - serializes accesses to fw_device.config_rom/.config_rom_length and
641 * fw_unit.directory, unless those accesses happen at safe occasions
642 */
643DECLARE_RWSEM(fw_device_rwsem);
644
609static DEFINE_IDR(fw_device_idr); 645static DEFINE_IDR(fw_device_idr);
610int fw_cdev_major; 646int fw_cdev_major;
611 647
@@ -613,11 +649,11 @@ struct fw_device *fw_device_get_by_devt(dev_t devt)
613{ 649{
614 struct fw_device *device; 650 struct fw_device *device;
615 651
616 down_read(&idr_rwsem); 652 down_read(&fw_device_rwsem);
617 device = idr_find(&fw_device_idr, MINOR(devt)); 653 device = idr_find(&fw_device_idr, MINOR(devt));
618 if (device) 654 if (device)
619 fw_device_get(device); 655 fw_device_get(device);
620 up_read(&idr_rwsem); 656 up_read(&fw_device_rwsem);
621 657
622 return device; 658 return device;
623} 659}
@@ -632,9 +668,9 @@ static void fw_device_shutdown(struct work_struct *work)
632 device_for_each_child(&device->device, NULL, shutdown_unit); 668 device_for_each_child(&device->device, NULL, shutdown_unit);
633 device_unregister(&device->device); 669 device_unregister(&device->device);
634 670
635 down_write(&idr_rwsem); 671 down_write(&fw_device_rwsem);
636 idr_remove(&fw_device_idr, minor); 672 idr_remove(&fw_device_idr, minor);
637 up_write(&idr_rwsem); 673 up_write(&fw_device_rwsem);
638 fw_device_put(device); 674 fw_device_put(device);
639} 675}
640 676
@@ -687,10 +723,10 @@ static void fw_device_init(struct work_struct *work)
687 err = -ENOMEM; 723 err = -ENOMEM;
688 724
689 fw_device_get(device); 725 fw_device_get(device);
690 down_write(&idr_rwsem); 726 down_write(&fw_device_rwsem);
691 if (idr_pre_get(&fw_device_idr, GFP_KERNEL)) 727 if (idr_pre_get(&fw_device_idr, GFP_KERNEL))
692 err = idr_get_new(&fw_device_idr, device, &minor); 728 err = idr_get_new(&fw_device_idr, device, &minor);
693 up_write(&idr_rwsem); 729 up_write(&fw_device_rwsem);
694 730
695 if (err < 0) 731 if (err < 0)
696 goto error; 732 goto error;
@@ -724,7 +760,7 @@ static void fw_device_init(struct work_struct *work)
724 if (atomic_cmpxchg(&device->state, 760 if (atomic_cmpxchg(&device->state,
725 FW_DEVICE_INITIALIZING, 761 FW_DEVICE_INITIALIZING,
726 FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN) { 762 FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN) {
727 fw_device_shutdown(&device->work.work); 763 fw_device_shutdown(work);
728 } else { 764 } else {
729 if (device->config_rom_retries) 765 if (device->config_rom_retries)
730 fw_notify("created device %s: GUID %08x%08x, S%d00, " 766 fw_notify("created device %s: GUID %08x%08x, S%d00, "
@@ -738,6 +774,7 @@ static void fw_device_init(struct work_struct *work)
738 device->device.bus_id, 774 device->device.bus_id,
739 device->config_rom[3], device->config_rom[4], 775 device->config_rom[3], device->config_rom[4],
740 1 << device->max_speed); 776 1 << device->max_speed);
777 device->config_rom_retries = 0;
741 } 778 }
742 779
743 /* 780 /*
@@ -752,9 +789,9 @@ static void fw_device_init(struct work_struct *work)
752 return; 789 return;
753 790
754 error_with_cdev: 791 error_with_cdev:
755 down_write(&idr_rwsem); 792 down_write(&fw_device_rwsem);
756 idr_remove(&fw_device_idr, minor); 793 idr_remove(&fw_device_idr, minor);
757 up_write(&idr_rwsem); 794 up_write(&fw_device_rwsem);
758 error: 795 error:
759 fw_device_put(device); /* fw_device_idr's reference */ 796 fw_device_put(device); /* fw_device_idr's reference */
760 797
@@ -784,6 +821,106 @@ static void fw_device_update(struct work_struct *work)
784 device_for_each_child(&device->device, NULL, update_unit); 821 device_for_each_child(&device->device, NULL, update_unit);
785} 822}
786 823
824enum {
825 REREAD_BIB_ERROR,
826 REREAD_BIB_GONE,
827 REREAD_BIB_UNCHANGED,
828 REREAD_BIB_CHANGED,
829};
830
831/* Reread and compare bus info block and header of root directory */
832static int reread_bus_info_block(struct fw_device *device, int generation)
833{
834 u32 q;
835 int i;
836
837 for (i = 0; i < 6; i++) {
838 if (read_rom(device, generation, i, &q) != RCODE_COMPLETE)
839 return REREAD_BIB_ERROR;
840
841 if (i == 0 && q == 0)
842 return REREAD_BIB_GONE;
843
844 if (i > device->config_rom_length || q != device->config_rom[i])
845 return REREAD_BIB_CHANGED;
846 }
847
848 return REREAD_BIB_UNCHANGED;
849}
850
851static void fw_device_refresh(struct work_struct *work)
852{
853 struct fw_device *device =
854 container_of(work, struct fw_device, work.work);
855 struct fw_card *card = device->card;
856 int node_id = device->node_id;
857
858 switch (reread_bus_info_block(device, device->generation)) {
859 case REREAD_BIB_ERROR:
860 if (device->config_rom_retries < MAX_RETRIES / 2 &&
861 atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
862 device->config_rom_retries++;
863 schedule_delayed_work(&device->work, RETRY_DELAY / 2);
864
865 return;
866 }
867 goto give_up;
868
869 case REREAD_BIB_GONE:
870 goto gone;
871
872 case REREAD_BIB_UNCHANGED:
873 if (atomic_cmpxchg(&device->state,
874 FW_DEVICE_INITIALIZING,
875 FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN)
876 goto gone;
877
878 fw_device_update(work);
879 device->config_rom_retries = 0;
880 goto out;
881
882 case REREAD_BIB_CHANGED:
883 break;
884 }
885
886 /*
887 * Something changed. We keep things simple and don't investigate
888 * further. We just destroy all previous units and create new ones.
889 */
890 device_for_each_child(&device->device, NULL, shutdown_unit);
891
892 if (read_bus_info_block(device, device->generation) < 0) {
893 if (device->config_rom_retries < MAX_RETRIES &&
894 atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
895 device->config_rom_retries++;
896 schedule_delayed_work(&device->work, RETRY_DELAY);
897
898 return;
899 }
900 goto give_up;
901 }
902
903 create_units(device);
904
905 if (atomic_cmpxchg(&device->state,
906 FW_DEVICE_INITIALIZING,
907 FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN)
908 goto gone;
909
910 fw_notify("refreshed device %s\n", device->device.bus_id);
911 device->config_rom_retries = 0;
912 goto out;
913
914 give_up:
915 fw_notify("giving up on refresh of device %s\n", device->device.bus_id);
916 gone:
917 atomic_set(&device->state, FW_DEVICE_SHUTDOWN);
918 fw_device_shutdown(work);
919 out:
920 if (node_id == card->root_node->node_id)
921 schedule_delayed_work(&card->work, 0);
922}
923
787void fw_node_event(struct fw_card *card, struct fw_node *node, int event) 924void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
788{ 925{
789 struct fw_device *device; 926 struct fw_device *device;
@@ -793,7 +930,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
793 case FW_NODE_LINK_ON: 930 case FW_NODE_LINK_ON:
794 if (!node->link_on) 931 if (!node->link_on)
795 break; 932 break;
796 933 create:
797 device = kzalloc(sizeof(*device), GFP_ATOMIC); 934 device = kzalloc(sizeof(*device), GFP_ATOMIC);
798 if (device == NULL) 935 if (device == NULL)
799 break; 936 break;
@@ -832,6 +969,23 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
832 schedule_delayed_work(&device->work, INITIAL_DELAY); 969 schedule_delayed_work(&device->work, INITIAL_DELAY);
833 break; 970 break;
834 971
972 case FW_NODE_INITIATED_RESET:
973 device = node->data;
974 if (device == NULL)
975 goto create;
976
977 device->node_id = node->node_id;
978 smp_wmb(); /* update node_id before generation */
979 device->generation = card->generation;
980 if (atomic_cmpxchg(&device->state,
981 FW_DEVICE_RUNNING,
982 FW_DEVICE_INITIALIZING) == FW_DEVICE_RUNNING) {
983 PREPARE_DELAYED_WORK(&device->work, fw_device_refresh);
984 schedule_delayed_work(&device->work,
985 node == card->local_node ? 0 : INITIAL_DELAY);
986 }
987 break;
988
835 case FW_NODE_UPDATED: 989 case FW_NODE_UPDATED:
836 if (!node->link_on || node->data == NULL) 990 if (!node->link_on || node->data == NULL)
837 break; 991 break;
diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h
index 0d771fda86de..5f131f5129da 100644
--- a/drivers/firewire/fw-device.h
+++ b/drivers/firewire/fw-device.h
@@ -21,6 +21,7 @@
21 21
22#include <linux/fs.h> 22#include <linux/fs.h>
23#include <linux/cdev.h> 23#include <linux/cdev.h>
24#include <linux/rwsem.h>
24#include <asm/atomic.h> 25#include <asm/atomic.h>
25 26
26enum fw_device_state { 27enum fw_device_state {
@@ -46,6 +47,11 @@ struct fw_attribute_group {
46 * fw_device.node_id is guaranteed to be current too. 47 * fw_device.node_id is guaranteed to be current too.
47 * 48 *
48 * The same applies to fw_device.card->node_id vs. fw_device.generation. 49 * The same applies to fw_device.card->node_id vs. fw_device.generation.
50 *
51 * fw_device.config_rom and fw_device.config_rom_length may be accessed during
52 * the lifetime of any fw_unit belonging to the fw_device, before device_del()
53 * was called on the last fw_unit. Alternatively, they may be accessed while
54 * holding fw_device_rwsem.
49 */ 55 */
50struct fw_device { 56struct fw_device {
51 atomic_t state; 57 atomic_t state;
@@ -53,6 +59,7 @@ struct fw_device {
53 int node_id; 59 int node_id;
54 int generation; 60 int generation;
55 unsigned max_speed; 61 unsigned max_speed;
62 bool cmc;
56 struct fw_card *card; 63 struct fw_card *card;
57 struct device device; 64 struct device device;
58 struct list_head link; 65 struct list_head link;
@@ -92,8 +99,12 @@ int fw_device_enable_phys_dma(struct fw_device *device);
92void fw_device_cdev_update(struct fw_device *device); 99void fw_device_cdev_update(struct fw_device *device);
93void fw_device_cdev_remove(struct fw_device *device); 100void fw_device_cdev_remove(struct fw_device *device);
94 101
102extern struct rw_semaphore fw_device_rwsem;
95extern int fw_cdev_major; 103extern int fw_cdev_major;
96 104
105/*
106 * fw_unit.directory must not be accessed after device_del(&fw_unit.device).
107 */
97struct fw_unit { 108struct fw_unit {
98 struct device device; 109 struct device device;
99 u32 *directory; 110 u32 *directory;
diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
index e99a33fcc923..2a999373863e 100644
--- a/drivers/firewire/fw-sbp2.c
+++ b/drivers/firewire/fw-sbp2.c
@@ -153,6 +153,7 @@ struct sbp2_target {
153 struct list_head lu_list; 153 struct list_head lu_list;
154 154
155 u64 management_agent_address; 155 u64 management_agent_address;
156 u64 guid;
156 int directory_id; 157 int directory_id;
157 int node_id; 158 int node_id;
158 int address_high; 159 int address_high;
@@ -1114,6 +1115,7 @@ static int sbp2_probe(struct device *dev)
1114 kref_init(&tgt->kref); 1115 kref_init(&tgt->kref);
1115 INIT_LIST_HEAD(&tgt->lu_list); 1116 INIT_LIST_HEAD(&tgt->lu_list);
1116 tgt->bus_id = unit->device.bus_id; 1117 tgt->bus_id = unit->device.bus_id;
1118 tgt->guid = (u64)device->config_rom[3] << 32 | device->config_rom[4];
1117 1119
1118 if (fw_device_enable_phys_dma(device) < 0) 1120 if (fw_device_enable_phys_dma(device) < 0)
1119 goto fail_shost_put; 1121 goto fail_shost_put;
@@ -1571,16 +1573,14 @@ sbp2_sysfs_ieee1394_id_show(struct device *dev, struct device_attribute *attr,
1571{ 1573{
1572 struct scsi_device *sdev = to_scsi_device(dev); 1574 struct scsi_device *sdev = to_scsi_device(dev);
1573 struct sbp2_logical_unit *lu; 1575 struct sbp2_logical_unit *lu;
1574 struct fw_device *device;
1575 1576
1576 if (!sdev) 1577 if (!sdev)
1577 return 0; 1578 return 0;
1578 1579
1579 lu = sdev->hostdata; 1580 lu = sdev->hostdata;
1580 device = fw_device(lu->tgt->unit->device.parent);
1581 1581
1582 return sprintf(buf, "%08x%08x:%06x:%04x\n", 1582 return sprintf(buf, "%016llx:%06x:%04x\n",
1583 device->config_rom[3], device->config_rom[4], 1583 (unsigned long long)lu->tgt->guid,
1584 lu->tgt->directory_id, lu->lun); 1584 lu->tgt->directory_id, lu->lun);
1585} 1585}
1586 1586
diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c
index d2c7a3d7e1cb..ebdec4c6c689 100644
--- a/drivers/firewire/fw-topology.c
+++ b/drivers/firewire/fw-topology.c
@@ -108,6 +108,7 @@ static struct fw_node *fw_node_create(u32 sid, int port_count, int color)
108 node->node_id = LOCAL_BUS | SELF_ID_PHY_ID(sid); 108 node->node_id = LOCAL_BUS | SELF_ID_PHY_ID(sid);
109 node->link_on = SELF_ID_LINK_ON(sid); 109 node->link_on = SELF_ID_LINK_ON(sid);
110 node->phy_speed = SELF_ID_PHY_SPEED(sid); 110 node->phy_speed = SELF_ID_PHY_SPEED(sid);
111 node->initiated_reset = SELF_ID_PHY_INITIATOR(sid);
111 node->port_count = port_count; 112 node->port_count = port_count;
112 113
113 atomic_set(&node->ref_count, 1); 114 atomic_set(&node->ref_count, 1);
@@ -431,6 +432,8 @@ update_tree(struct fw_card *card, struct fw_node *root)
431 event = FW_NODE_LINK_OFF; 432 event = FW_NODE_LINK_OFF;
432 else if (!node0->link_on && node1->link_on) 433 else if (!node0->link_on && node1->link_on)
433 event = FW_NODE_LINK_ON; 434 event = FW_NODE_LINK_ON;
435 else if (node1->initiated_reset && node1->link_on)
436 event = FW_NODE_INITIATED_RESET;
434 else 437 else
435 event = FW_NODE_UPDATED; 438 event = FW_NODE_UPDATED;
436 439
diff --git a/drivers/firewire/fw-topology.h b/drivers/firewire/fw-topology.h
index cedc1ec906e9..addb9f8ea776 100644
--- a/drivers/firewire/fw-topology.h
+++ b/drivers/firewire/fw-topology.h
@@ -20,11 +20,12 @@
20#define __fw_topology_h 20#define __fw_topology_h
21 21
22enum { 22enum {
23 FW_NODE_CREATED = 0x00, 23 FW_NODE_CREATED,
24 FW_NODE_UPDATED = 0x01, 24 FW_NODE_UPDATED,
25 FW_NODE_DESTROYED = 0x02, 25 FW_NODE_DESTROYED,
26 FW_NODE_LINK_ON = 0x03, 26 FW_NODE_LINK_ON,
27 FW_NODE_LINK_OFF = 0x04, 27 FW_NODE_LINK_OFF,
28 FW_NODE_INITIATED_RESET,
28}; 29};
29 30
30struct fw_node { 31struct fw_node {