aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ieee1394/ohci1394.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ieee1394/ohci1394.c')
-rw-r--r--drivers/ieee1394/ohci1394.c221
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);
157static int alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d, 157static 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);
160static void stop_dma_rcv_ctx(struct dma_rcv_ctx *d);
161static void free_dma_rcv_ctx(struct dma_rcv_ctx *d); 160static void free_dma_rcv_ctx(struct dma_rcv_ctx *d);
162 161
163static int alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d, 162static 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)
917static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg) 886static 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
2871static 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
2887static void free_dma_rcv_ctx(struct dma_rcv_ctx *d) 2727static 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,