I don't understand why it doesn't work for you. It does for me. Make sure you are calling the procedure by the same name as the procedure name that you create. (I made that mistake in the script posted above, creating sp_oper but calling oper, but after dropping oper and fixing the statement to call sp_oper the above script still gives me the expected output of 20.)
The only thing I can suggest is to add $DBI::errstr to the statement that calls sp_oper so it will give you more specific error information. Change the statement as follows: $dbh->do("CALL sp_oper(15, \@b, '+')") or die "cannot execute or call this procedure: $DBI::errstr\n";