]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/ieee1394/sbp2.c
i386: move mach-voyager
[linux-2.6-omap-h63xx.git] / drivers / ieee1394 / sbp2.c
index 875eadd5e8f551bcc5c261d892a1d4c3d6b24f49..a81ba8fca0db168314a2ce21aee0cecb0fd4f567 100644 (file)
@@ -118,14 +118,13 @@ MODULE_PARM_DESC(max_speed, "Force max speed "
                 "(3 = 800Mb/s, 2 = 400Mb/s, 1 = 200Mb/s, 0 = 100Mb/s)");
 
 /*
- * Set serialize_io to 1 if you'd like only one scsi command sent
- * down to us at a time (debugging). This might be necessary for very
- * badly behaved sbp2 devices.
+ * Set serialize_io to 0 or N to use dynamically appended lists of command ORBs.
+ * This is and always has been buggy in multiple subtle ways. See above TODOs.
  */
 static int sbp2_serialize_io = 1;
-module_param_named(serialize_io, sbp2_serialize_io, int, 0444);
-MODULE_PARM_DESC(serialize_io, "Serialize I/O coming from scsi drivers "
-                "(default = 1, faster = 0)");
+module_param_named(serialize_io, sbp2_serialize_io, bool, 0444);
+MODULE_PARM_DESC(serialize_io, "Serialize requests coming from SCSI drivers "
+                "(default = Y, faster but buggy = N)");
 
 /*
  * Bump up max_sectors if you'd like to support very large sized
@@ -154,9 +153,9 @@ MODULE_PARM_DESC(max_sectors, "Change max sectors per I/O supported "
  * are possible on OXFW911 and newer Oxsemi bridges.
  */
 static int sbp2_exclusive_login = 1;
-module_param_named(exclusive_login, sbp2_exclusive_login, int, 0644);
+module_param_named(exclusive_login, sbp2_exclusive_login, bool, 0644);
 MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device "
-                "(default = 1)");
+                "(default = Y, use N for concurrent initiators)");
 
 /*
  * If any of the following workarounds is required for your device to work,
@@ -194,6 +193,27 @@ MODULE_PARM_DESC(workarounds, "Work around device bugs (default = 0"
        ", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE)
        ", or a combination)");
 
+/*
+ * This influences the format of the sysfs attribute
+ * /sys/bus/scsi/devices/.../ieee1394_id.
+ *
+ * The default format is like in older kernels:  %016Lx:%d:%d
+ * It contains the target's EUI-64, a number given to the logical unit by
+ * the ieee1394 driver's nodemgr (starting at 0), and the LUN.
+ *
+ * The long format is:  %016Lx:%06x:%04x
+ * It contains the target's EUI-64, the unit directory's directory_ID as per
+ * IEEE 1212 clause 7.7.19, and the LUN.  This format comes closest to the
+ * format of SBP(-3) target port and logical unit identifier as per SAM (SCSI
+ * Architecture Model) rev.2 to 4 annex A.  Therefore and because it is
+ * independent of the implementation of the ieee1394 nodemgr, the longer format
+ * is recommended for future use.
+ */
+static int sbp2_long_sysfs_ieee1394_id;
+module_param_named(long_ieee1394_id, sbp2_long_sysfs_ieee1394_id, bool, 0644);
+MODULE_PARM_DESC(long_ieee1394_id, "8+3+2 bytes format of ieee1394_id in sysfs "
+                "(default = backwards-compatible = N, SAM-conforming = Y)");
+
 
 #define SBP2_INFO(fmt, args...)        HPSB_INFO("sbp2: "fmt, ## args)
 #define SBP2_ERR(fmt, args...) HPSB_ERR("sbp2: "fmt, ## args)
@@ -493,9 +513,9 @@ static int sbp2util_create_command_orb_pool(struct sbp2_lu *lu)
        return 0;
 }
 
-static void sbp2util_remove_command_orb_pool(struct sbp2_lu *lu)
+static void sbp2util_remove_command_orb_pool(struct sbp2_lu *lu,
+                                            struct hpsb_host *host)
 {
-       struct hpsb_host *host = lu->hi->host;
        struct list_head *lh, *next;
        struct sbp2_command_info *cmd;
        unsigned long flags;
@@ -753,11 +773,6 @@ static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *ud)
                        SBP2_ERR("failed to register lower 4GB address range");
                        goto failed_alloc;
                }
-#else
-               if (dma_set_mask(hi->host->device.parent, DMA_32BIT_MASK)) {
-                       SBP2_ERR("failed to set 4GB DMA mask");
-                       goto failed_alloc;
-               }
 #endif
        }
 
@@ -907,15 +922,16 @@ static void sbp2_remove_device(struct sbp2_lu *lu)
 
        if (!lu)
                return;
-
        hi = lu->hi;
+       if (!hi)
+               goto no_hi;
 
        if (lu->shost) {
                scsi_remove_host(lu->shost);
                scsi_host_put(lu->shost);
        }
        flush_scheduled_work();
-       sbp2util_remove_command_orb_pool(lu);
+       sbp2util_remove_command_orb_pool(lu, hi->host);
 
        list_del(&lu->lu_list);
 
@@ -956,9 +972,8 @@ static void sbp2_remove_device(struct sbp2_lu *lu)
 
        lu->ud->device.driver_data = NULL;
 
-       if (hi)
-               module_put(hi->host->driver->owner);
-
+       module_put(hi->host->driver->owner);
+no_hi:
        kfree(lu);
 }
 
