Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'ibmvnic-Correct-long-term-mapped-buffer-error-handling'

Thomas Falcon says:

====================
ibmvnic: Correct long-term-mapped buffer error handling

This patch set fixes the error-handling of long-term-mapped buffers
during adapter initialization and reset. The first patch fixes a bug
in an incorrectly defined descriptor that was keeping the return
codes from the VIO server from being properly checked. The second patch
fixes and cleans up the error-handling implementation.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+36 -46
+34 -45
drivers/net/ethernet/ibm/ibmvnic.c
··· 163 163 return rc; 164 164 } 165 165 166 - static void reset_long_term_buff(struct ibmvnic_adapter *adapter, 167 - struct ibmvnic_long_term_buff *ltb) 168 - { 169 - memset(ltb->buff, 0, ltb->size); 170 - 171 - init_completion(&adapter->fw_done); 172 - send_request_map(adapter, ltb->addr, ltb->size, ltb->map_id); 173 - wait_for_completion(&adapter->fw_done); 174 - } 175 - 176 166 static int alloc_long_term_buff(struct ibmvnic_adapter *adapter, 177 167 struct ibmvnic_long_term_buff *ltb, int size) 178 168 { ··· 183 193 send_request_map(adapter, ltb->addr, 184 194 ltb->size, ltb->map_id); 185 195 wait_for_completion(&adapter->fw_done); 196 + 197 + if (adapter->fw_done_rc) { 198 + dev_err(dev, "Couldn't map long term buffer,rc = %d\n", 199 + adapter->fw_done_rc); 200 + return -1; 201 + } 186 202 return 0; 187 203 } 188 204 ··· 204 208 adapter->reset_reason != VNIC_RESET_MOBILITY) 205 209 send_request_unmap(adapter, ltb->map_id); 206 210 dma_free_coherent(dev, ltb->size, ltb->buff, ltb->addr); 211 + } 212 + 213 + static int reset_long_term_buff(struct ibmvnic_adapter *adapter, 214 + struct ibmvnic_long_term_buff *ltb) 215 + { 216 + memset(ltb->buff, 0, ltb->size); 217 + 218 + init_completion(&adapter->fw_done); 219 + send_request_map(adapter, ltb->addr, ltb->size, ltb->map_id); 220 + wait_for_completion(&adapter->fw_done); 221 + 222 + if (adapter->fw_done_rc) { 223 + dev_info(&adapter->vdev->dev, 224 + "Reset failed, attempting to free and reallocate buffer\n"); 225 + free_long_term_buff(adapter, ltb); 226 + return alloc_long_term_buff(adapter, ltb, ltb->size); 227 + } 228 + return 0; 207 229 } 208 230 209 231 static void deactivate_rx_pools(struct ibmvnic_adapter *adapter) ··· 380 366 { 381 367 struct ibmvnic_rx_pool *rx_pool; 382 368 int rx_scrqs; 383 - int i, j; 369 + int i, j, rc; 384 370 385 371 rx_scrqs = be32_to_cpu(adapter->login_rsp_buf->num_rxadd_subcrqs); 386 372 for (i = 0; i < rx_scrqs; i++) { 387 373 rx_pool = &adapter->rx_pool[i]; 388 374 389 - reset_long_term_buff(adapter, &rx_pool->long_term_buff); 375 + rc = reset_long_term_buff(adapter, &rx_pool->long_term_buff); 376 + if (rc) 377 + return rc; 390 378 391 379 for (j = 0; j < rx_pool->size; j++) 392 380 rx_pool->free_map[j] = j; ··· 510 494 { 511 495 struct ibmvnic_tx_pool *tx_pool; 512 496 int tx_scrqs; 513 - int i, j; 497 + int i, j, rc; 514 498 515 499 tx_scrqs = be32_to_cpu(adapter->login_rsp_buf->num_txsubm_subcrqs); 516 500 for (i = 0; i < tx_scrqs; i++) { 517 501 tx_pool = &adapter->tx_pool[i]; 518 502 519 - reset_long_term_buff(adapter, &tx_pool->long_term_buff); 503 + rc = reset_long_term_buff(adapter, &tx_pool->long_term_buff); 504 + if (rc) 505 + return rc; 520 506 521 507 memset(tx_pool->tx_buff, 0, 522 508 adapter->req_tx_entries_per_subcrq * ··· 3093 3075 return 0; 3094 3076 } 3095 3077 3096 - static void handle_request_map_rsp(union ibmvnic_crq *crq, 3097 - struct ibmvnic_adapter *adapter) 3098 - { 3099 - struct device *dev = &adapter->vdev->dev; 3100 - u8 map_id = crq->request_map_rsp.map_id; 3101 - int tx_subcrqs; 3102 - int rx_subcrqs; 3103 - long rc; 3104 - int i; 3105 - 3106 - tx_subcrqs = be32_to_cpu(adapter->login_rsp_buf->num_txsubm_subcrqs); 3107 - rx_subcrqs = be32_to_cpu(adapter->login_rsp_buf->num_rxadd_subcrqs); 3108 - 3109 - rc = crq->request_map_rsp.rc.code; 3110 - if (rc) { 3111 - dev_err(dev, "Error %ld in REQUEST_MAP_RSP\n", rc); 3112 - adapter->map_id--; 3113 - /* need to find and zero tx/rx_pool map_id */ 3114 - for (i = 0; i < tx_subcrqs; i++) { 3115 - if (adapter->tx_pool[i].long_term_buff.map_id == map_id) 3116 - adapter->tx_pool[i].long_term_buff.map_id = 0; 3117 - } 3118 - for (i = 0; i < rx_subcrqs; i++) { 3119 - if (adapter->rx_pool[i].long_term_buff.map_id == map_id) 3120 - adapter->rx_pool[i].long_term_buff.map_id = 0; 3121 - } 3122 - } 3123 - complete(&adapter->fw_done); 3124 - } 3125 - 3126 3078 static void handle_request_unmap_rsp(union ibmvnic_crq *crq, 3127 3079 struct ibmvnic_adapter *adapter) 3128 3080 { ··· 3373 3385 handle_query_map_rsp(crq, adapter); 3374 3386 break; 3375 3387 case REQUEST_MAP_RSP: 3376 - handle_request_map_rsp(crq, adapter); 3388 + adapter->fw_done_rc = crq->request_map_rsp.rc.code; 3389 + complete(&adapter->fw_done); 3377 3390 break; 3378 3391 case REQUEST_UNMAP_RSP: 3379 3392 handle_request_unmap_rsp(crq, adapter);
+2 -1
drivers/net/ethernet/ibm/ibmvnic.h
··· 595 595 u8 cmd; 596 596 u8 reserved1; 597 597 u8 map_id; 598 - u8 reserved2[4]; 598 + u8 reserved2[8]; 599 599 struct ibmvnic_rc rc; 600 600 } __packed __aligned(8); 601 601 ··· 988 988 spinlock_t error_list_lock; 989 989 990 990 struct completion fw_done; 991 + int fw_done_rc; 991 992 992 993 /* partner capabilities */ 993 994 u64 min_tx_queues;