aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire
diff options
context:
space:
mode:
authorYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>2013-03-07 20:45:50 -0500
committerStefan Richter <stefanr@s5r6.in-berlin.de>2013-03-13 11:11:12 -0400
commit111534cd7a376b75e72ddea0c6d00ec956ce3343 (patch)
treeee49c45f44b9945a2110f6167cf878a404a47c74 /drivers/firewire
parenteac31d58ca2818e3fdc7a6e78fa1b56965f604e9 (diff)
firewire net: Introduce fwnet_broadcast_stop() to destroy broadcast resources.
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire')
-rw-r--r--drivers/firewire/net.c68
1 files changed, 36 insertions, 32 deletions
diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
index 21210fb94762..ca41446d62f4 100644
--- a/drivers/firewire/net.c
+++ b/drivers/firewire/net.c
@@ -1146,6 +1146,32 @@ static int fwnet_fifo_start(struct fwnet_device *dev)
1146 return 0; 1146 return 0;
1147} 1147}
1148 1148
1149static void __fwnet_broadcast_stop(struct fwnet_device *dev)
1150{
1151 unsigned u;
1152
1153 if (dev->broadcast_state != FWNET_BROADCAST_ERROR) {
1154 for (u = 0; u < FWNET_ISO_PAGE_COUNT; u++)
1155 kunmap(dev->broadcast_rcv_buffer.pages[u]);
1156 fw_iso_buffer_destroy(&dev->broadcast_rcv_buffer, dev->card);
1157 }
1158 if (dev->broadcast_rcv_context) {
1159 fw_iso_context_destroy(dev->broadcast_rcv_context);
1160 dev->broadcast_rcv_context = NULL;
1161 }
1162 kfree(dev->broadcast_rcv_buffer_ptrs);
1163 dev->broadcast_rcv_buffer_ptrs = NULL;
1164 dev->broadcast_state = FWNET_BROADCAST_ERROR;
1165}
1166
1167static void fwnet_broadcast_stop(struct fwnet_device *dev)
1168{
1169 if (dev->broadcast_state == FWNET_BROADCAST_ERROR)
1170 return;
1171 fw_iso_context_stop(dev->broadcast_rcv_context);
1172 __fwnet_broadcast_stop(dev);
1173}
1174
1149static int fwnet_broadcast_start(struct fwnet_device *dev) 1175static int fwnet_broadcast_start(struct fwnet_device *dev)
1150{ 1176{
1151 struct fw_iso_context *context; 1177 struct fw_iso_context *context;
@@ -1166,7 +1192,7 @@ static int fwnet_broadcast_start(struct fwnet_device *dev)
1166 ptrptr = kmalloc(sizeof(void *) * num_packets, GFP_KERNEL); 1192 ptrptr = kmalloc(sizeof(void *) * num_packets, GFP_KERNEL);
1167 if (!ptrptr) { 1193 if (!ptrptr) {
1168 retval = -ENOMEM; 1194 retval = -ENOMEM;
1169 goto failed_ptrs_alloc; 1195 goto failed;
1170 } 1196 }
1171 dev->broadcast_rcv_buffer_ptrs = ptrptr; 1197 dev->broadcast_rcv_buffer_ptrs = ptrptr;
1172 1198
@@ -1176,13 +1202,15 @@ static int fwnet_broadcast_start(struct fwnet_device *dev)
1176 fwnet_receive_broadcast, dev); 1202 fwnet_receive_broadcast, dev);
1177 if (IS_ERR(context)) { 1203 if (IS_ERR(context)) {
1178 retval = PTR_ERR(context); 1204 retval = PTR_ERR(context);
1179 goto failed_context_create; 1205 goto failed;
1180 } 1206 }
1181 1207
1182 retval = fw_iso_buffer_init(&dev->broadcast_rcv_buffer, dev->card, 1208 retval = fw_iso_buffer_init(&dev->broadcast_rcv_buffer, dev->card,
1183 FWNET_ISO_PAGE_COUNT, DMA_FROM_DEVICE); 1209 FWNET_ISO_PAGE_COUNT, DMA_FROM_DEVICE);
1184 if (retval < 0) 1210 if (retval < 0)
1185 goto failed_buffer_init; 1211 goto failed;
1212
1213 dev->broadcast_state = FWNET_BROADCAST_STOPPED;
1186 1214
1187 for (u = 0; u < FWNET_ISO_PAGE_COUNT; u++) { 1215 for (u = 0; u < FWNET_ISO_PAGE_COUNT; u++) {
1188 void *ptr; 1216 void *ptr;
@@ -1206,7 +1234,7 @@ static int fwnet_broadcast_start(struct fwnet_device *dev)
1206 retval = fw_iso_context_queue(context, &packet, 1234 retval = fw_iso_context_queue(context, &packet,
1207 &dev->broadcast_rcv_buffer, offset); 1235 &dev->broadcast_rcv_buffer, offset);
1208 if (retval < 0) 1236 if (retval < 0)
1209 goto failed_rcv_queue; 1237 goto failed;
1210 1238
1211 offset += max_receive; 1239 offset += max_receive;
1212 } 1240 }
@@ -1216,7 +1244,7 @@ static int fwnet_broadcast_start(struct fwnet_device *dev)
1216 retval = fw_iso_context_start(context, -1, 0, 1244 retval = fw_iso_context_start(context, -1, 0,
1217 FW_ISO_CONTEXT_MATCH_ALL_TAGS); /* ??? sync */ 1245 FW_ISO_CONTEXT_MATCH_ALL_TAGS); /* ??? sync */
1218 if (retval < 0) 1246 if (retval < 0)
1219 goto failed_rcv_queue; 1247 goto failed;
1220 1248
1221 /* FIXME: adjust it according to the min. speed of all known peers? */ 1249 /* FIXME: adjust it according to the min. speed of all known peers? */
1222 dev->broadcast_xmt_max_payload = IEEE1394_MAX_PAYLOAD_S100 1250 dev->broadcast_xmt_max_payload = IEEE1394_MAX_PAYLOAD_S100
@@ -1225,18 +1253,8 @@ static int fwnet_broadcast_start(struct fwnet_device *dev)
1225 1253
1226 return 0; 1254 return 0;
1227 1255
1228 failed_rcv_queue: 1256 failed:
1229 for (u = 0; u < FWNET_ISO_PAGE_COUNT; u++) 1257 __fwnet_broadcast_stop(dev);
1230 kunmap(dev->broadcast_rcv_buffer.pages[u]);
1231 fw_iso_buffer_destroy(&dev->broadcast_rcv_buffer, dev->card);
1232 failed_buffer_init:
1233 fw_iso_context_destroy(context);
1234 dev->broadcast_rcv_context = NULL;
1235 failed_context_create:
1236 kfree(dev->broadcast_rcv_buffer_ptrs);
1237 dev->broadcast_rcv_buffer_ptrs = NULL;
1238 failed_ptrs_alloc:
1239
1240 return retval; 1258 return retval;
1241} 1259}
1242 1260
@@ -1621,22 +1639,8 @@ static int fwnet_remove(struct device *_dev)
1621 unregister_netdev(net); 1639 unregister_netdev(net);
1622 1640
1623 fwnet_fifo_stop(dev); 1641 fwnet_fifo_stop(dev);
1624 if (dev->broadcast_rcv_context) { 1642 fwnet_broadcast_stop(dev);
1625 unsigned u;
1626
1627 fw_iso_context_stop(dev->broadcast_rcv_context);
1628 1643
1629 for (u = 0; u < FWNET_ISO_PAGE_COUNT; u++)
1630 kunmap(dev->broadcast_rcv_buffer.pages[u]);
1631
1632 fw_iso_buffer_destroy(&dev->broadcast_rcv_buffer,
1633 dev->card);
1634 fw_iso_context_destroy(dev->broadcast_rcv_context);
1635 dev->broadcast_rcv_context = NULL;
1636 kfree(dev->broadcast_rcv_buffer_ptrs);
1637 dev->broadcast_rcv_buffer_ptrs = NULL;
1638 dev->broadcast_state = FWNET_BROADCAST_ERROR;
1639 }
1640 for (i = 0; dev->queued_datagrams && i < 5; i++) 1644 for (i = 0; dev->queued_datagrams && i < 5; i++)
1641 ssleep(1); 1645 ssleep(1);
1642 WARN_ON(dev->queued_datagrams); 1646 WARN_ON(dev->queued_datagrams);