--- linux-4.3.0-rc5/drivers/gpu/drm/drm_dp_mst_topology.c.old 2015-10-15 00:52:13.293418345 -0700 +++ linux-4.3.0-rc5/drivers/gpu/drm/drm_dp_mst_topology.c 2015-10-15 00:53:32.145852512 -0700 @@ -2780,48 +2780,55 @@ void drm_dp_mst_topology_mgr_destroy(str EXPORT_SYMBOL(drm_dp_mst_topology_mgr_destroy); /* I2C device */ -static int drm_dp_mst_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, +static int drm_dp_mst_i2c_xfer(struct i2c_adapter *adapter, + struct i2c_msg *msgs, int num) { struct drm_dp_aux *aux = adapter->algo_data; - struct drm_dp_mst_port *port = container_of(aux, struct drm_dp_mst_port, aux); + struct drm_dp_mst_port *port = + container_of(aux, struct drm_dp_mst_port, aux); struct drm_dp_mst_branch *mstb; struct drm_dp_mst_topology_mgr *mgr = port->mgr; unsigned int i; - bool reading = false; struct drm_dp_sideband_msg_req_body msg; - struct drm_dp_sideband_msg_tx *txmsg = NULL; + struct drm_dp_sideband_msg_tx *txmsg; int ret; + int count; - mstb = drm_dp_get_validated_mstb_ref(mgr, port->parent); - if (!mstb) - return -EREMOTEIO; + if (unlikely(num <= 0)) { + DRM_DEBUG_KMS("Too few DP-MST I2C transactions (%d).\n", num); + return -EDOM; + } - /* construct i2c msg */ - /* see if last msg is a read */ - if (msgs[num - 1].flags & I2C_M_RD) - reading = true; - - if (!reading || (num - 1 > DP_REMOTE_I2C_READ_MAX_TRANSACTIONS)) { - DRM_DEBUG_KMS("Unsupported I2C transaction for MST device\n"); - ret = -EIO; - goto out; + if (unlikely(num > DP_REMOTE_I2C_READ_MAX_TRANSACTIONS + 1)) { + DRM_DEBUG_KMS("Too many DP-MST I2C transactions (%d).\n", num); + return -E2BIG; } + count = num - 1; + if (!likely(msgs[count].flags & I2C_M_RD)) { + DRM_DEBUG_KMS("Final DP-MST I2C transaction was not a read.\n"); + return -EINVAL; + } + + mstb = drm_dp_get_validated_mstb_ref(mgr, port->parent); + if (unlikely(!mstb)) + return -EREMOTEIO; + memset(&msg, 0, sizeof(msg)); msg.req_type = DP_REMOTE_I2C_READ; - msg.u.i2c_read.num_transactions = num - 1; + msg.u.i2c_read.num_transactions = count; msg.u.i2c_read.port_number = port->port_num; - for (i = 0; i < num - 1; i++) { + for (i = 0; i < count; i++) { msg.u.i2c_read.transactions[i].i2c_dev_id = msgs[i].addr; msg.u.i2c_read.transactions[i].num_bytes = msgs[i].len; msg.u.i2c_read.transactions[i].bytes = msgs[i].buf; } - msg.u.i2c_read.read_i2c_device_id = msgs[num - 1].addr; - msg.u.i2c_read.num_bytes_read = msgs[num - 1].len; + msg.u.i2c_read.read_i2c_device_id = msgs[count].addr; + msg.u.i2c_read.num_bytes_read = msgs[count].len; txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL); - if (!txmsg) { + if (unlikely(!txmsg)) { ret = -ENOMEM; goto out; } @@ -2838,11 +2845,11 @@ static int drm_dp_mst_i2c_xfer(struct i2 ret = -EREMOTEIO; goto out; } - if (txmsg->reply.u.remote_i2c_read_ack.num_bytes != msgs[num - 1].len) { + if (txmsg->reply.u.remote_i2c_read_ack.num_bytes != msgs[count].len) { ret = -EIO; goto out; } - memcpy(msgs[num - 1].buf, txmsg->reply.u.remote_i2c_read_ack.bytes, msgs[num - 1].len); + memcpy(msgs[count].buf, txmsg->reply.u.remote_i2c_read_ack.bytes, msgs[count].len); ret = num; } out: