diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index f4a5fe623da9c25a66211725ff9ad7004e5264bd..a8d46b1243b77e7cd39aa851956b59859d0e3385 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -124,6 +124,7 @@
 #include <linux/spinlock.h>
 #include <linux/completion.h>
 #include <linux/sched.h>
+#include <linux/init.h>
 #include <linux/proc_fs.h>
 #include <asm/dma.h>
 #include <asm/system.h>
@@ -173,6 +174,8 @@ STATIC void NCR_700_chip_reset(struct Scsi_Host *host);
 STATIC int NCR_700_slave_configure(Scsi_Device *SDpnt);
 STATIC void NCR_700_slave_destroy(Scsi_Device *SDpnt);
 
+static struct device_attribute **NCR_700_dev_attrs = NULL;
+
 static char *NCR_700_phase[] = {
 	"",
 	"after selection",
@@ -247,6 +250,9 @@ NCR_700_detect(Scsi_Host_Template *tpnt,
 	static int banner = 0;
 	int j;
 
+	if(tpnt->sdev_attrs == NULL)
+		tpnt->sdev_attrs = NCR_700_dev_attrs;
+
 	memory = dma_alloc_noncoherent(hostdata->dev, TOTAL_MEM_SIZE,
 				       &pScript, GFP_KERNEL);
 	if(memory == NULL) {
@@ -2015,6 +2021,56 @@ NCR_700_slave_destroy(Scsi_Device *SDp)
 	/* to do here: deallocate memory */
 }
 
+static ssize_t
+NCR_700_store_queue_depth(struct device *dev, const char *buf, size_t count)
+{
+	int depth;
+
+	struct scsi_device *SDp = to_scsi_device(dev);
+	depth = simple_strtoul(buf, NULL, 0);
+	if(depth > NCR_700_MAX_TAGS)
+		return -EINVAL;
+	scsi_adjust_queue_depth(SDp, MSG_ORDERED_TAG, depth);
+
+	return count;
+}
+
+static ssize_t
+NCR_700_show_active_tags(struct device *dev, char *buf)
+{
+	struct scsi_device *SDp = to_scsi_device(dev);
+
+	return snprintf(buf, 20, "%d\n", NCR_700_get_depth(SDp));
+}
+
+static struct device_attribute NCR_700_queue_depth_attr = {
+	.attr = {
+		.name = 	"queue_depth",
+		.mode =		S_IWUSR,
+	},
+	.store = NCR_700_store_queue_depth,
+};
+
+static struct device_attribute NCR_700_active_tags_attr = {
+	.attr = {
+		.name =		"active_tags",
+		.mode =		S_IRUGO,
+	},
+	.show = NCR_700_show_active_tags,
+};
+
+STATIC int __init
+NCR_700_init(void)
+{
+	scsi_sysfs_modify_sdev_attribute(&NCR_700_dev_attrs,
+					 &NCR_700_queue_depth_attr);
+	scsi_sysfs_modify_sdev_attribute(&NCR_700_dev_attrs,
+					 &NCR_700_active_tags_attr);
+	return 0;
+}
+
 EXPORT_SYMBOL(NCR_700_detect);
 EXPORT_SYMBOL(NCR_700_release);
 EXPORT_SYMBOL(NCR_700_intr);
+
+module_init(NCR_700_init);
diff --git a/drivers/scsi/NCR_D700.c b/drivers/scsi/NCR_D700.c
index 687e62e184221877dab9266a619bbac58551f0bd..efe023a5f5f5ae5b8bd4eab3a9ef625ba95bf0ef 100644
--- a/drivers/scsi/NCR_D700.c
+++ b/drivers/scsi/NCR_D700.c
@@ -385,6 +385,7 @@ static int __init NCR_D700_init(void)
 static void __exit NCR_D700_exit(void)
 {
 	mca_unregister_driver(&NCR_D700_driver);
+	scsi_sysfs_release_attributes();
 }
 
 module_init(NCR_D700_init);
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 07e18b0b1ddad4849200e6c9b5f8e5badf2374f1..f4969be0edc0da0d9e08909934889984b7bf725e 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -321,7 +321,12 @@ struct Scsi_Host * scsi_register(Scsi_Host_Template *shost_tp, int xtr_bytes)
            shost_tp->eh_host_reset_handler == NULL) {
 		printk(KERN_ERR "ERROR: SCSI host `%s' has no error handling\nERROR: This is not a safe way to run your SCSI host\nERROR: The error handling must be added to this driver\n", shost_tp->proc_name);
 		dump_stack();
-        } 
+        }
+	if(shost_tp->shost_attrs == NULL)
+		/* if its not set in the template, use the default */
+		 shost_tp->shost_attrs = scsi_sysfs_shost_attrs;
+	if(shost_tp->sdev_attrs == NULL)
+		 shost_tp->sdev_attrs = scsi_sysfs_sdev_attrs;
 	gfp_mask = GFP_KERNEL;
 	if (shost_tp->unchecked_isa_dma && xtr_bytes)
 		gfp_mask |= __GFP_DMA;