@@ -1489,69 +1504,6 @@ static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
        }
 }
 
-static void sbp2_prep_command_orb_no_sg(struct sbp2_command_orb *orb,
-                                       struct sbp2_fwhost_info *hi,
-                                       struct sbp2_command_info *cmd,
-                                       struct scatterlist *sgpnt,
-                                       u32 orb_direction,
-                                       unsigned int scsi_request_bufflen,
-                                       void *scsi_request_buffer,
-                                       enum dma_data_direction dma_dir)
-{
-       cmd->dma_dir = dma_dir;
-       cmd->dma_size = scsi_request_bufflen;
-       cmd->dma_type = CMD_DMA_SINGLE;
-       cmd->cmd_dma = dma_map_single(hi->host->device.parent,
-                                     scsi_request_buffer,
-                                     cmd->dma_size, cmd->dma_dir);
-       orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
-       orb->misc |= ORB_SET_DIRECTION(orb_direction);
-
-       /* handle case where we get a command w/o s/g enabled
-        * (but check for transfers larger than 64K) */
-       if (scsi_request_bufflen <= SBP2_MAX_SG_ELEMENT_LENGTH) {
-
-               orb->data_descriptor_lo = cmd->cmd_dma;
-               orb->misc |= ORB_SET_DATA_SIZE(scsi_request_bufflen);
-
-       } else {
-               /* The buffer is too large. Turn this into page tables. */
-
-               struct sbp2_unrestricted_page_table *sg_element =
-                                               &cmd->scatter_gather_element[0];
-               u32 sg_count, sg_len;
-               dma_addr_t sg_addr;
-
-               orb->data_descriptor_lo = cmd->sge_dma;
-               orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
-
-               /* fill out our SBP-2 page tables; split up the large buffer */
-               sg_count = 0;
-               sg_len = scsi_request_bufflen;
-               sg_addr = cmd->cmd_dma;
-               while (sg_len) {
-                       sg_element[sg_count].segment_base_lo = sg_addr;
-                       if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) {
-                               sg_element[sg_count].length_segment_base_hi =
-                                       PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH);
-                               sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH;
-                               sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH;
-                       } else {
-                               sg_element[sg_count].length_segment_base_hi =
-                                       PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len);
-                               sg_len = 0;
-                       }
-                       sg_count++;
-               }
-
-               orb->misc |= ORB_SET_DATA_SIZE(sg_count);
-
-               sbp2util_cpu_to_be32_buffer(sg_element,
-                               (sizeof(struct sbp2_unrestricted_page_table)) *
-                               sg_count);
-       }
-}
-
 static void sbp2_create_command_orb(struct sbp2_lu *lu,
                                    struct sbp2_command_info *cmd,
                                    unchar *scsi_cmd,
@@ -1595,13 +1547,9 @@ static void sbp2_create_command_orb(struct sbp2_lu *lu,
                orb->data_descriptor_hi = 0x0;
                orb->data_descriptor_lo = 0x0;
                orb->misc |= ORB_SET_DIRECTION(1);
-       } else if (scsi_use_sg)
+       } else
                sbp2_prep_command_orb_sg(orb, hi, cmd, scsi_use_sg, sgpnt,
                                         orb_direction, dma_dir);
-       else
-               sbp2_prep_command_orb_no_sg(orb, hi, cmd, sgpnt, orb_direction,
-                                           scsi_request_bufflen,
-                                           scsi_request_buffer, dma_dir);
 
        sbp2util_cpu_to_be32_buffer(orb, sizeof(*orb));
 
@@ -1690,15 +1638,15 @@ static int sbp2_send_command(struct sbp2_lu *lu, struct scsi_cmnd *SCpnt,
                             void (*done)(struct scsi_cmnd *))
 {
        unchar *scsi_cmd = (unchar *)SCpnt->cmnd;
-       unsigned int request_bufflen = SCpnt->request_bufflen;
+       unsigned int request_bufflen = scsi_bufflen(SCpnt);
        struct sbp2_command_info *cmd;
 
        cmd = sbp2util_allocate_command_orb(lu, SCpnt, done);
        if (!cmd)
                return -EIO;
 
-       sbp2_create_command_orb(lu, cmd, scsi_cmd, SCpnt->use_sg,
-                               request_bufflen, SCpnt->request_buffer,
+       sbp2_create_command_orb(lu, cmd, scsi_cmd, scsi_sg_count(SCpnt),
+                               request_bufflen, scsi_sglist(SCpnt),
                                SCpnt->sc_data_direction);
        sbp2_link_orb_command(lu, cmd);
 
@@ -2100,8 +2048,14 @@ static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev,
        if (!(lu = (struct sbp2_lu *)sdev->host->hostdata[0]))
                return 0;
 
-       return sprintf(buf, "%016Lx:%d:%d\n", (unsigned long long)lu->ne->guid,
-                      lu->ud->id, ORB_SET_LUN(lu->lun));
+       if (sbp2_long_sysfs_ieee1394_id)
+               return sprintf(buf, "%016Lx:%06x:%04x\n",
+                               (unsigned long long)lu->ne->guid,
+                               lu->ud->directory_id, ORB_SET_LUN(lu->lun));
+       else
+               return sprintf(buf, "%016Lx:%d:%d\n",
+                               (unsigned long long)lu->ne->guid,
+                               lu->ud->id, ORB_SET_LUN(lu->lun));
 }
 
 MODULE_AUTHOR("Ben Collins <bcollins@debian.org>");