Skip to content

Commit 3029a69

Browse files
mellanoxbmcdavem330
authored andcommitted
mlxsw: i2c: Allow flexible setting of I2C transactions size
Current implementation uses fixed size of I2C data transaction buffer. Allow to set size of I2C transactions according to I2C physical adapter capability. For that purpose adapter read and write size is obtained from the I2C physical adapter and buffer size is set according to the minimum of these two values. If adapter does not provide such info, default buffer size is to be used. It allows to improve performance of I2C access to silicon when long size transactions are used. Signed-off-by: Vadim Pasternak <vadimp@mellanox.com> Acked-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: Ido Schimmel <idosch@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 9bbd7ef commit 3029a69

File tree

1 file changed

+46
-18
lines changed
  • drivers/net/ethernet/mellanox/mlxsw

1 file changed

+46
-18
lines changed

drivers/net/ethernet/mellanox/mlxsw/i2c.c

Lines changed: 46 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,10 @@
4343
#define MLXSW_I2C_PREP_SIZE (MLXSW_I2C_ADDR_WIDTH + 28)
4444
#define MLXSW_I2C_MBOX_SIZE 20
4545
#define MLXSW_I2C_MBOX_OUT_PARAM_OFF 12
46-
#define MLXSW_I2C_MAX_BUFF_SIZE 32
4746
#define MLXSW_I2C_MBOX_OFFSET_BITS 20
4847
#define MLXSW_I2C_MBOX_SIZE_BITS 12
4948
#define MLXSW_I2C_ADDR_BUF_SIZE 4
50-
#define MLXSW_I2C_BLK_MAX 32
49+
#define MLXSW_I2C_BLK_DEF 32
5150
#define MLXSW_I2C_RETRY 5
5251
#define MLXSW_I2C_TIMEOUT_MSECS 5000
5352
#define MLXSW_I2C_MAX_DATA_SIZE 256
@@ -62,6 +61,7 @@
6261
* @dev: I2C device;
6362
* @core: switch core pointer;
6463
* @bus_info: bus info block;
64+
* @block_size: maximum block size allowed to pass to under layer;
6565
*/
6666
struct mlxsw_i2c {
6767
struct {
@@ -74,6 +74,7 @@ struct mlxsw_i2c {
7474
struct device *dev;
7575
struct mlxsw_core *core;
7676
struct mlxsw_bus_info bus_info;
77+
u16 block_size;
7778
};
7879

7980
#define MLXSW_I2C_READ_MSG(_client, _addr_buf, _buf, _len) { \
@@ -315,20 +316,26 @@ mlxsw_i2c_write(struct device *dev, size_t in_mbox_size, u8 *in_mbox, int num,
315316
struct i2c_client *client = to_i2c_client(dev);
316317
struct mlxsw_i2c *mlxsw_i2c = i2c_get_clientdata(client);
317318
unsigned long timeout = msecs_to_jiffies(MLXSW_I2C_TIMEOUT_MSECS);
318-
u8 tran_buf[MLXSW_I2C_MAX_BUFF_SIZE + MLXSW_I2C_ADDR_BUF_SIZE];
319319
int off = mlxsw_i2c->cmd.mb_off_in, chunk_size, i, j;
320320
unsigned long end;
321+
u8 *tran_buf;
321322
struct i2c_msg write_tran =
322-
MLXSW_I2C_WRITE_MSG(client, tran_buf, MLXSW_I2C_PUSH_CMD_SIZE);
323+
MLXSW_I2C_WRITE_MSG(client, NULL, MLXSW_I2C_PUSH_CMD_SIZE);
323324
int err;
324325

326+
tran_buf = kmalloc(mlxsw_i2c->block_size + MLXSW_I2C_ADDR_BUF_SIZE,
327+
GFP_KERNEL);
328+
if (!tran_buf)
329+
return -ENOMEM;
330+
331+
write_tran.buf = tran_buf;
325332
for (i = 0; i < num; i++) {
326-
chunk_size = (in_mbox_size > MLXSW_I2C_BLK_MAX) ?
327-
MLXSW_I2C_BLK_MAX : in_mbox_size;
333+
chunk_size = (in_mbox_size > mlxsw_i2c->block_size) ?
334+
mlxsw_i2c->block_size : in_mbox_size;
328335
write_tran.len = MLXSW_I2C_ADDR_WIDTH + chunk_size;
329336
mlxsw_i2c_set_slave_addr(tran_buf, off);
330337
memcpy(&tran_buf[MLXSW_I2C_ADDR_BUF_SIZE], in_mbox +
331-
MLXSW_I2C_BLK_MAX * i, chunk_size);
338+
mlxsw_i2c->block_size * i, chunk_size);
332339

333340
j = 0;
334341
end = jiffies + timeout;
@@ -342,9 +349,10 @@ mlxsw_i2c_write(struct device *dev, size_t in_mbox_size, u8 *in_mbox, int num,
342349
(j++ < MLXSW_I2C_RETRY));
343350

344351
if (err != 1) {
345-
if (!err)
352+
if (!err) {
346353
err = -EIO;
347-
return err;
354+
goto mlxsw_i2c_write_exit;
355+
}
348356
}
349357

350358
off += chunk_size;
@@ -355,24 +363,27 @@ mlxsw_i2c_write(struct device *dev, size_t in_mbox_size, u8 *in_mbox, int num,
355363
err = mlxsw_i2c_write_cmd(client, mlxsw_i2c, 0);
356364
if (err) {
357365
dev_err(&client->dev, "Could not start transaction");
358-
return -EIO;
366+
err = -EIO;
367+
goto mlxsw_i2c_write_exit;
359368
}
360369

361370
/* Wait until go bit is cleared. */
362371
err = mlxsw_i2c_wait_go_bit(client, mlxsw_i2c, p_status);
363372
if (err) {
364373
dev_err(&client->dev, "HW semaphore is not released");
365-
return err;
374+
goto mlxsw_i2c_write_exit;
366375
}
367376

368377
/* Validate transaction completion status. */
369378
if (*p_status) {
370379
dev_err(&client->dev, "Bad transaction completion status %x\n",
371380
*p_status);
372-
return -EIO;
381+
err = -EIO;
373382
}
374383

375-
return 0;
384+
mlxsw_i2c_write_exit:
385+
kfree(tran_buf);
386+
return err;
376387
}
377388

378389
/* Routine executes I2C command. */
@@ -395,8 +406,8 @@ mlxsw_i2c_cmd(struct device *dev, u16 opcode, u32 in_mod, size_t in_mbox_size,
395406

396407
if (in_mbox) {
397408
reg_size = mlxsw_i2c_get_reg_size(in_mbox);
398-
num = reg_size / MLXSW_I2C_BLK_MAX;
399-
if (reg_size % MLXSW_I2C_BLK_MAX)
409+
num = reg_size / mlxsw_i2c->block_size;
410+
if (reg_size % mlxsw_i2c->block_size)
400411
num++;
401412

402413
if (mutex_lock_interruptible(&mlxsw_i2c->cmd.lock) < 0) {
@@ -416,7 +427,7 @@ mlxsw_i2c_cmd(struct device *dev, u16 opcode, u32 in_mod, size_t in_mbox_size,
416427
} else {
417428
/* No input mailbox is case of initialization query command. */
418429
reg_size = MLXSW_I2C_MAX_DATA_SIZE;
419-
num = reg_size / MLXSW_I2C_BLK_MAX;
430+
num = reg_size / mlxsw_i2c->block_size;
420431

421432
if (mutex_lock_interruptible(&mlxsw_i2c->cmd.lock) < 0) {
422433
dev_err(&client->dev, "Could not acquire lock");
@@ -432,8 +443,8 @@ mlxsw_i2c_cmd(struct device *dev, u16 opcode, u32 in_mod, size_t in_mbox_size,
432443
/* Send read transaction to get output mailbox content. */
433444
read_tran[1].buf = out_mbox;
434445
for (i = 0; i < num; i++) {
435-
chunk_size = (reg_size > MLXSW_I2C_BLK_MAX) ?
436-
MLXSW_I2C_BLK_MAX : reg_size;
446+
chunk_size = (reg_size > mlxsw_i2c->block_size) ?
447+
mlxsw_i2c->block_size : reg_size;
437448
read_tran[1].len = chunk_size;
438449
mlxsw_i2c_set_slave_addr(tran_buf, off);
439450

@@ -546,6 +557,7 @@ static const struct mlxsw_bus mlxsw_i2c_bus = {
546557
static int mlxsw_i2c_probe(struct i2c_client *client,
547558
const struct i2c_device_id *id)
548559
{
560+
const struct i2c_adapter_quirks *quirks = client->adapter->quirks;
549561
struct mlxsw_i2c *mlxsw_i2c;
550562
u8 status;
551563
int err;
@@ -554,6 +566,22 @@ static int mlxsw_i2c_probe(struct i2c_client *client,
554566
if (!mlxsw_i2c)
555567
return -ENOMEM;
556568

569+
if (quirks) {
570+
if ((quirks->max_read_len &&
571+
quirks->max_read_len < MLXSW_I2C_BLK_DEF) ||
572+
(quirks->max_write_len &&
573+
quirks->max_write_len < MLXSW_I2C_BLK_DEF)) {
574+
dev_err(&client->dev, "Insufficient transaction buffer length\n");
575+
return -EOPNOTSUPP;
576+
}
577+
578+
mlxsw_i2c->block_size = max_t(u16, MLXSW_I2C_BLK_DEF,
579+
min_t(u16, quirks->max_read_len,
580+
quirks->max_write_len));
581+
} else {
582+
mlxsw_i2c->block_size = MLXSW_I2C_BLK_DEF;
583+
}
584+
557585
i2c_set_clientdata(client, mlxsw_i2c);
558586
mutex_init(&mlxsw_i2c->cmd.lock);
559587

0 commit comments

Comments
 (0)