Files @ d0a14f973771
Branch filter:

Location: vmkdrivers/vmkdrivers/src_9/drivers/net/tg3/tg3_vmware.c

unknown
ESXi-5.0-U1
/* Copyright (C) 2010 Broadcom Corporation.
 * Portions Copyright (C) VMware, Inc. 2007-2011. All Rights Reserved.
 */

static void tg3_vmware_timer(struct tg3 *tp)
{
	/*
	 * If the driver says this NIC is in promiscuous mode, the hardware
	 * better agree with it. See PR 88299 for more details, but there
	 * are cases (eg. bcm5704 rev10) that the set promiscuous bit is
	 * lost for no reason and this seems to be the least intrusive
	 * workaround for that issue (likely a hardware bug).
	 *
	 * This is happening on other cards as well (BCM5700 rev04) PR 97750
	 * Also, on some cards (5703) we have seen other bits getting messed up
	 */
	if (netif_carrier_ok(tp->dev)) {
		u32 rx_mode = tr32(MAC_RX_MODE);
		if (!(rx_mode & RX_MODE_PROMISC) && (rx_mode != tp->rx_mode)) {
         u32 val;
         tg3_read_mem(tp, 0xc04, &val);
         if (val != 1) {
            netdev_info(tp->dev, "ASF has wrong host driver state (0x%x)\n",
            val);
         }

			/*
			 * We love to warn the users every time there is such a
			 * register reset, but we do not want to do it forever
			 * given some NICs are really that bad (PR 105488).
			 */
			if (tp->vmware.rx_mode_reset_counter < 200) {
				netdev_info(tp->dev, "%s: rx_mode "
					    "0x%x(%s)=>0x%x tg3_flags 0x%x "
					    "tg3_flags2 0x%x\n",
					    tp->dev->name, rx_mode,
					    rx_mode & RX_MODE_PROMISC ? "on" : "off",
					    tp->rx_mode, tp->tg3_flags,
					    tp->tg3_flags2);
				tp->vmware.rx_mode_reset_counter++;
			}
			tw32_f(MAC_RX_MODE, tp->rx_mode);
		}
	}

	/*
	 * we've seen ssome 5703's (rev 10) which don't seen to
	 * generate an interrupt on link-up state changes. bug 89197.
	 */
	if (!netif_carrier_ok(tp->dev) &&
	    !(tp->tg3_flags &
	     (TG3_FLAG_USE_LINKCHG_REG | TG3_FLAG_POLL_SERDES))) {
		struct tg3_hw_status *sblk = tp->napi[0].hw_status;
		if (sblk->status & SD_STATUS_LINK_CHG) {
			sblk->status = SD_STATUS_UPDATED |
			       (sblk->status & ~SD_STATUS_LINK_CHG);
			tg3_setup_phy(tp, 0);
		}
	}
}

#if !defined(TG3_VMWARE_BMAPILNX_DISABLE)
static int
tg3_vmware_ioctl_cim(struct net_device *dev, struct ifreq *ifr)
{
	struct tg3 *tp = netdev_priv(dev);
	void __user *useraddr = ifr->ifr_data;
	struct tg3_ioctl_req req;
	int rc = 0;
	u32 val;

	if (copy_from_user(&req, useraddr, sizeof(req))) {
		netdev_err(dev, "%s: could not copy "
				"from user tg3_ioctl_req\n", __func__);
		return -EFAULT;
	}

	switch(req.cmd) {
	case TG3_VMWARE_CIM_CMD_ENABLE_NIC:
		netdev_info(dev, "%s: enable NIC\n", __func__);

		rc = tg3_open(tp->dev);
		break;
	case TG3_VMWARE_CIM_CMD_DISABLE_NIC:
		netdev_info(dev, "%s: disable NIC\n", __func__);

		rc = tg3_close(tp->dev);
		break;
	case TG3_VMWARE_CIM_CMD_REG_READ: {

		if(0x7ffc < req.cmd_req.reg_read.reg_offset) {
			netdev_err(dev, "%s: reg read: "
					"out of range: req reg: 0x%x\n",
				   __func__, req.cmd_req.reg_read.reg_offset);
			rc = -EINVAL;
			break;
		}

		val = tr32(req.cmd_req.reg_read.reg_offset);

		netdev_info(dev, "%s: reg read: reg: 0x%x value:0x%x",
			    __func__, req.cmd_req.reg_read.reg_offset,
			    req.cmd_req.reg_read.reg_value);
		req.cmd_req.reg_read.reg_value = val;

		break;
	} case TG3_VMWARE_CIM_CMD_REG_WRITE: {
		if(0x7ffc < req.cmd_req.reg_write.reg_offset) {
			netdev_err(dev, "%s: reg write: "
					"out of range: req reg: 0x%x\n",
				   __func__, req.cmd_req.reg_write.reg_offset);
			rc = -EINVAL;
			break;
		}

		netdev_info(dev, "%s: reg write: reg: 0x%x value:0x%x",
			    __func__, req.cmd_req.reg_write.reg_offset,
			    req.cmd_req.reg_write.reg_value);

		tw32(req.cmd_req.reg_write.reg_offset,
			 req.cmd_req.reg_write.reg_value);

		break;
	} case TG3_VMWARE_CIM_CMD_GET_NIC_PARAM:
		netdev_info(dev, "%s: get NIC param\n", __func__);

		req.cmd_req.get_nic_param.mtu = dev->mtu;
		memcpy(req.cmd_req.get_nic_param.current_mac_addr,
		       dev->dev_addr,
		       sizeof(req.cmd_req.get_nic_param.current_mac_addr));
		break;
	case TG3_VMWARE_CIM_CMD_GET_NIC_STATUS:
		netdev_info(dev, "%s: get NIC status\n", __func__);

		req.cmd_req.get_nic_status.nic_status = netif_running(dev);
		break;
	default:
		netdev_err(dev, "%s: unknown req.cmd: 0x%x\n",
			   __func__, req.cmd);
		rc = -EINVAL;
	}

	if (rc == 0 &&
	    copy_to_user(useraddr, &req, sizeof(req))) {
		netdev_err(dev, "%s: couldn't copy to user tg3_ioctl_req\n",
			   __func__);
                return -EFAULT;
	}

	return rc;
}
#endif  /* TG3_VMWARE_BMAPILNX */