struct be_eth_wrb *wrb;
struct be_eth_hdr_wrb *hdr;
- atomic_add(wrb_cnt, &txq->used);
hdr = queue_head_node(txq);
+ atomic_add(wrb_cnt, &txq->used);
queue_head_inc(txq);
+ if (skb_dma_map(&pdev->dev, skb, DMA_TO_DEVICE)) {
+ dev_err(&pdev->dev, "TX DMA mapping failed\n");
+ return 0;
+ }
+
if (skb->len > skb->data_len) {
int len = skb->len - skb->data_len;
- busaddr = pci_map_single(pdev, skb->data, len,
- PCI_DMA_TODEVICE);
wrb = queue_head_node(txq);
+ busaddr = skb_shinfo(skb)->dma_head;
wrb_fill(wrb, busaddr, len);
be_dws_cpu_to_le(wrb, sizeof(*wrb));
queue_head_inc(txq);
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
struct skb_frag_struct *frag =
&skb_shinfo(skb)->frags[i];
- busaddr = pci_map_page(pdev, frag->page,
- frag->page_offset,
- frag->size, PCI_DMA_TODEVICE);
+
+ busaddr = skb_shinfo(skb)->dma_maps[i];
wrb = queue_head_node(txq);
wrb_fill(wrb, busaddr, frag->size);
be_dws_cpu_to_le(wrb, sizeof(*wrb));
static netdev_tx_t be_xmit(struct sk_buff *skb,
struct net_device *netdev)
+
{
struct be_adapter *adapter = netdev_priv(netdev);
struct be_tx_obj *tx_obj = &adapter->tx_obj;
wrb_cnt = wrb_cnt_for_skb(skb, &dummy_wrb);
copied = make_tx_wrbs(adapter, skb, wrb_cnt, dummy_wrb);
+ if (copied) {
+ /* record the sent skb in the sent_skb table */
+ BUG_ON(tx_obj->sent_skb_list[start]);
+ tx_obj->sent_skb_list[start] = skb;
+
+ /* Ensure txq has space for the next skb; Else stop the queue
+ * *BEFORE* ringing the tx doorbell, so that we serialze the
+ * tx compls of the current transmit which'll wake up the queue
+ */
+ if ((BE_MAX_TX_FRAG_COUNT + atomic_read(&txq->used)) >=
+ txq->len) {
+ netif_stop_queue(netdev);
+ stopped = true;
+ }
- /* record the sent skb in the sent_skb table */
- BUG_ON(tx_obj->sent_skb_list[start]);
- tx_obj->sent_skb_list[start] = skb;
+ be_txq_notify(adapter, txq->id, wrb_cnt);
- /* Ensure that txq has space for the next skb; Else stop the queue
- * *BEFORE* ringing the tx doorbell, so that we serialze the
- * tx compls of the current transmit which'll wake up the queue
- */
- if ((BE_MAX_TX_FRAG_COUNT + atomic_read(&txq->used)) >= txq->len) {
- netif_stop_queue(netdev);
- stopped = true;
+ be_tx_stats_update(adapter, wrb_cnt, copied, stopped);
+ } else {
+ txq->head = start;
+ dev_kfree_skb_any(skb);
}
-
- be_txq_notify(adapter, txq->id, wrb_cnt);
-
- be_tx_stats_update(adapter, wrb_cnt, copied, stopped);
return NETDEV_TX_OK;
}
netif_receive_skb(skb);
}
- adapter->netdev->last_rx = jiffies;
-
return;
}
static void be_tx_compl_process(struct be_adapter *adapter, u16 last_index)
{
struct be_queue_info *txq = &adapter->tx_obj.q;
- struct be_eth_wrb *wrb;
struct sk_buff **sent_skbs = adapter->tx_obj.sent_skb_list;
struct sk_buff *sent_skb;
- u64 busaddr;
u16 cur_index, num_wrbs = 0;
cur_index = txq->tail;
do {
cur_index = txq->tail;
- wrb = queue_tail_node(txq);
- be_dws_le_to_cpu(wrb, sizeof(*wrb));
- busaddr = ((u64)wrb->frag_pa_hi << 32) | (u64)wrb->frag_pa_lo;
- if (busaddr != 0) {
- pci_unmap_single(adapter->pdev, busaddr,
- wrb->frag_len, PCI_DMA_TODEVICE);
- }
num_wrbs++;
queue_tail_inc(txq);
} while (cur_index != last_index);
atomic_sub(num_wrbs, &txq->used);
-
+ skb_dma_unmap(&adapter->pdev->dev, sent_skb, DMA_TO_DEVICE);
kfree_skb(sent_skb);
}
return 0;
}
+#define FW_FILE_HDR_SIGN "ServerEngines Corp. "
+char flash_cookie[2][16] = {"*** SE FLAS",
+ "H DIRECTORY *** "};
+static int be_flash_image(struct be_adapter *adapter,
+ const struct firmware *fw,
+ struct be_dma_mem *flash_cmd, u32 flash_type)
+{
+ int status;
+ u32 flash_op, image_offset = 0, total_bytes, image_size = 0;
+ int num_bytes;
+ const u8 *p = fw->data;
+ struct be_cmd_write_flashrom *req = flash_cmd->va;
+
+ switch (flash_type) {
+ case FLASHROM_TYPE_ISCSI_ACTIVE:
+ image_offset = FLASH_iSCSI_PRIMARY_IMAGE_START;
+ image_size = FLASH_IMAGE_MAX_SIZE;
+ break;
+ case FLASHROM_TYPE_ISCSI_BACKUP:
+ image_offset = FLASH_iSCSI_BACKUP_IMAGE_START;
+ image_size = FLASH_IMAGE_MAX_SIZE;
+ break;
+ case FLASHROM_TYPE_FCOE_FW_ACTIVE:
+ image_offset = FLASH_FCoE_PRIMARY_IMAGE_START;
+ image_size = FLASH_IMAGE_MAX_SIZE;
+ break;
+ case FLASHROM_TYPE_FCOE_FW_BACKUP:
+ image_offset = FLASH_FCoE_BACKUP_IMAGE_START;
+ image_size = FLASH_IMAGE_MAX_SIZE;
+ break;
+ case FLASHROM_TYPE_BIOS:
+ image_offset = FLASH_iSCSI_BIOS_START;
+ image_size = FLASH_BIOS_IMAGE_MAX_SIZE;
+ break;
+ case FLASHROM_TYPE_FCOE_BIOS:
+ image_offset = FLASH_FCoE_BIOS_START;
+ image_size = FLASH_BIOS_IMAGE_MAX_SIZE;
+ break;
+ case FLASHROM_TYPE_PXE_BIOS:
+ image_offset = FLASH_PXE_BIOS_START;
+ image_size = FLASH_BIOS_IMAGE_MAX_SIZE;
+ break;
+ default:
+ return 0;
+ }
+
+ p += sizeof(struct flash_file_hdr) + image_offset;
+ if (p + image_size > fw->data + fw->size)
+ return -1;
+
+ total_bytes = image_size;
+
+ while (total_bytes) {
+ if (total_bytes > 32*1024)
+ num_bytes = 32*1024;
+ else
+ num_bytes = total_bytes;
+ total_bytes -= num_bytes;
+
+ if (!total_bytes)
+ flash_op = FLASHROM_OPER_FLASH;
+ else
+ flash_op = FLASHROM_OPER_SAVE;
+ memcpy(req->params.data_buf, p, num_bytes);
+ p += num_bytes;
+ status = be_cmd_write_flashrom(adapter, flash_cmd,
+ flash_type, flash_op, num_bytes);
+ if (status) {
+ dev_err(&adapter->pdev->dev,
+ "cmd to write to flash rom failed. type/op %d/%d\n",
+ flash_type, flash_op);
+ return -1;
+ }
+ yield();
+ }
+
+ return 0;
+}
+
+int be_load_fw(struct be_adapter *adapter, u8 *func)
+{
+ char fw_file[ETHTOOL_FLASH_MAX_FILENAME];
+ const struct firmware *fw;
+ struct flash_file_hdr *fhdr;
+ struct flash_section_info *fsec = NULL;
+ struct be_dma_mem flash_cmd;
+ int status;
+ const u8 *p;
+ bool entry_found = false;
+ int flash_type;
+ char fw_ver[FW_VER_LEN];
+ char fw_cfg;
+
+ status = be_cmd_get_fw_ver(adapter, fw_ver);
+ if (status)
+ return status;
+
+ fw_cfg = *(fw_ver + 2);
+ if (fw_cfg == '0')
+ fw_cfg = '1';
+ strcpy(fw_file, func);
+
+ status = request_firmware(&fw, fw_file, &adapter->pdev->dev);
+ if (status)
+ goto fw_exit;
+
+ p = fw->data;
+ fhdr = (struct flash_file_hdr *) p;
+ if (memcmp(fhdr->sign, FW_FILE_HDR_SIGN, strlen(FW_FILE_HDR_SIGN))) {
+ dev_err(&adapter->pdev->dev,
+ "Firmware(%s) load error (signature did not match)\n",
+ fw_file);
+ status = -1;
+ goto fw_exit;
+ }
+
+ dev_info(&adapter->pdev->dev, "Flashing firmware file %s\n", fw_file);
+
+ p += sizeof(struct flash_file_hdr);
+ while (p < (fw->data + fw->size)) {
+ fsec = (struct flash_section_info *)p;
+ if (!memcmp(flash_cookie, fsec->cookie, sizeof(flash_cookie))) {
+ entry_found = true;
+ break;
+ }
+ p += 32;
+ }
+
+ if (!entry_found) {
+ status = -1;
+ dev_err(&adapter->pdev->dev,
+ "Flash cookie not found in firmware image\n");
+ goto fw_exit;
+ }
+
+ flash_cmd.size = sizeof(struct be_cmd_write_flashrom) + 32*1024;
+ flash_cmd.va = pci_alloc_consistent(adapter->pdev, flash_cmd.size,
+ &flash_cmd.dma);
+ if (!flash_cmd.va) {
+ status = -ENOMEM;
+ dev_err(&adapter->pdev->dev,
+ "Memory allocation failure while flashing\n");
+ goto fw_exit;
+ }
+
+ for (flash_type = FLASHROM_TYPE_ISCSI_ACTIVE;
+ flash_type <= FLASHROM_TYPE_FCOE_FW_BACKUP; flash_type++) {
+ status = be_flash_image(adapter, fw, &flash_cmd,
+ flash_type);
+ if (status)
+ break;
+ }
+
+ pci_free_consistent(adapter->pdev, flash_cmd.size, flash_cmd.va,
+ flash_cmd.dma);
+ if (status) {
+ dev_err(&adapter->pdev->dev, "Firmware load error\n");
+ goto fw_exit;
+ }
+
+ dev_info(&adapter->pdev->dev, "Firmware flashed succesfully\n");
+
+fw_exit:
+ release_firmware(fw);
+ return status;
+}
+
static struct net_device_ops be_netdev_ops = {
.ndo_open = be_open,
.ndo_stop = be_close,
adapter->rx_csum = true;
+ netif_set_gso_max_size(netdev, 65535);
+
BE_SET_NETDEV_OPS(netdev, &be_netdev_ops);
SET_ETHTOOL_OPS(netdev, &be_ethtool_ops);