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

Merge branch 'pegasus-errors'

Petko Manolov says:

====================
net: usb: pegasus: better error checking and DRIVER_VERSION removal

v3:

Pavel Skripkin again: make sure -ETIMEDOUT is returned by __mii_op() on timeout
condition;

v2:

Special thanks to Pavel Skripkin for the review and who caught a few bugs.
setup_pegasus_II() would not print an erroneous message on the success path.

v1:

Add error checking for get_registers() and derivatives. If the usb transfer
fail then just don't use the buffer where the legal data should have been
returned.

Remove DRIVER_VERSION per Greg KH request.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+77 -61
+77 -61
drivers/net/usb/pegasus.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 2 /* 3 - * Copyright (c) 1999-2013 Petko Manolov (petkan@nucleusys.com) 3 + * Copyright (c) 1999-2021 Petko Manolov (petkan@nucleusys.com) 4 4 * 5 - * ChangeLog: 6 - * .... Most of the time spent on reading sources & docs. 7 - * v0.2.x First official release for the Linux kernel. 8 - * v0.3.0 Beutified and structured, some bugs fixed. 9 - * v0.3.x URBifying bulk requests and bugfixing. First relatively 10 - * stable release. Still can touch device's registers only 11 - * from top-halves. 12 - * v0.4.0 Control messages remained unurbified are now URBs. 13 - * Now we can touch the HW at any time. 14 - * v0.4.9 Control urbs again use process context to wait. Argh... 15 - * Some long standing bugs (enable_net_traffic) fixed. 16 - * Also nasty trick about resubmiting control urb from 17 - * interrupt context used. Please let me know how it 18 - * behaves. Pegasus II support added since this version. 19 - * TODO: suppressing HCD warnings spewage on disconnect. 20 - * v0.4.13 Ethernet address is now set at probe(), not at open() 21 - * time as this seems to break dhcpd. 22 - * v0.5.0 branch to 2.5.x kernels 23 - * v0.5.1 ethtool support added 24 - * v0.5.5 rx socket buffers are in a pool and the their allocation 25 - * is out of the interrupt routine. 26 - * ... 27 - * v0.9.3 simplified [get|set]_register(s), async update registers 28 - * logic revisited, receive skb_pool removed. 29 5 */ 30 6 31 7 #include <linux/sched.h> ··· 21 45 /* 22 46 * Version Information 23 47 */ 24 - #define DRIVER_VERSION "v0.9.3 (2013/04/25)" 25 48 #define DRIVER_AUTHOR "Petko Manolov <petkan@nucleusys.com>" 26 49 #define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver" 27 50 ··· 107 132 static int set_registers(pegasus_t *pegasus, __u16 indx, __u16 size, 108 133 const void *data) 109 134 { 110 - return usb_control_msg_send(pegasus->usb, 0, PEGASUS_REQ_SET_REGS, 135 + int ret; 136 + 137 + ret = usb_control_msg_send(pegasus->usb, 0, PEGASUS_REQ_SET_REGS, 111 138 PEGASUS_REQT_WRITE, 0, indx, data, size, 112 139 1000, GFP_NOIO); 140 + if (ret < 0) 141 + netif_dbg(pegasus, drv, pegasus->net, "%s failed with %d\n", __func__, ret); 142 + 143 + return ret; 113 144 } 114 145 115 146 /* ··· 126 145 static int set_register(pegasus_t *pegasus, __u16 indx, __u8 data) 127 146 { 128 147 void *buf = &data; 148 + int ret; 129 149 130 - return usb_control_msg_send(pegasus->usb, 0, PEGASUS_REQ_SET_REG, 150 + ret = usb_control_msg_send(pegasus->usb, 0, PEGASUS_REQ_SET_REG, 131 151 PEGASUS_REQT_WRITE, data, indx, buf, 1, 132 152 1000, GFP_NOIO); 153 + if (ret < 0) 154 + netif_dbg(pegasus, drv, pegasus->net, "%s failed with %d\n", __func__, ret); 155 + 156 + return ret; 133 157 } 134 158 135 159 static int update_eth_regs_async(pegasus_t *pegasus) ··· 174 188 175 189 static int __mii_op(pegasus_t *p, __u8 phy, __u8 indx, __u16 *regd, __u8 cmd) 176 190 { 177 - int i; 178 - __u8 data[4] = { phy, 0, 0, indx }; 191 + int i, ret; 179 192 __le16 regdi; 180 - int ret = -ETIMEDOUT; 193 + __u8 data[4] = { phy, 0, 0, indx }; 181 194 182 195 if (cmd & PHY_WRITE) { 183 196 __le16 *t = (__le16 *) & data[1]; ··· 192 207 if (data[0] & PHY_DONE) 193 208 break; 194 209 } 195 - if (i >= REG_TIMEOUT) 210 + if (i >= REG_TIMEOUT) { 211 + ret = -ETIMEDOUT; 196 212 goto fail; 213 + } 197 214 if (cmd & PHY_READ) { 198 215 ret = get_registers(p, PhyData, 2, &regdi); 216 + if (ret < 0) 217 + goto fail; 199 218 *regd = le16_to_cpu(regdi); 200 - return ret; 201 219 } 202 220 return 0; 203 221 fail: ··· 223 235 static int mdio_read(struct net_device *dev, int phy_id, int loc) 224 236 { 225 237 pegasus_t *pegasus = netdev_priv(dev); 238 + int ret; 226 239 u16 res; 227 240 228 - read_mii_word(pegasus, phy_id, loc, &res); 241 + ret = read_mii_word(pegasus, phy_id, loc, &res); 242 + if (ret < 0) 243 + return ret; 244 + 229 245 return (int)res; 230 246 } 231 247 ··· 243 251 244 252 static int read_eprom_word(pegasus_t *pegasus, __u8 index, __u16 *retdata) 245 253 { 246 - int i; 247 - __u8 tmp = 0; 254 + int ret, i; 248 255 __le16 retdatai; 249 - int ret; 256 + __u8 tmp = 0; 250 257 251 258 set_register(pegasus, EpromCtrl, 0); 252 259 set_register(pegasus, EpromOffset, index); ··· 253 262 254 263 for (i = 0; i < REG_TIMEOUT; i++) { 255 264 ret = get_registers(pegasus, EpromCtrl, 1, &tmp); 265 + if (ret < 0) 266 + goto fail; 256 267 if (tmp & EPROM_DONE) 257 268 break; 258 - if (ret == -ESHUTDOWN) 259 - goto fail; 260 269 } 261 - if (i >= REG_TIMEOUT) 270 + if (i >= REG_TIMEOUT) { 271 + ret = -ETIMEDOUT; 262 272 goto fail; 273 + } 263 274 264 275 ret = get_registers(pegasus, EpromData, 2, &retdatai); 276 + if (ret < 0) 277 + goto fail; 265 278 *retdata = le16_to_cpu(retdatai); 266 279 return ret; 267 280 268 281 fail: 269 - netif_warn(pegasus, drv, pegasus->net, "%s failed\n", __func__); 270 - return -ETIMEDOUT; 282 + netif_dbg(pegasus, drv, pegasus->net, "%s failed\n", __func__); 283 + return ret; 271 284 } 272 285 273 286 #ifdef PEGASUS_WRITE_EEPROM ··· 319 324 return ret; 320 325 321 326 fail: 322 - netif_warn(pegasus, drv, pegasus->net, "%s failed\n", __func__); 327 + netif_dbg(pegasus, drv, pegasus->net, "%s failed\n", __func__); 323 328 return -ETIMEDOUT; 324 329 } 325 - #endif /* PEGASUS_WRITE_EEPROM */ 330 + #endif /* PEGASUS_WRITE_EEPROM */ 326 331 327 332 static inline int get_node_id(pegasus_t *pegasus, u8 *id) 328 333 { ··· 362 367 return; 363 368 err: 364 369 eth_hw_addr_random(pegasus->net); 365 - dev_info(&pegasus->intf->dev, "software assigned MAC address.\n"); 370 + netif_dbg(pegasus, drv, pegasus->net, "software assigned MAC address.\n"); 366 371 367 372 return; 368 373 } 369 374 370 375 static inline int reset_mac(pegasus_t *pegasus) 371 376 { 377 + int ret, i; 372 378 __u8 data = 0x8; 373 - int i; 374 379 375 380 set_register(pegasus, EthCtrl1, data); 376 381 for (i = 0; i < REG_TIMEOUT; i++) { 377 - get_registers(pegasus, EthCtrl1, 1, &data); 382 + ret = get_registers(pegasus, EthCtrl1, 1, &data); 383 + if (ret < 0) 384 + goto fail; 378 385 if (~data & 0x08) { 379 386 if (loopback) 380 387 break; ··· 399 402 } 400 403 if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_ELCON) { 401 404 __u16 auxmode; 402 - read_mii_word(pegasus, 3, 0x1b, &auxmode); 405 + ret = read_mii_word(pegasus, 3, 0x1b, &auxmode); 406 + if (ret < 0) 407 + goto fail; 403 408 auxmode |= 4; 404 409 write_mii_word(pegasus, 3, 0x1b, &auxmode); 405 410 } 406 411 407 412 return 0; 413 + fail: 414 + netif_dbg(pegasus, drv, pegasus->net, "%s failed\n", __func__); 415 + return ret; 408 416 } 409 417 410 418 static int enable_net_traffic(struct net_device *dev, struct usb_device *usb) 411 419 { 412 - __u16 linkpart; 413 - __u8 data[4]; 414 420 pegasus_t *pegasus = netdev_priv(dev); 415 421 int ret; 422 + __u16 linkpart; 423 + __u8 data[4]; 416 424 417 - read_mii_word(pegasus, pegasus->phy, MII_LPA, &linkpart); 425 + ret = read_mii_word(pegasus, pegasus->phy, MII_LPA, &linkpart); 426 + if (ret < 0) 427 + goto fail; 418 428 data[0] = 0xc8; /* TX & RX enable, append status, no CRC */ 419 429 data[1] = 0; 420 430 if (linkpart & (ADVERTISE_100FULL | ADVERTISE_10FULL)) ··· 439 435 usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS2 || 440 436 usb_dev_id[pegasus->dev_index].vendor == VENDOR_DLINK) { 441 437 u16 auxmode; 442 - read_mii_word(pegasus, 0, 0x1b, &auxmode); 438 + ret = read_mii_word(pegasus, 0, 0x1b, &auxmode); 439 + if (ret < 0) 440 + goto fail; 443 441 auxmode |= 4; 444 442 write_mii_word(pegasus, 0, 0x1b, &auxmode); 445 443 } 446 444 445 + return 0; 446 + fail: 447 + netif_dbg(pegasus, drv, pegasus->net, "%s failed\n", __func__); 447 448 return ret; 448 449 } 449 450 ··· 456 447 { 457 448 pegasus_t *pegasus = urb->context; 458 449 struct net_device *net; 450 + u8 *buf = urb->transfer_buffer; 459 451 int rx_status, count = urb->actual_length; 460 452 int status = urb->status; 461 - u8 *buf = urb->transfer_buffer; 462 453 __u16 pkt_len; 463 454 464 455 if (!pegasus) ··· 889 880 pegasus_t *pegasus = netdev_priv(dev); 890 881 891 882 strlcpy(info->driver, driver_name, sizeof(info->driver)); 892 - strlcpy(info->version, DRIVER_VERSION, sizeof(info->version)); 893 883 usb_make_path(pegasus->usb, info->bus_info, sizeof(info->bus_info)); 894 884 } 895 885 ··· 1006 998 data[0] = pegasus->phy; 1007 999 fallthrough; 1008 1000 case SIOCDEVPRIVATE + 1: 1009 - read_mii_word(pegasus, data[0], data[1] & 0x1f, &data[3]); 1010 - res = 0; 1001 + res = read_mii_word(pegasus, data[0], data[1] & 0x1f, &data[3]); 1011 1002 break; 1012 1003 case SIOCDEVPRIVATE + 2: 1013 1004 if (!capable(CAP_NET_ADMIN)) ··· 1040 1033 1041 1034 static __u8 mii_phy_probe(pegasus_t *pegasus) 1042 1035 { 1043 - int i; 1036 + int i, ret; 1044 1037 __u16 tmp; 1045 1038 1046 1039 for (i = 0; i < 32; i++) { 1047 - read_mii_word(pegasus, i, MII_BMSR, &tmp); 1040 + ret = read_mii_word(pegasus, i, MII_BMSR, &tmp); 1041 + if (ret < 0) 1042 + goto fail; 1048 1043 if (tmp == 0 || tmp == 0xffff || (tmp & BMSR_MEDIA) == 0) 1049 1044 continue; 1050 1045 else 1051 1046 return i; 1052 1047 } 1053 - 1048 + fail: 1054 1049 return 0xff; 1055 1050 } 1056 1051 1057 1052 static inline void setup_pegasus_II(pegasus_t *pegasus) 1058 1053 { 1054 + int ret; 1059 1055 __u8 data = 0xa5; 1060 1056 1061 1057 set_register(pegasus, Reg1d, 0); ··· 1070 1060 set_register(pegasus, Reg7b, 2); 1071 1061 1072 1062 set_register(pegasus, 0x83, data); 1073 - get_registers(pegasus, 0x83, 1, &data); 1063 + ret = get_registers(pegasus, 0x83, 1, &data); 1064 + if (ret < 0) 1065 + goto fail; 1074 1066 1075 1067 if (data == 0xa5) 1076 1068 pegasus->chip = 0x8513; ··· 1087 1075 set_register(pegasus, Reg81, 6); 1088 1076 else 1089 1077 set_register(pegasus, Reg81, 2); 1078 + 1079 + return; 1080 + fail: 1081 + netif_dbg(pegasus, drv, pegasus->net, "%s failed\n", __func__); 1090 1082 } 1091 1083 1092 1084 static void check_carrier(struct work_struct *work) ··· 1312 1296 1313 1297 static int __init pegasus_init(void) 1314 1298 { 1315 - pr_info("%s: %s, " DRIVER_DESC "\n", driver_name, DRIVER_VERSION); 1299 + pr_info("%s: " DRIVER_DESC "\n", driver_name); 1316 1300 if (devid) 1317 1301 parse_id(devid); 1318 1302 return usb_register(&pegasus_driver);