GIT 6429e0e94a9185b92b33f7b1bb0195eb54022a89 git+ssh://master.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6.git commit Author: Stefan Richter Date: Sun Sep 24 11:01:00 2006 +0200 ieee1394: ohci1394: suspend/resume cosmetics Reorder the definitions of ohci1394_pci_suspend and _resume. Remove redundant comments. Beautify return statements. Signed-off-by: Stefan Richter commit c914d3cf8c54ec472b93eed03dc515435aaf29d0 Author: Bernhard Kaindl Date: Wed Sep 6 14:58:30 2006 +0200 ieee1394: ohci1394: steps to implement suspend/resume I did a quick shot on what I described and the appended patch does the first thing needed for working suspend/resume in ohci1394 which is HW de- and re-initialisation. It works with suspend2disk on my Ricoh R5C552 IEEE 1394 Controller with the 2.6.17 kernel to the extent that if I call dvgrab --interactive after suspend2disk without unloading ohci1394, it does not lock up dvgrab with 100% CPU but properly connects to the camera, given that I first unplug and plug the camera after coming back from suspend. I guess that could be fixed by forcing a bus reset in the resume function. I cannot test suspend to RAM here at the moment and should follow the guidelines in Documentation/power/pci.txt also, so this is rather a quick report than a finished patch and there are some rough edges: However, with this patch, I have to unload at least some in-kernel users of ohci1394 like dv1394 or video1394 before suspending. Not doing that caused an Oops and a bad tasklet error, probably from not handling ISO tasklets during suspend/resume properly. Maybe these can be temporarily cleared or unregistered and re-registered for suspend/resume with help from the other layers or from the highlevel 1394 core, but I do not really know what these do. But this patch provides a useful base to start from and is already of much help for people which do not need dv1394 and video1394 or can unload them at least during suspend. I cannot test function with sbp2 at the moment, but raw1394 seems to work fine. Signed-off-by: Bernhard Kaindl Update: merge with previous two ohci1394 suspend/resume patches Signed-off-by: Stefan Richter commit 4dec0165b4793f467413dcafeced4757dc3e3fc9 Author: Stefan Richter Date: Thu Sep 14 22:06:48 2006 +0200 ieee1394: raw1394: add comments on lock usage Add a who-is-who about some locks and list heads in raw1394's struct definitions. Signed-off-by: Stefan Richter commit e575953ec17c3f5c1e738847d2d16c241bb99783 Author: Stefan Richter Date: Thu Sep 14 22:05:16 2006 +0200 ieee1394: raw1394: arm functions slept in atomic context Sleeping functions like copy_to_user were accessed inside spinlocks in raw1394's arm_register, arm_unregister, arm_get_buf, arm_set_buf. http://bugzilla.kernel.org/show_bug.cgi?id=7120 Signed-off-by: Stefan Richter Tested-by: David Trent commit 7db8c834c9169a76540104e05fe8c7ec47dbb5f3 Author: Stefan Richter Date: Mon Sep 11 20:17:14 2006 +0200 ieee1394: sbp2: slightly reorder sbp2scsi_abort Put the target's fetch agent into reset state before the underlying ORB DMA is unmapped and the ->done handler is called. It is highly unlikely but the target could access that ORB right before sbp2 sends the reset request. Signed-off-by: Stefan Richter commit 34d6ad74ff8007f2a8f67c551adeff4ab17583a7 Author: Stefan Richter Date: Wed Sep 6 23:42:00 2006 +0200 ieee1394: remove unused struct member from highlevel API struct hpsb_highlevel's struct module *owner is neither used by the IEEE 1394 core nor set by any of the in-tree drivers or the two out-of-tree highlevel drivers I know about (dfg1394, mem1394) --- nor is this member documented. An unscheduled removal seems acceptable. Signed-off-by: Stefan Richter drivers/ieee1394/highlevel.h | 1 drivers/ieee1394/ohci1394.c | 81 ++++++++++++++++++++++++++++-------- drivers/ieee1394/raw1394-private.h | 10 ++-- drivers/ieee1394/sbp2.c | 10 +--- 4 files changed, 69 insertions(+), 33 deletions(-) diff --git a/drivers/ieee1394/highlevel.h b/drivers/ieee1394/highlevel.h index 50f2dd2..4b33011 100644 --- a/drivers/ieee1394/highlevel.h +++ b/drivers/ieee1394/highlevel.h @@ -24,7 +24,6 @@ struct hpsb_address_serve { /* Only the following structures are of interest to actual highlevel drivers. */ struct hpsb_highlevel { - struct module *owner; const char *name; /* Any of the following pointers can legally be NULL, except for diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index dea1352..c835754 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -3529,49 +3529,92 @@ #endif /* CONFIG_PPC_PMAC */ } #ifdef CONFIG_PM -static int ohci1394_pci_resume (struct pci_dev *pdev) +static int ohci1394_pci_suspend(struct pci_dev *pdev, pm_message_t state) { -/* PowerMac resume code comes first */ + int err; + struct ti_ohci *ohci = pci_get_drvdata(pdev); + + PRINT(KERN_DEBUG, "suspend called"); + if (!ohci) + return -ENXIO; + + /* Clear the async DMA contexts and stop using the controller */ + hpsb_bus_reset(ohci->host); + + /* See ohci1394_pci_remove() for comments on this sequence */ + reg_write(ohci, OHCI1394_ConfigROMhdr, 0); + reg_write(ohci, OHCI1394_BusOptions, + (reg_read(ohci, OHCI1394_BusOptions) & 0x0000f007) | + 0x00ff0000); + reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff); + reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff); + reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff); + reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff); + reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff); + reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff); + set_phy_reg(ohci, 4, ~0xc0 & get_phy_reg(ohci, 4)); + reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff); + ohci_devctl(ohci->host, RESET_BUS, LONG_RESET_NO_FORCE_ROOT); + ohci_soft_reset(ohci); + + err = pci_save_state(pdev); + if (err) + return err; + err = pci_set_power_state(pdev, pci_choose_state(pdev, state)); + if (err) + return err; + +/* PowerMac suspend code comes last */ #ifdef CONFIG_PPC_PMAC if (machine_is(powermac)) { struct device_node *of_node; - /* Re-enable 1394 */ + /* Disable 1394 */ of_node = pci_device_to_OF_node (pdev); if (of_node) - pmac_call_feature (PMAC_FTR_1394_ENABLE, of_node, 0, 1); + pmac_call_feature(PMAC_FTR_1394_ENABLE, of_node, 0, 0); } #endif /* CONFIG_PPC_PMAC */ - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - return pci_enable_device(pdev); + return 0; } -static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state) +static int ohci1394_pci_resume(struct pci_dev *pdev) { int err; + struct ti_ohci *ohci = pci_get_drvdata(pdev); - err = pci_save_state(pdev); - if (err) - goto out; - err = pci_set_power_state(pdev, pci_choose_state(pdev, state)); - if (err) - goto out; + PRINT(KERN_DEBUG, "resume called"); + if (!ohci) + return -ENXIO; -/* PowerMac suspend code comes last */ +/* PowerMac resume code comes first */ #ifdef CONFIG_PPC_PMAC if (machine_is(powermac)) { struct device_node *of_node; - /* Disable 1394 */ + /* Re-enable 1394 */ of_node = pci_device_to_OF_node (pdev); if (of_node) - pmac_call_feature(PMAC_FTR_1394_ENABLE, of_node, 0, 0); + pmac_call_feature (PMAC_FTR_1394_ENABLE, of_node, 0, 1); } #endif /* CONFIG_PPC_PMAC */ -out: - return err; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + err = pci_enable_device(pdev); + if (err) + return err; + + /* See ohci1394_pci_probe() for comments on this sequence */ + ohci_soft_reset(ohci); + reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS); + reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff); + reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff); + mdelay(50); + ohci_initialize(ohci); + + return 0; } #endif /* CONFIG_PM */ diff --git a/drivers/ieee1394/raw1394-private.h b/drivers/ieee1394/raw1394-private.h index c7731d1..50daabf 100644 --- a/drivers/ieee1394/raw1394-private.h +++ b/drivers/ieee1394/raw1394-private.h @@ -27,12 +27,12 @@ struct file_info { struct hpsb_host *host; - struct list_head req_pending; - struct list_head req_complete; + struct list_head req_pending; /* protected by reqlists_lock */ + struct list_head req_complete; /* protected by reqlists_lock */ spinlock_t reqlists_lock; wait_queue_head_t wait_complete; - struct list_head addr_list; + struct list_head addr_list; /* protected by host_info_lock */ u8 __user *fcp_buffer; @@ -63,7 +63,7 @@ struct arm_addr { u8 client_transactions; u64 recvb; u16 rec_length; - u8 *addr_space_buffer; /* accessed by read/write/lock */ + u8 *addr_space_buffer; /* accessed by read/write/lock requests */ }; struct pending_request { @@ -79,7 +79,7 @@ struct pending_request { struct host_info { struct list_head list; struct hpsb_host *host; - struct list_head file_info_list; + struct list_head file_info_list; /* protected by host_info_lock */ }; #endif /* IEEE1394_RAW1394_PRIVATE_H */ diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 6986ac1..a155d96 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -2560,11 +2560,9 @@ static int sbp2scsi_abort(struct scsi_cm scsi_print_command(SCpnt); if (sbp2util_node_is_available(scsi_id)) { + sbp2_agent_reset(scsi_id, 1); - /* - * Right now, just return any matching command structures - * to the free pool. - */ + /* Return a matching command structure to the free pool. */ spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); command = sbp2util_find_command_for_SCpnt(scsi_id, SCpnt); if (command) { @@ -2585,10 +2583,6 @@ static int sbp2scsi_abort(struct scsi_cm } spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); - /* - * Initiate a fetch agent reset. - */ - sbp2_agent_reset(scsi_id, 1); sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY); }