aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Richter <stefanr@s5r6.in-berlin.de>2006-07-23 16:12:00 -0400
committerStefan Richter <stefanr@s5r6.in-berlin.de>2006-09-17 13:19:25 -0400
commitcc078189125db84a85a3bbb82df788b84fc68aa1 (patch)
tree223a5db571c2717fac380df21f3ee56f7c395728
parent9154df538fa044ac2b729ae5c6c47cae09e6977f (diff)
ieee1394: sbp2: safer last_orb and next_ORB handling
The sbp2 initiator has two ways to tell a target's fetch agent about new command ORBs: - Write the ORB's address to the ORB_POINTER register. This must not be done while the fetch agent is active. - Put the ORB's address into the previously submitted ORB's next_ORB field and write to the DOORBELL register. This may be done while the fetch agent is active or suspended. It must not be done while the fetch agent is in reset state. Sbp2 has a last_orb pointer which indicates in what way a new command should be announced. That pointer is concurrently accessed at various occasions. Furthermore, initiator and target are accessing the next_ORB field of ORBs concurrently and asynchronously. This patch does: - Protect all initiator accesses to last_orb by sbp2_command_orb_lock. - Add pci_dma_sync_single_for_device before a previously submitted ORB's next_ORB field is overwritten. - Insert a memory barrier between when next_ORB_lo and next_ORB_hi are overwritten. Next_ORB_hi must not be updated before next_ORB_lo. - Remove the rather unspecific and now superfluous qualifier "volatile" from the next_ORB fields. - Add comments on how last_orb is connected with what is known about the target's fetch agent's state. Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
-rw-r--r--drivers/ieee1394/sbp2.c101
-rw-r--r--drivers/ieee1394/sbp2.h4
2 files changed, 50 insertions, 55 deletions
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index baa063c9e6e3..e312d5e2a647 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -1705,6 +1705,7 @@ static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait)
1705 quadlet_t data; 1705 quadlet_t data;
1706 u64 addr; 1706 u64 addr;
1707 int retval; 1707 int retval;
1708 unsigned long flags;
1708 1709
1709 SBP2_DEBUG_ENTER(); 1710 SBP2_DEBUG_ENTER();
1710 1711
@@ -1724,7 +1725,9 @@ static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait)
1724 /* 1725 /*
1725 * Need to make sure orb pointer is written on next command 1726 * Need to make sure orb pointer is written on next command
1726 */ 1727 */
1728 spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
1727 scsi_id->last_orb = NULL; 1729 scsi_id->last_orb = NULL;
1730 spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
1728 1731
1729 return 0; 1732 return 0;
1730} 1733}
@@ -1966,8 +1969,12 @@ static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id,
1966{ 1969{
1967 struct sbp2scsi_host_info *hi = scsi_id->hi; 1970 struct sbp2scsi_host_info *hi = scsi_id->hi;
1968 struct sbp2_command_orb *command_orb = &command->command_orb; 1971 struct sbp2_command_orb *command_orb = &command->command_orb;
1969 struct node_entry *ne = scsi_id->ne; 1972 struct sbp2_command_orb *last_orb;
1970 u64 addr; 1973 dma_addr_t last_orb_dma;
1974 u64 addr = scsi_id->sbp2_command_block_agent_addr;
1975 quadlet_t data[2];
1976 size_t length;
1977 unsigned long flags;
1971 1978
1972 outstanding_orb_incr; 1979 outstanding_orb_incr;
1973 SBP2_ORB_DEBUG("sending command orb %p, total orbs = %x", 1980 SBP2_ORB_DEBUG("sending command orb %p, total orbs = %x",
@@ -1982,64 +1989,50 @@ static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id,
1982 /* 1989 /*
1983 * Check to see if there are any previous orbs to use 1990 * Check to see if there are any previous orbs to use
1984 */ 1991 */
1985 if (scsi_id->last_orb == NULL) { 1992 spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
1986 quadlet_t data[2]; 1993 last_orb = scsi_id->last_orb;
1987 1994 last_orb_dma = scsi_id->last_orb_dma;
1995 if (!last_orb) {
1988 /* 1996 /*
1989 * Ok, let's write to the target's management agent register 1997 * last_orb == NULL means: We know that the target's fetch agent
1998 * is not active right now.
1990 */ 1999 */
1991 addr = scsi_id->sbp2_command_block_agent_addr + SBP2_ORB_POINTER_OFFSET; 2000 addr += SBP2_ORB_POINTER_OFFSET;
1992 data[0] = ORB_SET_NODE_ID(hi->host->node_id); 2001 data[0] = ORB_SET_NODE_ID(hi->host->node_id);
1993 data[1] = command->command_orb_dma; 2002 data[1] = command->command_orb_dma;
1994 sbp2util_cpu_to_be32_buffer(data, 8); 2003 sbp2util_cpu_to_be32_buffer(data, 8);
1995 2004 length = 8;
1996 SBP2_ORB_DEBUG("write command agent, command orb %p", command_orb);
1997
1998 if (sbp2util_node_write_no_wait(ne, addr, data, 8) < 0) {
1999 SBP2_ERR("sbp2util_node_write_no_wait failed.\n");
2000 return -EIO;
2001 }
2002
2003 SBP2_ORB_DEBUG("write command agent complete");
2004
2005 scsi_id->last_orb = command_orb;
2006 scsi_id->last_orb_dma = command->command_orb_dma;
2007
2008 } else { 2005 } else {
2009 quadlet_t data;
2010
2011 /* 2006 /*
2012 * We have an orb already sent (maybe or maybe not 2007 * last_orb != NULL means: We know that the target's fetch agent
2013 * processed) that we can append this orb to. So do so, 2008 * is (very probably) not dead or in reset state right now.
2014 * and ring the doorbell. Have to be very careful 2009 * We have an ORB already sent that we can append a new one to.
2015 * modifying these next orb pointers, as they are accessed 2010 * The target's fetch agent may or may not have read this
2016 * both by the sbp2 device and us. 2011 * previous ORB yet.
2017 */ 2012 */
2018 scsi_id->last_orb->next_ORB_lo = 2013 pci_dma_sync_single_for_cpu(hi->host->pdev, last_orb_dma,
2019 cpu_to_be32(command->command_orb_dma); 2014 sizeof(struct sbp2_command_orb),
2015 PCI_DMA_BIDIRECTIONAL);
2016 last_orb->next_ORB_lo = cpu_to_be32(command->command_orb_dma);
2017 wmb();
2020 /* Tells hardware that this pointer is valid */ 2018 /* Tells hardware that this pointer is valid */
2021 scsi_id->last_orb->next_ORB_hi = 0x0; 2019 last_orb->next_ORB_hi = 0;
2022 pci_dma_sync_single_for_device(hi->host->pdev, 2020 pci_dma_sync_single_for_device(hi->host->pdev, last_orb_dma,
2023 scsi_id->last_orb_dma,
2024 sizeof(struct sbp2_command_orb), 2021 sizeof(struct sbp2_command_orb),
2025 PCI_DMA_BIDIRECTIONAL); 2022 PCI_DMA_BIDIRECTIONAL);
2023 addr += SBP2_DOORBELL_OFFSET;
2024 data[0] = 0;
2025 length = 4;
2026 }
2027 scsi_id->last_orb = command_orb;
2028 scsi_id->last_orb_dma = command->command_orb_dma;
2029 spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
2026 2030
2027 /* 2031 SBP2_ORB_DEBUG("write to %s register, command orb %p",
2028 * Ring the doorbell 2032 last_orb ? "DOORBELL" : "ORB_POINTER", command_orb);
2029 */ 2033 if (sbp2util_node_write_no_wait(scsi_id->ne, addr, data, length) < 0) {
2030 data = cpu_to_be32(command->command_orb_dma); 2034 SBP2_ERR("sbp2util_node_write_no_wait failed.\n");
2031 addr = scsi_id->sbp2_command_block_agent_addr + SBP2_DOORBELL_OFFSET; 2035 return -EIO;
2032
2033 SBP2_ORB_DEBUG("ring doorbell, command orb %p", command_orb);
2034
2035 if (sbp2util_node_write_no_wait(ne, addr, &data, 4) < 0) {
2036 SBP2_ERR("sbp2util_node_write_no_wait failed");
2037 return -EIO;
2038 }
2039
2040 scsi_id->last_orb = command_orb;
2041 scsi_id->last_orb_dma = command->command_orb_dma;
2042
2043 } 2036 }
2044 return 0; 2037 return 0;
2045} 2038}
@@ -2231,14 +2224,16 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
2231 } 2224 }
2232 2225
2233 /* 2226 /*
2234 * Check here to see if there are no commands in-use. If there are none, we can 2227 * Check here to see if there are no commands in-use. If there
2235 * null out last orb so that next time around we write directly to the orb pointer... 2228 * are none, we know that the fetch agent left the active state
2236 * Quick start saves one 1394 bus transaction. 2229 * _and_ that we did not reactivate it yet. Therefore clear
2230 * last_orb so that next time we write directly to the
2231 * ORB_POINTER register. That way the fetch agent does not need
2232 * to refetch the next_ORB.
2237 */ 2233 */
2238 spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); 2234 spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
2239 if (list_empty(&scsi_id->sbp2_command_orb_inuse)) { 2235 if (list_empty(&scsi_id->sbp2_command_orb_inuse))
2240 scsi_id->last_orb = NULL; 2236 scsi_id->last_orb = NULL;
2241 }
2242 spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); 2237 spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
2243 2238
2244 } else { 2239 } else {
diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h
index b22ce1aa8fe4..dd80906e8a92 100644
--- a/drivers/ieee1394/sbp2.h
+++ b/drivers/ieee1394/sbp2.h
@@ -46,8 +46,8 @@
46#define ORB_SET_DIRECTION(value) ((value & 0x1) << 27) 46#define ORB_SET_DIRECTION(value) ((value & 0x1) << 27)
47 47
48struct sbp2_command_orb { 48struct sbp2_command_orb {
49 volatile u32 next_ORB_hi; 49 u32 next_ORB_hi;
50 volatile u32 next_ORB_lo; 50 u32 next_ORB_lo;
51 u32 data_descriptor_hi; 51 u32 data_descriptor_hi;
52 u32 data_descriptor_lo; 52 u32 data_descriptor_lo;
53 u32 misc; 53 u32 misc;