Skip to content

Commit 53f8b1b

Browse files
cforno12-zzdavem330
authored andcommitted
ibmvnic: Allow device probe if the device is not ready at boot
Allow the device to be initialized at a later time if it is not available at boot. The device will be allowed to probe but will be given a "down" state. After completing device probe and registering the net device, the driver will await an interrupt signal from its partner device, indicating that it is ready for boot. The driver will schedule a work event to perform the necessary procedure and begin operation. Co-developed-by: Thomas Falcon <[email protected]> Signed-off-by: Thomas Falcon <[email protected]> Signed-off-by: Cristobal Forno <[email protected]> Acked-by: Lijun Pan <[email protected]> Reviewed-by: Dany Madden <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 1b6c215 commit 53f8b1b

File tree

2 files changed

+132
-27
lines changed

2 files changed

+132
-27
lines changed

drivers/net/ethernet/ibm/ibmvnic.c

Lines changed: 128 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,29 @@ static const struct ibmvnic_stat ibmvnic_stats[] = {
141141
{"internal_mac_rx_errors", IBMVNIC_STAT_OFF(internal_mac_rx_errors)},
142142
};
143143

144+
static int send_crq_init_complete(struct ibmvnic_adapter *adapter)
145+
{
146+
union ibmvnic_crq crq;
147+
148+
memset(&crq, 0, sizeof(crq));
149+
crq.generic.first = IBMVNIC_CRQ_INIT_CMD;
150+
crq.generic.cmd = IBMVNIC_CRQ_INIT_COMPLETE;
151+
152+
return ibmvnic_send_crq(adapter, &crq);
153+
}
154+
155+
static int send_version_xchg(struct ibmvnic_adapter *adapter)
156+
{
157+
union ibmvnic_crq crq;
158+
159+
memset(&crq, 0, sizeof(crq));
160+
crq.version_exchange.first = IBMVNIC_CRQ_CMD;
161+
crq.version_exchange.cmd = VERSION_EXCHANGE;
162+
crq.version_exchange.version = cpu_to_be16(ibmvnic_version);
163+
164+
return ibmvnic_send_crq(adapter, &crq);
165+
}
166+
144167
static long h_reg_sub_crq(unsigned long unit_address, unsigned long token,
145168
unsigned long length, unsigned long *number,
146169
unsigned long *irq)
@@ -2083,10 +2106,10 @@ static int do_reset(struct ibmvnic_adapter *adapter,
20832106
goto out;
20842107
}
20852108

