diff options
Diffstat (limited to 'drivers/net/usb/r815x.c')
| -rw-r--r-- | drivers/net/usb/r815x.c | 62 |
1 files changed, 42 insertions, 20 deletions
diff --git a/drivers/net/usb/r815x.c b/drivers/net/usb/r815x.c index 852392269718..2df2f4fb42a7 100644 --- a/drivers/net/usb/r815x.c +++ b/drivers/net/usb/r815x.c | |||
| @@ -24,34 +24,43 @@ | |||
| 24 | 24 | ||
| 25 | static int pla_read_word(struct usb_device *udev, u16 index) | 25 | static int pla_read_word(struct usb_device *udev, u16 index) |
| 26 | { | 26 | { |
| 27 | int data, ret; | 27 | int ret; |
| 28 | u8 shift = index & 2; | 28 | u8 shift = index & 2; |
| 29 | __le32 ocp_data; | 29 | __le32 *tmp; |
| 30 | |||
| 31 | tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); | ||
| 32 | if (!tmp) | ||
| 33 | return -ENOMEM; | ||
| 30 | 34 | ||
| 31 | index &= ~3; | 35 | index &= ~3; |
| 32 | 36 | ||
| 33 | ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | 37 | ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), |
| 34 | RTL815x_REQ_GET_REGS, RTL815x_REQT_READ, | 38 | RTL815x_REQ_GET_REGS, RTL815x_REQT_READ, |
| 35 | index, MCU_TYPE_PLA, &ocp_data, sizeof(ocp_data), | 39 | index, MCU_TYPE_PLA, tmp, sizeof(*tmp), 500); |
| 36 | 500); | ||
| 37 | if (ret < 0) | 40 | if (ret < 0) |
| 38 | return ret; | 41 | goto out2; |
| 39 | 42 | ||
| 40 | data = __le32_to_cpu(ocp_data); | 43 | ret = __le32_to_cpu(*tmp); |
| 41 | data >>= (shift * 8); | 44 | ret >>= (shift * 8); |
| 42 | data &= 0xffff; | 45 | ret &= 0xffff; |
| 43 | 46 | ||
| 44 | return data; | 47 | out2: |
| 48 | kfree(tmp); | ||
| 49 | return ret; | ||
| 45 | } | 50 | } |
| 46 | 51 | ||
| 47 | static int pla_write_word(struct usb_device *udev, u16 index, u32 data) | 52 | static int pla_write_word(struct usb_device *udev, u16 index, u32 data) |
| 48 | { | 53 | { |
| 49 | __le32 ocp_data; | 54 | __le32 *tmp; |
| 50 | u32 mask = 0xffff; | 55 | u32 mask = 0xffff; |
| 51 | u16 byen = BYTE_EN_WORD; | 56 | u16 byen = BYTE_EN_WORD; |
| 52 | u8 shift = index & 2; | 57 | u8 shift = index & 2; |
| 53 | int ret; | 58 | int ret; |
| 54 | 59 | ||
| 60 | tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); | ||
| 61 | if (!tmp) | ||
| 62 | return -ENOMEM; | ||
| 63 | |||
| 55 | data &= mask; | 64 | data &= mask; |
| 56 | 65 | ||
| 57 | if (shift) { | 66 | if (shift) { |
| @@ -63,19 +72,20 @@ static int pla_write_word(struct usb_device *udev, u16 index, u32 data) | |||
| 63 | 72 | ||
| 64 | ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | 73 | ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), |
| 65 | RTL815x_REQ_GET_REGS, RTL815x_REQT_READ, | 74 | RTL815x_REQ_GET_REGS, RTL815x_REQT_READ, |
| 66 | index, MCU_TYPE_PLA, &ocp_data, sizeof(ocp_data), | 75 | index, MCU_TYPE_PLA, tmp, sizeof(*tmp), 500); |
| 67 | 500); | ||
| 68 | if (ret < 0) | 76 | if (ret < 0) |
| 69 | return ret; | 77 | goto out3; |
| 70 | 78 | ||
| 71 | data |= __le32_to_cpu(ocp_data) & ~mask; | 79 | data |= __le32_to_cpu(*tmp) & ~mask; |
| 72 | ocp_data = __cpu_to_le32(data); | 80 | *tmp = __cpu_to_le32(data); |
| 73 | 81 | ||
| 74 | ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | 82 | ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), |
| 75 | RTL815x_REQ_SET_REGS, RTL815x_REQT_WRITE, | 83 | RTL815x_REQ_SET_REGS, RTL815x_REQT_WRITE, |
| 76 | index, MCU_TYPE_PLA | byen, &ocp_data, | 84 | index, MCU_TYPE_PLA | byen, tmp, sizeof(*tmp), |
| 77 | sizeof(ocp_data), 500); | 85 | 500); |
| 78 | 86 | ||
| 87 | out3: | ||
| 88 | kfree(tmp); | ||
| 79 | return ret; | 89 | return ret; |
| 80 | } | 90 | } |
| 81 | 91 | ||
| @@ -116,11 +126,18 @@ out1: | |||
| 116 | static int r815x_mdio_read(struct net_device *netdev, int phy_id, int reg) | 126 | static int r815x_mdio_read(struct net_device *netdev, int phy_id, int reg) |
| 117 | { | 127 | { |
| 118 | struct usbnet *dev = netdev_priv(netdev); | 128 | struct usbnet *dev = netdev_priv(netdev); |
| 129 | int ret; | ||
| 119 | 130 | ||
| 120 | if (phy_id != R815x_PHY_ID) | 131 | if (phy_id != R815x_PHY_ID) |
| 121 | return -EINVAL; | 132 | return -EINVAL; |
| 122 | 133 | ||
| 123 | return ocp_reg_read(dev, BASE_MII + reg * 2); | 134 | if (usb_autopm_get_interface(dev->intf) < 0) |
| 135 | return -ENODEV; | ||
| 136 | |||
| 137 | ret = ocp_reg_read(dev, BASE_MII + reg * 2); | ||
| 138 | |||
| 139 | usb_autopm_put_interface(dev->intf); | ||
| 140 | return ret; | ||
| 124 | } | 141 | } |
| 125 | 142 | ||
| 126 | static | 143 | static |
| @@ -131,7 +148,12 @@ void r815x_mdio_write(struct net_device *netdev, int phy_id, int reg, int val) | |||
| 131 | if (phy_id != R815x_PHY_ID) | 148 | if (phy_id != R815x_PHY_ID) |
| 132 | return; | 149 | return; |
| 133 | 150 | ||
| 151 | if (usb_autopm_get_interface(dev->intf) < 0) | ||
| 152 | return; | ||
| 153 | |||
| 134 | ocp_reg_write(dev, BASE_MII + reg * 2, val); | 154 | ocp_reg_write(dev, BASE_MII + reg * 2, val); |
| 155 | |||
| 156 | usb_autopm_put_interface(dev->intf); | ||
| 135 | } | 157 | } |
| 136 | 158 | ||
| 137 | static int r8153_bind(struct usbnet *dev, struct usb_interface *intf) | 159 | static int r8153_bind(struct usbnet *dev, struct usb_interface *intf) |
| @@ -150,7 +172,7 @@ static int r8153_bind(struct usbnet *dev, struct usb_interface *intf) | |||
| 150 | dev->mii.phy_id = R815x_PHY_ID; | 172 | dev->mii.phy_id = R815x_PHY_ID; |
| 151 | dev->mii.supports_gmii = 1; | 173 | dev->mii.supports_gmii = 1; |
| 152 | 174 | ||
| 153 | return 0; | 175 | return status; |
| 154 | } | 176 | } |
| 155 | 177 | ||
| 156 | static int r8152_bind(struct usbnet *dev, struct usb_interface *intf) | 178 | static int r8152_bind(struct usbnet *dev, struct usb_interface *intf) |
| @@ -169,7 +191,7 @@ static int r8152_bind(struct usbnet *dev, struct usb_interface *intf) | |||
| 169 | dev->mii.phy_id = R815x_PHY_ID; | 191 | dev->mii.phy_id = R815x_PHY_ID; |
| 170 | dev->mii.supports_gmii = 0; | 192 | dev->mii.supports_gmii = 0; |
| 171 | 193 | ||
| 172 | return 0; | 194 | return status; |
| 173 | } | 195 | } |
| 174 | 196 | ||
| 175 | static const struct driver_info r8152_info = { | 197 | static const struct driver_info r8152_info = { |