diff --git a/drivers/scsi/hosts.h b/drivers/scsi/hosts.h
index 3d85a6f80012363a4d196c33f2c43e4b718ba930..0468c3c45fb0fc6beb7711c80403006832b944be 100644
--- a/drivers/scsi/hosts.h
+++ b/drivers/scsi/hosts.h
@@ -356,6 +356,16 @@ typedef struct	SHT
      * FIXME: This should probably be a value in the template */
     #define SCSI_DEFAULT_HOST_BLOCKED	7
 
+    /*
+     * pointer to the sysfs class properties for this host
+     */
+    struct class_device_attribute **shost_attrs;
+
+    /*
+     * Pointer to the SCSI device properties for this host
+     */
+    struct device_attribute **sdev_attrs;
+
 } Scsi_Host_Template;
 
 /*
@@ -588,4 +598,6 @@ static inline Scsi_Device *scsi_find_device(struct Scsi_Host *shost,
         return NULL;
 }
 
+extern void scsi_sysfs_release_attributes(struct SHT *hostt);
+
 #endif
diff --git a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h
index 5a8eefb32f24a8c179123d3b3fb2e1aa1b2db6e7..448fadd040554f0ec0bb34ca4dd3913634f89754 100644
--- a/drivers/scsi/scsi.h
+++ b/drivers/scsi/scsi.h
@@ -682,4 +682,9 @@ static inline Scsi_Cmnd *scsi_find_tag(Scsi_Device *SDpnt, int tag) {
 
 int scsi_set_medium_removal(Scsi_Device *dev, char state);
 
+extern int scsi_sysfs_modify_sdev_attribute(struct device_attribute ***dev_attrs,
+					    struct device_attribute *attr);
+extern int scsi_sysfs_modify_shost_attribute(struct class_device_attribute ***class_attrs,
+					     struct class_device_attribute *attr);
+
 #endif /* _SCSI_H */
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index 950c8f8861931c2e07ca3b44491ef1fc872d0673..dda78cf7c068be323aabdcacfd04cdfd1676caf0 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -131,4 +131,9 @@ extern void scsi_sysfs_remove_host(struct Scsi_Host *);
 extern int scsi_sysfs_register(void);
 extern void scsi_sysfs_unregister(void);
 
+/* definitions for the linker default sections covering the host
+ * class and device attributes */
+extern struct class_device_attribute *scsi_sysfs_shost_attrs[];
+extern struct device_attribute *scsi_sysfs_sdev_attrs[];
+
 #endif /* _SCSI_PRIV_H */
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 253440c915d78204e6ed768e03c53181b9273c7b..ddc82627983ccbaa3094fb201a982e67029d6348 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -45,12 +45,13 @@ shost_rd_attr(cmd_per_lun, "%hd\n");
 shost_rd_attr(sg_tablesize, "%hu\n");
 shost_rd_attr(unchecked_isa_dma, "%d\n");
 
