Commit 2e8b981c authored by Michael S. Tsirkin's avatar Michael S. Tsirkin Committed by Roland Dreier

[PATCH] IB/mthca: add HCA board ID to sysfs info

Add support for reporting HCA board ID returned from QUERY_ADAPTER
firmware command through sysfs.
Signed-off-by: default avatarMichael S. Tsirkin <mst@mellanox.co.il>
Signed-off-by: default avatarRoland Dreier <rolandd@cisco.com>
parent 97f52eb4
...@@ -1085,6 +1085,34 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev, ...@@ -1085,6 +1085,34 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
return err; return err;
} }
static void get_board_id(void *vsd, char *board_id)
{
int i;
#define VSD_OFFSET_SIG1 0x00
#define VSD_OFFSET_SIG2 0xde
#define VSD_OFFSET_MLX_BOARD_ID 0xd0
#define VSD_OFFSET_TS_BOARD_ID 0x20
#define VSD_SIGNATURE_TOPSPIN 0x5ad
memset(board_id, 0, MTHCA_BOARD_ID_LEN);
if (be16_to_cpup(vsd + VSD_OFFSET_SIG1) == VSD_SIGNATURE_TOPSPIN &&
be16_to_cpup(vsd + VSD_OFFSET_SIG2) == VSD_SIGNATURE_TOPSPIN) {
strlcpy(board_id, vsd + VSD_OFFSET_TS_BOARD_ID, MTHCA_BOARD_ID_LEN);
} else {
/*
* The board ID is a string but the firmware byte
* swaps each 4-byte word before passing it back to
* us. Therefore we need to swab it before printing.
*/
for (i = 0; i < 4; ++i)
((u32 *) board_id)[i] =
swab32(*(u32 *) (vsd + VSD_OFFSET_MLX_BOARD_ID + i * 4));
}
}
int mthca_QUERY_ADAPTER(struct mthca_dev *dev, int mthca_QUERY_ADAPTER(struct mthca_dev *dev,
struct mthca_adapter *adapter, u8 *status) struct mthca_adapter *adapter, u8 *status)
{ {
...@@ -1097,6 +1125,7 @@ int mthca_QUERY_ADAPTER(struct mthca_dev *dev, ...@@ -1097,6 +1125,7 @@ int mthca_QUERY_ADAPTER(struct mthca_dev *dev,
#define QUERY_ADAPTER_DEVICE_ID_OFFSET 0x04 #define QUERY_ADAPTER_DEVICE_ID_OFFSET 0x04
#define QUERY_ADAPTER_REVISION_ID_OFFSET 0x08 #define QUERY_ADAPTER_REVISION_ID_OFFSET 0x08
#define QUERY_ADAPTER_INTA_PIN_OFFSET 0x10 #define QUERY_ADAPTER_INTA_PIN_OFFSET 0x10
#define QUERY_ADAPTER_VSD_OFFSET 0x20
mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
if (IS_ERR(mailbox)) if (IS_ERR(mailbox))
...@@ -1114,6 +1143,9 @@ int mthca_QUERY_ADAPTER(struct mthca_dev *dev, ...@@ -1114,6 +1143,9 @@ int mthca_QUERY_ADAPTER(struct mthca_dev *dev,
MTHCA_GET(adapter->revision_id, outbox, QUERY_ADAPTER_REVISION_ID_OFFSET); MTHCA_GET(adapter->revision_id, outbox, QUERY_ADAPTER_REVISION_ID_OFFSET);
MTHCA_GET(adapter->inta_pin, outbox, QUERY_ADAPTER_INTA_PIN_OFFSET); MTHCA_GET(adapter->inta_pin, outbox, QUERY_ADAPTER_INTA_PIN_OFFSET);
get_board_id(outbox + QUERY_ADAPTER_VSD_OFFSET / 4,
adapter->board_id);
out: out:
mthca_free_mailbox(dev, mailbox); mthca_free_mailbox(dev, mailbox);
return err; return err;
......
...@@ -184,10 +184,11 @@ struct mthca_dev_lim { ...@@ -184,10 +184,11 @@ struct mthca_dev_lim {
}; };
struct mthca_adapter { struct mthca_adapter {
u32 vendor_id; u32 vendor_id;
u32 device_id; u32 device_id;
u32 revision_id; u32 revision_id;
u8 inta_pin; char board_id[MTHCA_BOARD_ID_LEN];
u8 inta_pin;
}; };
struct mthca_init_hca_param { struct mthca_init_hca_param {
......
...@@ -68,6 +68,10 @@ enum { ...@@ -68,6 +68,10 @@ enum {
MTHCA_MAX_PORTS = 2 MTHCA_MAX_PORTS = 2
}; };
enum {
MTHCA_BOARD_ID_LEN = 64
};
enum { enum {
MTHCA_EQ_CONTEXT_SIZE = 0x40, MTHCA_EQ_CONTEXT_SIZE = 0x40,
MTHCA_CQ_CONTEXT_SIZE = 0x40, MTHCA_CQ_CONTEXT_SIZE = 0x40,
...@@ -248,6 +252,7 @@ struct mthca_dev { ...@@ -248,6 +252,7 @@ struct mthca_dev {
unsigned long device_cap_flags; unsigned long device_cap_flags;
u32 rev_id; u32 rev_id;
char board_id[MTHCA_BOARD_ID_LEN];
/* firmware info */ /* firmware info */
u64 fw_ver; u64 fw_ver;
......
...@@ -213,7 +213,6 @@ static int __devinit mthca_init_tavor(struct mthca_dev *mdev) ...@@ -213,7 +213,6 @@ static int __devinit mthca_init_tavor(struct mthca_dev *mdev)
struct mthca_dev_lim dev_lim; struct mthca_dev_lim dev_lim;
struct mthca_profile profile; struct mthca_profile profile;
struct mthca_init_hca_param init_hca; struct mthca_init_hca_param init_hca;
struct mthca_adapter adapter;
err = mthca_SYS_EN(mdev, &status); err = mthca_SYS_EN(mdev, &status);
if (err) { if (err) {
...@@ -271,26 +270,8 @@ static int __devinit mthca_init_tavor(struct mthca_dev *mdev) ...@@ -271,26 +270,8 @@ static int __devinit mthca_init_tavor(struct mthca_dev *mdev)
goto err_disable; goto err_disable;
} }
err = mthca_QUERY_ADAPTER(mdev, &adapter, &status);
if (err) {
mthca_err(mdev, "QUERY_ADAPTER command failed, aborting.\n");
goto err_close;
}
if (status) {
mthca_err(mdev, "QUERY_ADAPTER returned status 0x%02x, "
"aborting.\n", status);
err = -EINVAL;
goto err_close;
}
mdev->eq_table.inta_pin = adapter.inta_pin;
mdev->rev_id = adapter.revision_id;
return 0; return 0;
err_close:
mthca_CLOSE_HCA(mdev, 0, &status);
err_disable: err_disable:
mthca_SYS_DIS(mdev, &status); mthca_SYS_DIS(mdev, &status);
...@@ -507,7 +488,6 @@ static int __devinit mthca_init_arbel(struct mthca_dev *mdev) ...@@ -507,7 +488,6 @@ static int __devinit mthca_init_arbel(struct mthca_dev *mdev)
struct mthca_dev_lim dev_lim; struct mthca_dev_lim dev_lim;
struct mthca_profile profile; struct mthca_profile profile;
struct mthca_init_hca_param init_hca; struct mthca_init_hca_param init_hca;
struct mthca_adapter adapter;
u64 icm_size; u64 icm_size;
u8 status; u8 status;
int err; int err;
...@@ -575,21 +555,6 @@ static int __devinit mthca_init_arbel(struct mthca_dev *mdev) ...@@ -575,21 +555,6 @@ static int __devinit mthca_init_arbel(struct mthca_dev *mdev)
goto err_free_icm; goto err_free_icm;
} }
err = mthca_QUERY_ADAPTER(mdev, &adapter, &status);
if (err) {
mthca_err(mdev, "QUERY_ADAPTER command failed, aborting.\n");
goto err_free_icm;
}
if (status) {
mthca_err(mdev, "QUERY_ADAPTER returned status 0x%02x, "
"aborting.\n", status);
err = -EINVAL;
goto err_free_icm;
}
mdev->eq_table.inta_pin = adapter.inta_pin;
mdev->rev_id = adapter.revision_id;
return 0; return 0;
err_free_icm: err_free_icm:
...@@ -615,12 +580,68 @@ static int __devinit mthca_init_arbel(struct mthca_dev *mdev) ...@@ -615,12 +580,68 @@ static int __devinit mthca_init_arbel(struct mthca_dev *mdev)
return err; return err;
} }
static void mthca_close_hca(struct mthca_dev *mdev)
{
u8 status;
mthca_CLOSE_HCA(mdev, 0, &status);
if (mthca_is_memfree(mdev)) {
mthca_free_icm_table(mdev, mdev->cq_table.table);
mthca_free_icm_table(mdev, mdev->qp_table.rdb_table);
mthca_free_icm_table(mdev, mdev->qp_table.eqp_table);
mthca_free_icm_table(mdev, mdev->qp_table.qp_table);
mthca_free_icm_table(mdev, mdev->mr_table.mpt_table);
mthca_free_icm_table(mdev, mdev->mr_table.mtt_table);
mthca_unmap_eq_icm(mdev);
mthca_UNMAP_ICM_AUX(mdev, &status);
mthca_free_icm(mdev, mdev->fw.arbel.aux_icm);
mthca_UNMAP_FA(mdev, &status);
mthca_free_icm(mdev, mdev->fw.arbel.fw_icm);
if (!(mdev->mthca_flags & MTHCA_FLAG_NO_LAM))
mthca_DISABLE_LAM(mdev, &status);
} else
mthca_SYS_DIS(mdev, &status);
}
static int __devinit mthca_init_hca(struct mthca_dev *mdev) static int __devinit mthca_init_hca(struct mthca_dev *mdev)
{ {
u8 status;
int err;
struct mthca_adapter adapter;
if (mthca_is_memfree(mdev)) if (mthca_is_memfree(mdev))
return mthca_init_arbel(mdev); err = mthca_init_arbel(mdev);
else else
return mthca_init_tavor(mdev); err = mthca_init_tavor(mdev);
if (err)
return err;
err = mthca_QUERY_ADAPTER(mdev, &adapter, &status);
if (err) {
mthca_err(mdev, "QUERY_ADAPTER command failed, aborting.\n");
goto err_close;
}
if (status) {
mthca_err(mdev, "QUERY_ADAPTER returned status 0x%02x, "
"aborting.\n", status);
err = -EINVAL;
goto err_close;
}
mdev->eq_table.inta_pin = adapter.inta_pin;
mdev->rev_id = adapter.revision_id;
memcpy(mdev->board_id, adapter.board_id, sizeof mdev->board_id);
return 0;
err_close:
mthca_close_hca(mdev);
return err;
} }
static int __devinit mthca_setup_hca(struct mthca_dev *dev) static int __devinit mthca_setup_hca(struct mthca_dev *dev)
...@@ -845,33 +866,6 @@ static int __devinit mthca_enable_msi_x(struct mthca_dev *mdev) ...@@ -845,33 +866,6 @@ static int __devinit mthca_enable_msi_x(struct mthca_dev *mdev)
return 0; return 0;
} }
static void mthca_close_hca(struct mthca_dev *mdev)
{
u8 status;
mthca_CLOSE_HCA(mdev, 0, &status);
if (mthca_is_memfree(mdev)) {
mthca_free_icm_table(mdev, mdev->cq_table.table);
mthca_free_icm_table(mdev, mdev->qp_table.rdb_table);
mthca_free_icm_table(mdev, mdev->qp_table.eqp_table);
mthca_free_icm_table(mdev, mdev->qp_table.qp_table);
mthca_free_icm_table(mdev, mdev->mr_table.mpt_table);
mthca_free_icm_table(mdev, mdev->mr_table.mtt_table);
mthca_unmap_eq_icm(mdev);
mthca_UNMAP_ICM_AUX(mdev, &status);
mthca_free_icm(mdev, mdev->fw.arbel.aux_icm);
mthca_UNMAP_FA(mdev, &status);
mthca_free_icm(mdev, mdev->fw.arbel.fw_icm);
if (!(mdev->mthca_flags & MTHCA_FLAG_NO_LAM))
mthca_DISABLE_LAM(mdev, &status);
} else
mthca_SYS_DIS(mdev, &status);
}
/* Types of supported HCA */ /* Types of supported HCA */
enum { enum {
TAVOR, /* MT23108 */ TAVOR, /* MT23108 */
......
...@@ -958,14 +958,22 @@ static ssize_t show_hca(struct class_device *cdev, char *buf) ...@@ -958,14 +958,22 @@ static ssize_t show_hca(struct class_device *cdev, char *buf)
} }
} }
static ssize_t show_board(struct class_device *cdev, char *buf)
{
struct mthca_dev *dev = container_of(cdev, struct mthca_dev, ib_dev.class_dev);
return sprintf(buf, "%.*s\n", MTHCA_BOARD_ID_LEN, dev->board_id);
}
static CLASS_DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL); static CLASS_DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
static CLASS_DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL); static CLASS_DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
static CLASS_DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL); static CLASS_DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
static CLASS_DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL);
static struct class_device_attribute *mthca_class_attributes[] = { static struct class_device_attribute *mthca_class_attributes[] = {
&class_device_attr_hw_rev, &class_device_attr_hw_rev,
&class_device_attr_fw_ver, &class_device_attr_fw_ver,
&class_device_attr_hca_type &class_device_attr_hca_type,
&class_device_attr_board_id
}; };
int mthca_register_device(struct mthca_dev *dev) int mthca_register_device(struct mthca_dev *dev)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment