diff options
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/scsi_transport_spi.c | 258 |
1 files changed, 176 insertions, 82 deletions
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 4df21c92ff1e..1fb60313a516 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c | |||
@@ -52,13 +52,6 @@ | |||
52 | struct spi_internal { | 52 | struct spi_internal { |
53 | struct scsi_transport_template t; | 53 | struct scsi_transport_template t; |
54 | struct spi_function_template *f; | 54 | struct spi_function_template *f; |
55 | /* The actual attributes */ | ||
56 | struct class_device_attribute private_attrs[SPI_NUM_ATTRS]; | ||
57 | /* The array of null terminated pointers to attributes | ||
58 | * needed by scsi_sysfs.c */ | ||
59 | struct class_device_attribute *attrs[SPI_NUM_ATTRS + SPI_OTHER_ATTRS + 1]; | ||
60 | struct class_device_attribute private_host_attrs[SPI_HOST_ATTRS]; | ||
61 | struct class_device_attribute *host_attrs[SPI_HOST_ATTRS + 1]; | ||
62 | }; | 55 | }; |
63 | 56 | ||
64 | #define to_spi_internal(tmpl) container_of(tmpl, struct spi_internal, t) | 57 | #define to_spi_internal(tmpl) container_of(tmpl, struct spi_internal, t) |
@@ -174,17 +167,20 @@ static int spi_host_setup(struct transport_container *tc, struct device *dev, | |||
174 | return 0; | 167 | return 0; |
175 | } | 168 | } |
176 | 169 | ||
170 | static int spi_host_configure(struct transport_container *tc, | ||
171 | struct device *dev, | ||
172 | struct class_device *cdev); | ||
173 | |||
177 | static DECLARE_TRANSPORT_CLASS(spi_host_class, | 174 | static DECLARE_TRANSPORT_CLASS(spi_host_class, |
178 | "spi_host", | 175 | "spi_host", |
179 | spi_host_setup, | 176 | spi_host_setup, |
180 | NULL, | 177 | NULL, |
181 | NULL); | 178 | spi_host_configure); |
182 | 179 | ||
183 | static int spi_host_match(struct attribute_container *cont, | 180 | static int spi_host_match(struct attribute_container *cont, |
184 | struct device *dev) | 181 | struct device *dev) |
185 | { | 182 | { |
186 | struct Scsi_Host *shost; | 183 | struct Scsi_Host *shost; |
187 | struct spi_internal *i; | ||
188 | 184 | ||
189 | if (!scsi_is_host_device(dev)) | 185 | if (!scsi_is_host_device(dev)) |
190 | return 0; | 186 | return 0; |
@@ -194,11 +190,13 @@ static int spi_host_match(struct attribute_container *cont, | |||
194 | != &spi_host_class.class) | 190 | != &spi_host_class.class) |
195 | return 0; | 191 | return 0; |
196 | 192 | ||
197 | i = to_spi_internal(shost->transportt); | 193 | return &shost->transportt->host_attrs.ac == cont; |
198 | |||
199 | return &i->t.host_attrs.ac == cont; | ||
200 | } | 194 | } |
201 | 195 | ||
196 | static int spi_target_configure(struct transport_container *tc, | ||
197 | struct device *dev, | ||
198 | struct class_device *cdev); | ||
199 | |||
202 | static int spi_device_configure(struct transport_container *tc, | 200 | static int spi_device_configure(struct transport_container *tc, |
203 | struct device *dev, | 201 | struct device *dev, |
204 | struct class_device *cdev) | 202 | struct class_device *cdev) |
@@ -300,8 +298,10 @@ store_spi_transport_##field(struct class_device *cdev, const char *buf, \ | |||
300 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); \ | 298 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); \ |
301 | struct spi_internal *i = to_spi_internal(shost->transportt); \ | 299 | struct spi_internal *i = to_spi_internal(shost->transportt); \ |
302 | \ | 300 | \ |
301 | if (!i->f->set_##field) \ | ||
302 | return -EINVAL; \ | ||
303 | val = simple_strtoul(buf, NULL, 0); \ | 303 | val = simple_strtoul(buf, NULL, 0); \ |
304 | i->f->set_##field(starget, val); \ | 304 | i->f->set_##field(starget, val); \ |
305 | return count; \ | 305 | return count; \ |
306 | } | 306 | } |
307 | 307 | ||
@@ -317,6 +317,8 @@ store_spi_transport_##field(struct class_device *cdev, const char *buf, \ | |||
317 | struct spi_transport_attrs *tp \ | 317 | struct spi_transport_attrs *tp \ |
318 | = (struct spi_transport_attrs *)&starget->starget_data; \ | 318 | = (struct spi_transport_attrs *)&starget->starget_data; \ |
319 | \ | 319 | \ |
320 | if (i->f->set_##field) \ | ||
321 | return -EINVAL; \ | ||
320 | val = simple_strtoul(buf, NULL, 0); \ | 322 | val = simple_strtoul(buf, NULL, 0); \ |
321 | if (val > tp->max_##field) \ | 323 | if (val > tp->max_##field) \ |
322 | val = tp->max_##field; \ | 324 | val = tp->max_##field; \ |
@@ -327,14 +329,14 @@ store_spi_transport_##field(struct class_device *cdev, const char *buf, \ | |||
327 | #define spi_transport_rd_attr(field, format_string) \ | 329 | #define spi_transport_rd_attr(field, format_string) \ |
328 | spi_transport_show_function(field, format_string) \ | 330 | spi_transport_show_function(field, format_string) \ |
329 | spi_transport_store_function(field, format_string) \ | 331 | spi_transport_store_function(field, format_string) \ |
330 | static CLASS_DEVICE_ATTR(field, S_IRUGO | S_IWUSR, \ | 332 | static CLASS_DEVICE_ATTR(field, S_IRUGO, \ |
331 | show_spi_transport_##field, \ | 333 | show_spi_transport_##field, \ |
332 | store_spi_transport_##field); | 334 | store_spi_transport_##field); |
333 | 335 | ||
334 | #define spi_transport_simple_attr(field, format_string) \ | 336 | #define spi_transport_simple_attr(field, format_string) \ |
335 | spi_transport_show_simple(field, format_string) \ | 337 | spi_transport_show_simple(field, format_string) \ |
336 | spi_transport_store_simple(field, format_string) \ | 338 | spi_transport_store_simple(field, format_string) \ |
337 | static CLASS_DEVICE_ATTR(field, S_IRUGO | S_IWUSR, \ | 339 | static CLASS_DEVICE_ATTR(field, S_IRUGO, \ |
338 | show_spi_transport_##field, \ | 340 | show_spi_transport_##field, \ |
339 | store_spi_transport_##field); | 341 | store_spi_transport_##field); |
340 | 342 | ||
@@ -342,7 +344,7 @@ static CLASS_DEVICE_ATTR(field, S_IRUGO | S_IWUSR, \ | |||
342 | spi_transport_show_function(field, format_string) \ | 344 | spi_transport_show_function(field, format_string) \ |
343 | spi_transport_store_max(field, format_string) \ | 345 | spi_transport_store_max(field, format_string) \ |
344 | spi_transport_simple_attr(max_##field, format_string) \ | 346 | spi_transport_simple_attr(max_##field, format_string) \ |
345 | static CLASS_DEVICE_ATTR(field, S_IRUGO | S_IWUSR, \ | 347 | static CLASS_DEVICE_ATTR(field, S_IRUGO, \ |
346 | show_spi_transport_##field, \ | 348 | show_spi_transport_##field, \ |
347 | store_spi_transport_##field); | 349 | store_spi_transport_##field); |
348 | 350 | ||
@@ -472,6 +474,9 @@ store_spi_transport_period(struct class_device *cdev, const char *buf, | |||
472 | (struct spi_transport_attrs *)&starget->starget_data; | 474 | (struct spi_transport_attrs *)&starget->starget_data; |
473 | int period, retval; | 475 | int period, retval; |
474 | 476 | ||
477 | if (!i->f->set_period) | ||
478 | return -EINVAL; | ||
479 | |||
475 | retval = store_spi_transport_period_helper(cdev, buf, count, &period); | 480 | retval = store_spi_transport_period_helper(cdev, buf, count, &period); |
476 | 481 | ||
477 | if (period < tp->min_period) | 482 | if (period < tp->min_period) |
@@ -482,7 +487,7 @@ store_spi_transport_period(struct class_device *cdev, const char *buf, | |||
482 | return retval; | 487 | return retval; |
483 | } | 488 | } |
484 | 489 | ||
485 | static CLASS_DEVICE_ATTR(period, S_IRUGO | S_IWUSR, | 490 | static CLASS_DEVICE_ATTR(period, S_IRUGO, |
486 | show_spi_transport_period, | 491 | show_spi_transport_period, |
487 | store_spi_transport_period); | 492 | store_spi_transport_period); |
488 | 493 | ||
@@ -490,9 +495,14 @@ static ssize_t | |||
490 | show_spi_transport_min_period(struct class_device *cdev, char *buf) | 495 | show_spi_transport_min_period(struct class_device *cdev, char *buf) |
491 | { | 496 | { |
492 | struct scsi_target *starget = transport_class_to_starget(cdev); | 497 | struct scsi_target *starget = transport_class_to_starget(cdev); |
498 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | ||
499 | struct spi_internal *i = to_spi_internal(shost->transportt); | ||
493 | struct spi_transport_attrs *tp = | 500 | struct spi_transport_attrs *tp = |
494 | (struct spi_transport_attrs *)&starget->starget_data; | 501 | (struct spi_transport_attrs *)&starget->starget_data; |
495 | 502 | ||
503 | if (!i->f->set_period) | ||
504 | return -EINVAL; | ||
505 | |||
496 | return show_spi_transport_period_helper(buf, tp->min_period); | 506 | return show_spi_transport_period_helper(buf, tp->min_period); |
497 | } | 507 | } |
498 | 508 | ||
@@ -509,7 +519,7 @@ store_spi_transport_min_period(struct class_device *cdev, const char *buf, | |||
509 | } | 519 | } |
510 | 520 | ||
511 | 521 | ||
512 | static CLASS_DEVICE_ATTR(min_period, S_IRUGO | S_IWUSR, | 522 | static CLASS_DEVICE_ATTR(min_period, S_IRUGO, |
513 | show_spi_transport_min_period, | 523 | show_spi_transport_min_period, |
514 | store_spi_transport_min_period); | 524 | store_spi_transport_min_period); |
515 | 525 | ||
@@ -531,12 +541,15 @@ static ssize_t store_spi_host_signalling(struct class_device *cdev, | |||
531 | struct spi_internal *i = to_spi_internal(shost->transportt); | 541 | struct spi_internal *i = to_spi_internal(shost->transportt); |
532 | enum spi_signal_type type = spi_signal_to_value(buf); | 542 | enum spi_signal_type type = spi_signal_to_value(buf); |
533 | 543 | ||
544 | if (!i->f->set_signalling) | ||
545 | return -EINVAL; | ||
546 | |||
534 | if (type != SPI_SIGNAL_UNKNOWN) | 547 | if (type != SPI_SIGNAL_UNKNOWN) |
535 | i->f->set_signalling(shost, type); | 548 | i->f->set_signalling(shost, type); |
536 | 549 | ||
537 | return count; | 550 | return count; |
538 | } | 551 | } |
539 | static CLASS_DEVICE_ATTR(signalling, S_IRUGO | S_IWUSR, | 552 | static CLASS_DEVICE_ATTR(signalling, S_IRUGO, |
540 | show_spi_host_signalling, | 553 | show_spi_host_signalling, |
541 | store_spi_host_signalling); | 554 | store_spi_host_signalling); |
542 | 555 | ||
@@ -1262,35 +1275,6 @@ int spi_print_msg(const unsigned char *msg) | |||
1262 | EXPORT_SYMBOL(spi_print_msg); | 1275 | EXPORT_SYMBOL(spi_print_msg); |
1263 | #endif /* ! CONFIG_SCSI_CONSTANTS */ | 1276 | #endif /* ! CONFIG_SCSI_CONSTANTS */ |
1264 | 1277 | ||
1265 | #define SETUP_ATTRIBUTE(field) \ | ||
1266 | i->private_attrs[count] = class_device_attr_##field; \ | ||
1267 | if (!i->f->set_##field) { \ | ||
1268 | i->private_attrs[count].attr.mode = S_IRUGO; \ | ||
1269 | i->private_attrs[count].store = NULL; \ | ||
1270 | } \ | ||
1271 | i->attrs[count] = &i->private_attrs[count]; \ | ||
1272 | if (i->f->show_##field) \ | ||
1273 | count++ | ||
1274 | |||
1275 | #define SETUP_RELATED_ATTRIBUTE(field, rel_field) \ | ||
1276 | i->private_attrs[count] = class_device_attr_##field; \ | ||
1277 | if (!i->f->set_##rel_field) { \ | ||
1278 | i->private_attrs[count].attr.mode = S_IRUGO; \ | ||
1279 | i->private_attrs[count].store = NULL; \ | ||
1280 | } \ | ||
1281 | i->attrs[count] = &i->private_attrs[count]; \ | ||
1282 | if (i->f->show_##rel_field) \ | ||
1283 | count++ | ||
1284 | |||
1285 | #define SETUP_HOST_ATTRIBUTE(field) \ | ||
1286 | i->private_host_attrs[count] = class_device_attr_##field; \ | ||
1287 | if (!i->f->set_##field) { \ | ||
1288 | i->private_host_attrs[count].attr.mode = S_IRUGO; \ | ||
1289 | i->private_host_attrs[count].store = NULL; \ | ||
1290 | } \ | ||
1291 | i->host_attrs[count] = &i->private_host_attrs[count]; \ | ||
1292 | count++ | ||
1293 | |||
1294 | static int spi_device_match(struct attribute_container *cont, | 1278 | static int spi_device_match(struct attribute_container *cont, |
1295 | struct device *dev) | 1279 | struct device *dev) |
1296 | { | 1280 | { |
@@ -1343,16 +1327,156 @@ static DECLARE_TRANSPORT_CLASS(spi_transport_class, | |||
1343 | "spi_transport", | 1327 | "spi_transport", |
1344 | spi_setup_transport_attrs, | 1328 | spi_setup_transport_attrs, |
1345 | NULL, | 1329 | NULL, |
1346 | NULL); | 1330 | spi_target_configure); |
1347 | 1331 | ||
1348 | static DECLARE_ANON_TRANSPORT_CLASS(spi_device_class, | 1332 | static DECLARE_ANON_TRANSPORT_CLASS(spi_device_class, |
1349 | spi_device_match, | 1333 | spi_device_match, |
1350 | spi_device_configure); | 1334 | spi_device_configure); |
1351 | 1335 | ||
1336 | static struct attribute *host_attributes[] = { | ||
1337 | &class_device_attr_signalling.attr, | ||
1338 | NULL | ||
1339 | }; | ||
1340 | |||
1341 | static struct attribute_group host_attribute_group = { | ||
1342 | .attrs = host_attributes, | ||
1343 | }; | ||
1344 | |||
1345 | static int spi_host_configure(struct transport_container *tc, | ||
1346 | struct device *dev, | ||
1347 | struct class_device *cdev) | ||
1348 | { | ||
1349 | struct kobject *kobj = &cdev->kobj; | ||
1350 | struct Scsi_Host *shost = transport_class_to_shost(cdev); | ||
1351 | struct spi_internal *si = to_spi_internal(shost->transportt); | ||
1352 | struct attribute *attr = &class_device_attr_signalling.attr; | ||
1353 | int rc = 0; | ||
1354 | |||
1355 | if (si->f->set_signalling) | ||
1356 | rc = sysfs_chmod_file(kobj, attr, attr->mode | S_IWUSR); | ||
1357 | |||
1358 | return rc; | ||
1359 | } | ||
1360 | |||
1361 | /* returns true if we should be showing the variable. Also | ||
1362 | * overloads the return by setting 1<<1 if the attribute should | ||
1363 | * be writeable */ | ||
1364 | #define TARGET_ATTRIBUTE_HELPER(name) \ | ||
1365 | (si->f->show_##name ? 1 : 0) + \ | ||
1366 | (si->f->set_##name ? 2 : 0) | ||
1367 | |||
1368 | static int target_attribute_is_visible(struct kobject *kobj, | ||
1369 | struct attribute *attr, int i) | ||
1370 | { | ||
1371 | struct class_device *cdev = | ||
1372 | container_of(kobj, struct class_device, kobj); | ||
1373 | struct scsi_target *starget = transport_class_to_starget(cdev); | ||
1374 | struct Scsi_Host *shost = transport_class_to_shost(cdev); | ||
1375 | struct spi_internal *si = to_spi_internal(shost->transportt); | ||
1376 | |||
1377 | if (attr == &class_device_attr_period.attr && | ||
1378 | spi_support_sync(starget)) | ||
1379 | return TARGET_ATTRIBUTE_HELPER(period); | ||
1380 | else if (attr == &class_device_attr_min_period.attr && | ||
1381 | spi_support_sync(starget)) | ||
1382 | return TARGET_ATTRIBUTE_HELPER(period); | ||
1383 | else if (attr == &class_device_attr_offset.attr && | ||
1384 | spi_support_sync(starget)) | ||
1385 | return TARGET_ATTRIBUTE_HELPER(offset); | ||
1386 | else if (attr == &class_device_attr_max_offset.attr && | ||
1387 | spi_support_sync(starget)) | ||
1388 | return TARGET_ATTRIBUTE_HELPER(offset); | ||
1389 | else if (attr == &class_device_attr_width.attr && | ||
1390 | spi_support_wide(starget)) | ||
1391 | return TARGET_ATTRIBUTE_HELPER(width); | ||
1392 | else if (attr == &class_device_attr_max_width.attr && | ||
1393 | spi_support_wide(starget)) | ||
1394 | return TARGET_ATTRIBUTE_HELPER(width); | ||
1395 | else if (attr == &class_device_attr_iu.attr && | ||
1396 | spi_support_ius(starget)) | ||
1397 | return TARGET_ATTRIBUTE_HELPER(iu); | ||
1398 | else if (attr == &class_device_attr_dt.attr && | ||
1399 | spi_support_dt(starget)) | ||
1400 | return TARGET_ATTRIBUTE_HELPER(dt); | ||
1401 | else if (attr == &class_device_attr_qas.attr && | ||
1402 | spi_support_qas(starget)) | ||
1403 | return TARGET_ATTRIBUTE_HELPER(qas); | ||
1404 | else if (attr == &class_device_attr_wr_flow.attr && | ||
1405 | spi_support_ius(starget)) | ||
1406 | return TARGET_ATTRIBUTE_HELPER(wr_flow); | ||
1407 | else if (attr == &class_device_attr_rd_strm.attr && | ||
1408 | spi_support_ius(starget)) | ||
1409 | return TARGET_ATTRIBUTE_HELPER(rd_strm); | ||
1410 | else if (attr == &class_device_attr_rti.attr && | ||
1411 | spi_support_ius(starget)) | ||
1412 | return TARGET_ATTRIBUTE_HELPER(rti); | ||
1413 | else if (attr == &class_device_attr_pcomp_en.attr && | ||
1414 | spi_support_ius(starget)) | ||
1415 | return TARGET_ATTRIBUTE_HELPER(pcomp_en); | ||
1416 | else if (attr == &class_device_attr_hold_mcs.attr && | ||
1417 | spi_support_ius(starget)) | ||
1418 | return TARGET_ATTRIBUTE_HELPER(hold_mcs); | ||
1419 | else if (attr == &class_device_attr_revalidate.attr) | ||
1420 | return 1; | ||
1421 | |||
1422 | return 0; | ||
1423 | } | ||
1424 | |||
1425 | static struct attribute *target_attributes[] = { | ||
1426 | &class_device_attr_period.attr, | ||
1427 | &class_device_attr_min_period.attr, | ||
1428 | &class_device_attr_offset.attr, | ||
1429 | &class_device_attr_max_offset.attr, | ||
1430 | &class_device_attr_width.attr, | ||
1431 | &class_device_attr_max_width.attr, | ||
1432 | &class_device_attr_iu.attr, | ||
1433 | &class_device_attr_dt.attr, | ||
1434 | &class_device_attr_qas.attr, | ||
1435 | &class_device_attr_wr_flow.attr, | ||
1436 | &class_device_attr_rd_strm.attr, | ||
1437 | &class_device_attr_rti.attr, | ||
1438 | &class_device_attr_pcomp_en.attr, | ||
1439 | &class_device_attr_hold_mcs.attr, | ||
1440 | &class_device_attr_revalidate.attr, | ||
1441 | NULL | ||
1442 | }; | ||
1443 | |||
1444 | static struct attribute_group target_attribute_group = { | ||
1445 | .attrs = target_attributes, | ||
1446 | .is_visible = target_attribute_is_visible, | ||
1447 | }; | ||
1448 | |||
1449 | static int spi_target_configure(struct transport_container *tc, | ||
1450 | struct device *dev, | ||
1451 | struct class_device *cdev) | ||
1452 | { | ||
1453 | struct kobject *kobj = &cdev->kobj; | ||
1454 | int i; | ||
1455 | struct attribute *attr; | ||
1456 | int rc; | ||
1457 | |||
1458 | for (i = 0; (attr = target_attributes[i]) != NULL; i++) { | ||
1459 | int j = target_attribute_group.is_visible(kobj, attr, i); | ||
1460 | |||
1461 | /* FIXME: as well as returning -EEXIST, which we'd like | ||
1462 | * to ignore, sysfs also does a WARN_ON and dumps a trace, | ||
1463 | * which is bad, so temporarily, skip attributes that are | ||
1464 | * already visible (the revalidate one) */ | ||
1465 | if (j && attr != &class_device_attr_revalidate.attr) | ||
1466 | rc = sysfs_add_file_to_group(kobj, attr, | ||
1467 | target_attribute_group.name); | ||
1468 | /* and make the attribute writeable if we have a set | ||
1469 | * function */ | ||
1470 | if ((j & 1)) | ||
1471 | rc = sysfs_chmod_file(kobj, attr, attr->mode | S_IWUSR); | ||
1472 | } | ||
1473 | |||
1474 | return 0; | ||
1475 | } | ||
1476 | |||
1352 | struct scsi_transport_template * | 1477 | struct scsi_transport_template * |
1353 | spi_attach_transport(struct spi_function_template *ft) | 1478 | spi_attach_transport(struct spi_function_template *ft) |
1354 | { | 1479 | { |
1355 | int count = 0; | ||
1356 | struct spi_internal *i = kzalloc(sizeof(struct spi_internal), | 1480 | struct spi_internal *i = kzalloc(sizeof(struct spi_internal), |
1357 | GFP_KERNEL); | 1481 | GFP_KERNEL); |
1358 | 1482 | ||
@@ -1360,47 +1484,17 @@ spi_attach_transport(struct spi_function_template *ft) | |||
1360 | return NULL; | 1484 | return NULL; |
1361 | 1485 | ||
1362 | i->t.target_attrs.ac.class = &spi_transport_class.class; | 1486 | i->t.target_attrs.ac.class = &spi_transport_class.class; |
1363 | i->t.target_attrs.ac.attrs = &i->attrs[0]; | 1487 | i->t.target_attrs.ac.grp = &target_attribute_group; |
1364 | i->t.target_attrs.ac.match = spi_target_match; | 1488 | i->t.target_attrs.ac.match = spi_target_match; |
1365 | transport_container_register(&i->t.target_attrs); | 1489 | transport_container_register(&i->t.target_attrs); |
1366 | i->t.target_size = sizeof(struct spi_transport_attrs); | 1490 | i->t.target_size = sizeof(struct spi_transport_attrs); |
1367 | i->t.host_attrs.ac.class = &spi_host_class.class; | 1491 | i->t.host_attrs.ac.class = &spi_host_class.class; |
1368 | i->t.host_attrs.ac.attrs = &i->host_attrs[0]; | 1492 | i->t.host_attrs.ac.grp = &host_attribute_group; |
1369 | i->t.host_attrs.ac.match = spi_host_match; | 1493 | i->t.host_attrs.ac.match = spi_host_match; |
1370 | transport_container_register(&i->t.host_attrs); | 1494 | transport_container_register(&i->t.host_attrs); |
1371 | i->t.host_size = sizeof(struct spi_host_attrs); | 1495 | i->t.host_size = sizeof(struct spi_host_attrs); |
1372 | i->f = ft; | 1496 | i->f = ft; |
1373 | 1497 | ||
1374 | SETUP_ATTRIBUTE(period); | ||
1375 | SETUP_RELATED_ATTRIBUTE(min_period, period); | ||
1376 | SETUP_ATTRIBUTE(offset); | ||
1377 | SETUP_RELATED_ATTRIBUTE(max_offset, offset); | ||
1378 | SETUP_ATTRIBUTE(width); | ||
1379 | SETUP_RELATED_ATTRIBUTE(max_width, width); | ||
1380 | SETUP_ATTRIBUTE(iu); | ||
1381 | SETUP_ATTRIBUTE(dt); | ||
1382 | SETUP_ATTRIBUTE(qas); | ||
1383 | SETUP_ATTRIBUTE(wr_flow); | ||
1384 | SETUP_ATTRIBUTE(rd_strm); | ||
1385 | SETUP_ATTRIBUTE(rti); | ||
1386 | SETUP_ATTRIBUTE(pcomp_en); | ||
1387 | SETUP_ATTRIBUTE(hold_mcs); | ||
1388 | |||
1389 | /* if you add an attribute but forget to increase SPI_NUM_ATTRS | ||
1390 | * this bug will trigger */ | ||
1391 | BUG_ON(count > SPI_NUM_ATTRS); | ||
1392 | |||
1393 | i->attrs[count++] = &class_device_attr_revalidate; | ||
1394 | |||
1395 | i->attrs[count] = NULL; | ||
1396 | |||
1397 | count = 0; | ||
1398 | SETUP_HOST_ATTRIBUTE(signalling); | ||
1399 | |||
1400 | BUG_ON(count > SPI_HOST_ATTRS); | ||
1401 | |||
1402 | i->host_attrs[count] = NULL; | ||
1403 | |||
1404 | return &i->t; | 1498 | return &i->t; |
1405 | } | 1499 | } |
1406 | EXPORT_SYMBOL(spi_attach_transport); | 1500 | EXPORT_SYMBOL(spi_attach_transport); |