e = alt->endpoint + ep;
switch (e->desc.bmAttributes) {
case USB_ENDPOINT_XFER_INT:
- if (!(e->desc.bEndpointAddress & USB_DIR_IN))
+ if (!usb_endpoint_dir_in(&e->desc))
continue;
intr = 1;
/* FALLTHROUGH */
default:
continue;
}
- if (e->desc.bEndpointAddress & USB_DIR_IN) {
+ if (usb_endpoint_dir_in(&e->desc)) {
if (!intr && !in)
in = e;
else if (intr && !status)
{
struct usbnet *dev = netdev_priv(net);
int temp;
- DECLARE_WAIT_QUEUE_HEAD (unlink_wakeup);
+ DECLARE_WAIT_QUEUE_HEAD_ONSTACK (unlink_wakeup);
DECLARE_WAITQUEUE (wait, current);
netif_stop_queue (net);
* they'll probably want to use this base set.
*/
-void usbnet_get_drvinfo (struct net_device *net, struct ethtool_drvinfo *info)
+#if defined(CONFIG_MII) || defined(CONFIG_MII_MODULE)
+#define HAVE_MII
+
+int usbnet_get_settings (struct net_device *net, struct ethtool_cmd *cmd)
{
struct usbnet *dev = netdev_priv(net);
- /* REVISIT don't always return "usbnet" */
- strncpy (info->driver, driver_name, sizeof info->driver);
- strncpy (info->version, DRIVER_VERSION, sizeof info->version);
- strncpy (info->fw_version, dev->driver_info->description,
- sizeof info->fw_version);
- usb_make_path (dev->udev, info->bus_info, sizeof info->bus_info);
+ if (!dev->mii.mdio_read)
+ return -EOPNOTSUPP;
+
+ return mii_ethtool_gset(&dev->mii, cmd);
}
-EXPORT_SYMBOL_GPL(usbnet_get_drvinfo);
+EXPORT_SYMBOL_GPL(usbnet_get_settings);
+
+int usbnet_set_settings (struct net_device *net, struct ethtool_cmd *cmd)
+{
+ struct usbnet *dev = netdev_priv(net);
+ int retval;
+
+ if (!dev->mii.mdio_write)
+ return -EOPNOTSUPP;
-static u32 usbnet_get_link (struct net_device *net)
+ retval = mii_ethtool_sset(&dev->mii, cmd);
+
+ /* link speed/duplex might have changed */
+ if (dev->driver_info->link_reset)
+ dev->driver_info->link_reset(dev);
+
+ return retval;
+
+}
+EXPORT_SYMBOL_GPL(usbnet_set_settings);
+
+u32 usbnet_get_link (struct net_device *net)
{
struct usbnet *dev = netdev_priv(net);
if (dev->driver_info->check_connect)
return dev->driver_info->check_connect (dev) == 0;
+ /* if the device has mii operations, use those */
+ if (dev->mii.mdio_read)
+ return mii_link_ok(&dev->mii);
+
/* Otherwise, say we're up (to avoid breaking scripts) */
return 1;
}
+EXPORT_SYMBOL_GPL(usbnet_get_link);
+
+int usbnet_nway_reset(struct net_device *net)
+{
+ struct usbnet *dev = netdev_priv(net);
+
+ if (!dev->mii.mdio_write)
+ return -EOPNOTSUPP;
+
+ return mii_nway_restart(&dev->mii);
+}
+EXPORT_SYMBOL_GPL(usbnet_nway_reset);
+
+#endif /* HAVE_MII */
+
+void usbnet_get_drvinfo (struct net_device *net, struct ethtool_drvinfo *info)
+{
+ struct usbnet *dev = netdev_priv(net);
+
+ /* REVISIT don't always return "usbnet" */
+ strncpy (info->driver, driver_name, sizeof info->driver);
+ strncpy (info->version, DRIVER_VERSION, sizeof info->version);
+ strncpy (info->fw_version, dev->driver_info->description,
+ sizeof info->fw_version);
+ usb_make_path (dev->udev, info->bus_info, sizeof info->bus_info);
+}
+EXPORT_SYMBOL_GPL(usbnet_get_drvinfo);
u32 usbnet_get_msglevel (struct net_device *net)
{
/* drivers may override default ethtool_ops in their bind() routine */
static struct ethtool_ops usbnet_ethtool_ops = {
- .get_drvinfo = usbnet_get_drvinfo,
+#ifdef HAVE_MII
+ .get_settings = usbnet_get_settings,
+ .set_settings = usbnet_set_settings,
.get_link = usbnet_get_link,
+ .nway_reset = usbnet_nway_reset,
+#endif
+ .get_drvinfo = usbnet_get_drvinfo,
.get_msglevel = usbnet_get_msglevel,
.set_msglevel = usbnet_set_msglevel,
};
* especially now that control transfers can be queued.
*/
static void
-kevent (void *data)
+kevent (struct work_struct *work)
{
- struct usbnet *dev = data;
+ struct usbnet *dev =
+ container_of(work, struct usbnet, kevent);
int status;
/* usb_clear_halt() needs a thread context */
skb_queue_head_init (&dev->done);
dev->bh.func = usbnet_bh;
dev->bh.data = (unsigned long) dev;
- INIT_WORK (&dev->kevent, kevent, dev);
+ INIT_WORK (&dev->kevent, kevent);
dev->delay.function = usbnet_bh;
dev->delay.data = (unsigned long) dev;
init_timer (&dev->delay);
+ mutex_init (&dev->phy_mutex);
SET_MODULE_OWNER (net);
dev->net = net;