diff options
Diffstat (limited to 'drivers/scsi/ufs/ufshcd.c')
-rw-r--r-- | drivers/scsi/ufs/ufshcd.c | 328 |
1 files changed, 281 insertions, 47 deletions
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index b36ca9a2dfbb..04884d663e4e 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c | |||
@@ -36,9 +36,11 @@ | |||
36 | #include <linux/async.h> | 36 | #include <linux/async.h> |
37 | 37 | ||
38 | #include "ufshcd.h" | 38 | #include "ufshcd.h" |
39 | #include "unipro.h" | ||
39 | 40 | ||
40 | #define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\ | 41 | #define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\ |
41 | UTP_TASK_REQ_COMPL |\ | 42 | UTP_TASK_REQ_COMPL |\ |
43 | UIC_POWER_MODE |\ | ||
42 | UFSHCD_ERROR_MASK) | 44 | UFSHCD_ERROR_MASK) |
43 | /* UIC command timeout, unit: ms */ | 45 | /* UIC command timeout, unit: ms */ |
44 | #define UIC_CMD_TIMEOUT 500 | 46 | #define UIC_CMD_TIMEOUT 500 |
@@ -56,6 +58,9 @@ | |||
56 | /* Expose the flag value from utp_upiu_query.value */ | 58 | /* Expose the flag value from utp_upiu_query.value */ |
57 | #define MASK_QUERY_UPIU_FLAG_LOC 0xFF | 59 | #define MASK_QUERY_UPIU_FLAG_LOC 0xFF |
58 | 60 | ||
61 | /* Interrupt aggregation default timeout, unit: 40us */ | ||
62 | #define INT_AGGR_DEF_TO 0x02 | ||
63 | |||
59 | enum { | 64 | enum { |
60 | UFSHCD_MAX_CHANNEL = 0, | 65 | UFSHCD_MAX_CHANNEL = 0, |
61 | UFSHCD_MAX_ID = 1, | 66 | UFSHCD_MAX_ID = 1, |
@@ -78,12 +83,6 @@ enum { | |||
78 | UFSHCD_INT_CLEAR, | 83 | UFSHCD_INT_CLEAR, |
79 | }; | 84 | }; |
80 | 85 | ||
81 | /* Interrupt aggregation options */ | ||
82 | enum { | ||
83 | INT_AGGR_RESET, | ||
84 | INT_AGGR_CONFIG, | ||
85 | }; | ||
86 | |||
87 | /* | 86 | /* |
88 | * ufshcd_wait_for_register - wait for register value to change | 87 | * ufshcd_wait_for_register - wait for register value to change |
89 | * @hba - per-adapter interface | 88 | * @hba - per-adapter interface |
@@ -238,6 +237,18 @@ static inline int ufshcd_get_uic_cmd_result(struct ufs_hba *hba) | |||
238 | } | 237 | } |
239 | 238 | ||
240 | /** | 239 | /** |
240 | * ufshcd_get_dme_attr_val - Get the value of attribute returned by UIC command | ||
241 | * @hba: Pointer to adapter instance | ||
242 | * | ||
243 | * This function gets UIC command argument3 | ||
244 | * Returns 0 on success, non zero value on error | ||
245 | */ | ||
246 | static inline u32 ufshcd_get_dme_attr_val(struct ufs_hba *hba) | ||
247 | { | ||
248 | return ufshcd_readl(hba, REG_UIC_COMMAND_ARG_3); | ||
249 | } | ||
250 | |||
251 | /** | ||
241 | * ufshcd_get_req_rsp - returns the TR response transaction type | 252 | * ufshcd_get_req_rsp - returns the TR response transaction type |
242 | * @ucd_rsp_ptr: pointer to response UPIU | 253 | * @ucd_rsp_ptr: pointer to response UPIU |
243 | */ | 254 | */ |
@@ -260,6 +271,20 @@ ufshcd_get_rsp_upiu_result(struct utp_upiu_rsp *ucd_rsp_ptr) | |||
260 | return be32_to_cpu(ucd_rsp_ptr->header.dword_1) & MASK_RSP_UPIU_RESULT; | 271 | return be32_to_cpu(ucd_rsp_ptr->header.dword_1) & MASK_RSP_UPIU_RESULT; |
261 | } | 272 | } |
262 | 273 | ||
274 | /* | ||
275 | * ufshcd_get_rsp_upiu_data_seg_len - Get the data segment length | ||
276 | * from response UPIU | ||
277 | * @ucd_rsp_ptr: pointer to response UPIU | ||
278 | * | ||
279 | * Return the data segment length. | ||
280 | */ | ||
281 | static inline unsigned int | ||
282 | ufshcd_get_rsp_upiu_data_seg_len(struct utp_upiu_rsp *ucd_rsp_ptr) | ||
283 | { | ||
284 | return be32_to_cpu(ucd_rsp_ptr->header.dword_2) & | ||
285 | MASK_RSP_UPIU_DATA_SEG_LEN; | ||
286 | } | ||
287 | |||
263 | /** | 288 | /** |
264 | * ufshcd_is_exception_event - Check if the device raised an exception event | 289 | * ufshcd_is_exception_event - Check if the device raised an exception event |
265 | * @ucd_rsp_ptr: pointer to response UPIU | 290 | * @ucd_rsp_ptr: pointer to response UPIU |
@@ -276,30 +301,30 @@ static inline bool ufshcd_is_exception_event(struct utp_upiu_rsp *ucd_rsp_ptr) | |||
276 | } | 301 | } |
277 | 302 | ||
278 | /** | 303 | /** |
279 | * ufshcd_config_int_aggr - Configure interrupt aggregation values. | 304 | * ufshcd_reset_intr_aggr - Reset interrupt aggregation values. |
280 | * Currently there is no use case where we want to configure | ||
281 | * interrupt aggregation dynamically. So to configure interrupt | ||
282 | * aggregation, #define INT_AGGR_COUNTER_THRESHOLD_VALUE and | ||
283 | * INT_AGGR_TIMEOUT_VALUE are used. | ||
284 | * @hba: per adapter instance | 305 | * @hba: per adapter instance |
285 | * @option: Interrupt aggregation option | ||
286 | */ | 306 | */ |
287 | static inline void | 307 | static inline void |
288 | ufshcd_config_int_aggr(struct ufs_hba *hba, int option) | 308 | ufshcd_reset_intr_aggr(struct ufs_hba *hba) |
289 | { | 309 | { |
290 | switch (option) { | 310 | ufshcd_writel(hba, INT_AGGR_ENABLE | |
291 | case INT_AGGR_RESET: | 311 | INT_AGGR_COUNTER_AND_TIMER_RESET, |
292 | ufshcd_writel(hba, INT_AGGR_ENABLE | | 312 | REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL); |
293 | INT_AGGR_COUNTER_AND_TIMER_RESET, | 313 | } |
294 | REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL); | 314 | |
295 | break; | 315 | /** |
296 | case INT_AGGR_CONFIG: | 316 | * ufshcd_config_intr_aggr - Configure interrupt aggregation values. |
297 | ufshcd_writel(hba, INT_AGGR_ENABLE | INT_AGGR_PARAM_WRITE | | 317 | * @hba: per adapter instance |
298 | INT_AGGR_COUNTER_THRESHOLD_VALUE | | 318 | * @cnt: Interrupt aggregation counter threshold |
299 | INT_AGGR_TIMEOUT_VALUE, | 319 | * @tmout: Interrupt aggregation timeout value |
300 | REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL); | 320 | */ |
301 | break; | 321 | static inline void |
302 | } | 322 | ufshcd_config_intr_aggr(struct ufs_hba *hba, u8 cnt, u8 tmout) |
323 | { | ||
324 | ufshcd_writel(hba, INT_AGGR_ENABLE | INT_AGGR_PARAM_WRITE | | ||
325 | INT_AGGR_COUNTER_THLD_VAL(cnt) | | ||
326 | INT_AGGR_TIMEOUT_VAL(tmout), | ||
327 | REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL); | ||
303 | } | 328 | } |
304 | 329 | ||
305 | /** | 330 | /** |
@@ -355,7 +380,8 @@ void ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag) | |||
355 | static inline void ufshcd_copy_sense_data(struct ufshcd_lrb *lrbp) | 380 | static inline void ufshcd_copy_sense_data(struct ufshcd_lrb *lrbp) |
356 | { | 381 | { |
357 | int len; | 382 | int len; |
358 | if (lrbp->sense_buffer) { | 383 | if (lrbp->sense_buffer && |
384 | ufshcd_get_rsp_upiu_data_seg_len(lrbp->ucd_rsp_ptr)) { | ||
359 | len = be16_to_cpu(lrbp->ucd_rsp_ptr->sr.sense_data_len); | 385 | len = be16_to_cpu(lrbp->ucd_rsp_ptr->sr.sense_data_len); |
360 | memcpy(lrbp->sense_buffer, | 386 | memcpy(lrbp->sense_buffer, |
361 | lrbp->ucd_rsp_ptr->sr.sense_data, | 387 | lrbp->ucd_rsp_ptr->sr.sense_data, |
@@ -446,6 +472,18 @@ static inline bool ufshcd_ready_for_uic_cmd(struct ufs_hba *hba) | |||
446 | } | 472 | } |
447 | 473 | ||
448 | /** | 474 | /** |
475 | * ufshcd_get_upmcrs - Get the power mode change request status | ||
476 | * @hba: Pointer to adapter instance | ||
477 | * | ||
478 | * This function gets the UPMCRS field of HCS register | ||
479 | * Returns value of UPMCRS field | ||
480 | */ | ||
481 | static inline u8 ufshcd_get_upmcrs(struct ufs_hba *hba) | ||
482 | { | ||
483 | return (ufshcd_readl(hba, REG_CONTROLLER_STATUS) >> 8) & 0x7; | ||
484 | } | ||
485 | |||
486 | /** | ||
449 | * ufshcd_dispatch_uic_cmd - Dispatch UIC commands to unipro layers | 487 | * ufshcd_dispatch_uic_cmd - Dispatch UIC commands to unipro layers |
450 | * @hba: per adapter instance | 488 | * @hba: per adapter instance |
451 | * @uic_cmd: UIC command | 489 | * @uic_cmd: UIC command |
@@ -1362,6 +1400,202 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba) | |||
1362 | } | 1400 | } |
1363 | 1401 | ||
1364 | /** | 1402 | /** |
1403 | * ufshcd_dme_set_attr - UIC command for DME_SET, DME_PEER_SET | ||
1404 | * @hba: per adapter instance | ||
1405 | * @attr_sel: uic command argument1 | ||
1406 | * @attr_set: attribute set type as uic command argument2 | ||
1407 | * @mib_val: setting value as uic command argument3 | ||
1408 | * @peer: indicate whether peer or local | ||
1409 | * | ||
1410 | * Returns 0 on success, non-zero value on failure | ||
1411 | */ | ||
1412 | int ufshcd_dme_set_attr(struct ufs_hba *hba, u32 attr_sel, | ||
1413 | u8 attr_set, u32 mib_val, u8 peer) | ||
1414 | { | ||
1415 | struct uic_command uic_cmd = {0}; | ||
1416 | static const char *const action[] = { | ||
1417 | "dme-set", | ||
1418 | "dme-peer-set" | ||
1419 | }; | ||
1420 | const char *set = action[!!peer]; | ||
1421 | int ret; | ||
1422 | |||
1423 | uic_cmd.command = peer ? | ||
1424 | UIC_CMD_DME_PEER_SET : UIC_CMD_DME_SET; | ||
1425 | uic_cmd.argument1 = attr_sel; | ||
1426 | uic_cmd.argument2 = UIC_ARG_ATTR_TYPE(attr_set); | ||
1427 | uic_cmd.argument3 = mib_val; | ||
1428 | |||
1429 | ret = ufshcd_send_uic_cmd(hba, &uic_cmd); | ||
1430 | if (ret) | ||
1431 | dev_err(hba->dev, "%s: attr-id 0x%x val 0x%x error code %d\n", | ||
1432 | set, UIC_GET_ATTR_ID(attr_sel), mib_val, ret); | ||
1433 | |||
1434 | return ret; | ||
1435 | } | ||
1436 | EXPORT_SYMBOL_GPL(ufshcd_dme_set_attr); | ||
1437 | |||
1438 | /** | ||
1439 | * ufshcd_dme_get_attr - UIC command for DME_GET, DME_PEER_GET | ||
1440 | * @hba: per adapter instance | ||
1441 | * @attr_sel: uic command argument1 | ||
1442 | * @mib_val: the value of the attribute as returned by the UIC command | ||
1443 | * @peer: indicate whether peer or local | ||
1444 | * | ||
1445 | * Returns 0 on success, non-zero value on failure | ||
1446 | */ | ||
1447 | int ufshcd_dme_get_attr(struct ufs_hba *hba, u32 attr_sel, | ||
1448 | u32 *mib_val, u8 peer) | ||
1449 | { | ||
1450 | struct uic_command uic_cmd = {0}; | ||
1451 | static const char *const action[] = { | ||
1452 | "dme-get", | ||
1453 | "dme-peer-get" | ||
1454 | }; | ||
1455 | const char *get = action[!!peer]; | ||
1456 | int ret; | ||
1457 | |||
1458 | uic_cmd.command = peer ? | ||
1459 | UIC_CMD_DME_PEER_GET : UIC_CMD_DME_GET; | ||
1460 | uic_cmd.argument1 = attr_sel; | ||
1461 | |||
1462 | ret = ufshcd_send_uic_cmd(hba, &uic_cmd); | ||
1463 | if (ret) { | ||
1464 | dev_err(hba->dev, "%s: attr-id 0x%x error code %d\n", | ||
1465 | get, UIC_GET_ATTR_ID(attr_sel), ret); | ||
1466 | goto out; | ||
1467 | } | ||
1468 | |||
1469 | if (mib_val) | ||
1470 | *mib_val = uic_cmd.argument3; | ||
1471 | out: | ||
1472 | return ret; | ||
1473 | } | ||
1474 | EXPORT_SYMBOL_GPL(ufshcd_dme_get_attr); | ||
1475 | |||
1476 | /** | ||
1477 | * ufshcd_uic_change_pwr_mode - Perform the UIC power mode chage | ||
1478 | * using DME_SET primitives. | ||
1479 | * @hba: per adapter instance | ||
1480 | * @mode: powr mode value | ||
1481 | * | ||
1482 | * Returns 0 on success, non-zero value on failure | ||
1483 | */ | ||
1484 | int ufshcd_uic_change_pwr_mode(struct ufs_hba *hba, u8 mode) | ||
1485 | { | ||
1486 | struct uic_command uic_cmd = {0}; | ||
1487 | struct completion pwr_done; | ||
1488 | unsigned long flags; | ||
1489 | u8 status; | ||
1490 | int ret; | ||
1491 | |||
1492 | uic_cmd.command = UIC_CMD_DME_SET; | ||
1493 | uic_cmd.argument1 = UIC_ARG_MIB(PA_PWRMODE); | ||
1494 | uic_cmd.argument3 = mode; | ||
1495 | init_completion(&pwr_done); | ||
1496 | |||
1497 | mutex_lock(&hba->uic_cmd_mutex); | ||
1498 | |||
1499 | spin_lock_irqsave(hba->host->host_lock, flags); | ||
1500 | hba->pwr_done = &pwr_done; | ||
1501 | spin_unlock_irqrestore(hba->host->host_lock, flags); | ||
1502 | ret = __ufshcd_send_uic_cmd(hba, &uic_cmd); | ||
1503 | if (ret) { | ||
1504 | dev_err(hba->dev, | ||
1505 | "pwr mode change with mode 0x%x uic error %d\n", | ||
1506 | mode, ret); | ||
1507 | goto out; | ||
1508 | } | ||
1509 | |||
1510 | if (!wait_for_completion_timeout(hba->pwr_done, | ||
1511 | msecs_to_jiffies(UIC_CMD_TIMEOUT))) { | ||
1512 | dev_err(hba->dev, | ||
1513 | "pwr mode change with mode 0x%x completion timeout\n", | ||
1514 | mode); | ||
1515 | ret = -ETIMEDOUT; | ||
1516 | goto out; | ||
1517 | } | ||
1518 | |||
1519 | status = ufshcd_get_upmcrs(hba); | ||
1520 | if (status != PWR_LOCAL) { | ||
1521 | dev_err(hba->dev, | ||
1522 | "pwr mode change failed, host umpcrs:0x%x\n", | ||
1523 | status); | ||
1524 | ret = (status != PWR_OK) ? status : -1; | ||
1525 | } | ||
1526 | out: | ||
1527 | spin_lock_irqsave(hba->host->host_lock, flags); | ||
1528 | hba->pwr_done = NULL; | ||
1529 | spin_unlock_irqrestore(hba->host->host_lock, flags); | ||
1530 | mutex_unlock(&hba->uic_cmd_mutex); | ||
1531 | return ret; | ||
1532 | } | ||
1533 | |||
1534 | /** | ||
1535 | * ufshcd_config_max_pwr_mode - Set & Change power mode with | ||
1536 | * maximum capability attribute information. | ||
1537 | * @hba: per adapter instance | ||
1538 | * | ||
1539 | * Returns 0 on success, non-zero value on failure | ||
1540 | */ | ||
1541 | static int ufshcd_config_max_pwr_mode(struct ufs_hba *hba) | ||
1542 | { | ||
1543 | enum {RX = 0, TX = 1}; | ||
1544 | u32 lanes[] = {1, 1}; | ||
1545 | u32 gear[] = {1, 1}; | ||
1546 | u8 pwr[] = {FASTAUTO_MODE, FASTAUTO_MODE}; | ||
1547 | int ret; | ||
1548 | |||
1549 | /* Get the connected lane count */ | ||
1550 | ufshcd_dme_get(hba, UIC_ARG_MIB(PA_CONNECTEDRXDATALANES), &lanes[RX]); | ||
1551 | ufshcd_dme_get(hba, UIC_ARG_MIB(PA_CONNECTEDTXDATALANES), &lanes[TX]); | ||
1552 | |||
1553 | /* | ||
1554 | * First, get the maximum gears of HS speed. | ||
1555 | * If a zero value, it means there is no HSGEAR capability. | ||
1556 | * Then, get the maximum gears of PWM speed. | ||
1557 | */ | ||
1558 | ufshcd_dme_get(hba, UIC_ARG_MIB(PA_MAXRXHSGEAR), &gear[RX]); | ||
1559 | if (!gear[RX]) { | ||
1560 | ufshcd_dme_get(hba, UIC_ARG_MIB(PA_MAXRXPWMGEAR), &gear[RX]); | ||
1561 | pwr[RX] = SLOWAUTO_MODE; | ||
1562 | } | ||
1563 | |||
1564 | ufshcd_dme_peer_get(hba, UIC_ARG_MIB(PA_MAXRXHSGEAR), &gear[TX]); | ||
1565 | if (!gear[TX]) { | ||
1566 | ufshcd_dme_peer_get(hba, UIC_ARG_MIB(PA_MAXRXPWMGEAR), | ||
1567 | &gear[TX]); | ||
1568 | pwr[TX] = SLOWAUTO_MODE; | ||
1569 | } | ||
1570 | |||
1571 | /* | ||
1572 | * Configure attributes for power mode change with below. | ||
1573 | * - PA_RXGEAR, PA_ACTIVERXDATALANES, PA_RXTERMINATION, | ||
1574 | * - PA_TXGEAR, PA_ACTIVETXDATALANES, PA_TXTERMINATION, | ||
1575 | * - PA_HSSERIES | ||
1576 | */ | ||
1577 | ufshcd_dme_set(hba, UIC_ARG_MIB(PA_RXGEAR), gear[RX]); | ||
1578 | ufshcd_dme_set(hba, UIC_ARG_MIB(PA_ACTIVERXDATALANES), lanes[RX]); | ||
1579 | if (pwr[RX] == FASTAUTO_MODE) | ||
1580 | ufshcd_dme_set(hba, UIC_ARG_MIB(PA_RXTERMINATION), TRUE); | ||
1581 | |||
1582 | ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TXGEAR), gear[TX]); | ||
1583 | ufshcd_dme_set(hba, UIC_ARG_MIB(PA_ACTIVETXDATALANES), lanes[TX]); | ||
1584 | if (pwr[TX] == FASTAUTO_MODE) | ||
1585 | ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TXTERMINATION), TRUE); | ||
1586 | |||
1587 | if (pwr[RX] == FASTAUTO_MODE || pwr[TX] == FASTAUTO_MODE) | ||
1588 | ufshcd_dme_set(hba, UIC_ARG_MIB(PA_HSSERIES), PA_HS_MODE_B); | ||
1589 | |||
1590 | ret = ufshcd_uic_change_pwr_mode(hba, pwr[RX] << 4 | pwr[TX]); | ||
1591 | if (ret) | ||
1592 | dev_err(hba->dev, | ||
1593 | "pwr_mode: power mode change failed %d\n", ret); | ||
1594 | |||
1595 | return ret; | ||
1596 | } | ||
1597 | |||
1598 | /** | ||
1365 | * ufshcd_complete_dev_init() - checks device readiness | 1599 | * ufshcd_complete_dev_init() - checks device readiness |
1366 | * hba: per-adapter instance | 1600 | * hba: per-adapter instance |
1367 | * | 1601 | * |
@@ -1442,7 +1676,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba) | |||
1442 | ufshcd_enable_intr(hba, UFSHCD_ENABLE_INTRS); | 1676 | ufshcd_enable_intr(hba, UFSHCD_ENABLE_INTRS); |
1443 | 1677 | ||
1444 | /* Configure interrupt aggregation */ | 1678 | /* Configure interrupt aggregation */ |
1445 | ufshcd_config_int_aggr(hba, INT_AGGR_CONFIG); | 1679 | ufshcd_config_intr_aggr(hba, hba->nutrs - 1, INT_AGGR_DEF_TO); |
1446 | 1680 | ||
1447 | /* Configure UTRL and UTMRL base address registers */ | 1681 | /* Configure UTRL and UTMRL base address registers */ |
1448 | ufshcd_writel(hba, lower_32_bits(hba->utrdl_dma_addr), | 1682 | ufshcd_writel(hba, lower_32_bits(hba->utrdl_dma_addr), |
@@ -1788,32 +2022,24 @@ ufshcd_scsi_cmd_status(struct ufshcd_lrb *lrbp, int scsi_status) | |||
1788 | int result = 0; | 2022 | int result = 0; |
1789 | 2023 | ||
1790 | switch (scsi_status) { | 2024 | switch (scsi_status) { |
1791 | case SAM_STAT_GOOD: | ||
1792 | result |= DID_OK << 16 | | ||
1793 | COMMAND_COMPLETE << 8 | | ||
1794 | SAM_STAT_GOOD; | ||
1795 | break; | ||
1796 | case SAM_STAT_CHECK_CONDITION: | 2025 | case SAM_STAT_CHECK_CONDITION: |
2026 | ufshcd_copy_sense_data(lrbp); | ||
2027 | case SAM_STAT_GOOD: | ||
1797 | result |= DID_OK << 16 | | 2028 | result |= DID_OK << 16 | |
1798 | COMMAND_COMPLETE << 8 | | 2029 | COMMAND_COMPLETE << 8 | |
1799 | SAM_STAT_CHECK_CONDITION; | 2030 | scsi_status; |
1800 | ufshcd_copy_sense_data(lrbp); | ||
1801 | break; | ||
1802 | case SAM_STAT_BUSY: | ||
1803 | result |= SAM_STAT_BUSY; | ||
1804 | break; | 2031 | break; |
1805 | case SAM_STAT_TASK_SET_FULL: | 2032 | case SAM_STAT_TASK_SET_FULL: |
1806 | |||
1807 | /* | 2033 | /* |
1808 | * If a LUN reports SAM_STAT_TASK_SET_FULL, then the LUN queue | 2034 | * If a LUN reports SAM_STAT_TASK_SET_FULL, then the LUN queue |
1809 | * depth needs to be adjusted to the exact number of | 2035 | * depth needs to be adjusted to the exact number of |
1810 | * outstanding commands the LUN can handle at any given time. | 2036 | * outstanding commands the LUN can handle at any given time. |
1811 | */ | 2037 | */ |
1812 | ufshcd_adjust_lun_qdepth(lrbp->cmd); | 2038 | ufshcd_adjust_lun_qdepth(lrbp->cmd); |
1813 | result |= SAM_STAT_TASK_SET_FULL; | 2039 | case SAM_STAT_BUSY: |
1814 | break; | ||
1815 | case SAM_STAT_TASK_ABORTED: | 2040 | case SAM_STAT_TASK_ABORTED: |
1816 | result |= SAM_STAT_TASK_ABORTED; | 2041 | ufshcd_copy_sense_data(lrbp); |
2042 | result |= scsi_status; | ||
1817 | break; | 2043 | break; |
1818 | default: | 2044 | default: |
1819 | result |= DID_ERROR << 16; | 2045 | result |= DID_ERROR << 16; |
@@ -1898,14 +2124,20 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) | |||
1898 | /** | 2124 | /** |
1899 | * ufshcd_uic_cmd_compl - handle completion of uic command | 2125 | * ufshcd_uic_cmd_compl - handle completion of uic command |
1900 | * @hba: per adapter instance | 2126 | * @hba: per adapter instance |
2127 | * @intr_status: interrupt status generated by the controller | ||
1901 | */ | 2128 | */ |
1902 | static void ufshcd_uic_cmd_compl(struct ufs_hba *hba) | 2129 | static void ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status) |
1903 | { | 2130 | { |
1904 | if (hba->active_uic_cmd) { | 2131 | if ((intr_status & UIC_COMMAND_COMPL) && hba->active_uic_cmd) { |
1905 | hba->active_uic_cmd->argument2 |= | 2132 | hba->active_uic_cmd->argument2 |= |
1906 | ufshcd_get_uic_cmd_result(hba); | 2133 | ufshcd_get_uic_cmd_result(hba); |
2134 | hba->active_uic_cmd->argument3 = | ||
2135 | ufshcd_get_dme_attr_val(hba); | ||
1907 | complete(&hba->active_uic_cmd->done); | 2136 | complete(&hba->active_uic_cmd->done); |
1908 | } | 2137 | } |
2138 | |||
2139 | if ((intr_status & UIC_POWER_MODE) && hba->pwr_done) | ||
2140 | complete(hba->pwr_done); | ||
1909 | } | 2141 | } |
1910 | 2142 | ||
1911 | /** | 2143 | /** |
@@ -1960,7 +2192,7 @@ static void ufshcd_transfer_req_compl(struct ufs_hba *hba) | |||
1960 | 2192 | ||
1961 | /* Reset interrupt aggregation counters */ | 2193 | /* Reset interrupt aggregation counters */ |
1962 | if (int_aggr_reset) | 2194 | if (int_aggr_reset) |
1963 | ufshcd_config_int_aggr(hba, INT_AGGR_RESET); | 2195 | ufshcd_reset_intr_aggr(hba); |
1964 | } | 2196 | } |
1965 | 2197 | ||
1966 | /** | 2198 | /** |
@@ -2251,8 +2483,8 @@ static void ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status) | |||
2251 | if (hba->errors) | 2483 | if (hba->errors) |
2252 | ufshcd_err_handler(hba); | 2484 | ufshcd_err_handler(hba); |
2253 | 2485 | ||
2254 | if (intr_status & UIC_COMMAND_COMPL) | 2486 | if (intr_status & UFSHCD_UIC_MASK) |
2255 | ufshcd_uic_cmd_compl(hba); | 2487 | ufshcd_uic_cmd_compl(hba, intr_status); |
2256 | 2488 | ||
2257 | if (intr_status & UTP_TASK_REQ_COMPL) | 2489 | if (intr_status & UTP_TASK_REQ_COMPL) |
2258 | ufshcd_tmc_handler(hba); | 2490 | ufshcd_tmc_handler(hba); |
@@ -2494,6 +2726,8 @@ static void ufshcd_async_scan(void *data, async_cookie_t cookie) | |||
2494 | if (ret) | 2726 | if (ret) |
2495 | goto out; | 2727 | goto out; |
2496 | 2728 | ||
2729 | ufshcd_config_max_pwr_mode(hba); | ||
2730 | |||
2497 | ret = ufshcd_verify_dev_init(hba); | 2731 | ret = ufshcd_verify_dev_init(hba); |
2498 | if (ret) | 2732 | if (ret) |
2499 | goto out; | 2733 | goto out; |