aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
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);