diff options
-rw-r--r-- | drivers/ata/sata_sil24.c | 227 |
1 files changed, 206 insertions, 21 deletions
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index b4f81eb8bbbe..03bfbb65c533 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include <linux/libata.h> | 30 | #include <linux/libata.h> |
31 | 31 | ||
32 | #define DRV_NAME "sata_sil24" | 32 | #define DRV_NAME "sata_sil24" |
33 | #define DRV_VERSION "1.0" | 33 | #define DRV_VERSION "1.1" |
34 | 34 | ||
35 | /* | 35 | /* |
36 | * Port request block (PRB) 32 bytes | 36 | * Port request block (PRB) 32 bytes |
@@ -238,7 +238,7 @@ enum { | |||
238 | SIL24_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | | 238 | SIL24_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | |
239 | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | | 239 | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | |
240 | ATA_FLAG_NCQ | ATA_FLAG_ACPI_SATA | | 240 | ATA_FLAG_NCQ | ATA_FLAG_ACPI_SATA | |
241 | ATA_FLAG_AN, | 241 | ATA_FLAG_AN | ATA_FLAG_PMP, |
242 | SIL24_COMMON_LFLAGS = ATA_LFLAG_SKIP_D2H_BSY, | 242 | SIL24_COMMON_LFLAGS = ATA_LFLAG_SKIP_D2H_BSY, |
243 | SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */ | 243 | SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */ |
244 | 244 | ||
@@ -330,9 +330,14 @@ static u8 sil24_check_status(struct ata_port *ap); | |||
330 | static int sil24_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val); | 330 | static int sil24_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val); |
331 | static int sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val); | 331 | static int sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val); |
332 | static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf); | 332 | static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf); |
333 | static int sil24_qc_defer(struct ata_queued_cmd *qc); | ||
333 | static void sil24_qc_prep(struct ata_queued_cmd *qc); | 334 | static void sil24_qc_prep(struct ata_queued_cmd *qc); |
334 | static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc); | 335 | static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc); |
335 | static void sil24_irq_clear(struct ata_port *ap); | 336 | static void sil24_irq_clear(struct ata_port *ap); |
337 | static void sil24_pmp_attach(struct ata_port *ap); | ||
338 | static void sil24_pmp_detach(struct ata_port *ap); | ||
339 | static int sil24_pmp_read(struct ata_device *dev, int pmp, int reg, u32 *r_val); | ||
340 | static int sil24_pmp_write(struct ata_device *dev, int pmp, int reg, u32 val); | ||
336 | static void sil24_freeze(struct ata_port *ap); | 341 | static void sil24_freeze(struct ata_port *ap); |
337 | static void sil24_thaw(struct ata_port *ap); | 342 | static void sil24_thaw(struct ata_port *ap); |
338 | static void sil24_error_handler(struct ata_port *ap); | 343 | static void sil24_error_handler(struct ata_port *ap); |
@@ -341,6 +346,7 @@ static int sil24_port_start(struct ata_port *ap); | |||
341 | static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); | 346 | static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); |
342 | #ifdef CONFIG_PM | 347 | #ifdef CONFIG_PM |
343 | static int sil24_pci_device_resume(struct pci_dev *pdev); | 348 | static int sil24_pci_device_resume(struct pci_dev *pdev); |
349 | static int sil24_port_resume(struct ata_port *ap); | ||
344 | #endif | 350 | #endif |
345 | 351 | ||
346 | static const struct pci_device_id sil24_pci_tbl[] = { | 352 | static const struct pci_device_id sil24_pci_tbl[] = { |
@@ -393,7 +399,7 @@ static const struct ata_port_operations sil24_ops = { | |||
393 | 399 | ||
394 | .tf_read = sil24_tf_read, | 400 | .tf_read = sil24_tf_read, |
395 | 401 | ||
396 | .qc_defer = ata_std_qc_defer, | 402 | .qc_defer = sil24_qc_defer, |
397 | .qc_prep = sil24_qc_prep, | 403 | .qc_prep = sil24_qc_prep, |
398 | .qc_issue = sil24_qc_issue, | 404 | .qc_issue = sil24_qc_issue, |
399 | 405 | ||
@@ -402,12 +408,21 @@ static const struct ata_port_operations sil24_ops = { | |||
402 | .scr_read = sil24_scr_read, | 408 | .scr_read = sil24_scr_read, |
403 | .scr_write = sil24_scr_write, | 409 | .scr_write = sil24_scr_write, |
404 | 410 | ||
411 | .pmp_attach = sil24_pmp_attach, | ||
412 | .pmp_detach = sil24_pmp_detach, | ||
413 | .pmp_read = sil24_pmp_read, | ||
414 | .pmp_write = sil24_pmp_write, | ||
415 | |||
405 | .freeze = sil24_freeze, | 416 | .freeze = sil24_freeze, |
406 | .thaw = sil24_thaw, | 417 | .thaw = sil24_thaw, |
407 | .error_handler = sil24_error_handler, | 418 | .error_handler = sil24_error_handler, |
408 | .post_internal_cmd = sil24_post_internal_cmd, | 419 | .post_internal_cmd = sil24_post_internal_cmd, |
409 | 420 | ||
410 | .port_start = sil24_port_start, | 421 | .port_start = sil24_port_start, |
422 | |||
423 | #ifdef CONFIG_PM | ||
424 | .port_resume = sil24_port_resume, | ||
425 | #endif | ||
411 | }; | 426 | }; |
412 | 427 | ||
413 | /* | 428 | /* |
@@ -521,11 +536,40 @@ static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf) | |||
521 | *tf = pp->tf; | 536 | *tf = pp->tf; |
522 | } | 537 | } |
523 | 538 | ||
539 | static void sil24_config_pmp(struct ata_port *ap, int attached) | ||
540 | { | ||
541 | void __iomem *port = ap->ioaddr.cmd_addr; | ||
542 | |||
543 | if (attached) | ||
544 | writel(PORT_CS_PMP_EN, port + PORT_CTRL_STAT); | ||
545 | else | ||
546 | writel(PORT_CS_PMP_EN, port + PORT_CTRL_CLR); | ||
547 | } | ||
548 | |||
549 | static void sil24_clear_pmp(struct ata_port *ap) | ||
550 | { | ||
551 | void __iomem *port = ap->ioaddr.cmd_addr; | ||
552 | int i; | ||
553 | |||
554 | writel(PORT_CS_PMP_RESUME, port + PORT_CTRL_CLR); | ||
555 | |||
556 | for (i = 0; i < SATA_PMP_MAX_PORTS; i++) { | ||
557 | void __iomem *pmp_base = port + PORT_PMP + i * PORT_PMP_SIZE; | ||
558 | |||
559 | writel(0, pmp_base + PORT_PMP_STATUS); | ||
560 | writel(0, pmp_base + PORT_PMP_QACTIVE); | ||
561 | } | ||
562 | } | ||
563 | |||
524 | static int sil24_init_port(struct ata_port *ap) | 564 | static int sil24_init_port(struct ata_port *ap) |
525 | { | 565 | { |
526 | void __iomem *port = ap->ioaddr.cmd_addr; | 566 | void __iomem *port = ap->ioaddr.cmd_addr; |
527 | u32 tmp; | 567 | u32 tmp; |
528 | 568 | ||
569 | /* clear PMP error status */ | ||
570 | if (ap->nr_pmp_links) | ||
571 | sil24_clear_pmp(ap); | ||
572 | |||
529 | writel(PORT_CS_INIT, port + PORT_CTRL_STAT); | 573 | writel(PORT_CS_INIT, port + PORT_CTRL_STAT); |
530 | ata_wait_register(port + PORT_CTRL_STAT, | 574 | ata_wait_register(port + PORT_CTRL_STAT, |
531 | PORT_CS_INIT, PORT_CS_INIT, 10, 100); | 575 | PORT_CS_INIT, PORT_CS_INIT, 10, 100); |
@@ -640,7 +684,7 @@ static int sil24_do_softreset(struct ata_link *link, unsigned int *class, | |||
640 | static int sil24_softreset(struct ata_link *link, unsigned int *class, | 684 | static int sil24_softreset(struct ata_link *link, unsigned int *class, |
641 | unsigned long deadline) | 685 | unsigned long deadline) |
642 | { | 686 | { |
643 | return sil24_do_softreset(link, class, 0, deadline); | 687 | return sil24_do_softreset(link, class, SATA_PMP_CTRL_PORT, deadline); |
644 | } | 688 | } |
645 | 689 | ||
646 | static int sil24_hardreset(struct ata_link *link, unsigned int *class, | 690 | static int sil24_hardreset(struct ata_link *link, unsigned int *class, |
@@ -708,6 +752,38 @@ static inline void sil24_fill_sg(struct ata_queued_cmd *qc, | |||
708 | } | 752 | } |
709 | } | 753 | } |
710 | 754 | ||
755 | static int sil24_qc_defer(struct ata_queued_cmd *qc) | ||
756 | { | ||
757 | struct ata_link *link = qc->dev->link; | ||
758 | struct ata_port *ap = link->ap; | ||
759 | u8 prot = qc->tf.protocol; | ||
760 | int is_atapi = (prot == ATA_PROT_ATAPI || | ||
761 | prot == ATA_PROT_ATAPI_NODATA || | ||
762 | prot == ATA_PROT_ATAPI_DMA); | ||
763 | |||
764 | /* ATAPI commands completing with CHECK_SENSE cause various | ||
765 | * weird problems if other commands are active. PMP DMA CS | ||
766 | * errata doesn't cover all and HSM violation occurs even with | ||
767 | * only one other device active. Always run an ATAPI command | ||
768 | * by itself. | ||
769 | */ | ||
770 | if (unlikely(ap->excl_link)) { | ||
771 | if (link == ap->excl_link) { | ||
772 | if (ap->nr_active_links) | ||
773 | return ATA_DEFER_PORT; | ||
774 | qc->flags |= ATA_QCFLAG_CLEAR_EXCL; | ||
775 | } else | ||
776 | return ATA_DEFER_PORT; | ||
777 | } else if (unlikely(is_atapi)) { | ||
778 | ap->excl_link = link; | ||
779 | if (ap->nr_active_links) | ||
780 | return ATA_DEFER_PORT; | ||
781 | qc->flags |= ATA_QCFLAG_CLEAR_EXCL; | ||
782 | } | ||
783 | |||
784 | return ata_std_qc_defer(qc); | ||
785 | } | ||
786 | |||
711 | static void sil24_qc_prep(struct ata_queued_cmd *qc) | 787 | static void sil24_qc_prep(struct ata_queued_cmd *qc) |
712 | { | 788 | { |
713 | struct ata_port *ap = qc->ap; | 789 | struct ata_port *ap = qc->ap; |
@@ -751,7 +827,7 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc) | |||
751 | } | 827 | } |
752 | 828 | ||
753 | prb->ctrl = cpu_to_le16(ctrl); | 829 | prb->ctrl = cpu_to_le16(ctrl); |
754 | ata_tf_to_fis(&qc->tf, 0, 1, prb->fis); | 830 | ata_tf_to_fis(&qc->tf, qc->dev->link->pmp, 1, prb->fis); |
755 | 831 | ||
756 | if (qc->flags & ATA_QCFLAG_DMAMAP) | 832 | if (qc->flags & ATA_QCFLAG_DMAMAP) |
757 | sil24_fill_sg(qc, sge); | 833 | sil24_fill_sg(qc, sge); |
@@ -780,6 +856,65 @@ static void sil24_irq_clear(struct ata_port *ap) | |||
780 | /* unused */ | 856 | /* unused */ |
781 | } | 857 | } |
782 | 858 | ||
859 | static void sil24_pmp_attach(struct ata_port *ap) | ||
860 | { | ||
861 | sil24_config_pmp(ap, 1); | ||
862 | sil24_init_port(ap); | ||
863 | } | ||
864 | |||
865 | static void sil24_pmp_detach(struct ata_port *ap) | ||
866 | { | ||
867 | sil24_init_port(ap); | ||
868 | sil24_config_pmp(ap, 0); | ||
869 | } | ||
870 | |||
871 | static int sil24_pmp_read(struct ata_device *dev, int pmp, int reg, u32 *r_val) | ||
872 | { | ||
873 | struct ata_port *ap = dev->link->ap; | ||
874 | struct ata_taskfile tf; | ||
875 | int rc; | ||
876 | |||
877 | sata_pmp_read_init_tf(&tf, dev, pmp, reg); | ||
878 | rc = sil24_exec_polled_cmd(ap, SATA_PMP_CTRL_PORT, &tf, 1, 0, | ||
879 | SATA_PMP_SCR_TIMEOUT); | ||
880 | if (rc == 0) { | ||
881 | sil24_read_tf(ap, 0, &tf); | ||
882 | *r_val = sata_pmp_read_val(&tf); | ||
883 | } | ||
884 | return rc; | ||
885 | } | ||
886 | |||
887 | static int sil24_pmp_write(struct ata_device *dev, int pmp, int reg, u32 val) | ||
888 | { | ||
889 | struct ata_port *ap = dev->link->ap; | ||
890 | struct ata_taskfile tf; | ||
891 | |||
892 | sata_pmp_write_init_tf(&tf, dev, pmp, reg, val); | ||
893 | return sil24_exec_polled_cmd(ap, SATA_PMP_CTRL_PORT, &tf, 1, 0, | ||
894 | SATA_PMP_SCR_TIMEOUT); | ||
895 | } | ||
896 | |||
897 | static int sil24_pmp_softreset(struct ata_link *link, unsigned int *class, | ||
898 | unsigned long deadline) | ||
899 | { | ||
900 | return sil24_do_softreset(link, class, link->pmp, deadline); | ||
901 | } | ||
902 | |||
903 | static int sil24_pmp_hardreset(struct ata_link *link, unsigned int *class, | ||
904 | unsigned long deadline) | ||
905 | { | ||
906 | int rc; | ||
907 | |||
908 | rc = sil24_init_port(link->ap); | ||
909 | if (rc) { | ||
910 | ata_link_printk(link, KERN_ERR, | ||
911 | "hardreset failed (port not ready)\n"); | ||
912 | return rc; | ||
913 | } | ||
914 | |||
915 | return sata_pmp_std_hardreset(link, class, deadline); | ||
916 | } | ||
917 | |||
783 | static void sil24_freeze(struct ata_port *ap) | 918 | static void sil24_freeze(struct ata_port *ap) |
784 | { | 919 | { |
785 | void __iomem *port = ap->ioaddr.cmd_addr; | 920 | void __iomem *port = ap->ioaddr.cmd_addr; |
@@ -807,8 +942,10 @@ static void sil24_error_intr(struct ata_port *ap) | |||
807 | { | 942 | { |
808 | void __iomem *port = ap->ioaddr.cmd_addr; | 943 | void __iomem *port = ap->ioaddr.cmd_addr; |
809 | struct sil24_port_priv *pp = ap->private_data; | 944 | struct sil24_port_priv *pp = ap->private_data; |
810 | struct ata_eh_info *ehi = &ap->link.eh_info; | 945 | struct ata_queued_cmd *qc = NULL; |
811 | int freeze = 0; | 946 | struct ata_link *link; |
947 | struct ata_eh_info *ehi; | ||
948 | int abort = 0, freeze = 0; | ||
812 | u32 irq_stat; | 949 | u32 irq_stat; |
813 | 950 | ||
814 | /* on error, we need to clear IRQ explicitly */ | 951 | /* on error, we need to clear IRQ explicitly */ |
@@ -816,6 +953,8 @@ static void sil24_error_intr(struct ata_port *ap) | |||
816 | writel(irq_stat, port + PORT_IRQ_STAT); | 953 | writel(irq_stat, port + PORT_IRQ_STAT); |
817 | 954 | ||
818 | /* first, analyze and record host port events */ | 955 | /* first, analyze and record host port events */ |
956 | link = &ap->link; | ||
957 | ehi = &link->eh_info; | ||
819 | ata_ehi_clear_desc(ehi); | 958 | ata_ehi_clear_desc(ehi); |
820 | 959 | ||
821 | ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat); | 960 | ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat); |
@@ -844,8 +983,43 @@ static void sil24_error_intr(struct ata_port *ap) | |||
844 | if (irq_stat & PORT_IRQ_ERROR) { | 983 | if (irq_stat & PORT_IRQ_ERROR) { |
845 | struct sil24_cerr_info *ci = NULL; | 984 | struct sil24_cerr_info *ci = NULL; |
846 | unsigned int err_mask = 0, action = 0; | 985 | unsigned int err_mask = 0, action = 0; |
847 | struct ata_queued_cmd *qc; | 986 | u32 context, cerr; |
848 | u32 cerr; | 987 | int pmp; |
988 | |||
989 | abort = 1; | ||
990 | |||
991 | /* DMA Context Switch Failure in Port Multiplier Mode | ||
992 | * errata. If we have active commands to 3 or more | ||
993 | * devices, any error condition on active devices can | ||
994 | * corrupt DMA context switching. | ||
995 | */ | ||
996 | if (ap->nr_active_links >= 3) { | ||
997 | ehi->err_mask |= AC_ERR_OTHER; | ||
998 | ehi->action |= ATA_EH_HARDRESET; | ||
999 | ata_ehi_push_desc(ehi, "PMP DMA CS errata"); | ||
1000 | freeze = 1; | ||
1001 | } | ||
1002 | |||
1003 | /* find out the offending link and qc */ | ||
1004 | if (ap->nr_pmp_links) { | ||
1005 | context = readl(port + PORT_CONTEXT); | ||
1006 | pmp = (context >> 5) & 0xf; | ||
1007 | |||
1008 | if (pmp < ap->nr_pmp_links) { | ||
1009 | link = &ap->pmp_link[pmp]; | ||
1010 | ehi = &link->eh_info; | ||
1011 | qc = ata_qc_from_tag(ap, link->active_tag); | ||
1012 | |||
1013 | ata_ehi_clear_desc(ehi); | ||
1014 | ata_ehi_push_desc(ehi, "irq_stat 0x%08x", | ||
1015 | irq_stat); | ||
1016 | } else { | ||
1017 | err_mask |= AC_ERR_HSM; | ||
1018 | action |= ATA_EH_HARDRESET; | ||
1019 | freeze = 1; | ||
1020 | } | ||
1021 | } else | ||
1022 | qc = ata_qc_from_tag(ap, link->active_tag); | ||
849 | 1023 | ||
850 | /* analyze CMD_ERR */ | 1024 | /* analyze CMD_ERR */ |
851 | cerr = readl(port + PORT_CMD_ERR); | 1025 | cerr = readl(port + PORT_CMD_ERR); |
@@ -864,7 +1038,6 @@ static void sil24_error_intr(struct ata_port *ap) | |||
864 | } | 1038 | } |
865 | 1039 | ||
866 | /* record error info */ | 1040 | /* record error info */ |
867 | qc = ata_qc_from_tag(ap, ap->link.active_tag); | ||
868 | if (qc) { | 1041 | if (qc) { |
869 | sil24_read_tf(ap, qc->tag, &pp->tf); | 1042 | sil24_read_tf(ap, qc->tag, &pp->tf); |
870 | qc->err_mask |= err_mask; | 1043 | qc->err_mask |= err_mask; |
@@ -872,13 +1045,21 @@ static void sil24_error_intr(struct ata_port *ap) | |||
872 | ehi->err_mask |= err_mask; | 1045 | ehi->err_mask |= err_mask; |
873 | 1046 | ||
874 | ehi->action |= action; | 1047 | ehi->action |= action; |
1048 | |||
1049 | /* if PMP, resume */ | ||
1050 | if (ap->nr_pmp_links) | ||
1051 | writel(PORT_CS_PMP_RESUME, port + PORT_CTRL_STAT); | ||
875 | } | 1052 | } |
876 | 1053 | ||
877 | /* freeze or abort */ | 1054 | /* freeze or abort */ |
878 | if (freeze) | 1055 | if (freeze) |
879 | ata_port_freeze(ap); | 1056 | ata_port_freeze(ap); |
880 | else | 1057 | else if (abort) { |
881 | ata_port_abort(ap); | 1058 | if (qc) |
1059 | ata_link_abort(qc->dev->link); | ||
1060 | else | ||
1061 | ata_port_abort(ap); | ||
1062 | } | ||
882 | } | 1063 | } |
883 | 1064 | ||
884 | static void sil24_finish_qc(struct ata_queued_cmd *qc) | 1065 | static void sil24_finish_qc(struct ata_queued_cmd *qc) |
@@ -971,16 +1152,14 @@ static irqreturn_t sil24_interrupt(int irq, void *dev_instance) | |||
971 | 1152 | ||
972 | static void sil24_error_handler(struct ata_port *ap) | 1153 | static void sil24_error_handler(struct ata_port *ap) |
973 | { | 1154 | { |
974 | struct ata_eh_context *ehc = &ap->link.eh_context; | 1155 | if (sil24_init_port(ap)) |
975 | |||
976 | if (sil24_init_port(ap)) { | ||
977 | ata_eh_freeze_port(ap); | 1156 | ata_eh_freeze_port(ap); |
978 | ehc->i.action |= ATA_EH_HARDRESET; | ||
979 | } | ||
980 | 1157 | ||
981 | /* perform recovery */ | 1158 | /* perform recovery */ |
982 | ata_do_eh(ap, ata_std_prereset, sil24_softreset, sil24_hardreset, | 1159 | sata_pmp_do_eh(ap, ata_std_prereset, sil24_softreset, sil24_hardreset, |
983 | ata_std_postreset); | 1160 | ata_std_postreset, sata_pmp_std_prereset, |
1161 | sil24_pmp_softreset, sil24_pmp_hardreset, | ||
1162 | sata_pmp_std_postreset); | ||
984 | } | 1163 | } |
985 | 1164 | ||
986 | static void sil24_post_internal_cmd(struct ata_queued_cmd *qc) | 1165 | static void sil24_post_internal_cmd(struct ata_queued_cmd *qc) |
@@ -988,8 +1167,8 @@ static void sil24_post_internal_cmd(struct ata_queued_cmd *qc) | |||
988 | struct ata_port *ap = qc->ap; | 1167 | struct ata_port *ap = qc->ap; |
989 | 1168 | ||
990 | /* make DMA engine forget about the failed command */ | 1169 | /* make DMA engine forget about the failed command */ |
991 | if (qc->flags & ATA_QCFLAG_FAILED) | 1170 | if ((qc->flags & ATA_QCFLAG_FAILED) && sil24_init_port(ap)) |
992 | sil24_init_port(ap); | 1171 | ata_eh_freeze_port(ap); |
993 | } | 1172 | } |
994 | 1173 | ||
995 | static int sil24_port_start(struct ata_port *ap) | 1174 | static int sil24_port_start(struct ata_port *ap) |
@@ -1190,6 +1369,12 @@ static int sil24_pci_device_resume(struct pci_dev *pdev) | |||
1190 | 1369 | ||
1191 | return 0; | 1370 | return 0; |
1192 | } | 1371 | } |
1372 | |||
1373 | static int sil24_port_resume(struct ata_port *ap) | ||
1374 | { | ||
1375 | sil24_config_pmp(ap, ap->nr_pmp_links); | ||
1376 | return 0; | ||
1377 | } | ||
1193 | #endif | 1378 | #endif |
1194 | 1379 | ||
1195 | static int __init sil24_init(void) | 1380 | static int __init sil24_init(void) |