aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rapidio/rio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rapidio/rio.c')
-rw-r--r--drivers/rapidio/rio.c95
1 files changed, 93 insertions, 2 deletions
diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c
index c40665a4fa33..d4bd69013c50 100644
--- a/drivers/rapidio/rio.c
+++ b/drivers/rapidio/rio.c
@@ -33,6 +33,7 @@
33 33
34static LIST_HEAD(rio_mports); 34static LIST_HEAD(rio_mports);
35static unsigned char next_portid; 35static unsigned char next_portid;
36static DEFINE_SPINLOCK(rio_mmap_lock);
36 37
37/** 38/**
38 * rio_local_get_device_id - Get the base/extended device id for a port 39 * rio_local_get_device_id - Get the base/extended device id for a port
@@ -398,6 +399,49 @@ int rio_release_inb_pwrite(struct rio_dev *rdev)
398EXPORT_SYMBOL_GPL(rio_release_inb_pwrite); 399EXPORT_SYMBOL_GPL(rio_release_inb_pwrite);
399 400
400/** 401/**
402 * rio_map_inb_region -- Map inbound memory region.
403 * @mport: Master port.
404 * @lstart: physical address of memory region to be mapped
405 * @rbase: RIO base address assigned to this window
406 * @size: Size of the memory region
407 * @rflags: Flags for mapping.
408 *
409 * Return: 0 -- Success.
410 *
411 * This function will create the mapping from RIO space to local memory.
412 */
413int rio_map_inb_region(struct rio_mport *mport, dma_addr_t local,
414 u64 rbase, u32 size, u32 rflags)
415{
416 int rc = 0;
417 unsigned long flags;
418
419 if (!mport->ops->map_inb)
420 return -1;
421 spin_lock_irqsave(&rio_mmap_lock, flags);
422 rc = mport->ops->map_inb(mport, local, rbase, size, rflags);
423 spin_unlock_irqrestore(&rio_mmap_lock, flags);
424 return rc;
425}
426EXPORT_SYMBOL_GPL(rio_map_inb_region);
427
428/**
429 * rio_unmap_inb_region -- Unmap the inbound memory region
430 * @mport: Master port
431 * @lstart: physical address of memory region to be unmapped
432 */
433void rio_unmap_inb_region(struct rio_mport *mport, dma_addr_t lstart)
434{
435 unsigned long flags;
436 if (!mport->ops->unmap_inb)
437 return;
438 spin_lock_irqsave(&rio_mmap_lock, flags);
439 mport->ops->unmap_inb(mport, lstart);
440 spin_unlock_irqrestore(&rio_mmap_lock, flags);
441}
442EXPORT_SYMBOL_GPL(rio_unmap_inb_region);
443
444/**
401 * rio_mport_get_physefb - Helper function that returns register offset 445 * rio_mport_get_physefb - Helper function that returns register offset
402 * for Physical Layer Extended Features Block. 446 * for Physical Layer Extended Features Block.
403 * @port: Master port to issue transaction 447 * @port: Master port to issue transaction
@@ -1216,15 +1260,62 @@ static int __devinit rio_init(void)
1216 return 0; 1260 return 0;
1217} 1261}
1218 1262
1263static struct workqueue_struct *rio_wq;
1264
1265struct rio_disc_work {
1266 struct work_struct work;
1267 struct rio_mport *mport;
1268};
1269
1270static void __devinit disc_work_handler(struct work_struct *_work)
1271{
1272 struct rio_disc_work *work;
1273
1274 work = container_of(_work, struct rio_disc_work, work);
1275 pr_debug("RIO: discovery work for mport %d %s\n",
1276 work->mport->id, work->mport->name);
1277 rio_disc_mport(work->mport);
1278
1279 kfree(work);
1280}
1281
1219int __devinit rio_init_mports(void) 1282int __devinit rio_init_mports(void)
1220{ 1283{
1221 struct rio_mport *port; 1284 struct rio_mport *port;
1285 struct rio_disc_work *work;
1286 int no_disc = 0;
1222 1287
1223 list_for_each_entry(port, &rio_mports, node) { 1288 list_for_each_entry(port, &rio_mports, node) {
1224 if (port->host_deviceid >= 0) 1289 if (port->host_deviceid >= 0)
1225 rio_enum_mport(port); 1290 rio_enum_mport(port);
1226 else 1291 else if (!no_disc) {
1227 rio_disc_mport(port); 1292 if (!rio_wq) {
1293 rio_wq = alloc_workqueue("riodisc", 0, 0);
1294 if (!rio_wq) {
1295 pr_err("RIO: unable allocate rio_wq\n");
1296 no_disc = 1;
1297 continue;
1298 }
1299 }
1300
1301 work = kzalloc(sizeof *work, GFP_KERNEL);
1302 if (!work) {
1303 pr_err("RIO: no memory for work struct\n");
1304 no_disc = 1;
1305 continue;
1306 }
1307
1308 work->mport = port;
1309 INIT_WORK(&work->work, disc_work_handler);
1310 queue_work(rio_wq, &work->work);
1311 }
1312 }
1313
1314 if (rio_wq) {
1315 pr_debug("RIO: flush discovery workqueue\n");
1316 flush_workqueue(rio_wq);
1317 pr_debug("RIO: flush discovery workqueue finished\n");
1318 destroy_workqueue(rio_wq);
1228 } 1319 }
1229 1320
1230 rio_init(); 1321 rio_init();