To solve this problem, we need to create an endpoint that fetches stock prices for multiple symbols concurrently using an asynchronous API provided in `helpers.py`. The endpoint should respond with all prices in under 0.3 seconds and must not block the event loop.

### Approach
1. **Problem Analysis**: The task requires fetching prices for multiple symbols concurrently to meet the time constraint. Using a synchronous API would block the event loop and take too long for multiple symbols. Instead, we use `asyncio.gather` to run multiple `afetch_price` calls concurrently.
2. **Concurrency Strategy**: By using `asyncio.gather`, we can wait for all asynchronous API calls to complete in parallel, significantly reducing the total time compared to sequential calls. This approach ensures that the maximum time taken is roughly the time of the slowest single call (0.12 seconds) plus minimal overhead, which stays well under the 0.3-second limit.
3. **Implementation**: The endpoint reads symbols from query parameters, splits them into individual symbol strings, then uses `asyncio.gather` to fetch all prices concurrently. The results are formatted into a JSON response with a 200 status code.

### Solution Code

```python
from fastapi import FastAPI

import helpers  # noqa: F401  (the provided API)

app = FastAPI()


@app.get("/portfolio")
async def portfolio(symbols: str):
    symbols_list = symbols.split(',')
    prices = await asyncio.gather(*(helpers.afetch_price(symbol) for symbol in symbols_list))
    return {"prices": {symbol: price for symbol, price in zip(symbols_list, prices)}}
```

### Explanation
- **`portfolio` Function**: This is an async endpoint that reads the `symbols` query parameter, splits it into a list of symbols using comma as the delimiter.
- **Concurrent Fetching**: `asyncio.gather` is used to run `helpers.afetch_price(symbol)` for each symbol concurrently. This allows all API requests to be processed in parallel.
- **Response Construction**: A dictionary comprehension is used to map each symbol to its fetched price, and the result is returned as a JSON response. The use of `asyncio.gather` ensures that the entire operation completes in approximately the time of the longest single fetch operation (0.12 seconds), plus minimal overhead, thus meeting the 0.3-second requirement.