aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@HansenPartnership.com>2008-01-05 11:18:27 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-01-23 12:29:18 -0500
commit9b161a4d3e83518323ce13822e55de70c630aa65 (patch)
tree1a08462a016105ef372fba8c5aa4ef24205aa46b /drivers/scsi
parentd4acd722b7bb5f48b9fc3848e8c2a845b100d84f (diff)
[SCSI] scsi_transport_spi: convert to attribute groups
This conversion makes full use of the is_visible() callback on attribute groups. Now, each device appears only with its capability flags in the transport class directory. Previously each device appeared with the capability of the host, so this is a functionality improvement. Converting to attribute groups allows us to sweep away most of the home grown #defines that were effectively doing the same thing. Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/scsi_transport_spi.c258
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 @@
52struct spi_internal { 52struct 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
170static int spi_host_configure(struct transport_container *tc,
171 struct device *dev,
172 struct class_device *cdev);
173
177static DECLARE_TRANSPORT_CLASS(spi_host_class, 174static 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
183static int spi_host_match(struct attribute_container *cont, 180static 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
196static int spi_target_configure(struct transport_container *tc,
197 struct device *dev,
198 struct class_device *cdev);
199
202static int spi_device_configure(struct transport_container *tc, 200static 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) \
330static CLASS_DEVICE_ATTR(field, S_IRUGO | S_IWUSR, \ 332static 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) \
337static CLASS_DEVICE_ATTR(field, S_IRUGO | S_IWUSR, \ 339static 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) \
345static CLASS_DEVICE_ATTR(field, S_IRUGO | S_IWUSR, \ 347static 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
485static CLASS_DEVICE_ATTR(period, S_IRUGO | S_IWUSR, 490static 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
490show_spi_transport_min_period(struct class_device *cdev, char *buf) 495show_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
512static CLASS_DEVICE_ATTR(min_period, S_IRUGO | S_IWUSR, 522static 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}
539static CLASS_DEVICE_ATTR(signalling, S_IRUGO | S_IWUSR, 552static 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)
1262EXPORT_SYMBOL(spi_print_msg); 1275EXPORT_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
1294static int spi_device_match(struct attribute_container *cont, 1278static 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
1348static DECLARE_ANON_TRANSPORT_CLASS(spi_device_class, 1332static 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
1336static struct attribute *host_attributes[] = {
1337 &class_device_attr_signalling.attr,
1338 NULL
1339};
1340
1341static struct attribute_group host_attribute_group = {
1342 .attrs = host_attributes,
1343};
1344
1345static 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
1368static 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
1425static 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
1444static struct attribute_group target_attribute_group = {
1445 .attrs = target_attributes,
1446 .is_visible = target_attribute_is_visible,
1447};
1448
1449static 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
1352struct scsi_transport_template * 1477struct scsi_transport_template *
1353spi_attach_transport(struct spi_function_template *ft) 1478spi_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}
1406EXPORT_SYMBOL(spi_attach_transport); 1500EXPORT_SYMBOL(spi_attach_transport);