Can MySql nested SP be a bottleneck?
There's nothing inherently wrong with what you are doing, assuming the strings you're splitting up into pieces to form the IN sets are coming from a safe source, but I would have these suggestions for optimization:

There's not an obvious reason to make the call to a separate procedure, as this could all be accomplished in a single procedure, and everything requires some finite amount of time to be done, so writing it as a single proc would save some small amount of time, which helps when you're doing a large amount of the same thing... though I don't think that's the biggest issue, by far.

I suspect the big time killer here is the repeated creation of the temporary table.  On my unimpressive dual 1GHz Opteron test machine, I see dramatically different creation times for temporary tables:

Query OK, 0 rows affected (0.24 sec) # ENGINE=InnoDB (default)
Query OK, 0 rows affected (0.02 sec) # ENGINE=MyISAM
Query OK, 0 rows affected (0.00 sec) # ENGINE=MEMORY


Since you are not using the temporary table to directly update another table, you should be free to use the most lightweight engine that fits the application, even if that means you're mixing transactional and non-transactional storage engines, because you don't need subsequent queries based on the temporary table to actually replicate correctly to downstream slaves and there's nothing here to roll back.  You're creating, inserting, selecting, dropping, and this should not have any impact on replication (otherwise, it might).

You should also evaluate the EXPLAIN output from the queries in the nested proc to be sure they are optimal.  Using derived tables, e.g., SELECT ... FROM (SELECT...) do not really appear to be necessary and may not be the most optimal way to write those queries. 

For example:

insert into areas (id, code, name, shortName, levelid, sortOrder)
select a.ID, a.Code, a.Name, a.ShortName, a.LevelID, 0
    from (select id from GeoArea where Code = _parentArea) as t
    INNER JOIN
    GeoAreaLinkCache c
    ON
    c.ParentAreaID = t.id
    inner join GeoArea a
    on c.ChildAreaID = a.ID
    INNER JOIN
    (select id from GeoAreaLevel where Identifier = _areaType) as l
    ON
    a.LevelID = l.id


...would likely be much better written this way (assuming I've parsed it correctly):

INSERT INTO areas (id, code, name, shortName, levelid, sortOrder)
SELECT a.ID, a.Code, a.Name, a.ShortName, a.LevelID, 0
  FROM GeoArea t
 INNER JOIN GeoAreaLinkCache c ON c.ParentAreaID = t.id
 INNER JOIN GeoArea a on c.ChildAreaID = a.ID
 INNER JOIN GeoAreaLevel l ON l.id = a.LevelID
 WHERE l.Identifier = _areaType
   AND t.Code = _parentArea;


Avoiding the derived tables potentially gives the optimizer a lot more options when formulating the query plan because derived tables generally limit the usability of indexes.  They may be logically equivalent but aren't equivalent in execution.