static int i2400mu_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt) { int result; struct i2400mu *i2400mu = container_of(i2400m, struct i2400mu, i2400m); struct device *dev = i2400m_dev(i2400m); static const __le32 i2400m_WARM_BOOT_BARKER[4] = { cpu_to_le32(I2400M_WARM_RESET_BARKER), cpu_to_le32(I2400M_WARM_RESET_BARKER), cpu_to_le32(I2400M_WARM_RESET_BARKER), cpu_to_le32(I2400M_WARM_RESET_BARKER), }; static const __le32 i2400m_COLD_BOOT_BARKER[4] = { cpu_to_le32(I2400M_COLD_RESET_BARKER), cpu_to_le32(I2400M_COLD_RESET_BARKER), cpu_to_le32(I2400M_COLD_RESET_BARKER), cpu_to_le32(I2400M_COLD_RESET_BARKER), }; d_fnstart(3, dev, "(i2400m %p rt %u)\n", i2400m, rt); if (rt == I2400M_RT_WARM) result = __i2400mu_send_barker( i2400mu, i2400m_WARM_BOOT_BARKER, sizeof(i2400m_WARM_BOOT_BARKER), i2400mu->endpoint_cfg.bulk_out); else if (rt == I2400M_RT_COLD) result = __i2400mu_send_barker( i2400mu, i2400m_COLD_BOOT_BARKER, sizeof(i2400m_COLD_BOOT_BARKER), i2400mu->endpoint_cfg.reset_cold); else if (rt == I2400M_RT_BUS) { result = usb_reset_device(i2400mu->usb_dev); switch (result) { case 0: case -EINVAL: case -ENODEV: case -ENOENT: case -ESHUTDOWN: result = 0; break; default: dev_err(dev, "USB reset failed (%d), giving up!\n", result); } } else { result = -EINVAL; BUG(); } if (result < 0 && result != -EINVAL && rt != I2400M_RT_BUS) { dev_err(dev, "%s reset failed (%d); trying USB reset\n", rt == I2400M_RT_WARM ? "warm" : "cold", result); usb_queue_reset_device(i2400mu->usb_iface); result = -ENODEV; } d_fnend(3, dev, "(i2400m %p rt %u) = %d\n", i2400m, rt, result); return result; }
/* * Reset a device at different levels (warm, cold or bus) * * @i2400m: device descriptor * @reset_type: soft, warm or bus reset (I2400M_RT_WARM/SOFT/BUS) * * Warm and cold resets get a USB reset if they fail. * * Warm reset: * * The device will be fully reset internally, but won't be * disconnected from the USB bus (so no reenumeration will * happen). Firmware upload will be neccessary. * * The device will send a reboot barker in the notification endpoint * that will trigger the driver to reinitialize the state * automatically from notif.c:i2400m_notification_grok() into * i2400m_dev_bootstrap_delayed(). * * Cold and bus (USB) reset: * * The device will be fully reset internally, disconnected from the * USB bus an a reenumeration will happen. Firmware upload will be * neccessary. Thus, we don't do any locking or struct * reinitialization, as we are going to be fully disconnected and * reenumerated. * * Note we need to return -ENODEV if a warm reset was requested and we * had to resort to a bus reset. See i2400m_op_reset(), wimax_reset() * and wimax_dev->op_reset. * * WARNING: no driver state saved/fixed */ static int i2400mu_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt) { int result; struct i2400mu *i2400mu = container_of(i2400m, struct i2400mu, i2400m); struct device *dev = i2400m_dev(i2400m); static const __le32 i2400m_WARM_BOOT_BARKER[4] = { cpu_to_le32(I2400M_WARM_RESET_BARKER), cpu_to_le32(I2400M_WARM_RESET_BARKER), cpu_to_le32(I2400M_WARM_RESET_BARKER), cpu_to_le32(I2400M_WARM_RESET_BARKER), }; static const __le32 i2400m_COLD_BOOT_BARKER[4] = { cpu_to_le32(I2400M_COLD_RESET_BARKER), cpu_to_le32(I2400M_COLD_RESET_BARKER), cpu_to_le32(I2400M_COLD_RESET_BARKER), cpu_to_le32(I2400M_COLD_RESET_BARKER), }; d_fnstart(3, dev, "(i2400m %p rt %u)\n", i2400m, rt); if (rt == I2400M_RT_WARM) result = __i2400mu_send_barker(i2400mu, i2400m_WARM_BOOT_BARKER, sizeof(i2400m_WARM_BOOT_BARKER), I2400MU_EP_BULK_OUT); else if (rt == I2400M_RT_COLD) result = __i2400mu_send_barker(i2400mu, i2400m_COLD_BOOT_BARKER, sizeof(i2400m_COLD_BOOT_BARKER), I2400MU_EP_RESET_COLD); else if (rt == I2400M_RT_BUS) { do_bus_reset: result = usb_reset_device(i2400mu->usb_dev); switch (result) { case 0: case -EINVAL: /* device is gone */ case -ENODEV: case -ENOENT: case -ESHUTDOWN: result = rt == I2400M_RT_WARM ? -ENODEV : 0; break; /* We assume the device is disconnected */ default: dev_err(dev, "USB reset failed (%d), giving up!\n", result); } } else { result = -EINVAL; /* shut gcc up in certain arches */ BUG(); } if (result < 0 && result != -EINVAL /* device is gone */ && rt != I2400M_RT_BUS) { dev_err(dev, "%s reset failed (%d); trying USB reset\n", rt == I2400M_RT_WARM ? "warm" : "cold", result); rt = I2400M_RT_BUS; goto do_bus_reset; } d_fnend(3, dev, "(i2400m %p rt %u) = %d\n", i2400m, rt, result); return result; }
/* * Reset a device at different levels (warm, cold or bus) * * @i2400m: device descriptor * @reset_type: soft, warm or bus reset (I2400M_RT_WARM/SOFT/BUS) * * Warm and cold resets get a USB reset if they fail. * * Warm reset: * * The device will be fully reset internally, but won't be * disconnected from the USB bus (so no reenumeration will * happen). Firmware upload will be necessary. * * The device will send a reboot barker in the notification endpoint * that will trigger the driver to reinitialize the state * automatically from notif.c:i2400m_notification_grok() into * i2400m_dev_bootstrap_delayed(). * * Cold and bus (USB) reset: * * The device will be fully reset internally, disconnected from the * USB bus an a reenumeration will happen. Firmware upload will be * necessary. Thus, we don't do any locking or struct * reinitialization, as we are going to be fully disconnected and * reenumerated. * * Note we need to return -ENODEV if a warm reset was requested and we * had to resort to a bus reset. See i2400m_op_reset(), wimax_reset() * and wimax_dev->op_reset. * * WARNING: no driver state saved/fixed */ static int i2400mu_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt) { int result; struct i2400mu *i2400mu = container_of(i2400m, struct i2400mu, i2400m); struct device *dev = i2400m_dev(i2400m); static const __le32 i2400m_WARM_BOOT_BARKER[4] = { cpu_to_le32(I2400M_WARM_RESET_BARKER), cpu_to_le32(I2400M_WARM_RESET_BARKER), cpu_to_le32(I2400M_WARM_RESET_BARKER), cpu_to_le32(I2400M_WARM_RESET_BARKER), }; static const __le32 i2400m_COLD_BOOT_BARKER[4] = { cpu_to_le32(I2400M_COLD_RESET_BARKER), cpu_to_le32(I2400M_COLD_RESET_BARKER), cpu_to_le32(I2400M_COLD_RESET_BARKER), cpu_to_le32(I2400M_COLD_RESET_BARKER), }; d_fnstart(3, dev, "(i2400m %p rt %u)\n", i2400m, rt); if (rt == I2400M_RT_WARM) result = __i2400mu_send_barker( i2400mu, i2400m_WARM_BOOT_BARKER, sizeof(i2400m_WARM_BOOT_BARKER), i2400mu->endpoint_cfg.bulk_out); else if (rt == I2400M_RT_COLD) result = __i2400mu_send_barker( i2400mu, i2400m_COLD_BOOT_BARKER, sizeof(i2400m_COLD_BOOT_BARKER), i2400mu->endpoint_cfg.reset_cold); else if (rt == I2400M_RT_BUS) { result = usb_reset_device(i2400mu->usb_dev); switch (result) { case 0: case -EINVAL: /* device is gone */ case -ENODEV: case -ENOENT: case -ESHUTDOWN: result = 0; break; /* We assume the device is disconnected */ default: dev_err(dev, "USB reset failed (%d), giving up!\n", result); } } else { result = -EINVAL; /* shut gcc up in certain arches */ BUG(); } if (result < 0 && result != -EINVAL /* device is gone */ && rt != I2400M_RT_BUS) { /* * Things failed -- resort to lower level reset, that * we queue in another context; the reason for this is * that the pre and post reset functionality requires * the i2400m->init_mutex; RT_WARM and RT_COLD can * come from areas where i2400m->init_mutex is taken. */ dev_err(dev, "%s reset failed (%d); trying USB reset\n", rt == I2400M_RT_WARM ? "warm" : "cold", result); usb_queue_reset_device(i2400mu->usb_iface); result = -ENODEV; } d_fnend(3, dev, "(i2400m %p rt %u) = %d\n", i2400m, rt, result); return result; }