cxgb3_main.c
来自「linux 内核源代码」· C语言 代码 · 共 2,534 行 · 第 1/5 页
C
2,534 行
static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)#define CXGB3_ATTR_RW(name, val_expr, store_method) \CXGB3_SHOW(name, val_expr) \static DEVICE_ATTR(name, S_IRUGO | S_IWUSR, show_##name, store_method)CXGB3_ATTR_R(cam_size, t3_mc5_size(&adap->mc5));CXGB3_ATTR_RW(nfilters, adap->params.mc5.nfilters, store_nfilters);CXGB3_ATTR_RW(nservers, adap->params.mc5.nservers, store_nservers);static struct attribute *cxgb3_attrs[] = { &dev_attr_cam_size.attr, &dev_attr_nfilters.attr, &dev_attr_nservers.attr, NULL};static struct attribute_group cxgb3_attr_group = {.attrs = cxgb3_attrs };static ssize_t tm_attr_show(struct device *d, struct device_attribute *attr, char *buf, int sched){ struct port_info *pi = netdev_priv(to_net_dev(d)); struct adapter *adap = pi->adapter; unsigned int v, addr, bpt, cpt; ssize_t len; addr = A_TP_TX_MOD_Q1_Q0_RATE_LIMIT - sched / 2; rtnl_lock(); t3_write_reg(adap, A_TP_TM_PIO_ADDR, addr); v = t3_read_reg(adap, A_TP_TM_PIO_DATA); if (sched & 1) v >>= 16; bpt = (v >> 8) & 0xff; cpt = v & 0xff; if (!cpt) len = sprintf(buf, "disabled\n"); else { v = (adap->params.vpd.cclk * 1000) / cpt; len = sprintf(buf, "%u Kbps\n", (v * bpt) / 125); } rtnl_unlock(); return len;}static ssize_t tm_attr_store(struct device *d, struct device_attribute *attr, const char *buf, size_t len, int sched){ struct port_info *pi = netdev_priv(to_net_dev(d)); struct adapter *adap = pi->adapter; unsigned int val; char *endp; ssize_t ret; if (!capable(CAP_NET_ADMIN)) return -EPERM; val = simple_strtoul(buf, &endp, 0); if (endp == buf || val > 10000000) return -EINVAL; rtnl_lock(); ret = t3_config_sched(adap, val, sched); if (!ret) ret = len; rtnl_unlock(); return ret;}#define TM_ATTR(name, sched) \static ssize_t show_##name(struct device *d, struct device_attribute *attr, \ char *buf) \{ \ return tm_attr_show(d, attr, buf, sched); \} \static ssize_t store_##name(struct device *d, struct device_attribute *attr, \ const char *buf, size_t len) \{ \ return tm_attr_store(d, attr, buf, len, sched); \} \static DEVICE_ATTR(name, S_IRUGO | S_IWUSR, show_##name, store_##name)TM_ATTR(sched0, 0);TM_ATTR(sched1, 1);TM_ATTR(sched2, 2);TM_ATTR(sched3, 3);TM_ATTR(sched4, 4);TM_ATTR(sched5, 5);TM_ATTR(sched6, 6);TM_ATTR(sched7, 7);static struct attribute *offload_attrs[] = { &dev_attr_sched0.attr, &dev_attr_sched1.attr, &dev_attr_sched2.attr, &dev_attr_sched3.attr, &dev_attr_sched4.attr, &dev_attr_sched5.attr, &dev_attr_sched6.attr, &dev_attr_sched7.attr, NULL};static struct attribute_group offload_attr_group = {.attrs = offload_attrs };/* * Sends an sk_buff to an offload queue driver * after dealing with any active network taps. */static inline int offload_tx(struct t3cdev *tdev, struct sk_buff *skb){ int ret; local_bh_disable(); ret = t3_offload_tx(tdev, skb); local_bh_enable(); return ret;}static int write_smt_entry(struct adapter *adapter, int idx){ struct cpl_smt_write_req *req; struct sk_buff *skb = alloc_skb(sizeof(*req), GFP_KERNEL); if (!skb) return -ENOMEM; req = (struct cpl_smt_write_req *)__skb_put(skb, sizeof(*req)); req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SMT_WRITE_REQ, idx)); req->mtu_idx = NMTUS - 1; /* should be 0 but there's a T3 bug */ req->iff = idx; memset(req->src_mac1, 0, sizeof(req->src_mac1)); memcpy(req->src_mac0, adapter->port[idx]->dev_addr, ETH_ALEN); skb->priority = 1; offload_tx(&adapter->tdev, skb); return 0;}static int init_smt(struct adapter *adapter){ int i; for_each_port(adapter, i) write_smt_entry(adapter, i); return 0;}static void init_port_mtus(struct adapter *adapter){ unsigned int mtus = adapter->port[0]->mtu; if (adapter->port[1]) mtus |= adapter->port[1]->mtu << 16; t3_write_reg(adapter, A_TP_MTU_PORT_TABLE, mtus);}static void send_pktsched_cmd(struct adapter *adap, int sched, int qidx, int lo, int hi, int port){ struct sk_buff *skb; struct mngt_pktsched_wr *req; skb = alloc_skb(sizeof(*req), GFP_KERNEL | __GFP_NOFAIL); req = (struct mngt_pktsched_wr *)skb_put(skb, sizeof(*req)); req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_MNGT)); req->mngt_opcode = FW_MNGTOPCODE_PKTSCHED_SET; req->sched = sched; req->idx = qidx; req->min = lo; req->max = hi; req->binding = port; t3_mgmt_tx(adap, skb);}static void bind_qsets(struct adapter *adap){ int i, j; for_each_port(adap, i) { const struct port_info *pi = adap2pinfo(adap, i); for (j = 0; j < pi->nqsets; ++j) send_pktsched_cmd(adap, 1, pi->first_qset + j, -1, -1, i); }}#define FW_FNAME "t3fw-%d.%d.%d.bin"#define TPSRAM_NAME "t3%c_protocol_sram-%d.%d.%d.bin"static int upgrade_fw(struct adapter *adap){ int ret; char buf[64]; const struct firmware *fw; struct device *dev = &adap->pdev->dev; snprintf(buf, sizeof(buf), FW_FNAME, FW_VERSION_MAJOR, FW_VERSION_MINOR, FW_VERSION_MICRO); ret = request_firmware(&fw, buf, dev); if (ret < 0) { dev_err(dev, "could not upgrade firmware: unable to load %s\n", buf); return ret; } ret = t3_load_fw(adap, fw->data, fw->size); release_firmware(fw); if (ret == 0) dev_info(dev, "successful upgrade to firmware %d.%d.%d\n", FW_VERSION_MAJOR, FW_VERSION_MINOR, FW_VERSION_MICRO); else dev_err(dev, "failed to upgrade to firmware %d.%d.%d\n", FW_VERSION_MAJOR, FW_VERSION_MINOR, FW_VERSION_MICRO); return ret;}static inline char t3rev2char(struct adapter *adapter){ char rev = 0; switch(adapter->params.rev) { case T3_REV_B: case T3_REV_B2: rev = 'b'; break; case T3_REV_C: rev = 'c'; break; } return rev;}static int update_tpsram(struct adapter *adap){ const struct firmware *tpsram; char buf[64]; struct device *dev = &adap->pdev->dev; int ret; char rev; rev = t3rev2char(adap); if (!rev) return 0; snprintf(buf, sizeof(buf), TPSRAM_NAME, rev, TP_VERSION_MAJOR, TP_VERSION_MINOR, TP_VERSION_MICRO); ret = request_firmware(&tpsram, buf, dev); if (ret < 0) { dev_err(dev, "could not load TP SRAM: unable to load %s\n", buf); return ret; } ret = t3_check_tpsram(adap, tpsram->data, tpsram->size); if (ret) goto release_tpsram; ret = t3_set_proto_sram(adap, tpsram->data); if (ret == 0) dev_info(dev, "successful update of protocol engine " "to %d.%d.%d\n", TP_VERSION_MAJOR, TP_VERSION_MINOR, TP_VERSION_MICRO); else dev_err(dev, "failed to update of protocol engine %d.%d.%d\n", TP_VERSION_MAJOR, TP_VERSION_MINOR, TP_VERSION_MICRO); if (ret) dev_err(dev, "loading protocol SRAM failed\n");release_tpsram: release_firmware(tpsram); return ret;}/** * cxgb_up - enable the adapter * @adapter: adapter being enabled * * Called when the first port is enabled, this function performs the * actions necessary to make an adapter operational, such as completing * the initialization of HW modules, and enabling interrupts. * * Must be called with the rtnl lock held. */static int cxgb_up(struct adapter *adap){ int err; int must_load; if (!(adap->flags & FULL_INIT_DONE)) { err = t3_check_fw_version(adap, &must_load); if (err == -EINVAL) { err = upgrade_fw(adap); if (err && must_load) goto out; } err = t3_check_tpsram_version(adap, &must_load); if (err == -EINVAL) { err = update_tpsram(adap); if (err && must_load) goto out; } err = t3_init_hw(adap, 0); if (err) goto out; t3_write_reg(adap, A_ULPRX_TDDP_PSZ, V_HPZ0(PAGE_SHIFT - 12)); err = setup_sge_qsets(adap); if (err) goto out; setup_rss(adap); init_napi(adap); adap->flags |= FULL_INIT_DONE; } t3_intr_clear(adap); if (adap->flags & USING_MSIX) { name_msix_vecs(adap); err = request_irq(adap->msix_info[0].vec, t3_async_intr_handler, 0, adap->msix_info[0].desc, adap); if (err) goto irq_err; if (request_msix_data_irqs(adap)) { free_irq(adap->msix_info[0].vec, adap); goto irq_err; } } else if ((err = request_irq(adap->pdev->irq, t3_intr_handler(adap, adap->sge.qs[0].rspq. polling), (adap->flags & USING_MSI) ? 0 : IRQF_SHARED, adap->name, adap))) goto irq_err; enable_all_napi(adap); t3_sge_start(adap); t3_intr_enable(adap); if ((adap->flags & (USING_MSIX | QUEUES_BOUND)) == USING_MSIX) bind_qsets(adap); adap->flags |= QUEUES_BOUND;out: return err;irq_err: CH_ERR(adap, "request_irq failed, err %d\n", err); goto out;}/* * Release resources when all the ports and offloading have been stopped. */static void cxgb_down(struct adapter *adapter){ t3_sge_stop(adapter); spin_lock_irq(&adapter->work_lock); /* sync with PHY intr task */ t3_intr_disable(adapter); spin_unlock_irq(&adapter->work_lock); if (adapter->flags & USING_MSIX) { int i, n = 0; free_irq(adapter->msix_info[0].vec, adapter); for_each_port(adapter, i) n += adap2pinfo(adapter, i)->nqsets; for (i = 0; i < n; ++i) free_irq(adapter->msix_info[i + 1].vec, &adapter->sge.qs[i]); } else free_irq(adapter->pdev->irq, adapter); flush_workqueue(cxgb3_wq); /* wait for external IRQ handler */ quiesce_rx(adapter);}static void schedule_chk_task(struct adapter *adap){ unsigned int timeo; timeo = adap->params.linkpoll_period ? (HZ * adap->params.linkpoll_period) / 10 : adap->params.stats_update_period * HZ; if (timeo) queue_delayed_work(cxgb3_wq, &adap->adap_check_task, timeo);}static int offload_open(struct net_device *dev){ struct port_info *pi = netdev_priv(dev); struct adapter *adapter = pi->adapter; struct t3cdev *tdev = dev2t3cdev(dev); int adap_up = adapter->open_device_map & PORT_MASK; int err; if (test_and_set_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map)) return 0; if (!adap_up && (err = cxgb_up(adapter)) < 0) return err; t3_tp_set_offload_mode(adapter, 1); tdev->lldev = adapter->port[0]; err = cxgb3_offload_activate(adapter); if (err) goto out; init_port_mtus(adapter); t3_load_mtus(adapter, adapter->params.mtus, adapter->params.a_wnd, adapter->params.b_wnd, adapter->params.rev == 0 ? adapter->port[0]->mtu : 0xffff); init_smt(adapter); /* Never mind if the next step fails */ sysfs_create_group(&tdev->lldev->dev.kobj, &offload_attr_group); /* Call back all registered clients */ cxgb3_add_clients(tdev);out: /* restore them in case the offload module has changed them */ if (err) { t3_tp_set_offload_mode(adapter, 0); clear_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map); cxgb3_set_dummy_ops(tdev); } return err;}static int offload_close(struct t3cdev *tdev){ struct adapter *adapter = tdev2adap(tdev); if (!test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map)) return 0; /* Call back all registered clients */ cxgb3_remove_clients(tdev); sysfs_remove_group(&tdev->lldev->dev.kobj, &offload_attr_group); tdev->lldev = NULL; cxgb3_set_dummy_ops(tdev); t3_tp_set_offload_mode(adapter, 0); clear_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map); if (!adapter->open_device_map) cxgb_down(adapter); cxgb3_offload_deactivate(adapter); return 0;}static int cxgb_open(struct net_device *dev){ struct port_info *pi = netdev_priv(dev); struct adapter *adapter = pi->adapter; int other_ports = adapter->open_device_map & PORT_MASK; int err; if (!adapter->open_device_map && (err = cxgb_up(adapter)) < 0) { quiesce_rx(adapter); return err; } set_bit(pi->port_id, &adapter->open_device_map); if (is_offload(adapter) && !ofld_disable) { err = offload_open(dev); if (err) printk(KERN_WARNING "Could not initialize offload capabilities\n"); } link_start(dev); t3_port_intr_enable(adapter, pi->port_id); netif_start_queue(dev); if (!other_ports) schedule_chk_task(adapter); return 0;}static int cxgb_close(struct net_device *dev){ struct port_info *pi = netdev_priv(dev); struct adapter *adapter = pi->adapter; t3_port_intr_disable(adapter, pi->port_id); netif_stop_queue(dev); pi->phy.ops->power_down(&pi->phy, 1); netif_carrier_off(dev); t3_mac_disable(&pi->mac, MAC_DIRECTION_TX | MAC_DIRECTION_RX);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?