-static struct class_device_attribute *const shost_attrs[] = {
+struct class_device_attribute *scsi_sysfs_shost_attrs[] = {
 	&class_device_attr_unique_id,
 	&class_device_attr_host_busy,
 	&class_device_attr_cmd_per_lun,
 	&class_device_attr_sg_tablesize,
 	&class_device_attr_unchecked_isa_dma,
+	NULL
 };
 
 static struct class shost_class = {
@@ -243,7 +244,8 @@ store_rescan_field (struct device *dev, const char *buf, size_t count)
 
 static DEVICE_ATTR(rescan, S_IRUGO | S_IWUSR, show_rescan_field, store_rescan_field)
 
-static struct device_attribute * const sdev_attrs[] = {
+/* Default template for device attributes.  May NOT be modified */
+struct device_attribute *scsi_sysfs_sdev_attrs[] = {
 	&dev_attr_device_blocked,
 	&dev_attr_queue_depth,
 	&dev_attr_type,
@@ -254,6 +256,7 @@ static struct device_attribute * const sdev_attrs[] = {
 	&dev_attr_rev,
 	&dev_attr_online,
 	&dev_attr_rescan,
+	NULL
 };
 
 static void scsi_device_release(struct device *dev)
@@ -287,9 +290,9 @@ int scsi_device_register(struct scsi_device *sdev)
 	if (error)
 		return error;
 
-	for (i = 0; !error && i < ARRAY_SIZE(sdev_attrs); i++)
+	for (i = 0; !error && sdev->host->hostt->sdev_attrs[i] != NULL; i++)
 		error = device_create_file(&sdev->sdev_driverfs_dev,
-					   sdev_attrs[i]);
+					   sdev->host->hostt->sdev_attrs[i]);
 
 	if (error)
 		scsi_device_unregister(sdev);
@@ -305,8 +308,8 @@ void scsi_device_unregister(struct scsi_device *sdev)
 {
 	int i;
 
-	for (i = 0; i < ARRAY_SIZE(sdev_attrs); i++)
-		device_remove_file(&sdev->sdev_driverfs_dev, sdev_attrs[i]);
+	for (i = 0; sdev->host->hostt->sdev_attrs[i] != NULL; i++)
+		device_remove_file(&sdev->sdev_driverfs_dev, sdev->host->hostt->sdev_attrs[i]);
 	device_unregister(&sdev->sdev_driverfs_dev);
 }
 
@@ -357,9 +360,9 @@ int scsi_sysfs_add_host(struct Scsi_Host *shost, struct device *dev)
 	if (error)
 		goto clean_device;
 
-	for (i = 0; !error && i < ARRAY_SIZE(shost_attrs); i++)
+	for (i = 0; !error && shost->hostt->shost_attrs[i] != NULL; i++)
 		error = class_device_create_file(&shost->class_dev,
-					   shost_attrs[i]);
+					   shost->hostt->shost_attrs[i]);
 	if (error)
 		goto clean_class;
 
@@ -383,3 +386,118 @@ void scsi_sysfs_remove_host(struct Scsi_Host *shost)
 	device_del(&shost->host_gendev);
 }
 
+/** scsi_sysfs_modify_shost_attribute - modify or add a host class attribute
+ *
+ * @class_attrs:host class attribute list to be added to or modified
+ * @attr:	individual attribute to change or added
+ *
+ * returns zero if successful or error if not
+ **/
+int scsi_sysfs_modify_shost_attribute(struct class_device_attribute ***class_attrs,
+				      struct class_device_attribute *attr)
+{
+	int modify = 0;
+	int num_attrs;
+
+	if(*class_attrs == NULL)
+		*class_attrs = scsi_sysfs_shost_attrs;
+
+	for(num_attrs=0; (*class_attrs)[num_attrs] != NULL; num_attrs++)
+		if(strcmp((*class_attrs)[num_attrs]->attr.name, attr->attr.name) == 0)
+			modify = num_attrs;
+
+	if(*class_attrs == scsi_sysfs_shost_attrs || !modify) {
+		/* note: need space for null at the end as well */
+		struct class_device_attribute **tmp_attrs = kmalloc(sizeof(struct class_device_attribute)*(num_attrs + (modify ? 1 : 2)), GFP_KERNEL);
+		if(tmp_attrs == NULL)
+			return -ENOMEM;
+		memcpy(tmp_attrs, *class_attrs, sizeof(struct class_device_attribute)*num_attrs);
+		if(*class_attrs != scsi_sysfs_shost_attrs)
+			kfree(*class_attrs);
+		*class_attrs = tmp_attrs;
+	}
+	if(modify) {
+		/* spare the caller from having to copy things it's
+		 * not interested in */
+		struct class_device_attribute *old_attr =
+			(*class_attrs)[modify];
+		/* extend permissions */
+		attr->attr.mode |= old_attr->attr.mode;
+
+		/* override null show/store with default */
+		if(attr->show == NULL)
+			attr->show = old_attr->show;
+		if(attr->store == NULL)
+			attr->store = old_attr->store;
+		(*class_attrs)[modify] = attr;
+	} else {
+		(*class_attrs)[num_attrs++] = attr;
+		(*class_attrs)[num_attrs] = NULL;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(scsi_sysfs_modify_shost_attribute);
+
+/** scsi_sysfs_modify_sdev_attribute - modify or add a host device attribute
+ *
+ * @dev_attrs:	pointer to the attribute list to be added to or modified
+ * @attr:	individual attribute to change or added
+ *
+ * returns zero if successful or error if not
+ **/
+int scsi_sysfs_modify_sdev_attribute(struct device_attribute ***dev_attrs,
+				     struct device_attribute *attr)
+{
+	int modify = 0;
+	int num_attrs;
+
+	if(*dev_attrs == NULL)
+		*dev_attrs = scsi_sysfs_sdev_attrs;
+
+	for(num_attrs=0; (*dev_attrs)[num_attrs] != NULL; num_attrs++)
+		if(strcmp((*dev_attrs)[num_attrs]->attr.name, attr->attr.name) == 0)
+			modify = num_attrs;
+
+	if(*dev_attrs == scsi_sysfs_sdev_attrs || !modify) {
+		/* note: need space for null at the end as well */
+		struct device_attribute **tmp_attrs = kmalloc(sizeof(struct device_attribute)*(num_attrs + (modify ? 1 : 2)), GFP_KERNEL);
+		if(tmp_attrs == NULL)
+			return -ENOMEM;
+		memcpy(tmp_attrs, *dev_attrs, sizeof(struct device_attribute)*num_attrs);
+		if(*dev_attrs != scsi_sysfs_sdev_attrs)
+			kfree(*dev_attrs);
+		*dev_attrs = tmp_attrs;
+	}
+	if(modify) {
+		/* spare the caller from having to copy things it's
+		 * not interested in */
+		struct device_attribute *old_attr =
+			(*dev_attrs)[modify];
+		/* extend permissions */
+		attr->attr.mode |= old_attr->attr.mode;
+
+		/* override null show/store with default */
+		if(attr->show == NULL)
+			attr->show = old_attr->show;
+		if(attr->store == NULL)
+			attr->store = old_attr->store;
+		(*dev_attrs)[modify] = attr;
+	} else {
+		(*dev_attrs)[num_attrs++] = attr;
+		(*dev_attrs)[num_attrs] = NULL;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(scsi_sysfs_modify_sdev_attribute);
+
+void scsi_sysfs_release_attributes(struct SHT *hostt)
+{
+	if(hostt->sdev_attrs != scsi_sysfs_sdev_attrs)
+		kfree(hostt->sdev_attrs);
+
+	if(hostt->shost_attrs != scsi_sysfs_shost_attrs)
+		kfree(hostt->shost_attrs);
+}
+EXPORT_SYMBOL(scsi_sysfs_release_attributes);