diff options
Diffstat (limited to 'drivers/ieee1394/ohci1394.c')
-rw-r--r-- | drivers/ieee1394/ohci1394.c | 221 |
1 files changed, 10 insertions, 211 deletions
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index a75b1446b6ed..5667c8102efc 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c | |||
@@ -157,7 +157,6 @@ static void dma_trm_reset(struct dma_trm_ctx *d); | |||
157 | static int alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d, | 157 | static int alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d, |
158 | enum context_type type, int ctx, int num_desc, | 158 | enum context_type type, int ctx, int num_desc, |
159 | int buf_size, int split_buf_size, int context_base); | 159 | int buf_size, int split_buf_size, int context_base); |
160 | static void stop_dma_rcv_ctx(struct dma_rcv_ctx *d); | ||
161 | static void free_dma_rcv_ctx(struct dma_rcv_ctx *d); | 160 | static void free_dma_rcv_ctx(struct dma_rcv_ctx *d); |
162 | 161 | ||
163 | static int alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d, | 162 | static int alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d, |
@@ -520,9 +519,6 @@ static void ohci_initialize(struct ti_ohci *ohci) | |||
520 | initialize_dma_trm_ctx(&ohci->at_req_context); | 519 | initialize_dma_trm_ctx(&ohci->at_req_context); |
521 | initialize_dma_trm_ctx(&ohci->at_resp_context); | 520 | initialize_dma_trm_ctx(&ohci->at_resp_context); |
522 | 521 | ||
523 | /* Initialize IR Legacy DMA channel mask */ | ||
524 | ohci->ir_legacy_channels = 0; | ||
525 | |||
526 | /* Accept AR requests from all nodes */ | 522 | /* Accept AR requests from all nodes */ |
527 | reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000); | 523 | reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000); |
528 | 524 | ||
@@ -869,36 +865,9 @@ static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet) | |||
869 | return -EOVERFLOW; | 865 | return -EOVERFLOW; |
870 | } | 866 | } |
871 | 867 | ||
872 | /* Decide whether we have an iso, a request, or a response packet */ | ||
873 | if (packet->type == hpsb_raw) | 868 | if (packet->type == hpsb_raw) |
874 | d = &ohci->at_req_context; | 869 | d = &ohci->at_req_context; |
875 | else if ((packet->tcode == TCODE_ISO_DATA) && (packet->type == hpsb_iso)) { | 870 | else if ((packet->tcode & 0x02) && (packet->tcode != TCODE_ISO_DATA)) |
876 | /* The legacy IT DMA context is initialized on first | ||
877 | * use. However, the alloc cannot be run from | ||
878 | * interrupt context, so we bail out if that is the | ||
879 | * case. I don't see anyone sending ISO packets from | ||
880 | * interrupt context anyway... */ | ||
881 | |||
882 | if (ohci->it_legacy_context.ohci == NULL) { | ||
883 | if (in_interrupt()) { | ||
884 | PRINT(KERN_ERR, | ||
885 | "legacy IT context cannot be initialized during interrupt"); | ||
886 | return -EINVAL; | ||
887 | } | ||
888 | |||
889 | if (alloc_dma_trm_ctx(ohci, &ohci->it_legacy_context, | ||
890 | DMA_CTX_ISO, 0, IT_NUM_DESC, | ||
891 | OHCI1394_IsoXmitContextBase) < 0) { | ||
892 | PRINT(KERN_ERR, | ||
893 | "error initializing legacy IT context"); | ||
894 | return -ENOMEM; | ||
895 | } | ||
896 | |||
897 | initialize_dma_trm_ctx(&ohci->it_legacy_context); | ||
898 | } | ||
899 | |||
900 | d = &ohci->it_legacy_context; | ||
901 | } else if ((packet->tcode & 0x02) && (packet->tcode != TCODE_ISO_DATA)) | ||
902 | d = &ohci->at_resp_context; | 871 | d = &ohci->at_resp_context; |
903 | else | 872 | else |
904 | d = &ohci->at_req_context; | 873 | d = &ohci->at_req_context; |
@@ -917,9 +886,7 @@ static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet) | |||
917 | static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg) | 886 | static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg) |
918 | { | 887 | { |
919 | struct ti_ohci *ohci = host->hostdata; | 888 | struct ti_ohci *ohci = host->hostdata; |
920 | int retval = 0; | 889 | int retval = 0, phy_reg; |
921 | unsigned long flags; | ||
922 | int phy_reg; | ||
923 | 890 | ||
924 | switch (cmd) { | 891 | switch (cmd) { |
925 | case RESET_BUS: | 892 | case RESET_BUS: |
@@ -1012,117 +979,6 @@ static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg) | |||
1012 | dma_trm_reset(&ohci->at_resp_context); | 979 | dma_trm_reset(&ohci->at_resp_context); |
1013 | break; | 980 | break; |
1014 | 981 | ||
1015 | case ISO_LISTEN_CHANNEL: | ||
1016 | { | ||
1017 | u64 mask; | ||
1018 | struct dma_rcv_ctx *d = &ohci->ir_legacy_context; | ||
1019 | int ir_legacy_active; | ||
1020 | |||
1021 | if (arg<0 || arg>63) { | ||
1022 | PRINT(KERN_ERR, | ||
1023 | "%s: IS0 listen channel %d is out of range", | ||
1024 | __FUNCTION__, arg); | ||
1025 | return -EFAULT; | ||
1026 | } | ||
1027 | |||
1028 | mask = (u64)0x1<<arg; | ||
1029 | |||
1030 | spin_lock_irqsave(&ohci->IR_channel_lock, flags); | ||
1031 | |||
1032 | if (ohci->ISO_channel_usage & mask) { | ||
1033 | PRINT(KERN_ERR, | ||
1034 | "%s: IS0 listen channel %d is already used", | ||
1035 | __FUNCTION__, arg); | ||
1036 | spin_unlock_irqrestore(&ohci->IR_channel_lock, flags); | ||
1037 | return -EFAULT; | ||
1038 | } | ||
1039 | |||
1040 | ir_legacy_active = ohci->ir_legacy_channels; | ||
1041 | |||
1042 | ohci->ISO_channel_usage |= mask; | ||
1043 | ohci->ir_legacy_channels |= mask; | ||
1044 | |||
1045 | spin_unlock_irqrestore(&ohci->IR_channel_lock, flags); | ||
1046 | |||
1047 | if (!ir_legacy_active) { | ||
1048 | if (ohci1394_register_iso_tasklet(ohci, | ||
1049 | &ohci->ir_legacy_tasklet) < 0) { | ||
1050 | PRINT(KERN_ERR, "No IR DMA context available"); | ||
1051 | return -EBUSY; | ||
1052 | } | ||
1053 | |||
1054 | /* the IR context can be assigned to any DMA context | ||
1055 | * by ohci1394_register_iso_tasklet */ | ||
1056 | d->ctx = ohci->ir_legacy_tasklet.context; | ||
1057 | d->ctrlSet = OHCI1394_IsoRcvContextControlSet + | ||
1058 | 32*d->ctx; | ||
1059 | d->ctrlClear = OHCI1394_IsoRcvContextControlClear + | ||
1060 | 32*d->ctx; | ||
1061 | d->cmdPtr = OHCI1394_IsoRcvCommandPtr + 32*d->ctx; | ||
1062 | d->ctxtMatch = OHCI1394_IsoRcvContextMatch + 32*d->ctx; | ||
1063 | |||
1064 | initialize_dma_rcv_ctx(&ohci->ir_legacy_context, 1); | ||
1065 | |||
1066 | if (printk_ratelimit()) | ||
1067 | DBGMSG("IR legacy activated"); | ||
1068 | } | ||
1069 | |||
1070 | spin_lock_irqsave(&ohci->IR_channel_lock, flags); | ||
1071 | |||
1072 | if (arg>31) | ||
1073 | reg_write(ohci, OHCI1394_IRMultiChanMaskHiSet, | ||
1074 | 1<<(arg-32)); | ||
1075 | else | ||
1076 | reg_write(ohci, OHCI1394_IRMultiChanMaskLoSet, | ||
1077 | 1<<arg); | ||
1078 | |||
1079 | spin_unlock_irqrestore(&ohci->IR_channel_lock, flags); | ||
1080 | DBGMSG("Listening enabled on channel %d", arg); | ||
1081 | break; | ||
1082 | } | ||
1083 | case ISO_UNLISTEN_CHANNEL: | ||
1084 | { | ||
1085 | u64 mask; | ||
1086 | |||
1087 | if (arg<0 || arg>63) { | ||
1088 | PRINT(KERN_ERR, | ||
1089 | "%s: IS0 unlisten channel %d is out of range", | ||
1090 | __FUNCTION__, arg); | ||
1091 | return -EFAULT; | ||
1092 | } | ||
1093 | |||
1094 | mask = (u64)0x1<<arg; | ||
1095 | |||
1096 | spin_lock_irqsave(&ohci->IR_channel_lock, flags); | ||
1097 | |||
1098 | if (!(ohci->ISO_channel_usage & mask)) { | ||
1099 | PRINT(KERN_ERR, | ||
1100 | "%s: IS0 unlisten channel %d is not used", | ||
1101 | __FUNCTION__, arg); | ||
1102 | spin_unlock_irqrestore(&ohci->IR_channel_lock, flags); | ||
1103 | return -EFAULT; | ||
1104 | } | ||
1105 | |||
1106 | ohci->ISO_channel_usage &= ~mask; | ||
1107 | ohci->ir_legacy_channels &= ~mask; | ||
1108 | |||
1109 | if (arg>31) | ||
1110 | reg_write(ohci, OHCI1394_IRMultiChanMaskHiClear, | ||
1111 | 1<<(arg-32)); | ||
1112 | else | ||
1113 | reg_write(ohci, OHCI1394_IRMultiChanMaskLoClear, | ||
1114 | 1<<arg); | ||
1115 | |||
1116 | spin_unlock_irqrestore(&ohci->IR_channel_lock, flags); | ||
1117 | DBGMSG("Listening disabled on channel %d", arg); | ||
1118 | |||
1119 | if (ohci->ir_legacy_channels == 0) { | ||
1120 | stop_dma_rcv_ctx(&ohci->ir_legacy_context); | ||
1121 | DBGMSG("ISO legacy receive context stopped"); | ||
1122 | } | ||
1123 | |||
1124 | break; | ||
1125 | } | ||
1126 | default: | 982 | default: |
1127 | PRINT_G(KERN_ERR, "ohci_devctl cmd %d not implemented yet", | 983 | PRINT_G(KERN_ERR, "ohci_devctl cmd %d not implemented yet", |
1128 | cmd); | 984 | cmd); |
@@ -2868,22 +2724,6 @@ static void dma_trm_tasklet (unsigned long data) | |||
2868 | spin_unlock_irqrestore(&d->lock, flags); | 2724 | spin_unlock_irqrestore(&d->lock, flags); |
2869 | } | 2725 | } |
2870 | 2726 | ||
2871 | static void stop_dma_rcv_ctx(struct dma_rcv_ctx *d) | ||
2872 | { | ||
2873 | if (d->ctrlClear) { | ||
2874 | ohci1394_stop_context(d->ohci, d->ctrlClear, NULL); | ||
2875 | |||
2876 | if (d->type == DMA_CTX_ISO) { | ||
2877 | /* disable interrupts */ | ||
2878 | reg_write(d->ohci, OHCI1394_IsoRecvIntMaskClear, 1 << d->ctx); | ||
2879 | ohci1394_unregister_iso_tasklet(d->ohci, &d->ohci->ir_legacy_tasklet); | ||
2880 | } else { | ||
2881 | tasklet_kill(&d->task); | ||
2882 | } | ||
2883 | } | ||
2884 | } | ||
2885 | |||
2886 | |||
2887 | static void free_dma_rcv_ctx(struct dma_rcv_ctx *d) | 2727 | static void free_dma_rcv_ctx(struct dma_rcv_ctx *d) |
2888 | { | 2728 | { |
2889 | int i; | 2729 | int i; |
@@ -3005,18 +2845,11 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d, | |||
3005 | 2845 | ||
3006 | spin_lock_init(&d->lock); | 2846 | spin_lock_init(&d->lock); |
3007 | 2847 | ||
3008 | if (type == DMA_CTX_ISO) { | 2848 | d->ctrlSet = context_base + OHCI1394_ContextControlSet; |
3009 | ohci1394_init_iso_tasklet(&ohci->ir_legacy_tasklet, | 2849 | d->ctrlClear = context_base + OHCI1394_ContextControlClear; |
3010 | OHCI_ISO_MULTICHANNEL_RECEIVE, | 2850 | d->cmdPtr = context_base + OHCI1394_ContextCommandPtr; |
3011 | dma_rcv_tasklet, (unsigned long) d); | ||
3012 | } else { | ||
3013 | d->ctrlSet = context_base + OHCI1394_ContextControlSet; | ||
3014 | d->ctrlClear = context_base + OHCI1394_ContextControlClear; | ||
3015 | d->cmdPtr = context_base + OHCI1394_ContextCommandPtr; | ||
3016 | |||
3017 | tasklet_init (&d->task, dma_rcv_tasklet, (unsigned long) d); | ||
3018 | } | ||
3019 | 2851 | ||
2852 | tasklet_init(&d->task, dma_rcv_tasklet, (unsigned long) d); | ||
3020 | return 0; | 2853 | return 0; |
3021 | } | 2854 | } |
3022 | 2855 | ||
@@ -3097,28 +2930,10 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d, | |||
3097 | spin_lock_init(&d->lock); | 2930 | spin_lock_init(&d->lock); |
3098 | 2931 | ||
3099 | /* initialize tasklet */ | 2932 | /* initialize tasklet */ |
3100 | if (type == DMA_CTX_ISO) { | 2933 | d->ctrlSet = context_base + OHCI1394_ContextControlSet; |
3101 | ohci1394_init_iso_tasklet(&ohci->it_legacy_tasklet, OHCI_ISO_TRANSMIT, | 2934 | d->ctrlClear = context_base + OHCI1394_ContextControlClear; |
3102 | dma_trm_tasklet, (unsigned long) d); | 2935 | d->cmdPtr = context_base + OHCI1394_ContextCommandPtr; |
3103 | if (ohci1394_register_iso_tasklet(ohci, | 2936 | tasklet_init(&d->task, dma_trm_tasklet, (unsigned long)d); |
3104 | &ohci->it_legacy_tasklet) < 0) { | ||
3105 | PRINT(KERN_ERR, "No IT DMA context available"); | ||
3106 | free_dma_trm_ctx(d); | ||
3107 | return -EBUSY; | ||
3108 | } | ||
3109 | |||
3110 | /* IT can be assigned to any context by register_iso_tasklet */ | ||
3111 | d->ctx = ohci->it_legacy_tasklet.context; | ||
3112 | d->ctrlSet = OHCI1394_IsoXmitContextControlSet + 16 * d->ctx; | ||
3113 | d->ctrlClear = OHCI1394_IsoXmitContextControlClear + 16 * d->ctx; | ||
3114 | d->cmdPtr = OHCI1394_IsoXmitCommandPtr + 16 * d->ctx; | ||
3115 | } else { | ||
3116 | d->ctrlSet = context_base + OHCI1394_ContextControlSet; | ||
3117 | d->ctrlClear = context_base + OHCI1394_ContextControlClear; | ||
3118 | d->cmdPtr = context_base + OHCI1394_ContextCommandPtr; | ||
3119 | tasklet_init (&d->task, dma_trm_tasklet, (unsigned long)d); | ||
3120 | } | ||
3121 | |||
3122 | return 0; | 2937 | return 0; |
3123 | } | 2938 | } |
3124 | 2939 | ||
@@ -3344,20 +3159,6 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev, | |||
3344 | ohci->ISO_channel_usage = 0; | 3159 | ohci->ISO_channel_usage = 0; |
3345 | spin_lock_init(&ohci->IR_channel_lock); | 3160 | spin_lock_init(&ohci->IR_channel_lock); |
3346 | 3161 | ||
3347 | /* Allocate the IR DMA context right here so we don't have | ||
3348 | * to do it in interrupt path - note that this doesn't | ||
3349 | * waste much memory and avoids the jugglery required to | ||
3350 | * allocate it in IRQ path. */ | ||
3351 | if (alloc_dma_rcv_ctx(ohci, &ohci->ir_legacy_context, | ||
3352 | DMA_CTX_ISO, 0, IR_NUM_DESC, | ||
3353 | IR_BUF_SIZE, IR_SPLIT_BUF_SIZE, | ||
3354 | OHCI1394_IsoRcvContextBase) < 0) { | ||
3355 | FAIL(-ENOMEM, "Cannot allocate IR Legacy DMA context"); | ||
3356 | } | ||
3357 | |||
3358 | /* We hopefully don't have to pre-allocate IT DMA like we did | ||
3359 | * for IR DMA above. Allocate it on-demand and mark inactive. */ | ||
3360 | ohci->it_legacy_context.ohci = NULL; | ||
3361 | spin_lock_init(&ohci->event_lock); | 3162 | spin_lock_init(&ohci->event_lock); |
3362 | 3163 | ||
3363 | /* | 3164 | /* |
@@ -3450,8 +3251,6 @@ static void ohci1394_pci_remove(struct pci_dev *pdev) | |||
3450 | free_dma_rcv_ctx(&ohci->ar_resp_context); | 3251 | free_dma_rcv_ctx(&ohci->ar_resp_context); |
3451 | free_dma_trm_ctx(&ohci->at_req_context); | 3252 | free_dma_trm_ctx(&ohci->at_req_context); |
3452 | free_dma_trm_ctx(&ohci->at_resp_context); | 3253 | free_dma_trm_ctx(&ohci->at_resp_context); |
3453 | free_dma_rcv_ctx(&ohci->ir_legacy_context); | ||
3454 | free_dma_trm_ctx(&ohci->it_legacy_context); | ||
3455 | 3254 | ||
3456 | case OHCI_INIT_HAVE_SELFID_BUFFER: | 3255 | case OHCI_INIT_HAVE_SELFID_BUFFER: |
3457 | pci_free_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE, | 3256 | pci_free_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE, |