2086-
/* If the adapter was in PROBE state prior to the reset,
2109+
/* If the adapter was in PROBE or DOWN state prior to the reset,
20872110
* exit here.
20882111
*/
2089-
if (reset_state == VNIC_PROBED) {
2112+
if (reset_state == VNIC_PROBED || reset_state == VNIC_DOWN) {
20902113
rc = 0;
20912114
goto out;
20922115
}
@@ -2212,10 +2235,10 @@ static int do_hard_reset(struct ibmvnic_adapter *adapter,
22122235
if (rc)
22132236
goto out;
22142237

2215-
/* If the adapter was in PROBE state prior to the reset,
2238+
/* If the adapter was in PROBE or DOWN state prior to the reset,
22162239
* exit here.
22172240
*/
2218-
if (reset_state == VNIC_PROBED)
2241+
if (reset_state == VNIC_PROBED || reset_state == VNIC_DOWN)
22192242
goto out;
22202243

22212244
rc = ibmvnic_login(netdev);
@@ -2268,6 +2291,76 @@ static struct ibmvnic_rwi *get_next_rwi(struct ibmvnic_adapter *adapter)
22682291
return rwi;
22692292
}
22702293

2294+
/**
2295+
* do_passive_init - complete probing when partner device is detected.
2296+
* @adapter: ibmvnic_adapter struct
2297+
*
2298+
* If the ibmvnic device does not have a partner device to communicate with at boot
2299+
* and that partner device comes online at a later time, this function is called
2300+
* to complete the initialization process of ibmvnic device.
2301+
* Caller is expected to hold rtnl_lock().
2302+
*
2303+
* Returns non-zero if sub-CRQs are not initialized properly leaving the device
2304+
* in the down state.
2305+
* Returns 0 upon success and the device is in PROBED state.
2306+
*/
2307+
2308+
static int do_passive_init(struct ibmvnic_adapter *adapter)
2309+
{
2310+
unsigned long timeout = msecs_to_jiffies(30000);
2311+
struct net_device *netdev = adapter->netdev;
2312+
struct device *dev = &adapter->vdev->dev;
2313+
int rc;
2314+
2315+
netdev_dbg(netdev, "Partner device found, probing.\n");
2316+
2317+
adapter->state = VNIC_PROBING;
2318+
reinit_completion(&adapter->init_done);
2319+
adapter->init_done_rc = 0;
2320+
adapter->crq.active = true;
2321+
2322+
rc = send_crq_init_complete(adapter);
2323+
if (rc)
2324+
goto out;
2325+
2326+
rc = send_version_xchg(adapter);
2327+
if (rc)
2328+
netdev_dbg(adapter->netdev, "send_version_xchg failed, rc=%d\n", rc);
2329+
2330+
if (!wait_for_completion_timeout(&adapter->init_done, timeout)) {
2331+
dev_err(dev, "Initialization sequence timed out\n");
2332+
rc = -ETIMEDOUT;
2333+
goto out;
2334+
}
2335+
2336+
rc = init_sub_crqs(adapter);
2337+
if (rc) {
2338+
dev_err(dev, "Initialization of sub crqs failed, rc=%d\n", rc);
2339+
goto out;
2340+
}
2341+
2342+
rc = init_sub_crq_irqs(adapter);
2343+
if (rc) {
2344+
dev_err(dev, "Failed to initialize sub crq irqs\n, rc=%d", rc);
2345+
goto init_failed;
2346+
}
2347+
2348+
netdev->mtu = adapter->req_mtu - ETH_HLEN;
2349+
netdev->min_mtu = adapter->min_mtu - ETH_HLEN;
2350+
netdev->max_mtu = adapter->max_mtu - ETH_HLEN;
2351+
2352+
adapter->state = VNIC_PROBED;
2353+
netdev_dbg(netdev, "Probed successfully. Waiting for signal from partner device.\n");
2354+
2355+
return 0;
2356+
2357+
init_failed:
2358+
release_sub_crqs(adapter, 1);
2359+
out:
2360+
adapter->state = VNIC_DOWN;
2361+
return rc;
2362+
}
2363+
22712364
static void __ibmvnic_reset(struct work_struct *work)
22722365
{
22732366
struct ibmvnic_rwi *rwi;
@@ -2304,7 +2397,13 @@ static void __ibmvnic_reset(struct work_struct *work)
23042397
}
23052398
spin_unlock_irqrestore(&adapter->state_lock, flags);
23062399

2307-
if (adapter->force_reset_recovery) {
2400+
if (rwi->reset_reason == VNIC_RESET_PASSIVE_INIT) {
2401+
rtnl_lock();
2402+
rc = do_passive_init(adapter);
2403+
rtnl_unlock();
2404+
if (!rc)
2405+
netif_carrier_on(adapter->netdev);
2406+
} else if (adapter->force_reset_recovery) {
23082407
/* Since we are doing a hard reset now, clear the
23092408
* failover_pending flag so we don't ignore any
23102409
* future MOBILITY or other resets.
@@ -3773,18 +3872,6 @@ static int ibmvnic_send_crq_init(struct ibmvnic_adapter *adapter)
37733872
return 0;
37743873
}
37753874

3776-
static int send_version_xchg(struct ibmvnic_adapter *adapter)
3777-
{
3778-
union ibmvnic_crq crq;
3779-
3780-
memset(&crq, 0, sizeof(crq));
3781-
crq.version_exchange.first = IBMVNIC_CRQ_CMD;
3782-
crq.version_exchange.cmd = VERSION_EXCHANGE;
3783-
crq.version_exchange.version = cpu_to_be16(ibmvnic_version);
3784-
3785-
return ibmvnic_send_crq(adapter, &crq);
3786-
}
3787-
37883875
struct vnic_login_client_data {
37893876
u8 type;
37903877
__be16 len;
@@ -4904,7 +4991,12 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
49044991
complete(&adapter->init_done);
49054992
adapter->init_done_rc = -EIO;
49064993
}
4907-
rc = ibmvnic_reset(adapter, VNIC_RESET_FAILOVER);
4994+
4995+
if (adapter->state == VNIC_DOWN)
4996+
rc = ibmvnic_reset(adapter, VNIC_RESET_PASSIVE_INIT);
4997+
else
4998+
rc = ibmvnic_reset(adapter, VNIC_RESET_FAILOVER);
4999+
49085000
if (rc && rc != -EBUSY) {
49095001
/* We were unable to schedule the failover
49105002
* reset either because the adapter was still
@@ -5327,6 +5419,7 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
53275419
struct ibmvnic_adapter *adapter;
53285420
struct net_device *netdev;
53295421
unsigned char *mac_addr_p;
5422+
bool init_success;
53305423
int rc;
53315424

53325425
dev_dbg(&dev->dev, "entering ibmvnic_probe for UA 0x%x\n",
@@ -5373,6 +5466,7 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
53735466
init_completion(&adapter->stats_done);
53745467
clear_bit(0, &adapter->resetting);
53755468

5469+
init_success = false;
53765470
do {
53775471
rc = init_crq_queue(adapter);
53785472
if (rc) {
@@ -5382,10 +5476,16 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
53825476
}
53835477

53845478
rc = ibmvnic_reset_init(adapter, false);
5385-
if (rc && rc != EAGAIN)
5386-
goto ibmvnic_init_fail;
53875479
} while (rc == EAGAIN);
53885480

5481+
/* We are ignoring the error from ibmvnic_reset_init() assuming that the
5482+
* partner is not ready. CRQ is not active. When the partner becomes
5483+
* ready, we will do the passive init reset.
5484+
*/
5485+
5486+
if (!rc)
5487+
init_success = true;
5488+
53895489
rc = init_stats_buffers(adapter);
53905490
if (rc)
53915491
goto ibmvnic_init_fail;
@@ -5394,10 +5494,6 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
53945494
if (rc)
53955495
goto ibmvnic_stats_fail;
53965496

5397-
netdev->mtu = adapter->req_mtu - ETH_HLEN;
5398-
netdev->min_mtu = adapter->min_mtu - ETH_HLEN;
5399-
netdev->max_mtu = adapter->max_mtu - ETH_HLEN;
5400-
54015497
rc = device_create_file(&dev->dev, &dev_attr_failover);
54025498
if (rc)
54035499
goto ibmvnic_dev_file_err;
@@ -5410,7 +5506,14 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
54105506
}
54115507
dev_info(&dev->dev, "ibmvnic registered\n");
54125508

5413-
adapter->state = VNIC_PROBED;
5509+
if (init_success) {
5510+
adapter->state = VNIC_PROBED;
5511+
netdev->mtu = adapter->req_mtu - ETH_HLEN;
5512+
netdev->min_mtu = adapter->min_mtu - ETH_HLEN;
5513+
netdev->max_mtu = adapter->max_mtu - ETH_HLEN;
5514+
} else {
5515+
adapter->state = VNIC_DOWN;
5516+
}
54145517

54155518
adapter->wait_for_reset = false;
54165519
adapter->last_reset_time = jiffies;

drivers/net/ethernet/ibm/ibmvnic.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -851,14 +851,16 @@ enum vnic_state {VNIC_PROBING = 1,
851851
VNIC_CLOSING,
852852
VNIC_CLOSED,
853853
VNIC_REMOVING,
854-
VNIC_REMOVED};
854+
VNIC_REMOVED,
855+
VNIC_DOWN};
855856

856857
enum ibmvnic_reset_reason {VNIC_RESET_FAILOVER = 1,
857858
VNIC_RESET_MOBILITY,
858859
VNIC_RESET_FATAL,
859860
VNIC_RESET_NON_FATAL,
860861
VNIC_RESET_TIMEOUT,
861-
VNIC_RESET_CHANGE_PARAM};
862+
VNIC_RESET_CHANGE_PARAM,
863+
VNIC_RESET_PASSIVE_INIT};
862864

863865
struct ibmvnic_rwi {
864866
enum ibmvnic_reset_reason reset_reason;

0 commit comments

Comments
 (0)