Skip to content

Commit

Permalink
Merge pull request #9 from paulc11/master
Browse files Browse the repository at this point in the history
Added support for bind/unbind sx_core
  • Loading branch information
dvirl1 authored Apr 6, 2017
2 parents 880b863 + ff108a1 commit 72eb1fe
Showing 1 changed file with 101 additions and 57 deletions.
158 changes: 101 additions & 57 deletions mlnx-asic-drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,10 @@ static unsigned short port_led_control = 0;
module_param(port_led_control, ushort, 0);
MODULE_PARM_DESC(port_led_control, "Port led control is enable, default is no");

static ssize_t store_bind_sx_core(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t len);
static struct kobj_attribute bind_sx_core_attr = __ATTR(bind_sx_core, S_IWUSR, NULL, store_bind_sx_core);
static struct switchdev_if *g_switchdev_if = NULL;

int mlxsw_local_port_mapping[] = {
0x2d, 0x2f, 0x2a, 0x2b, 0x26, 0x28, 0x23, 0x25, 0x01, 0x21, 0x05, 0x03,
0x08, 0x06, 0x0b, 0x0a, 0x0f, 0x0d, 0x1d, 0x1f, 0x19, 0x1b, 0x15, 0x17,
Expand All @@ -366,8 +370,12 @@ int mlxsw_local_port_mapping[] = {
reg_data.op_tlv.tid = 0; \
reg_data.dev_id = devif->dev_id;

#define REG_ACCESS(devif, REGID, reg_data, err) \
#define REG_ACCESS(devif, REGID, reg_data, err, ret_on_null_ptr) \
mutex_lock(&devif->access_lock); \
if (!devif->REG_##REGID || !devif->DEV_CONTEXT) { \
mutex_unlock(&devif->access_lock); \
return ret_on_null_ptr; \
} \
err = devif->REG_##REGID((struct sx_dev *)devif->DEV_CONTEXT(), &reg_data); \
mutex_unlock(&devif->access_lock); \
if (err) \
Expand All @@ -377,6 +385,72 @@ int mlxsw_local_port_mapping[] = {
if (time_before(jiffies, entry.last_updated + refresh) && entry.valid) \
return 0;

#define GET_ONE_SX_CORE_FUNC(func_name) \
if (!(g_switchdev_if->func_name)) { \
g_switchdev_if->func_name = __symbol_get("sx_ACCESS_"#func_name); \
}

#define PUT_ONE_SX_CORE_FUNC(func_name) \
if (g_switchdev_if->func_name) { \
__symbol_put("sx_ACCESS_"#func_name); \
g_switchdev_if->func_name = NULL; \
}

static ssize_t store_bind_sx_core(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t len)
{
int ret;
int value;

ret = kstrtoint(buf, 10, &value);
if (ret) {
printk(KERN_INFO "sysfs entry bind_sx_core got invalid value\n");
return ret;
}

if (value) {
mutex_lock(&(g_switchdev_if->access_lock));
if (!g_switchdev_if->DEV_CONTEXT) {
g_switchdev_if->DEV_CONTEXT = __symbol_get("sx_get_dev_context");
}
GET_ONE_SX_CORE_FUNC(REG_MFSC);
GET_ONE_SX_CORE_FUNC(REG_MFSM);
GET_ONE_SX_CORE_FUNC(REG_MTMP);
GET_ONE_SX_CORE_FUNC(REG_MTCAP);
GET_ONE_SX_CORE_FUNC(REG_MCIA);
GET_ONE_SX_CORE_FUNC(REG_PMPC);
GET_ONE_SX_CORE_FUNC(REG_MSCI);
GET_ONE_SX_CORE_FUNC(REG_MJTAG);
GET_ONE_SX_CORE_FUNC(REG_PMAOS);
GET_ONE_SX_CORE_FUNC(REG_MFCR);
GET_ONE_SX_CORE_FUNC(REG_MGIR);
GET_ONE_SX_CORE_FUNC(REG_MLCR);
GET_ONE_SX_CORE_FUNC(REG_PMLP);
mutex_unlock(&(g_switchdev_if->access_lock));
} else {
mutex_lock(&(g_switchdev_if->access_lock));
if (g_switchdev_if->DEV_CONTEXT) {
__symbol_put("sx_get_dev_context");
g_switchdev_if->DEV_CONTEXT = NULL;
}
PUT_ONE_SX_CORE_FUNC(REG_MFSC);
PUT_ONE_SX_CORE_FUNC(REG_MFSM);
PUT_ONE_SX_CORE_FUNC(REG_MTMP);
PUT_ONE_SX_CORE_FUNC(REG_MTCAP);
PUT_ONE_SX_CORE_FUNC(REG_MCIA);
PUT_ONE_SX_CORE_FUNC(REG_PMPC);
PUT_ONE_SX_CORE_FUNC(REG_MSCI);
PUT_ONE_SX_CORE_FUNC(REG_MJTAG);
PUT_ONE_SX_CORE_FUNC(REG_PMAOS);
PUT_ONE_SX_CORE_FUNC(REG_MFCR);
PUT_ONE_SX_CORE_FUNC(REG_MGIR);
PUT_ONE_SX_CORE_FUNC(REG_MLCR);
PUT_ONE_SX_CORE_FUNC(REG_PMLP);
mutex_unlock(&(g_switchdev_if->access_lock));
}

return len;
}

static int fan_get_power(struct switchdev_if *devif, struct fan_config *fan, u8 cache_drop)
{
int err = 0;
Expand All @@ -386,14 +460,11 @@ static int fan_get_power(struct switchdev_if *devif, struct fan_config *fan, u8
if (!cache_drop)
ENTRY_DATA_VALID(fan->entry, ENTRY_DATA_VALID_TIME);

if (!devif->REG_MFSC || !devif->DEV_CONTEXT)
return err;

memset(&reg_data, 0, sizeof(struct ku_access_mfsc_reg));
SET_REG_TEMPLATE(reg_data, MFSC_REG_ID, method, devif);
reg_data.mfsc_reg.pwm = fan->pwm_id; /* Will affect all FANs */

REG_ACCESS(devif, MFSC, reg_data, err);
REG_ACCESS(devif, MFSC, reg_data, err, err);

fan->entry.last_updated = jiffies;
fan->entry.valid = 1;
Expand All @@ -408,15 +479,12 @@ static int fan_set_power(struct switchdev_if *devif, struct fan_config *fan)
u8 method = REG_WRITE;
struct ku_access_mfsc_reg reg_data;

if (!devif->REG_MFSC || !devif->DEV_CONTEXT)
return err;

memset(&reg_data, 0, sizeof(struct ku_access_mfsc_reg));
SET_REG_TEMPLATE(reg_data, MFSC_REG_ID, method, devif);
reg_data.mfsc_reg.pwm = fan->pwm_id; /* Will affect all FANs */
reg_data.mfsc_reg.pwm_duty_cycle = fan->pwm_duty_cycle;

REG_ACCESS(devif, MFSC, reg_data, err);
REG_ACCESS(devif, MFSC, reg_data, err, err);

return err;
}
Expand All @@ -429,14 +497,11 @@ static int fan_get_speed(struct switchdev_if *devif, struct fan_config *fan, cha

ENTRY_DATA_VALID(fan->entry, ENTRY_DATA_VALID_TIME);

if (!devif->REG_MFSM || !devif->DEV_CONTEXT)
return ENODEV;

memset(&reg_data, 0, sizeof(struct ku_access_mfsm_reg));
SET_REG_TEMPLATE(reg_data, MFSM_REG_ID, method, devif);
reg_data.mfsm_reg.tacho = fan->tacho_id[tacho_id];

REG_ACCESS(devif, MFSM, reg_data, err);
REG_ACCESS(devif, MFSM, reg_data, err, ENODEV);
fan->entry.last_updated = jiffies;
fan->entry.valid = 1;

Expand Down Expand Up @@ -502,13 +567,10 @@ static int fan_get_config(struct switchdev_if *devif, struct fan_config_params *

ENTRY_DATA_VALID(fan_config->entry, ENTRY_DATA_VALID_TIME);

if (!devif->REG_MFCR || !devif->DEV_CONTEXT)
return ENODEV;

memset(&reg_data, 0, sizeof(struct ku_access_mfcr_reg));
SET_REG_TEMPLATE(reg_data, MFCR_REG_ID, method, devif);

REG_ACCESS(devif, MFCR, reg_data, err);
REG_ACCESS(devif, MFCR, reg_data, err, ENODEV);
fan_config->entry.last_updated = jiffies;
fan_config->entry.valid = 1;

Expand All @@ -528,14 +590,11 @@ static int temp_get(struct switchdev_if *devif, struct temp_config *temp, u8 id,
if (!cache_drop)
ENTRY_DATA_VALID(temp->entry, ENTRY_DATA_VALID_TIME);

if (!devif->REG_MTMP || !devif->DEV_CONTEXT)
return ENODEV;

memset(&reg_data, 0, sizeof(struct ku_access_mtmp_reg));
SET_REG_TEMPLATE(reg_data, MTMP_REG_ID, method, devif);
reg_data.mtmp_reg.sensor_index = temp->sensor_index + id; /* Sensors index to access */

REG_ACCESS(devif, MTMP, reg_data, err);
REG_ACCESS(devif, MTMP, reg_data, err, ENODEV);
temp->entry.last_updated = jiffies;
temp->entry.valid = 1;
/* For temp->temperature < 0 consider to set:
Expand All @@ -556,13 +615,10 @@ static int temp_get_config(struct switchdev_if *devif, struct temp_config_params
u8 method = REG_QUERY;
struct ku_access_mtcap_reg reg_data;

if (!devif->REG_MTCAP || !devif->DEV_CONTEXT)
return ENODEV;

memset(&reg_data, 0, sizeof(struct ku_access_mtcap_reg));
SET_REG_TEMPLATE(reg_data, MTCAP_REG_ID, method, devif);

REG_ACCESS(devif, MTCAP, reg_data, err);
REG_ACCESS(devif, MTCAP, reg_data, err, ENODEV);

temp_config->sensor_active = reg_data.mtcap_reg.sensor_count;

Expand All @@ -577,17 +633,14 @@ static int qsfp_get(struct switchdev_if *devif, struct qsfp_config *qsfp)

ENTRY_DATA_VALID(qsfp->entry, ENTRY_DATA_VALID_TIME);

if (!devif->REG_MCIA || !devif->DEV_CONTEXT)
return ENODEV;

memset(&reg_data, 0, sizeof(struct ku_access_mcia_reg));
SET_REG_TEMPLATE(reg_data, MCIA_REG_ID, method, devif);
reg_data.mcia_reg.module = qsfp->module_index;
reg_data.mcia_reg.l = qsfp->lock;
reg_data.mcia_reg.page_number = 0;
reg_data.mcia_reg.size = QSFP_SUB_PAGE_SIZE;

REG_ACCESS(devif, MCIA, reg_data, err);
REG_ACCESS(devif, MCIA, reg_data, err, ENODEV);
qsfp->entry.last_updated = jiffies;
qsfp->entry.valid = 1;

Expand All @@ -608,9 +661,6 @@ static int qsfp_get_eeprom(struct switchdev_if *devif, struct qsfp_config *qsfp,
u16 page_shift[QSFP_PAGE_NUM + 1] = { 0x00, 0x80, 0x80, 0x80, 0x80, 0x00 };
u16 sub_page_size[QSFP_SUB_PAGE_NUM] = { QSFP_SUB_PAGE_SIZE, QSFP_SUB_PAGE_SIZE, QSFP_LAST_SUB_PAGE_SIZE};

if (!devif->REG_MCIA || !devif->DEV_CONTEXT)
return ENODEV;

memset(&reg_data, 0, sizeof(struct ku_access_mcia_reg));
SET_REG_TEMPLATE(reg_data, MCIA_REG_ID, method, devif);
reg_data.mcia_reg.i2c_device_address = qsfp_eeprom_i2c_addr;
Expand All @@ -633,7 +683,7 @@ static int qsfp_get_eeprom(struct switchdev_if *devif, struct qsfp_config *qsfp,
else
reg_data.mcia_reg.size = sub_page_size[j];

REG_ACCESS(devif, MCIA, reg_data, err);
REG_ACCESS(devif, MCIA, reg_data, err, ENODEV);

if (reg_data.mcia_reg.status)
return err;
Expand Down Expand Up @@ -668,13 +718,10 @@ static int qsfp_get_event(struct switchdev_if *devif, struct qsfp_config_params

ENTRY_DATA_VALID(qsfp_config->entry, ENTRY_DATA_VALID_TIME);

if (!devif->REG_PMPC || !devif->DEV_CONTEXT)
return ENODEV;

memset(&reg_data, 0, sizeof(struct ku_access_pmpc_reg));
SET_REG_TEMPLATE(reg_data, PMPC_REG_ID, method, devif);

REG_ACCESS(devif, PMPC, reg_data, err);
REG_ACCESS(devif, PMPC, reg_data, err, ENODEV);
qsfp_config->entry.last_updated = jiffies;
qsfp_config->entry.valid = 1;

Expand All @@ -690,16 +737,13 @@ static int qsfp_set_event(struct switchdev_if *devif, u32 *bitmap)
u8 method = REG_WRITE;
struct ku_access_pmpc_reg reg_data;

if (!devif->REG_PMPC || !devif->DEV_CONTEXT)
return ENODEV;

memset(&reg_data, 0, sizeof(struct ku_access_pmpc_reg));
SET_REG_TEMPLATE(reg_data, PMPC_REG_ID, method, devif);

memcpy(reg_data.pmpc_reg.module_state_updated_bitmap, bitmap,
sizeof(reg_data.pmpc_reg.module_state_updated_bitmap[0] * 8));

REG_ACCESS(devif, PMPC, reg_data, err);
REG_ACCESS(devif, PMPC, reg_data, err, ENODEV);

return err;
}
Expand All @@ -711,14 +755,11 @@ static int cpld_get(struct switchdev_if *devif, struct cpld_config *cpld)
u8 method = REG_QUERY;
struct ku_access_msci_reg reg_data;

if (!devif->REG_MSCI || !devif->DEV_CONTEXT)
return err;

memset(&reg_data, 0, sizeof(struct ku_access_msci_reg));
SET_REG_TEMPLATE(reg_data, MSCI_REG_ID, method, devif);
reg_data.msci_reg.index = cpld->index;

REG_ACCESS(devif, MSCI, reg_data, err);
REG_ACCESS(devif, MSCI, reg_data, err, err);
cpld->entry.last_updated = jiffies;
cpld->entry.valid = 1;

Expand All @@ -733,13 +774,10 @@ static int mgir_get(struct switchdev_if *devif, u16 *device_id)
u8 method = REG_QUERY;
struct ku_access_mgir_reg reg_data;

if (!devif->REG_MGIR || !devif->DEV_CONTEXT)
return err;

memset(&reg_data, 0, sizeof(struct ku_access_mgir_reg));
SET_REG_TEMPLATE(reg_data, MGIR_REG_ID, method, devif);

REG_ACCESS(devif, MGIR, reg_data, err);
REG_ACCESS(devif, MGIR, reg_data, err, err);

*device_id = reg_data.mgir_reg.hw_info.device_id;

Expand All @@ -752,14 +790,11 @@ static int pmlp_get(struct switchdev_if *devif, u8 local_port, u8 *width)
u8 method = REG_QUERY;
struct ku_access_pmlp_reg reg_data;

if (!devif->REG_PMLP || !devif->DEV_CONTEXT)
return err;

memset(&reg_data, 0, sizeof(struct ku_access_mgir_reg));
SET_REG_TEMPLATE(reg_data, PMLP_REG_ID, method, devif);
reg_data.pmlp_reg.local_port = local_port;

REG_ACCESS(devif, PMLP, reg_data, err);
REG_ACCESS(devif, PMLP, reg_data, err, err);

*width = reg_data.pmlp_reg.width;

Expand Down Expand Up @@ -1959,9 +1994,6 @@ static int _mlxsw_port_led_brightness(struct led_classdev *led,
struct ku_access_mlcr_reg reg_data;
int err = 0;

if (!devif->REG_MLCR || !devif->DEV_CONTEXT)
return err;

memset(&reg_data, 0, sizeof(struct ku_access_mlcr_reg));
SET_REG_TEMPLATE(reg_data, MLCR_REG_ID, method, devif);
mlcr_reg.led_type = pled->led_type;
Expand All @@ -1976,7 +2008,7 @@ static int _mlxsw_port_led_brightness(struct led_classdev *led,
else
mlcr_reg.beacon_duration = LED_OFF_COLOR;

REG_ACCESS(devif, MLCR, reg_data, err);
REG_ACCESS(devif, MLCR, reg_data, err, err);

return err;
}
Expand Down Expand Up @@ -2247,6 +2279,7 @@ static int asic_probe(struct i2c_client *client, const struct i2c_device_id *dev
err = -ENOMEM;
goto exit_no_memory;
}
g_switchdev_if = &(asicdata->switchdevif);
i2c_set_clientdata(client, asicdata);

INIT_LIST_HEAD(&asicdata->list);
Expand Down Expand Up @@ -2418,8 +2451,17 @@ static int asic_probe(struct i2c_client *client, const struct i2c_device_id *dev
goto exit_remove_thermal_bind;
}

err = sysfs_create_file(&(THIS_MODULE->mkobj.kobj), &(bind_sx_core_attr.attr));
if (err) {
goto exit_remove_port_led;
}

return 0;

exit_remove_port_led:
if (port_led_control)
port_led_remove(asicdata);

exit_remove_thermal_bind:
if (auto_thermal_control)
thermal_zone_unbind_cooling_device(asicdata->tzdev, 0, asicdata->tcdev);
Expand Down Expand Up @@ -2453,6 +2495,8 @@ static int asic_remove(struct i2c_client *client)
{
struct asic_data *asicdata = i2c_get_clientdata(client);

sysfs_remove_file(&(THIS_MODULE->mkobj.kobj), &(bind_sx_core_attr.attr));

if (port_led_control)
port_led_remove(asicdata);

Expand Down

0 comments on commit 72eb1fe

Please sign in to comment.