Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/radeon: add a i2c bus mutex

The i2c and aux buses use the same pads so add
a mutex to protect access to the pads.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Christian König <christian.koenig@amd.com>

authored by

Alex Deucher and committed by
Alex Deucher
831719d6 182407a6

+37 -8
+14 -4
drivers/gpu/drm/radeon/atombios_dp.c
··· 95 95 int index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction); 96 96 unsigned char *base; 97 97 int recv_bytes; 98 + int r = 0; 98 99 99 100 memset(&args, 0, sizeof(args)); 101 + 102 + mutex_lock(&chan->mutex); 100 103 101 104 base = (unsigned char *)(rdev->mode_info.atom_context->scratch + 1); 102 105 ··· 120 117 /* timeout */ 121 118 if (args.v1.ucReplyStatus == 1) { 122 119 DRM_DEBUG_KMS("dp_aux_ch timeout\n"); 123 - return -ETIMEDOUT; 120 + r = -ETIMEDOUT; 121 + goto done; 124 122 } 125 123 126 124 /* flags not zero */ 127 125 if (args.v1.ucReplyStatus == 2) { 128 126 DRM_DEBUG_KMS("dp_aux_ch flags not zero\n"); 129 - return -EBUSY; 127 + r = -EBUSY; 128 + goto done; 130 129 } 131 130 132 131 /* error */ 133 132 if (args.v1.ucReplyStatus == 3) { 134 133 DRM_DEBUG_KMS("dp_aux_ch error\n"); 135 - return -EIO; 134 + r = -EIO; 135 + goto done; 136 136 } 137 137 138 138 recv_bytes = args.v1.ucDataOutLen; ··· 145 139 if (recv && recv_size) 146 140 radeon_atom_copy_swap(recv, base + 16, recv_bytes, false); 147 141 148 - return recv_bytes; 142 + r = recv_bytes; 143 + done: 144 + mutex_unlock(&chan->mutex); 145 + 146 + return r; 149 147 } 150 148 151 149 #define BARE_ADDRESS_SIZE 3
+13 -4
drivers/gpu/drm/radeon/atombios_i2c.c
··· 43 43 int index = GetIndexIntoMasterTable(COMMAND, ProcessI2cChannelTransaction); 44 44 unsigned char *base; 45 45 u16 out = cpu_to_le16(0); 46 + int r = 0; 46 47 47 48 memset(&args, 0, sizeof(args)); 49 + 50 + mutex_lock(&chan->mutex); 48 51 49 52 base = (unsigned char *)rdev->mode_info.atom_context->scratch; 50 53 51 54 if (flags & HW_I2C_WRITE) { 52 55 if (num > ATOM_MAX_HW_I2C_WRITE) { 53 56 DRM_ERROR("hw i2c: tried to write too many bytes (%d vs 3)\n", num); 54 - return -EINVAL; 57 + r = -EINVAL; 58 + goto done; 55 59 } 56 60 if (buf == NULL) 57 61 args.ucRegIndex = 0; ··· 69 65 } else { 70 66 if (num > ATOM_MAX_HW_I2C_READ) { 71 67 DRM_ERROR("hw i2c: tried to read too many bytes (%d vs 255)\n", num); 72 - return -EINVAL; 68 + r = -EINVAL; 69 + goto done; 73 70 } 74 71 args.ucRegIndex = 0; 75 72 args.lpI2CDataOut = 0; ··· 87 82 /* error */ 88 83 if (args.ucStatus != HW_ASSISTED_I2C_STATUS_SUCCESS) { 89 84 DRM_DEBUG_KMS("hw_i2c error\n"); 90 - return -EIO; 85 + r = -EIO; 86 + goto done; 91 87 } 92 88 93 89 if (!(flags & HW_I2C_WRITE)) 94 90 radeon_atom_copy_swap(buf, base, num, false); 95 91 96 - return 0; 92 + done: 93 + mutex_unlock(&chan->mutex); 94 + 95 + return r; 97 96 } 98 97 99 98 int radeon_atom_hw_i2c_xfer(struct i2c_adapter *i2c_adap,
+9
drivers/gpu/drm/radeon/radeon_i2c.c
··· 94 94 struct radeon_i2c_bus_rec *rec = &i2c->rec; 95 95 uint32_t temp; 96 96 97 + mutex_lock(&i2c->mutex); 98 + 97 99 /* RV410 appears to have a bug where the hw i2c in reset 98 100 * holds the i2c port in a bad state - switch hw i2c away before 99 101 * doing DDC - do this for all r200s/r300s/r400s for safety sake ··· 172 170 temp = RREG32(rec->mask_data_reg) & ~rec->mask_data_mask; 173 171 WREG32(rec->mask_data_reg, temp); 174 172 temp = RREG32(rec->mask_data_reg); 173 + 174 + mutex_unlock(&i2c->mutex); 175 175 } 176 176 177 177 static int get_clock(void *i2c_priv) ··· 817 813 struct radeon_i2c_bus_rec *rec = &i2c->rec; 818 814 int ret = 0; 819 815 816 + mutex_lock(&i2c->mutex); 817 + 820 818 switch (rdev->family) { 821 819 case CHIP_R100: 822 820 case CHIP_RV100: ··· 885 879 break; 886 880 } 887 881 882 + mutex_unlock(&i2c->mutex); 883 + 888 884 return ret; 889 885 } 890 886 ··· 927 919 i2c->adapter.dev.parent = &dev->pdev->dev; 928 920 i2c->dev = dev; 929 921 i2c_set_adapdata(&i2c->adapter, i2c); 922 + mutex_init(&i2c->mutex); 930 923 if (rec->mm_i2c || 931 924 (rec->hw_capable && 932 925 radeon_hw_i2c &&
+1
drivers/gpu/drm/radeon/radeon_mode.h
··· 191 191 struct radeon_i2c_bus_rec rec; 192 192 struct drm_dp_aux aux; 193 193 bool has_aux; 194 + struct mutex mutex; 194 195 }; 195 196 196 197 /* mostly for macs, but really any system without connector tables */