Commit 12b4fdb4f6bccb5459a2f75fbe0eab253bfceab4

Authored by Seungwon Jeon
Committed by James Bottomley
1 parent 7d568652d3

[SCSI] ufs: add dme configuration primitives

Implements to support GET and SET operations of the DME.
These operations are used to configure the behavior of
the UNIPRO. Along with basic operation, {Peer/AttrSetType}
can be mixed.

Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
Reviewed-by: Subhash Jadavani <subhashj@codeaurora.org>
Tested-by: Yaniv Gardi <ygardi@codeaurora.org>
Signed-off-by: Santosh Y <santoshsy@gmail.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>

Showing 3 changed files with 145 additions and 0 deletions Side-by-side Diff

drivers/scsi/ufs/ufshcd.c
... ... @@ -235,6 +235,18 @@
235 235 }
236 236  
237 237 /**
  238 + * ufshcd_get_dme_attr_val - Get the value of attribute returned by UIC command
  239 + * @hba: Pointer to adapter instance
  240 + *
  241 + * This function gets UIC command argument3
  242 + * Returns 0 on success, non zero value on error
  243 + */
  244 +static inline u32 ufshcd_get_dme_attr_val(struct ufs_hba *hba)
  245 +{
  246 + return ufshcd_readl(hba, REG_UIC_COMMAND_ARG_3);
  247 +}
  248 +
  249 +/**
238 250 * ufshcd_get_req_rsp - returns the TR response transaction type
239 251 * @ucd_rsp_ptr: pointer to response UPIU
240 252 */
... ... @@ -1374,6 +1386,80 @@
1374 1386 }
1375 1387  
1376 1388 /**
  1389 + * ufshcd_dme_set_attr - UIC command for DME_SET, DME_PEER_SET
  1390 + * @hba: per adapter instance
  1391 + * @attr_sel: uic command argument1
  1392 + * @attr_set: attribute set type as uic command argument2
  1393 + * @mib_val: setting value as uic command argument3
  1394 + * @peer: indicate whether peer or local
  1395 + *
  1396 + * Returns 0 on success, non-zero value on failure
  1397 + */
  1398 +int ufshcd_dme_set_attr(struct ufs_hba *hba, u32 attr_sel,
  1399 + u8 attr_set, u32 mib_val, u8 peer)
  1400 +{
  1401 + struct uic_command uic_cmd = {0};
  1402 + static const char *const action[] = {
  1403 + "dme-set",
  1404 + "dme-peer-set"
  1405 + };
  1406 + const char *set = action[!!peer];
  1407 + int ret;
  1408 +
  1409 + uic_cmd.command = peer ?
  1410 + UIC_CMD_DME_PEER_SET : UIC_CMD_DME_SET;
  1411 + uic_cmd.argument1 = attr_sel;
  1412 + uic_cmd.argument2 = UIC_ARG_ATTR_TYPE(attr_set);
  1413 + uic_cmd.argument3 = mib_val;
  1414 +
  1415 + ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
  1416 + if (ret)
  1417 + dev_err(hba->dev, "%s: attr-id 0x%x val 0x%x error code %d\n",
  1418 + set, UIC_GET_ATTR_ID(attr_sel), mib_val, ret);
  1419 +
  1420 + return ret;
  1421 +}
  1422 +EXPORT_SYMBOL_GPL(ufshcd_dme_set_attr);
  1423 +
  1424 +/**
  1425 + * ufshcd_dme_get_attr - UIC command for DME_GET, DME_PEER_GET
  1426 + * @hba: per adapter instance
  1427 + * @attr_sel: uic command argument1
  1428 + * @mib_val: the value of the attribute as returned by the UIC command
  1429 + * @peer: indicate whether peer or local
  1430 + *
  1431 + * Returns 0 on success, non-zero value on failure
  1432 + */
  1433 +int ufshcd_dme_get_attr(struct ufs_hba *hba, u32 attr_sel,
  1434 + u32 *mib_val, u8 peer)
  1435 +{
  1436 + struct uic_command uic_cmd = {0};
  1437 + static const char *const action[] = {
  1438 + "dme-get",
  1439 + "dme-peer-get"
  1440 + };
  1441 + const char *get = action[!!peer];
  1442 + int ret;
  1443 +
  1444 + uic_cmd.command = peer ?
  1445 + UIC_CMD_DME_PEER_GET : UIC_CMD_DME_GET;
  1446 + uic_cmd.argument1 = attr_sel;
  1447 +
  1448 + ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
  1449 + if (ret) {
  1450 + dev_err(hba->dev, "%s: attr-id 0x%x error code %d\n",
  1451 + get, UIC_GET_ATTR_ID(attr_sel), ret);
  1452 + goto out;
  1453 + }
  1454 +
  1455 + if (mib_val)
  1456 + *mib_val = uic_cmd.argument3;
  1457 +out:
  1458 + return ret;
  1459 +}
  1460 +EXPORT_SYMBOL_GPL(ufshcd_dme_get_attr);
  1461 +
  1462 +/**
1377 1463 * ufshcd_complete_dev_init() - checks device readiness
1378 1464 * hba: per-adapter instance
1379 1465 *
... ... @@ -1908,6 +1994,8 @@
1908 1994 if (hba->active_uic_cmd) {
1909 1995 hba->active_uic_cmd->argument2 |=
1910 1996 ufshcd_get_uic_cmd_result(hba);
  1997 + hba->active_uic_cmd->argument3 =
  1998 + ufshcd_get_dme_attr_val(hba);
1911 1999 complete(&hba->active_uic_cmd->done);
1912 2000 }
1913 2001 }
drivers/scsi/ufs/ufshcd.h
... ... @@ -263,5 +263,56 @@
263 263 extern int ufshcd_runtime_suspend(struct ufs_hba *hba);
264 264 extern int ufshcd_runtime_resume(struct ufs_hba *hba);
265 265 extern int ufshcd_runtime_idle(struct ufs_hba *hba);
  266 +extern int ufshcd_dme_set_attr(struct ufs_hba *hba, u32 attr_sel,
  267 + u8 attr_set, u32 mib_val, u8 peer);
  268 +extern int ufshcd_dme_get_attr(struct ufs_hba *hba, u32 attr_sel,
  269 + u32 *mib_val, u8 peer);
  270 +
  271 +/* UIC command interfaces for DME primitives */
  272 +#define DME_LOCAL 0
  273 +#define DME_PEER 1
  274 +#define ATTR_SET_NOR 0 /* NORMAL */
  275 +#define ATTR_SET_ST 1 /* STATIC */
  276 +
  277 +static inline int ufshcd_dme_set(struct ufs_hba *hba, u32 attr_sel,
  278 + u32 mib_val)
  279 +{
  280 + return ufshcd_dme_set_attr(hba, attr_sel, ATTR_SET_NOR,
  281 + mib_val, DME_LOCAL);
  282 +}
  283 +
  284 +static inline int ufshcd_dme_st_set(struct ufs_hba *hba, u32 attr_sel,
  285 + u32 mib_val)
  286 +{
  287 + return ufshcd_dme_set_attr(hba, attr_sel, ATTR_SET_ST,
  288 + mib_val, DME_LOCAL);
  289 +}
  290 +
  291 +static inline int ufshcd_dme_peer_set(struct ufs_hba *hba, u32 attr_sel,
  292 + u32 mib_val)
  293 +{
  294 + return ufshcd_dme_set_attr(hba, attr_sel, ATTR_SET_NOR,
  295 + mib_val, DME_PEER);
  296 +}
  297 +
  298 +static inline int ufshcd_dme_peer_st_set(struct ufs_hba *hba, u32 attr_sel,
  299 + u32 mib_val)
  300 +{
  301 + return ufshcd_dme_set_attr(hba, attr_sel, ATTR_SET_ST,
  302 + mib_val, DME_PEER);
  303 +}
  304 +
  305 +static inline int ufshcd_dme_get(struct ufs_hba *hba,
  306 + u32 attr_sel, u32 *mib_val)
  307 +{
  308 + return ufshcd_dme_get_attr(hba, attr_sel, mib_val, DME_LOCAL);
  309 +}
  310 +
  311 +static inline int ufshcd_dme_peer_get(struct ufs_hba *hba,
  312 + u32 attr_sel, u32 *mib_val)
  313 +{
  314 + return ufshcd_dme_get_attr(hba, attr_sel, mib_val, DME_PEER);
  315 +}
  316 +
266 317 #endif /* End of Header */
drivers/scsi/ufs/ufshci.h
... ... @@ -191,6 +191,12 @@
191 191 #define CONFIG_RESULT_CODE_MASK 0xFF
192 192 #define GENERIC_ERROR_CODE_MASK 0xFF
193 193  
  194 +#define UIC_ARG_MIB_SEL(attr, sel) ((((attr) & 0xFFFF) << 16) |\
  195 + ((sel) & 0xFFFF))
  196 +#define UIC_ARG_MIB(attr) UIC_ARG_MIB_SEL(attr, 0)
  197 +#define UIC_ARG_ATTR_TYPE(t) (((t) & 0xFF) << 16)
  198 +#define UIC_GET_ATTR_ID(v) (((v) >> 16) & 0xFFFF)
  199 +
194 200 /* UIC Commands */
195 201 enum {
196 202 UIC_CMD_DME_GET = 0x01,