GIT 1be7be03e875c53ac7575ab458606dc14ae199e5 git+ssh://master.kernel.org/pub/scm/linux/kernel/git/scjody/ieee1394.git#for-mm commit 1be7be03e875c53ac7575ab458606dc14ae199e5 Author: Stefan Richter Date: Tue Jan 31 00:13:49 2006 -0500 ohci1394: log physical posted write errors Give a warning if incoming write requests to the physical range fail. Signed-off-by: Stefan Richter Signed-off-by: Jody McIntyre commit b2d38cccad4ef80d6b672b8f89aae5fe2907b113 Author: Stefan Richter Date: Tue Jan 31 00:13:33 2006 -0500 sbp2: variable status FIFO address (fix login timeout) Let the ieee1394 core select a suitable 1394 address range for sbp2's status FIFO instead of using a fixed range. Since the core only selects addresses which are guaranteed to be out of the "physical range" as per OHCI 1.1, this patch also fixes an old bug: OHCI controllers which implement a writeable PhysicalUpperBound register included sbp2's status FIFO in the physical range. That way sbp2 was never notified of a succesful login and always failed after timeout. Affected OHCI host adapters include ALi and Fujitsu controllers. As another side effect of this patch, the status FIFO is no longer located in a range for which OHCI chips perform "posted writes". Each status write now requires a response subaction. But since large data transfers involve only few status writes, there is no measurable decrease of I/O throughput. What's more, the status FIFO is now safe from potential host bus errors. Nevertheless, posted writes could be re-enabled by extensions to the ARM features of the 1394 stack. Signed-off-by: Stefan Richter Signed-off-by: Jody McIntyre commit 61daa34c132c5d4ed8630e2c46e9bf2f0c7b3428 Author: Stefan Richter Date: Tue Jan 31 00:13:06 2006 -0500 sbp2: fix another deadlock after disconnection If there were commands enqueued but not completed before an SBP-2 unit was unplugged (or an attempt to reconnect failed), knodemgrd or any process which tried to remove the device would sleep uninterruptibly in blk_execute_rq(). Therefore make sure that all commands are completed when sbp2 retreats. Signed-off-by: Stefan Richter Signed-off-by: Jody McIntyre commit d415a9a9685578058800f2677bfeb8090fc212a1 Author: Stefan Richter Date: Tue Jan 31 00:12:01 2006 -0500 sbp2: prevent unloading of 1394 low-level driver When a new SBP-2 unit is added, sbp2 now takes a reference on the 1394 low-level driver (ohci1394 or pcilynx). This prevents the 1394 host driver module from being unloaded, e.g. by an administrative routine cleanup of unused kernel modules or when another 1394 driver which depends on ohci1394 is unloaded. The reference is dropped when the SBP-2 unit was disconnected, when sbp2 is unloaded or detached from the unit, or when addition of the SBP-2 unit failed. Signed-off-by: Stefan Richter Signed-off-by: Jody McIntyre commit 9857ae47369e953b77193d20984ccfc69deb4c22 Author: Jody McIntyre Date: Tue Jan 31 00:11:24 2006 -0500 This patch allows building the modules with an absolute SUBDIRS path, especially for building them out of tree. Signed-Off-By: Johannes Berg Signed-off-by: Jody McIntyre --- diff --git a/drivers/ieee1394/Makefile b/drivers/ieee1394/Makefile index 6f53611..180bf82 100644 --- a/drivers/ieee1394/Makefile +++ b/drivers/ieee1394/Makefile @@ -16,7 +16,7 @@ obj-$(CONFIG_IEEE1394_DV1394) += dv1394. obj-$(CONFIG_IEEE1394_ETH1394) += eth1394.o quiet_cmd_oui2c = OUI2C $@ - cmd_oui2c = $(CONFIG_SHELL) $(srctree)/$(src)/oui2c.sh < $< > $@ + cmd_oui2c = $(CONFIG_SHELL) $(src)/oui2c.sh < $< > $@ targets := oui.c $(obj)/oui.o: $(obj)/oui.c diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index b6b96fa..eb329a8 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -572,6 +572,7 @@ static void ohci_initialize(struct ti_oh OHCI1394_reqTxComplete | OHCI1394_isochRx | OHCI1394_isochTx | + OHCI1394_postedWriteErr | OHCI1394_cycleInconsistent); /* Enable link */ @@ -2374,7 +2375,10 @@ static irqreturn_t ohci_irq_handler(int event &= ~OHCI1394_unrecoverableError; } - + if (event & OHCI1394_postedWriteErr) { + PRINT(KERN_ERR, "physical posted write error"); + /* no recovery strategy yet, had to involve protocol drivers */ + } if (event & OHCI1394_cycleInconsistent) { /* We subscribe to the cycleInconsistent event only to * clear the corresponding event bit... otherwise, @@ -2382,7 +2386,6 @@ static irqreturn_t ohci_irq_handler(int DBGMSG("OHCI1394_cycleInconsistent"); event &= ~OHCI1394_cycleInconsistent; } - if (event & OHCI1394_busReset) { /* The busReset event bit can't be cleared during the * selfID phase, so we disable busReset interrupts, to @@ -2426,7 +2429,6 @@ static irqreturn_t ohci_irq_handler(int } event &= ~OHCI1394_busReset; } - if (event & OHCI1394_reqTxComplete) { struct dma_trm_ctx *d = &ohci->at_req_context; DBGMSG("Got reqTxComplete interrupt " diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 18d7eda..81d7243 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -643,9 +643,15 @@ static int sbp2_remove(struct device *de if (!scsi_id) return 0; - /* Trigger shutdown functions in scsi's highlevel. */ - if (scsi_id->scsi_host) + if (scsi_id->scsi_host) { + /* Get rid of enqueued commands if there is no chance to + * send them. */ + if (!sbp2util_node_is_available(scsi_id)) + sbp2scsi_complete_all_commands(scsi_id, DID_NO_CONNECT); + /* scsi_remove_device() will trigger shutdown functions of SCSI + * highlevel drivers which would deadlock if blocked. */ scsi_unblock_requests(scsi_id->scsi_host); + } sdev = scsi_id->sdev; if (sdev) { scsi_id->sdev = NULL; @@ -742,11 +748,6 @@ static struct scsi_id_instance_data *sbp hi->host = ud->ne->host; INIT_LIST_HEAD(&hi->scsi_ids); - /* Register our sbp2 status address space... */ - hpsb_register_addrspace(&sbp2_highlevel, ud->ne->host, &sbp2_ops, - SBP2_STATUS_FIFO_ADDRESS, - SBP2_STATUS_FIFO_ADDRESS + - SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(SBP2_MAX_UDS_PER_NODE+1)); #ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA /* Handle data movement if physical dma is not * enabled/supportedon host controller */ @@ -755,10 +756,28 @@ static struct scsi_id_instance_data *sbp #endif } + /* Prevent unloading of the 1394 host */ + if (!try_module_get(hi->host->driver->owner)) { + SBP2_ERR("failed to get a reference on 1394 host driver"); + goto failed_alloc; + } + scsi_id->hi = hi; list_add_tail(&scsi_id->scsi_list, &hi->scsi_ids); + /* Register the status FIFO address range. We could use the same FIFO + * for targets at different nodes. However we need different FIFOs per + * target in order to support multi-unit devices. */ + scsi_id->status_fifo_addr = hpsb_allocate_and_register_addrspace( + &sbp2_highlevel, ud->ne->host, &sbp2_ops, + sizeof(struct sbp2_status_block), sizeof(quadlet_t), + ~0ULL, ~0ULL); + if (!scsi_id->status_fifo_addr) { + SBP2_ERR("failed to allocate status FIFO address range"); + goto failed_alloc; + } + /* Register our host with the SCSI stack. */ scsi_host = scsi_host_alloc(&scsi_driver_template, sizeof(unsigned long)); @@ -997,8 +1016,15 @@ static void sbp2_remove_device(struct sc SBP2_DMA_FREE("single query logins data"); } + if (scsi_id->status_fifo_addr) + hpsb_unregister_addrspace(&sbp2_highlevel, hi->host, + scsi_id->status_fifo_addr); + scsi_id->ud->device.driver_data = NULL; + if (hi) + module_put(hi->host->driver->owner); + SBP2_DEBUG("SBP-2 device removed, SCSI ID = %d", scsi_id->ud->id); kfree(scsi_id); @@ -1075,11 +1101,10 @@ static int sbp2_query_logins(struct scsi ORB_SET_QUERY_LOGINS_RESP_LENGTH(sizeof(struct sbp2_query_logins_response)); SBP2_DEBUG("sbp2_query_logins: reserved_resp_length initialized"); - scsi_id->query_logins_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO + - SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->ud->id); - scsi_id->query_logins_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) | - SBP2_STATUS_FIFO_ADDRESS_HI); - SBP2_DEBUG("sbp2_query_logins: status FIFO initialized"); + scsi_id->query_logins_orb->status_fifo_hi = + ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id); + scsi_id->query_logins_orb->status_fifo_lo = + ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr); sbp2util_cpu_to_be32_buffer(scsi_id->query_logins_orb, sizeof(struct sbp2_query_logins_orb)); @@ -1184,11 +1209,10 @@ static int sbp2_login_device(struct scsi ORB_SET_LOGIN_RESP_LENGTH(sizeof(struct sbp2_login_response)); SBP2_DEBUG("sbp2_login_device: passwd_resp_lengths initialized"); - scsi_id->login_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO + - SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->ud->id); - scsi_id->login_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) | - SBP2_STATUS_FIFO_ADDRESS_HI); - SBP2_DEBUG("sbp2_login_device: status FIFO initialized"); + scsi_id->login_orb->status_fifo_hi = + ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id); + scsi_id->login_orb->status_fifo_lo = + ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr); /* * Byte swap ORB if necessary @@ -1301,10 +1325,10 @@ static int sbp2_logout_device(struct scs scsi_id->logout_orb->login_ID_misc |= ORB_SET_NOTIFY(1); scsi_id->logout_orb->reserved5 = 0x0; - scsi_id->logout_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO + - SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->ud->id); - scsi_id->logout_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) | - SBP2_STATUS_FIFO_ADDRESS_HI); + scsi_id->logout_orb->status_fifo_hi = + ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id); + scsi_id->logout_orb->status_fifo_lo = + ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr); /* * Byte swap ORB if necessary @@ -1366,10 +1390,10 @@ static int sbp2_reconnect_device(struct scsi_id->reconnect_orb->login_ID_misc |= ORB_SET_NOTIFY(1); scsi_id->reconnect_orb->reserved5 = 0x0; - scsi_id->reconnect_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO + - SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->ud->id); - scsi_id->reconnect_orb->status_FIFO_hi = - (ORB_SET_NODE_ID(hi->host->node_id) | SBP2_STATUS_FIFO_ADDRESS_HI); + scsi_id->reconnect_orb->status_fifo_hi = + ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id); + scsi_id->reconnect_orb->status_fifo_lo = + ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr); /* * Byte swap ORB if necessary @@ -2114,7 +2138,6 @@ static int sbp2_handle_status_write(stru { struct sbp2scsi_host_info *hi; struct scsi_id_instance_data *scsi_id = NULL, *scsi_id_tmp; - u32 id; struct scsi_cmnd *SCpnt = NULL; u32 scsi_status = SBP2_SCSI_STATUS_GOOD; struct sbp2_command_info *command; @@ -2137,12 +2160,12 @@ static int sbp2_handle_status_write(stru } /* - * Find our scsi_id structure by looking at the status fifo address written to by - * the sbp2 device. + * Find our scsi_id structure by looking at the status fifo address + * written to by the sbp2 device. */ - id = SBP2_STATUS_FIFO_OFFSET_TO_ENTRY((u32)(addr - SBP2_STATUS_FIFO_ADDRESS)); list_for_each_entry(scsi_id_tmp, &hi->scsi_ids, scsi_list) { - if (scsi_id_tmp->ne->nodeid == nodeid && scsi_id_tmp->ud->id == id) { + if (scsi_id_tmp->ne->nodeid == nodeid && + scsi_id_tmp->status_fifo_addr == addr) { scsi_id = scsi_id_tmp; break; } diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h index 900ea1d..e2d357a 100644 --- a/drivers/ieee1394/sbp2.h +++ b/drivers/ieee1394/sbp2.h @@ -33,15 +33,17 @@ #define ORB_DIRECTION_NO_DATA_TRANSFER 0x2 #define ORB_SET_NULL_PTR(value) ((value & 0x1) << 31) -#define ORB_SET_NOTIFY(value) ((value & 0x1) << 31) -#define ORB_SET_RQ_FMT(value) ((value & 0x3) << 29) /* unused ? */ +#define ORB_SET_NOTIFY(value) ((value & 0x1) << 31) +#define ORB_SET_RQ_FMT(value) ((value & 0x3) << 29) /* unused ? */ #define ORB_SET_NODE_ID(value) ((value & 0xffff) << 16) -#define ORB_SET_DATA_SIZE(value) (value & 0xffff) -#define ORB_SET_PAGE_SIZE(value) ((value & 0x7) << 16) -#define ORB_SET_PAGE_TABLE_PRESENT(value) ((value & 0x1) << 19) -#define ORB_SET_MAX_PAYLOAD(value) ((value & 0xf) << 20) -#define ORB_SET_SPEED(value) ((value & 0x7) << 24) -#define ORB_SET_DIRECTION(value) ((value & 0x1) << 27) +#define ORB_SET_STATUS_FIFO_HI(value, id) (value >> 32 | ORB_SET_NODE_ID(id)) +#define ORB_SET_STATUS_FIFO_LO(value) (value & 0xffffffff) +#define ORB_SET_DATA_SIZE(value) (value & 0xffff) +#define ORB_SET_PAGE_SIZE(value) ((value & 0x7) << 16) +#define ORB_SET_PAGE_TABLE_PRESENT(value) ((value & 0x1) << 19) +#define ORB_SET_MAX_PAYLOAD(value) ((value & 0xf) << 20) +#define ORB_SET_SPEED(value) ((value & 0x7) << 24) +#define ORB_SET_DIRECTION(value) ((value & 0x1) << 27) struct sbp2_command_orb { volatile u32 next_ORB_hi; @@ -76,8 +78,8 @@ struct sbp2_login_orb { u32 login_response_lo; u32 lun_misc; u32 passwd_resp_lengths; - u32 status_FIFO_hi; - u32 status_FIFO_lo; + u32 status_fifo_hi; + u32 status_fifo_lo; }; #define RESPONSE_GET_LOGIN_ID(value) (value & 0xffff) @@ -102,8 +104,8 @@ struct sbp2_query_logins_orb { u32 query_response_lo; u32 lun_misc; u32 reserved_resp_length; - u32 status_FIFO_hi; - u32 status_FIFO_lo; + u32 status_fifo_hi; + u32 status_fifo_lo; }; #define RESPONSE_GET_MAX_LOGINS(value) (value & 0xffff) @@ -123,8 +125,8 @@ struct sbp2_reconnect_orb { u32 reserved4; u32 login_ID_misc; u32 reserved5; - u32 status_FIFO_hi; - u32 status_FIFO_lo; + u32 status_fifo_hi; + u32 status_fifo_lo; }; struct sbp2_logout_orb { @@ -134,8 +136,8 @@ struct sbp2_logout_orb { u32 reserved4; u32 login_ID_misc; u32 reserved5; - u32 status_FIFO_hi; - u32 status_FIFO_lo; + u32 status_fifo_hi; + u32 status_fifo_lo; }; #define PAGE_TABLE_SET_SEGMENT_BASE_HI(value) (value & 0xffff) @@ -195,30 +197,6 @@ struct sbp2_status_block { * Miscellaneous SBP2 related config rom defines */ -/* The status fifo address definition below is used as a base for each - * node, which a chunk seperately assigned to each unit directory in the - * node. For example, 0xfffe00000000ULL is used for the first sbp2 device - * detected on node 0, 0xfffe00000020ULL for the next sbp2 device on node - * 0, and so on. - * - * Note: We could use a single status fifo address for all sbp2 devices, - * and figure out which sbp2 device the status belongs to by looking at - * the source node id of the status write... but, using separate addresses - * for each sbp2 unit directory allows for better code and the ability to - * support multiple luns within a single 1394 node. - * - * Also note that we choose the address range below as it is a region - * specified for write posting, where the ohci controller will - * automatically send an ack_complete when the status is written by the - * sbp2 device... saving a split transaction. =) - */ -#define SBP2_STATUS_FIFO_ADDRESS 0xfffe00000000ULL -#define SBP2_STATUS_FIFO_ADDRESS_HI 0xfffe -#define SBP2_STATUS_FIFO_ADDRESS_LO 0x0 - -#define SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(entry) ((entry) << 5) -#define SBP2_STATUS_FIFO_OFFSET_TO_ENTRY(offset) ((offset) >> 5) - #define SBP2_UNIT_DIRECTORY_OFFSET_KEY 0xd1 #define SBP2_CSR_OFFSET_KEY 0x54 #define SBP2_UNIT_SPEC_ID_KEY 0x12 @@ -258,7 +236,6 @@ struct sbp2_status_block { */ #define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000 -#define SBP2_MAX_UDS_PER_NODE 16 /* Maximum scsi devices per node */ #define SBP2_MAX_SECTORS 255 /* Max sectors supported */ #define SBP2_MAX_CMDS 8 /* This should be safe */ @@ -338,6 +315,11 @@ struct scsi_id_instance_data { u32 sbp2_firmware_revision; /* + * Address for the device to write status blocks to + */ + u64 status_fifo_addr; + + /* * Variable used for logins, reconnects, logouts, query logins */ atomic_t sbp2_login_complete;