+static struct attribute *host_attributes[] = {
+ &class_device_attr_signalling.attr,
+ NULL
+};
+
+static struct attribute_group host_attribute_group = {
+ .attrs = host_attributes,
+};
+
+static int spi_host_configure(struct transport_container *tc,
+ struct device *dev,
+ struct class_device *cdev)
+{
+ struct kobject *kobj = &cdev->kobj;
+ struct Scsi_Host *shost = transport_class_to_shost(cdev);
+ struct spi_internal *si = to_spi_internal(shost->transportt);
+ struct attribute *attr = &class_device_attr_signalling.attr;
+ int rc = 0;
+
+ if (si->f->set_signalling)
+ rc = sysfs_chmod_file(kobj, attr, attr->mode | S_IWUSR);
+
+ return rc;
+}
+
+/* returns true if we should be showing the variable. Also
+ * overloads the return by setting 1<<1 if the attribute should
+ * be writeable */
+#define TARGET_ATTRIBUTE_HELPER(name) \
+ (si->f->show_##name ? 1 : 0) + \
+ (si->f->set_##name ? 2 : 0)
+
+static int target_attribute_is_visible(struct kobject *kobj,
+ struct attribute *attr, int i)
+{
+ struct class_device *cdev =
+ container_of(kobj, struct class_device, kobj);
+ struct scsi_target *starget = transport_class_to_starget(cdev);
+ struct Scsi_Host *shost = transport_class_to_shost(cdev);
+ struct spi_internal *si = to_spi_internal(shost->transportt);
+
+ if (attr == &class_device_attr_period.attr &&
+ spi_support_sync(starget))
+ return TARGET_ATTRIBUTE_HELPER(period);
+ else if (attr == &class_device_attr_min_period.attr &&
+ spi_support_sync(starget))
+ return TARGET_ATTRIBUTE_HELPER(period);
+ else if (attr == &class_device_attr_offset.attr &&
+ spi_support_sync(starget))
+ return TARGET_ATTRIBUTE_HELPER(offset);
+ else if (attr == &class_device_attr_max_offset.attr &&
+ spi_support_sync(starget))
+ return TARGET_ATTRIBUTE_HELPER(offset);
+ else if (attr == &class_device_attr_width.attr &&
+ spi_support_wide(starget))
+ return TARGET_ATTRIBUTE_HELPER(width);
+ else if (attr == &class_device_attr_max_width.attr &&
+ spi_support_wide(starget))
+ return TARGET_ATTRIBUTE_HELPER(width);
+ else if (attr == &class_device_attr_iu.attr &&
+ spi_support_ius(starget))
+ return TARGET_ATTRIBUTE_HELPER(iu);
+ else if (attr == &class_device_attr_dt.attr &&
+ spi_support_dt(starget))
+ return TARGET_ATTRIBUTE_HELPER(dt);
+ else if (attr == &class_device_attr_qas.attr &&
+ spi_support_qas(starget))
+ return TARGET_ATTRIBUTE_HELPER(qas);
+ else if (attr == &class_device_attr_wr_flow.attr &&
+ spi_support_ius(starget))
+ return TARGET_ATTRIBUTE_HELPER(wr_flow);
+ else if (attr == &class_device_attr_rd_strm.attr &&
+ spi_support_ius(starget))
+ return TARGET_ATTRIBUTE_HELPER(rd_strm);
+ else if (attr == &class_device_attr_rti.attr &&
+ spi_support_ius(starget))
+ return TARGET_ATTRIBUTE_HELPER(rti);
+ else if (attr == &class_device_attr_pcomp_en.attr &&
+ spi_support_ius(starget))
+ return TARGET_ATTRIBUTE_HELPER(pcomp_en);
+ else if (attr == &class_device_attr_hold_mcs.attr &&
+ spi_support_ius(starget))
+ return TARGET_ATTRIBUTE_HELPER(hold_mcs);
+ else if (attr == &class_device_attr_revalidate.attr)
+ return 1;
+
+ return 0;
+}
+
+static struct attribute *target_attributes[] = {
+ &class_device_attr_period.attr,
+ &class_device_attr_min_period.attr,
+ &class_device_attr_offset.attr,
+ &class_device_attr_max_offset.attr,
+ &class_device_attr_width.attr,
+ &class_device_attr_max_width.attr,
+ &class_device_attr_iu.attr,
+ &class_device_attr_dt.attr,
+ &class_device_attr_qas.attr,
+ &class_device_attr_wr_flow.attr,
+ &class_device_attr_rd_strm.attr,
+ &class_device_attr_rti.attr,
+ &class_device_attr_pcomp_en.attr,
+ &class_device_attr_hold_mcs.attr,
+ &class_device_attr_revalidate.attr,
+ NULL
+};
+
+static struct attribute_group target_attribute_group = {
+ .attrs = target_attributes,
+ .is_visible = target_attribute_is_visible,
+};
+
+static int spi_target_configure(struct transport_container *tc,
+ struct device *dev,
+ struct class_device *cdev)
+{
+ struct kobject *kobj = &cdev->kobj;
+ int i;
+ struct attribute *attr;
+ int rc;
+
+ for (i = 0; (attr = target_attributes[i]) != NULL; i++) {
+ int j = target_attribute_group.is_visible(kobj, attr, i);
+
+ /* FIXME: as well as returning -EEXIST, which we'd like
+ * to ignore, sysfs also does a WARN_ON and dumps a trace,
+ * which is bad, so temporarily, skip attributes that are
+ * already visible (the revalidate one) */
+ if (j && attr != &class_device_attr_revalidate.attr)
+ rc = sysfs_add_file_to_group(kobj, attr,
+ target_attribute_group.name);
+ /* and make the attribute writeable if we have a set
+ * function */
+ if ((j & 1))
+ rc = sysfs_chmod_file(kobj, attr, attr->mode | S_IWUSR);
+ }
+
+ return 0;
+}
+