aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/pata_legacy.c
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2008-03-24 23:22:49 -0400
committerJeff Garzik <jgarzik@redhat.com>2008-04-17 15:44:17 -0400
commit029cfd6b74fc5c517865fad78cf4a3ea8d9b664a (patch)
tree4a40f44f29321e433497a51d2f6cfe1922ae1d58 /drivers/ata/pata_legacy.c
parent68d1d07b510bb57a504588adc2bd2758adea0965 (diff)
libata: implement and use ops inheritance
libata lets low level drivers build ata_port_operations table and register it with libata core layer. This allows low level drivers high level of flexibility but also burdens them with lots of boilerplate entries. This becomes worse for drivers which support related similar controllers which differ slightly. They share most of the operations except for a few. However, the driver still needs to list all operations for each variant. This results in large number of duplicate entries, which is not only inefficient but also error-prone as it becomes very difficult to tell what the actual differences are. This duplicate boilerplates all over the low level drivers also make updating the core layer exteremely difficult and error-prone. When compounded with multi-branched development model, it ends up accumulating inconsistencies over time. Some of those inconsistencies cause immediate problems and fixed. Others just remain there dormant making maintenance increasingly difficult. To rectify the problem, this patch implements ata_port_operations inheritance. To allow LLDs to easily re-use their own ops tables overriding only specific methods, this patch implements poor man's class inheritance. An ops table has ->inherits field which can be set to any ops table as long as it doesn't create a loop. When the host is started, the inheritance chain is followed and any operation which isn't specified is taken from the nearest ancestor which has it specified. This operation is called finalization and done only once per an ops table and the LLD doesn't have to do anything special about it other than making the ops table non-const such that libata can update it. libata provides four base ops tables lower drivers can inherit from - base, sata, pmp, sff and bmdma. To avoid overriding these ops accidentaly, these ops are declared const and LLDs should always inherit these instead of using them directly. After finalization, all the ops table are identical before and after the patch except for setting .irq_handler to ata_interrupt in drivers which didn't use to. The .irq_handler doesn't have any actual effect and the field will soon be removed by later patch. * sata_sx4 is still using old style EH and currently doesn't take advantage of ops inheritance. Signed-off-by: Tejun Heo <htejun@gmail.com>
Diffstat (limited to 'drivers/ata/pata_legacy.c')
-rw-r--r--drivers/ata/pata_legacy.c260
1 files changed, 17 insertions, 243 deletions
diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c
index 5329b954c5f2..2474068596f4 100644
--- a/drivers/ata/pata_legacy.c
+++ b/drivers/ata/pata_legacy.c
@@ -211,6 +211,11 @@ static struct scsi_host_template legacy_sht = {
211 ATA_PIO_SHT(DRV_NAME), 211 ATA_PIO_SHT(DRV_NAME),
212}; 212};
213 213
214static const struct ata_port_operations legacy_base_port_ops = {
215 .inherits = &ata_sff_port_ops,
216 .cable_detect = ata_cable_40wire,
217};
218
214/* 219/*
215 * These ops are used if the user indicates the hardware 220 * These ops are used if the user indicates the hardware
216 * snoops the commands to decide on the mode and handles the 221 * snoops the commands to decide on the mode and handles the
@@ -220,55 +225,14 @@ static struct scsi_host_template legacy_sht = {
220 */ 225 */
221 226
222static struct ata_port_operations simple_port_ops = { 227static struct ata_port_operations simple_port_ops = {
223 .tf_load = ata_tf_load, 228 .inherits = &legacy_base_port_ops,
224 .tf_read = ata_tf_read,
225 .check_status = ata_check_status,
226 .exec_command = ata_exec_command,
227 .dev_select = ata_std_dev_select,
228
229 .freeze = ata_bmdma_freeze,
230 .thaw = ata_bmdma_thaw,
231 .error_handler = ata_bmdma_error_handler,
232 .post_internal_cmd = ata_bmdma_post_internal_cmd,
233 .cable_detect = ata_cable_40wire,
234
235 .qc_prep = ata_qc_prep,
236 .qc_issue = ata_qc_issue_prot,
237
238 .data_xfer = ata_data_xfer_noirq, 229 .data_xfer = ata_data_xfer_noirq,
239
240 .irq_handler = ata_interrupt,
241 .irq_clear = ata_noop_irq_clear,
242 .irq_on = ata_irq_on,
243
244 .port_start = ata_sff_port_start,
245}; 230};
246 231
247static struct ata_port_operations legacy_port_ops = { 232static struct ata_port_operations legacy_port_ops = {
248 .set_mode = legacy_set_mode, 233 .inherits = &legacy_base_port_ops,
249
250 .tf_load = ata_tf_load,
251 .tf_read = ata_tf_read,
252 .check_status = ata_check_status,
253 .exec_command = ata_exec_command,
254 .dev_select = ata_std_dev_select,
255 .cable_detect = ata_cable_40wire,
256
257 .freeze = ata_bmdma_freeze,
258 .thaw = ata_bmdma_thaw,
259 .error_handler = ata_bmdma_error_handler,
260 .post_internal_cmd = ata_bmdma_post_internal_cmd,
261
262 .qc_prep = ata_qc_prep,
263 .qc_issue = ata_qc_issue_prot,
264
265 .data_xfer = ata_data_xfer_noirq, 234 .data_xfer = ata_data_xfer_noirq,
266 235 .set_mode = legacy_set_mode,
267 .irq_handler = ata_interrupt,
268 .irq_clear = ata_noop_irq_clear,
269 .irq_on = ata_irq_on,
270
271 .port_start = ata_sff_port_start,
272}; 236};
273 237
274/* 238/*
@@ -359,30 +323,9 @@ static unsigned int pdc_data_xfer_vlb(struct ata_device *dev,
359} 323}
360 324
361static struct ata_port_operations pdc20230_port_ops = { 325static struct ata_port_operations pdc20230_port_ops = {
326 .inherits = &legacy_base_port_ops,
362 .set_piomode = pdc20230_set_piomode, 327 .set_piomode = pdc20230_set_piomode,
363
364 .tf_load = ata_tf_load,
365 .tf_read = ata_tf_read,
366 .check_status = ata_check_status,
367 .exec_command = ata_exec_command,
368 .dev_select = ata_std_dev_select,
369
370 .freeze = ata_bmdma_freeze,
371 .thaw = ata_bmdma_thaw,
372 .error_handler = ata_bmdma_error_handler,
373 .post_internal_cmd = ata_bmdma_post_internal_cmd,
374 .cable_detect = ata_cable_40wire,
375
376 .qc_prep = ata_qc_prep,
377 .qc_issue = ata_qc_issue_prot,
378
379 .data_xfer = pdc_data_xfer_vlb, 328 .data_xfer = pdc_data_xfer_vlb,
380
381 .irq_handler = ata_interrupt,
382 .irq_clear = ata_noop_irq_clear,
383 .irq_on = ata_irq_on,
384
385 .port_start = ata_sff_port_start,
386}; 329};
387 330
388/* 331/*
@@ -413,30 +356,8 @@ static void ht6560a_set_piomode(struct ata_port *ap, struct ata_device *adev)
413} 356}
414 357
415static struct ata_port_operations ht6560a_port_ops = { 358static struct ata_port_operations ht6560a_port_ops = {
359 .inherits = &legacy_base_port_ops,
416 .set_piomode = ht6560a_set_piomode, 360 .set_piomode = ht6560a_set_piomode,
417
418 .tf_load = ata_tf_load,
419 .tf_read = ata_tf_read,
420 .check_status = ata_check_status,
421 .exec_command = ata_exec_command,
422 .dev_select = ata_std_dev_select,
423
424 .freeze = ata_bmdma_freeze,
425 .thaw = ata_bmdma_thaw,
426 .error_handler = ata_bmdma_error_handler,
427 .post_internal_cmd = ata_bmdma_post_internal_cmd,
428 .cable_detect = ata_cable_40wire,
429
430 .qc_prep = ata_qc_prep,
431 .qc_issue = ata_qc_issue_prot,
432
433 .data_xfer = ata_data_xfer, /* Check vlb/noirq */
434
435 .irq_handler = ata_interrupt,
436 .irq_clear = ata_noop_irq_clear,
437 .irq_on = ata_irq_on,
438
439 .port_start = ata_sff_port_start,
440}; 361};
441 362
442/* 363/*
@@ -478,30 +399,8 @@ static void ht6560b_set_piomode(struct ata_port *ap, struct ata_device *adev)
478} 399}
479 400
480static struct ata_port_operations ht6560b_port_ops = { 401static struct ata_port_operations ht6560b_port_ops = {
402 .inherits = &legacy_base_port_ops,
481 .set_piomode = ht6560b_set_piomode, 403 .set_piomode = ht6560b_set_piomode,
482
483 .tf_load = ata_tf_load,
484 .tf_read = ata_tf_read,
485 .check_status = ata_check_status,
486 .exec_command = ata_exec_command,
487 .dev_select = ata_std_dev_select,
488
489 .freeze = ata_bmdma_freeze,
490 .thaw = ata_bmdma_thaw,
491 .error_handler = ata_bmdma_error_handler,
492 .post_internal_cmd = ata_bmdma_post_internal_cmd,
493 .cable_detect = ata_cable_40wire,
494
495 .qc_prep = ata_qc_prep,
496 .qc_issue = ata_qc_issue_prot,
497
498 .data_xfer = ata_data_xfer, /* FIXME: Check 32bit and noirq */
499
500 .irq_handler = ata_interrupt,
501 .irq_clear = ata_noop_irq_clear,
502 .irq_on = ata_irq_on,
503
504 .port_start = ata_sff_port_start,
505}; 404};
506 405
507/* 406/*
@@ -599,30 +498,8 @@ static void opti82c611a_set_piomode(struct ata_port *ap,
599 498
600 499
601static struct ata_port_operations opti82c611a_port_ops = { 500static struct ata_port_operations opti82c611a_port_ops = {
501 .inherits = &legacy_base_port_ops,
602 .set_piomode = opti82c611a_set_piomode, 502 .set_piomode = opti82c611a_set_piomode,
603
604 .tf_load = ata_tf_load,
605 .tf_read = ata_tf_read,
606 .check_status = ata_check_status,
607 .exec_command = ata_exec_command,
608 .dev_select = ata_std_dev_select,
609
610 .freeze = ata_bmdma_freeze,
611 .thaw = ata_bmdma_thaw,
612 .error_handler = ata_bmdma_error_handler,
613 .post_internal_cmd = ata_bmdma_post_internal_cmd,
614 .cable_detect = ata_cable_40wire,
615
616 .qc_prep = ata_qc_prep,
617 .qc_issue = ata_qc_issue_prot,
618
619 .data_xfer = ata_data_xfer,
620
621 .irq_handler = ata_interrupt,
622 .irq_clear = ata_noop_irq_clear,
623 .irq_on = ata_irq_on,
624
625 .port_start = ata_sff_port_start,
626}; 503};
627 504
628/* 505/*
@@ -731,30 +608,9 @@ static unsigned int opti82c46x_qc_issue_prot(struct ata_queued_cmd *qc)
731} 608}
732 609
733static struct ata_port_operations opti82c46x_port_ops = { 610static struct ata_port_operations opti82c46x_port_ops = {
611 .inherits = &legacy_base_port_ops,
734 .set_piomode = opti82c46x_set_piomode, 612 .set_piomode = opti82c46x_set_piomode,
735
736 .tf_load = ata_tf_load,
737 .tf_read = ata_tf_read,
738 .check_status = ata_check_status,
739 .exec_command = ata_exec_command,
740 .dev_select = ata_std_dev_select,
741
742 .freeze = ata_bmdma_freeze,
743 .thaw = ata_bmdma_thaw,
744 .error_handler = ata_bmdma_error_handler,
745 .post_internal_cmd = ata_bmdma_post_internal_cmd,
746 .cable_detect = ata_cable_40wire,
747
748 .qc_prep = ata_qc_prep,
749 .qc_issue = opti82c46x_qc_issue_prot, 613 .qc_issue = opti82c46x_qc_issue_prot,
750
751 .data_xfer = ata_data_xfer,
752
753 .irq_handler = ata_interrupt,
754 .irq_clear = ata_noop_irq_clear,
755 .irq_on = ata_irq_on,
756
757 .port_start = ata_sff_port_start,
758}; 614};
759 615
760static void qdi6500_set_piomode(struct ata_port *ap, struct ata_device *adev) 616static void qdi6500_set_piomode(struct ata_port *ap, struct ata_device *adev)
@@ -916,84 +772,22 @@ static int qdi_port(struct platform_device *dev,
916} 772}
917 773
918static struct ata_port_operations qdi6500_port_ops = { 774static struct ata_port_operations qdi6500_port_ops = {
775 .inherits = &legacy_base_port_ops,
919 .set_piomode = qdi6500_set_piomode, 776 .set_piomode = qdi6500_set_piomode,
920
921 .tf_load = ata_tf_load,
922 .tf_read = ata_tf_read,
923 .check_status = ata_check_status,
924 .exec_command = ata_exec_command,
925 .dev_select = ata_std_dev_select,
926
927 .freeze = ata_bmdma_freeze,
928 .thaw = ata_bmdma_thaw,
929 .error_handler = ata_bmdma_error_handler,
930 .post_internal_cmd = ata_bmdma_post_internal_cmd,
931 .cable_detect = ata_cable_40wire,
932
933 .qc_prep = ata_qc_prep,
934 .qc_issue = qdi_qc_issue_prot, 777 .qc_issue = qdi_qc_issue_prot,
935
936 .data_xfer = vlb32_data_xfer, 778 .data_xfer = vlb32_data_xfer,
937
938 .irq_handler = ata_interrupt,
939 .irq_clear = ata_noop_irq_clear,
940 .irq_on = ata_irq_on,
941
942 .port_start = ata_sff_port_start,
943}; 779};
944 780
945static struct ata_port_operations qdi6580_port_ops = { 781static struct ata_port_operations qdi6580_port_ops = {
782 .inherits = &legacy_base_port_ops,
946 .set_piomode = qdi6580_set_piomode, 783 .set_piomode = qdi6580_set_piomode,
947
948 .tf_load = ata_tf_load,
949 .tf_read = ata_tf_read,
950 .check_status = ata_check_status,
951 .exec_command = ata_exec_command,
952 .dev_select = ata_std_dev_select,
953
954 .freeze = ata_bmdma_freeze,
955 .thaw = ata_bmdma_thaw,
956 .error_handler = ata_bmdma_error_handler,
957 .post_internal_cmd = ata_bmdma_post_internal_cmd,
958 .cable_detect = ata_cable_40wire,
959
960 .qc_prep = ata_qc_prep,
961 .qc_issue = ata_qc_issue_prot,
962
963 .data_xfer = vlb32_data_xfer, 784 .data_xfer = vlb32_data_xfer,
964
965 .irq_handler = ata_interrupt,
966 .irq_clear = ata_noop_irq_clear,
967 .irq_on = ata_irq_on,
968
969 .port_start = ata_sff_port_start,
970}; 785};
971 786
972static struct ata_port_operations qdi6580dp_port_ops = { 787static struct ata_port_operations qdi6580dp_port_ops = {
788 .inherits = &legacy_base_port_ops,
973 .set_piomode = qdi6580dp_set_piomode, 789 .set_piomode = qdi6580dp_set_piomode,
974
975 .tf_load = ata_tf_load,
976 .tf_read = ata_tf_read,
977 .check_status = ata_check_status,
978 .exec_command = ata_exec_command,
979 .dev_select = ata_std_dev_select,
980
981 .freeze = ata_bmdma_freeze,
982 .thaw = ata_bmdma_thaw,
983 .error_handler = ata_bmdma_error_handler,
984 .post_internal_cmd = ata_bmdma_post_internal_cmd,
985 .cable_detect = ata_cable_40wire,
986
987 .qc_prep = ata_qc_prep,
988 .qc_issue = qdi_qc_issue_prot,
989
990 .data_xfer = vlb32_data_xfer, 790 .data_xfer = vlb32_data_xfer,
991
992 .irq_handler = ata_interrupt,
993 .irq_clear = ata_noop_irq_clear,
994 .irq_on = ata_irq_on,
995
996 .port_start = ata_sff_port_start,
997}; 791};
998 792
999static DEFINE_SPINLOCK(winbond_lock); 793static DEFINE_SPINLOCK(winbond_lock);
@@ -1062,29 +856,9 @@ static int winbond_port(struct platform_device *dev,
1062} 856}
1063 857
1064static struct ata_port_operations winbond_port_ops = { 858static struct ata_port_operations winbond_port_ops = {
859 .inherits = &legacy_base_port_ops,
1065 .set_piomode = winbond_set_piomode, 860 .set_piomode = winbond_set_piomode,
1066
1067 .tf_load = ata_tf_load,
1068 .tf_read = ata_tf_read,
1069 .check_status = ata_check_status,
1070 .exec_command = ata_exec_command,
1071 .dev_select = ata_std_dev_select,
1072
1073 .freeze = ata_bmdma_freeze,
1074 .thaw = ata_bmdma_thaw,
1075 .error_handler = ata_bmdma_error_handler,
1076 .post_internal_cmd = ata_bmdma_post_internal_cmd,
1077 .cable_detect = ata_cable_40wire,
1078
1079 .qc_prep = ata_qc_prep,
1080 .qc_issue = ata_qc_issue_prot,
1081
1082 .data_xfer = vlb32_data_xfer, 861 .data_xfer = vlb32_data_xfer,
1083
1084 .irq_clear = ata_noop_irq_clear,
1085 .irq_on = ata_irq_on,
1086
1087 .port_start = ata_sff_port_start,
1088}; 862};
1089 863
1090static struct legacy_controller controllers[] = { 864static struct legacy_controller controllers[] = {